Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Get the object containing the actual cross-reference
Get the object containing the actual cross-reference [message #1768837] Mon, 24 July 2017 09:11 Go to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 69
Registered: July 2009
Member
Hello everyone

I am looking for the right way to get to the object refering to my current object via cross-reference.

My code-generator needs to deal with some logic when the current object is a cross-reference which can be contained within different types.

Using the debugger I saw the the objects impl has the information within the eStorage under which I found a grammarElementOrArray field which has eAssignmentImpl. The eContainer of the assignment is the object containing the cross-reference.

What would be the correct (and most efficient) API to access this information?

Thanks
Re: Get the object containing the actual cross-reference [message #1768844 is a reply to message #1768837] Mon, 24 July 2017 10:10 Go to previous messageGo to next message
Axel Guckelsberger is currently offline Axel GuckelsbergerFriend
Messages: 354
Registered: July 2009
Senior Member
I think this is not Xtext specific, but a general EMF question.

Maybe this helps:
https://sdqweb.ipd.kit.edu/wiki/EMF_Reverse_Lookup_/_navigating_unidirectional_references_bidirectional
Re: Get the object containing the actual cross-reference [message #1768848 is a reply to message #1768844] Mon, 24 July 2017 10:42 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 69
Registered: July 2009
Member
Thanks, though I have to figure how to use this in my Xtext setup.

I was tempted to add the question to the EMF-Forum but I was hoping that Xtext provides some utility api (like EcoreUtils2, and the like).
Re: Get the object containing the actual cross-reference [message #1768857 is a reply to message #1768837] Mon, 24 July 2017 11:43 Go to previous messageGo to next message
Karsten Thoms is currently offline Karsten ThomsFriend
Messages: 762
Registered: July 2009
Location: Dortmund, Germany
Senior Member

No, that's a plain EMF issue. The ECrossReferenceAdapter is the way to go. Note that one object could be referred by several elements, although likely not in your case.
Re: Get the object containing the actual cross-reference [message #1768889 is a reply to message #1768857] Mon, 24 July 2017 15:25 Go to previous messageGo to next message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 69
Registered: July 2009
Member
Using the ECrossReferenceAdapter yields the same results as by navigating upwards with eContainer calls.

I assume my design might be broken a little.

I will try to explain my model using a simplified version. What I am modelling is a simple structure:
Data
- 1 -n Fields
- 1- n Groups 
-- each Group can define 1-n Fields again
-- each Group can define 1-n Subgroups


Within the configuration I try to model we have lots of Fields which have to be specified in several Data blocks, so I want to define a common type which again defines 1-n Fields. Those common-fields are cross-referenced at each location where a field would be valid. The generator expands those types as though there would be n fields.


In order to keep everything as simple as possible I changed my model like this (skipping the groups and subgroups since it is the same as in the previous sample), so there should be no need for an additional Common-DSL.
Model
-Common
-- 1-n CommonField
--- 1-n Field
-Data
-- 1 -n Field | CommonField
-- 1- n Group


Basically starting a new dsl-file you have to choose if you are going to define a data-block or a common-block.


Example file for common declaration
Common {
	CommonA{
		Text A
		Text B
		Text C
		Text D
	}
	CommonB{
		Date X
		Date Y
	}
}


Putting it together
SomethingA

Fields {
		Integer IntA
		Integer IntB
                type CommonB  // <-- interesting
}
GroupA {
	Fields {
		Integer IntX
                type CommonA // <-- the generator has to know that this cross-ref is inside GroupA
	}
}


The grammar is modelled like this (skipped everything not relevant). The model is defined with Xcore
ModelRule returns Model:
	 "Common" "{" (commonFields+=CommonFieldsRule)+ "}" |data=DataRule
;

CommonFieldsRule returns CommonField:
	name=ID "{"
		(fields+=FieldRule)+
	"}"	
;

DataRule returns Data: 
	name=ID
	("Fields" "{"
		(fields+=FieldRule)+
	"}")*
	(groups+=GroupRule)+
;


GroupRule returns Group:
		name=ID "{"
		("Fields" "{"
			(fields+=SingleFieldOrCommonFieldRefRule)+
		"}")*
		(groups+=GroupRule)*
	"}"
;

SingleFieldOrCommonFieldRefRule returns Field:
	CommonFieldRefRule | FieldRule
;

CommonFieldRefRule returns CommonFieldRef:
	"type" fieldRef=[CommonField]
;


FieldRule returns SingleField:
	name=ID
;


All this works as expected, except the one problem stated in the beginning. I cannot figure out if a cross-reference to a CommonField was specified within a (Sub-)Group or just within the Data-block.


Now I tried using the recommended ECrossReferenceAdapter in my Generator.

class DatenversorgungDslGenerator extends AbstractGenerator {

	@Inject
    private XtextResourceSet resourceSet;

	val crossReferenceAdapter = new ECrossReferenceAdapter()

	override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
		resourceSet.eAdapters.add(crossReferenceAdapter)
		... start codegen
	}
...

	def dispatch CharSequence printData(Group group)'''
		<group.name»>
			«FOR field : group.fields.filter[it.valid]»
				«field.printData»
			«ENDFOR»
			«FOR subgroups : group.groups.filter[it.valid]»
				«subgroups.printData»
			«ENDFOR»
		</group.name»>
	'''
	
	
	
	def dispatch CharSequence printData (CommonFieldRef commonFieldRef)'''
		«FOR field : commonFieldRef.fieldRef.fields»
			field.printData»
		«ENDFOR»
	'''
	
	
	def dispatch CharSequence printData(SingleField field){
		val sb = new StringBuilder("<")
		... append some stuff
		if(field.eContainer instanceof Group){
			sb.append("group=\"" + (field.eContainer as Group).name + "\"")
		}
		else if (field.eContainer instanceof CommonField) {
			// figure out if the CommonField was referenced from within a group
			val settings = crossReferenceAdapter.getInverseReferences(field.eContainer, true) // eContainer of CommonField should be CommonFieldRef which contains the cross-ref
			settings.forEach[
				println(it.EObject)
				val x = (it.EStructuralFeature) as EReference
				if(x.equals(MyPackage.eINSTANCE.commonFieldRef_FieldRef)){
					println(it.EObject)					
				}
			]
		}
		
		return sb.toString
	}


My problem in the last method is, no matter what I try with the EReference I get from the ECrossReferenceAdapter, the results are always within the "Common" branch of Model where I was hoping to navigate (inverse) to the Data-branch.

[Updated on: Mon, 24 July 2017 15:33]

Report message to a moderator

Re: Get the object containing the actual cross-reference [message #1768895 is a reply to message #1768889] Mon, 24 July 2017 17:12 Go to previous message
Marc Schlegel is currently offline Marc SchlegelFriend
Messages: 69
Registered: July 2009
Member
Oh oh...I think I just forgot to model the "opposite" direction in my xcore model.

EDIT: Using opposite declaration for cross-references doesnt work in my case because in Xtext they have to be modelled on both sides when crossing resource-boundaries (because the model needs to be reconstructed from the file).

I ended up changing my generator by passing down a possible group (if available) instead of trying to resolve the location of the cross-reference


Thanks for everyones help

[Updated on: Tue, 25 July 2017 09:29]

Report message to a moderator

Previous Topic:Unable to resolve some references in .mwe2 file
Next Topic:INT interferes with defined terminals
Goto Forum:
  


Current Time: Thu Sep 19 14:24:00 GMT 2024

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

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

Back to the top