All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yaoqiang.bpmn.model.BPMNModelUtils Maven / Gradle / Ivy

There is a newer version: 2.2.18
Show newest version
package org.yaoqiang.bpmn.model;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.yaoqiang.bpmn.model.BPMNModelParsingErrors.ErrorMessage;
import org.yaoqiang.bpmn.model.elements.XMLCollection;
import org.yaoqiang.bpmn.model.elements.XMLComplexElement;
import org.yaoqiang.bpmn.model.elements.XMLElement;
import org.yaoqiang.bpmn.model.elements.activities.Activity;
import org.yaoqiang.bpmn.model.elements.activities.CallActivity;
import org.yaoqiang.bpmn.model.elements.activities.SubProcess;
import org.yaoqiang.bpmn.model.elements.artifacts.Artifacts;
import org.yaoqiang.bpmn.model.elements.artifacts.Association;
import org.yaoqiang.bpmn.model.elements.artifacts.Category;
import org.yaoqiang.bpmn.model.elements.artifacts.CategoryValue;
import org.yaoqiang.bpmn.model.elements.bpmndi.BPMNEdge;
import org.yaoqiang.bpmn.model.elements.bpmndi.BPMNShape;
import org.yaoqiang.bpmn.model.elements.choreography.Choreography;
import org.yaoqiang.bpmn.model.elements.choreographyactivities.ChoreographyActivity;
import org.yaoqiang.bpmn.model.elements.choreographyactivities.ChoreographyTask;
import org.yaoqiang.bpmn.model.elements.choreographyactivities.SubChoreography;
import org.yaoqiang.bpmn.model.elements.collaboration.Collaboration;
import org.yaoqiang.bpmn.model.elements.collaboration.MessageFlow;
import org.yaoqiang.bpmn.model.elements.collaboration.Participant;
import org.yaoqiang.bpmn.model.elements.core.common.BPMNError;
import org.yaoqiang.bpmn.model.elements.core.common.FlowElement;
import org.yaoqiang.bpmn.model.elements.core.common.FlowElementsContainer;
import org.yaoqiang.bpmn.model.elements.core.common.FlowNode;
import org.yaoqiang.bpmn.model.elements.core.common.ItemDefinition;
import org.yaoqiang.bpmn.model.elements.core.common.Message;
import org.yaoqiang.bpmn.model.elements.core.common.Resource;
import org.yaoqiang.bpmn.model.elements.core.common.ResourceParameter;
import org.yaoqiang.bpmn.model.elements.core.common.SequenceFlow;
import org.yaoqiang.bpmn.model.elements.core.foundation.BaseElement;
import org.yaoqiang.bpmn.model.elements.core.foundation.Documentation;
import org.yaoqiang.bpmn.model.elements.core.infrastructure.Definitions;
import org.yaoqiang.bpmn.model.elements.data.DataObject;
import org.yaoqiang.bpmn.model.elements.data.DataObjectReference;
import org.yaoqiang.bpmn.model.elements.data.DataStore;
import org.yaoqiang.bpmn.model.elements.data.DataStoreReference;
import org.yaoqiang.bpmn.model.elements.data.Properties;
import org.yaoqiang.bpmn.model.elements.events.BoundaryEvent;
import org.yaoqiang.bpmn.model.elements.events.CatchEvent;
import org.yaoqiang.bpmn.model.elements.events.Event;
import org.yaoqiang.bpmn.model.elements.events.StartEvent;
import org.yaoqiang.bpmn.model.elements.events.ThrowEvent;
import org.yaoqiang.bpmn.model.elements.process.BPMNProcess;
import org.yaoqiang.bpmn.model.elements.process.Lane;
import org.yaoqiang.bpmn.model.elements.process.LaneSet;

/**
 * BPMNModelUtils
 * 
 * @author Shi Yaoqiang([email protected])
 */
public class BPMNModelUtils {

	public static Definitions getDefinitions(XMLElement el) {
		if (el == null)
			return null;
		while (!(el instanceof Definitions)) {
			el = el.getParent();
			if (el == null)
				break;
		}
		return (Definitions) el;
	}

	public static boolean hasAttachments(BaseElement el) {
		boolean hasAttachments = false;
		for (XMLElement doc : el.getDocumentations().getXMLElements()) {
			String format = ((Documentation) doc).getTextFormat();
			if (format.length() != 0 && !format.equals("text/plain")) {
				return true;
			}
		}
		return hasAttachments;
	}

