Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » ScopeProvider and Linker
ScopeProvider and Linker [message #1763891] Mon, 22 May 2017 16:38 Go to next message
Fy Za is currently offline Fy ZaFriend
Messages: 245
Registered: March 2010
Senior Member
Hi all

I have this metamodel
package fsm : fsm = 'http://fsm'
{
	class FSM
	{
		property ownedState#owningFSM : State[*|1] { ordered composes };
	}
	class State
	{
		property owningFSM#ownedState : FSM[1];
		attribute name : String[?];
		property outgoingTransition#source : Transition[*|1] { ordered composes };
		property incomingTransition#target : Transition[*|1] { ordered };
		attribute initial : Boolean[1];
		attribute final : Boolean[1];
	}
	class Transition
	{
		property source#outgoingTransition : State[1];
		property target#incomingTransition : State[1];
		attribute input : String[?];
		attribute output : String[?];
	}
	primitive datatype _'String' : 'java.lang.String' { serializable };
}


I generate a Xtext grammar from this metamodel
// automatically generated by Xtext
grammar org.xtext.example.fsm.FSM with org.eclipse.xtext.common.Terminals

import "http://fsm" 
import "http://www.eclipse.org/emf/2002/Ecore" as ecore

FSM returns FSM:
	{FSM}
	'FSM'
	'{'
		('ownedState' '{' ownedState+=State ( "," ownedState+=State)* '}' )?
	'}';

State returns State:
	initial?='initial'
	final?='final'
	'State'
	'{'
		('name' name=ID)?
		('outgoingTransition' '{' outgoingTransition+=Transition ( "," outgoingTransition+=Transition)* '}' )?
	'}';

Transition returns Transition:
	'Transition'
	'{'
		('input' input=STRING)?
		('output' output=STRING)?
		'target' target=[State|ID]
	'}';


In order to manage the eopposite relation target <--> incomingTransition
I create a FSMLinker class
public class FSMLinker extends LazyLinker {
	@Override
	protected EObject createProxy(EObject obj, INode node, EReference eRef) {
                        State s = (State) ((Transition)obj).eContainer();
			FSM fsm = (FSM) s.eContainer();
			for (State  state : fsm.getOwnedState())
				if(state.getName().equals(node.getText())){
					return state;
				}

		return super.createProxy(obj, node, eRef);
	}
}

I manage also the scope provider by editing FSMScopeProvider
class FSMScopeProvider extends AbstractFSMScopeProvider {

	override getScope(EObject object, EReference ref) {
		if (object instanceof Transition) {
			scope_Transition_target(object as Transition, ref)
		}
	}
	def scope_Transition_target(Transition transition, EReference reference) {
		var ArrayList<IEObjectDescription> res = new ArrayList<IEObjectDescription>
		var State s = transition.eContainer as State
		var FSM fsm = s.eContainer as FSM
		for (state : fsm.ownedState) {
			res.add(EObjectDescription.create(state.name, state))
		}
		return new SimpleScope(IScope.NULLSCOPE, res)
	}
}

When I create a model like this
FSM{
	ownedState
	{ 
		initial final State { name s1  outgoingTransition {Transition {
			input "did" output "aa" target s1     
		}   
			
		}},
		initial final State { name s2 }       
	}      
}           

no error is happened.
However, when i change the model to be like that

FSM{
	ownedState
	{ 
		initial final State { name s1  outgoingTransition {Transition {
			input "did" output "aa" target s2     
		}   
			
		}},
		initial final State { name s2 }       
	}      
}           

An error appears
- The required feature 'target' of 'fsm.impl.TransitionImpl@58395231{platform:/resource/fsm/test.fsm#//@ownedState.0/@outgoingTransition.0}' must be set

Any suggestion?
Re: ScopeProvider and Linker [message #1763894 is a reply to message #1763891] Mon, 22 May 2017 16:56 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Hi,

unfortuantely the way you post your stuff makes it hard to reproduce. (having an xcore metamodel would make it easier for example)

i dont see where you create the transitions. and i dont know your rules: shall this work within one files. or with multiple files as well.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ScopeProvider and Linker [message #1763896 is a reply to message #1763894] Mon, 22 May 2017 17:01 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Maybe it is enhough to clone the proxy instead of simply returning it. But as I said. A reproducible example would help

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ScopeProvider and Linker [message #1763908 is a reply to message #1763896] Mon, 22 May 2017 19:07 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
well after installing and fiddling around with oclinecore the following seems to work

public class MyDslDerivedStateComputer implements IDerivedStateComputer {
	
	@Inject
	SyntheticLinkingSupport sls;

	@Override
	public void installDerivedState(DerivedStateAwareResource resource, boolean preLinkingPhase) {
		if (!resource.getContents().isEmpty() && preLinkingPhase) {
			FSM fsm = (FSM) resource.getContents().get(0);
			for (State s : fsm.getOwnedState()) {
				for (State ss : fsm.getOwnedState()) {
					for (Transition t : ss.getOutgoingTransition()) {
						List<INode> nodes = NodeModelUtils.findNodesForFeature(t, FsmPackage.Literals.TRANSITION__TARGET);
						if (!nodes.isEmpty()) {
							String text = nodes.get(0).getText().trim();
							if (s.getName().equals(text)) {
								final EObject proxy = EcoreUtil.create(FsmPackage.Literals.TRANSITION);
								((InternalEObject) proxy).eSetProxyURI(EcoreUtil.getURI(t));
								s.getIncomingTransition().add((Transition) proxy);
							}
						}
					}
				}
			}
		}
		
	}

	@Override
	public void discardDerivedState(DerivedStateAwareResource resource) {
		if (!resource.getContents().isEmpty()) {
			FSM fsm = (FSM) resource.getContents().get(0);
			for (State s : fsm.getOwnedState()) {
				s.getIncomingTransition().clear();
			}
		}
		
	}

}


class MyDslRuntimeModule extends AbstractMyDslRuntimeModule {

	def Class<? extends IDerivedStateComputer> bindIDerivedStateComputer() {
		MyDslDerivedStateComputer
	}
	
	def Class<? extends Manager> bindIResourceDescription$Manager() {
		DerivedStateAwareResourceDescriptionManager
	}
	
	override Class<? extends XtextResource> bindXtextResource() {
		DerivedStateAwareResource
	}
	
}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ScopeProvider and Linker [message #1763915 is a reply to message #1763908] Mon, 22 May 2017 21:38 Go to previous messageGo to next message
Fy Za is currently offline Fy ZaFriend
Messages: 245
Registered: March 2010
Senior Member
Thank you Christian for your personal investment.
I am sorry if the case study is not very clear.
I shared it in my github https://github.com/fzalila/fsm

I added the MyDslDerivedStateComputer.
I comment the Linker class.
The error disappears.
However, when I save a fsm model (test.fsm ) as xmi here, the incomingTransition reference, the eopposite reference of target reference, is not populated.

It means that the state "s3"
<ownedState name="s3" initial="true" final="true"/>
lacks
... incomingTransition="//@ownedState.0/@outgoingTransition.0">

Any idea how can I complete this information?

Re: ScopeProvider and Linker [message #1763916 is a reply to message #1763915] Mon, 22 May 2017 22:01 Go to previous messageGo to next message
Fy Za is currently offline Fy ZaFriend
Messages: 245
Registered: March 2010
Senior Member
In addition, when I try to create the model with the EMF editor and I add the target reference, an error occurs
It says that State.incomingTransition violates the upper bound: It holds 1 values, but only 0 are allowed.
However State.incomingTransition is an 0..* reference

Any suggestion?

java.lang.RuntimeException: Could not serialize State:
State.incomingTransition violates the upper bound: It holds 1 values, but only 0 are allowed.
Semantic Object: FSM.ownedState[0]->State's'
URI: platform:/resource/fsm-examples/My.fsm
Context: State returns State
	at org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic$ExceptionThrowingAcceptor.accept(ISerializationDiagnostic.java:131)
	at org.eclipse.xtext.serializer.sequencer.BacktrackingSemanticSequencer.createSequence(BacktrackingSemanticSequencer.java:503)
	at org.xtext.example.fsm.serializer.FSMSemanticSequencer.sequence_State(FSMSemanticSequencer.java:69)
	at org.xtext.example.fsm.serializer.FSMSemanticSequencer.sequence(FSMSemanticSequencer.java:39)
	at org.eclipse.xtext.serializer.sequencer.AbstractSemanticSequencer.createSequence(AbstractSemanticSequencer.java:67)
	at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.acceptEObjectRuleCall(SequenceFeeder.java:325)
	at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.acceptRuleCall(SequenceFeeder.java:352)
	at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.accept(SequenceFeeder.java:263)
	at org.eclipse.xtext.serializer.sequencer.BacktrackingSemanticSequencer.accept(BacktrackingSemanticSequencer.java:434)
	at org.eclipse.xtext.serializer.sequencer.BacktrackingSemanticSequencer.createSequence(BacktrackingSemanticSequencer.java:501)
	at org.xtext.example.fsm.serializer.FSMSemanticSequencer.sequence_FSM(FSMSemanticSequencer.java:57)
	at org.xtext.example.fsm.serializer.FSMSemanticSequencer.sequence(FSMSemanticSequencer.java:36)
	at org.eclipse.xtext.serializer.sequencer.AbstractSemanticSequencer.createSequence(AbstractSemanticSequencer.java:67)
	at org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:115)
	at org.eclipse.xtext.serializer.impl.Serializer.serializeToRegions(Serializer.java:136)
	at org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:142)
	at org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:189)
	at org.eclipse.xtext.resource.XtextResource.doSave(XtextResource.java:386)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.save(ResourceImpl.java:1430)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.saveOnlyIfChangedWithMemoryBuffer(ResourceImpl.java:1144)
	at org.eclipse.emf.ecore.resource.impl.ResourceImpl.save(ResourceImpl.java:985)
	at fsm.presentation.FsmEditor$18.execute(FsmEditor.java:1498)
	at org.eclipse.ui.actions.WorkspaceModifyOperation.lambda$0(WorkspaceModifyOperation.java:107)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2240)
	at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:2267)
	at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:128)
	at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:119)
