/******************************************************************************* * 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 *******************************************************************************/ package org.eclipse.bpmn2.modeler.ui.views.outline; import java.util.ArrayList; import java.util.List; import org.eclipse.bpmn2.Activity; import org.eclipse.bpmn2.BoundaryEvent; import org.eclipse.bpmn2.CallActivity; import org.eclipse.bpmn2.CatchEvent; import org.eclipse.bpmn2.Choreography; import org.eclipse.bpmn2.ChoreographyActivity; import org.eclipse.bpmn2.Definitions; import org.eclipse.bpmn2.FlowElement; import org.eclipse.bpmn2.FlowElementsContainer; import org.eclipse.bpmn2.FlowNode; import org.eclipse.bpmn2.Lane; import org.eclipse.bpmn2.LaneSet; import org.eclipse.bpmn2.Participant; import org.eclipse.bpmn2.Process; import org.eclipse.bpmn2.SequenceFlow; import org.eclipse.bpmn2.SubChoreography; import org.eclipse.bpmn2.SubProcess; import org.eclipse.bpmn2.ThrowEvent; import org.eclipse.bpmn2.modeler.core.utils.ModelUtil; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EObject; public class FlowElementTreeEditPart extends AbstractGraphicsTreeEditPart { public FlowElementTreeEditPart(DiagramTreeEditPart dep, FlowElement flowElement) { super(dep, flowElement); } public FlowElement getFlowElement() { return (FlowElement) getModel(); } // ======================= overwriteable behaviour ======================== /** * Creates the EditPolicies of this EditPart. Subclasses often overwrite * this method to change the behaviour of the editpart. */ @Override protected void createEditPolicies() { } @Override protected List<Object> getModelChildren() { List<Object> retList = new ArrayList<Object>(); FlowElement elem = getFlowElement(); if (elem instanceof FlowElementsContainer) { FlowElementsContainer container = (FlowElementsContainer)elem; return getFlowElementsContainerChildren(container); } else if (elem instanceof ChoreographyActivity) { ChoreographyActivity ca = (ChoreographyActivity)elem; retList.addAll(ca.getParticipantRefs()); } else if (elem instanceof CallActivity) { // render a Call Activity with its called element target // (a Process or Global Task) as the child node. // DON'T DO IT! This causes an infinite loop. // TODO: figure out how to stop recursion at referenced process level. // CallableElement target = ((CallActivity)elem).getCalledElementRef(); // if (target!=null) { // retList.add(target); // } } else if (elem instanceof CatchEvent) { retList.addAll(((CatchEvent)elem).getEventDefinitions()); retList.addAll(((CatchEvent)elem).getDataOutputAssociation()); } else if (elem instanceof ThrowEvent) { retList.addAll(((ThrowEvent)elem).getEventDefinitions()); retList.addAll(((ThrowEvent)elem).getDataInputAssociation()); } if (elem instanceof Activity) { // Boundary Events are children nodes of Activities Definitions definitions = ModelUtil.getDefinitions(elem); if (definitions!=null) { TreeIterator<EObject> iter = definitions.eAllContents(); while (iter.hasNext()) { EObject o = iter.next(); if (o instanceof BoundaryEvent && ((BoundaryEvent)o).getAttachedToRef() == elem) { retList.add(o); } } retList.addAll(((Activity)elem).getDataInputAssociations()); retList.addAll(((Activity)elem).getDataOutputAssociations()); } } return retList; } public static List<Object> getFlowElementsContainerChildren(FlowElementsContainer container) { List<Object> retList = new ArrayList<Object>(); List<FlowElement> flowElements = new ArrayList<FlowElement>(); for (FlowElement fe : container.getFlowElements()) { if (!(fe instanceof BoundaryEvent)) flowElements.add(fe); } if (container.getLaneSets().size()==0) retList.addAll(flowElements); else { for (LaneSet ls : container.getLaneSets()) { retList.addAll(ls.getLanes()); } // only add the flow element if it's not contained in a Lane List<Object> laneElements = new ArrayList<Object>(); for (FlowElement fe : flowElements) { boolean inLane = false; for (LaneSet ls : container.getLaneSets()) { if (isInLane(fe,ls)) { inLane = true; break; } } if (inLane) laneElements.add(fe); else retList.add(fe); } // don't include any sequence flows that connect flow // nodes that are contained in Lanes List<SequenceFlow> flows = new ArrayList<SequenceFlow>(); for (Object fn : laneElements) { if (fn instanceof FlowNode) { for (SequenceFlow sf : ((FlowNode)fn).getIncoming()) { if ( laneElements.contains(sf.getSourceRef()) && laneElements.contains(sf.getTargetRef()) && !flows.contains(sf)) { flows.add(sf); } } for (SequenceFlow sf : ((FlowNode)fn).getOutgoing()) { if ( laneElements.contains(sf.getSourceRef()) && laneElements.contains(sf.getTargetRef()) && !flows.contains(sf)) { flows.add(sf); } } } } retList.removeAll(flows); } // add the list of Artifacts if (container instanceof Process) { retList.addAll(((Process)container).getArtifacts()); } else if (container instanceof SubProcess) { retList.addAll(((SubProcess)container).getArtifacts()); } if (container instanceof SubChoreography) { retList.addAll(((SubChoreography)container).getArtifacts()); } if (container instanceof Choreography) { // Add Pools as children if the Pool has a Process associated with it, // or if the Participant is NOT referenced by a Choreography Activity. for (Participant p : ((Choreography)container).getParticipants()) { // if (p.getProcessRef()!=null) retList.add(p); // else { for (FlowElement fe : flowElements) { if (fe instanceof ChoreographyActivity) { if (!((ChoreographyActivity)fe).getParticipantRefs().contains(p) && !retList.contains(p)) { retList.add(p); } } } } } } return retList; } public static boolean isInLane(FlowElement fe, LaneSet ls) { if (ls==null || ls.getLanes().size()==0) return false; for (Lane ln : ls.getLanes()) { if (ln.getFlowNodeRefs().contains(fe)) return true; if (isInLane(fe, ln.getChildLaneSet())) return true; } return false; } }