Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "GEF/GEF4/Common"

< GEF‎ | GEF4
Line 37: Line 37:
 
An [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] provides facilities to register and retrieve adapters via an [[GEF/GEF4/Common#IAdaptable, AdapterKey | AdapterKey]], which combines a type key ([http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/Class.html Class] or [http://docs.guava-libraries.googlecode.com/git-history/v15.0/javadoc/com/google/common/reflect/TypeToken.html TypeToken]) with an (optional) [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/String.html String] role. Having the option to use a [http://docs.guava-libraries.googlecode.com/git-history/v15.0/javadoc/com/google/common/reflect/TypeToken.html TypeToken] instead of a simple [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/Class.html Class] key, enables the type-safe registration of adapters with parameterized types. The combination with an additional (optional) role enables that multiple adapters of the same type may be registered at an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]].   
 
An [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] provides facilities to register and retrieve adapters via an [[GEF/GEF4/Common#IAdaptable, AdapterKey | AdapterKey]], which combines a type key ([http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/Class.html Class] or [http://docs.guava-libraries.googlecode.com/git-history/v15.0/javadoc/com/google/common/reflect/TypeToken.html TypeToken]) with an (optional) [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/String.html String] role. Having the option to use a [http://docs.guava-libraries.googlecode.com/git-history/v15.0/javadoc/com/google/common/reflect/TypeToken.html TypeToken] instead of a simple [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/Class.html Class] key, enables the type-safe registration of adapters with parameterized types. The combination with an additional (optional) role enables that multiple adapters of the same type may be registered at an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]].   
  
The 'traditional' getAdapter(Class<? super T>) method provided by the Eclipse Core Runtime [http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fcore%2Fruntime%2FIAdaptable.html IAdaptable] here is a mere convenience operation that will retrieve the single adapter registered with the respective [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/Class.html Class] key and the ''default'' role (or the only adapter registered under the given Class key, if there is only one adapter for that type key).  
+
The 'traditional' getAdapter(Class<? super T>) method provided by the Eclipse Core Runtime [http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fcore%2Fruntime%2FIAdaptable.html IAdaptable] here is a mere convenience operation that will retrieve the single adapter registered with the respective [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/Class.html Class] key and the ''default'' role (or the only adapter registered under the given [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/Class.html Class] key, if there is only one adapter for that type key).  
  
 
An adapter can thus now be registered and retrieved in various ways:
 
An adapter can thus now be registered and retrieved in various ways:
Line 87: Line 87:
  
 
=== AdaptableSupport ===
 
=== AdaptableSupport ===
To enforce that implementers of IAdaptable properly follow the above outlined contract, the package furthermore provides an AdaptableSupport class, which does not formally implement the [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] interface but provides implementations for all its methods and can thus be simply used as a delegate, as follows:
+
To enforce that implementers of [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] properly follow the above outlined contract, the package furthermore provides an [[GEF/GEF4/Common#AdaptableSupport | AdaptableSupport]] class, which does not formally implement the [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] interface but provides implementations for all its methods and can thus be simply used as a delegate, as follows:
  
 
<source lang="java">
 
<source lang="java">
Line 105: Line 105:
  
  
It needs to be provided with a [http://docs.oracle.com/javase/7/docs/api/index.html?java/beans/PropertyChangeSupport.html PropertyChangeSupport], which will be used to notify listeners about registration and unregistration of adapters. In case the adaptable, by which it is used as a delegate, is also [[GEF/GEF4/Common#IActivatable | IActivatable]], it will ensure that all [[GEF/GEF4/Common#IActivatable | IActivatable]] adapters are properly activated/deactivated when being registered/unregistered dependent on the active state of the adaptable at that moment.  
+
It needs to be provided with a [http://docs.oracle.com/javase/7/docs/api/index.html?java/beans/PropertyChangeSupport.html PropertyChangeSupport], which will be used to notify listeners about registration and unregistration of adapters. In case the [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]], by which it is used as a delegate, is also [[GEF/GEF4/Common#IActivatable | IActivatable]], it will ensure that all [[GEF/GEF4/Common#IActivatable | IActivatable]] adapters are properly activated/deactivated when being registered/unregistered dependent on the active state of the adaptable at that moment.  
  
 
=== AdapterStore ===
 
=== AdapterStore ===
The package furthermore provides an AdaptableStore, which can be used as a standalone [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]].
+
The package furthermore provides an [[GEF/GEF4/Common#AdaptableStore | AdaptableStore]], which can be used as a standalone [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]].
  
 
== Dispose  ==
 
== Dispose  ==
Line 122: Line 122:
 
[[File:GEF4-Common-inject-adaptermap.png|969px]]
 
[[File:GEF4-Common-inject-adaptermap.png|969px]]
  
This package contains [https://github.com/google/guice Google Guice]-based support for injection of adapters into an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]]. That is, if an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] implementation provides an [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Inject.html @Inject]-annotated method with a single Map<AdapterKey<?>, Object> parameter that is annotated with a respective inject annotation (@AdapterMap), and if respective adapter bindings are provided within a Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module], adapter instances can automatically be injected into instances of the [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] by means of a specific [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/MembersInjector.html MembersInjector]. It needs to be pointed out that respective adapter bindings are evaluated polymorphically, i.e. a concrete adaptable will also be injected with all adapters that registered for super types of it.
+
This package contains [https://github.com/google/guice Google Guice]-based support for injecting adapters into an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]]. That is, if an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] implementation provides an [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Inject.html @Inject]-annotated method with a single Map<AdapterKey<?>, Object> parameter, which is annotated with a respective inject annotation (@AdapterMap), and if corresponding adapter map-bindings targeting the [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] implementation are provided within a Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module], adapter instances can automatically be injected into instances of the [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]]. It needs to be pointed out that respective adapter map-bindings are evaluated polymorphically, i.e. a concrete adaptable will also be injected with all adapters that registered for super types of it.
  
 
=== AdapterMapInjectionSupport, AdaptableTypeListener, AdapterMapInjector ===
 
=== AdapterMapInjectionSupport, AdaptableTypeListener, AdapterMapInjector ===
To enable injection of adapters to IAdaptables, a specific [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/spi/TypeListener.html TypeListener] (AdaptableTypeListener) needs to be registered in the Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module]. To ensure this is done properly, a respective support [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module] is provided, namely AdapterMapInjectionSupport, which can easily be integrated into a custom [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module] as follows:
+
To enable injection of adapters to an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]], a specific [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/spi/TypeListener.html TypeListener] (AdaptableTypeListener) needs to be registered in the Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module]. To ensure this is done properly, a respective support [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module] is provided, namely AdapterMapInjectionSupport, which can easily be integrated into a custom [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module] as follows:
  
 
<source lang="java">
 
<source lang="java">
Line 141: Line 141:
  
  
This will ensure that the AdaptableTypeListener is properly registered (and itself injected). The AdaptableTypeListener will register a dedicated [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/MembersInjector.html MembersInjector] (AdapterMapInjector) on all suitable IAdaptable implementations it encounters.
+
This will ensure that the [[GEF/GEF4/Common#AdapterMapInjectionSupport, AdaptableTypeListener, AdapterMapInjector | AdaptableTypeListener]] is properly registered (and itself injected). The [[GEF/GEF4/Common#AdapterMapInjectionSupport, AdaptableTypeListener, AdapterMapInjector | AdaptableTypeListener]] will register a dedicated [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/MembersInjector.html MembersInjector] ([[GEF/GEF4/Common#AdapterMapInjectionSupport, AdaptableTypeListener, AdapterMapInjector | AdapterMapInjector]]) on all suitable [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] implementations it encounters.
  
 
=== AdapterMap, AdapterMaps ===
 
=== AdapterMap, AdapterMaps ===
The @AdapterMap annotation is used in two ways. First, it is used to specify respective adapter map-bindings within the Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module]. Second, it is used to specify the injection point, i.e. the method within the [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] implementation that should be injected with adapters.
+
The [[GEF/GEF4/Common#AdapterMap, AdapterMaps | @AdapterMap]] annotation is used in two ways. First, it is used to mark the injection point, i.e. the parameter of the method within the [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] implementation that is to be injected. Second, it is used to specify respective adapter map-bindings within the Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module].  
  
Specifying the injection point within a respective IAdaptable implementation is achieved by means of a method, which is marked for injection by means of an [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Inject.html @Inject] annotation, and furthermore provides a single Map<AdapterKey<?>, Object> parameter that is annotated with @AdapterMap as follows:
+
Specifying the injection point within a respective [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] implementation is achieved by means of a method, which is marked for injection by means of an [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Inject.html @Inject] annotation, and furthermore provides a single Map<AdapterKey<?>, Object> parameter that is annotated with [[GEF/GEF4/Common#AdapterMap, AdapterMaps | @AdapterMap]] as follows:
  
 
<source lang="java">
 
<source lang="java">
Line 186: Line 186:
  
  
When adapter map injection is properly enabled in the [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module], all suitable IAdaptable instances that are created through an [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Injector.html Injector] will be injected. To this extend, the @AdapterMap bindings can be compared to the Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/name/Named.html @Named] bindings, only that a 'Class' instead of a 'String' key is used. However, @AdapterMap bindings are more powerful, as they are evaluated polymorphically. That is, if an adapter map binding is specified for a specific [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] type, let's say 'A', it will be evaluated for instances of all subtypes of 'A' as well, as long as they are suitable for injection (i.e. they directly or via inheritance provide a respective method for adapter map injection). This is a very powerful mechanism that is used intensively by the [[GEF/GEF4/MVC | GEF4 MVC]] component. It allows to register certain adapters already for some abstract base type, so that each concrete sub-type will be injected with a respective adapter instance.
+
When adapter map injection is properly enabled in the [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module], all suitable [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] instances that are created through an [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Injector.html Injector], which is aware of the respective [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Module.html Module], will be injected.  
 +
 
 +
To this extend, the [[GEF/GEF4/Common#AdapterMap, AdapterMaps | @AdapterMap]]-bindings can be compared to the Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/name/Named.html @Named] bindings, only that a [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/Class.html Class] instead of a [http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/String.html String] key is used. However, [[GEF/GEF4/Common#AdapterMap, AdapterMaps | @AdapterMap]]-bindings are more powerful, as they are evaluated polymorphically. That is, if an binding is specified for a specific [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]], let's say 'A', it will be evaluated for instances of all subtypes of 'A' as well, as long as they are suitable for injection (i.e. they directly or via inheritance provide a respective method for adapter map injection). This is a very powerful mechanism that is used intensively by the [[GEF/GEF4/MVC | GEF4 MVC]] component. It allows to register certain adapters already for some abstract base type, so that each concrete sub-type will be injected with a respective adapter instance.
  
 
=== AdaptableScope, AdaptableScopes ===
 
=== AdaptableScope, AdaptableScopes ===
Line 194: Line 196:
  
 
=== AdaptableScope ===  
 
=== AdaptableScope ===  
An AdaptableScope is a Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Scope.html Scope] that is bound to an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] instance. It can be used to scope the adapter instances injected through adapter map injection. To enable this, the respective adapter map bindings have to be 'scoped' and the scope has to be entered for the respective IAdaptables before injection of adapters is triggered.
+
An [[GEF/GEF4/Common#AdaptableScope | AdaptableScope]] is a Guice [http://google.github.io/guice/api-docs/3.0/javadoc/com/google/inject/Scope.html Scope] that is bound to an [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] instance. It can be used to scope the adapter instances injected through [[GEF/GEF4/Common#AdapterMap, AdapterMaps | @AdapterMap]]-injection. To enable this, the respective adapter map bindings have to be 'scoped' and the scope has to be entered for the respective [[GEF/GEF4/Common#IAdaptable, AdapterKey | IAdaptable]] instance before injection of adapters is triggered.
 +
 
 +
 
  
 
== Notify  ==
 
== Notify  ==

Revision as of 03:57, 11 May 2015

Note to non-wiki readers: This documentation is generated from the Eclipse wiki - if you have corrections or additions it would be awesome if you added them in the original wiki page.


Introduction

The GEF4 Common component provides key concepts and infrastructure to be potentially used by all other GEF4 components.

Activate

  • package: org.eclipse.gef4.common.activate

IActivatable

ActivatableSupport

GEF4-Common-activate.png

Adapt

  • package: org.eclipse.gef4.common.adapt

GEF4-Common-adapt.png

The adapt package provides a modernized interpretation of the Eclipse Core Runtime's IAdaptable, providing the following enhancements:

  1. Adapters may be registered and retrieved by means of a TypeToken key as an alternative to a Class key, which ensures that adapters with parameterized types may also be registered and retrieved in a type-safe manner, not only via their raw type. For instance, an adapter instance a1 of parameterized type A<T1> and an instance a2 of type A<T2> can both be registered at an IAdaptable. The GEF/GEF4/MVC GEF4 MVC component makes use of this intensively, when registering providers, i.e. a Provider<IGeometry> and a Provider<IFXAnchor> can both be registered at an IVisualPart simultaneously.
  2. Adapters may (optionally) be registered and retrieved by providing an additional role key, which allows to register multiple adapters of the same type (using different roles) at an IAdaptable. For instance, adapter instances a1 and a2 of type A can both be registered at an adaptable using different roles. The GEF/GEF4/MVC GEF4 MVC component again makes use of this, when registering providers. Different geometry providers (Provider<IGeometry>) are e.g. registered for selection and hover feedback, by registering respective providers with respective roles.
  3. Adapters may request a back-reference to the respective IAdaptable they get registered at, by implementing a respective back-interface ( IAdaptable.Bound). Again, this is intensively used within GEF/GEF4/MVC GEF4 MVC, where an IBehavior or IPolicy for instance needs to be aware of the host IVisualPart it is registered at.
  4. IAdaptable provides support for registering property change listeners, to be notified whenever adapters are registered or unregistered.

Besides the IAdaptable, IAdaptable.Bound, and AdapterKey abstractions that formalize the modernized adaptable pattern, the package also provides a supporting class ( AdaptableSupport) to implement IAdaptable in compliance with its contract, as well as a standalone implementation ( AdapterStore).

IAdaptable, AdapterKey

An IAdaptable provides facilities to register and retrieve adapters via an AdapterKey, which combines a type key (Class or TypeToken) with an (optional) String role. Having the option to use a TypeToken instead of a simple Class key, enables the type-safe registration of adapters with parameterized types. The combination with an additional (optional) role enables that multiple adapters of the same type may be registered at an IAdaptable.

The 'traditional' getAdapter(Class<? super T>) method provided by the Eclipse Core Runtime IAdaptable here is a mere convenience operation that will retrieve the single adapter registered with the respective Class key and the default role (or the only adapter registered under the given Class key, if there is only one adapter for that type key).

An adapter can thus now be registered and retrieved in various ways:

  // register and retrieve adapter 'a' of raw type 'A' under 'default' role (traditional adaptable objects pattern).
  adaptable.setAdapter(A.class, a); 
  A a = adaptable.getAdapter(A.class);
 
  // register and retrieve adapter 'a' of parameterized type 'A<T>' under 'default' role
  adaptable.setAdapter(new TypeToken<A<T>>(){}, a);
  A<T> a = adaptable.getAdapter(new TypeToken<A<T>>(){});
 
  // register and retrieve adapter 'a' of raw type 'A' under role 'a1'
  adaptable.setAdapter(AdapterKey.get(A.class, "a1"));
  A a = adaptable.getAdapter(AdapterKey.get(A.class));
 
  // register and retrieve adapter 'a' of parameterized type 'A<T>' under role 'a1'
  adaptable.setAdapter(AdapterKey.get(new TypeToken<A<T>>(){}, "a1"));
  A a = adaptable.getAdapter(AdapterKey.get(new TypeToken<A<T>>(){}, "a1"));


To formalize support for notifying listeners about registration and unregistration of adapters, IAdaptable furthermore extends IPropertyChangeNotifier, which provides capabilities for registering and unregistering respective listeners.

IAdaptable.Bound

To formalize that an adapter may need to obtain a back reference to an IAdaptable, the IAdaptable.Bound interface was introduced. If an adapter implements this interface, the adaptable at which the adapter is registered is responsible of providing a back reference to the adapter as follows:

public class MyAdaptable implements IAdaptable {
 
  public <T> void setAdapter(AdapterKey<? super T> key, T adapter) {
    ...
    if (adapter instanceof IAdaptable.Bound) {
      ((IAdaptable.Bound<A>) adapter).setAdaptable(this);
    ...
  }
 
  public <T> T unsetAdapter(AdapterKey<? super T> key) {
    ...
    if (adapter instanceof IAdaptable.Bound) {
      ((IAdaptable.Bound<A>) adapter).setAdaptable(null);
    }
    ...
  }
}

AdaptableSupport

To enforce that implementers of IAdaptable properly follow the above outlined contract, the package furthermore provides an AdaptableSupport class, which does not formally implement the IAdaptable interface but provides implementations for all its methods and can thus be simply used as a delegate, as follows:

public class MyAdaptable implements IAdaptable {
 
  // create delegates
  private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
  private AdaptableSupport<MyAdaptable> ads = new AdaptableSupport<MyAdaptable>(this, pcs);
 
  public <T> T getAdapter(AdapterKey<? super T> key){
    return ads.getAdapter(key);
  }
 
  ...
}


It needs to be provided with a PropertyChangeSupport, which will be used to notify listeners about registration and unregistration of adapters. In case the IAdaptable, by which it is used as a delegate, is also IActivatable, it will ensure that all IActivatable adapters are properly activated/deactivated when being registered/unregistered dependent on the active state of the adaptable at that moment.

AdapterStore

The package furthermore provides an AdaptableStore, which can be used as a standalone IAdaptable.

Dispose

  • package: org.eclipse.gef4.common.dispose

GEF4-Common-dispose.png

Inject

  • package: org.eclipse.gef4.common.inject

GEF4-Common-inject-adaptermap.png

This package contains Google Guice-based support for injecting adapters into an IAdaptable. That is, if an IAdaptable implementation provides an @Inject-annotated method with a single Map<AdapterKey<?>, Object> parameter, which is annotated with a respective inject annotation (@AdapterMap), and if corresponding adapter map-bindings targeting the IAdaptable implementation are provided within a Guice Module, adapter instances can automatically be injected into instances of the IAdaptable. It needs to be pointed out that respective adapter map-bindings are evaluated polymorphically, i.e. a concrete adaptable will also be injected with all adapters that registered for super types of it.

AdapterMapInjectionSupport, AdaptableTypeListener, AdapterMapInjector

To enable injection of adapters to an IAdaptable, a specific TypeListener (AdaptableTypeListener) needs to be registered in the Guice Module. To ensure this is done properly, a respective support Module is provided, namely AdapterMapInjectionSupport, which can easily be integrated into a custom Module as follows:

public class MyModule extends AbstractModule {
 
  @Override
  protected void configure() {
    // register adapter map injection support
    install(new AdapterMapInjectionSupport());
 
    ...
  }
}


This will ensure that the AdaptableTypeListener is properly registered (and itself injected). The AdaptableTypeListener will register a dedicated MembersInjector ( AdapterMapInjector) on all suitable IAdaptable implementations it encounters.

AdapterMap, AdapterMaps

The @AdapterMap annotation is used in two ways. First, it is used to mark the injection point, i.e. the parameter of the method within the IAdaptable implementation that is to be injected. Second, it is used to specify respective adapter map-bindings within the Guice Module.

Specifying the injection point within a respective IAdaptable implementation is achieved by means of a method, which is marked for injection by means of an @Inject annotation, and furthermore provides a single Map<AdapterKey<?>, Object> parameter that is annotated with @AdapterMap as follows:

public class MyAdaptable implements IAdaptable {
 
  @Inject(optional = true)
  public void setAdapters(@AdapterMap Map<AdapterKey<?>, Object> adaptersWithKeys) {
    ...
  }
}


Specifying the to be injected adapters is performed by means of map-bindings in the Module.

public class MyModule extends AbstractModule {
 
  @Override
  protected void configure() {
    ...
 
    // obtain a map binder to bind adapters for the respective IAdaptable type.
    MapBinder<AdapterKey<?>, Object> adapterMapBinder = AdapterMaps.getAdapterMapBinder(binder(), MyAdaptable.class);
 
   // add adapter (map) binding for binding adapter 'a' of raw type 'A' to each MyAdaptable instance
   adapterMapBinder.addBinding(AdapterKey.get(A.class)).toInstance(a);
 
  // add adapter (map) binding for binding an instance of raw type 'A' to each MyAdaptable instance
   adapterMapBinder.addBinding(AdapterKey.get(A.class)).to(A.class);
 
   // add adapter (map) binding for binding adapter 'a' with parameterized type 'A<T>' to each MyAdaptable instance
   adapterMapBinder.addBinding(AdapterKey.get(new TypeToken<A<T>>(){})).toInstance(a); 
 
   ...
  }
}


When adapter map injection is properly enabled in the Module, all suitable IAdaptable instances that are created through an Injector, which is aware of the respective Module, will be injected.

To this extend, the @AdapterMap-bindings can be compared to the Guice @Named bindings, only that a Class instead of a String key is used. However, @AdapterMap-bindings are more powerful, as they are evaluated polymorphically. That is, if an binding is specified for a specific IAdaptable, let's say 'A', it will be evaluated for instances of all subtypes of 'A' as well, as long as they are suitable for injection (i.e. they directly or via inheritance provide a respective method for adapter map injection). This is a very powerful mechanism that is used intensively by the GEF4 MVC component. It allows to register certain adapters already for some abstract base type, so that each concrete sub-type will be injected with a respective adapter instance.

AdaptableScope, AdaptableScopes

In addition to basic injection support for adapters, the package also provides support for scoping the to be injected adapter instances by means of a dedicated Guice Scope ( AdaptableScope).

GEF4-Common-inject-adaptablescopes.png

AdaptableScope

An AdaptableScope is a Guice Scope that is bound to an IAdaptable instance. It can be used to scope the adapter instances injected through @AdapterMap-injection. To enable this, the respective adapter map bindings have to be 'scoped' and the scope has to be entered for the respective IAdaptable instance before injection of adapters is triggered.


Notify

  • package: org.eclipse.gef4.common.notify

GEF4-Common-notify.png

Properties

  • package: org.eclipse.gef4.common.properties

GEF4-Common-properties.png

IPropertyChangeNotifier

Reflect

  • package: org.eclipse.gef4.common.reflect

GEF4-Common-reflect.png

Back to the top