Re: ScopeProvider and Linker [message #1763919 is a reply to message #1763916] Tue, 23 May 2017 03:05 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
For the latter you have to customize itransientvalueservice

Unfortunately the eopposit support in Xtext is quite bad.
So I have no idea.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ScopeProvider and Linker [message #1763920 is a reply to message #1763919] Tue, 23 May 2017 03:11 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
and i my unit test it works fine

/*
 * generated by Xtext 2.12.0-SNAPSHOT
 */
package org.xtext.example.mydsl.tests

import com.google.inject.Inject
import fsm.FSM
import org.eclipse.xtext.testing.InjectWith
import org.eclipse.xtext.testing.XtextRunner
import org.eclipse.xtext.testing.util.ParseHelper
import org.eclipse.xtext.testing.validation.ValidationTestHelper
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.eclipse.emf.ecore.EPackage
import fsm.FsmPackage
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
import org.eclipse.emf.common.util.URI
import java.io.ByteArrayOutputStream
import java.nio.charset.StandardCharsets

@RunWith(XtextRunner)
@InjectWith(MyDslInjectorProvider)
class MyDslParsingTest {
	@Inject
	ParseHelper<FSM> parseHelper
	
	@Inject extension ValidationTestHelper h
	
	@Test
	def void loadModel() {
		EPackage.Registry.INSTANCE.put(FsmPackage.eNS_URI, FsmPackage::eINSTANCE)
		val result = parseHelper.parse('''
			FSM{
				ownedState
				{ 
					initial final State { name s1  outgoingTransition {Transition {
						input "did" output "aa" target s2     
					}   
						
					}},
					initial final State { name s2 }       
				}      
			}           
		''')
		Assert.assertNotNull(result)
		Assert.assertTrue(result.eResource.errors.isEmpty)
		println(result.validate)
		println('''
		«FOR s : result.ownedState»
			«s.name»: 
			«FOR t : s.outgoingTransition»
				«t.target.name»
			«ENDFOR»
			«s.name»: «s.incomingTransition»
		«ENDFOR»
		''')
		
		val RS2 = new ResourceSetImpl
		val r2 = RS2.createResource(URI.createURI("dummy.xmi"))
		r2.contents.add(result)
		val baos = new ByteArrayOutputStream
		r2.save(baos, null)
		println(new String(baos.toByteArray, StandardCharsets.UTF_8))
	}
}



Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ScopeProvider and Linker [message #1763946 is a reply to message #1763920] Tue, 23 May 2017 09:42 Go to previous messageGo to next message
Fy Za is currently offline Fy ZaFriend
Messages: 245
Registered: March 2010
Senior Member
For me also the test is fine.
For the tested model
FSM{
				ownedState
				{ 
					initial final State { name s1  outgoingTransition {Transition {
						input "did" output "aa" target s2     
					}   
						
					}},
					initial final State { name s2 }       
				}      
			}     

when, I test parse it, I obtain the correct xmi
<?xml version="1.0" encoding="ASCII"?>
<fsm:FSM xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:fsm="http://fsm">
  <ownedState name="s1" initial="true" final="true">
    <outgoingTransition target="//@ownedState.1" input="did" output="aa"/>
  </ownedState>
  <ownedState name="s2" incomingTransition="//@ownedState.0/@outgoingTransition.0" initial="true" final="true"/>
</fsm:FSM>

However, when I Run my toxmi method
I obtain the following without incomingTransition
<?xml version="1.0" encoding="ASCII"?>
<fsm:FSM xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:fsm="http://fsm">
  <ownedState name="s1" initial="true" final="true">
    <outgoingTransition target="//@ownedState.1" input="did" output="aa"/>
  </ownedState>
  <ownedState name="s2" initial="true" final="true"/>
</fsm:FSM>


This is my code used to save as xmi.
	public void run(IAction action) {
		IFile file = getFile();
		URI xtextURI = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
	    
	    XtextResourceSet resourceSet = new XtextResourceSet();
	    Resource xtextResource = resourceSet.createResource(xtextURI);
	    System.out.println(xtextURI.toString());
	    if (xtextResource != null){
		    Map<String,Boolean> options = new HashMap<String,Boolean>();
		    options.put(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
		    try {
				xtextResource.load(options);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		    Resource xmiResource = new XMIResourceFactoryImpl().createResource(xtextURI.trimFileExtension().appendFileExtension("xmi"));
		    xmiResource.getContents().add(xtextResource.getContents().get(0));
		    EcoreUtil.resolveAll(resourceSet);
		    try {
				xmiResource.save(null);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    }else{
	    	ModelStatus sts = new ModelStatus(IStatus.ERROR, "org.eclipse.xtext.toXmi", "http://fsm", "Impossible to load the selected file for xmi conversion.\n" +
	    			"Maybe this file is not an XText instance ? Status");
	    	ErrorDialog.openError(shell, "Error", "Impossible to load the selected file for xmi conversion.\n" +
	    			"Maybe this file is not an XText instance ?", sts);
	    }
	}


Is it correct, PLZ ?
Re: ScopeProvider and Linker [message #1763952 is a reply to message #1763946] Tue, 23 May 2017 11:08 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
XtextResourceSet resourceSet = new XtextResourceSet();
Resource xtextResource = resourceSet.createResource(xtextURI);
System.out.println(xtextURI.toString());

maybe you should inject a iresourcesetprovider
to obtain the resourceset for the project


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

[Updated on: Tue, 23 May 2017 11:25]

Report message to a moderator

Re: ScopeProvider and Linker [message #1763964 is a reply to message #1763952] Tue, 23 May 2017 12:49 Go to previous messageGo to next message
Fy Za is currently offline Fy ZaFriend
Messages: 245
Registered: March 2010
Senior Member
I update my toXmi class
	public void run(IAction action) {
		IFile file = getFile();

	    
		Injector injector = FsmActivator.getInstance().getInjector("org.xtext.example.fsm.FSM");
		XtextResourceSetProvider provider = injector.getInstance(XtextResourceSetProvider.class);
		ResourceSet resourceSet = provider.get(file.getProject()); 

		URI xtextURI = URI.createPlatformResourceURI(file.getFullPath().toString(), true);

		XtextResource xtextResource = (XtextResource) resourceSet.getResource(xtextURI, true);;

	    if (xtextResource != null){
		    Map<String,Boolean> options = new HashMap<String,Boolean>();
		    options.put(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
		    try {
				xtextResource.load(options);
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		    Resource xmiResource = new XMIResourceFactoryImpl().createResource(xtextURI.trimFileExtension().appendFileExtension("xmi"));
		    xmiResource.getContents().add(xtextResource.getContents().get(0));

		    EcoreUtil.resolveAll(resourceSet);
		    try {
				xmiResource.save(null);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    }else{
	    	ModelStatus sts = new ModelStatus(IStatus.ERROR, "org.eclipse.xtext.toXmi", "http://fsm", "Impossible to load the selected file for xmi conversion.\n" +
	    			"Maybe this file is not an XText instance ? Status");
	    	ErrorDialog.openError(shell, "Error", "Impossible to load the selected file for xmi conversion.\n" +
	    			"Maybe this file is not an XText instance ?", sts);
	    }
	}

I obtain that
<?xml version="1.0" encoding="ASCII"?>
<fsm:FSM xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:fsm="http://fsm">
  <ownedState name="s1" initial="true" final="true">
    <outgoingTransition input="did" output="aa">
      <target href="My.fsm#|0"/>
    </outgoingTransition>
  </ownedState>
  <ownedState name="s2" initial="true" final="true"/>
</fsm:FSM>

No IncomingTransition and target reference is not correct.

Plz, Christian, Does exist an example that can be followed to create my own toxmi module for my dsl?

best regards
Re: ScopeProvider and Linker [message #1763968 is a reply to message #1763964] Tue, 23 May 2017 13:00 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
no but if you push your stuff and a example project i might one day find the time to debug this.
did you check the model is correct "after" loading from xtext?

<target href="My.fsm#|0"/>

is an unresolved proxy.

this might have todo with how you load the model.

- can you leave out the resolve all
- and do a EcoreUtil.resolve after loading the model?


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ScopeProvider and Linker [message #1763969 is a reply to message #1763968] Tue, 23 May 2017 13:16 Go to previous messageGo to next message
Fy Za is currently offline Fy ZaFriend
Messages: 245
Registered: March 2010
Senior Member
The whole projects are here https://github.com/fzalila/fsm
This is my EMF project
https://github.com/fzalila/fsm/tree/master/org.eclipse.fsm
This is my Xtext project
https://github.com/fzalila/fsm/tree/master/org.xtext.example.fsm
This is my toXmi module https://github.com/fzalila/fsm/tree/master/org.eclipse.xtext.toXmi
and this is my example project
https://github.com/fzalila/fsm/tree/master/fsm-examples

Re: ScopeProvider and Linker [message #1763971 is a reply to message #1763969] Tue, 23 May 2017 13:34 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
issue is here

public void installDerivedState(DerivedStateAwareResource resource, boolean preLinkingPhase) {
if (!resource.getContents().isEmpty()) {
FSM fsm = (FSM) resource.getContents().get(0);

//remove the && preLinkingPhase


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: ScopeProvider and Linker [message #1763972 is a reply to message #1763971] Tue, 23 May 2017 13:44 Go to previous message
Fy Za is currently offline Fy ZaFriend
Messages: 245
Registered: March 2010
Senior Member
wonderfuuuuuuuuuuuuuul!!

Thanks Christian :-)

It works perfectly
Previous Topic:Loading Xtext Resource Into EMF Editor Breaks on Save?
Next Topic:[SOLVED] Xtext : Personalize Description
Goto Forum:
  


Current Time: Tue Apr 16 19:01:38 GMT 2024

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

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

Back to the top