Element factories
Element factories are used to recreate workbench model objects from data that was saved during workbench shutdown.
Before we look closely at the element factory extension, we need to review a general technique
that is used throughout the platform to add plug-in specific behavior to common platform model objects.
When browsing the various workbench classes, you will notice that many of the workbench interfaces extend the
IAdaptable
interface.
Plug-ins use adapters to add specific behavior to pre-existing types in the system. For example, the workbench may want
resources to answer a label and an image for display purposes. We know that it's not good design to add UI specific
behavior to low-level objects, so how can we add this behavior to the resource types?
Plug-ins can register adapters that add behavior to pre-existing types.
Application code can then query an object for a particular adapter. If there is one registered for it,
the application can obtain the adapter and use the new behaviors defined in the adapter.
By providing a facility to dynamically query an adapter for an object, we can improve the flexibility of the system
as it evolves. New adapters can be registered for platform types by new plug-ins without having to change the
definitions of the original types. The pattern to ask an object for a particular
adapter is as follows:
//given an object o, we want to do "workbench" things with it.
if (!(o instanceof IAdaptable)) {
return null;
}
IWorkbenchAdapter adapter = (IWorkbenchAdapter)o.getAdapter(IWorkbenchAdapter.class);
if (adapter == null)
return null;
// now I can treat o as an IWorkbenchAdapter
...
If there is no adapter registered for the object in hand, null will be returned as the adapter. Clients must be
prepared to handle this case. There may be times when an expected adapter has not been registered.
The workbench uses adapters to obtain UI information from the base platform types, such as
IResource
.
Adapters shield the base types from UI-specific knowledge and allow the workbench to evolve its interfaces
without changing the definitions of the base.
Without adapters, any class that might be passed around in the workbench API would have to implement the UI
interfaces, which would increase the number of class definitions, introduces tight
coupling, and create circular dependencies between the core and UI classes. With adapters, each class implements
IAdaptable
and uses the adapter registry to allow plug-ins to extend the behavior of the base types.
Throughout the workbench code, you'll see cases where a platform core type is queried for an adapter.
The query is used to obtain an object that knows how to answer UI oriented information about
the type.
Element factories
When the workbench is shut down by the user, it must save the current state of the
IAdaptable
objects that are shown in the workbench. An object's state is stored by saving
the primitive data parameters of the object in a special format, an
IMemento. The id of a factory that can recreate
the object from an
IMemento
is also stored and the data is saved in the file system.
When the platform is restarted, the workbench finds the element factory associated with the
IMemento's
factory id. It finds the factory by checking the plug-in registry for contributions to the
org.eclipse.ui.elementFactories
extension.
The markup is pretty simple. We just have to specify the id of the factory and the corresponding class that
implements the factory.
The following code snippet is from the workbench plugin.xml.
<extension
point="org.eclipse.ui.elementFactories">
<factory
class="org.eclipse.ui.internal.model.ResourceFactory"
id="org.eclipse.ui.internal.model.ResourceFactory">
</factory>
<factory
class="org.eclipse.ui.internal.model.WorkspaceFactory"
id="org.eclipse.ui.internal.model.WorkspaceFactory">
</factory>
<factory
class="org.eclipse.ui.part.FileEditorInputFactory"
id="org.eclipse.ui.part.FileEditorInputFactory">
</factory>
<factory
class="org.eclipse.ui.internal.dialogs.WelcomeEditorInputFactory"
id="org.eclipse.ui.internal.dialogs.WelcomeEditorInputFactory">
</factory>
<factory
class="org.eclipse.ui.internal.WorkingSetFactory"
id="org.eclipse.ui.internal.WorkingSetFactory">
</factory>
</extension>