	public static void refreshTypes(Definitions defs) {
		defs.resetTypes();
		for (XMLElement el : defs.getItemDefinitions()) {
			ItemDefinition itemDefinition = (ItemDefinition) el;
			defs.addType(itemDefinition.getStructureRef());
		}
	}

	public static void fillAllFlowNodeSequenceFlowRefs(Definitions defs) {
		for (BPMNProcess p : defs.getProcesses()) {
			fillFlowNodeSequenceFlowRefs(p);
		}
	}

	public static void fillFlowNodeSequenceFlowRefs(FlowElementsContainer container) {
		for (SequenceFlow sf : container.getSequenceFlows()) {
			FlowElement source = container.getFlowElement(sf.getSourceRef());
			if (source != null && source instanceof FlowNode) {
				((FlowNode) source).addOutgoing(sf.getId());
			}
			FlowElement target = container.getFlowElement(sf.getTargetRef());
			if (target != null && target instanceof FlowNode) {
				((FlowNode) target).addIncoming(sf.getId());
			}
		}

		for (FlowNode node : container.getFlowNodes()) {
			if (node instanceof FlowElementsContainer) {
				fillFlowNodeSequenceFlowRefs((FlowElementsContainer) node);
			}
		}
	}

	public static List getAllItemDefinitions(XMLElement el) {
		List items = new ArrayList();
		Definitions defs = getDefinitions(el);
		if (defs == null) {
			return items;
		} else {
			items.addAll(Arrays.asList(new String[] { "xsd:string", "xsd:boolean", "xsd:int", "xsd:integer", "xsd:byte", "xsd:date", "xsd:long", "xsd:double",
					"xsd:float" }));
			items.addAll(defs.getItemDefinitions());
		}
		return items;
	}

	public static String getCategoryValueId(Definitions defs, String label) {
		String[] catvalue = label.split(":");
		if (catvalue.length != 2) {
			catvalue = new String[] { "", label };
		}
		for (XMLElement category : defs.getCategories()) {
			String catName = ((Category) category).getName();
			if (catvalue[0].equals(catName)) {
				for (XMLElement categoryValue : ((Category) category).getCategoryValueList()) {
					String catValue = ((CategoryValue) categoryValue).getValue();
					if (catvalue[1].equals(catValue)) {
						return ((CategoryValue) categoryValue).getId();
					}
				}
			}
		}
		return "";
	}

	public static Object[] getAllCategoryValueNames(Definitions defs) {
		List categories = new ArrayList();
		for (XMLElement category : defs.getCategories()) {
			String catName = ((Category) category).getName();
			for (XMLElement categoryValue : ((Category) category).getCategoryValueList()) {
				String catValue = ((CategoryValue) categoryValue).getValue();
				if (catName.length() == 0) {
					categories.add(catValue);
				} else {
					categories.add(catName + ":" + catValue);
				}
			}
		}
		return categories.toArray();
	}

	public static String getCategoryValueString(Definitions defs, String categoryValueId) {
		CategoryValue categoryValue = defs.getCategoryValue(categoryValueId);
		if (categoryValue == null) {
			return "";
		} else {
			String catName = categoryValue.getParent().getParent().getName();
			String catValue = categoryValue.getValue();
			if (catName.length() == 0) {
				return catValue;
			} else {
				return catName + ":" + catValue;
			}
		}
	}

	public static List getCategoryValueList(Definitions defs, String flowElementId) {
		List categoryValues = new ArrayList();
		for (String id : getCachedCategoryValueIds(defs, flowElementId)) {
			categoryValues.add(getCategoryValueString(defs, id));
		}
		return categoryValues;
	}

	public static Set getAllCategoryValueIds(Category category) {
		Set ids = new HashSet();
		for (XMLElement categoryValue : category.getCategoryValueList()) {
			ids.add(((CategoryValue) categoryValue).getId());
		}
		return ids;
	}

