package org.activiti.designer.features;
import org.eclipse.bpmn2.FlowElement;
import org.eclipse.bpmn2.FlowNode;
import org.eclipse.bpmn2.SequenceFlow;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.IReason;
import org.eclipse.graphiti.features.context.IUpdateContext;
import org.eclipse.graphiti.features.impl.AbstractUpdateFeature;
import org.eclipse.graphiti.features.impl.Reason;
import org.eclipse.graphiti.mm.pictograms.Connection;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
/**
* Provides update feature that updates the business model for connections if
* the graphical model points to a different source or target object than the
* corresponding flow in the business model. This is an unfortunate necessity
* because for some reason, relinking the connector doesn't trigger a business
* model update (probably a bug in Graphiti or the way it's used). Assuming this
* will be fixed within the Graphiti framework in a later version, this is
* marked as deprecated for later deletion.
*
* @author Tiese Barrell
* @since 0.5.0
* @version 1
*
*/
@Deprecated
public class UpdateConnectionFlowElementFeature extends AbstractUpdateFeature {
private SyncObjects syncObjects;
public UpdateConnectionFlowElementFeature(IFeatureProvider fp) {
super(fp);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.graphiti.func.IUpdate#canUpdate(org.eclipse.graphiti.features
* .context.IUpdateContext)
*/
public boolean canUpdate(IUpdateContext context) {
// return true, if linked business object is an SequenceFlow
Object bo = getBusinessObjectForPictogramElement(context.getPictogramElement());
return (bo instanceof SequenceFlow);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.graphiti.func.IUpdate#updateNeeded(org.eclipse.graphiti.features
* .context.IUpdateContext)
*/
public IReason updateNeeded(IUpdateContext context) {
final PictogramElement pictogramElement = context.getPictogramElement();
final Object bo = getBusinessObjectForPictogramElement(pictogramElement);
this.syncObjects = new SyncObjects(context);
//TODO: reinstate this block, but only for updateable connectors to automatically update if needed so the user is not required to do this manually
// possibly, #update() should be expanded to detect duplicate updates if the user still forces it and updating is no longer required. This depends on the lifecycle of this
//instance and would entail creating a force override of the #isOutOfSync() method's result to reflect having been manually updated.
// if (bo instanceof SequenceFlow && isOutOfSync(context)) {
// // manually force an update
// // FIXME: need transaction that's writable
// TransactionalEditingDomain editingDomain = getDiagramEditor().getEditingDomain();
// CommandExec.getSingleton().executeFeatureWithContext(this, context);
// }
//FIXME: this is far from perfect, but limits red dashed connectors to updateable connectors only
if (isOutOfSync(context)) {
return Reason.createTrueReason("This sequence flow requires updating because the source and \ndestination nodes have changed since the diagram was last saved. \n\nUse right-click > Update to update the sequence flow");
}
return Reason.createFalseReason();
}
public boolean update(IUpdateContext context) {
this.syncObjects = new SyncObjects(context);
return this.syncObjects.update();
}
private boolean isOutOfSync(final IUpdateContext context) {
return this.syncObjects.isOutOfSync();
}
private class SyncObjects {
private String graphicalStartId;
private String graphicalEndId;
private String businessStartId;
private String businessEndId;
private FlowElement targetStartObject;
private FlowElement targetEndObject;
private SequenceFlow businessModelObjectToUpdate;
private final IUpdateContext context;
public SyncObjects(final IUpdateContext context) {
this.context = context;
setup();
}
private void setup() {
final PictogramElement pictogramElement = context.getPictogramElement();
final Object bo = getBusinessObjectForPictogramElement(pictogramElement);
if (pictogramElement instanceof Connection) {
final Connection anchor = (Connection) pictogramElement;
final Object startPE = getBusinessObjectForPictogramElement(anchor.getStart().getParent().getLink()
.getPictogramElement());
if (startPE instanceof FlowElement) {
targetStartObject = (FlowElement) startPE;
graphicalStartId = targetStartObject.getId();
}
final Object endPE = getBusinessObjectForPictogramElement(anchor.getEnd().getParent().getLink()
.getPictogramElement());
if (endPE instanceof FlowElement) {
targetEndObject = (FlowElement) endPE;
graphicalEndId = targetEndObject.getId();
}
businessModelObjectToUpdate = ((SequenceFlow) bo);
businessStartId = businessModelObjectToUpdate.getSourceRef().getId();
businessEndId = businessModelObjectToUpdate.getTargetRef().getId();
}
}
public boolean isOutOfSync() {
if (!graphicalStartId.equals(businessStartId) || !graphicalEndId.equals(businessEndId)) {
return true;
}
return false;
}
public boolean update() {
if (isOutOfSync()) {
System.out
.println(String
.format("Updating because the pictogram elements point from %s to %s and the business objects point from %s to %s",
graphicalStartId, graphicalEndId, businessStartId, businessEndId));
businessModelObjectToUpdate.setSourceRef((FlowNode) targetStartObject);
businessModelObjectToUpdate.setTargetRef((FlowNode) targetEndObject);
return true;
}
return false;
}
}
}