/******************************************************************************* * Copyright (c) 2011, 2012 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 * * @author Innar Made ******************************************************************************/ package org.eclipse.bpmn2.modeler.ui.diagram; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import org.eclipse.bpmn2.AdHocSubProcess; import org.eclipse.bpmn2.Association; import org.eclipse.bpmn2.BoundaryEvent; import org.eclipse.bpmn2.BusinessRuleTask; import org.eclipse.bpmn2.CallActivity; import org.eclipse.bpmn2.CallChoreography; import org.eclipse.bpmn2.CallConversation; import org.eclipse.bpmn2.CancelEventDefinition; import org.eclipse.bpmn2.ChoreographyTask; import org.eclipse.bpmn2.CompensateEventDefinition; import org.eclipse.bpmn2.ComplexGateway; import org.eclipse.bpmn2.ConditionalEventDefinition; import org.eclipse.bpmn2.Conversation; import org.eclipse.bpmn2.ConversationLink; import org.eclipse.bpmn2.DataAssociation; import org.eclipse.bpmn2.DataInput; import org.eclipse.bpmn2.DataObject; import org.eclipse.bpmn2.DataObjectReference; import org.eclipse.bpmn2.DataOutput; import org.eclipse.bpmn2.DataStoreReference; import org.eclipse.bpmn2.EndEvent; import org.eclipse.bpmn2.ErrorEventDefinition; import org.eclipse.bpmn2.EscalationEventDefinition; import org.eclipse.bpmn2.EventBasedGateway; import org.eclipse.bpmn2.ExclusiveGateway; import org.eclipse.bpmn2.GlobalBusinessRuleTask; import org.eclipse.bpmn2.GlobalManualTask; import org.eclipse.bpmn2.GlobalScriptTask; import org.eclipse.bpmn2.GlobalTask; import org.eclipse.bpmn2.GlobalUserTask; import org.eclipse.bpmn2.Group; import org.eclipse.bpmn2.InclusiveGateway; import org.eclipse.bpmn2.IntermediateCatchEvent; import org.eclipse.bpmn2.IntermediateThrowEvent; import org.eclipse.bpmn2.Lane; import org.eclipse.bpmn2.LinkEventDefinition; import org.eclipse.bpmn2.ManualTask; import org.eclipse.bpmn2.Message; import org.eclipse.bpmn2.MessageEventDefinition; import org.eclipse.bpmn2.MessageFlow; import org.eclipse.bpmn2.ParallelGateway; import org.eclipse.bpmn2.Participant; import org.eclipse.bpmn2.ReceiveTask; import org.eclipse.bpmn2.ScriptTask; import org.eclipse.bpmn2.SendTask; import org.eclipse.bpmn2.SequenceFlow; import org.eclipse.bpmn2.ServiceTask; import org.eclipse.bpmn2.SignalEventDefinition; import org.eclipse.bpmn2.StartEvent; import org.eclipse.bpmn2.SubChoreography; import org.eclipse.bpmn2.SubConversation; import org.eclipse.bpmn2.SubProcess; import org.eclipse.bpmn2.Task; import org.eclipse.bpmn2.TerminateEventDefinition; import org.eclipse.bpmn2.TextAnnotation; import org.eclipse.bpmn2.TimerEventDefinition; import org.eclipse.bpmn2.Transaction; import org.eclipse.bpmn2.UserTask; import org.eclipse.bpmn2.di.BPMNDiagram; import org.eclipse.bpmn2.modeler.core.LifecycleEvent; import org.eclipse.bpmn2.modeler.core.LifecycleEvent.EventType; import org.eclipse.bpmn2.modeler.core.di.DIImport; import org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2AddFeature; import org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2CreateConnectionFeature; import org.eclipse.bpmn2.modeler.core.features.AbstractBpmn2CreateFeature; import org.eclipse.bpmn2.modeler.core.features.BPMNDiagramFeatureContainer; import org.eclipse.bpmn2.modeler.core.features.CustomConnectionFeatureContainer; import org.eclipse.bpmn2.modeler.core.features.CustomElementFeatureContainer; import org.eclipse.bpmn2.modeler.core.features.CustomShapeFeatureContainer; import org.eclipse.bpmn2.modeler.core.features.CustomShapeFeatureContainer.CreateCustomShapeFeature; import org.eclipse.bpmn2.modeler.core.features.DefaultCopyBPMNElementFeature; import org.eclipse.bpmn2.modeler.core.features.DefaultDeleteBPMNShapeFeature; import org.eclipse.bpmn2.modeler.core.features.DefaultPasteBPMNElementFeature; import org.eclipse.bpmn2.modeler.core.features.DefaultRemoveBPMNShapeFeature; import org.eclipse.bpmn2.modeler.core.features.GraphitiConstants; import org.eclipse.bpmn2.modeler.core.features.IBpmn2FeatureProvider; import org.eclipse.bpmn2.modeler.core.features.IConnectionFeatureContainer; import org.eclipse.bpmn2.modeler.core.features.ICustomElementFeatureContainer; import org.eclipse.bpmn2.modeler.core.features.IFeatureContainer; import org.eclipse.bpmn2.modeler.core.features.IShapeFeatureContainer; 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.core.features.flow.AbstractCreateFlowFeature; import org.eclipse.bpmn2.modeler.core.features.label.LabelFeatureContainer; import org.eclipse.bpmn2.modeler.core.runtime.CustomTaskDescriptor; import org.eclipse.bpmn2.modeler.core.runtime.FeatureContainerDescriptor; import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime; import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil; import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport; import org.eclipse.bpmn2.modeler.ui.editor.DefaultBPMN2Editor; import org.eclipse.bpmn2.modeler.ui.features.activity.subprocess.AdHocSubProcessFeatureContainer; 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.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.callactivity.CallActivityFeatureContainer; import org.eclipse.bpmn2.modeler.ui.features.callactivity.CallGlobalBusinessRuleTaskFeatureContainer; import org.eclipse.bpmn2.modeler.ui.features.callactivity.CallGlobalManualTaskFeatureContainer; import org.eclipse.bpmn2.modeler.ui.features.callactivity.CallGlobalScriptTaskFeatureContainer; import org.eclipse.bpmn2.modeler.ui.features.callactivity.CallGlobalTaskFeatureContainer; import org.eclipse.bpmn2.modeler.ui.features.callactivity.CallGlobalUserTaskFeatureContainer; 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.CallConversationFeatureContainer; 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.conversation.SubConversationFeatureContainer; 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.DataAssociationFeatureContainer; 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.emf.ecore.EObject; import org.eclipse.graphiti.dt.IDiagramTypeProvider; import org.eclipse.graphiti.features.IAddBendpointFeature; import org.eclipse.graphiti.features.IAddFeature; import org.eclipse.graphiti.features.ICopyFeature; 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.IFeature; import org.eclipse.graphiti.features.ILayoutFeature; import org.eclipse.graphiti.features.IMoveBendpointFeature; import org.eclipse.graphiti.features.IMoveConnectionDecoratorFeature; import org.eclipse.graphiti.features.IMoveShapeFeature; import org.eclipse.graphiti.features.IPasteFeature; import org.eclipse.graphiti.features.IReason; import org.eclipse.graphiti.features.IReconnectionFeature; import org.eclipse.graphiti.features.IRemoveBendpointFeature; import org.eclipse.graphiti.features.IRemoveFeature; 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.IContext; import org.eclipse.graphiti.features.context.ICopyContext; import org.eclipse.graphiti.features.context.ICustomContext; 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.IMoveConnectionDecoratorContext; import org.eclipse.graphiti.features.context.IMoveShapeContext; import org.eclipse.graphiti.features.context.IPasteContext; import org.eclipse.graphiti.features.context.IPictogramElementContext; import org.eclipse.graphiti.features.context.IReconnectionContext; import org.eclipse.graphiti.features.context.IRemoveBendpointContext; import org.eclipse.graphiti.features.context.IRemoveContext; import org.eclipse.graphiti.features.context.IResizeShapeContext; import org.eclipse.graphiti.features.context.IUpdateContext; import org.eclipse.graphiti.features.custom.ICustomFeature; import org.eclipse.graphiti.features.impl.Reason; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.platform.IDiagramBehavior; 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 * */ @SuppressWarnings("rawtypes") public class BPMN2FeatureProvider extends DefaultFeatureProvider implements IBpmn2FeatureProvider { private LinkedHashMap<Class,IFeatureContainer> containers; private LinkedHashMap<String,ICustomElementFeatureContainer> customTaskContainers; private ICreateFeature[] createFeatures; private ICreateConnectionFeature[] createConnectionFeatures; private HashMap<Class,IFeature> mapBusinessObjectClassToCreateFeature = new HashMap<Class,IFeature>(); private DefaultCopyBPMNElementFeature defaultCopyFeature = new DefaultCopyBPMNElementFeature(this); private DefaultPasteBPMNElementFeature defaultPasteFeature = new DefaultPasteBPMNElementFeature(this); public BPMN2FeatureProvider(IDiagramTypeProvider dtp) { super(dtp); } private void initializeFeatureContainers() { containers = new LinkedHashMap<Class,IFeatureContainer>(); containers.put(Group.class,new GroupFeatureContainer()); containers.put(DataObject.class,new DataObjectFeatureContainer()); containers.put(DataObjectReference.class,new DataObjectReferenceFeatureContainer()); containers.put(DataStoreReference.class,new DataStoreReferenceFeatureContainer()); containers.put(DataInput.class,new DataInputFeatureContainer()); containers.put(DataOutput.class,new DataOutputFeatureContainer()); containers.put(Message.class,new MessageFeatureContainer()); containers.put(StartEvent.class,new StartEventFeatureContainer()); containers.put(EndEvent.class,new EndEventFeatureContainer()); containers.put(IntermediateCatchEvent.class,new IntermediateCatchEventFeatureContainer()); containers.put(IntermediateThrowEvent.class,new IntermediateThrowEventFeatureContainer()); containers.put(BoundaryEvent.class,new BoundaryEventFeatureContainer()); containers.put(Task.class,new TaskFeatureContainer()); containers.put(ScriptTask.class,new ScriptTaskFeatureContainer()); containers.put(ServiceTask.class,new ServiceTaskFeatureContainer()); containers.put(UserTask.class,new UserTaskFeatureContainer()); containers.put(ManualTask.class,new ManualTaskFeatureContainer()); containers.put(BusinessRuleTask.class,new BusinessRuleTaskFeatureContainer()); containers.put(SendTask.class,new SendTaskFeatureContainer()); containers.put(ReceiveTask.class,new ReceiveTaskFeatureContainer()); containers.put(ChoreographyTask.class,new ChoreographyTaskFeatureContainer()); containers.put(ExclusiveGateway.class,new ExclusiveGatewayFeatureContainer()); containers.put(InclusiveGateway.class,new InclusiveGatewayFeatureContainer()); containers.put(ParallelGateway.class,new ParallelGatewayFeatureContainer()); containers.put(EventBasedGateway.class,new EventBasedGatewayFeatureContainer()); containers.put(ComplexGateway.class,new ComplexGatewayFeatureContainer()); containers.put(AdHocSubProcess.class,new AdHocSubProcessFeatureContainer()); containers.put(CallActivity.class,new CallActivityFeatureContainer()); containers.put(GlobalTask.class,new CallGlobalTaskFeatureContainer()); containers.put(GlobalBusinessRuleTask.class,new CallGlobalBusinessRuleTaskFeatureContainer()); containers.put(GlobalManualTask.class,new CallGlobalManualTaskFeatureContainer()); containers.put(GlobalScriptTask.class,new CallGlobalScriptTaskFeatureContainer()); containers.put(GlobalUserTask.class,new CallGlobalUserTaskFeatureContainer()); containers.put(Transaction.class,new TransactionFeatureContainer()); containers.put(SubProcess.class,new SubProcessFeatureContainer()); containers.put(ConditionalEventDefinition.class,new ConditionalEventDefinitionContainer()); containers.put(MessageEventDefinition.class,new MessageEventDefinitionContainer()); containers.put(TimerEventDefinition.class,new TimerEventDefinitionContainer()); containers.put(SignalEventDefinition.class,new SignalEventDefinitionContainer()); containers.put(EscalationEventDefinition.class,new EscalationEventDefinitionContainer()); containers.put(CompensateEventDefinition.class,new CompensateEventDefinitionContainer()); containers.put(LinkEventDefinition.class,new LinkEventDefinitionContainer()); containers.put(ErrorEventDefinition.class,new ErrorEventDefinitionContainer()); containers.put(CancelEventDefinition.class,new CancelEventDefinitionContainer()); containers.put(TerminateEventDefinition.class,new TerminateEventDefinitionFeatureContainer()); containers.put(SequenceFlow.class,new SequenceFlowFeatureContainer()); containers.put(MessageFlow.class,new MessageFlowFeatureContainer()); containers.put(Association.class,new AssociationFeatureContainer()); containers.put(Conversation.class,new ConversationFeatureContainer()); containers.put(SubConversation.class,new SubConversationFeatureContainer()); containers.put(CallConversation.class,new CallConversationFeatureContainer()); containers.put(ConversationLink.class,new ConversationLinkFeatureContainer()); containers.put(DataAssociation.class,new DataAssociationFeatureContainer()); containers.put(SubChoreography.class,new SubChoreographyFeatureContainer()); containers.put(CallChoreography.class,new CallChoreographyFeatureContainer()); containers.put(Participant.class,new ParticipantFeatureContainer()); containers.put(Lane.class,new LaneFeatureContainer()); containers.put(TextAnnotation.class,new TextAnnotationFeatureContainer()); containers.put(BPMNDiagram.class,new BPMNDiagramFeatureContainer()); // these have no BPMN2 element equivalents containers.put(ChoreographyMessageLinkFeatureContainer.class,new ChoreographyMessageLinkFeatureContainer()); containers.put(LabelFeatureContainer.class,new LabelFeatureContainer()); } public void addFeatureContainer(String id, ICustomElementFeatureContainer fc) throws Exception { if (customTaskContainers==null) { customTaskContainers = new LinkedHashMap<String,ICustomElementFeatureContainer>(); } customTaskContainers.put(id,fc); updateFeatureLists(); } public void init() { updateFeatureLists(); } private void updateFeatureLists() { initializeFeatureContainers(); // Collect all of the <featureContainerDelegate> extensions defined by the current TargetRuntime // and replace the ones in our list of FeatureContainers IDiagramBehavior diagramBehavior = getDiagramTypeProvider().getDiagramBehavior(); TargetRuntime rt = diagramBehavior != null ? TargetRuntime.getRuntime(diagramBehavior) : TargetRuntime.getDefaultRuntime(); for (FeatureContainerDescriptor fcd : rt.getFeatureContainerDescriptors()) { IFeatureContainer fc = fcd.getFeatureContainer(); if (fc instanceof IConnectionFeatureContainer) { ICreateConnectionFeature createConnectionFeature = ((IConnectionFeatureContainer)fc) .getCreateConnectionFeature(this); if (createConnectionFeature!=null) { containers.put(fcd.getType(), fc); } } if (fc instanceof IShapeFeatureContainer) { ICreateFeature createFeature = ((IShapeFeatureContainer)fc).getCreateFeature(this); if (createFeature != null) { containers.put(fcd.getType(), fc); } } } // build the list of CreateFeatures from our new list of all FeatureContainers List<ICreateFeature> createFeaturesList = new ArrayList<ICreateFeature>(); List<ICreateConnectionFeature> createConnectionFeatureList = new ArrayList<ICreateConnectionFeature>(); for (IFeatureContainer fc : containers.values()) { if (fc instanceof IConnectionFeatureContainer) { ICreateConnectionFeature createConnectionFeature = ((IConnectionFeatureContainer) fc) .getCreateConnectionFeature(this); if (createConnectionFeature != null) { createConnectionFeatureList.add(createConnectionFeature); } } if (fc instanceof IShapeFeatureContainer) { ICreateFeature createFeature = ((IShapeFeatureContainer) fc).getCreateFeature(this); if (createFeature != null) { createFeaturesList.add(createFeature); } } } if (customTaskContainers!=null) { for (IFeatureContainer fc : customTaskContainers.values()) { if (fc instanceof IConnectionFeatureContainer) { ICreateConnectionFeature createConnectionFeature = ((IConnectionFeatureContainer) fc) .getCreateConnectionFeature(this); if (createConnectionFeature != null) { createConnectionFeatureList.add(createConnectionFeature); } } if (fc instanceof IShapeFeatureContainer) { ICreateFeature createFeature = ((IShapeFeatureContainer) fc).getCreateFeature(this); if (createFeature != null) { createFeaturesList.add(createFeature); } } } } createFeatures = createFeaturesList.toArray(new ICreateFeature[createFeaturesList.size()]); createConnectionFeatures = createConnectionFeatureList .toArray(new ICreateConnectionFeature[createConnectionFeatureList.size()]); mapBusinessObjectClassToCreateFeature.clear(); for (IFeature cf : createFeatures) { if (cf instanceof AbstractBpmn2CreateFeature) { if (cf instanceof CreateCustomShapeFeature) { continue; } AbstractBpmn2CreateFeature acf = (AbstractBpmn2CreateFeature)cf; mapBusinessObjectClassToCreateFeature.put(acf.getFeatureClass().getInstanceClass(), cf); } } for (IFeature cf : createConnectionFeatures) { if (cf instanceof AbstractCreateFlowFeature) { AbstractBpmn2CreateConnectionFeature acf = (AbstractBpmn2CreateConnectionFeature)cf; mapBusinessObjectClassToCreateFeature.put(acf.getFeatureClass().getInstanceClass(), cf); } } } private EObject getApplyObject(IContext context) { if (context instanceof IAddContext) { Object object = ((IAddContext) context).getNewObject(); if (object instanceof EObject) return (EObject)object; } else if (context instanceof IPictogramElementContext) { return BusinessObjectUtil.getFirstElementOfType( (((IPictogramElementContext) context).getPictogramElement()), EObject.class); } else if (context instanceof IReconnectionContext) { return BusinessObjectUtil.getFirstElementOfType( (((IReconnectionContext) context).getConnection()), EObject.class); } return null; } public IFeatureContainer getFeatureContainer(Class clazz) { return containers.get(clazz); } public IFeatureContainer getFeatureContainer(IContext context) { // The special LabelFeatureContainer is used to add labels to figures that were // added within the given IContext // LabelFeatureContainer lfc = (LabelFeatureContainer) containers.get(LabelFeatureContainer.class); // if (lfc.getApplyObject(context)!=null) // return lfc; TargetRuntime rt = getTargetRuntime(); EObject object = getApplyObject(context); if (object!=null) { FeatureContainerDescriptor fcd = rt.getFeatureContainer(object.eClass()); if (fcd!=null) return fcd.getFeatureContainer(); } Object id = CustomElementFeatureContainer.getId(context); for (IFeatureContainer container : containers.values()) { if (id!=null && !(container instanceof ICustomElementFeatureContainer)) continue; Object o = container.getApplyObject(context); if (o != null && container.canApplyTo(o)) { return container; } } if (id!=null) { for (CustomTaskDescriptor ct : rt.getCustomTaskDescriptors()) { if (id.equals(ct.getId())) { ICustomElementFeatureContainer container = (ICustomElementFeatureContainer)ct.getFeatureContainer(); return container; } } } // last chance: check custom task feature containers if (customTaskContainers!=null) { if (id!=null) { IFeatureContainer container = customTaskContainers.get(id); if (container!=null && container.getApplyObject(context)!=null) return container; } else { for (IFeatureContainer container : customTaskContainers.values()) { if (container.getApplyObject(context)!=null) return container; } } } return null; } @Override public IAddFeature getAddFeature(IAddContext context) { // only here do we need to search all of the Custom Task extensions to check if // the newObject (in AddContext) is a Custom Task. This is because of a chicken/egg // problem during DIImport: the Custom Task feature containers are not added to // the toolpalette until AFTER the file is loaded (in DIImport) and getAddFeature() // is called during file loading. Object id = CustomElementFeatureContainer.getId(context); if (id!=null) { TargetRuntime rt = getTargetRuntime(); for (CustomTaskDescriptor ct : rt.getCustomTaskDescriptors()) { if (id.equals(ct.getId())) { ICustomElementFeatureContainer container = (ICustomElementFeatureContainer)ct.getFeatureContainer(); return container.getAddFeature(this); } } } IFeatureContainer container = getFeatureContainer(context); if (container!=null) { IAddFeature feature = container.getAddFeature(this); if (feature != null) return feature; } return super.getAddFeature(context); } @Override public ICreateFeature[] getCreateFeatures() { return createFeatures; } @Override public IUpdateFeature getUpdateFeature(IUpdateContext context) { IFeatureContainer container = getFeatureContainer(context); if (container!=null) { IUpdateFeature feature = container.getUpdateFeature(this); if (feature != null) return feature; } return super.getUpdateFeature(context); } @Override public ICreateConnectionFeature[] getCreateConnectionFeatures() { return createConnectionFeatures; } @Override public IDirectEditingFeature getDirectEditingFeature(IDirectEditingContext context) { IFeatureContainer container = getFeatureContainer(context); if (container!=null) { IDirectEditingFeature feature = container.getDirectEditingFeature(this); if (feature != null) return feature; } return super.getDirectEditingFeature(context); } @Override public ILayoutFeature getLayoutFeature(ILayoutContext context) { IFeatureContainer container = getFeatureContainer(context); if (container!=null) { ILayoutFeature feature = container.getLayoutFeature(this); if (feature != null) return feature; } return super.getLayoutFeature(context); } @Override public IMoveShapeFeature getMoveShapeFeature(IMoveShapeContext context) { IFeatureContainer container = getFeatureContainer(context); if (container instanceof IShapeFeatureContainer) { IMoveShapeFeature feature = ((IShapeFeatureContainer)container).getMoveFeature(this); if (feature != null) return feature; } return super.getMoveShapeFeature(context); } @Override public IMoveConnectionDecoratorFeature getMoveConnectionDecoratorFeature(IMoveConnectionDecoratorContext context) { IFeatureContainer container = getFeatureContainer(context); if (container instanceof IConnectionFeatureContainer) { IMoveConnectionDecoratorFeature feature = ((IConnectionFeatureContainer)container).getMoveConnectionDecoratorFeature(this); if (feature != null) return feature; } return super.getMoveConnectionDecoratorFeature(context); } @Override public IResizeShapeFeature getResizeShapeFeature(IResizeShapeContext context) { IFeatureContainer container = getFeatureContainer(context); if (container instanceof IShapeFeatureContainer) { IResizeShapeFeature feature = ((IShapeFeatureContainer)container).getResizeFeature(this); if (feature != null) 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) { IFeatureContainer container = getFeatureContainer(context); if (container instanceof IConnectionFeatureContainer) { IReconnectionFeature feature = ((IConnectionFeatureContainer)container).getReconnectionFeature(this); if (feature != null) return feature; } return super.getReconnectionFeature(context); } @Override public IDeleteFeature getDeleteFeature(IDeleteContext context) { IFeatureContainer container = getFeatureContainer(context); if (container!=null) { IDeleteFeature feature = container.getDeleteFeature(this); if (feature != null) return feature; } return new DefaultDeleteBPMNShapeFeature(this); } @Override public IRemoveFeature getRemoveFeature(IRemoveContext context) { IFeatureContainer container = getFeatureContainer(context); if (container!=null) { IRemoveFeature feature = container.getRemoveFeature(this); if (feature != null) return feature; } return new DefaultRemoveBPMNShapeFeature(this); } @Override public ICustomFeature[] getCustomFeatures(ICustomContext context) { List<ICustomFeature> list = new ArrayList<ICustomFeature>(); TargetRuntime rt = getTargetRuntime(); String id = CustomElementFeatureContainer.getId(context); if (id!=null) { for (CustomTaskDescriptor ct : rt.getCustomTaskDescriptors()) { ICustomElementFeatureContainer ctf = ct.getFeatureContainer(); if (ctf!=null && id.equals(ctf.getId())) { ICustomFeature[] cfa = ctf.getCustomFeatures(this); if (cfa!=null) { for (ICustomFeature cf : cfa) { if (cf.isAvailable(context)) { boolean found = false; for (ICustomFeature cfl : list) { if (cfl.getClass() == cf.getClass()) { found = true; break; } } if (!found) list.add(cf); } } } } } } else { for (IFeatureContainer fc : containers.values()) { Object o = fc.getApplyObject(context); if (o!=null && fc.canApplyTo(o)) { ICustomFeature[] cfa = fc.getCustomFeatures(this); if (cfa!=null) { for (ICustomFeature cf : cfa) { boolean found = false; for (ICustomFeature cfl : list) { if (cfl.getClass() == cf.getClass()) { found = true; break; } } if (!found) list.add(cf); } } } } } // list.add(new ValidateModelFeature(this)); return list.toArray(new ICustomFeature[list.size()]); } // TODO: move this to the adapter registry public IFeature getCreateFeatureForPictogramElement(PictogramElement pe) { if (pe!=null) { String id = FeatureSupport.getPropertyValue(pe,GraphitiConstants.CUSTOM_ELEMENT_ID); if (id!=null) { for (IFeatureContainer container : containers.values()) { if (container instanceof ICustomElementFeatureContainer) { ICustomElementFeatureContainer ctf = (ICustomElementFeatureContainer)container; if (id.equals(ctf.getId())) { if (ctf instanceof CustomShapeFeatureContainer) return ((CustomShapeFeatureContainer)ctf).getCreateFeature(this); else if (ctf instanceof CustomConnectionFeatureContainer) return ((CustomConnectionFeatureContainer)ctf).getCreateConnectionFeature(this); } } } } EObject be = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(pe); return getCreateFeatureForBusinessObject(be); } return null; } public IFeature getCreateFeatureForBusinessObject(Object be) { IFeature feature = null; if (be!=null) { Class[] ifs = be.getClass().getInterfaces(); for (int i=0; i<ifs.length && feature==null; ++i) { feature = mapBusinessObjectClassToCreateFeature.get(ifs[i]); } } return feature; } public IFeature getCreateFeatureForBusinessObject(Class clazz) { return mapBusinessObjectClassToCreateFeature.get(clazz); } public void link(PictogramElement element, Object[] objects) { if (element.getLink()==null) { super.link(element, objects); } else { for (Object o : objects) { if (o instanceof EObject && !element.getLink().getBusinessObjects().contains(o)) { element.getLink().getBusinessObjects().add((EObject) o); } } } } @Override public ICopyFeature getCopyFeature(ICopyContext context) { // TODO: COPY-PASTE enable this once copy-paste functionality is working if (defaultCopyFeature.canCopy(context)) return defaultCopyFeature; return null; } @Override public IPasteFeature getPasteFeature(IPasteContext context) { // TODO: COPY-PASTE enable this once copy-paste functionality is working if (defaultPasteFeature.canPaste(context)) return defaultPasteFeature; return null; } @Override public IReason canAdd(IAddContext context) { IReason reason = super.canAdd(context); EObject object = (EObject) context.getNewObject(); TargetRuntime rt = TargetRuntime.getRuntime(object); LifecycleEvent event = new LifecycleEvent(EventType.PICTOGRAMELEMENT_CAN_ADD, this, context, object, rt); event.doit = reason.toBoolean(); LifecycleEvent.notify(event); if (event.doit != reason.toBoolean()) reason = (event.doit ? Reason.createTrueReason() : Reason.createFalseReason()); return reason; } @Override public IReason updateNeeded(IUpdateContext context) { IReason reason = super.updateNeeded(context); PictogramElement pe = context.getPictogramElement(); TargetRuntime rt = TargetRuntime.getRuntime(pe); LifecycleEvent event = new LifecycleEvent(EventType.PICTOGRAMELEMENT_UPDATE_NEEDED, this, context, pe, rt); event.doit = reason.toBoolean(); LifecycleEvent.notify(event); if (event.doit != reason.toBoolean()) reason = (event.doit ? Reason.createTrueReason() : Reason.createFalseReason()); return reason; } @Override public IReason canUpdate(IUpdateContext context) { IReason reason = super.canUpdate(context); PictogramElement pe = context.getPictogramElement(); TargetRuntime rt = TargetRuntime.getRuntime(pe); LifecycleEvent event = new LifecycleEvent(EventType.PICTOGRAMELEMENT_CAN_UPDATE, this, context, pe, rt); event.doit = reason.toBoolean(); LifecycleEvent.notify(event); if (event.doit != reason.toBoolean()) reason = (event.doit ? Reason.createTrueReason() : Reason.createFalseReason()); return reason; } @Override public IReason canLayout(ILayoutContext context) { IReason reason = super.canLayout(context); PictogramElement pe = context.getPictogramElement(); TargetRuntime rt = TargetRuntime.getRuntime(pe); LifecycleEvent event = new LifecycleEvent(EventType.PICTOGRAMELEMENT_CAN_LAYOUT, this, context, pe, rt); event.doit = reason.toBoolean(); LifecycleEvent.notify(event); if (event.doit != reason.toBoolean()) reason = (event.doit ? Reason.createTrueReason() : Reason.createFalseReason()); return reason; } @Override public PictogramElement addIfPossible(IAddContext context) { IAddFeature addElementFeature = getAddFeature(context); PictogramElement pe = super.addIfPossible(context); if (pe!=null) { PictogramElement le = null; if (addElementFeature instanceof AbstractBpmn2AddFeature) { context.putProperty(GraphitiConstants.PICTOGRAM_ELEMENT, pe); IAddFeature addLabelFeature = ((AbstractBpmn2AddFeature)addElementFeature).getAddLabelFeature(this); if (addLabelFeature!=null && addLabelFeature.canAdd(context)) { le = addLabelFeature.add(context); } } TargetRuntime rt = TargetRuntime.getRuntime(pe); List<PictogramElement> pes = new ArrayList<PictogramElement>(); LifecycleEvent.notify(new LifecycleEvent(EventType.PICTOGRAMELEMENT_ADDED, this, context, pe, rt)); if (le!=null) { ((AbstractBpmn2AddFeature)addElementFeature).updatePictogramElement(context, pe); if (!DIImport.isImporting(context)) { context.putProperty(GraphitiConstants.INITIAL_UPDATE, Boolean.TRUE); ((AbstractBpmn2AddFeature)addElementFeature).layoutPictogramElement(context, pe); } } } return pe; } /** * returns the target runtime for the current editor * * @return */ protected TargetRuntime getTargetRuntime() { DefaultBPMN2Editor editor = (DefaultBPMN2Editor)getDiagramTypeProvider().getDiagramBehavior().getDiagramContainer(); return editor.getTargetRuntime(); } }