EMF is a very powerful framework and with power comes…responsibility. You can achieve great things with a minimum of effort using EMF, but if something goes wrong, you can also spend hours trying to find out why. This blog post is part of a series on things you should do and things you should not do when using EMF. You can use the link to the series pilot to navigate to the start and the link below to navigate to the next blog once it is published.
EMF Dos #9: Use EMF ItemProviders
To display entities in a tree view or in other views, you need a label provider and a content provider. The label provider provides an icon and a text to display each entity type. The content provider defines the children of an entity. Additionally, the label and content providers need to notify their viewers if the label or content changes due to data changes. The viewers will update only if there are data changes. You could implement the label and content providers manually, which is a lot of work, or you can rely on EMF-generated infrastructure.
For every entity defined in your Ecore, EMF will generate an ItemProvider in the Edit-Plugin. The ItemProvider implements methods to get an icon and a text for the entity (getText() and getImage()). Since you want to display all kinds of entities in a tree view, you need to create a label provider that will know the type of your entity and use the matching ItemProvider to retrieve a text and an icon. This label provider needs to implement the ILabelProvider interface. Similarly, a content provider would have to implement the ITreeContentProvider interface and define the children for all the different kinds of entities. For this purpose, EMF provides a fully functional label and content providers: AdapterFactoryLabelProvider and AdapterFactoryContentProvider. They both work in the same way, so I will focus on the AdapterFactoryLabelProvider.
Conceptually, an AdapterFactoryLabelProvider is able to provide labels for all supported entities by delegating to the appropriate generated ItemProviders. Technically, the AdapterFactoryLabelProvider requires an AdapterFactory to do this (see the constructor). An AdapterFactory creates adapters (wrappers) for a given entity. For each EMF model, EMF generates an AdapterFactory for the ItemProviders of its entities. Basically, the adapt() method of the AdapterFactory returns the appropriate ItemProvider for a specific entity.
To construct an AdapterFactoryLabelProvider, you can pass in the AdapterFactory of your model, and the label provider will be able to display your entities based on their ItemProviders.
If you want to display entities from multiple models you can use a ComposedAdapterFactory, which I will describe in my next blog.
The AdapterFactoryLabelProvider will — with the help of the ItemProviders — update its viewers if any of the entities it provided a label for change. Furthermore, the AdapterFactoryLabelProvider is very loosely coupled to the ItemProviders that implement entity-specific display behaviour.
Since the ItemProviders are generated (but can be adapted if necessary), the AdapterFactoryLabelProvider and AdapterFactoryContentProvider really are a big productivity boost in displaying EMF-based entities in your viewers.
Stay tuned for more Dos and Don´ts in my next blog!