Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Implicit reference to an EObject
Implicit reference to an EObject [message #1769577] Tue, 01 August 2017 20:59 Go to next message
Nicolas Hili is currently offline Nicolas HiliFriend
Messages: 40
Registered: March 2017
Member
Hi all,

I am trying to implement an action language for UML state machines in order to be able to graphically model state machines and to use a Xtext editor to write action code for transition effects and state entry/exit. It works, and I have two editors side-by-side. When a state or a transition is selected, the Xtext editor allows me to write action code with syntax highlighting, auto-completion, and so on. When I finish editing my action code using Xtext, a UML Opaque Behavior is created for the transition effect/state entry/exit, and the action code is stored as a String in the body of the Opaque Behavior. The action code is not explicitly stored in an independent Resource.

My problem is the following: I do not know how to create my scope provider (for auto completion) without having to explicitly refer in my grammar to the contextual EObject (transition or state) for which I am currently editing the action code.

The following will better illustrate my problem:

myDSL.xtext:
Action:
	container=[uml::NamedElement] '/' // I want to get rid of this line
	statements+=Statement*
;

Statement:
	SendStatement
;

SendStatement:
	'send' portRef=PortRef ':' operation=Operation ';'
;

/* ... */



The desired output:
reception/
	send portOwnedByThisComponent:myMessage();


This output shows the action code of a transition named reception. The action code simply sends a message myMessage to the port named portOwnedByThisComponent. My problem is that I want to get rid of the first line. I am currently editing (in the graphical editor) the reception transition and I do not want to explicitly refer to it in the action code (as the action code is embedded as a String in the Opaque Behavior of the transition, I already know that this action code is related to this transition).

However:

myDSLScopeProvider.xtend:
override getScope(EObject context, EReference reference) {
		
		val contextElement = ContextElementUtil.getContextElement(reference.eResource)
		val rootElement = EcoreUtil2.getRootContainer(context) // Give me the Action
		
		val scope = super.getScope(context, reference)
		
		if (context instanceof SendStatement && reference == MyDSLPackage.Literals.PORT_REF__PORT) {
			val component = getComponent((rootElement as Action).container) // my problem is here
			val candidates = EcoreUtil2.getAllContentsOfType(component, Port)
			
			for (var i = candidates.length -1; i >= 0; i--) {
				candidates.remove(i);
			}
			return Scopes.scopeFor(candidates)
		}
}
/* ... */


In my scope provider, to be able to only accept sending messages through ports owned by the component containing the state or the transition for which the action code is edited, I need to keep a reference to the state/transition. Therefore, the line:

val component = getComponent((rootElement as Action).container)


requires me to have a reference to rootElement.container (which is, according to my grammar, a NamedElement, and specifically either a UML Transition or a UML State). The function getComponent then returns the component (UML Class) containing the state/transition.

My question: how to get rid of that? How is it possible to get an implicit reference to the state/transition without explicitly referring to it in my grammar (using injection ?). My first attempt was to retrieve the currently edited UML element in the graphical editor (the one that is currently selected). But I think this is not the correct way of doing it, as I will probably need to parse my action code (for analysis purposes, M2M, M2T, ...) even if the model is not opened in the graphical editor. The action code is simply stored as a string, and it is not contained in an independent resource, so I cannot rely on the name of that resource to know to which transition/state the action code refers. My guess is to use injections, but I do not know where to start.

Hope it is clear. Let me know otherwise,

Best,

Nicolas
Re: Implicit reference to an EObject [message #1769675 is a reply to message #1769577] Wed, 02 August 2017 14:50 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14062
Registered: July 2009
Senior Member
what you can do is something like

Action:
	// no container here
	statements+=Statement*
;

ActionUncalled:
	container=[uml::NamedElement] '/' //  take care that the derived metamodel has the container
;




and then use org.eclipse.xtext.linking.lazy.SyntheticLinkingSupport.createAndSetProxy(EObject, EReference, String) to give the name for the reference

e.g. as described in https://www.eclipse.org/forums/index.php?t=msg&th=1086361&goto=1763908&#msg_1763908


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicit reference to an EObject [message #1769681 is a reply to message #1769675] Wed, 02 August 2017 15:36 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14062
Registered: July 2009
Senior Member
PS maybe your requirements are differently and I did not get them
Maybe you can come up with a different explanation


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicit reference to an EObject [message #1769721 is a reply to message #1769675] Wed, 02 August 2017 21:33 Go to previous messageGo to next message
Nicolas Hili is currently offline Nicolas HiliFriend
Messages: 40
Registered: March 2017
Member
Hello Christian,

Thanks a lot for your proposed solution, which is I think very close to what I want to achieve. I think it is actually half of the solution I am looking for :)

Following your message and the other forum thread, I did the following:


  1. I modified the Xtext resource by adding the ActionUncalled rule. However, I am not sure to understand how the ActionUncalled rule affects my generated metamodel. Should it automatically create the container derived attribute in the Action EObject in the generated metamodel ? In my case, the rule does nothing (apart from creating an ActionUncalled concept in the metamodel that is never used);
  2. Following the previous observation, I manually edited the generated metamodel (not sure this is the correct way of doing it) to add the container derived attribute in the Action EObject;
  3. I edited my MyDSLRuntimeModule as following:
    class MyDSLRuntimeModule extends AbstractMyDSLRuntimeModule {
    		
    	def Class<? extends IDerivedStateComputer> bindIDerivedStateComputer() {
    		println("test")
    		MyDSLDerivedStateComputer
    	}
    	
    	override bindXtextResource() {
    		DerivedStateAwareResource;
    	}
    	
    	def Class<? extends IResourceDescription.Manager> bindIResourceDescriptionManager() {
    		DerivedStateAwareResourceDescriptionManager;
    	}
    
    }
    

  4. I implemented a first prototype of MyDSLDerivedStateComputer as follow:
    	@Inject
    	SyntheticLinkingSupport sls;
    	
    	@Override
    	public void installDerivedState(DerivedStateAwareResource resource, boolean preLinkingPhase) {
    		if (!resource.getContents().isEmpty()) {
    			// preLinkingPhase seems to always be false
    			EObject obj = resource.getContents().get(0); // returns the Action
    			sls.createAndSetProxy(obj, MyDSLPackage.Literals.ACTION__CONTAINER, "PLAYING");
    		}
    	}
    
    	@Override
    	public void discardDerivedState(DerivedStateAwareResource resource) {
    			// nothing here
    	}
    

    "PLAYING" is the name of the state that I refer to. I am using a SimpleNameProvider.
  5. After all these steps, in my MyDSLScopeProvider,
    (rootElement as Action).container
    returns my container! I could then get rid of the first line in my grammar!


However, I do not know now how to change the line:
sls.createAndSetProxy(obj, MyDSLPackage.Literals.ACTION__CONTAINER, "PLAYING");


so "PLAYING" is the name of an EObject (provided that the ResourceDescription exists and therefore the EObject I want to refer to has been exported) that is provided to the MyDSLDerivedStateComputer from outside.

Assuming that I have the graphical editor and the Xtext editor opened side-by-side and the State or Transition to which the action code refers to, I could easily (1) get the active editor, and (2) get the selected graphical element.

But assuming that I do not have the graphical editor opened and I only have a reference to my State or my Transition, as well as a String containing the action code, how do I ask Xtext to parse the String containing the action code and provides the MyDSLDerivedStateComputer with a reference of the EObject?

I hope it is clearer,

Related questions from above:


  1. What is the purpose of the rule Action_Uncalled ?
  2. Do I really need to edit the generated metamodel to add the derived attribute ?


Thanks a lot for your time,

Nicolas
Re: Implicit reference to an EObject [message #1769723 is a reply to message #1769721] Wed, 02 August 2017 21:42 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14062
Registered: July 2009
Senior Member
Sorry paste problem

Should read
ActionUncalled returns Action: ...

This should add the missing container reference to the action class
Then you should get the container constant as well.


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicit reference to an EObject [message #1769803 is a reply to message #1769723] Thu, 03 August 2017 13:58 Go to previous messageGo to next message
Nicolas Hili is currently offline Nicolas HiliFriend
Messages: 40
Registered: March 2017
Member
Hey Christian,

Thanks for your reply.

I understand a bit better now. It works using the ActionUncall rule.

For my other issue (injecting the EObject into Xtext), I managed to find a workaround. When I instantiate my Xtext editor, I get the IDerivedStateComputer from the injector:
MyDSLActivator activator = MyDSLActivator.getInstance();
Injector injector = activator.getInjector(MyDSLActivator.MYDSL_MYDSL);
MyDSLDerivedStateComputer myDSLDerivedStateComputer = (MyDSLDerivedStateComputer)injector.getInstance(IDerivedStateComputer.class);

From the class responsible for instantiating the Xtext editor, I then set the reference to the EObject to MyDSLDerivedStateComputer (which contain a field to store it). I can then use its name by using org.eclipse.xtext.linking.lazy.SyntheticLinkingSupport.createAndSetProxy(EObject, EReference, String) .

Not sure it is the best way to achieve it, but it works :)
Hope this could help others,

Thanks a lot,

Nicolas
Re: Implicit reference to an EObject [message #1769805 is a reply to message #1769803] Thu, 03 August 2017 13:59 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14062
Registered: July 2009
Senior Member
what is the object/place you are at. why is this place itself not created via guice
so that you can do a simple

@Inject?


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicit reference to an EObject [message #1770027 is a reply to message #1769805] Mon, 07 August 2017 15:14 Go to previous messageGo to next message
Nicolas Hili is currently offline Nicolas HiliFriend
Messages: 40
Registered: March 2017
Member
Hello Christian,

Sorry for my late answer,

That's a solution, but not sure how to do it properly with Guice (I am a newbie using Guice). In my runtime module, I implemented an "input" field (typed with NamedElement) and a method with the @Provides annotation:

@Provides @Named("input")
def NamedElement getInput() {
	return input;
}


And in my DerivedStateComputer, I added the field with the following annotations:

@Inject @Named("input") @Nullable
NamedElement input;


However, in my runtime module, I still have to set the value of "input" at run-time. So, whenever/wherever the selection in my graphical editor is changed, I get the newly edited input (typed with NamedElement) and set the new value to the runtime module. Is that the correct way of doing it? I feel I am missing something.

Nicolas
Re: Implicit reference to an EObject [message #1770028 is a reply to message #1770027] Mon, 07 August 2017 15:17 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14062
Registered: July 2009
Senior Member
hmmm i am not sure if i got your context (so where is the place you have/know the named element.
where is the code you call the code? how is that code created (via guice?)


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicit reference to an EObject [message #1770031 is a reply to message #1770028] Mon, 07 August 2017 15:44 Go to previous messageGo to next message
Nicolas Hili is currently offline Nicolas HiliFriend
Messages: 40
Registered: March 2017
Member
The place I have the named element is an Eclipse part extending org.eclipse.ui.part.Page and implementing ISelectionListener. In the `selectionChanged' function, I get the new selection, and if it is a NamedElement (either State or Transition), I want to update the NamedElement in my DerivedStateComputer.
Re: Implicit reference to an EObject [message #1770037 is a reply to message #1770031] Mon, 07 August 2017 16:25 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14062
Registered: July 2009
Senior Member
if you register the part with the xtext factory

class="org.xtext.example.mydsl.ui.MyDslExecutableExtensionFactory:a.b.c.MyView"

create a objectholder class
mark it with @singleton
inject it to both MyView and the inferrer

simply


Need professional support for Xtext, Xpand, EMF?
Go to: https://www.itemis.com/en/it-services/methods-and-tools/xtext
Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Implicit reference to an EObject [message #1770052 is a reply to message #1770037] Mon, 07 August 2017 18:44 Go to previous message
Nicolas Hili is currently offline Nicolas HiliFriend
Messages: 40
Registered: March 2017
Member
Thanks Christian,

I will give it a try soon.

Nicolas
Previous Topic:How to override Error Messages
Next Topic:Xtext validation
Goto Forum:
  


Current Time: Sat Sep 18 08:46:45 GMT 2021

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

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

Back to the top