	public static Set getCachedCategoryValueIds(Definitions defs, String flowElementId) {
		Set categoryValues = new HashSet();
		for (XMLElement cat : defs.getCategories()) {
			for (XMLElement catValue : ((Category) cat).getCategoryValueList()) {
				for (XMLElement el : ((CategoryValue) catValue).getCategorizedFlowElements(false)) {
					if (((FlowElement) el).getId().equals(flowElementId))
						categoryValues.add(((CategoryValue) catValue).getId());
				}
			}
		}
		return categoryValues;
	}

	public static List getCategorizedFlowElements(CategoryValue categoryValue) {
		List flowElements = new ArrayList();
		String id = categoryValue.getId();
		Definitions defs = getDefinitions(categoryValue);
		for (XMLElement rootElement : defs.getRootElementList()) {
			flowElements.addAll(getFlowElements(rootElement, id, null));
		}
		return flowElements;
	}

	public static List getAllDataObjects(Definitions defs, String itemId) {
		List result = new ArrayList();

		List dataObjects = new ArrayList();
		for (XMLElement p : getAllNoneEmptyProcesses(defs)) {
			BPMNProcess process = (BPMNProcess) p;
			dataObjects.addAll(process.getDataInOuts());
			for (XMLElement f : getFlowElements(process, null, null)) {
				if (f instanceof DataObject) {
					dataObjects.add(f);
				} else if (f instanceof Activity) {
					dataObjects.addAll(((Activity) f).getDataInOuts());
				} else if (f instanceof CatchEvent) {
					dataObjects.addAll(((CatchEvent) f).getDataOutputList());
				} else if (f instanceof ThrowEvent) {
					dataObjects.addAll(((ThrowEvent) f).getDataInputList());
				}
			}
		}

		if (itemId != null && itemId.length() != 0) {
			for (XMLElement o : dataObjects) {
				String itemRef = ((XMLComplexElement) o).get("itemSubjectRef").toValue();
				if (itemRef.length() == 0) {
					continue;
				}
				int index = itemRef.indexOf(":");
				if (index != -1) {
					itemRef = itemRef.substring(index + 1);
				}
				index = itemId.indexOf(":");
				if (index != -1) {
					itemId = itemId.substring(index + 1);
				}
				if (itemRef.equals(itemId)) {
					result.add(o);
				}
			}
		} else {
			return dataObjects;
		}

		return result;
	}

	public static Object[] getAllDataStoreNames(Definitions defs) {
		List dataStores = new ArrayList();
		for (XMLElement dataStore : defs.getDataStores()) {
			dataStores.add(((DataStore) dataStore).getName());
		}
		return dataStores.toArray();
	}

	public static String getDataStoreId(Definitions defs, String label) {
		for (XMLElement dataStore : defs.getDataStores()) {
			if (((DataStore) dataStore).getName().equals(label)) {
				return ((DataStore) dataStore).getId();
			}
		}
		return "";
	}

	public static FlowNode getInitialFlowNode(Definitions defs) {
		FlowNode initial = null;
		for (BPMNProcess p : defs.getProcesses()) {
			for (XMLElement flowElement : p.getFlowElementList()) {
				if (flowElement instanceof FlowNode) {
					if (((FlowNode) flowElement).getIncomings().isEmpty()) {
						initial = (FlowNode) flowElement;
						break;
					}
				}
			}
		}
		return initial;
	}

	public static List getAllConditionalSequenceFlows(Definitions defs) {
		List sfList = new ArrayList();
		for (BPMNProcess p : defs.getProcesses()) {
			for (SequenceFlow sf : p.getSequenceFlows()) {
				if (!sf.getConditionExpression().isEmpty()) {
					sfList.add(sf);
				}
			}
		}
		return sfList;
	}

	public static List getAllFlowElements(XMLElement element) {
		List flowElements = new ArrayList();
		Definitions defs = getDefinitions(element);
		for (XMLElement rootElement : defs.getRootElementList()) {
			flowElements.addAll(getFlowElements(rootElement, null, null));
		}
		return flowElements;
	}

	public static List getAllSubProcesses(XMLElement element) {
		List flowElements = new ArrayList();
		Definitions defs = getDefinitions(element);
		for (XMLElement rootElement : defs.getRootElementList()) {
			flowElements.addAll(getFlowElements(rootElement, null, SubProcess.class));
		}
		return flowElements;
	}

