Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » How to find the cross-references of an Eobject across files?
How to find the cross-references of an Eobject across files? [message #1835491] Fri, 04 December 2020 16:18 Go to next message
Giray Ozel is currently offline Giray OzelFriend
Messages: 18
Registered: February 2018
Junior Member
I have the following grammar. I have simplified it for the sake of demonstrating my issue.

Head:
	model=Model;

Model:
	ActivityModel | ComponentModel;

ActivityModel:
	activities+=Activity+
;

Activity:
	name=ID
;

ComponentModel:
	'Component' name=ID
	activities+=ComponentActivity+
;

ComponentActivity:
	name=ID ':'
	activityReference=[Activity]
;


I have these two files:

activityModel.myDsl
MyActivity


componentModel.myDsl
Component system
a : MyActivity
b : MyActivity


My goal is to navigate to ComponentModel instance from the Activity instance.

So, I tried accessing the "eCrossReferences" property of the activity but that was thrown out quickly since the list was empty.

Next, I started looking into "EcoreUtil.UsageCrossReferencer" but for that I need to give a resource as a parameter so it knows where to look. Is that the right direction? How do I find the resource, which is basically another file?

	// Xtend code
	val resource = ???;
	val settings = EcoreUtil.UsageCrossReferencer.find(activity,
		resource);
	for (setting : settings) {
		if (setting.EObject instanceof ComponentActivity) {
			return setting.EObject.eContainer() as TranslationModel;
		}
	}
Re: How to find the cross-references of an Eobject across files? [message #1835493 is a reply to message #1835491] Fri, 04 December 2020 17:17 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
Xtext has IReferenceFinder for finding references.

about your code: when you have an eObject in hand, you can ask it for its resource.

unfortunately you have zero hint how and where you want to execute this code


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to find the cross-references of an Eobject across files? [message #1835569 is a reply to message #1835493] Mon, 07 December 2020 09:57 Go to previous messageGo to next message
Giray Ozel is currently offline Giray OzelFriend
Messages: 18
Registered: February 2018
Junior Member
Christian Dietrich wrote on Fri, 04 December 2020 17:17
Xtext has IReferenceFinder for finding references.

about your code: when you have an eObject in hand, you can ask it for its resource.

unfortunately you have zero hint how and where you want to execute this code


I don't have an eObject inhand but I would like to get to the eObject of the ComponentModel ultimately. My difficulty is finding the references without having a resource to scope the UsageCrossReferencer or IReferenceFinder.

I would like to use it for code generation.
Re: How to find the cross-references of an Eobject across files? [message #1835570 is a reply to message #1835569] Mon, 07 December 2020 11:14 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
if you dont have a eobject at hand then i dont understand what you are doing and where you code is called from

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to find the cross-references of an Eobject across files? [message #1835571 is a reply to message #1835570] Mon, 07 December 2020 11:45 Go to previous messageGo to next message
Giray Ozel is currently offline Giray OzelFriend
Messages: 18
Registered: February 2018
Junior Member
The only eObject in hand that I have is the activity, which doesn't have a direct relationship to the ComponentActivity. What I would like to do is find all component activities that refer to the activity in hand and count them. And those component activities are in different files.

class MyDslGenerator extends AbstractGenerator {

	override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
		val model = (resource.allContents.head as Head).model
		if (model instanceof ActivityModel) {
			val activityModel = model as ActivityModel
			fsa.generateFile("Activities.txt", ActivityGenerator.generate(activityModel))
		}
	}
}

class ActivityGenerator {
	static def generate(ActivityModel activityModel) '''
	«FOR activity : activityModel.activities»
	Activity «activity.name» is referenced by «getReferenceCount(activity)» component activities.
	«ENDFOR»
	'''
	
	def static getReferenceCount(Activity activity) {
		// TODO: find the count of referencing component activities
		return 0;
	}
	
}
Re: How to find the cross-references of an Eobject across files? [message #1835572 is a reply to message #1835571] Mon, 07 December 2020 12:17 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
but with activityModel you have an eObject in hand ?!?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to find the cross-references of an Eobject across files? [message #1835576 is a reply to message #1835572] Mon, 07 December 2020 13:26 Go to previous messageGo to next message
Tamas Miklossy is currently offline Tamas MiklossyFriend
Messages: 157
Registered: February 2016
Senior Member
Hello Giray,

The following code snippet demonstrates the usage of the IReferenceFinder interface from the ActivityGenerator class:
package org.xtext.example.mydsl.generator

import com.google.inject.Inject
import com.google.inject.Provider
import org.eclipse.core.runtime.NullProgressMonitor
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EReference
import org.eclipse.emf.ecore.util.EcoreUtil
import org.eclipse.xtext.findReferences.IReferenceFinder
import org.eclipse.xtext.findReferences.IReferenceFinder.IResourceAccess
import org.eclipse.xtext.findReferences.TargetURIs
import org.eclipse.xtext.resource.IReferenceDescription
import org.eclipse.xtext.resource.IResourceDescriptions
import org.xtext.example.mydsl.myDsl.Activity
import org.xtext.example.mydsl.myDsl.ActivityModel

class ActivityGenerator {
	
	@Inject IReferenceFinder referenceFinder
	@Inject Provider<TargetURIs> targetURIProvider
	@Inject IResourceDescriptions resourceDescriptions
	
	def generate(ActivityModel activityModel) '''
		«FOR activity : activityModel.activities»
		Activity «activity.name» is referenced by «getReferenceCount(activity)» component activities.
		«ENDFOR»
	'''
	
	def getReferenceCount(Activity activity) {
		val acceptor = new MyDslReferenceAcceptor
		val uri = EcoreUtil.getURI(activity)
		val targetURIs = targetURIProvider.get
		targetURIs.addURI(uri)
		referenceFinder.findAllReferences(targetURIs, null, resourceDescriptions, acceptor, new NullProgressMonitor)
		return acceptor.count
	}
}

class MyDslReferenceAcceptor implements IReferenceFinder.Acceptor {
	
	int count = 0
	
	override accept(IReferenceDescription description) {
		count++
	}
	
	override accept(EObject source, URI sourceURI, EReference eReference, int index, EObject targetOrProxy, URI targetURI) {

	}
	
	def getCount() {
		count
	}
}


Hope that helps,
Tamás
Re: How to find the cross-references of an Eobject across files? [message #1835641 is a reply to message #1835576] Wed, 09 December 2020 11:28 Go to previous messageGo to next message
Giray Ozel is currently offline Giray OzelFriend
Messages: 18
Registered: February 2018
Junior Member
Hi Tamás,

Thanks for the example code but the injected dependencies are null for me so I get a NullPointerException on line "val targetURIs = targetURIProvider.get". Is there another configuration that is required?
Re: How to find the cross-references of an Eobject across files? [message #1835651 is a reply to message #1835641] Wed, 09 December 2020 13:38 Go to previous messageGo to next message
Tamas Miklossy is currently offline Tamas MiklossyFriend
Messages: 157
Registered: February 2016
Senior Member
You should inject the ActivityGenerator into the MyDslGenerator so that all members in the ActivityGenerator gets injected:

class MyDslGenerator extends AbstractGenerator {

	@Inject ActivityGenerator activityGenerator

	override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
		val model = (resource.allContents.head as Head).model
		if (model instanceof ActivityModel) {
			val activityModel = model as ActivityModel
			fsa.generateFile("Activities.txt", activityGenerator.generate(activityModel))
		}
	}
}
Re: How to find the cross-references of an Eobject across files? [message #1835868 is a reply to message #1835651] Tue, 15 December 2020 13:10 Go to previous messageGo to next message
Giray Ozel is currently offline Giray OzelFriend
Messages: 18
Registered: February 2018
Junior Member
Thanks Tamás, injecting it like that did the trick.

I would like to also group the references per component so I can have the following code text generated:

	static def generate(ActivityModel activityModel) '''
	«FOR activity : activityModel.activities»
	Activity «activity.name» is referenced by:
		«FOR pair : getReferenceCountPerComponent(activity)»
			«pair.value» activities in component '«pair.key.name»'
		«ENDFOR»
	«ENDFOR»
	'''

	def static List<Pair<ComponentModel, Integer>> getReferenceCountPerComponent(Activity activity) 
...


Is the best way to just modify the "override accept(IReferenceDescription description)" method to get the eObject (and navigate to the ComponentModel by asking for the eContainer) from the description parameter and keep count per component internally in the acceptor? If so, how does one go about to getting the EObject from an IReferenceDescription?
Re: How to find the cross-references of an Eobject across files? [message #1835951 is a reply to message #1835868] Thu, 17 December 2020 05:57 Go to previous message
Tamas Miklossy is currently offline Tamas MiklossyFriend
Messages: 157
Registered: February 2016
Senior Member
Hello Giray,

You may get some inspiration from the GEF DOT project.

The DotDescriptionLabelProvider class contains some implementation to access the eObject from an IEObjectDescription. Similar should also work for accessing the eObject from an IReferenceDescription.

Hope that helps,
Tamás
Previous Topic:Problems with JDK 14
Next Topic:Calling doGenerate in other doGenerate
Goto Forum:
  


Current Time: Fri Mar 29 12:30:25 GMT 2024

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

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

Back to the top