Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » ReferenceDescription contains empty eReference
ReferenceDescription contains empty eReference [message #1649199] Wed, 04 March 2015 07:48 Go to next message
Bernd Hofner is currently offline Bernd HofnerFriend
Messages: 68
Registered: July 2009
Member
Hello,

here the short version of my problem:

I'm iterating through the each ReferenceDescription rd of each ResourceDescription r of my workspace.
When accessing the Reference described by the ResourceDescription, using rd.getEReference(),
I sometimes get the desired reference, but sometimes the returned reference is NULL.

Opening the affected resource file in the DSL editor remedies the problem -
so I gather its a problem when and how much of the underlying cache is filled/refreshed.

Can I somehow force the cache to be refreshed sufficiently deep to have the references of the
ReferenceDescriptions resolved? Using
 XtextResourceSet.getEObject(Source URI of my reference)

gets the desired result - but is painfully slow.

Note that I'm currently stuck with XText 1.0.2.

Has anyone here an idea?


Now the long version of the problem:

My DSL provides a CSS like mechanism that allows to declare and set named properties
which are then cascaded down the package hierarchy. On the way down, a property value
can be overridden by an equally named property.

Example:
package A {

	Declare Property resultTable

	Property resultTable= "Table A"
	
	Rule A1 {
		// no "Property resultTable" given 
		// => fall back to nearest value in scope: "Table A"
		// scope resolution: 
		// -> Rule: no property "resultTable" defined 
		// -> contained in Package A: property "resultTable" is defined there => "Table A"
	}
	Rule A2 {
		Property resultTable= "Table A1"
		// Property "resultTable" is given, so the value "Table A" given on package level 
		// is overridden with "Table A1"
		// scope resolution: 
		// -> Rule: property "resultTable" is defined => "Table A1"
	}
}

Package A.B {
	Property resultTable= "Table A.B"
	
	Rule AB1 {
		// no "Property resultTable" given 
		// => fall back to nearest value in scope: "Table A.B"
		// scope resolution: 
		// -> Rule: no property "resultTable" defined
		// -> contained in Package A.B: property "resultTable" is defined => "Table A.B"
	}
}

Package A.C {
	
	Rule AC1 {
		// no "Property resultTable" given 
		// => fall back to nearest value in scope: "Table A"
		// scope resolution: 
		// -> Rule: no property "resultTable" defined 
		// -> contained in Package A.C: no property "resultTable" defined
		// -> contained in Package A: property "resultTable" is defined => "Table A"
	}
}


When generating output from the DSL, I collect the properties and property values for a given "Rule" model element.
I do this by walking through the resource descriptions:

// We're looking for "Property" model elements 
EClass 	eclsElement= DqlFactory.eINSTANCE.getDqlPackage().getProperty();
		
Provider<IResourceDescriptions> provider=
	Access.getIResourceDescriptions();

Iterator<IResourceDescription> resourceDescs=
	provider.get().getAllResourceDescriptions().iterator();
while(resourceDescs.hasNext())
{
	IResourceDescription resourceDesc=
		resourceDescs.next();
	for(IReferenceDescription rd : resourceDesc.getReferenceDescriptions())
	{
// !! rd.getEReference() == null if "reference cache" has not been refreshed !!
		if(rd.getEReference() != null && eclsElement.equals(rd.getEReference().eContainer()))
		{
			EObject eProp= getResourceSet().getEObject(rd.getSourceEObjectUri(), true);
			Property e= (Property)eEigenschaft;
			// now collect the property and its value.
		}
	}
}

I found out that I can force the resolution of references like this:

EObject eReferer= getResourceSet().getEObject(rd.getSourceEObjectUri(), true);
if(eclsElement.equals(eReferer.eClass())) {
	...
}

with:

private XtextResourceSet getResourceSet()
{
	if(resourceSet == null)
		resourceSet= new XtextResourceSet();
	return resourceSet;
}


But this is painfully slow when iterating over a workspace with lots of resources.

Thanks in advance for any ideas,

Bernd
Re: ReferenceDescription contains empty eReference [message #1649346 is a reply to message #1649199] Wed, 04 March 2015 09:24 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Hi,

hard to give advice on a such old question, but:
where is the reference in your (not posted grammar)



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ReferenceDescription contains empty eReference [message #1649356 is a reply to message #1649346] Wed, 04 March 2015 09:30 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
p.s:

maybe you can store the following information in the user data of the EObjectDescriptions

- which property is declared in which package

and use that information to calculate your property map

(i remember adapting the indexing in this old version was much more difficult than it is today)


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Wed, 04 March 2015 09:31]

Report message to a moderator

Re: ReferenceDescription contains empty eReference [message #1649419 is a reply to message #1649356] Wed, 04 March 2015 10:07 Go to previous messageGo to next message
Bernd Hofner is currently offline Bernd HofnerFriend
Messages: 68
Registered: July 2009
Member
Hello Christian,

thanks for the reply!

Is there significant hope that this problem won't occur with XText 2?

The reference is from the property to the property declaration.

The grammar looks like this (for the sake of the forum post, I replaced "Eigenschaft" with "Property" in my above example.

Eigenschaftsdeklaration:
	'Deklariere Eigenschaft' name=ID;

Eigenschaft:
	'Eigenschaft' eigenschaft=[Eigenschaftsdeklaration|QualifiedName] '=' wert=STRING
;
Regel :
	'Regel' name=ID '{'

		// Optionale Auflistung von Eigenschaften.		
		(properties+=Eigenschaft)*

	'}';



Regarding filling the UserData - where would I need to hook into the parsing process to fill user data? I guess this would have to happen while parsing a "Property/Eigenschaft".

Bye, Bernd
Re: ReferenceDescription contains empty eReference [message #1649428 is a reply to message #1649419] Wed, 04 March 2015 10:13 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
set a breakpoint to EObjectDescription.create.

you may need a custom resourcedescription manager + maybe a custom resourcedescription as well
(downloading eclipse helios takes hours currently)

please note: you need the nodel model to give add a name to the Eigenschaft.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ReferenceDescription contains empty eReference [message #1649429 is a reply to message #1649428] Wed, 04 March 2015 10:13 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Another Question: what is the entry point for the generation?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ReferenceDescription contains empty eReference [message #1649778 is a reply to message #1649428] Wed, 04 March 2015 13:56 Go to previous messageGo to next message
Bernd Hofner is currently offline Bernd HofnerFriend
Messages: 68
Registered: July 2009
Member
Hello Christian,

> set a breakpoint to EObjectDescription.create.
I'll give it a try and have a look at the world around me from there.

> please note: you need the nodel model to give add a name to the Eigenschaft.
Hmm, I'm not sure if I understood that.
You mean that the model element "Eigenschaft" needs to have a name? Would this do?:

Eigenschaft:
'Eigenschaft' name=[Eigenschaftsdeklaration|QualifiedName] '=' wert=STRING
;
Re: ReferenceDescription contains empty eReference [message #1649788 is a reply to message #1649778] Wed, 04 March 2015 14:03 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
I thought you want to find out all visible 'Eigenschaften' in a Package.

thus you need them in the index.
thus you need a qualifiedNameProvider to get that name (name of the declaration)
since the name calc is done when the model is not liked yet you need
the node model to get the 'text' at the place of the cross reference


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ReferenceDescription contains empty eReference [message #1649812 is a reply to message #1649429] Wed, 04 March 2015 14:19 Go to previous messageGo to next message
Bernd Hofner is currently offline Bernd HofnerFriend
Messages: 68
Registered: July 2009
Member
>Another Question: what is the entry point for the generation?

My *.xpt template starts from a given Rule (Regel) model element.

I can dump the code section on you, if it helps.
It's currently full of debug output and notes to help me get into the problem context again and discarded lanes of thought. Sorry about the mess:

I spit out messages when passing through resource files named "eigenschaften.dql" - by convention, I place the "Eigenschaft" definitions in these files - but for the final code, I don' want to rely on this convention.

One of the ideas I would try to pursue is to limit the resolution of the referenced URI (getResourceSet().getEObject() to the cases where the "chance" that I need it resoved (i.e. it points to the right kind of model element) is high. I haven't quite grasped if I find enough relevant data for such a distinction in the ReferenceDescription and the URIs.

	public List<Eigenschaft> getProperties(Regel regel) {

		System.out.println("Regel " + regel.getName());
		
		// Alle Eigenschaften aus dem umgebenden Scope einsammeln.
		PackageDeclaration regelPackage= (PackageDeclaration)regel.eContainer();
		String regelPackageName= regelPackage.getName();
		
		
		Provider<IResourceDescriptions> provider=
			Access.getIResourceDescriptions();
		provider.get().getAllResourceDescriptions();
		
		

		Iterator<IResourceDescription> resourceDescs=
			provider.get().getAllResourceDescriptions().iterator();
		while(resourceDescs.hasNext())
		{
			IResourceDescription resourceDesc=
				resourceDescs.next();

			// Debug resolution of reference
			/*
			 * Die TargetURI zeigt auf die Eigenschaftsdeklaration, die zufällig
			 * in der gleichen Resource steht. 
			 * Wenn man den gesamten Cache durchsucht:
			 * 		a) Passende ResourceDescription finden:
			 * 				resourceDec.uri == targetEObj.uri."resourceUri()"
			 * 		b) In dieser ResourceDescription dann die exportierte EObjectDescription finden, die zur EObj-URI passt:
			 * 				eObjDesc.eFragment = targetEObj.uri.fragment()
			 * 		Wann diese eObjDesc dann eine EigenschaftsDeklaration ist, sollten wir die Referenz auflösen. 
			 *  
			 */
			
			
			/* -------------------------------- */
			if(resourceDesc.getURI().toString().contains("eigenschaften.dql")) {
				System.out.println("Eigenschaften: " + resourceDesc.getURI().toString());
				
				for(IReferenceDescription rd : resourceDesc.getReferenceDescriptions()) {
					
					Eigenschaft e= null;
					if(rd.getEReference() == null) {
						
						
						System.out.println(rd.getSourceEObjectUri());	// platform:/resource/DQ-DM-Doc/moVe/eigenschaften.dql#//@elements.0/@elements.1
						System.out.println(rd.getTargetEObjectUri());	// platform:/resource/DQ-DM-Doc/moVe/eigenschaften.dql#//@elements.0/@elements.0
						URI uri= rd.getSourceEObjectUri();
						
						System.out.println(uri.fragment());				// 	//@elements.0/@elements.1
						System.out.println(uri.path());					//	/resource/DQ-DM-Doc/moVe/eigenschaften.dql
						System.out.println(uri.scheme());				//	platform
						System.out.println(uri.toPlatformString(false));	//	/DQ-DM-Doc/moVe/eigenschaften.dql
						System.out.println(uri.toPlatformString(true));		//	/DQ-DM-Doc/moVe/eigenschaften.dql
						
						System.out.println(resourceDesc.getURI());		//	platform:/resource/DQ-DM-Doc/moVe/eigenschaften.dql
						
						for(IEObjectDescription ied : resourceDesc.getExportedObjects()) {
							System.out.println(ied.getName());
							System.out.println(ied.getEClass());
							System.out.println(ied.getEObjectURI());
							System.out.println(ied.getEObjectOrProxy());
							
							if(ied.getEObjectURI().equals(rd.getTargetEObjectUri())) {
								System.out.println(ied.getName());			// move.ErgebnisRelevanz
								System.out.println(ied.getEClass());		// org.eclipse.emf.ecore.impl.EClassImpl@7804a579 (name: Eigenschaftsdeklaration) (instanceClassName: null) (abstract: false, interface: false)
								System.out.println(ied.getEObjectURI());	// platform:/resource/DQ-DM-Doc/moVe/eigenschaften.dql#//@elements.0/@elements.0
							}
						}
						/*
						Iterator<IResourceDescription> rds=
							provider.get().getAllResourceDescriptions().iterator();
						while (rds.hasNext()) {
							IResourceDescription r
						}
						*/
						
						/*
							Funktioniert nicht
						IResourceDescription resDesc= provider.get().getResourceDescription(rd.getSourceEObjectUri());
						for(IEObjectDescription objDesc : resDesc.getExportedObjects()) {
							System.out.println(objDesc.getName());
						}
						*/
						
						EObject eReferer= getResourceSet().getEObject(rd.getSourceEObjectUri(), true);
						if(eclsElement.equals(eReferer.eClass())) {
							e= (Eigenschaft)eReferer;
						}
					} 
					else if(eclsElement.equals(rd.getEReference().eContainer())) {
						EObject eReferer= getResourceSet().getEObject(rd.getSourceEObjectUri(), true);						
						e= (Eigenschaft)eReferer;
					}
					if(e != null) {
						System.out.println("Eigenschaft: " + e.getEigenschaft().getName() + "= " + e.getWert()); 						
					}
				}
			}
			/* -------------------------------- */
			
			for(IReferenceDescription rd : resourceDesc.getReferenceDescriptions())
			{
				// rd.getEReference().getEType()		// EClass name: Eigenschaftsdeklaration 
				// rd.getEReference().eContainer()		// EClass name: Eigenschaft
				// System.out.println(rd.getEReference().getEReferenceType());		
				// System.out.println(rd.getEReference().getEReferenceType().getName());
				
				
				Eigenschaft e= null;
				if(rd.getEReference() == null) {
					// slow
					EObject eReferer= getResourceSet().getEObject(rd.getSourceEObjectUri(), true);
					if(eclsElement.equals(eReferer.eClass())) {
						e= (Eigenschaft)eReferer;
					}
				} 
				else if(eclsElement.equals(rd.getEReference().eContainer())) {
					// quick
					EObject eReferer= getResourceSet().getEObject(rd.getSourceEObjectUri(), true);						
					e= (Eigenschaft)eReferer;
				}
				if(e != null) {
					/*
					if(eReferer.eIsProxy()) {
						eReferer= EcoreUtil.resolve(eReferer, eReferer.eResource());
					}
					*/
					System.out.println("Eigenschaft: " + e.getEigenschaft().getName() + "= " + e.getWert()); 						
					collectEigenschaft(regelPackageName, e);
				}
			}
		}
		
		// Eigene Eigenschaften überschreiben ggf vorher eingesammlte Eigenschaften
		for(Eigenschaft regelEigenschaft : regel.getProperties())
		{
			name2Prop.put(regelEigenschaft.getEigenschaft().getName(), regelEigenschaft);
		}

		// Sortiere nach Eigenschaftsname
		List<Eigenschaft> scopedEigenschaften= new ArrayList<Eigenschaft>(name2Prop.values());
		Collections.sort(
				scopedEigenschaften, 
				new Comparator<Eigenschaft>() {
					@Override
					public int compare(Eigenschaft a, Eigenschaft b) {
						return CollectorUtil.qualifiedName(a.getEigenschaft()).compareTo(
								CollectorUtil.qualifiedName(b.getEigenschaft()));
					}
				}
		);
		
		return scopedEigenschaften;
	}
Re: ReferenceDescription contains empty eReference [message #1649837 is a reply to message #1649812] Wed, 04 March 2015 14:30 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
that is i understood it.
you would want to have all

Property resultTable= "Table A"

in the index with the information where it is

e.g.
- Property resultTable in A
- Property resultTable in A.A2
- Property resultTable in A.B

and based on that information you can get the right IEobjectDescription
(if you store the value in the index as well you would not even need to resolve it at all)


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ReferenceDescription contains empty eReference [message #1649868 is a reply to message #1649837] Wed, 04 March 2015 14:53 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
p.S.

maybe you can even ecode all the information in the calculated names of the elements. thus you would only have to write a name provider


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Wed, 04 March 2015 14:53]

Report message to a moderator

Re: ReferenceDescription contains empty eReference [message #1651235 is a reply to message #1649868] Thu, 05 March 2015 07:29 Go to previous messageGo to next message
Bernd Hofner is currently offline Bernd HofnerFriend
Messages: 68
Registered: July 2009
Member
Hmm, yes I can see the benefits of giving the "Eigenschaft" model element a name, thus making it a real citizen of the index.
I thought it might be a problem that the name is at the same time a reference to a "Deklariere Eigenschaft" ME, but I will give it a try.
Thanks for the inspriration!

Re: ReferenceDescription contains empty eReference [message #1651282 is a reply to message #1651235] Thu, 05 March 2015 08:02 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Hi,

as i said: the only thing you have to take care of is to read the reference text from the node model (dont know how NodeModelUtils was called back then)


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ReferenceDescription contains empty eReference [message #1654214 is a reply to message #1651282] Fri, 06 March 2015 15:38 Go to previous message
Bernd Hofner is currently offline Bernd HofnerFriend
Messages: 68
Registered: July 2009
Member
I soved the problem now using the following quick and dirty approach:

Iterate over the ResourceDescriptions and collect the EObjectURI of all exported objects of the "type" "Deklariere Eigenschaft" in a hashset.
Iterate over the ResourceDescriptions, collecting the contained IResourceDescriptions that have a targetEObjectUri that is in the previously collected hashmap.

The sourceEObjectUri of such a IResourceDescription then points to an Eigenschaft model element.

This works reasonably fast and reliable.
Nevertheless I'll have a look how to enrich the index with the desired user data.

Previous Topic:Question about autocompletion
Next Topic:XtextCON 2015
Goto Forum:
  


Current Time: Sat Apr 20 02:04:20 GMT 2024

Powered by FUDForum. Page generated in 0.04517 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top