	public static List getAllEvents(XMLElement element) {
		List flowElements = new ArrayList();
		Definitions defs = getDefinitions(element);
		for (XMLElement rootElement : defs.getRootElementList()) {
			flowElements.addAll(getFlowElements(rootElement, null, Event.class));
		}
		return flowElements;
	}

	public static List getAllDataStoreRefs(XMLElement element) {
		List flowElements = new ArrayList();
		Definitions defs = getDefinitions(element);
		for (XMLElement rootElement : defs.getRootElementList()) {
			flowElements.addAll(getFlowElements(rootElement, null, DataStoreReference.class));
		}
		return flowElements;
	}

	public static List getAllDataObjectRefs(XMLElement element) {
		List flowElements = new ArrayList();
		Definitions defs = getDefinitions(element);
		for (XMLElement rootElement : defs.getRootElementList()) {
			flowElements.addAll(getFlowElements(rootElement, null, DataObjectReference.class));
		}
		return flowElements;
	}

	public static List getAllProperties(Definitions defs) {
		List propertyList = new ArrayList();
		List els = new ArrayList();
		els.addAll(defs.getProcesses());
		for (BPMNProcess p : defs.getProcesses()) {
			els.addAll(getFlowElements(p, null, Event.class));
			els.addAll(getFlowElements(p, null, Activity.class));
		}
		for (XMLElement el : els) {
			Properties properties = (Properties) ((BaseElement) el).get("properties");
			if (properties != null) {
				propertyList.addAll(properties.getXMLElements());
			}
		}
		return propertyList;
	}

	public static List getFlowElements(XMLElement element, String id, Class type) {
		List flowElements = new ArrayList();
		if (element instanceof FlowElementsContainer) {
			for (XMLElement el : ((FlowElementsContainer) element).getFlowElements().getXMLElements()) {
				FlowElement flowElement = (FlowElement) el;
				if (id == null && type == null || type != null && type.isAssignableFrom(flowElement.getClass())
						|| flowElement.getCategoryValueRefSet().contains(id)) {
					flowElements.add(flowElement);
				}
				if (flowElement instanceof FlowElementsContainer) {
					flowElements.addAll(getFlowElements(flowElement, id, type));
				}
			}
		}
		return flowElements;
	}

	public static FlowElement getFlowElement(FlowElementsContainer container, String id) {
		FlowElement flowElement = container.getFlowElement(id);
		if (flowElement == null) {
			for (XMLElement el : container.getFlowNodes()) {
				if (el instanceof FlowElementsContainer) {
					flowElement = getFlowElement((FlowElementsContainer) el, id);
				}
			}
		}
		return flowElement;
	}

	public static StartEvent getStartEvent(FlowElementsContainer container) {
		for (FlowNode flowNode : container.getFlowNodes()) {
			if (flowNode instanceof StartEvent) {
				return (StartEvent) flowNode;
			}
		}
		return null;
	}

	public static List getDataInOuts(XMLElement actOrEvent, String type) {
		if (actOrEvent instanceof Activity) {
			if ("selectDataInput".equals(type)) {
				return ((Activity) actOrEvent).getIoSpecification().getDataInputList();
			} else {
				return ((Activity) actOrEvent).getIoSpecification().getDataOutputList();
			}
		} else if (actOrEvent instanceof ThrowEvent) {
			return ((ThrowEvent) actOrEvent).getDataInputList();
		} else if (actOrEvent instanceof CatchEvent) {
			return ((CatchEvent) actOrEvent).getDataOutputList();
		} else {
			return new ArrayList();
		}
	}

	public static int getEventDefinitionRefNumbers(XMLElement element, String ref) {
		int count = 0;
		for (XMLElement el : getAllEvents(element)) {
			if (((Event) el).hasEventDefinitionRef(ref)) {
				count++;
			}
		}
		return count;
	}

	public static ResourceParameter getResourceParameter(Definitions defs, String paramRef) {
		ResourceParameter param = null;
		for (XMLElement el : defs.getResources()) {
			param = ((Resource) el).getResourceParameter(paramRef);
			if (param != null) {
				return param;
			}
		}
		return param;
	}

	public static BaseElement getDefaultFlowElementsContainer(Definitions defs) {
		BaseElement container = getChoreography(defs);
		if (container == null) {
			container = getCollaboration(defs);
			if (container == null) {
				container = getDefaultProcess(defs);
			}
		}
		return container;
	}

	public static Artifacts getArtifacts(Definitions defs) {
		return getArtifacts(defs, true);
	}

	public static Artifacts getArtifacts(Definitions defs, boolean create) {
		Artifacts artifacts = null;
		Collaboration collaboration = getCollaboration(defs);
		Choreography choreography = getChoreography(defs);
		BPMNProcess process = getDefaultProcess(defs);
		if (collaboration != null) {
			artifacts = collaboration.getArtifacts();
		} else if (choreography != null) {
			artifacts = choreography.getArtifacts();
		} else if (process != null) {
			artifacts = process.getArtifacts();
		} else if (create) {
			process = defs.createProcess(true);
			artifacts = process.getArtifacts();
		}
		return artifacts;
	}

	public static Collaboration getCollaboration(Definitions defs) {
		for (XMLElement root : defs.getRootElementList()) {
			if (root instanceof Collaboration && !(root instanceof Choreography)) {
				return (Collaboration) root;
			}
		}
		return null;
	}

	public static Choreography getChoreography(Definitions defs) {
		for (XMLElement root : defs.getRootElementList()) {
			if (root instanceof Choreography) {
				return (Choreography) root;
			}
		}
		return null;
	}

	public static Choreography getParentChoreography(XMLElement el) {
		if (el == null)
			return null;
		while (!(el instanceof Choreography)) {
			el = el.getParent();
			if (el == null)
				break;
		}
		return (Choreography) el;
	}

	public static List getAllNoneEmptyProcesses(Definitions defs) {
		List processes = new ArrayList();
		for (XMLElement root : defs.getRootElementList()) {
			if (root instanceof BPMNProcess && !((BPMNProcess) root).isEmptyProcess()) {
				processes.add(root);
			}
		}
		return processes;
	}

	public static BPMNProcess getDefaultProcess(Definitions defs) {
		for (XMLElement root : defs.getRootElementList()) {
			if (root instanceof BPMNProcess) {
				Participant participant = getParticipantByProcessId(((BPMNProcess) root).getId(), defs);
				if (participant == null && !hasProcessRef(defs, ((BPMNProcess) root).getId())) {
					return (BPMNProcess) root;
				}
			}
		}
		return null;
	}

	public static BPMNProcess getParentProcess(XMLElement el) {
		if (el == null)
			return null;
		while (!(el instanceof BPMNProcess)) {
			el = el.getParent();
			if (el == null)
				break;
		}
		return (BPMNProcess) el;
	}

	public static FlowElementsContainer getParentFlowElementsContainer(XMLElement el) {
		if (el == null)
			return null;
		if (el instanceof FlowElementsContainer) {
			el = el.getParent();
		}
		while (!(el instanceof FlowElementsContainer)) {
			el = el.getParent();
			if (el == null)
				break;
		}
		return (FlowElementsContainer) el;
	}

	public static Participant getParticipantByProcessId(String processId, Definitions defs) {
		for (XMLElement root : defs.getRootElementList()) {
			if (root instanceof Collaboration) {
				for (XMLElement part : ((Collaboration) root).getParticipantList()) {
					String processRef = ((Participant) part).getProcessRef();
					if (processRef == null || processRef.length() == 0) {
						continue;
					}
					int index = processRef.indexOf(":");
					if (index > 0) {
						processRef = processRef.substring(index + 1);
					}
					if (processRef.equals(processId)) {
						return (Participant) part;
					}
				}
			}
		}
		return null;
	}

	public static Message getMessageByStructure(String type, Definitions defs) {
		for (XMLElement msg : defs.getMessages()) {
			String itemId = ((Message) msg).getItemRef();
			XMLElement item = defs.getRootElement(itemId);
			if (item != null) {
				if (((ItemDefinition) item).getStructureRef().equals(type)) {
					return (Message) msg;
				}
			}
		}
		return null;
	}

	public static BPMNError getErrorByStructure(String type, Definitions defs) {
		for (XMLElement err : defs.getErrors()) {
			String itemId = ((BPMNError) err).getStructureRef();
			XMLElement item = defs.getRootElement(itemId);
			if (item != null) {
				if (((ItemDefinition) item).getStructureRef().equals(type)) {
					return (BPMNError) err;
				}
			}
		}
		return null;
	}

