Friday, May 7, 2010

Eclipse Modelling Best Practies

1. We should have a single in-memory instance of the working model of an emf resource .
* It should be the a single point contact for managing the lifecycle and behavior of the emf model.

* It should contain the corresponding editing domain, reference to the file resource and the global resource set.

* It should maintain a single copy of the domain model in the memory.
getModel(IResource resource):EObject

* It should maintain the list of cross-references for the model in context
getReferences():List

* It should be a resource-change listener so that
* * it can unload the model and delete the emf resource when the file resource is deleted
* * it can modify the resource-uri when the file is moved / renamed
addListener(PropertyChangeListener propertyChangeListener)

* ModelProvider should also register all required ItemAdapterFactories and provide the composite adapter factory
getAdapterFactory() : AdapterFactory

* It should take care of saving the Resource, provide ResourceSaveable and check if the resource is dirty.

* Whenever the resource uri is changed then using EcoreUtil CrossReferencer ModelProvider should find out what all models should be refactored.

* It should be deleted (resource.delete()) whenever the file resource is deleted

* It should be reloaded when its dirty editor is closed without saving its changes.

2. Item Provider is the single-most powerful feature in EMF
* Implement content and label provider by using mixing interfaces through delegate pattern.
Public Object[] getchilren(Object object){
ITreeItemContentProvider adapter = (ITreeItemContentProvider)adapterFactory.adapt
(object, ITreeItemContentProvider.class);
return adpter.getChildren(object).toArray();
}
* adapt the model objects to implement whatever interfaces the editors and views need
* propagate the change-notifications to viewers
* act as command factory
* provide a property source for model objects

3.Effective usage of Common Command Fwk
* getResult() should be overridden to return relevant model objects so that
** result of one command can be input to another command
** getAffectedObjects() will give the affected model objects for which the the required diagram element or xml node or language statement or property section can be selected and highlighted.

4. How to synch up the WorkingModel with changes in file Resource ?
Lets assume WorkingModel has the methods addListener(PropertyChangeListener propertyChangeListener) and removeListener(PropertyChangeListener propertyChangeListener);

The Editor then is added as a propertyChangeListner for its workingModel
if (propertyChangeListner == null) {
propertyChangeListner = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (WorkingModel.PROP_DIRTY.equals(evt.getPropertyName())) {
editorDirtyStateChanged();
} else if (WorkingCopy.PROP_RELOADED.equals(evt.getPropertyName())) {
reloadModel(currentFile);
} else if (WorkingCopy.PROP_REMOVED.equals(evt.getPropertyName())) {
Object newLocation = evt.getNewValue();
if(newLocation == null) { // file deleted
removeWorkingModel();
close(false);
}else if (newLocation instanceof IPath) {
// file renamed
IFile newFile = ResourcesPlugin.getWorkspace().getRoot().getFile((IPath)
newLocation);
if (newFile != null && newFile.exists()) {
reloadModel(newFile);
} else {
close(false);
}
} else {
close(false);
}
}
}

protected void reloadModel(IFile newFile) {
try {
IDE.openEditor(getSite().getPage(), newFile);
} catch (PartInitException e) {
ErrorDialog.openError(getSite().getShell(),
"Error in editor initialization", null, e.getStatus());
}
close(false);
}

5. How to find References of an EObject ?
Collection referrers = EcoreUtil.UsageCrossReferencer.find(eo, eo.eResource());
iterate through the references : referer.getEObject()

6. Why Notification Listeners in EMF are also called Adapters ?
Apart from observing the changes in eObjects, they also help - extending the behavior i.e. support additional interfaces without subclassing - (Adapter pattern)

7. Attaching an adapter :
(i) Attaching an Adapter as Observer :
Adapter myEObjectObserver = // make an ui component
implement org.eclipse.emf.common.notify.Adapter
myEObject.eAdapters().add(myEObjectObserver);
myEObjectObserver will be notified whenever the eobject is modified
(ii) Attaching an Adapter as a Behaviour Extension :
MyEObject myEObject =
AdapterFactory myEObjectAdapterFactory =
if(myEObjectAdapterFactory.isFactoryType(myEObjectType)){
Adapter myEObjectObserver= myEObjectAdapterFactory.adapt(myEObject, myEObjectType);
.....
}

Stay Tuned .. to be continued ..

No comments: