Home » Modeling » TMF (Xtext) » Dangling reference when dynamically creating EMF instances
Dangling reference when dynamically creating EMF instances [message #671296] |
Tue, 17 May 2011 12:02 |
Ulli Hafner Messages: 8 Registered: July 2009 |
Junior Member |
|
|
Hi,
I'm trying to write a xtext grammar that uses some predefined instances
that are computed dynamically. Where is the best way to load these
instances so that these instances are available when pressing CTRL-SPACE?
My grammar is quite simple:
----------------
grammar de.faktorlogik.ips.dsl.Rules with org.eclipse.xtext.common.Terminals
generate rules "http://www.faktorlogik.de/ips/dsl/Rules"
Model:
rule=Rule;
Concept:
'concept' name=ID;
Property:
'property' name=ID;
Rule:
concept=[Concept] 'and' restriction=Restriction;
Restriction:
'(' property=[Property] 'some' concept=[Concept] ')';
----------------------
Concept and Property instances are actually not defined using the
editor, they are created dynamically. I only defined them in the grammar
in order to use them as references in the Rule definition.
My Editor should basically parse the following input:
----------------------
concept1 and (property1 some concept2)
----------------------
The elements concept1, property1, and concept2 are dynamically computed.
Currently I've extended from AbstractDeclarativeScopeProvider and
instantiate the objects dynamically from within methods
public IScope scope_Concept(Model model, EReference reference) {
return new MapBasedScope(computeAvailableConcepts());
}
public IScope scope_Property(Model model, EReference reference) {
return new MapBasedScope(computeAvailableProperties())
}
This approach works for the context assist, however I'm always getting
the following validation error:
The feature 'property' of
'de.faktorlogik.ips.dsl.rules.impl.RestrictionImpl@1fdbab5 {platform:/resource/hello.world/src/rules.flips#//@rule/@res triction}'
contains a dangling reference
'de.faktorlogik.ips.dsl.rules.impl.PropertyImpl@a484c7{#//}'
rules.flips /hello.world/src line: 1 /hello.world/src/rules.flips Xtext
Check (fast)
Am I doing something fundamentally wrong? Or where would be the best
place to instantiate those predefined instances? (Currently the scope
methods are invoked on every CTRL-SPACE, maybe a method that would be
invoked only once would be sufficient?
Thanks,
Ulli
|
|
|
Re: Dangling reference when dynamically creating EMF instances [message #671493 is a reply to message #671296] |
Wed, 18 May 2011 05:50 |
Knut Wannheden Messages: 298 Registered: July 2009 |
Senior Member |
|
|
Hi Ulli,
Welcome to the Xtext community!
See answers inline.
On 5/17/11 2:02 PM, Ulli Hafner wrote:
> Hi,
>
> I'm trying to write a xtext grammar that uses some predefined instances that
> are computed dynamically. Where is the best way to load these instances so
> that these instances are available when pressing CTRL-SPACE?
>
> My grammar is quite simple:
> ----------------
> grammar de.faktorlogik.ips.dsl.Rules with org.eclipse.xtext.common.Terminals
>
> generate rules "http://www.faktorlogik.de/ips/dsl/Rules"
>
> Model:
> rule=Rule;
>
> Concept:
> 'concept' name=ID;
>
> Property:
> 'property' name=ID;
>
> Rule:
> concept=[Concept] 'and' restriction=Restriction;
>
> Restriction:
> '(' property=[Property] 'some' concept=[Concept] ')';
> ----------------------
>
> Concept and Property instances are actually not defined using the editor, they
> are created dynamically. I only defined them in the grammar in order to use
> them as references in the Rule definition.
>
I would consider maintaining the Ecore model by hand as the parser rules for
Concept and Property are not used and thus rather confusing.
> My Editor should basically parse the following input:
> ----------------------
> concept1 and (property1 some concept2)
> ----------------------
>
> The elements concept1, property1, and concept2 are dynamically computed.
>
> Currently I've extended from AbstractDeclarativeScopeProvider and instantiate
> the objects dynamically from within methods
>
> public IScope scope_Concept(Model model, EReference reference) {
> return new MapBasedScope(computeAvailableConcepts());
> }
>
> public IScope scope_Property(Model model, EReference reference) {
> return new MapBasedScope(computeAvailableProperties())
> }
>
> This approach works for the context assist, however I'm always getting the
> following validation error:
>
> The feature 'property' of
> 'de.faktorlogik.ips.dsl.rules.impl.RestrictionImpl@1fdbab5 {platform:/resource/hello.world/src/rules.flips#//@rule/@res triction}'
> contains a dangling reference
> 'de.faktorlogik.ips.dsl.rules.impl.PropertyImpl@a484c7{#//}' rules.flips
> /hello.world/src line: 1 /hello.world/src/rules.flips Xtext Check (fast)
>
> Am I doing something fundamentally wrong? Or where would be the best place to
> instantiate those predefined instances? (Currently the scope methods are
> invoked on every CTRL-SPACE, maybe a method that would be invoked only once
> would be sufficient?
>
The problem is that your Concept and Property instances are not contained by
any EMF resource. And there is a standard EMF validation checking against
references to such non-contained objects.
I would consider the following approaches (in the given order) to solve the
problem:
1. Presumably the Concept and Property instances are created based on some
other external, persisted data. If possible and feasible it would make sense
to implement an IResourceServiceProvider (see also
GenericResourceServiceProvider) for this external content. That way you could
add the Concept and Property instances to the Xtext index and link against that.
2. On the fly generate an EMF Resource containing the Concepts and Properties
and add it to the ResourceSet which contains your model. You could do this
dynamically in the ScopeProvider or possibly up front in the Linker (using the
afterModelLinked() hook).
3. Add the Concept and Property instances as additional top-level objects to
the XtextResource containing your model. This however makes most sense if
these instances are derived from data in your model. (Xbase based languages
use this approach to store derived Java types.)
4. Disable the EMF validation. You can do this by binding a
@Named(CompositeEValidator.USE_EOBJECT_VALIDATOR) Boolean to "false". You
could also be more specific and bind CompositeEValidator to a custom subclass
where you override initDefaults() to add an EObjectValidator which in
validate_EveryReferenceIsContained() returns "true". But I wouldn't really
recommend this approach if you don't have very good reasons.
Hope that helps,
--knut
|
|
|
Re: Dangling reference when dynamically creating EMF instances [message #671623 is a reply to message #671493] |
Wed, 18 May 2011 14:02 |
Ulli Hafner Messages: 8 Registered: July 2009 |
Junior Member |
|
|
On 05/18/2011 07:50 AM, Knut Wannheden wrote:
> Hi Ulli,
>
> Welcome to the Xtext community!
>
> See answers inline.
Hi Knut :-)
Thanks for the links. The GenericResourceServiceProvider seems to be
part of xtext 2.0. Is it worth to update to this pre-release version or
can I adapt the DefaultResourceServiceProvider from the 1.0 release, too?
Ulli
>
> On 5/17/11 2:02 PM, Ulli Hafner wrote:
>> Hi,
>>
>> I'm trying to write a xtext grammar that uses some predefined
>> instances that
>> are computed dynamically. Where is the best way to load these
>> instances so
>> that these instances are available when pressing CTRL-SPACE?
>>
>> My grammar is quite simple:
>> ----------------
>> grammar de.faktorlogik.ips.dsl.Rules with
>> org.eclipse.xtext.common.Terminals
>>
>> generate rules "http://www.faktorlogik.de/ips/dsl/Rules"
>>
>> Model:
>> rule=Rule;
>>
>> Concept:
>> 'concept' name=ID;
>>
>> Property:
>> 'property' name=ID;
>>
>> Rule:
>> concept=[Concept] 'and' restriction=Restriction;
>>
>> Restriction:
>> '(' property=[Property] 'some' concept=[Concept] ')';
>> ----------------------
>>
>> Concept and Property instances are actually not defined using the
>> editor, they
>> are created dynamically. I only defined them in the grammar in order
>> to use
>> them as references in the Rule definition.
>>
>
> I would consider maintaining the Ecore model by hand as the parser rules
> for Concept and Property are not used and thus rather confusing.
>
>> My Editor should basically parse the following input:
>> ----------------------
>> concept1 and (property1 some concept2)
>> ----------------------
>>
>> The elements concept1, property1, and concept2 are dynamically computed.
>>
>> Currently I've extended from AbstractDeclarativeScopeProvider and
>> instantiate
>> the objects dynamically from within methods
>>
>> public IScope scope_Concept(Model model, EReference reference) {
>> return new MapBasedScope(computeAvailableConcepts());
>> }
>>
>> public IScope scope_Property(Model model, EReference reference) {
>> return new MapBasedScope(computeAvailableProperties())
>> }
>>
>> This approach works for the context assist, however I'm always getting
>> the
>> following validation error:
>>
>> The feature 'property' of
>> 'de.faktorlogik.ips.dsl.rules.impl.RestrictionImpl@1fdbab5 {platform:/resource/hello.world/src/rules.flips#//@rule/@res triction}'
>>
>> contains a dangling reference
>> 'de.faktorlogik.ips.dsl.rules.impl.PropertyImpl@a484c7{#//}' rules.flips
>> /hello.world/src line: 1 /hello.world/src/rules.flips Xtext Check (fast)
>>
>> Am I doing something fundamentally wrong? Or where would be the best
>> place to
>> instantiate those predefined instances? (Currently the scope methods are
>> invoked on every CTRL-SPACE, maybe a method that would be invoked only
>> once
>> would be sufficient?
>>
>
> The problem is that your Concept and Property instances are not
> contained by any EMF resource. And there is a standard EMF validation
> checking against references to such non-contained objects.
>
> I would consider the following approaches (in the given order) to solve
> the problem:
>
> 1. Presumably the Concept and Property instances are created based on
> some other external, persisted data. If possible and feasible it would
> make sense to implement an IResourceServiceProvider (see also
> GenericResourceServiceProvider) for this external content. That way you
> could add the Concept and Property instances to the Xtext index and link
> against that.
>
> 2. On the fly generate an EMF Resource containing the Concepts and
> Properties and add it to the ResourceSet which contains your model. You
> could do this dynamically in the ScopeProvider or possibly up front in
> the Linker (using the afterModelLinked() hook).
>
> 3. Add the Concept and Property instances as additional top-level
> objects to the XtextResource containing your model. This however makes
> most sense if these instances are derived from data in your model.
> (Xbase based languages use this approach to store derived Java types.)
>
> 4. Disable the EMF validation. You can do this by binding a
> @Named(CompositeEValidator.USE_EOBJECT_VALIDATOR) Boolean to "false".
> You could also be more specific and bind CompositeEValidator to a custom
> subclass where you override initDefaults() to add an EObjectValidator
> which in validate_EveryReferenceIsContained() returns "true". But I
> wouldn't really recommend this approach if you don't have very good
> reasons.
>
> Hope that helps,
>
> --knut
|
|
| | |
Re: Dangling reference when dynamically creating EMF instances [message #671887 is a reply to message #671652] |
Thu, 19 May 2011 08:46 |
Ulli Hafner Messages: 8 Registered: July 2009 |
Junior Member |
|
|
On 05/18/2011 05:09 PM, Alexander Nittka wrote:
> Hi,
>
> just as a side question. Do you need Concept and Property to be
> referrable, i.e. do you really need cross references to them? This
> usually makes sense if you can actually navigate to them (F3) which in
> your case would not be possible anyway. For simpe scenarios, I could
> imagine that implementing adapted code completion and validation would
> work just as well (Rule: concept=ID... instead of Rule: concept=[Concept]).
>
> However, I assume that this is not enough in your case. So here is a
> second question. What do you mean by dynamically calculated? Really
> dynamically in the sense that different Concepts are used in different
> contexts or would it be possible that these concepts can be put into a
> "library", i.e. a model visible by default which is part of your plugin
> (analogous to the default terminals provided by Xtext or basic types
> always visible in Java).
>
> Alex
Hi Alex,
that is a good point :-)
Actually concepts and properties should not be referrable, I just need
them for code completion. What I'm trying to get is a parser for rules
that use a predefined set of concepts that contain some properties. The
concepts and properties are defined in an OWL model (web ontology
language) and are quite similar to classes and associations in Java.
E.g., I have a concept 'Pizza' that has a property 'topping' which
refers to another concept 'Salami' that has a property 'spiciness' that
refers to a concept 'Hot'. (These concepts are given before I'm opening
the editor, but they can change during an Eclipse session. I.e. the user
changes the OWL model, opens the xtext editor to define some rules,
closes the editor, changes the model, opens the rule editor, etc.)
What I would like to have is an editor, that can parse e.g. the
following expression:
Pizza 'and' topping 'is' Salami 'and' spiciness 'is' Hot
Context assist must be context sensitive, e.g. when the cursor is at X:
"Pizza 'and' X" then only topping should be available and not spiciness.
As well as after the user typed 'topping' then only all topping should
be available.
Seems that my xtext starting point was to complicated at all. I tried to
go forward with your approach, however I don't find a way to provide
code completion for these IDs?
E.g., now I have
Concept:
ID;
Property:
ID;
Rule:
concept=Concept 'and' property=Property;
Since Concept and Property are now just strings the code completion
using the ScopeProvider seems to be not possible. Do I need to implement
a IValueConverterService to get code completion on theses IDs?
Thanks, Ulli
|
|
|
Re: Dangling reference when dynamically creating EMF instances [message #671891 is a reply to message #671887] |
Thu, 19 May 2011 09:26 |
Alexander Nittka Messages: 1193 Registered: July 2009 |
Senior Member |
|
|
Hi,
still too complicated (I'd say):
Rule: concept=ID 'and' property=ID;
The proposalProvider now has a method completeRule_Concept and a method completeRule_Property. There you add your proposals (acceptor.accept(createCompletionProposal("Pizza",context)));
In the completeRule_Property, you retrieve the model element from the context and and check which concept is used, so you propose only the properties of that concept.
Similarly you adapt validation, so that only valid concepts and their properties are used. It would make sense to hold a datastructure for concepts and properties, so that you have easy access to them from wherever they are needed (code completion, validation, highlighting if you want...)
Alex
Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext@itemis.de
|
|
|
Re: Dangling reference when dynamically creating EMF instances [message #672244 is a reply to message #671891] |
Fri, 20 May 2011 12:41 |
Ulli Hafner Messages: 8 Registered: July 2009 |
Junior Member |
|
|
On 05/19/2011 11:26 AM, Alexander Nittka wrote:
> Hi,
>
> still too complicated (I'd say):
>
> Rule: concept=ID 'and' property=ID;
>
> The proposalProvider now has a method completeRule_Concept and a method
> completeRule_Property. There you add your proposals
> (acceptor.accept(createCompletionProposal("Pizza",context)));
> In the completeRule_Property, you retrieve the model element from the
> context and and check which concept is used, so you propose only the
> properties of that concept.
> Similarly you adapt validation, so that only valid concepts and their
> properties are used. It would make sense to hold a datastructure for
> concepts and properties, so that you have easy access to them from
> wherever they are needed (code completion, validation, highlighting if
> you want...)
>
> Alex
Hi Alex,
thanks for your valuable input! I implemented your idea and it works
exactly like I wanted to have it:-)
Ulli
|
|
|
Re: Dangling reference when dynamically creating EMF instances [message #673288 is a reply to message #671887] |
Mon, 23 May 2011 06:29 |
Knut Wannheden Messages: 298 Registered: July 2009 |
Senior Member |
|
|
Hi Ulli,
On 5/19/11 10:46 AM, Ulli Hafner wrote:
> On 05/18/2011 05:09 PM, Alexander Nittka wrote:
>
> E.g., I have a concept 'Pizza' that has a property 'topping' which refers to
> another concept 'Salami' that has a property 'spiciness' that refers to a
> concept 'Hot'. (These concepts are given before I'm opening the editor, but
> they can change during an Eclipse session. I.e. the user changes the OWL
> model, opens the xtext editor to define some rules, closes the editor, changes
> the model, opens the rule editor, etc.)
>
Since the identifiers in your Xtext language conceptually represent references
to objects in your OWL model I would also define them as cross references in
the Xtext grammar. Even if you only need code completion, as you say.
The reason for declaring it as a cross reference is that you probably would
like a change to the OWL model to cause the referencing Xtext files to be
revalidated. The only reasonable way to support this is to use cross
references. The Xtext builder will then (provided that the OWL model is in the
index as I outlined in approach 1 of my first reply) automatically revalidate
any referencing Xtext files as soon as the the OWL model is modified.
> What I would like to have is an editor, that can parse e.g. the following
> expression:
>
> Pizza 'and' topping 'is' Salami 'and' spiciness 'is' Hot
>
> Context assist must be context sensitive, e.g. when the cursor is at X:
> "Pizza 'and' X" then only topping should be available and not spiciness. As
> well as after the user typed 'topping' then only all topping should be available.
>
This should work automatically if you define the scope provider accordingly
for your language.
Again, I think what Alex proposes will certainly fulfill your code completion
requirements, but to me it sounds like you should actually go through the
extra trouble to use proper cross references.
--knut
|
|
| | |
Re: Dangling reference when dynamically creating EMF instances [message #673400 is a reply to message #673290] |
Mon, 23 May 2011 13:51 |
Ulli Hafner Messages: 8 Registered: July 2009 |
Junior Member |
|
|
On 05/23/2011 08:46 AM, Ed Willink wrote:
> Hi
>>
>> Since the identifiers in your Xtext language conceptually represent
>> references to objects in your OWL model I would also define them as
>> cross references in the Xtext grammar. Even if you only need code
>> completion, as you say.
>>
> You may think that you only want code completion, but if you work
> with-Xtext you will find all sorts of functionality such Find
> References, Name Refactoring, Go to Definition work almost
> automatically. If you start to work against-Xtext you will find that
> every new piece of functionality involves a new fight with largely
> undocumented APIs. and that fight is in danger of requiring repeated
> work with each new Xtext release.
Well, I already noted that the API is not well documented (which is
quite uncommon for Eclipse projects). Most of the JavaDoc is just
denoting the authors of the API...
>
> I use Xtext for OCL for which source may be perhaps 75% references.
> Using true AST model references in the Indigo release rather than CST
> references in the Helios release has made many parts of the code much
> cleaner. For the Xtext OCL editor, even 'built-in' operator names and
> 'built-in' types are references so that they can be model-defined.
>
> If, after detailed study, you really want to reject references, then I
> suspect you should reject Xtext too.
>
I think the "quick and dirty" approach works quite well for our use case
right now. I still can switch to the more complex approach in some later
iterations.
Ulli
|
|
| |
Re: Dangling reference when dynamically creating EMF instances [message #673405 is a reply to message #673290] |
Mon, 23 May 2011 13:51 |
Ulli Hafner Messages: 8 Registered: July 2009 |
Junior Member |
|
|
On 05/23/2011 08:46 AM, Ed Willink wrote:
> Hi
>>
>> Since the identifiers in your Xtext language conceptually represent
>> references to objects in your OWL model I would also define them as
>> cross references in the Xtext grammar. Even if you only need code
>> completion, as you say.
>>
> You may think that you only want code completion, but if you work
> with-Xtext you will find all sorts of functionality such Find
> References, Name Refactoring, Go to Definition work almost
> automatically. If you start to work against-Xtext you will find that
> every new piece of functionality involves a new fight with largely
> undocumented APIs. and that fight is in danger of requiring repeated
> work with each new Xtext release.
Well, I already noted that the API is not well documented (which is
quite uncommon for Eclipse projects). Most of the JavaDoc is just
denoting the authors of the API...
>
> I use Xtext for OCL for which source may be perhaps 75% references.
> Using true AST model references in the Indigo release rather than CST
> references in the Helios release has made many parts of the code much
> cleaner. For the Xtext OCL editor, even 'built-in' operator names and
> 'built-in' types are references so that they can be model-defined.
>
> If, after detailed study, you really want to reject references, then I
> suspect you should reject Xtext too.
>
I think the "quick and dirty" approach works quite well for our use case
right now. I still can switch to the more complex approach in some later
iterations.
Ulli
|
|
| | |
Goto Forum:
Current Time: Wed Sep 25 22:36:32 GMT 2024
Powered by FUDForum. Page generated in 0.04973 seconds
|