	public static ItemDefinition getItemDefinitionByStructure(String type, Definitions defs) {
		for (XMLElement id : defs.getItemDefinitions()) {
			if (((ItemDefinition) id).getStructureRef().equals(type)) {
				return (ItemDefinition) id;
			}
		}
		return null;
	}

	public static boolean hasItemDefinition(String type, Definitions defs) {
		for (XMLElement id : defs.getItemDefinitions()) {
			if (((ItemDefinition) id).getStructureRef().equals(type)) {
				return true;
			}
		}
		return false;
	}

	public static boolean hasMessageFlowRef(FlowElementsContainer container, String messageFlowId) {
		boolean has = false;
		for (XMLElement flowElement : container.getFlowElements().getXMLElements()) {
			if (flowElement instanceof ChoreographyTask) {
				for (XMLElement mfRef : ((ChoreographyTask) flowElement).getMessageFlowRefList()) {
					if (messageFlowId.equals(mfRef.toValue())) {
						return true;
					}
				}
			} else if (flowElement instanceof SubChoreography) {
				has = hasMessageFlowRef((SubChoreography) flowElement, messageFlowId);
			}
		}
		return has;
	}

	public static boolean hasChoreographyActivity(Definitions defs) {
		Choreography choreography = BPMNModelUtils.getChoreography(defs);
		if (choreography == null) {
			return false;
		}
		for (XMLElement flowElement : choreography.getFlowElementList()) {
			if (flowElement instanceof ChoreographyActivity) {
				return true;
			}
		}
		return false;
	}

	public static boolean hasParticipantRef(XMLElement owner, String participantId) {
		Choreography choreography = BPMNModelUtils.getChoreography(BPMNModelUtils.getDefinitions(owner));
		if (choreography == null) {
			return false;
		}
		Set acts = getChoreographyActivityByParticipantRef(choreography, participantId);
		acts.remove(owner);
		if (acts.size() > 0) {
			return true;
		}
		return false;
	}

	public static boolean hasProcessRef(Definitions defs, String id) {
		boolean has = false;
		for (XMLElement el : getAllNoneEmptyProcesses(defs)) {
			has = hasProcessRef((FlowElementsContainer) el, id);
		}
		return has;
	}

	public static boolean hasProcessRef(FlowElementsContainer container, String id) {
		boolean has = false;
		for (XMLElement f : container.getFlowElements().getXMLElements()) {
			if (f instanceof CallActivity) {
				if (((CallActivity) f).getCalledElement().equals(id)) {
					return true;
				}
			} else if (f instanceof SubProcess) {
				has = hasProcessRef((FlowElementsContainer) f, id);
			}
		}
		return has;
	}

	public static Set getChoreographyActivityByParticipantRef(Definitions defs, String participantId) {
		Set acts = new HashSet();
		Choreography choreography = BPMNModelUtils.getChoreography(defs);
		if (choreography == null) {
			return acts;
		}
		acts.addAll(getChoreographyActivityByParticipantRef(choreography, participantId));

		return acts;
	}

	public static Set getChoreographyActivityByParticipantRef(FlowElementsContainer container, String participantId) {
		Set acts = new HashSet();
		for (XMLElement flowElement : container.getFlowElements().getXMLElements()) {
			if (flowElement instanceof ChoreographyTask) {
				for (String participant : ((ChoreographyTask) flowElement).getParticipantList()) {
					if (participantId.equals(participant)) {
						acts.add((ChoreographyTask) flowElement);
					}
				}
			} else if (flowElement instanceof SubChoreography) {
				for (String participant : ((SubChoreography) flowElement).getParticipantList()) {
					if (participantId.equals(participant)) {
						acts.add((SubChoreography) flowElement);
					}
				}
				acts.addAll(getChoreographyActivityByParticipantRef((SubChoreography) flowElement, participantId));
			}
		}
		return acts;
	}

	public static List getLanes(LaneSet laneSet) {
		List lanes = new ArrayList();
		if (laneSet == null) {
			return lanes;
		}

		for (XMLElement lane : laneSet.getLaneList()) {
			LaneSet childLaneSet = ((Lane) lane).getChildLaneSet();
			if (childLaneSet.getLaneList().size() == 0) {
				lanes.add(lane);
			} else {
				lanes.add(lane);
				lanes.addAll(getLanes(((Lane) lane).getChildLaneSet()));
			}
		}
		return lanes;
	}

