| Dynamically loading model specific code from within generated code. [message #412073] |
Thu, 16 August 2007 08:15  |
Eclipse User |
|
|
|
Hi,
I am trying to do the followin:
In my Model there´s an EClass 'Service' that has an inherited name
(String) attribute, and a function 'query()' which returns an Object.
The implementation of query() is model specific (for every instance of
Service I want to write a different implementation for the query function.
Suppose I got a model instance with two Services with names
'modelinstance.RecipeOfTheDay' and another one 'modelinstance.MoonPhases'.
I now created a Datatype 'Query' which is an interface that only
contains the 'query()' method declaration.
I now set up a contract that for every Service in a Model instance which
must be fulfilled:
- there must be a (hand written) class that implements the Query interface.
- the fqn of that class must be:
'service.getName().toLowerCase().concat(".QueryImpl")
(for the example above the to handwritten classes fqns would be:
modelinstance.recipeoftheday.QueryImpl
modelinstance.moonphases.QueryImpl)
Now I insert code into the generated ServiceImpl class that dynamically
tries to load the respective hand-written query implementation as soon
as possible, and delegate all calls to service.query() to QueryImpl.query();
I now have problems finding the 'as soon as possible':
To me, as soon as possible is the point where a services name attribute
is set by the Resource model instantiation code (the model is loaded
from an xmi file).
So the first idea was to just modify the setName() function inside the
generated Class. Unfortunately the name attribute is inherited from a
superclass 'AbstractService'. Overwriting the setName() method in
ServiceImpl.java does not help, it seems the ResourceLoader calls
setName() for AbstractService.
Since this did not work i tried to observe the name Attribute with an
Adapter. I overwrote the ServiceImpl() constructor to automatically add
an Observer for the name Attribute, like this:
public ServiceImpl(){
super();
// inserted code
eAdapters.add(new NameObserver());
This doesn´t work, I get a NullPointerException.
The only thing that´s left is to load the model-specific delegation
class at the first call to the query() function.
Is this the only working possibility?
Of course I could also write some external code that initializes the
Query implementations from Outside, but this isn´t half as nice...
Thanks for your comments,
Felix
|
|
|
| Re: Dynamically loading model specific code from within generated code. [message #412077 is a reply to message #412073] |
Thu, 16 August 2007 08:54   |
Eclipse User |
|
|
|
Felix,
Comments below.
Felix Dorner wrote:
> Hi,
>
> I am trying to do the followin:
>
> In my Model there´s an EClass 'Service' that has an inherited name
> (String) attribute, and a function 'query()' which returns an Object.
>
> The implementation of query() is model specific (for every instance of
> Service I want to write a different implementation for the query
> function.
>
> Suppose I got a model instance with two Services with names
> 'modelinstance.RecipeOfTheDay' and another one
> 'modelinstance.MoonPhases'.
>
> I now created a Datatype 'Query' which is an interface that only
> contains the 'query()' method declaration.
I suppose you could have made this an EClass with only an EOperation for
query and marked its isInterface to be true so that only the interface
is generated. Then Service could extend it...
>
> I now set up a contract that for every Service in a Model instance
> which must be fulfilled:
>
> - there must be a (hand written) class that implements the Query
> interface.
If you did the above, then the class could be modeled and generated.
>
> - the fqn of that class must be:
> 'service.getName().toLowerCase().concat(".QueryImpl")
> (for the example above the to handwritten classes fqns would be:
> modelinstance.recipeoftheday.QueryImpl
> modelinstance.moonphases.QueryImpl)
So you'll use reflection to find the class I suppose...
>
> Now I insert code into the generated ServiceImpl class that
> dynamically tries to load the respective hand-written query
> implementation as soon as possible, and delegate all calls to
> service.query() to QueryImpl.query();
>
> I now have problems finding the 'as soon as possible':
>
> To me, as soon as possible is the point where a services name
> attribute is set by the Resource model instantiation code (the model
> is loaded from an xmi file).
Why not wait until the first invocation?
>
> So the first idea was to just modify the setName() function inside the
> generated Class. Unfortunately the name attribute is inherited from a
> superclass 'AbstractService'. Overwriting the setName() method in
> ServiceImpl.java does not help, it seems the ResourceLoader calls
> setName() for AbstractService.
If you override it, it definitely should call yours...
>
> Since this did not work i tried to observe the name Attribute with an
> Adapter. I overwrote the ServiceImpl() constructor to automatically
> add an Observer for the name Attribute, like this:
>
> public ServiceImpl(){
> super();
> // inserted code
> eAdapters.add(new NameObserver());
>
> This doesn´t work, I get a NullPointerException.
I suppose you should use eAdapters() to ensure that the list is actually
created.
>
>
> The only thing that´s left is to load the model-specific delegation
> class at the first call to the query() function.
> Is this the only working possibility?
That does seem best in any case...
>
>
> Of course I could also write some external code that initializes the
> Query implementations from Outside, but this isn´t half as nice...
It seems to me it would maybe be nicer if all services were modeled
subclasses of query and then they could have their own persistent data
when they are serialized. But I might not understand the use case very
well.
>
>
>
> Thanks for your comments,
>
> Felix
>
|
|
|
| Re: Dynamically loading model specific code from within generated code. [message #412078 is a reply to message #412077] |
Thu, 16 August 2007 09:13  |
Eclipse User |
|
|
|
> So you'll use reflection to find the class I suppose...
Yeah thats true.
> Why not wait until the first invocation?
I consider this bad because I want to check that the above contract is
fulfilled as soon as possible, i.e. at model instantiation time.
Otherwise an instance may run for a long time (well - minutes in this
case...:-D) with a predictible runtime exception when the first
invocation occurs.
>>
>> So the first idea was to just modify the setName() function inside the
>> generated Class. Unfortunately the name attribute is inherited from a
>> superclass 'AbstractService'. Overwriting the setName() method in
>> ServiceImpl.java does not help, it seems the ResourceLoader calls
>> setName() for AbstractService.
> If you override it, it definitely should call yours...
Hmm i´ll check that again.
> I suppose you should use eAdapters() to ensure that the list is actually
> created.
Shame on me..
>> Of course I could also write some external code that initializes the
>> Query implementations from Outside, but this isn´t half as nice...
> It seems to me it would maybe be nicer if all services were modeled
> subclasses of query and then they could have their own persistent data
> when they are serialized. But I might not understand the use case very
> well.
The use case above is a radical abstraction from what I am actually
doing. Anyway, if one could ever know before starting to design a model
how requirements will evolve... :-s
Thanks Ed for your (as always) fast response.
|
|
|
Powered by
FUDForum. Page generated in 0.03588 seconds