blob: 4da4001bb7af85f377cbec78718bdc1799e91b3a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2012, 2013, 2014 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.core.features.data;
import java.util.List;
import org.eclipse.bpmn2.DataInput;
import org.eclipse.bpmn2.DataOutput;
import org.eclipse.bpmn2.FlowElement;
import org.eclipse.bpmn2.FlowElementsContainer;
import org.eclipse.bpmn2.InputOutputSpecification;
import org.eclipse.bpmn2.InputSet;
import org.eclipse.bpmn2.ItemAwareElement;
import org.eclipse.bpmn2.OutputSet;
import org.eclipse.bpmn2.Process;
import org.eclipse.bpmn2.modeler.core.adapters.ExtendedPropertiesAdapter;
import org.eclipse.bpmn2.modeler.core.features.DefaultMoveBPMNShapeFeature;
import org.eclipse.bpmn2.modeler.core.model.Bpmn2ModelerFactory;
import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil;
import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IMoveShapeContext;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Shape;
/**
* MoveFeature class for all Data items including DataObject, DataStore,
* DataObjectReference, DataStoreReference, DataInput and DataOutput.
* <p>
* The first four of these (referred to collectively as "DataObjects" here) are
* both ItemAwareElements and FlowElements, so their containment rules are
* different than DataInput and DataOutput items: DataObjects are contained in
* FlowElementContainers (in the "flowElements" containment list) whereas
* DataInput and DataOutput objects are contained in an InputOutputSpecification
* container and must also be included in at least one InputSet or OutputSet,
* depending on the item type.
*/
public class MoveDataFeature extends DefaultMoveBPMNShapeFeature {
public MoveDataFeature(IFeatureProvider fp) {
super(fp);
}
public boolean canMoveShape(IMoveShapeContext context) {
if (super.canMoveShape(context)) {
Shape shape = context.getShape();
EObject dataObject = BusinessObjectUtil.getBusinessObjectForPictogramElement(shape);
if (dataObject instanceof ItemAwareElement) {
if (dataObject instanceof FlowElement) {
if (FeatureSupport.isValidDataTarget(context))
return true;
}
else {
// It must be a DataInput or DataOutput object, which is NOT
// a FlowElement. These can only be moved into a container
// that has an InputOutputSpecification.
Shape targetContainer = context.getTargetContainer();
if (targetContainer==context.getSourceContainer())
// target is the same as source container
return true;
// target is different from source container
EObject targetObject = FeatureSupport.getTargetObject(context);
if (targetObject instanceof Process) {
return true;
}
}
}
}
return false;
}
protected void postMoveShape(IMoveShapeContext context) {
Shape shape = context.getShape();
ItemAwareElement dataObject = (ItemAwareElement) BusinessObjectUtil.getBusinessObjectForPictogramElement(shape);
ContainerShape sourceContainer = context.getSourceContainer();
ContainerShape targetContainer = context.getTargetContainer();
if (sourceContainer!=targetContainer) {
EObject targetObject = FeatureSupport.getTargetObject(context);
if ((dataObject instanceof FlowElement) && (targetObject != null)) {
// The Item Aware data object is also a FlowElement, so it
// belongs in a FlowElementsContainer.
List<FlowElement> flowElements = ((FlowElementsContainer)targetObject).getFlowElements();
if (flowElements != null)
flowElements.add((FlowElement)dataObject);
}
else {
// The data object must be either a DataInput or DataOutput,
// so it belongs in an ioSpecification.
Resource resource = targetObject.eResource();
InputOutputSpecification ioSpec = null;
EStructuralFeature f = targetObject.eClass().getEStructuralFeature("ioSpecification"); //$NON-NLS-1$
ioSpec = (InputOutputSpecification) targetObject.eGet(f);
if (ioSpec==null) {
ExtendedPropertiesAdapter adapter = ExtendedPropertiesAdapter.adapt(targetObject);
ioSpec = (InputOutputSpecification) adapter.getFeatureDescriptor(f).createFeature(resource, null);
targetObject.eSet(f, ioSpec);
}
// add the data object to the ioSpec and input/output set
// bulletproofing: the ioSpec SHOULD have at least one InputSet AND
// at least one OutputSet. If not, add them here.
if (ioSpec.getInputSets().size()==0)
ioSpec.getInputSets().add(Bpmn2ModelerFactory.eINSTANCE.createInputSet());
if (ioSpec.getOutputSets().size()==0)
ioSpec.getOutputSets().add(Bpmn2ModelerFactory.eINSTANCE.createOutputSet());
InputOutputSpecification oldIoSpec = (InputOutputSpecification) dataObject.eContainer();
if (dataObject instanceof DataInput) {
ioSpec.getDataInputs().add((DataInput)dataObject);
ioSpec.getInputSets().get(0).getDataInputRefs().add((DataInput)dataObject);
for (InputSet is : oldIoSpec.getInputSets())
is.getDataInputRefs().remove(dataObject);
}
else {
ioSpec.getDataOutputs().add((DataOutput)dataObject);
ioSpec.getOutputSets().get(0).getDataOutputRefs().add((DataOutput)dataObject);
for (OutputSet os : oldIoSpec.getOutputSets())
os.getDataOutputRefs().remove(dataObject);
}
}
}
super.postMoveShape(context);
}
}