	public static Set getFlowNodeRefs(Lane lane) {
		Set refs = new HashSet();
		refs.addAll(lane.getFlowNodeRefs());
		LaneSet childLaneSet = lane.getChildLaneSet();
		for (XMLElement childLane : childLaneSet.getLaneList()) {
			refs.addAll(getFlowNodeRefs((Lane) childLane));
		}
		return refs;
	}

	public static void removeEmptyProcess(Definitions definitions, XMLElement bpmnElement) {
		BPMNProcess process = getParentProcess(bpmnElement);
		if (process != null && process.isEmptyProcess() && !hasProcessRef(definitions, process.getId())) {
			((XMLCollection) process.getParent()).remove(process.getId());
			Participant participant = getParticipantByProcessId(process.getId(), definitions);
			if (participant != null) {
				participant.setProcessRef("");
			}
		}
	}

	public static void generateBPMNDI(Definitions definitions, Collaboration collaboration, Map bpmnElementMap, List shapes,
			List edges) {
		int num = 2;
		int count = 0;
		for (XMLElement e : collaboration.getParticipantList()) {
			BaseElement element = (BaseElement) e;
			if (element instanceof Participant) {
				String id = element.getId();
				if (id.length() == 0) {
					id = "_" + num;
					while (bpmnElementMap.containsKey(id)) {
						id = "_" + ++num;
					}
					element.setId(id);
					bpmnElementMap.put(id, element);
				}
				BPMNShape shape = new BPMNShape(null);
				shape.setBpmnElement(id);
				shape.setHorizontal(true);
				shape.getBounds().setX(0);
				shape.getBounds().setY(count++ * 250);
				shape.getBounds().setHeight(200);
				BPMNProcess process = definitions.getProcess(((Participant) element).getProcessRef());
				if (process != null) {
					generateBPMNDI(process, bpmnElementMap, shapes, edges);
				}
				shapes.add(0, shape);
			}
		}

		for (XMLElement e : collaboration.getMessageFlowList()) {
			BaseElement element = (BaseElement) e;
			if (element instanceof MessageFlow) {
				String id = element.getId();
				if (id.length() == 0) {
					id = "_" + num;
					while (bpmnElementMap.containsKey(id)) {
						id = "_" + ++num;
					}
					element.setId(id);
					bpmnElementMap.put(id, element);
				}
				BPMNEdge edge = new BPMNEdge(null);
				edge.setBpmnElement(id);
				edges.add(edge);
			}
		}
	}

	public static void generateBPMNDI(FlowElementsContainer container, Map bpmnElementMap, List shapes, List edges) {
		int num = 2;
		List laneShapes = new ArrayList();
		List elements = new ArrayList();
		elements.addAll(container.getFlowElements().getXMLElements());
		elements.addAll(container.getArtifacts().getXMLElements());
		if (container instanceof BPMNProcess) {
			elements.addAll(((BPMNProcess) container).getLanes());
		}
		for (XMLElement e : elements) {
			BaseElement element = (BaseElement) e;
			if (element instanceof FlowElementsContainer) {
				generateBPMNDI((FlowElementsContainer) element, bpmnElementMap, shapes, edges);
			}
			String id = element.getId();
			if (id.length() == 0) {
				id = "_" + num;
				while (bpmnElementMap.containsKey(id)) {
					id = "_" + ++num;
				}
				element.setId(id);
				bpmnElementMap.put(id, element);
			}
			if (element instanceof SequenceFlow || element instanceof Association) {
				BPMNEdge edge = new BPMNEdge(null);
				edge.setBpmnElement(id);
				edges.add(edge);
			} else if (!(element instanceof DataObject)) {
				BPMNShape shape = new BPMNShape(null);
				shape.setBpmnElement(id);
				if (element instanceof Lane) {
					shape.setHorizontal(true);
					shape.getBounds().setHeight(200);
				}
				if (element instanceof BoundaryEvent) {
					shapes.add(shape);
				} else if (element instanceof Lane) {
					laneShapes.add(0, shape);
				} else {
					shapes.add(0, shape);
				}
			}
		}
		for (XMLElement shape : laneShapes) {
			shapes.add(0, shape);
		}
	}

