/******************************************************************************* * 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 Bob Brodt ******************************************************************************/ package org.eclipse.bpmn2.modeler.core.features; import org.eclipse.bpmn2.BaseElement; import org.eclipse.bpmn2.Collaboration; import org.eclipse.bpmn2.Participant; 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.ToolTipProvider; import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesAdapter; import org.eclipse.bpmn2.modeler.core.merrimac.dialogs.ObjectEditingDialog; import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory; import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory.KeyValue; import org.eclipse.bpmn2.modeler.core.preferences.Bpmn2Preferences; import org.eclipse.bpmn2.modeler.core.preferences.ModelEnablements; 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.core.utils.ModelUtil; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.graphiti.IExecutionInfo; import org.eclipse.graphiti.features.IFeatureAndContext; import org.eclipse.graphiti.features.IFeatureProvider; import org.eclipse.graphiti.features.context.IContext; import org.eclipse.graphiti.features.context.ICreateContext; import org.eclipse.graphiti.features.context.impl.AddContext; import org.eclipse.graphiti.features.impl.AbstractCreateFeature; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.ui.editor.DiagramEditor; import org.eclipse.osgi.util.NLS; /** * This is the Graphiti CreateFeature base class for all BPMN2 model elements which are considered "shapes" * e.g. {@link org.eclipse.bpmn2.Activity}, {@link org.eclipse.bpmn2.DataObject}, {@link org.eclipse.bpmn2.Gateway}, * {@link org.eclipse.bpmn2.Event}, etc. * * The Type Parameter "T" is the BPMN2 element class. * * @param <T> the generic type of the BPMN2 element */ public abstract class AbstractBpmn2CreateFeature<T extends BaseElement> extends AbstractCreateFeature implements IBpmn2CreateFeature<T, ICreateContext> { /** The changes done. */ protected boolean changesDone = true; /** * Default constructor for this Create Feature. The name and description are * generated by looking up the business object class name in the Messages * class. * * @param fp the BPMN2 Modeler Feature Provider * {@link org.eclipse.bpmn2.modeler.ui.diagram.BPMN2FeatureProvider} */ public AbstractBpmn2CreateFeature(IFeatureProvider fp) { super(fp,"",""); //$NON-NLS-1$ //$NON-NLS-2$ } @Override public String getCreateName() { return ModelUtil.getTypeLabel(getFeatureClass()); } /* (non-Javadoc) * @see org.eclipse.graphiti.features.impl.AbstractCreateFeature#getCreateDescription() * This is displayed in the Edit -> Undo/Redo menu */ @Override public String getCreateDescription() { // TODO: get description from Messages by generating a field name using the business object class // {@see ExtendedPropertiesAdapter#getDescription()} String description = ToolTipProvider.INSTANCE.getToolTip(this, getFeatureClass()); if (!description.isEmpty()) return description; return NLS.bind(Messages.AbstractBpmn2CreateFeature_Create, getCreateName()); } @Override public String getName() { return getCreateName(); } @Override public String getDescription() { return getCreateDescription(); } /* (non-Javadoc) * @see org.eclipse.graphiti.features.impl.AbstractFeature#isAvailable(org.eclipse.graphiti.features.context.IContext) * Returns true if this type of shape is available in the tool palette and context menus. */ @Override public boolean isAvailable(IContext context) { return isModelObjectEnabled(); } @Override public boolean canCreate(ICreateContext context) { if (context.getTargetContainer().equals(getDiagram())) { // Only Participants are allowed in a Conversation BPMNDiagram bpmnDiagram = BusinessObjectUtil.getFirstElementOfType(getDiagram(), BPMNDiagram.class); BaseElement bpmnElement = bpmnDiagram.getPlane().getBpmnElement(); if (bpmnElement instanceof Collaboration) { // If this is a Collaboration and it already contains ConversationNodes // then this is a Conversation Diagram - it can't contain any FlowNodes, // Data items, or Lanes. Collaboration collaboration = (Collaboration) bpmnElement; if (!collaboration.getConversations().isEmpty()) { return false; } } } // attempting to create an object in a Participant that has been pushed down // or a Participant that is just a reference to an actual Participant is not allowed. // {@see CreateParticipantReferenceFeature} if (FeatureSupport.isTargetParticipant(context)) { Participant participant = FeatureSupport.getTargetParticipant(context); if (FeatureSupport.isParticipantReference(getDiagram(), participant)) { return false; } if (FeatureSupport.hasBpmnDiagram(participant)) { return false; } } // otherwise, we can create the object return true; } /* (non-Javadoc) * @see org.eclipse.bpmn2.modeler.core.features.IBpmn2CreateFeature#createBusinessObject(org.eclipse.graphiti.features.context.IContext) * Creates the business object, i.e. the BPMN2 element */ @SuppressWarnings({ "unchecked", "rawtypes" }) public T createBusinessObject(ICreateContext context) { Object bo = context.getProperty(GraphitiConstants.BUSINESS_OBJECT); if (bo!=null) return (T) bo; Resource resource = getResource(context); EClass eclass = getBusinessObjectClass(); String id = (String)context.getProperty(GraphitiConstants.CUSTOM_ELEMENT_ID); T businessObject = (T) Bpmn2ModelerFactory.createObject(resource,eclass, new KeyValue(GraphitiConstants.CUSTOM_ELEMENT_ID, id)); putBusinessObject(context, businessObject); changesDone = true; return businessObject; } protected Resource getResource(ICreateContext context) { PictogramElement pe = context.getTargetContainer(); if (pe==null) pe = context.getTargetConnection(); return ExtendedPropertiesAdapter.getResource(pe); } /* (non-Javadoc) * @see org.eclipse.bpmn2.modeler.core.features.IBpmn2CreateFeature#getBusinessObject(org.eclipse.graphiti.features.context.IContext) * Fetches the business object from the Create Context */ @SuppressWarnings("unchecked") public T getBusinessObject(ICreateContext context) { return (T) context.getProperty(GraphitiConstants.BUSINESS_OBJECT); } /* (non-Javadoc) * @see org.eclipse.bpmn2.modeler.core.features.IBpmn2CreateFeature#putBusinessObject(org.eclipse.graphiti.features.context.IContext, org.eclipse.emf.ecore.EObject) * Saves the business object in the Create Context. * If the object is a Custom Element, it is initialized as defined in the extension plugin's plugin.xml */ public void putBusinessObject(ICreateContext context, T businessObject) { context.putProperty(GraphitiConstants.BUSINESS_OBJECT, businessObject); // ModelExtensionDescriptor#populateObject() is already called in Bpmn2ModelerFactory // See https://issues.jboss.org/browse/SWITCHYARD-2484 // String id = (String)context.getProperty(GraphitiConstants.CUSTOM_ELEMENT_ID); // if (id!=null) { // TargetRuntime rt = TargetRuntime.getCurrentRuntime(); // CustomTaskDescriptor ctd = rt.getCustomTask(id); // ctd.populateObject(businessObject, businessObject.eResource(), true); // } TargetRuntime rt = TargetRuntime.getRuntime(getDiagramEditor()); LifecycleEvent.notify(new LifecycleEvent(EventType.BUSINESSOBJECT_INITIALIZED, getFeatureProvider(), context, businessObject, rt)); } public EClass getFeatureClass() { return getBusinessObjectClass(); } @Override protected Object getBusinessObjectForPictogramElement(PictogramElement pe) { // the Graphiti {@link // org.eclipse.graphiti.features.impl.AbstractFeature#getBusinessObjectForPictogramElement()} // will return null if the pictogram element is not "active". In some // cases we also want to check // the business object if the PE has not yet been realized {@see // org.eclipse.bpmn2.modeler.core.features.CompoundCreateFeaturePart#canCreate(IContext)} Object bo = super.getBusinessObjectForPictogramElement(pe); if (bo!=null) return bo; return BusinessObjectUtil.getFirstBaseElement(pe); } /* (non-Javadoc) * @see org.eclipse.bpmn2.modeler.core.features.IBpmn2CreateFeature#postExecute(org.eclipse.graphiti.IExecutionInfo) * Invoked after the graphic has been created to display an optional configuration dialog. * The configuration dialog popup is enabled/disabled in the user Preferences for BPMN2 Editor. */ public void postExecute(IExecutionInfo executionInfo) { for (IFeatureAndContext fc : executionInfo.getExecutionList()) { IContext context = fc.getContext(); if (context instanceof ICreateContext) { ICreateContext cc = (ICreateContext)context; T businessObject = getBusinessObject(cc); Bpmn2Preferences prefs = (Bpmn2Preferences) ((DiagramEditor) getDiagramEditor()).getAdapter(Bpmn2Preferences.class); if (prefs!=null && prefs.getShowPopupConfigDialog(businessObject)) { ObjectEditingDialog dialog = new ObjectEditingDialog((DiagramEditor)getDiagramEditor(), businessObject); dialog.open(); } } } } /** * Creates and prepares a new AddContext from a CreateContext. * * @param context the original CreateContext * @param newObject the new object, a BPMN2 model object. * @return the new AddContext */ protected AddContext createAddContext(ICreateContext context, Object newObject) { AddContext newContext = new AddContext(context, newObject); // copy properties into the new context Object value = context.getProperty(GraphitiConstants.CUSTOM_ELEMENT_ID); newContext.putProperty(GraphitiConstants.CUSTOM_ELEMENT_ID, value); value = context.getProperty(GraphitiConstants.IMPORT_PROPERTY); newContext.putProperty(GraphitiConstants.IMPORT_PROPERTY, value); value = context.getProperty(GraphitiConstants.BUSINESS_OBJECT); newContext.putProperty(GraphitiConstants.BUSINESS_OBJECT, value); return newContext; } /** * Convenience method to check if a model object was disabled in the extension plugin. * * @return true/false depending on if the model object is enabled or disabled. * If disabled, the object will not be available and will not appear in the tool palette * or context menus. */ protected boolean isModelObjectEnabled() { ModelEnablements me = getModelEnablements(); if (me!=null) return me.isEnabled(getBusinessObjectClass()); return false; } /** * Checks if model object is enabled. * * @param object the object * @return true, if model object is enabled */ protected boolean isModelObjectEnabled(EObject object) { ModelEnablements me = getModelEnablements(); if (me!=null) return me.isEnabled(object.eClass()); return false; } /** * Gets the model enablements. * * @return the model enablements */ protected ModelEnablements getModelEnablements() { DiagramEditor editor = (DiagramEditor) getDiagramEditor(); return (ModelEnablements) editor.getAdapter(ModelEnablements.class); } /* (non-Javadoc) * @see org.eclipse.graphiti.features.impl.AbstractFeature#hasDoneChanges() */ @Override public boolean hasDoneChanges() { return changesDone; } protected DiagramEditor getDiagramEditor() { return (DiagramEditor)getFeatureProvider().getDiagramTypeProvider().getDiagramBehavior().getDiagramContainer(); } }