# Providing Update Functionality

## Strategies for Update

As described in the chapter “providing add functionality” the values of the business objects (e.g. the EClass name) are stored in the graphics algorithm of the pictogram elements. But this is done only once. If the business model changes the example diagram does not realize the changes.

For that purpose we need an update feature which is used by the diagram to react on business model changes.

The behavior of the update is straight forward, when the user is changing the domain model directly via the diagram. For example if the user changes a text in the diagram using direct-editing or the property-sheet, then this text should be changed in the diagram immediately.

However, if the domain-model is changed outside the diagram (e.g. in a separate editor or viewer, maybe even by another user), then it is questionable, if the diagram should be updated immediately. Often an immediate update would destroy a previously good layout or hide previously important information. Therefore Graphiti supports two update-strategies:

1. If the automatic update is active, then a change in the business model will immediately update the diagram.
2. If the automatic update is inactive, then a change in the business model will only mark the changed diagram shapes as outdated. The user can then manually update the outdated shapes.

Figure: Shape marked as outdated (tooltip shows reason)

Figure: Outdated shape can be updated manually

By default the automatic update is inactive, but this can be configured by overwriting the following methods in the IDiagramTypeProvider:

- If isAutoUpdateAtStartup returns true, then the diagram will be updated, when it is initially opened in the graphical editor or viewr. This will make the tool dirty.
- If isAutoUpdateAtRuntime returns true, then the diagram will be updated, when it is already open in the graphical editor or viewer, but only if the tool is already dirty.
- If isAutoUpdateAtReset returns true, then the diagram will be updated, if the tool is already dirty and the user chooses to discard his changes (reset the diagram), when a change from outside the diagram occurs.

## Creating an Update Feature

An update feature has to implement the interface IUpdateFeature. Instead of implementing it directly it should extend one of the available base classes. In this example we extend the base class AbstractUpdateFeature

In this case we have to implement/overwrite 3 methods:

- The method canUpdate has to check whether the values of the current pictogram element of the given context can be updated.
- The method update has to update this pictogram element. It has to copy the latest values from the business objects to the graphics algorithm of this pictogram element.
- The method updateNeeded has to check whether the values in the pictogram element are up to date, that means whether the graphics algorithm of this pictogram element contain the latest values from the business objects.

Hint: An update feature can and should also be used (called) if any functionality of the editor or viewer (e.g. any custom feature) modifies parts of the domain model. This works just like the model view controller pattern.

In this example we want to update the EClass name. You can see the complete implementation of the update feature here:

package org.eclipse.graphiti.examples.tutorial.features;
public class TutorialUpdateEClassFeature extends AbstractUpdateFeature {
public TutorialUpdateEClassFeature(IFeatureProvider fp) {
super(fp);
}
public boolean canUpdate(IUpdateContext context) {
// return true, if linked business object is a EClass
Object bo =
getBusinessObjectForPictogramElement(context.getPictogramElement());
return (bo instanceof EClass);
}
public IReason updateNeeded(IUpdateContext context) {
// retrieve name from pictogram model
String pictogramName = null;
PictogramElement pictogramElement = context.getPictogramElement();
if (pictogramElement instanceof ContainerShape) {
ContainerShape cs = (ContainerShape) pictogramElement;
for (Shape shape : cs.getChildren()) {
if (shape.getGraphicsAlgorithm() instanceof Text) {
Text text = (Text) shape.getGraphicsAlgorithm();
pictogramName = text.getValue();
}
}
}
// retrieve name from business model
String businessName = null;
Object bo = getBusinessObjectForPictogramElement(pictogramElement);
if (bo instanceof EClass) {
EClass eClass = (EClass) bo;
businessName = eClass.getName();
}
// update needed, if names are different
boolean updateNameNeeded =
((pictogramName == null && businessName != null) ||
(pictogramName != null && !pictogramName.equals(businessName)));
if (updateNameNeeded) {
return Reason.createTrueReason("Name is out of date");
} else {
return Reason.createFalseReason();
}
}
public boolean update(IUpdateContext context) {
// retrieve name from business model
String businessName = null;
PictogramElement pictogramElement = context.getPictogramElement();
Object bo = getBusinessObjectForPictogramElement(pictogramElement);
if (bo instanceof EClass) {
EClass eClass = (EClass) bo;
businessName = eClass.getName();
}
// Set name in pictogram model
if (pictogramElement instanceof ContainerShape) {
ContainerShape cs = (ContainerShape) pictogramElement;
for (Shape shape : cs.getChildren()) {
if (shape.getGraphicsAlgorithm() instanceof Text) {
Text text = (Text) shape.getGraphicsAlgorithm();
text.setValue(businessName);
return true;
}
}
}
return false;
}
}

Additionally the feature provider has to deliver our newly created feature (overwrite the method getUpdateFeature).

This implementation can be seen here:

@Override
public IUpdateFeature getUpdateFeature(IUpdateContext context) {
PictogramElement pictogramElement = context.getPictogramElement();
if (pictogramElement instanceof ContainerShape) {
Object bo = getBusinessObjectForPictogramElement(pictogramElement);
if (bo instanceof EClass) {
return new TutorialUpdateEClassFeature(this);
}
}
return super.getUpdateFeature(context);
}

## Test: Update a EClass Name

Note: if the Graphiti project wizard for a "New Graphiti Sample Project" does not work correctly and you can not test the update feature as described below, please continue with the next chapters and provide custom functionality to rename a EClass. That will allow testing the update feature by changing the same EClass in two different diagrams.

Now start the editor again and test it:

1. create new diagram
2. create a EClass "A"
3. save current diagram
4. move this new EClass to make the diagram editor dirty
5. go to the Project Explorer
6. find the new EClass under "EClasses"
7. rename this EClass via context menu to "B"
8. when you activate the editor, you will receive a popup, choose yes and you will get the updated EClass (since isAutoUpdateAtReset is set to true by default)
9. save current diagram
10. close the editor
11. go to the Project Explorer
12. rename this EClass via context menu to "C"
13. reopen the diagram editor
14. the diagram will not be updated automatically, instead the editor visualizes dirty states, when the editor is activated (since isAutoUpdateAtStartup is set to false by default)
15. move mouse on dirty EClass shape and hit appearing update button. The name "C" should appear.