In this post I briefly describe how you can easily create Guice injected EAdapters for your model. These can then be used in client code which itself doesn't even have to be Guice aware.
Let's assume we'd like to define an adapter Foo in which we'd like to use the Xtext scope provider service:
public class Foo extends AdapterImpl {
@Inject
private IScopeProvider scopeProvider;
public void foo() {
// ...
}
}
public class FooAdapterFactory extends AdapterFactoryImpl {
@Inject
private Provider<Foo> adapterProvider;
@Override
public boolean isFactoryForType(Object type) {
return Foo.class == type;
}
@Override
protected Adapter createAdapter(Notifier target) {
return adapterProvider.get();
}
}
Next we register this adapter factory with the model's resource set. By doing this the client code can obtain an adapter without using the adapter factory directly and also without requiring to be created by the Guice container. E.g.
Model model = ...;
Foo foo = (Foo) EcoreUtil.getRegisteredAdapter(model, Foo.class);
foo.foo();
The most natural place to add the adapter factory to the resource set is in the Xtext linker, where we have the afterModelLinked() hook:
public class MyDslLinker extends LazyLinker {
@Override
protected void afterModelLinked(EObject model, IDiagnosticConsumer diagnosticsConsumer) {
registerFooAdapterFactory(model.eResource().getResourceSet());
}
@Inject
private Provider<FooAdapterFactory> factoryProvider;
private void registerFooAdapterFactory(ResourceSet resourceSet) {
EList<AdapterFactory> adapterFactories = resourceSet.getAdapterFactories();
if (Iterables.isEmpty((Iterables.filter(adapterFactories, FooAdapterFactory.class)))) {
adapterFactories.add(factoryProvider.get());
}
}
}
As a final step we must add a binding to MyDslRuntimeModule:
public class MyDslRuntimeModule extends AbstractCodeTabRuntimeModule {
@Override
public Class<? extends org.eclipse.xtext.linking.ILinker> bindILinker() {
return MyDslLinker.class;
}
}
Now we're all set! All the client code has to do is to obtain the adapter using the EcoreUtil.getRegisteredAdapter() method as described earlier.
No comments:
Post a Comment