	public static Document parseDocument(Object toParse, boolean isFile, List errorMessages) {

		Document document = null;

		try {
			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
			docBuilderFactory.setValidating(true);
			docBuilderFactory.setNamespaceAware(true);
			docBuilderFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
			docBuilderFactory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", "BPMN20.xsd");

			DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
			BPMNModelParsingErrors pErrors = new BPMNModelParsingErrors();
			docBuilder.setErrorHandler(pErrors);
			docBuilder.setEntityResolver(new BPMNModelEntityResolver());
			if (isFile) {
				String filepath = toParse.toString();
				File f = new File(filepath);
				if (!f.exists()) {
					URL url = BPMNModelUtils.class.getResource(filepath);
					if (url == null) {
						if (filepath.startsWith("http") || filepath.startsWith("ftp")) {
							url = new URL(filepath);
						}
					}
					if (url != null) {
						document = docBuilder.parse(url.openStream());
					} else {
						document = docBuilder.parse(new InputSource(new StringReader(toParse.toString())));
					}
				} else {
					if (filepath.endsWith(".gz")) {
						document = docBuilder.parse(new GZIPInputStream(new FileInputStream(f)));
					} else {
						document = docBuilder.parse(new FileInputStream(f));
					}
				}
			} else {
				if (toParse instanceof String) {
					document = docBuilder.parse(new InputSource(new StringReader(toParse.toString())));
				} else if (toParse instanceof InputStream) {
					document = docBuilder.parse((InputStream) toParse);
				}
			}
			errorMessages.addAll(pErrors.getErrorMessages());
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return document;
	}

	public static String getShortClassName(String fullClassName) {
		int lastDot = fullClassName.lastIndexOf(".");
		if (lastDot >= 0) {
			return fullClassName.substring(lastDot + 1, fullClassName.length());
		}
		return fullClassName;
	}

	public static Node getChildByName(Node parent, String childName) {
		NodeList children = parent.getChildNodes();
		for (int i = 0; i < children.getLength(); ++i) {
			Node child = children.item(i);
			if (child.getLocalName() != null && child.getLocalName().equals(childName)) {
				return child;
			}
		}
		return null;
	}

	public static String getChildNodesContent(Node node) {
		String txt = "";
		if (node != null) {
			if (node.hasChildNodes()) {
				Node fc = node.getFirstChild();
				if (fc.getNodeType() == Node.CDATA_SECTION_NODE || fc.getNodeType() == Node.TEXT_NODE) {
					return fc.getNodeValue();
				}
				txt = BPMNModelUtils.getContent(node, true);
				try {
					String fcnc = BPMNModelUtils.getContent(fc, true);
					String closedTag = "";
					if (fcnc.trim().length() > 0) {
						fcnc = fcnc.trim();
					}

					int i1, i2;
					i1 = txt.lastIndexOf(fcnc);
					i2 = txt.lastIndexOf(closedTag);
					txt = txt.substring(i1, i2).trim();
					if (txt.startsWith("")) {
						txt = txt.substring(9, txt.lastIndexOf("]]>"));
					}
				} catch (Exception ex) {
					NodeList nl = node.getChildNodes();
					txt = "";
					try {
						for (int i = 0; i < nl.getLength(); i++) {
							Node sn = nl.item(i);
							if (sn instanceof Element) {
								txt += BPMNModelUtils.getContent(sn, true);
							} else {
								String nv = sn.getNodeValue();
								// trim only the begining of the string
								if (i > 0) {
									txt += nv.substring(1);
								} else if (i == 0 && nv.trim().length() == 0) {
									continue;
								} else {
									txt += nv;
								}
							}
						}
					} catch (Exception ex2) {
					}
				}
			}
		}
		return txt;
	}

	public static String getContent(Node node, boolean omitXMLDeclaration) {
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();

			// Use a Transformer for output
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();
			transformer.setOutputProperty("indent", "yes");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
			transformer.setOutputProperty("encoding", "UTF-8");
			if (omitXMLDeclaration) {
				transformer.setOutputProperty("omit-xml-declaration", "yes");
			}

			DOMSource source = new DOMSource(node);
			StreamResult result = new StreamResult(baos);
			transformer.transform(source, result);

			String cont = baos.toString("UTF8");

			baos.close();
			return cont;
		} catch (Exception ex) {
			return "";
		}
	}

}