Home » Modeling » TMF (Xtext) » Problem with scopes
| |
Re: Problem with scopes [message #893377 is a reply to message #893350] |
Tue, 03 July 2012 18:39 |
Sergio Otero Messages: 39 Registered: June 2012 |
Member |
|
|
Hi
I'll try to define the problem using a variation of the Martin Fowler example (and writing without Eclipse, so maybe there are some errors)
Imagine that when selecting the State in a Transition, you don't want all available States, but only States without Actions (i know it doesn't make sense here, it's only a example).
Transition: event=[Event] '=>' state=[State]
You can accomplish that doing:
def IScope scope_Transition_state(Transition t, EReference ref) {
Scopes::scopeFor(t.stateMachine.states.filter[s | s.actions.size == 0])
}
def Statemachine stateMachine(Transition t) {
// navigate from transition to it's parent Statemachine
}
Suppose you change the grammar to support the definition of events, commands and states in separated files
From:
Statemachine :
'events'
(events+=Event)+
'end'
('resetEvents'
(resetEvents+=[Event])+
'end')?
'commands'
(commands+=Command)+
'end'
(states+=State)+;
To
Statemachine: Event | Command | State
Only with this change, you can define in separate files Events, Commands and States and references like "Transition: event=[Event] '=>' state=[State];" continue to work perfectly.
The problem is that now i cannot do the "trick" of browsing the EMF model to do the scoping.
Instead of that, i would need to get the default proposal and filter those that have 0 actions (this is only an alternative without the grammar change):
def IScope scope_Transition_state(Transition t, EReference ref) {
val baseScope = super.delegateGetScope(t, ref)
// I don't know how to filter here the object IScope
baseScope
}
I've tried to use FilteringScope with a closure like you suggested in other thread (http://www.eclipse.org/forums/index.php/m/802897/). More or less like that:
val filtscope = new FilteringScope(baseScope, [iod| EObjectOrProxy instanceof State])
It's not testing if the State has 0 actions, but even that returns false because the object is a proxy, not the State.
Maybe digging more inside IEObjectDescription i could get it to work, but something tells me this is not the best way
If you need more clarifications, please tell me.
Thanks
Sergio
|
|
|
Re: Problem with scopes [message #893391 is a reply to message #893377] |
Tue, 03 July 2012 19:52 |
|
Hi,
Using this example you a facing a lot of problems/restrictions at the same time.
never the less lets give it a try, (using the fowler sample of xtext 2.2.1)
(0) change grammar to allow only one thing in one file and states having zero actions
(1) we want to store the information of a State having actions in the index. since indexing is done at a state where no cross refs exists/are linked we could do something like ....
sadly the hooks for such things are still far away from being perfect,
public class StatenachineResourceDescriptionStrategy extends
DefaultResourceDescriptionStrategy {
public static final String HAS_ACTIONS = "HAS_ACTIONS";
@Override
public boolean createEObjectDescriptions(EObject eObject,
IAcceptor<IEObjectDescription> acceptor) {
if (eObject instanceof State) {
return createStateDescriptions((State) eObject, acceptor);
}
return super.createEObjectDescriptions(eObject, acceptor);
}
public boolean createStateDescriptions(State state, IAcceptor<IEObjectDescription> acceptor) {
if (getQualifiedNameProvider() == null)
return false;
try {
QualifiedName qualifiedName = getQualifiedNameProvider().getFullyQualifiedName(state);
if (qualifiedName != null) {
Map<String, String> data = new HashMap<String, String>();
data.put(HAS_ACTIONS, Boolean.toString(NodeModelUtils.findNodesForFeature(state, StatemachinePackage.Literals.STATE__ACTIONS).size() > 0));
acceptor.accept(EObjectDescription.create(qualifiedName, state, data ));
}
} catch (Exception exc) {
exc.printStackTrace();
}
return true;
}
}
and bind it in the runtime module
public Class<? extends IDefaultResourceDescriptionStrategy> bindIDefaultResourceDescriptionStrategy() {
return StatenachineResourceDescriptionStrategy.class;
}
finally we use the data in the scope provider
public class StatemachineScopeProvider extends AbstractDeclarativeScopeProvider {
public IScope scope_Transition_state(Transition t, EReference ref) {
return new FilteringScope(delegateGetScope(t, ref), new Predicate<IEObjectDescription>() {
@Override
public boolean apply(IEObjectDescription input) {
String hasActions = input.getUserData(StatenachineResourceDescriptionStrategy.HAS_ACTIONS);
return hasActions != null && !Boolean.valueOf(hasActions);
}
});
}
}
please note: (if states and transitions are defined in the same file) you have to do a second adoptions for the local resource
public class StatemchineImportedNamespaceAwareLocalScopeProvider extends
ImportedNamespaceAwareLocalScopeProvider {
@Inject
private IQualifiedNameProvider qualifiedNameProvider;
@Override
protected ISelectable internalGetAllDescriptions(final Resource resource) {
Iterable<EObject> allContents = new Iterable<EObject>(){
public Iterator<EObject> iterator() {
return EcoreUtil.getAllContents(resource, false);
}
};
Iterable<IEObjectDescription> allDescriptions = scopedElementsFor2(allContents, qualifiedNameProvider);
return new MultimapBasedSelectable(allDescriptions);
}
public <T extends EObject> Iterable<IEObjectDescription> scopedElementsFor2(Iterable<? extends T> elements,
final Function<T, QualifiedName> nameComputation) {
Iterable<IEObjectDescription> transformed = Iterables.transform(elements,
new Function<T, IEObjectDescription>() {
public IEObjectDescription apply(T from) {
final QualifiedName qualifiedName = nameComputation.apply(from);
Map<String, String> data = new HashMap<String, String>();
if (from instanceof State) {
data.put(StatenachineResourceDescriptionStrategy.HAS_ACTIONS,Boolean.toString(((State)from).getActions().size() > 0));
if (qualifiedName != null)
return new EObjectDescription(qualifiedName, from, data );
} else {
if (qualifiedName != null)
return new EObjectDescription(qualifiedName, from, null );
}
return null;
}
});
return Iterables.filter(transformed, Predicates.notNull());
}
}
and again do the binding
public void configureIScopeProviderDelegate(com.google.inject.Binder binder) {
binder.bind(IScopeProvider.class).annotatedWith(Names.named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)).to(StatemchineImportedNamespaceAwareLocalScopeProvider.class);
}
~Christian
--
Need training, onsite consulting or any other kind of help for Xtext?
Go visit http://xtext.itemis.com or send a mail to xtext@itemis.de
|
|
| |
Goto Forum:
Current Time: Tue Sep 24 14:36:05 GMT 2024
Powered by FUDForum. Page generated in 0.03910 seconds
|