Home » Modeling » TMF (Xtext) » Example for linking to imported objects?
Example for linking to imported objects? [message #59591] |
Thu, 16 July 2009 15:30  |
Eclipse User |
|
|
|
I'm wondering if there is a relativly simple example or implementation
out there for how to link to an object in a custom imported ecore
derived model?
in other words, I have an importURI for
platform:/resource/myproject.foo/MyModel.fee
And in my grammer, something like:
import 'platform:/resource/org.myplugin.balh/src/model/fee.ecore' as fee
....
SomeElement :
someRef=[fee:SomeEObject|ID] value=INT;
Where SomeEObject has an attribute refID that I want to link through.
And let's say I just want to present all instances of SomeEObject from
the top-level container to ContentAssist and Linker.
This sounds like it should be straighforward but I've been all over the
docuementation for Scopes and Linking and I think I can figure out a
hard way to do it, but I'm wondering if there is an easy one..
Here is where I am.. I have succesfully created custom linking service
and scope provider that subclass the defaults and I'm getting an
appropriate context and references passed in. But how to interrogate
the imported model instance? There is a lot of plumbing in there for
adapters and proxies, but I must admit it is pretty opaque to me.
|
|
| |
Re: Example for linking to imported objects? [message #59837 is a reply to message #59695] |
Thu, 16 July 2009 20:17   |
Eclipse User |
|
|
|
On 2009-07-16 13:28:26 -0700, Sebastian Zarnekow
<Sebastian.Zarnekow@itemis.de> said:
> Hi Miles,
>
> I think we will come up with an more complete example that covers this
> scenario in the near future. Please stay tuned :-)
I may do a blog entry if I can get this working.. ;)
>
> Meanwhile you may want to have a look at the class ScopedElements and
> the usages of its static helper methods. Linking on ContentAssist is
> all about Scoping.
Right, I got that part. My reading of docs is that it generally doesn't
make sense to do the linking service as the scope covers both that and
content, right?
So I did someting like
EList<Resource> resources =
context.eResource().getResourceSet().getResources();
List<IScopedElement> allElems = new ArrayList<IScopedElement>();
for (Resource resource : resources) {
System.err.println(resource);
EObject content = resource.getContents().get(0);
if (content instanceof SAttributed) {
for (SAttribute attr : ((SAttributed)
content).getAttributes()) {
allElems.add(ScopedElement.create(attr.getID(), attr));
};
Scope scope = new Scope();
scope.setElements(allElems);
return scope;
}
// Iterables.addAll(allElems, elems);
}
return super.getScope(context, reference);
Just to see if I was getting anywhere. And one really weird thing is
that if I used the super.getScope method, the referenced resource shows
up, but if I create my own scope first, it doesn't -- ever. Anyway,
with above I seem to get references, but this is what I mean by
figuring out the hard way to do it.. ;)
Now, basically by accident I've discoverd that an exception is getting
eaten. :( Because it's caught I never see it in debugger and for
wahtever reason it doesn't show up in console either. Its somewhere in
here:
try {
if (getEncoder().isCrossLinkFragment(this, uriFragment)) {
Triple<EObject, EReference, AbstractNode> triple =
getEncoder().decode(this, uriFragment);
List<EObject> linkedObjects =
getLinkingService().getLinkedObjects(triple.getFirst(),
triple.getSecond(),
triple.getThird());
if (linkedObjects.isEmpty()) {
XtextLinkingDiagnostic diag = createDiagnostic(triple);
if (!getErrors().contains(diag))
getErrors().add(diag);
return null;
}
if (linkedObjects.size() > 1)
throw new IllegalStateException("linkingService returned more than
one object for fragment "
+ uriFragment);
EObject result = linkedObjects.get(0);
if
(!triple.getSecond().getEReferenceType().isSuperTypeOf(resul t.eClass()))
{
XtextLinkingDiagnostic diag = createDiagnostic(triple);
if (!getErrors().contains(diag))
getErrors().add(diag);
return null;
}
// remove previously added error markers, since everything should
be fine now
XtextLinkingDiagnostic diag = createDiagnostic(triple);
getErrors().remove(diag);
return result;
}
} catch (RuntimeException e) {
// wrapped because the javaDoc of this method states that
WrappedExceptions are thrown
throw new WrappedException(e);
}
|
|
|
Re: Example for linking to imported objects? [message #59861 is a reply to message #59837] |
Thu, 16 July 2009 20:21   |
Eclipse User |
|
|
|
Oh, and I don't think I made clear, but even though I'm returning the
elements now they don't show up in content assist and the model
validates no matter what the value. So I'm thinkiong I actually do need
to do something with getLinkingObjects so that I can identify what
reference I want to use to link to, and when I set the breakpoint in
that method, the exception shows itself.
On 2009-07-16 17:17:48 -0700, Miles Parker <milesparker@gmail.com> said:
> On 2009-07-16 13:28:26 -0700, Sebastian Zarnekow
> <Sebastian.Zarnekow@itemis.de> said:
>
>> Hi Miles,
>>
>> I think we will come up with an more complete example that covers this
>> scenario in the near future. Please stay tuned :-)
>
> I may do a blog entry if I can get this working.. ;)
>
>>
>> Meanwhile you may want to have a look at the class ScopedElements and
>> the usages of its static helper methods. Linking on ContentAssist is
>> all about Scoping.
>
> Right, I got that part. My reading of docs is that it generally doesn't
> make sense to do the linking service as the scope covers both that and
> content, right?
>
> So I did someting like
>
> EList<Resource> resources =
> context.eResource().getResourceSet().getResources();
> List<IScopedElement> allElems = new ArrayList<IScopedElement>();
> for (Resource resource : resources) {
> System.err.println(resource);
> EObject content = resource.getContents().get(0);
> if (content instanceof SAttributed) {
> for (SAttribute attr : ((SAttributed)
> content).getAttributes()) {
> allElems.add(ScopedElement.create(attr.getID(), attr));
> };
> Scope scope = new Scope();
> scope.setElements(allElems);
> return scope;
> }
> // Iterables.addAll(allElems, elems);
> }
> return super.getScope(context, reference);
>
>
> Just to see if I was getting anywhere. And one really weird thing is
> that if I used the super.getScope method, the referenced resource shows
> up, but if I create my own scope first, it doesn't -- ever. Anyway,
> with above I seem to get references, but this is what I mean by
> figuring out the hard way to do it.. ;)
>
> Now, basically by accident I've discoverd that an exception is getting
> eaten. :( Because it's caught I never see it in debugger and for
> wahtever reason it doesn't show up in console either. Its somewhere in
> here:
>
> try {
> if (getEncoder().isCrossLinkFragment(this, uriFragment)) {
> Triple<EObject, EReference, AbstractNode> triple =
> getEncoder().decode(this, uriFragment);
> List<EObject> linkedObjects =
> getLinkingService().getLinkedObjects(triple.getFirst(),
> triple.getSecond(),
> triple.getThird());
> if (linkedObjects.isEmpty()) {
> XtextLinkingDiagnostic diag = createDiagnostic(triple);
> if (!getErrors().contains(diag))
> getErrors().add(diag);
> return null;
> }
> if (linkedObjects.size() > 1)
> throw new IllegalStateException("linkingService returned more than
> one object for fragment "
> + uriFragment);
> EObject result = linkedObjects.get(0);
> if
> (!triple.getSecond().getEReferenceType().isSuperTypeOf(resul t.eClass()))
> {
> XtextLinkingDiagnostic diag = createDiagnostic(triple);
> if (!getErrors().contains(diag))
> getErrors().add(diag);
> return null;
> }
> // remove previously added error markers, since everything should
> be fine now
> XtextLinkingDiagnostic diag = createDiagnostic(triple);
> getErrors().remove(diag);
> return result;
> }
> } catch (RuntimeException e) {
> // wrapped because the javaDoc of this method states that
> WrappedExceptions are thrown
> throw new WrappedException(e);
> }
|
|
|
Re: Example for linking to imported objects? [message #59933 is a reply to message #59861] |
Fri, 17 July 2009 05:01   |
Eclipse User |
|
|
|
Hi Miles,
please open the error log view in your eclipse and have a look for the
caught exception. I guess it was logged there.
Do you use the importURI mechanism to import other resources? These ones
are handled by the default scopes (you Scope implementation most likely
does it not) and only resolved on demand. That means, that there are no
other resources in your resource set which leads to the fact, that you
do not see any proposals.
Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
Am 17.07.2009 2:21 Uhr, schrieb Miles Parker:
>
> Oh, and I don't think I made clear, but even though I'm returning the
> elements now they don't show up in content assist and the model
> validates no matter what the value. So I'm thinkiong I actually do need
> to do something with getLinkingObjects so that I can identify what
> reference I want to use to link to, and when I set the breakpoint in
> that method, the exception shows itself.
>
> On 2009-07-16 17:17:48 -0700, Miles Parker <milesparker@gmail.com> said:
>
>> On 2009-07-16 13:28:26 -0700, Sebastian Zarnekow
>> <Sebastian.Zarnekow@itemis.de> said:
>>
>>> Hi Miles,
>>>
>>> I think we will come up with an more complete example that covers
>>> this scenario in the near future. Please stay tuned :-)
>>
>> I may do a blog entry if I can get this working.. ;)
>>
>>>
>>> Meanwhile you may want to have a look at the class ScopedElements and
>>> the usages of its static helper methods. Linking on ContentAssist is
>>> all about Scoping.
>>
>> Right, I got that part. My reading of docs is that it generally
>> doesn't make sense to do the linking service as the scope covers both
>> that and content, right?
>>
>> So I did someting like
>>
>> EList<Resource> resources =
>> context.eResource().getResourceSet().getResources();
>> List<IScopedElement> allElems = new ArrayList<IScopedElement>();
>> for (Resource resource : resources) {
>> System.err.println(resource);
>> EObject content = resource.getContents().get(0);
>> if (content instanceof SAttributed) {
>> for (SAttribute attr : ((SAttributed) content).getAttributes()) {
>> allElems.add(ScopedElement.create(attr.getID(), attr));
>> };
>> Scope scope = new Scope();
>> scope.setElements(allElems);
>> return scope;
>> }
>> // Iterables.addAll(allElems, elems);
>> }
>> return super.getScope(context, reference);
>>
>>
>> Just to see if I was getting anywhere. And one really weird thing is
>> that if I used the super.getScope method, the referenced resource
>> shows up, but if I create my own scope first, it doesn't -- ever.
>> Anyway, with above I seem to get references, but this is what I mean
>> by figuring out the hard way to do it.. ;)
>>
>> Now, basically by accident I've discoverd that an exception is getting
>> eaten. :( Because it's caught I never see it in debugger and for
>> wahtever reason it doesn't show up in console either. Its somewhere in
>> here:
>>
>> try {
>> if (getEncoder().isCrossLinkFragment(this, uriFragment)) {
>> Triple<EObject, EReference, AbstractNode> triple =
>> getEncoder().decode(this, uriFragment);
>> List<EObject> linkedObjects =
>> getLinkingService().getLinkedObjects(triple.getFirst(),
>> triple.getSecond(),
>> triple.getThird());
>> if (linkedObjects.isEmpty()) {
>> XtextLinkingDiagnostic diag = createDiagnostic(triple);
>> if (!getErrors().contains(diag))
>> getErrors().add(diag);
>> return null;
>> }
>> if (linkedObjects.size() > 1)
>> throw new IllegalStateException("linkingService returned more than one
>> object for fragment "
>> + uriFragment);
>> EObject result = linkedObjects.get(0);
>> if
>> (!triple.getSecond().getEReferenceType().isSuperTypeOf(resul t.eClass()))
>> {
>> XtextLinkingDiagnostic diag = createDiagnostic(triple);
>> if (!getErrors().contains(diag))
>> getErrors().add(diag);
>> return null;
>> }
>> // remove previously added error markers, since everything should be
>> fine now
>> XtextLinkingDiagnostic diag = createDiagnostic(triple);
>> getErrors().remove(diag);
>> return result;
>> }
>> } catch (RuntimeException e) {
>> // wrapped because the javaDoc of this method states that
>> WrappedExceptions are thrown
>> throw new WrappedException(e);
>> }
>
>
|
|
|
Re: Example for linking to imported objects? [message #60323 is a reply to message #59933] |
Fri, 17 July 2009 15:38   |
Eclipse User |
|
|
|
On 2009-07-17 02:01:27 -0700, Sebastian Zarnekow
<Sebastian.Zarnekow@itemis.de> said:
> Hi Miles,
>
> please open the error log view in your eclipse and have a look for the
> caught exception. I guess it was logged there.
No, that's the issue. If it were I would have noticed it. :) Somehow
the WrappedException is not propogating through and in the debugger I
can't get a stack trace from it. I meant to mention that it is an NPE.
So clearly somewhere in the try block there is an unexpected state that
we're getting to -- its always a bit of a funny smell to trap
RuntimeExceptions.. :)
>
> Do you use the importURI mechanism to import other resources? These
> ones are handled by the default scopes (you Scope implementation most
> likely does it not) and only resolved on demand. That means, that there
> are no other resources in your resource set which leads to the fact,
> that you do not see any proposals.
Yes, but then how do I force them to be resolved so that they do
appear? I think that is the core question. (I understood that the
scopes would not be resolved for a manually created scope, but what
surprised me was that if I do a new Scope then the imported resource
*never* gets loaded, even when I subsequenty do call the super default
method. Luckily it does work the other way around, so that if I am
careful to make sure that the super default scope method is called
first, then it does get loaded.
Its not clear from the code, but instances of SAttributed only exist in
the imported reference so the way the experimental code works now is it
always first calls the default scope creation. The issue there of
course is that the first time through we don't get the referernces. I'm
thinking that a hacky way to handle this is to call the
super.getScope() and then just ignore the results and build the Scope
manually. But anyway, with the current approach, I do get the set of
candidate objects from the imported resource, but then I get the
(swallowed) NPE. This is getting a little circular. :D
|
|
|
Re: Example for linking to imported objects? [message #60392 is a reply to message #60323] |
Fri, 17 July 2009 16:12   |
Eclipse User |
|
|
|
Hi Miles,
I guess the default poor mans reference mechanism to external files (via
importURI) may not be sufficient in your case.
What about making it explicit:
sAttributeContainer=[SAttributeContainer|String]
instead of the plain vanilla importURI=STRING.
You'ld have to implement the logic for this specific cross reference on
your own.
What do you think?
Btw: The caught NPE sounds like there was an unresolved EMF proxy involved.
Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
Am 17.07.2009 21:38 Uhr, schrieb Miles Parker:
> On 2009-07-17 02:01:27 -0700, Sebastian Zarnekow
> <Sebastian.Zarnekow@itemis.de> said:
>
>> Hi Miles,
>>
>> please open the error log view in your eclipse and have a look for the
>> caught exception. I guess it was logged there.
>
> No, that's the issue. If it were I would have noticed it. :) Somehow the
> WrappedException is not propogating through and in the debugger I can't
> get a stack trace from it. I meant to mention that it is an NPE. So
> clearly somewhere in the try block there is an unexpected state that
> we're getting to -- its always a bit of a funny smell to trap
> RuntimeExceptions.. :)
>
>>
>> Do you use the importURI mechanism to import other resources? These
>> ones are handled by the default scopes (you Scope implementation most
>> likely does it not) and only resolved on demand. That means, that
>> there are no other resources in your resource set which leads to the
>> fact, that you do not see any proposals.
>
> Yes, but then how do I force them to be resolved so that they do appear?
> I think that is the core question. (I understood that the scopes would
> not be resolved for a manually created scope, but what surprised me was
> that if I do a new Scope then the imported resource *never* gets loaded,
> even when I subsequenty do call the super default method. Luckily it
> does work the other way around, so that if I am careful to make sure
> that the super default scope method is called first, then it does get
> loaded.
>
> Its not clear from the code, but instances of SAttributed only exist in
> the imported reference so the way the experimental code works now is it
> always first calls the default scope creation. The issue there of course
> is that the first time through we don't get the referernces. I'm
> thinking that a hacky way to handle this is to call the super.getScope()
> and then just ignore the results and build the Scope manually. But
> anyway, with the current approach, I do get the set of candidate objects
> from the imported resource, but then I get the (swallowed) NPE. This is
> getting a little circular. :D
>
|
|
|
Re: Example for linking to imported objects? [message #60484 is a reply to message #60392] |
Fri, 17 July 2009 18:00   |
Eclipse User |
|
|
|
OK, it works! Thanks, Sebastian. I learned a lot about the internals in
the process..I never seem to be able to avoid that, lol.
The code ends up looking like this...
public IScope getScope(EObject context, EReference reference) {
IScope defaultScope = super.getScope(context, reference);
if (reference.getEType() == MetaABMPackage.eINSTANCE.getSAttribute()) {
EList<Resource> resources =
context.eResource().getResourceSet().getResources();
List<IScopedElement> allElems = new ArrayList<IScopedElement>();
for (Resource resource : resources) {
EObject content = resource.getContents().get(0);
if (reference.getEType() ==
MetaABMPackage.eINSTANCE.getSAttribute() && content instanceof
SAttributed) {
for (SAttribute attr : ((SAttributed)
content).getAttributes()) {
allElems.add(ScopedElement.create(attr.getID(), attr));
};
}
}
Scope scope = new Scope();
scope.setOuterScope(defaultScope);
scope.setElements(allElems);
return scope;
}
return defaultScope;
}
Here was I think the little secret..when I created the Scope, I didn't
assign an outer scope. So in AbstractScope it was looking for an outer
scope and throwing an NPE. It isn't clear to me why we should assume
that there is always an outer scope but perhaps I missed that
requirement. I think I should be able to implement the scope so it
doesn't need to do the overhead of getting all of the irrelevant
refernces each time, but so far performance isn't an issue. It is
almost all neccessary semantics, but still it seems that there should
be a way to provide some hooks to simplify the mechanism a bit (perhaps
a seperate abstract class). Let me know if you think this might be
something useful.
I think I will write up a quick blog entry on this so let me know if
you have any ideas to add.
On 2009-07-17 13:12:06 -0700, Sebastian Zarnekow
<Sebastian.Zarnekow@itemis.de> said:
> Hi Miles,
>
> I guess the default poor mans reference mechanism to external files
> (via importURI) may not be sufficient in your case.
>
> What about making it explicit:
>
> sAttributeContainer=[SAttributeContainer|String]
>
> instead of the plain vanilla importURI=STRING.
> You'ld have to implement the logic for this specific cross reference on
> your own.
>
> What do you think?
The importURI handles it so nicely though. :)
BTW, the refernced model contains a lot more than just the attributes
so that's why in answer to your question on my earlier post, yes it is
worth it to avoid the model to model transform. To make the M2M work in
the oAW XTExt, I actually had to build a whole bunch of wrapper
elements that were then unrolled on the M2M side.. Total nightmare,
impossible to maintain. :) But here I'm simplifying things a great deal
so that I can see if I can just get the linking to work correctly.
> Btw: The caught NPE sounds like there was an unresolved EMF proxy involved.
I did in fact have a reference to another metamodel in there -- so
thanks for the hint -- but it was being resolved properly as I had a
URI mapping for it. Good old EMF..
Any idea of why the Exception is getting swallowed though? I am getting
one of those pesky "log4j:WARN No appenders could be found for logger"
messages. If this was showing up in log properly it would have been a
lot easier to track this down.
-Miles
|
|
| |
Re: Example for linking to imported objects? [message #61668 is a reply to message #61002] |
Tue, 21 July 2009 02:04  |
Eclipse User |
|
|
|
Yeah, that was my presumption as well and no reason to think otherwise
as that's where all of the workflow issues go. I have seen a similar
issue with trapping RTEs in the core Eclipse UI code a while back. If
there are issues created with calling environment simultaneuously then
it is possible to get into a situation where the exception gets lost.
Anyway, I'll let you know if I'm able to get any more insight on this
or a repeatable test case.
On 2009-07-20 01:25:05 -0700, Sebastian Zarnekow
<Sebastian.Zarnekow@itemis.de> said:
> Hi Miles,
>
> see below.
>
> Am 18.07.2009 0:00 Uhr, schrieb Miles Parker:
>>
>> Any idea of why the Exception is getting swallowed though? I am getting
>> one of those pesky "log4j:WARN No appenders could be found for logger"
>> messages. If this was showing up in log properly it would have been a
>> lot easier to track this down.
>
> I don't think that this will lead to entirely "forgotten" exceptions.
> Did you find anything in the console output. Most properly the logger
> will delegate to the standard output in case of missing appenders.
>
> Regards,
> Sebastian
|
|
|
Goto Forum:
Current Time: Sat May 10 01:07:27 EDT 2025
Powered by FUDForum. Page generated in 0.04027 seconds
|