/*******************************************************************************
* Copyright (c) 2011 Red Hat, Inc.
* All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.eclipse.bpmn2.modeler.ui.diagram;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.bpmn2.modeler.core.features.ConnectionFeatureContainer;
import org.eclipse.bpmn2.modeler.core.features.DefaultBpmnDeleteFeature;
import org.eclipse.bpmn2.modeler.core.features.FeatureContainer;
import org.eclipse.bpmn2.modeler.core.features.bendpoint.AddBendpointFeature;
import org.eclipse.bpmn2.modeler.core.features.bendpoint.MoveBendpointFeature;
import org.eclipse.bpmn2.modeler.core.features.bendpoint.RemoveBendpointFeature;
import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.AdHocSubProcessFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.CallActivityFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.SubProcessFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.TransactionFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.BusinessRuleTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.CustomTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.ManualTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.ReceiveTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.ScriptTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.SendTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.ServiceTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.TaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.activity.task.UserTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.artifact.GroupFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.artifact.TextAnnotationFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.choreography.CallChoreographyFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.choreography.ChoreographyMessageLinkFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.choreography.ChoreographyTaskFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.choreography.SubChoreographyFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.conversation.ConversationFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.conversation.ConversationLinkFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.data.DataInputFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.data.DataObjectFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.data.DataObjectReferenceFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.data.DataOutputFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.data.DataStoreReferenceFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.data.MessageFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.BoundaryEventFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.EndEventFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.IntermediateCatchEventFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.IntermediateThrowEventFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.StartEventFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.CancelEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.CompensateEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.ConditionalEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.ErrorEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.EscalationEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.LinkEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.MessageEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.SignalEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.TerminateEventDefinitionFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.event.definitions.TimerEventDefinitionContainer;
import org.eclipse.bpmn2.modeler.ui.features.flow.AssociationFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.flow.DataInputAssociationFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.flow.DataOutputAssociationFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.flow.MessageFlowFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.flow.SequenceFlowFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.gateway.ComplexGatewayFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.gateway.EventBasedGatewayFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.gateway.ExclusiveGatewayFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.gateway.InclusiveGatewayFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.gateway.ParallelGatewayFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.lane.LaneFeatureContainer;
import org.eclipse.bpmn2.modeler.ui.features.participant.ParticipantFeatureContainer;
import org.eclipse.graphiti.dt.IDiagramTypeProvider;
import org.eclipse.graphiti.features.IAddBendpointFeature;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.ICreateConnectionFeature;
import org.eclipse.graphiti.features.ICreateFeature;
import org.eclipse.graphiti.features.IDeleteFeature;
import org.eclipse.graphiti.features.IDirectEditingFeature;
import org.eclipse.graphiti.features.ILayoutFeature;
import org.eclipse.graphiti.features.IMoveBendpointFeature;
import org.eclipse.graphiti.features.IMoveShapeFeature;
import org.eclipse.graphiti.features.IReconnectionFeature;
import org.eclipse.graphiti.features.IRemoveBendpointFeature;
import org.eclipse.graphiti.features.IResizeShapeFeature;
import org.eclipse.graphiti.features.IUpdateFeature;
import org.eclipse.graphiti.features.context.IAddBendpointContext;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.IDeleteContext;
import org.eclipse.graphiti.features.context.IDirectEditingContext;
import org.eclipse.graphiti.features.context.ILayoutContext;
import org.eclipse.graphiti.features.context.IMoveBendpointContext;
import org.eclipse.graphiti.features.context.IMoveShapeContext;
import org.eclipse.graphiti.features.context.IReconnectionContext;
import org.eclipse.graphiti.features.context.IRemoveBendpointContext;
import org.eclipse.graphiti.features.context.IResizeShapeContext;
import org.eclipse.graphiti.features.context.IUpdateContext;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.ui.features.DefaultFeatureProvider;
/**
* Determines what kinds of business objects can be added to a diagram.
*
* @author imeikas
*
*/
public class BPMNFeatureProvider extends DefaultFeatureProvider {
private List<FeatureContainer> containers;
private ICreateFeature[] createFeatures;
private ICreateConnectionFeature[] createConnectionFeatures;
public BPMNFeatureProvider(IDiagramTypeProvider dtp) {
super(dtp);
containers = new ArrayList<FeatureContainer>();
containers.add(new GroupFeatureContainer());
containers.add(new DataObjectFeatureContainer());
containers.add(new DataObjectReferenceFeatureContainer());
containers.add(new DataStoreReferenceFeatureContainer());
containers.add(new DataInputFeatureContainer());
containers.add(new DataOutputFeatureContainer());
containers.add(new MessageFeatureContainer());
containers.add(new StartEventFeatureContainer());
containers.add(new EndEventFeatureContainer());
containers.add(new IntermediateCatchEventFeatureContainer());
containers.add(new IntermediateThrowEventFeatureContainer());
containers.add(new BoundaryEventFeatureContainer());
containers.add(new TaskFeatureContainer());
containers.add(new ScriptTaskFeatureContainer());
containers.add(new ServiceTaskFeatureContainer());
containers.add(new UserTaskFeatureContainer());
containers.add(new ManualTaskFeatureContainer());
containers.add(new BusinessRuleTaskFeatureContainer());
containers.add(new SendTaskFeatureContainer());
containers.add(new ReceiveTaskFeatureContainer());
containers.add(new ChoreographyTaskFeatureContainer());
containers.add(new ExclusiveGatewayFeatureContainer());
containers.add(new InclusiveGatewayFeatureContainer());
containers.add(new ParallelGatewayFeatureContainer());
containers.add(new EventBasedGatewayFeatureContainer());
containers.add(new ComplexGatewayFeatureContainer());
containers.add(new AdHocSubProcessFeatureContainer());
containers.add(new CallActivityFeatureContainer());
containers.add(new TransactionFeatureContainer());
containers.add(new SubProcessFeatureContainer());
containers.add(new ConditionalEventDefinitionContainer());
containers.add(new MessageEventDefinitionContainer());
containers.add(new TimerEventDefinitionContainer());
containers.add(new SignalEventDefinitionContainer());
containers.add(new EscalationEventDefinitionContainer());
containers.add(new CompensateEventDefinitionContainer());
containers.add(new LinkEventDefinitionContainer());
containers.add(new ErrorEventDefinitionContainer());
containers.add(new CancelEventDefinitionContainer());
containers.add(new TerminateEventDefinitionFeatureContainer());
containers.add(new SequenceFlowFeatureContainer());
containers.add(new MessageFlowFeatureContainer());
containers.add(new AssociationFeatureContainer());
containers.add(new ConversationFeatureContainer());
containers.add(new ConversationLinkFeatureContainer());
containers.add(new DataInputAssociationFeatureContainer());
containers.add(new DataOutputAssociationFeatureContainer());
containers.add(new SubChoreographyFeatureContainer());
containers.add(new CallChoreographyFeatureContainer());
containers.add(new ParticipantFeatureContainer());
containers.add(new LaneFeatureContainer());
containers.add(new TextAnnotationFeatureContainer());
containers.add(new ChoreographyMessageLinkFeatureContainer());
updateFeatureLists();
}
public void addFeatureContainer(FeatureContainer fc) throws Exception {
boolean canAdd = true;
if (fc instanceof CustomTaskFeatureContainer) {
CustomTaskFeatureContainer ctfc = (CustomTaskFeatureContainer)fc;
for (FeatureContainer container : containers) {
if (container instanceof CustomTaskFeatureContainer) {
// don't add duplicates
String oldId = ((CustomTaskFeatureContainer)container).getId();
String newId = ctfc.getId();
if (oldId!=null && newId!=null) {
if (oldId.equals(newId)) {
canAdd = false;
break;
}
}
else if (oldId==newId) {
canAdd = false;
break;
}
}
}
}
else {
for (FeatureContainer container : containers) {
if (container.getClass().isInstance(fc)) {
canAdd = false;
break;
}
}
}
if (canAdd) {
containers.add(fc);
updateFeatureLists();
}
else
throw new Exception("Attempt to add a Custom Feature with a duplicate ID "+fc.getClass().getName());
}
private void updateFeatureLists() {
List<ICreateFeature> createFeaturesList = new ArrayList<ICreateFeature>();
for (FeatureContainer container : containers) {
ICreateFeature createFeature = container.getCreateFeature(this);
if (createFeature != null) {
createFeaturesList.add(createFeature);
}
}
createFeatures = createFeaturesList.toArray(new ICreateFeature[createFeaturesList.size()]);
List<ICreateConnectionFeature> createConnectionFeatureList = new ArrayList<ICreateConnectionFeature>();
for (FeatureContainer c : containers) {
if (c instanceof ConnectionFeatureContainer) {
ConnectionFeatureContainer connectionFeatureContainer = (ConnectionFeatureContainer) c;
ICreateConnectionFeature createConnectionFeature = connectionFeatureContainer
.getCreateConnectionFeature(this);
if (createConnectionFeature == null) {
continue;
}
createConnectionFeatureList.add(createConnectionFeature);
}
}
createConnectionFeatures = createConnectionFeatureList
.toArray(new ICreateConnectionFeature[createConnectionFeatureList.size()]);
}
@Override
public IAddFeature getAddFeature(IAddContext context) {
Object id = CustomTaskFeatureContainer.getId(context);
for (FeatureContainer container : containers) {
if (id!=null && !(container instanceof CustomTaskFeatureContainer))
continue;
Object o = container.getApplyObject(context);
if (o != null && container.canApplyTo(o)) {
IAddFeature feature = container.getAddFeature(this);
if (feature == null) {
break;
}
return feature;
}
}
return super.getAddFeature(context);
}
@Override
public ICreateFeature[] getCreateFeatures() {
return createFeatures;
}
@Override
public IUpdateFeature getUpdateFeature(IUpdateContext context) {
Object id = CustomTaskFeatureContainer.getId(context);
for (FeatureContainer container : containers) {
if (id!=null && !(container instanceof CustomTaskFeatureContainer))
continue;
Object o = container.getApplyObject(context);
if (o != null && container.canApplyTo(o)) {
IUpdateFeature feature = container.getUpdateFeature(this);
if (feature == null) {
break;
}
return feature;
}
}
return super.getUpdateFeature(context);
}
@Override
public ICreateConnectionFeature[] getCreateConnectionFeatures() {
return createConnectionFeatures;
}
@Override
public IDirectEditingFeature getDirectEditingFeature(IDirectEditingContext context) {
Object id = CustomTaskFeatureContainer.getId(context);
for (FeatureContainer container : containers) {
if (id!=null && !(container instanceof CustomTaskFeatureContainer))
continue;
Object o = container.getApplyObject(context);
if (o != null && container.canApplyTo(o)) {
IDirectEditingFeature feature = container.getDirectEditingFeature(this);
if (feature == null) {
break;
}
return feature;
}
}
return super.getDirectEditingFeature(context);
}
@Override
public ILayoutFeature getLayoutFeature(ILayoutContext context) {
Object id = CustomTaskFeatureContainer.getId(context);
for (FeatureContainer container : containers) {
if (id!=null && !(container instanceof CustomTaskFeatureContainer))
continue;
Object o = container.getApplyObject(context);
if (o != null && container.canApplyTo(o)) {
ILayoutFeature feature = container.getLayoutFeature(this);
if (feature == null) {
break;
}
return feature;
}
}
return super.getLayoutFeature(context);
}
@Override
public IMoveShapeFeature getMoveShapeFeature(IMoveShapeContext context) {
Object id = CustomTaskFeatureContainer.getId(context);
for (FeatureContainer container : containers) {
if (id!=null && !(container instanceof CustomTaskFeatureContainer))
continue;
Object o = container.getApplyObject(context);
if (o != null && container.canApplyTo(o)) {
IMoveShapeFeature feature = container.getMoveFeature(this);
if (feature == null) {
break;
}
return feature;
}
}
return super.getMoveShapeFeature(context);
}
@Override
public IResizeShapeFeature getResizeShapeFeature(IResizeShapeContext context) {
Object id = CustomTaskFeatureContainer.getId(context);
for (FeatureContainer container : containers) {
if (id!=null && !(container instanceof CustomTaskFeatureContainer))
continue;
Object o = container.getApplyObject(context);
if (o != null && container.canApplyTo(o)) {
IResizeShapeFeature feature = container.getResizeFeature(this);
if (feature == null) {
break;
}
return feature;
}
}
return super.getResizeShapeFeature(context);
}
@Override
public IAddBendpointFeature getAddBendpointFeature(IAddBendpointContext context) {
return new AddBendpointFeature(this);
}
@Override
public IMoveBendpointFeature getMoveBendpointFeature(IMoveBendpointContext context) {
return new MoveBendpointFeature(this);
}
@Override
public IRemoveBendpointFeature getRemoveBendpointFeature(IRemoveBendpointContext context) {
return new RemoveBendpointFeature(this);
}
@Override
public IReconnectionFeature getReconnectionFeature(
IReconnectionContext context) {
for (FeatureContainer container : containers) {
Object o = container.getApplyObject(context);
if (o != null && container.canApplyTo(o) && container instanceof ConnectionFeatureContainer) {
IReconnectionFeature feature = ((ConnectionFeatureContainer)container).getReconnectionFeature(this);
if (feature == null) {
break;
}
return feature;
}
}
return super.getReconnectionFeature(context);
}
@Override
public IDeleteFeature getDeleteFeature(IDeleteContext context) {
Object id = CustomTaskFeatureContainer.getId(context);
for (FeatureContainer container : containers) {
if (id!=null && !(container instanceof CustomTaskFeatureContainer))
continue;
Object o = container.getApplyObject(context);
if (o != null && container.canApplyTo(o)) {
IDeleteFeature feature = container.getDeleteFeature(this);
if (feature != null) {
return feature;
}
}
}
return new DefaultBpmnDeleteFeature(this);
}
}