Java tutorial
/* * Copyright 2017 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.designer.bpmn2.impl; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import bpsim.BPSimDataType; import bpsim.BpsimPackage; import bpsim.ControlParameters; import bpsim.CostParameters; import bpsim.ElementParameters; import bpsim.FloatingParameterType; import bpsim.NormalDistributionType; import bpsim.Parameter; import bpsim.ParameterValue; import bpsim.PoissonDistributionType; import bpsim.ResourceParameters; import bpsim.Scenario; import bpsim.TimeParameters; import bpsim.UniformDistributionType; import bpsim.impl.BpsimPackageImpl; import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; import org.apache.commons.lang3.StringUtils; import org.eclipse.bpmn2.Activity; import org.eclipse.bpmn2.AdHocOrdering; import org.eclipse.bpmn2.AdHocSubProcess; import org.eclipse.bpmn2.Artifact; import org.eclipse.bpmn2.Association; import org.eclipse.bpmn2.AssociationDirection; import org.eclipse.bpmn2.BaseElement; import org.eclipse.bpmn2.BoundaryEvent; import org.eclipse.bpmn2.BusinessRuleTask; import org.eclipse.bpmn2.CallActivity; import org.eclipse.bpmn2.CallableElement; import org.eclipse.bpmn2.CancelEventDefinition; import org.eclipse.bpmn2.CatchEvent; import org.eclipse.bpmn2.Choreography; import org.eclipse.bpmn2.Collaboration; import org.eclipse.bpmn2.CompensateEventDefinition; import org.eclipse.bpmn2.ComplexGateway; import org.eclipse.bpmn2.ConditionalEventDefinition; import org.eclipse.bpmn2.Conversation; import org.eclipse.bpmn2.DataInput; import org.eclipse.bpmn2.DataInputAssociation; import org.eclipse.bpmn2.DataObject; import org.eclipse.bpmn2.DataOutput; import org.eclipse.bpmn2.DataOutputAssociation; import org.eclipse.bpmn2.Definitions; import org.eclipse.bpmn2.Documentation; import org.eclipse.bpmn2.EndEvent; import org.eclipse.bpmn2.Error; import org.eclipse.bpmn2.ErrorEventDefinition; import org.eclipse.bpmn2.Escalation; import org.eclipse.bpmn2.EscalationEventDefinition; import org.eclipse.bpmn2.Event; import org.eclipse.bpmn2.EventBasedGateway; import org.eclipse.bpmn2.EventDefinition; import org.eclipse.bpmn2.ExclusiveGateway; import org.eclipse.bpmn2.Expression; import org.eclipse.bpmn2.ExtensionAttributeValue; import org.eclipse.bpmn2.FlowElement; import org.eclipse.bpmn2.FlowElementsContainer; import org.eclipse.bpmn2.FlowNode; import org.eclipse.bpmn2.FormalExpression; import org.eclipse.bpmn2.Gateway; import org.eclipse.bpmn2.GlobalBusinessRuleTask; import org.eclipse.bpmn2.GlobalChoreographyTask; 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.InputSet; import org.eclipse.bpmn2.Interface; import org.eclipse.bpmn2.IntermediateCatchEvent; import org.eclipse.bpmn2.IntermediateThrowEvent; import org.eclipse.bpmn2.ItemAwareElement; import org.eclipse.bpmn2.ItemDefinition; import org.eclipse.bpmn2.Lane; import org.eclipse.bpmn2.LaneSet; import org.eclipse.bpmn2.ManualTask; import org.eclipse.bpmn2.Message; import org.eclipse.bpmn2.MessageEventDefinition; import org.eclipse.bpmn2.MultiInstanceLoopCharacteristics; import org.eclipse.bpmn2.Operation; import org.eclipse.bpmn2.OutputSet; import org.eclipse.bpmn2.ParallelGateway; import org.eclipse.bpmn2.PotentialOwner; import org.eclipse.bpmn2.Process; import org.eclipse.bpmn2.Property; import org.eclipse.bpmn2.ReceiveTask; import org.eclipse.bpmn2.Relationship; import org.eclipse.bpmn2.Resource; import org.eclipse.bpmn2.ResourceRole; import org.eclipse.bpmn2.RootElement; import org.eclipse.bpmn2.ScriptTask; import org.eclipse.bpmn2.SendTask; import org.eclipse.bpmn2.SequenceFlow; import org.eclipse.bpmn2.ServiceTask; import org.eclipse.bpmn2.Signal; import org.eclipse.bpmn2.SignalEventDefinition; import org.eclipse.bpmn2.StartEvent; import org.eclipse.bpmn2.SubProcess; import org.eclipse.bpmn2.Task; import org.eclipse.bpmn2.TerminateEventDefinition; import org.eclipse.bpmn2.TextAnnotation; import org.eclipse.bpmn2.ThrowEvent; import org.eclipse.bpmn2.TimerEventDefinition; import org.eclipse.bpmn2.UserTask; import org.eclipse.bpmn2.di.BPMNDiagram; import org.eclipse.bpmn2.di.BPMNEdge; import org.eclipse.bpmn2.di.BPMNPlane; import org.eclipse.bpmn2.di.BPMNShape; import org.eclipse.dd.dc.Bounds; import org.eclipse.dd.dc.Point; import org.eclipse.dd.di.DiagramElement; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.util.FeatureMap; import org.jboss.drools.DroolsPackage; import org.jboss.drools.GlobalType; import org.jboss.drools.ImportType; import org.jboss.drools.MetaDataType; import org.jboss.drools.OnEntryScriptType; import org.jboss.drools.OnExitScriptType; import org.jboss.drools.impl.DroolsPackageImpl; import org.jbpm.designer.bpmn2.BpmnMarshallerHelper; import org.jbpm.designer.util.Utils; import org.jbpm.designer.web.profile.IDiagramProfile; import org.jbpm.workflow.core.node.RuleSetNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.apache.commons.lang3.StringEscapeUtils.unescapeXml; // transform BPMN2 into JSON public class Bpmn2JsonMarshaller { public static final String defaultBgColor_Activities = "#fafad2"; public static final String defaultBgColor_Events = "#f5deb3"; public static final String defaultBgColor_StartEvents = "#9acd32"; public static final String defaultBgColor_EndEvents = "#ff6347"; public static final String defaultBgColor_DataObjects = "#C0C0C0"; public static final String defaultBgColor_CatchingEvents = "#f5deb3"; public static final String defaultBgColor_ThrowingEvents = "#8cabff"; public static final String defaultBgColor_Gateways = "#f0e68c"; public static final String defaultBgColor_Swimlanes = "#ffffff"; public static final String defaultBrColor = "#000000"; public static final String defaultBrColor_CatchingEvents = "#a0522d"; public static final String defaultBrColor_ThrowingEvents = "#008cec"; public static final String defaultBrColor_Gateways = "#a67f00"; public static final String defaultFontColor = "#000000"; public static final String defaultSequenceflowColor = "#000000"; private static final List<String> defaultTypesList = Arrays.asList("Object", "Boolean", "Float", "Integer", "List", "String"); private Map<String, DiagramElement> _diagramElements = new HashMap<String, DiagramElement>(); private Map<String, Association> _diagramAssociations = new HashMap<String, Association>(); private Scenario _simulationScenario = null; private static final Logger _logger = LoggerFactory.getLogger(Bpmn2JsonMarshaller.class); private IDiagramProfile profile; private boolean coordianteManipulation = true; public void setProfile(IDiagramProfile profile) { this.profile = profile; } public String marshall(Definitions def, String preProcessingData) throws IOException { DroolsPackageImpl.init(); BpsimPackageImpl.init(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); JsonFactory f = new JsonFactory(); JsonGenerator generator = f.createJsonGenerator(baos, JsonEncoding.UTF8); if (def.getRelationships() != null && def.getRelationships().size() > 0) { // current support for single relationship Relationship relationship = def.getRelationships().get(0); for (ExtensionAttributeValue extattrval : relationship.getExtensionValues()) { FeatureMap extensionElements = extattrval.getValue(); @SuppressWarnings("unchecked") List<BPSimDataType> bpsimExtensions = (List<BPSimDataType>) extensionElements .get(BpsimPackage.Literals.DOCUMENT_ROOT__BP_SIM_DATA, true); if (bpsimExtensions != null && bpsimExtensions.size() > 0) { BPSimDataType processAnalysis = bpsimExtensions.get(0); if (processAnalysis.getScenario() != null && processAnalysis.getScenario().size() > 0) { _simulationScenario = processAnalysis.getScenario().get(0); } } } } if (preProcessingData == null || preProcessingData.length() < 1) { preProcessingData = "ReadOnlyService"; } // this is a temp way to determine if // coordinate system changes are necessary String bpmn2Exporter = def.getExporter(); String bpmn2ExporterVersion = def.getExporterVersion(); boolean haveExporter = bpmn2Exporter != null && bpmn2ExporterVersion != null; if (_simulationScenario != null && !haveExporter) { coordianteManipulation = false; } marshallDefinitions(def, generator, preProcessingData); generator.close(); return baos.toString("UTF-8"); } private void linkSequenceFlows(List<FlowElement> flowElements) { Map<String, FlowNode> nodes = new HashMap<String, FlowNode>(); for (FlowElement flowElement : flowElements) { if (flowElement instanceof FlowNode) { nodes.put(flowElement.getId(), (FlowNode) flowElement); if (flowElement instanceof SubProcess) { linkSequenceFlows(((SubProcess) flowElement).getFlowElements()); } } } for (FlowElement flowElement : flowElements) { if (flowElement instanceof SequenceFlow) { SequenceFlow sequenceFlow = (SequenceFlow) flowElement; if (sequenceFlow.getSourceRef() == null && sequenceFlow.getTargetRef() == null) { String id = sequenceFlow.getId(); try { String[] subids = id.split("-_"); String id1 = subids[0]; String id2 = "_" + subids[1]; FlowNode source = nodes.get(id1); if (source != null) { sequenceFlow.setSourceRef(source); } FlowNode target = nodes.get(id2); if (target != null) { sequenceFlow.setTargetRef(target); } } catch (Throwable t) { // Do nothing } } } } } protected void marshallDefinitions(Definitions def, JsonGenerator generator, String preProcessingData) throws JsonGenerationException, IOException { try { generator.writeStartObject(); generator.writeObjectField("resourceId", def.getId()); /** * "properties":{"name":"", * "documentation":"", * "auditing":"", * "monitoring":"", * "executable":"true", * "package":"com.sample", * "vardefs":"a,b,c,d", * "lanes" : "a,b,c", * "id":"", * "version":"", * "author":"", * "language":"", * "namespaces":"", * "targetnamespace":"", * "expressionlanguage":"", * "typelanguage":"", * "creationdate":"", * "modificationdate":"" * } */ Map<String, Object> props = new LinkedHashMap<String, Object>(); props.put("namespaces", ""); //props.put("targetnamespace", def.getTargetNamespace()); props.put("targetnamespace", "http://www.omg.org/bpmn20"); props.put("typelanguage", def.getTypeLanguage()); props.put("name", unescapeXml(def.getName())); props.put("id", def.getId()); props.put("expressionlanguage", def.getExpressionLanguage()); props.put("exporter", StringUtils.isNotEmpty(def.getExporter()) ? def.getExporter() : ""); props.put("exporterversion", StringUtils.isNotEmpty(def.getExporterVersion()) ? def.getExporterVersion() : ""); // backwards compat for BZ 1048191 if (def.getDocumentation() != null && def.getDocumentation().size() > 0) { props.put("documentation", def.getDocumentation().get(0).getText()); } for (RootElement rootElement : def.getRootElements()) { if (rootElement instanceof Process) { // have to wait for process node to finish properties and stencil marshalling props.put("executable", ((Process) rootElement).isIsExecutable() + ""); props.put("id", rootElement.getId()); if (rootElement.getDocumentation() != null && rootElement.getDocumentation().size() > 0) { props.put("documentation", rootElement.getDocumentation().get(0).getText()); } Process pr = (Process) rootElement; if (pr.getName() != null && pr.getName().length() > 0) { props.put("processn", unescapeXml(((Process) rootElement).getName())); } List<Property> processProperties = ((Process) rootElement).getProperties(); if (processProperties != null && processProperties.size() > 0) { String propVal = ""; for (int i = 0; i < processProperties.size(); i++) { Property p = processProperties.get(i); String pKPI = Utils.getMetaDataValue(p.getExtensionValues(), "customKPI"); propVal += p.getId(); // check the structureRef value if (p.getItemSubjectRef() != null && p.getItemSubjectRef().getStructureRef() != null) { propVal += ":" + p.getItemSubjectRef().getStructureRef(); } if (pKPI != null && pKPI.length() > 0) { propVal += ":" + pKPI; } if (i != processProperties.size() - 1) { propVal += ","; } } props.put("vardefs", propVal); } // packageName and version and adHoc are jbpm-specific extension attribute Iterator<FeatureMap.Entry> iter = ((Process) rootElement).getAnyAttribute().iterator(); while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("packageName")) { props.put("package", entry.getValue()); } if (entry.getEStructuralFeature().getName().equals("version")) { props.put("version", entry.getValue()); } if (entry.getEStructuralFeature().getName().equals("adHoc")) { props.put("adhocprocess", entry.getValue()); } } // process imports, custom description and globals extension elements String allImports = ""; if ((rootElement).getExtensionValues() != null && (rootElement).getExtensionValues().size() > 0) { String importsStr = ""; String globalsStr = ""; for (ExtensionAttributeValue extattrval : rootElement.getExtensionValues()) { FeatureMap extensionElements = extattrval.getValue(); @SuppressWarnings("unchecked") List<ImportType> importExtensions = (List<ImportType>) extensionElements .get(DroolsPackage.Literals.DOCUMENT_ROOT__IMPORT, true); @SuppressWarnings("unchecked") List<GlobalType> globalExtensions = (List<GlobalType>) extensionElements .get(DroolsPackage.Literals.DOCUMENT_ROOT__GLOBAL, true); List<MetaDataType> metadataExtensions = (List<MetaDataType>) extensionElements .get(DroolsPackage.Literals.DOCUMENT_ROOT__META_DATA, true); for (ImportType importType : importExtensions) { importsStr += importType.getName(); importsStr += "|default,"; } for (GlobalType globalType : globalExtensions) { globalsStr += (globalType.getIdentifier() + ":" + globalType.getType()); globalsStr += ","; } for (MetaDataType metaType : metadataExtensions) { if (metaType.getName().equals("customDescription")) { props.put("customdescription", metaType.getMetaValue()); } else if (metaType.getName().equals("customCaseIdPrefix")) { props.put("customcaseidprefix", metaType.getMetaValue()); } else if (metaType.getName().equals("customCaseRoles")) { props.put("customcaseroles", metaType.getMetaValue()); } else if (metaType.getName().equals("customSLADueDate")) { props.put("customsladuedate", metaType.getMetaValue()); } else { props.put(metaType.getName(), metaType.getMetaValue()); } } } allImports += importsStr; if (globalsStr.length() > 0) { if (globalsStr.endsWith(",")) { globalsStr = globalsStr.substring(0, globalsStr.length() - 1); } props.put("globals", globalsStr); } } // definitions imports (wsdl) List<org.eclipse.bpmn2.Import> wsdlImports = def.getImports(); if (wsdlImports != null) { for (org.eclipse.bpmn2.Import imp : wsdlImports) { allImports += imp.getLocation() + "|" + imp.getNamespace() + "|wsdl,"; } } if (allImports.endsWith(",")) { allImports = allImports.substring(0, allImports.length() - 1); } props.put("imports", allImports); // simulation if (_simulationScenario != null && _simulationScenario.getScenarioParameters() != null) { props.put("currency", _simulationScenario.getScenarioParameters().getBaseCurrencyUnit() == null ? "" : _simulationScenario.getScenarioParameters().getBaseCurrencyUnit()); props.put("timeunit", _simulationScenario.getScenarioParameters().getBaseTimeUnit().getName()); } marshallProperties(props, generator); marshallStencil("BPMNDiagram", generator); linkSequenceFlows(((Process) rootElement).getFlowElements()); marshallProcess((Process) rootElement, def, generator, preProcessingData); } else if (rootElement instanceof Interface) { // TODO } else if (rootElement instanceof ItemDefinition) { // TODO } else if (rootElement instanceof Resource) { // TODO } else if (rootElement instanceof Error) { // TODO } else if (rootElement instanceof Message) { // TODO } else if (rootElement instanceof Signal) { // TODO } else if (rootElement instanceof Escalation) { // TODO } else if (rootElement instanceof Collaboration) { } else { _logger.warn("Unknown root element " + rootElement + ". This element will not be parsed."); } } generator.writeObjectFieldStart("stencilset"); generator.writeObjectField("url", this.profile.getStencilSetURL()); generator.writeObjectField("namespace", this.profile.getStencilSetNamespaceURL()); generator.writeEndObject(); generator.writeArrayFieldStart("ssextensions"); generator.writeObject(this.profile.getStencilSetExtensionURL()); generator.writeEndArray(); generator.writeEndObject(); } finally { _diagramElements.clear(); } } protected void marshallCallableElement(CallableElement callableElement, Definitions def, JsonGenerator generator) throws JsonGenerationException, IOException { generator.writeStartObject(); generator.writeObjectField("resourceId", callableElement.getId()); if (callableElement instanceof Choreography) { marshallChoreography((Choreography) callableElement, generator); } else if (callableElement instanceof Conversation) { marshallConversation((Conversation) callableElement, generator); } else if (callableElement instanceof GlobalChoreographyTask) { marshallGlobalChoreographyTask((GlobalChoreographyTask) callableElement, generator); } else if (callableElement instanceof GlobalTask) { marshallGlobalTask((GlobalTask) callableElement, generator); } else if (callableElement instanceof Process) { marshallProcess((Process) callableElement, def, generator, ""); } else { throw new UnsupportedOperationException("TODO"); //TODO! } generator.writeEndObject(); } protected void marshallProcess(Process process, Definitions def, JsonGenerator generator, String preProcessingData) throws JsonGenerationException, IOException { BPMNPlane plane = null; for (BPMNDiagram d : def.getDiagrams()) { if (d != null) { BPMNPlane p = d.getPlane(); if (p != null) { if (p.getBpmnElement() == process) { plane = p; break; } } } } if (plane == null) { throw new IllegalArgumentException("Could not find BPMNDI information"); } generator.writeArrayFieldStart("childShapes"); List<String> laneFlowElementsIds = new ArrayList<String>(); for (LaneSet laneSet : process.getLaneSets()) { for (Lane lane : laneSet.getLanes()) { // we only want to marshall lanes if we have the bpmndi info for them! if (findDiagramElement(plane, lane) != null) { laneFlowElementsIds.addAll(marshallLanes(lane, plane, generator, 0, 0, preProcessingData, def)); } } } for (FlowElement flowElement : process.getFlowElements()) { if (!laneFlowElementsIds.contains(flowElement.getId())) { marshallFlowElement(flowElement, plane, generator, 0, 0, preProcessingData, def); } } for (Artifact artifact : process.getArtifacts()) { marshallArtifact(artifact, plane, generator, 0, 0, preProcessingData, def); } generator.writeEndArray(); } private void setCatchEventProperties(CatchEvent event, Map<String, Object> properties, Definitions def) { if (event.getOutputSet() != null) { List<DataOutput> dataOutputs = event.getOutputSet().getDataOutputRefs(); StringBuffer doutbuff = new StringBuffer(); for (DataOutput dout : dataOutputs) { doutbuff.append(dout.getName()); String dtype = getAnyAttributeValue(dout, "dtype"); if (dtype != null && !dtype.isEmpty()) { doutbuff.append(":").append(dtype); } doutbuff.append(","); } if (doutbuff.length() > 0) { doutbuff.setLength(doutbuff.length() - 1); } properties.put("dataoutput", doutbuff.toString()); List<DataOutputAssociation> outputAssociations = event.getDataOutputAssociation(); StringBuffer doutassociationbuff = new StringBuffer(); for (DataOutputAssociation doa : outputAssociations) { String doaName = ((DataOutput) doa.getSourceRef().get(0)).getName(); if (doaName != null && doaName.length() > 0) { doutassociationbuff.append("[dout]" + updateDataInputOutputDashes(((DataOutput) doa.getSourceRef().get(0)).getName())); doutassociationbuff.append("->"); doutassociationbuff.append(doa.getTargetRef().getId()); doutassociationbuff.append(","); } } if (doutassociationbuff.length() > 0) { doutassociationbuff.setLength(doutassociationbuff.length() - 1); } properties.put("dataoutputassociations", doutassociationbuff.toString()); } // event definitions List<EventDefinition> eventdefs = getEventDefinitionsForEvent(event); for (EventDefinition ed : eventdefs) { if (ed instanceof TimerEventDefinition) { TimerEventDefinition ted = (TimerEventDefinition) ed; if (ted.getTimeDate() != null) { try { properties.put("timedate", ((FormalExpression) ted.getTimeDate()).getBody()); } catch (Exception e) { _logger.info("Could not find timedate for : " + ted); } } if (ted.getTimeDuration() != null) { try { properties.put("timeduration", ((FormalExpression) ted.getTimeDuration()).getBody()); } catch (Exception e) { _logger.info("Could not find timeduration for : " + ted); } } if (ted.getTimeCycle() != null) { try { properties.put("timecycle", ((FormalExpression) ted.getTimeCycle()).getBody()); if (((FormalExpression) ted.getTimeCycle()).getLanguage() != null) { properties.put("timecyclelanguage", ((FormalExpression) ted.getTimeCycle()).getLanguage()); } } catch (Exception e) { _logger.info("Could not find timecycle for : " + ted); } } } else if (ed instanceof SignalEventDefinition) { if (((SignalEventDefinition) ed).getSignalRef() != null) { // find signal with the corresponding id boolean foundSignalRef = false; List<RootElement> rootElements = def.getRootElements(); for (RootElement re : rootElements) { if (re instanceof Signal) { if (re.getId().equals(((SignalEventDefinition) ed).getSignalRef())) { properties.put("signalref", ((Signal) re).getName()); foundSignalRef = true; } } } if (!foundSignalRef) { properties.put("signalref", ""); } } else { properties.put("signalref", ""); } } else if (ed instanceof ErrorEventDefinition) { if (((ErrorEventDefinition) ed).getErrorRef() != null && ((ErrorEventDefinition) ed).getErrorRef().getErrorCode() != null) { properties.put("errorref", ((ErrorEventDefinition) ed).getErrorRef().getErrorCode()); } else { properties.put("errorref", ""); } } else if (ed instanceof ConditionalEventDefinition) { try { FormalExpression conditionalExp = (FormalExpression) ((ConditionalEventDefinition) ed) .getCondition(); if (conditionalExp.getBody() != null) { properties.put("conditionexpression", conditionalExp.getBody().replaceAll("\n", "\\\\n")); } if (conditionalExp.getLanguage() != null) { String languageVal = conditionalExp.getLanguage(); if (languageVal.equals("http://www.jboss.org/drools/rule")) { properties.put("conditionlanguage", "drools"); } else if (languageVal.equals("http://www.mvel.org/2.0")) { properties.put("conditionlanguage", "mvel"); } else { // default to drools properties.put("conditionlanguage", "drools"); } } } catch (Exception e) { _logger.info("Could not find conditional expression for: " + ed); } } else if (ed instanceof EscalationEventDefinition) { if (((EscalationEventDefinition) ed).getEscalationRef() != null) { Escalation esc = ((EscalationEventDefinition) ed).getEscalationRef(); if (esc.getEscalationCode() != null && esc.getEscalationCode().length() > 0) { properties.put("escalationcode", esc.getEscalationCode()); } else { properties.put("escalationcode", ""); } } } else if (ed instanceof MessageEventDefinition) { setMessageRefProperties(properties, ((MessageEventDefinition) ed).getMessageRef()); } else if (ed instanceof CompensateEventDefinition) { if (((CompensateEventDefinition) ed).getActivityRef() != null) { Activity act = ((CompensateEventDefinition) ed).getActivityRef(); properties.put("activityref", act.getName()); } } } // custom SLA due date marshalCustomSLADueDateMetadata(event, properties); } private void setMessageRefProperties(final Map<String, Object> properties, final Message message) { if (message != null) { if (message.getName() != null) { properties.put("messageref", message.getName()); } else { properties.put("messageref", message.getId()); } } } private void setThrowEventProperties(ThrowEvent event, Map<String, Object> properties, Definitions def) { if (event.getInputSet() != null) { List<DataInput> dataInputs = event.getInputSet().getDataInputRefs(); StringBuffer dinbuff = new StringBuffer(); for (DataInput din : dataInputs) { dinbuff.append(din.getName()); String dtype = getAnyAttributeValue(din, "dtype"); if (dtype != null && !dtype.isEmpty()) { dinbuff.append(":").append(dtype); } dinbuff.append(","); } if (dinbuff.length() > 0) { dinbuff.setLength(dinbuff.length() - 1); } properties.put("datainput", dinbuff.toString()); StringBuilder associationBuff = new StringBuilder(); marshallDataInputAssociations(associationBuff, event.getDataInputAssociation()); String assignmentString = associationBuff.toString(); if (assignmentString.endsWith(",")) { assignmentString = assignmentString.substring(0, assignmentString.length() - 1); } properties.put("datainputassociations", assignmentString); } // signal scope String signalScope = Utils.getMetaDataValue(event.getExtensionValues(), "customScope"); if (signalScope != null) { properties.put("signalscope", signalScope); } // event definitions List<EventDefinition> eventdefs = getEventDefinitionsForEvent(event); for (EventDefinition ed : eventdefs) { if (ed instanceof TimerEventDefinition) { TimerEventDefinition ted = (TimerEventDefinition) ed; if (ted.getTimeDate() != null) { try { properties.put("timedate", ((FormalExpression) ted.getTimeDate()).getBody()); } catch (Exception e) { _logger.info("Could not find timedate for: " + ted); } } if (ted.getTimeDuration() != null) { try { properties.put("timeduration", ((FormalExpression) ted.getTimeDuration()).getBody()); } catch (Exception e) { _logger.info("Could not find timeduration for: " + ted); } } if (ted.getTimeCycle() != null) { try { properties.put("timecycle", ((FormalExpression) ted.getTimeCycle()).getBody()); if (((FormalExpression) ted.getTimeCycle()).getLanguage() != null) { properties.put("timecyclelanguage", ((FormalExpression) ted.getTimeCycle()).getLanguage()); } } catch (Exception e) { _logger.info("Could not find timecycle for: " + ted); } } } else if (ed instanceof SignalEventDefinition) { if (((SignalEventDefinition) ed).getSignalRef() != null) { // find signal with the corresponding id boolean foundSignalRef = false; List<RootElement> rootElements = def.getRootElements(); for (RootElement re : rootElements) { if (re instanceof Signal) { if (re.getId().equals(((SignalEventDefinition) ed).getSignalRef())) { properties.put("signalref", ((Signal) re).getName()); foundSignalRef = true; } } } if (!foundSignalRef) { properties.put("signalref", ""); } } else { properties.put("signalref", ""); } } else if (ed instanceof ErrorEventDefinition) { if (((ErrorEventDefinition) ed).getErrorRef() != null && ((ErrorEventDefinition) ed).getErrorRef().getErrorCode() != null) { properties.put("errorref", ((ErrorEventDefinition) ed).getErrorRef().getErrorCode()); } else { properties.put("errorref", ""); } } else if (ed instanceof ConditionalEventDefinition) { try { FormalExpression conditionalExp = (FormalExpression) ((ConditionalEventDefinition) ed) .getCondition(); if (conditionalExp.getBody() != null) { properties.put("conditionexpression", conditionalExp.getBody()); } if (conditionalExp.getLanguage() != null) { String languageVal = conditionalExp.getLanguage(); if (languageVal.equals("http://www.jboss.org/drools/rule")) { properties.put("conditionlanguage", "drools"); } else if (languageVal.equals("http://www.mvel.org/2.0")) { properties.put("conditionlanguage", "mvel"); } else { // default to drools properties.put("conditionlanguage", "drools"); } } } catch (Exception e) { _logger.info("Could not find conditionexpression for: " + ed); } } else if (ed instanceof EscalationEventDefinition) { if (((EscalationEventDefinition) ed).getEscalationRef() != null) { Escalation esc = ((EscalationEventDefinition) ed).getEscalationRef(); if (esc.getEscalationCode() != null && esc.getEscalationCode().length() > 0) { properties.put("escalationcode", esc.getEscalationCode()); } else { properties.put("escalationcode", ""); } } } else if (ed instanceof MessageEventDefinition) { setMessageRefProperties(properties, ((MessageEventDefinition) ed).getMessageRef()); } else if (ed instanceof CompensateEventDefinition) { if (((CompensateEventDefinition) ed).getActivityRef() != null) { Activity act = ((CompensateEventDefinition) ed).getActivityRef(); properties.put("activityref", act.getName()); } } } } private List<String> marshallLanes(Lane lane, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, String preProcessingData, Definitions def) throws JsonGenerationException, IOException { Bounds bounds = ((BPMNShape) findDiagramElement(plane, lane)).getBounds(); List<String> nodeRefIds = new ArrayList<String>(); if (bounds != null) { generator.writeStartObject(); generator.writeObjectField("resourceId", lane.getId()); Map<String, Object> laneProperties = new LinkedHashMap<String, Object>(); if (lane.getName() != null) { laneProperties.put("name", unescapeXml(lane.getName())); } else { laneProperties.put("name", ""); } // overwrite name if elementname extension element is present String elementName = Utils.getMetaDataValue(lane.getExtensionValues(), "elementname"); if (elementName != null) { laneProperties.put("name", elementName); } Documentation doc = getDocumentation(lane); if (doc != null) { laneProperties.put("documentation", doc.getText()); } Iterator<FeatureMap.Entry> iter = lane.getAnyAttribute().iterator(); boolean foundBgColor = false; boolean foundBrColor = false; boolean foundFontColor = false; boolean foundSelectable = false; while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("background-color") || entry.getEStructuralFeature().getName().equals("bgcolor")) { laneProperties.put("bgcolor", entry.getValue()); foundBgColor = true; } if (entry.getEStructuralFeature().getName().equals("border-color") || entry.getEStructuralFeature().getName().equals("bordercolor")) { laneProperties.put("bordercolor", entry.getValue()); foundBrColor = true; } if (entry.getEStructuralFeature().getName().equals("fontsize")) { laneProperties.put("fontsize", entry.getValue()); foundBrColor = true; } if (entry.getEStructuralFeature().getName().equals("color") || entry.getEStructuralFeature().getName().equals("fontcolor")) { laneProperties.put("fontcolor", entry.getValue()); foundFontColor = true; } if (entry.getEStructuralFeature().getName().equals("selectable")) { laneProperties.put("isselectable", entry.getValue()); foundSelectable = true; } } if (!foundBgColor) { laneProperties.put("bgcolor", defaultBgColor_Swimlanes); } if (!foundBrColor) { laneProperties.put("bordercolor", defaultBrColor); } if (!foundFontColor) { laneProperties.put("fontcolor", defaultFontColor); } if (!foundSelectable) { laneProperties.put("isselectable", "true"); } marshallProperties(laneProperties, generator); generator.writeObjectFieldStart("stencil"); generator.writeObjectField("id", "Lane"); generator.writeEndObject(); generator.writeArrayFieldStart("childShapes"); for (FlowElement flowElement : lane.getFlowNodeRefs()) { nodeRefIds.add(flowElement.getId()); if (coordianteManipulation) { marshallFlowElement(flowElement, plane, generator, bounds.getX(), bounds.getY(), preProcessingData, def); } else { marshallFlowElement(flowElement, plane, generator, 0, 0, preProcessingData, def); } } generator.writeEndArray(); generator.writeArrayFieldStart("outgoing"); Process process = (Process) plane.getBpmnElement(); writeAssociations(process, lane.getId(), generator); generator.writeEndArray(); generator.writeObjectFieldStart("bounds"); generator.writeObjectFieldStart("lowerRight"); generator.writeObjectField("x", bounds.getX() + bounds.getWidth() - xOffset); generator.writeObjectField("y", bounds.getY() + bounds.getHeight() - yOffset); generator.writeEndObject(); generator.writeObjectFieldStart("upperLeft"); generator.writeObjectField("x", bounds.getX() - xOffset); generator.writeObjectField("y", bounds.getY() - yOffset); generator.writeEndObject(); generator.writeEndObject(); generator.writeEndObject(); } else { // dont marshall the lane unless it has BPMNDI info (eclipse editor does not generate it for lanes currently. for (FlowElement flowElement : lane.getFlowNodeRefs()) { nodeRefIds.add(flowElement.getId()); // we dont want an offset here! marshallFlowElement(flowElement, plane, generator, 0, 0, preProcessingData, def); } } return nodeRefIds; } protected void marshallFlowElement(FlowElement flowElement, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, String preProcessingData, Definitions def) throws JsonGenerationException, IOException { generator.writeStartObject(); generator.writeObjectField("resourceId", flowElement.getId()); Map<String, Object> flowElementProperties = new LinkedHashMap<String, Object>(); Iterator<FeatureMap.Entry> iter = flowElement.getAnyAttribute().iterator(); boolean foundBgColor = false; boolean foundBrColor = false; boolean foundFontColor = false; boolean foundSelectable = false; while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("background-color") || entry.getEStructuralFeature().getName().equals("bgcolor")) { flowElementProperties.put("bgcolor", entry.getValue()); foundBgColor = true; } if (entry.getEStructuralFeature().getName().equals("border-color") || entry.getEStructuralFeature().getName().equals("bordercolor")) { flowElementProperties.put("bordercolor", entry.getValue()); foundBrColor = true; } if (entry.getEStructuralFeature().getName().equals("fontsize")) { flowElementProperties.put("fontsize", entry.getValue()); foundBrColor = true; } if (entry.getEStructuralFeature().getName().equals("color") || entry.getEStructuralFeature().getName().equals("fontcolor")) { flowElementProperties.put("fontcolor", entry.getValue()); foundFontColor = true; } if (entry.getEStructuralFeature().getName().equals("selectable")) { flowElementProperties.put("isselectable", entry.getValue()); foundSelectable = true; } } if (!foundBgColor) { if (flowElement instanceof Activity || flowElement instanceof SubProcess) { flowElementProperties.put("bgcolor", defaultBgColor_Activities); } else if (flowElement instanceof StartEvent) { flowElementProperties.put("bgcolor", defaultBgColor_StartEvents); } else if (flowElement instanceof EndEvent) { flowElementProperties.put("bgcolor", defaultBgColor_EndEvents); } else if (flowElement instanceof DataObject) { flowElementProperties.put("bgcolor", defaultBgColor_DataObjects); } else if (flowElement instanceof CatchEvent) { flowElementProperties.put("bgcolor", defaultBgColor_CatchingEvents); } else if (flowElement instanceof ThrowEvent) { flowElementProperties.put("bgcolor", defaultBgColor_ThrowingEvents); } else if (flowElement instanceof Gateway) { flowElementProperties.put("bgcolor", defaultBgColor_Gateways); } else if (flowElement instanceof Lane) { flowElementProperties.put("bgcolor", defaultBgColor_Swimlanes); } else { flowElementProperties.put("bgcolor", defaultBgColor_Events); } } if (!foundBrColor) { if (flowElement instanceof CatchEvent && !(flowElement instanceof StartEvent)) { flowElementProperties.put("bordercolor", defaultBrColor_CatchingEvents); } else if (flowElement instanceof ThrowEvent && !(flowElement instanceof EndEvent)) { flowElementProperties.put("bordercolor", defaultBrColor_ThrowingEvents); } else if (flowElement instanceof Gateway) { flowElementProperties.put("bordercolor", defaultBrColor_Gateways); } else { flowElementProperties.put("bordercolor", defaultBrColor); } } if (!foundFontColor) { flowElementProperties.put("fontcolor", defaultFontColor); } if (!foundSelectable) { flowElementProperties.put("isselectable", "true"); } Map<String, Object> catchEventProperties = new LinkedHashMap<String, Object>(flowElementProperties); Map<String, Object> throwEventProperties = new LinkedHashMap<String, Object>(flowElementProperties); if (flowElement instanceof CatchEvent) { setCatchEventProperties((CatchEvent) flowElement, catchEventProperties, def); } if (flowElement instanceof ThrowEvent) { setThrowEventProperties((ThrowEvent) flowElement, throwEventProperties, def); } if (flowElement instanceof StartEvent) { marshallStartEvent((StartEvent) flowElement, plane, generator, xOffset, yOffset, catchEventProperties); } else if (flowElement instanceof EndEvent) { marshallEndEvent((EndEvent) flowElement, plane, generator, xOffset, yOffset, throwEventProperties); } else if (flowElement instanceof IntermediateThrowEvent) { marshallIntermediateThrowEvent((IntermediateThrowEvent) flowElement, plane, generator, xOffset, yOffset, throwEventProperties); } else if (flowElement instanceof IntermediateCatchEvent) { marshallIntermediateCatchEvent((IntermediateCatchEvent) flowElement, plane, generator, xOffset, yOffset, catchEventProperties); } else if (flowElement instanceof BoundaryEvent) { marshallBoundaryEvent((BoundaryEvent) flowElement, plane, generator, xOffset, yOffset, catchEventProperties); } else if (flowElement instanceof Task) { marshallTask((Task) flowElement, plane, generator, xOffset, yOffset, preProcessingData, def, flowElementProperties); } else if (flowElement instanceof TextAnnotation) { marshallTextAnnotation((TextAnnotation) flowElement, plane, generator, xOffset, yOffset, preProcessingData, def, flowElementProperties); } else if (flowElement instanceof SequenceFlow) { marshallSequenceFlow((SequenceFlow) flowElement, plane, generator, xOffset, yOffset); } else if (flowElement instanceof ParallelGateway) { marshallParallelGateway((ParallelGateway) flowElement, plane, generator, xOffset, yOffset, flowElementProperties); } else if (flowElement instanceof ExclusiveGateway) { marshallExclusiveGateway((ExclusiveGateway) flowElement, plane, generator, xOffset, yOffset, flowElementProperties); } else if (flowElement instanceof InclusiveGateway) { marshallInclusiveGateway((InclusiveGateway) flowElement, plane, generator, xOffset, yOffset, flowElementProperties); } else if (flowElement instanceof EventBasedGateway) { marshallEventBasedGateway((EventBasedGateway) flowElement, plane, generator, xOffset, yOffset, flowElementProperties); } else if (flowElement instanceof ComplexGateway) { marshallComplexGateway((ComplexGateway) flowElement, plane, generator, xOffset, yOffset, flowElementProperties); } else if (flowElement instanceof CallActivity) { marshallCallActivity((CallActivity) flowElement, plane, generator, xOffset, yOffset, flowElementProperties); } else if (flowElement instanceof SubProcess) { marshallSubProcess((SubProcess) flowElement, plane, generator, xOffset, yOffset, preProcessingData, def, flowElementProperties); } else if (flowElement instanceof DataObject) { // only marshall if we can find DI info for it - BZ 800346 if (findDiagramElement(plane, (DataObject) flowElement) != null) { marshallDataObject((DataObject) flowElement, plane, generator, xOffset, yOffset, flowElementProperties); } else { _logger.info("Could not marshall Data Object " + (DataObject) flowElement + " because no DI information could be found."); } } else { throw new UnsupportedOperationException("Unknown flow element " + flowElement); } generator.writeEndObject(); } protected void marshallStartEvent(StartEvent startEvent, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> properties) throws JsonGenerationException, IOException { // custom SLA due date marshalCustomSLADueDateMetadata(startEvent, properties); setSimulationProperties(startEvent.getId(), properties); List<EventDefinition> eventDefinitions = getEventDefinitionsForEvent(startEvent); properties.put("isinterrupting", startEvent.isIsInterrupting()); if (eventDefinitions == null || eventDefinitions.size() == 0) { marshallNode(startEvent, properties, "StartNoneEvent", plane, generator, xOffset, yOffset); } else if (eventDefinitions.size() == 1) { EventDefinition eventDefinition = eventDefinitions.get(0); if (eventDefinition instanceof ConditionalEventDefinition) { marshallNode(startEvent, properties, "StartConditionalEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof SignalEventDefinition) { marshallNode(startEvent, properties, "StartSignalEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof MessageEventDefinition) { marshallNode(startEvent, properties, "StartMessageEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof TimerEventDefinition) { marshallNode(startEvent, properties, "StartTimerEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof ErrorEventDefinition) { marshallNode(startEvent, properties, "StartErrorEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof ConditionalEventDefinition) { marshallNode(startEvent, properties, "StartConditionalEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof EscalationEventDefinition) { marshallNode(startEvent, properties, "StartEscalationEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof CompensateEventDefinition) { marshallNode(startEvent, properties, "StartCompensationEvent", plane, generator, xOffset, yOffset); } else { throw new UnsupportedOperationException("Event definition not supported: " + eventDefinition); } } else { throw new UnsupportedOperationException("Multiple event definitions not supported for start event"); } } protected void marshallEndEvent(EndEvent endEvent, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> properties) throws JsonGenerationException, IOException { setSimulationProperties(endEvent.getId(), properties); List<EventDefinition> eventDefinitions = getEventDefinitionsForEvent(endEvent); if (eventDefinitions == null || eventDefinitions.size() == 0) { marshallNode(endEvent, properties, "EndNoneEvent", plane, generator, xOffset, yOffset); } else if (eventDefinitions.size() == 1) { EventDefinition eventDefinition = eventDefinitions.get(0); if (eventDefinition instanceof TerminateEventDefinition) { marshallNode(endEvent, properties, "EndTerminateEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof SignalEventDefinition) { marshallNode(endEvent, properties, "EndSignalEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof MessageEventDefinition) { marshallNode(endEvent, properties, "EndMessageEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof ErrorEventDefinition) { marshallNode(endEvent, properties, "EndErrorEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof EscalationEventDefinition) { marshallNode(endEvent, properties, "EndEscalationEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof CompensateEventDefinition) { marshallNode(endEvent, properties, "EndCompensationEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof CancelEventDefinition) { marshallNode(endEvent, properties, "EndCancelEvent", plane, generator, xOffset, yOffset); } else { throw new UnsupportedOperationException("Event definition not supported: " + eventDefinition); } } else { throw new UnsupportedOperationException("Multiple event definitions not supported for end event"); } } protected void marshallIntermediateCatchEvent(IntermediateCatchEvent catchEvent, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> properties) throws JsonGenerationException, IOException { List<EventDefinition> eventDefinitions = getEventDefinitionsForEvent(catchEvent); // simulation properties setSimulationProperties(catchEvent.getId(), properties); if (eventDefinitions.size() == 1) { EventDefinition eventDefinition = eventDefinitions.get(0); if (eventDefinition instanceof SignalEventDefinition) { marshallNode(catchEvent, properties, "IntermediateSignalEventCatching", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof MessageEventDefinition) { marshallNode(catchEvent, properties, "IntermediateMessageEventCatching", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof TimerEventDefinition) { marshallNode(catchEvent, properties, "IntermediateTimerEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof ConditionalEventDefinition) { marshallNode(catchEvent, properties, "IntermediateConditionalEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof ErrorEventDefinition) { marshallNode(catchEvent, properties, "IntermediateErrorEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof EscalationEventDefinition) { marshallNode(catchEvent, properties, "IntermediateEscalationEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof CompensateEventDefinition) { marshallNode(catchEvent, properties, "IntermediateCompensationEventCatching", plane, generator, xOffset, yOffset); } else { throw new UnsupportedOperationException("Event definition not supported: " + eventDefinition); } } else { throw new UnsupportedOperationException("Intermediate catch event does not have event definition."); } } protected void marshallBoundaryEvent(BoundaryEvent boundaryEvent, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> catchEventProperties) throws JsonGenerationException, IOException { List<EventDefinition> eventDefinitions = getEventDefinitionsForEvent(boundaryEvent); if (boundaryEvent.isCancelActivity()) { catchEventProperties.put("boundarycancelactivity", "true"); } else { catchEventProperties.put("boundarycancelactivity", "false"); } // custom SLA due date marshalCustomSLADueDateMetadata(boundaryEvent, catchEventProperties); // simulation properties setSimulationProperties(boundaryEvent.getId(), catchEventProperties); if (eventDefinitions.size() == 1) { EventDefinition eventDefinition = eventDefinitions.get(0); if (eventDefinition instanceof SignalEventDefinition) { marshallNode(boundaryEvent, catchEventProperties, "IntermediateSignalEventCatching", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof EscalationEventDefinition) { marshallNode(boundaryEvent, catchEventProperties, "IntermediateEscalationEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof ErrorEventDefinition) { marshallNode(boundaryEvent, catchEventProperties, "IntermediateErrorEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof TimerEventDefinition) { marshallNode(boundaryEvent, catchEventProperties, "IntermediateTimerEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof CompensateEventDefinition) { marshallNode(boundaryEvent, catchEventProperties, "IntermediateCompensationEventCatching", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof ConditionalEventDefinition) { marshallNode(boundaryEvent, catchEventProperties, "IntermediateConditionalEvent", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof MessageEventDefinition) { marshallNode(boundaryEvent, catchEventProperties, "IntermediateMessageEventCatching", plane, generator, xOffset, yOffset); } else { throw new UnsupportedOperationException("Event definition not supported: " + eventDefinition); } } else { throw new UnsupportedOperationException( "None or multiple event definitions not supported for boundary event"); } } protected void marshallIntermediateThrowEvent(IntermediateThrowEvent throwEvent, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> properties) throws JsonGenerationException, IOException { List<EventDefinition> eventDefinitions = getEventDefinitionsForEvent(throwEvent); // simulation properties setSimulationProperties(throwEvent.getId(), properties); if (eventDefinitions.size() == 0) { marshallNode(throwEvent, properties, "IntermediateEvent", plane, generator, xOffset, yOffset); } else if (eventDefinitions.size() == 1) { EventDefinition eventDefinition = eventDefinitions.get(0); if (eventDefinition instanceof SignalEventDefinition) { marshallNode(throwEvent, properties, "IntermediateSignalEventThrowing", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof MessageEventDefinition) { marshallNode(throwEvent, properties, "IntermediateMessageEventThrowing", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof EscalationEventDefinition) { marshallNode(throwEvent, properties, "IntermediateEscalationEventThrowing", plane, generator, xOffset, yOffset); } else if (eventDefinition instanceof CompensateEventDefinition) { marshallNode(throwEvent, properties, "IntermediateCompensationEventThrowing", plane, generator, xOffset, yOffset); } else { throw new UnsupportedOperationException("Event definition not supported: " + eventDefinition); } } else { throw new UnsupportedOperationException( "None or multiple event definitions not supported for intermediate throw event"); } } protected void marshallCallActivity(CallActivity callActivity, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { Map<String, Object> properties = new LinkedHashMap<String, Object>(flowElementProperties); Iterator<FeatureMap.Entry> iter = callActivity.getAnyAttribute().iterator(); while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("independent")) { properties.put("independent", entry.getValue()); } if (entry.getEStructuralFeature().getName().equals("waitForCompletion")) { properties.put("waitforcompletion", entry.getValue()); } } if (callActivity.getCalledElement() != null && callActivity.getCalledElement().length() > 0) { properties.put("calledelement", callActivity.getCalledElement()); } // custom async String customAsyncMetaData = Utils.getMetaDataValue(callActivity.getExtensionValues(), "customAsync"); String customAsync = (customAsyncMetaData != null && customAsyncMetaData.length() > 0) ? customAsyncMetaData : "false"; properties.put("isasync", customAsync); // custom abortParent String customAbortParentMetaData = Utils.getMetaDataValue(callActivity.getExtensionValues(), "customAbortParent"); String customAbortParent = (customAbortParentMetaData != null && customAbortParentMetaData.length() > 0) ? customAbortParentMetaData : "true"; properties.put("isabortparent", customAbortParent); // custom SLA due date marshalCustomSLADueDateMetadata(callActivity, properties); // data inputs marshallDataInputSet(callActivity, properties); // data outputs marshallDataOutputSet(callActivity, properties); // assignments StringBuilder associationBuff = new StringBuilder(); List<DataInputAssociation> inputAssociations = callActivity.getDataInputAssociations(); List<DataOutputAssociation> outputAssociations = callActivity.getDataOutputAssociations(); marshallDataInputAssociations(associationBuff, inputAssociations); marshallDataOutputAssociations(associationBuff, outputAssociations); String assignmentString = associationBuff.toString(); if (assignmentString.endsWith(",")) { assignmentString = assignmentString.substring(0, assignmentString.length() - 1); } properties.put("assignments", assignmentString); // on-entry and on-exit actions marshallEntryExitActions(callActivity, properties); // simulation properties setSimulationProperties(callActivity.getId(), properties); marshallNode(callActivity, properties, "ReusableSubprocess", plane, generator, xOffset, yOffset); } protected void marshallTask(Task task, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, String preProcessingData, Definitions def, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { Map<String, Object> properties = new LinkedHashMap<String, Object>(flowElementProperties); String taskType = "None"; if (task instanceof BusinessRuleTask) { taskType = "Business Rule"; Iterator<FeatureMap.Entry> iter = task.getAnyAttribute().iterator(); while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("ruleFlowGroup")) { properties.put("ruleflowgroup", entry.getValue()); } } String ruleLanguage = ((BusinessRuleTask) task).getImplementation(); if (RuleSetNode.DMN_LANG.equals(ruleLanguage)) { ruleLanguage = BpmnMarshallerHelper.RULE_LANG_DMN; } else { ruleLanguage = BpmnMarshallerHelper.RULE_LANG_DRL; } properties.put("rulelanguage", ruleLanguage); } else if (task instanceof ScriptTask) { ScriptTask scriptTask = (ScriptTask) task; properties.put("script", scriptTask.getScript() != null ? scriptTask.getScript().replace("\\", "\\\\").replace("\n", "\\n") : ""); String format = scriptTask.getScriptFormat(); if (format != null && format.length() > 0) { String formatToWrite = getScriptLanguageFormat(format); properties.put("script_language", formatToWrite); } taskType = "Script"; } else if (task instanceof ServiceTask) { taskType = "Service"; ServiceTask serviceTask = (ServiceTask) task; if (serviceTask.getOperationRef() != null && serviceTask.getImplementation() != null) { properties.put("serviceimplementation", serviceTask.getImplementation()); properties.put("serviceoperation", serviceTask.getOperationRef().getName() == null ? serviceTask.getOperationRef().getImplementationRef() : serviceTask.getOperationRef().getName()); if (def != null) { List<RootElement> roots = def.getRootElements(); for (RootElement root : roots) { if (root instanceof Interface) { Interface inter = (Interface) root; List<Operation> interOperations = inter.getOperations(); for (Operation interOper : interOperations) { if (interOper.getId().equals(serviceTask.getOperationRef().getId())) { properties.put("serviceinterface", inter.getName() == null ? inter.getImplementationRef() : inter.getName()); } } } } } } } else if (task instanceof ManualTask) { taskType = "Manual"; } else if (task instanceof UserTask) { taskType = "User"; // get the user task actors List<ResourceRole> roles = task.getResources(); StringBuilder sb = new StringBuilder(); for (ResourceRole role : roles) { if (role instanceof PotentialOwner) { FormalExpression fe = (FormalExpression) ((PotentialOwner) role) .getResourceAssignmentExpression().getExpression(); if (fe.getBody() != null && fe.getBody().length() > 0) { sb.append(fe.getBody()); sb.append(","); } } } if (sb.length() > 0) { sb.setLength(sb.length() - 1); } properties.put("actors", sb.toString()); } else if (task instanceof SendTask) { taskType = "Send"; SendTask st = (SendTask) task; setMessageRefProperties(properties, st.getMessageRef()); } else if (task instanceof ReceiveTask) { taskType = "Receive"; ReceiveTask rt = (ReceiveTask) task; setMessageRefProperties(properties, rt.getMessageRef()); } // custom async String customAsyncMetaData = Utils.getMetaDataValue(task.getExtensionValues(), "customAsync"); String customAsync = (customAsyncMetaData != null && customAsyncMetaData.length() > 0) ? customAsyncMetaData : "false"; properties.put("isasync", customAsync); // custom autostart String customAutoStartMetaData = Utils.getMetaDataValue(task.getExtensionValues(), "customAutoStart"); String customAutoStart = (customAutoStartMetaData != null && customAutoStartMetaData.length() > 0) ? customAutoStartMetaData : "false"; properties.put("customautostart", customAutoStart); // custom SLA due date marshalCustomSLADueDateMetadata(task, properties); // backwards compatibility with jbds editor boolean foundTaskName = false; if (task instanceof UserTask && task.getIoSpecification() != null && task.getIoSpecification().getDataInputs() != null) { List<DataInput> taskDataInputs = task.getIoSpecification().getDataInputs(); for (DataInput din : taskDataInputs) { if (din.getName() != null && din.getName().equals("TaskName")) { List<DataInputAssociation> taskDataInputAssociations = task.getDataInputAssociations(); for (DataInputAssociation dia : taskDataInputAssociations) { if (dia.getTargetRef() != null && dia.getTargetRef().getId().equals(din.getId()) && dia.getAssignment() != null && !dia.getAssignment().isEmpty() && dia.getAssignment().get(0).getFrom() != null) { properties.put("taskname", ((FormalExpression) dia.getAssignment().get(0).getFrom()).getBody()); foundTaskName = true; } } break; } } } if (!foundTaskName) { // try the drools specific attribute set on the task Iterator<FeatureMap.Entry> iter = task.getAnyAttribute().iterator(); while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("taskName")) { String tname = (String) entry.getValue(); if (tname != null && tname.length() > 0) { properties.put("taskname", tname); } } } } // check if we are dealing with a custom task boolean isCustomElement = isCustomElement((String) properties.get("taskname"), preProcessingData); if (isCustomElement) { properties.put("tasktype", properties.get("taskname")); } else { properties.put("tasktype", taskType); } // multiple instance if (task.getLoopCharacteristics() != null) { properties.put("multipleinstance", "true"); MultiInstanceLoopCharacteristics taskmi = (MultiInstanceLoopCharacteristics) task .getLoopCharacteristics(); if (taskmi.getLoopDataInputRef() != null) { ItemAwareElement iedatainput = taskmi.getLoopDataInputRef(); List<DataInputAssociation> taskInputAssociations = task.getDataInputAssociations(); for (DataInputAssociation dia : taskInputAssociations) { if (dia.getTargetRef().equals(iedatainput)) { properties.put("multipleinstancecollectioninput", dia.getSourceRef().get(0).getId()); break; } } } if (taskmi.getLoopDataOutputRef() != null) { ItemAwareElement iedataoutput = taskmi.getLoopDataOutputRef(); List<DataOutputAssociation> taskOutputAssociations = task.getDataOutputAssociations(); for (DataOutputAssociation dout : taskOutputAssociations) { if (dout.getSourceRef().get(0).equals(iedataoutput)) { properties.put("multipleinstancecollectionoutput", dout.getTargetRef().getId()); break; } } } if (taskmi.getInputDataItem() != null && taskmi.getInputDataItem().getItemSubjectRef() != null) { List<DataInput> taskDataInputs = task.getIoSpecification().getDataInputs(); for (DataInput din : taskDataInputs) { if (din != null && din.getItemSubjectRef() != null && taskmi.getInputDataItem() != null && taskmi.getInputDataItem().getItemSubjectRef() != null) { if (din.getItemSubjectRef().getId() .equals(taskmi.getInputDataItem().getItemSubjectRef().getId())) { properties.put("multipleinstancedatainput", din.getName()); } } } } if (taskmi.getOutputDataItem() != null && taskmi.getOutputDataItem().getItemSubjectRef() != null) { List<DataOutput> taskDataOutputs = task.getIoSpecification().getDataOutputs(); for (DataOutput dout : taskDataOutputs) { if (dout != null && dout.getItemSubjectRef() != null && taskmi.getOutputDataItem() != null && taskmi.getOutputDataItem().getItemSubjectRef() != null) { if (dout.getItemSubjectRef().getId() .equals(taskmi.getOutputDataItem().getItemSubjectRef().getId())) { properties.put("multipleinstancedataoutput", dout.getName()); } } } } if (taskmi.getCompletionCondition() != null) { try { if (taskmi.getCompletionCondition() instanceof FormalExpression) { properties.put("multipleinstancecompletioncondition", ((FormalExpression) taskmi.getCompletionCondition()).getBody()); } } catch (Exception e) { _logger.info("Could not find multipleinstancecompletioncondition for: " + taskmi); } } } else { properties.put("multipleinstance", "false"); } // data inputs List<String> disallowedInputs = new ArrayList<String>(); disallowedInputs.add("miinputCollection"); if ((task instanceof UserTask) || isCustomElement) { disallowedInputs.add("TaskName"); } marshallDataInputSet(task, properties, disallowedInputs); DataInput groupDataInput = null; DataInput skippableDataInput = null; DataInput commentDataInput = null; DataInput descriptionDataInput = null; DataInput contentDataInput = null; DataInput priorityDataInput = null; DataInput localeDataInput = null; DataInput createdByDataInput = null; DataInput notCompletedReassignInput = null; DataInput notStartedReassignInput = null; DataInput notCompletedNotificationInput = null; DataInput notStartedNotificationInput = null; if (task.getIoSpecification() != null) { List<InputSet> inputSetList = task.getIoSpecification().getInputSets(); for (InputSet inset : inputSetList) { List<DataInput> dataInputList = inset.getDataInputRefs(); for (DataInput dataIn : dataInputList) { // dont add "TaskName" as that is added manually String dataInName = dataIn.getName(); if (task instanceof UserTask && dataInName != null) { if (dataInName.equals("GroupId")) { groupDataInput = dataIn; } else if (dataInName.equals("Skippable")) { skippableDataInput = dataIn; } else if (dataInName.equals("Comment")) { commentDataInput = dataIn; } else if (dataInName.equals("Description")) { descriptionDataInput = dataIn; } else if (dataInName.equals("Content")) { contentDataInput = dataIn; } else if (dataInName.equals("Priority")) { priorityDataInput = dataIn; } else if (dataInName.equals("Locale")) { localeDataInput = dataIn; } else if (dataInName.equals("CreatedBy")) { createdByDataInput = dataIn; } else if (dataInName.equals("NotCompletedReassign")) { notCompletedReassignInput = dataIn; } else if (dataInName.equals("NotStartedReassign")) { notStartedReassignInput = dataIn; } else if (dataInName.equals("NotCompletedNotify")) { notCompletedNotificationInput = dataIn; } else if (dataInName.equals("NotStartedNotify")) { notStartedNotificationInput = dataIn; } } } } } // data outputs marshallDataOutputSet(task, properties, Arrays.asList("mioutputCollection")); // assignments StringBuilder associationBuff = new StringBuilder(); List<DataInputAssociation> inputAssociations = task.getDataInputAssociations(); List<DataOutputAssociation> outputAssociations = task.getDataOutputAssociations(); List<String> uniDirectionalAssociations = new ArrayList<String>(); //List<String> biDirectionalAssociations = new ArrayList<String>(); for (DataInputAssociation datain : inputAssociations) { boolean proceed = true; if (task.getLoopCharacteristics() != null) { MultiInstanceLoopCharacteristics taskMultiLoop = (MultiInstanceLoopCharacteristics) task .getLoopCharacteristics(); // dont include associations that include mi loop data inputs if (taskMultiLoop.getInputDataItem() != null && taskMultiLoop.getInputDataItem().getId() != null) { if (datain.getSourceRef() != null && datain.getSourceRef().size() > 0 && datain.getSourceRef() .get(0).getId().equals(taskMultiLoop.getInputDataItem().getId())) { proceed = false; } } // dont include associations that include loopDataInputRef as target if (taskMultiLoop.getLoopDataInputRef() != null) { if (datain.getTargetRef().equals(taskMultiLoop.getLoopDataInputRef())) { proceed = false; } } } if (proceed) { String lhsAssociation = ""; if (datain.getSourceRef() != null && datain.getSourceRef().size() > 0) { if (datain.getTransformation() != null && datain.getTransformation().getBody() != null) { lhsAssociation = datain.getTransformation().getBody(); } else { lhsAssociation = datain.getSourceRef().get(0).getId(); } } String rhsAssociation = ""; if (datain.getTargetRef() != null) { rhsAssociation = ((DataInput) datain.getTargetRef()).getName(); } //boolean isBiDirectional = false; boolean isAssignment = false; if (datain.getAssignment() != null && datain.getAssignment().size() > 0) { isAssignment = true; } // else { // // check if this is a bi-directional association // for(DataOutputAssociation dataout : outputAssociations) { // if(dataout.getTargetRef().getId().equals(lhsAssociation) && // ((DataOutput) dataout.getSourceRef().get(0)).getName().equals(rhsAssociation)) { // isBiDirectional = true; // break; // } // } // } if (isAssignment) { // only know how to deal with formal expressions if (datain.getAssignment().get(0).getFrom() instanceof FormalExpression) { String associationValue = ((FormalExpression) datain.getAssignment().get(0).getFrom()) .getBody(); if (associationValue == null) { associationValue = ""; } // Handle properties that have their independent input editors if (isCustomElement((String) properties.get("taskname"), preProcessingData)) { if (!(rhsAssociation.equals("TaskName"))) { // for custom tasks (workitems) we do not want to modify assiciation value, just encode it // JBPM-7462 String replacer = encodeAssociationValue(associationValue); associationBuff.append("[din]" + rhsAssociation).append("=").append(replacer); associationBuff.append(","); properties.put(rhsAssociation.toLowerCase(), associationValue); } } else { if (!(task instanceof UserTask) || !(rhsAssociation.equals("GroupId") || rhsAssociation.equals("Skippable") || rhsAssociation.equals("Comment") || rhsAssociation.equals("Description") || rhsAssociation.equals("Priority") || rhsAssociation.equals("Content") || rhsAssociation.equals("TaskName") || rhsAssociation.equals("Locale") || rhsAssociation.equals("CreatedBy") || rhsAssociation.equals("NotCompletedReassign") || rhsAssociation.equals("NotStartedReassign") || rhsAssociation.equals("NotCompletedNotify") || rhsAssociation.equals("NotStartedNotify"))) { String replacer = encodeAssociationValue(associationValue); associationBuff.append("[din]" + updateDataInputOutputDashes(rhsAssociation)) .append("=").append(replacer); associationBuff.append(","); properties.put(rhsAssociation.toLowerCase(), associationValue); } } if (rhsAssociation.equalsIgnoreCase("TaskName")) { properties.put("taskname", associationValue); } if (task instanceof UserTask && datain.getAssignment().get(0).getTo() != null && ((FormalExpression) datain.getAssignment().get(0).getTo()).getBody() != null && datain.getAssignment().get(0).getFrom() != null) { String toBody = ((FormalExpression) datain.getAssignment().get(0).getTo()).getBody(); String fromBody = ((FormalExpression) datain.getAssignment().get(0).getFrom()) .getBody(); if (toBody != null) { if (groupDataInput != null && toBody.equals(groupDataInput.getId())) { properties.put("groupid", fromBody == null ? "" : fromBody); } else if (skippableDataInput != null && toBody.equals(skippableDataInput.getId())) { properties.put("skippable", fromBody); } else if (commentDataInput != null && toBody.equals(commentDataInput.getId())) { properties.put("subject", fromBody); } else if (descriptionDataInput != null && toBody.equals(descriptionDataInput.getId())) { properties.put("description", fromBody); } else if (priorityDataInput != null && toBody.equals(priorityDataInput.getId())) { properties.put("priority", fromBody == null ? "" : fromBody); } else if (contentDataInput != null && toBody.equals(contentDataInput.getId())) { properties.put("content", fromBody); } else if (localeDataInput != null && toBody.equals(localeDataInput.getId())) { properties.put("locale", fromBody); } else if (createdByDataInput != null && toBody.equals(createdByDataInput.getId())) { properties.put("createdby", fromBody); } else if (notCompletedReassignInput != null && toBody.equals(notCompletedReassignInput.getId())) { properties.put("tmpreassignmentnotcompleted", updateReassignmentAndNotificationInput(fromBody, "not-completed")); } else if (notStartedReassignInput != null && toBody.equals(notStartedReassignInput.getId())) { properties.put("tmpreassignmentnotstarted", updateReassignmentAndNotificationInput(fromBody, "not-started")); } else if (notCompletedNotificationInput != null && toBody.equals(notCompletedNotificationInput.getId())) { properties.put("tmpnotificationnotcompleted", updateReassignmentAndNotificationInput(fromBody, "not-completed")); } else if (notStartedNotificationInput != null && toBody.equals(notStartedNotificationInput.getId())) { properties.put("tmpnotificationnotstarted", updateReassignmentAndNotificationInput(fromBody, "not-started")); } } } } } // else if(isBiDirectional) { // associationBuff.append(lhsAssociation).append("<->").append(rhsAssociation); // associationBuff.append(","); // biDirectionalAssociations.add(lhsAssociation + "," + rhsAssociation); // } else { if (lhsAssociation != null && lhsAssociation.length() > 0) { associationBuff.append("[din]" + lhsAssociation).append("->") .append(updateDataInputOutputDashes(rhsAssociation)); associationBuff.append(","); // Handle properties that have their independent input editors if (isCustomElement((String) properties.get("taskname"), preProcessingData)) { properties.put(rhsAssociation.toLowerCase(), lhsAssociation); } } uniDirectionalAssociations.add(lhsAssociation + "," + rhsAssociation); // if(contentDataInput != null) { // if(rhsAssociation.equals(contentDataInput.getName())) { // properties.put("content", lhsAssociation); // } // } } } } if (properties.get("tmpreassignmentnotcompleted") != null && ((String) properties.get("tmpreassignmentnotcompleted")).length() > 0 && properties.get("tmpreassignmentnotstarted") != null && ((String) properties.get("tmpreassignmentnotstarted")).length() > 0) { properties.put("reassignment", properties.get("tmpreassignmentnotcompleted") + "^" + properties.get("tmpreassignmentnotstarted")); } else if (properties.get("tmpreassignmentnotcompleted") != null && ((String) properties.get("tmpreassignmentnotcompleted")).length() > 0) { properties.put("reassignment", properties.get("tmpreassignmentnotcompleted")); } else if (properties.get("tmpreassignmentnotstarted") != null && ((String) properties.get("tmpreassignmentnotstarted")).length() > 0) { properties.put("reassignment", properties.get("tmpreassignmentnotstarted")); } if (properties.get("tmpnotificationnotcompleted") != null && ((String) properties.get("tmpnotificationnotcompleted")).length() > 0 && properties.get("tmpnotificationnotstarted") != null && ((String) properties.get("tmpnotificationnotstarted")).length() > 0) { properties.put("notifications", properties.get("tmpnotificationnotcompleted") + "^" + properties.get("tmpnotificationnotstarted")); } else if (properties.get("tmpnotificationnotcompleted") != null && ((String) properties.get("tmpnotificationnotcompleted")).length() > 0) { properties.put("notifications", properties.get("tmpnotificationnotcompleted")); } else if (properties.get("tmpnotificationnotstarted") != null && ((String) properties.get("tmpnotificationnotstarted")).length() > 0) { properties.put("notifications", properties.get("tmpnotificationnotstarted")); } for (DataOutputAssociation dataout : outputAssociations) { boolean proceed = true; if (task.getLoopCharacteristics() != null) { MultiInstanceLoopCharacteristics taskMultiLoop = (MultiInstanceLoopCharacteristics) task .getLoopCharacteristics(); // dont include associations that include mi loop data outputs if (taskMultiLoop.getOutputDataItem() != null && taskMultiLoop.getOutputDataItem().getId() != null) { if (dataout.getTargetRef().getId().equals(taskMultiLoop.getOutputDataItem().getId())) { proceed = false; } } // dont include associations that include loopDataOutputRef as source if (taskMultiLoop.getLoopDataOutputRef() != null) { if (dataout.getSourceRef().get(0).equals(taskMultiLoop.getLoopDataOutputRef())) { proceed = false; } } } if (proceed) { if (dataout.getSourceRef().size() > 0) { String lhsAssociation = ((DataOutput) dataout.getSourceRef().get(0)).getName(); String rhsAssociation = dataout.getTargetRef().getId(); boolean wasBiDirectional = false; // check if we already addressed this association as bidirectional // for(String bda : biDirectionalAssociations) { // String[] dbaparts = bda.split( ",\\s*" ); // if(dbaparts[0].equals(rhsAssociation) && dbaparts[1].equals(lhsAssociation)) { // wasBiDirectional = true; // break; // } // } if (dataout.getTransformation() != null && dataout.getTransformation().getBody() != null) { rhsAssociation = encodeAssociationValue(dataout.getTransformation().getBody()); } if (!wasBiDirectional) { if (lhsAssociation != null && lhsAssociation.length() > 0) { associationBuff.append("[dout]" + updateDataInputOutputDashes(lhsAssociation)) .append("->").append(rhsAssociation); associationBuff.append(","); } } } } } String assignmentString = associationBuff.toString(); if (assignmentString.endsWith(",")) { assignmentString = assignmentString.substring(0, assignmentString.length() - 1); } properties.put("assignments", assignmentString); // on-entry and on-exit actions marshallEntryExitActions(task, properties); // simulation properties setSimulationProperties(task.getId(), properties); // marshall the node out if (isCustomElement((String) properties.get("taskname"), preProcessingData)) { marshallNode(task, properties, (String) properties.get("taskname"), plane, generator, xOffset, yOffset); } else { marshallNode(task, properties, "Task", plane, generator, xOffset, yOffset); } } private void marshallEntryExitActions(BaseElement element, Map<String, Object> properties) { if (element.getExtensionValues() != null && element.getExtensionValues().size() > 0) { String onEntryStr = ""; String onExitStr = ""; for (ExtensionAttributeValue extattrval : element.getExtensionValues()) { FeatureMap extensionElements = extattrval.getValue(); @SuppressWarnings("unchecked") List<OnEntryScriptType> onEntryExtensions = (List<OnEntryScriptType>) extensionElements .get(DroolsPackage.Literals.DOCUMENT_ROOT__ON_ENTRY_SCRIPT, true); @SuppressWarnings("unchecked") List<OnExitScriptType> onExitExtensions = (List<OnExitScriptType>) extensionElements .get(DroolsPackage.Literals.DOCUMENT_ROOT__ON_EXIT_SCRIPT, true); for (OnEntryScriptType onEntryScript : onEntryExtensions) { if (onEntryScript.getScript() != null) { onEntryStr += onEntryScript.getScript().replace("\\", "\\\\").replace("\n", "\\n"); if (!onEntryStr.endsWith("\\n")) { onEntryStr += "\n"; } if (onEntryScript.getScriptFormat() != null) { String format = onEntryScript.getScriptFormat(); String formatToWrite = getScriptLanguageFormat(format); properties.put("script_language", formatToWrite); } } } for (OnExitScriptType onExitScript : onExitExtensions) { if (onExitScript.getScript() != null) { onExitStr += onExitScript.getScript().replace("\\", "\\\\").replace("\n", "\\n"); if (!onExitStr.endsWith("\\n")) { onExitStr += "\n"; } if (onExitScript.getScriptFormat() != null) { String format = onExitScript.getScriptFormat(); String formatToWrite = getScriptLanguageFormat(format); if (properties.get("script_language") == null) { properties.put("script_language", formatToWrite); } } } } } if (onEntryStr.length() > 0) { if (onEntryStr.endsWith("|")) { onEntryStr = onEntryStr.substring(0, onEntryStr.length() - 1); } properties.put("onentryactions", onEntryStr); } if (onExitStr.length() > 0) { if (onExitStr.endsWith("|")) { onExitStr = onExitStr.substring(0, onExitStr.length() - 1); } properties.put("onexitactions", onExitStr); } } } private String getScriptLanguageFormat(String fullQualifiedFormat) { return getScriptLanguageFormat(fullQualifiedFormat, "java"); } private String getScriptLanguageFormat(String fullQualifiedFormat, String defaultLanguage) { if (fullQualifiedFormat == null) { return ""; } else if (fullQualifiedFormat.equals("http://www.java.com/java")) { return "java"; } else if (fullQualifiedFormat.equals("http://www.mvel.org/2.0")) { return "mvel"; } else if (fullQualifiedFormat.equals("http://www.javascript.com/javascript")) { return "javascript"; } else if (fullQualifiedFormat.equals("http://www.jboss.org/drools/rule")) { return "drools"; } else if (fullQualifiedFormat.equals("http://www.omg.org/spec/FEEL/20140401")) { return "FEEL"; } else { return defaultLanguage; } } private void marshallDataInputSet(Activity activity, Map<String, Object> properties) { marshallDataInputSet(activity, properties, new ArrayList<String>()); } private void marshallDataInputSet(Activity activity, Map<String, Object> properties, List<String> disallowedNames) { if (activity.getIoSpecification() != null) { List<InputSet> inputSetList = activity.getIoSpecification().getInputSets(); StringBuilder dataInBuffer = new StringBuilder(); for (InputSet inset : inputSetList) { List<DataInput> dataInputList = inset.getDataInputRefs(); marshallItemAwareElements(activity, dataInputList, dataInBuffer, disallowedNames); } if (dataInBuffer.length() > 0) { dataInBuffer.setLength(dataInBuffer.length() - 1); } properties.put("datainputset", dataInBuffer.toString()); } } private void marshallDataOutputSet(Activity activity, Map<String, Object> properties) { marshallDataOutputSet(activity, properties, new ArrayList<String>()); } private void marshallDataOutputSet(Activity activity, Map<String, Object> properties, List<String> disallowedNames) { if (activity.getIoSpecification() != null) { List<OutputSet> outputSetList = activity.getIoSpecification().getOutputSets(); StringBuilder dataOutBuffer = new StringBuilder(); for (OutputSet outset : outputSetList) { List<DataOutput> dataOutputList = outset.getDataOutputRefs(); marshallItemAwareElements(activity, dataOutputList, dataOutBuffer, disallowedNames); } if (dataOutBuffer.length() > 0) { dataOutBuffer.setLength(dataOutBuffer.length() - 1); } properties.put("dataoutputset", dataOutBuffer.toString()); } } private void marshallItemAwareElements(Activity activity, List<? extends ItemAwareElement> elements, StringBuilder buffer, List<String> disallowedNames) { for (ItemAwareElement element : elements) { String name = null; if (element instanceof DataInput) { name = ((DataInput) element).getName(); } if (element instanceof DataOutput) { name = ((DataOutput) element).getName(); } if (name != null && !name.isEmpty() && !disallowedNames.contains(name)) { buffer.append(name); if (element.getItemSubjectRef() != null && element.getItemSubjectRef().getStructureRef() != null && !element.getItemSubjectRef().getStructureRef().isEmpty()) { buffer.append(":").append(element.getItemSubjectRef().getStructureRef()); } else if (activity.eContainer() instanceof SubProcess) { // BZ1247105: for Outputs on Tasks inside sub-processes String dtype = getAnyAttributeValue(element, "dtype"); if (dtype != null && !dtype.isEmpty()) { buffer.append(":").append(dtype); } } buffer.append(","); } } } protected void marshallParallelGateway(ParallelGateway gateway, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { marshallNode(gateway, flowElementProperties, "ParallelGateway", plane, generator, xOffset, yOffset); } protected void marshallExclusiveGateway(ExclusiveGateway gateway, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { if (gateway.getDefault() != null) { SequenceFlow defsf = gateway.getDefault(); String defGatewayStr = ""; if (defsf.getName() != null && defsf.getName().length() > 0) { defGatewayStr = defsf.getName() + " : " + defsf.getId(); } else { defGatewayStr = defsf.getId(); } flowElementProperties.put("defaultgate", defGatewayStr); } marshallNode(gateway, flowElementProperties, "Exclusive_Databased_Gateway", plane, generator, xOffset, yOffset); } protected void marshallInclusiveGateway(InclusiveGateway gateway, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { if (gateway.getDefault() != null) { SequenceFlow defsf = gateway.getDefault(); String defGatewayStr = ""; if (defsf.getName() != null && defsf.getName().length() > 0) { defGatewayStr = defsf.getName() + " : " + defsf.getId(); } else { defGatewayStr = defsf.getId(); } flowElementProperties.put("defaultgate", defGatewayStr); } marshallNode(gateway, flowElementProperties, "InclusiveGateway", plane, generator, xOffset, yOffset); } protected void marshallEventBasedGateway(EventBasedGateway gateway, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { marshallNode(gateway, flowElementProperties, "EventbasedGateway", plane, generator, xOffset, yOffset); } protected void marshallComplexGateway(ComplexGateway gateway, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { marshallNode(gateway, flowElementProperties, "ComplexGateway", plane, generator, xOffset, yOffset); } protected void marshallNode(FlowNode node, Map<String, Object> properties, String stencil, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset) throws JsonGenerationException, IOException { if (properties == null) { properties = new LinkedHashMap<String, Object>(); } if (node.getDocumentation() != null && node.getDocumentation().size() > 0) { properties.put("documentation", node.getDocumentation().get(0).getText()); } if (node.getName() != null) { properties.put("name", unescapeXml(node.getName())); } else { if (node instanceof TextAnnotation) { if (((TextAnnotation) node).getText() != null) { properties.put("name", ((TextAnnotation) node).getText()); } else { properties.put("name", ""); } } else { properties.put("name", ""); } } // overwrite name if elementname extension element is present String elementName = Utils.getMetaDataValue(node.getExtensionValues(), "elementname"); if (elementName != null) { properties.put("name", elementName); } marshallProperties(properties, generator); generator.writeObjectFieldStart("stencil"); generator.writeObjectField("id", stencil); generator.writeEndObject(); generator.writeArrayFieldStart("childShapes"); generator.writeEndArray(); generator.writeArrayFieldStart("outgoing"); for (SequenceFlow outgoing : node.getOutgoing()) { generator.writeStartObject(); generator.writeObjectField("resourceId", outgoing.getId()); generator.writeEndObject(); } // we need to also add associations as outgoing elements Process process = (Process) plane.getBpmnElement(); writeAssociations(process, node.getId(), generator); // and boundary events for activities List<BoundaryEvent> boundaryEvents = new ArrayList<BoundaryEvent>(); findBoundaryEvents(process, boundaryEvents); for (BoundaryEvent be : boundaryEvents) { if (be.getAttachedToRef().getId().equals(node.getId())) { generator.writeStartObject(); generator.writeObjectField("resourceId", be.getId()); generator.writeEndObject(); } } generator.writeEndArray(); // boundary events have a docker if (node instanceof BoundaryEvent) { Iterator<FeatureMap.Entry> iter = node.getAnyAttribute().iterator(); boolean foundDockerInfo = false; while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("dockerinfo")) { foundDockerInfo = true; String dockerInfoStr = String.valueOf(entry.getValue()); if (dockerInfoStr != null && dockerInfoStr.length() > 0) { if (dockerInfoStr.endsWith("|")) { dockerInfoStr = dockerInfoStr.substring(0, dockerInfoStr.length() - 1); String[] dockerInfoParts = dockerInfoStr.split("\\|"); String infoPartsToUse = dockerInfoParts[0]; String[] infoPartsToUseParts = infoPartsToUse.split("\\^"); if (infoPartsToUseParts != null && infoPartsToUseParts.length > 0) { generator.writeArrayFieldStart("dockers"); generator.writeStartObject(); generator.writeObjectField("x", Double.valueOf(infoPartsToUseParts[0])); generator.writeObjectField("y", Double.valueOf(infoPartsToUseParts[1])); generator.writeEndObject(); generator.writeEndArray(); } } } } } // backwards compatibility to older versions -- BZ 1196259 if (!foundDockerInfo) { // find the edge associated with this boundary event for (DiagramElement element : plane.getPlaneElement()) { if (element instanceof BPMNEdge && ((BPMNEdge) element).getBpmnElement() == node) { List<Point> waypoints = ((BPMNEdge) element).getWaypoint(); if (waypoints != null && waypoints.size() > 0) { // one per boundary event Point p = waypoints.get(0); if (p != null) { generator.writeArrayFieldStart("dockers"); generator.writeStartObject(); generator.writeObjectField("x", p.getX()); generator.writeObjectField("y", p.getY()); generator.writeEndObject(); generator.writeEndArray(); } } } } } } BPMNShape shape = (BPMNShape) findDiagramElement(plane, node); Bounds bounds = shape.getBounds(); correctEventNodeSize(shape); generator.writeObjectFieldStart("bounds"); generator.writeObjectFieldStart("lowerRight"); generator.writeObjectField("x", bounds.getX() + bounds.getWidth() - xOffset); generator.writeObjectField("y", bounds.getY() + bounds.getHeight() - yOffset); generator.writeEndObject(); generator.writeObjectFieldStart("upperLeft"); generator.writeObjectField("x", bounds.getX() - xOffset); generator.writeObjectField("y", bounds.getY() - yOffset); generator.writeEndObject(); generator.writeEndObject(); } private void correctEventNodeSize(BPMNShape shape) { BaseElement element = shape.getBpmnElement(); if (element instanceof Event) { // // do not "fix" events as they shape is circle - leave bounds as is // Bounds bounds = shape.getBounds(); // float width = bounds.getWidth(); // float height = bounds.getHeight(); // if (width != 30 || height != 30) { // bounds.setWidth(30); // bounds.setHeight(30); // float x = bounds.getX(); // float y = bounds.getY(); // x = x - ((30 - width)/2); // y = y - ((30 - height)/2); // bounds.setX(x); // bounds.setY(y); // } } else if (element instanceof Gateway) { Bounds bounds = shape.getBounds(); float width = bounds.getWidth(); float height = bounds.getHeight(); if (width != 40 || height != 40) { bounds.setWidth(40); bounds.setHeight(40); float x = bounds.getX(); float y = bounds.getY(); x = x - ((40 - width) / 2); y = y - ((40 - height) / 2); bounds.setX(x); bounds.setY(y); } } } protected void marshallDataObject(DataObject dataObject, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { Map<String, Object> properties = new LinkedHashMap<String, Object>(flowElementProperties); if (dataObject.getDocumentation() != null && dataObject.getDocumentation().size() > 0) { properties.put("documentation", dataObject.getDocumentation().get(0).getText()); } if (dataObject.getName() != null && dataObject.getName().length() > 0) { properties.put("name", unescapeXml(dataObject.getName())); } else { // we need a name, use id instead properties.put("name", dataObject.getId()); } // overwrite name if elementname extension element is present String elementName = Utils.getMetaDataValue(dataObject.getExtensionValues(), "elementname"); if (elementName != null) { properties.put("name", elementName); } if (dataObject.getItemSubjectRef().getStructureRef() != null && dataObject.getItemSubjectRef().getStructureRef().length() > 0) { if (defaultTypesList.contains(dataObject.getItemSubjectRef().getStructureRef())) { properties.put("standardtype", dataObject.getItemSubjectRef().getStructureRef()); } else { properties.put("customtype", dataObject.getItemSubjectRef().getStructureRef()); } } Association outgoingAssociaton = findOutgoingAssociation(plane, dataObject); Association incomingAssociation = null; Process process = (Process) plane.getBpmnElement(); for (Artifact artifact : process.getArtifacts()) { if (artifact instanceof Association) { Association association = (Association) artifact; if (association.getTargetRef() == dataObject) { incomingAssociation = association; } } } if (outgoingAssociaton != null && incomingAssociation == null) { properties.put("input_output", "Input"); } if (outgoingAssociaton == null && incomingAssociation != null) { properties.put("input_output", "Output"); } marshallProperties(properties, generator); generator.writeObjectFieldStart("stencil"); generator.writeObjectField("id", "DataObject"); generator.writeEndObject(); generator.writeArrayFieldStart("childShapes"); generator.writeEndArray(); generator.writeArrayFieldStart("outgoing"); List<Association> associations = findOutgoingAssociations(plane, dataObject); if (associations != null) { for (Association as : associations) { generator.writeStartObject(); generator.writeObjectField("resourceId", as.getId()); generator.writeEndObject(); } } generator.writeEndArray(); Bounds bounds = ((BPMNShape) findDiagramElement(plane, dataObject)).getBounds(); generator.writeObjectFieldStart("bounds"); generator.writeObjectFieldStart("lowerRight"); generator.writeObjectField("x", bounds.getX() + bounds.getWidth() - xOffset); generator.writeObjectField("y", bounds.getY() + bounds.getHeight() - yOffset); generator.writeEndObject(); generator.writeObjectFieldStart("upperLeft"); generator.writeObjectField("x", bounds.getX() - xOffset); generator.writeObjectField("y", bounds.getY() - yOffset); generator.writeEndObject(); generator.writeEndObject(); } protected void marshallSubProcess(SubProcess subProcess, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, String preProcessingData, Definitions def, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { Map<String, Object> properties = new LinkedHashMap<String, Object>(flowElementProperties); if (subProcess.getName() != null) { properties.put("name", unescapeXml(subProcess.getName())); } else { properties.put("name", ""); } // overwrite name if elementname extension element is present String elementName = Utils.getMetaDataValue(subProcess.getExtensionValues(), "elementname"); if (elementName != null) { properties.put("name", elementName); } if (subProcess.getDocumentation() != null && subProcess.getDocumentation().size() > 0) { properties.put("documentation", subProcess.getDocumentation().get(0).getText()); } if (subProcess instanceof AdHocSubProcess) { AdHocSubProcess ahsp = (AdHocSubProcess) subProcess; if (ahsp.getOrdering().equals(AdHocOrdering.PARALLEL)) { properties.put("adhocordering", "Parallel"); } else if (ahsp.getOrdering().equals(AdHocOrdering.SEQUENTIAL)) { properties.put("adhocordering", "Sequential"); } else { // default to parallel properties.put("adhocordering", "Parallel"); } if (ahsp.getCompletionCondition() != null) { try { FormalExpression completionExpression = (FormalExpression) ahsp.getCompletionCondition(); if (completionExpression != null) { properties.put("adhoccompletioncondition", completionExpression.getBody().replaceAll("\n", "\\\\n")); if (completionExpression.getLanguage() != null) { String completionLanguage = getScriptLanguageFormat(completionExpression.getLanguage()); properties.put("script_language", completionLanguage); } } } catch (Exception e) { _logger.info("Could not find adhoccompletioncondition for: " + ahsp); } } final String customActivationCondition = Utils.getMetaDataValue(ahsp.getExtensionValues(), "customActivationCondition"); if (customActivationCondition != null && customActivationCondition.length() > 0) { properties.put("adhocactivationcondition", customActivationCondition); } } // custom async String customAsyncMetaData = Utils.getMetaDataValue(subProcess.getExtensionValues(), "customAsync"); String customAsync = (customAsyncMetaData != null && customAsyncMetaData.length() > 0) ? customAsyncMetaData : "false"; properties.put("isasync", customAsync); // custom SLA due date marshalCustomSLADueDateMetadata(subProcess, properties); // data inputs marshallDataInputSet(subProcess, properties); // data outputs marshallDataOutputSet(subProcess, properties); // assignments StringBuilder associationBuff = new StringBuilder(); List<DataInputAssociation> inputAssociations = subProcess.getDataInputAssociations(); List<DataOutputAssociation> outputAssociations = subProcess.getDataOutputAssociations(); marshallDataInputAssociations(associationBuff, inputAssociations); marshallDataOutputAssociations(associationBuff, outputAssociations); String assignmentString = associationBuff.toString(); if (assignmentString.endsWith(",")) { assignmentString = assignmentString.substring(0, assignmentString.length() - 1); } properties.put("assignments", assignmentString); // on-entry and on-exit actions marshallEntryExitActions(subProcess, properties); // loop characteristics boolean haveValidLoopCharacteristics = false; if (subProcess.getLoopCharacteristics() != null && subProcess.getLoopCharacteristics() instanceof MultiInstanceLoopCharacteristics) { haveValidLoopCharacteristics = true; properties.put("mitrigger", "true"); MultiInstanceLoopCharacteristics taskmi = (MultiInstanceLoopCharacteristics) subProcess .getLoopCharacteristics(); if (taskmi.getLoopDataInputRef() != null) { ItemAwareElement iedatainput = taskmi.getLoopDataInputRef(); List<DataInputAssociation> taskInputAssociations = subProcess.getDataInputAssociations(); for (DataInputAssociation dia : taskInputAssociations) { if (dia.getTargetRef().equals(iedatainput)) { properties.put("multipleinstancecollectioninput", dia.getSourceRef().get(0).getId()); break; } } } if (taskmi.getLoopDataOutputRef() != null) { ItemAwareElement iedataoutput = taskmi.getLoopDataOutputRef(); List<DataOutputAssociation> taskOutputAssociations = subProcess.getDataOutputAssociations(); for (DataOutputAssociation dout : taskOutputAssociations) { if (dout.getSourceRef().get(0).equals(iedataoutput)) { properties.put("multipleinstancecollectionoutput", dout.getTargetRef().getId()); break; } } } if (taskmi.getInputDataItem() != null) { List<DataInput> taskDataInputs = subProcess.getIoSpecification().getDataInputs(); for (DataInput din : taskDataInputs) { if (din.getItemSubjectRef() == null) { // for backward compatibility as the where only input supported properties.put("multipleinstancedatainput", taskmi.getInputDataItem().getId()); } if (din.getItemSubjectRef() != null && din.getItemSubjectRef().getId() .equals(taskmi.getInputDataItem().getItemSubjectRef().getId())) { properties.put("multipleinstancedatainput", din.getName()); break; } } } if (taskmi.getOutputDataItem() != null) { List<DataOutput> taskDataOutputs = subProcess.getIoSpecification().getDataOutputs(); for (DataOutput dout : taskDataOutputs) { if (dout.getItemSubjectRef() == null) { properties.put("multipleinstancedataoutput", taskmi.getOutputDataItem().getId()); break; } if (dout.getItemSubjectRef() != null && dout.getItemSubjectRef().getId() .equals(taskmi.getOutputDataItem().getItemSubjectRef().getId())) { properties.put("multipleinstancedataoutput", dout.getName()); break; } } } if (taskmi.getCompletionCondition() != null) { try { if (taskmi.getCompletionCondition() instanceof FormalExpression) { properties.put("multipleinstancecompletioncondition", ((FormalExpression) taskmi.getCompletionCondition()).getBody()); } } catch (Exception e) { _logger.info("Could not find multipleinstancecompletioncondition for : " + taskmi); } } } // properties List<Property> processProperties = subProcess.getProperties(); if (processProperties != null && processProperties.size() > 0) { String propVal = ""; for (int i = 0; i < processProperties.size(); i++) { Property p = processProperties.get(i); String pKPI = Utils.getMetaDataValue(p.getExtensionValues(), "customKPI"); propVal += p.getId(); // check the structureRef value if (p.getItemSubjectRef() != null && p.getItemSubjectRef().getStructureRef() != null) { propVal += ":" + p.getItemSubjectRef().getStructureRef(); } if (pKPI != null && pKPI.length() > 0) { propVal += ":" + pKPI; } if (i != processProperties.size() - 1) { propVal += ","; } } properties.put("vardefs", propVal); } // simulation properties setSimulationProperties(subProcess.getId(), properties); marshallProperties(properties, generator); generator.writeObjectFieldStart("stencil"); if (subProcess instanceof AdHocSubProcess) { generator.writeObjectField("id", "AdHocSubprocess"); } else { if (subProcess.isTriggeredByEvent()) { generator.writeObjectField("id", "EventSubprocess"); } else { if (haveValidLoopCharacteristics) { generator.writeObjectField("id", "MultipleInstanceSubprocess"); } else { generator.writeObjectField("id", "Subprocess"); } } } generator.writeEndObject(); generator.writeArrayFieldStart("childShapes"); Bounds bounds = ((BPMNShape) findDiagramElement(plane, subProcess)).getBounds(); for (FlowElement flowElement : subProcess.getFlowElements()) { if (coordianteManipulation) { marshallFlowElement(flowElement, plane, generator, bounds.getX(), bounds.getY(), preProcessingData, def); } else { marshallFlowElement(flowElement, plane, generator, 0, 0, preProcessingData, def); } } for (Artifact artifact : subProcess.getArtifacts()) { if (coordianteManipulation) { marshallArtifact(artifact, plane, generator, bounds.getX(), bounds.getY(), preProcessingData, def); } else { marshallArtifact(artifact, plane, generator, 0, 0, preProcessingData, def); } } generator.writeEndArray(); generator.writeArrayFieldStart("outgoing"); for (BoundaryEvent boundaryEvent : subProcess.getBoundaryEventRefs()) { generator.writeStartObject(); generator.writeObjectField("resourceId", boundaryEvent.getId()); generator.writeEndObject(); } for (SequenceFlow outgoing : subProcess.getOutgoing()) { generator.writeStartObject(); generator.writeObjectField("resourceId", outgoing.getId()); generator.writeEndObject(); } Process process = (Process) plane.getBpmnElement(); writeAssociations(process, subProcess.getId(), generator); // subprocess boundary events List<BoundaryEvent> boundaryEvents = new ArrayList<BoundaryEvent>(); findBoundaryEvents(process, boundaryEvents); for (BoundaryEvent be : boundaryEvents) { if (be.getAttachedToRef().getId().equals(subProcess.getId())) { generator.writeStartObject(); generator.writeObjectField("resourceId", be.getId()); generator.writeEndObject(); } } generator.writeEndArray(); generator.writeObjectFieldStart("bounds"); generator.writeObjectFieldStart("lowerRight"); generator.writeObjectField("x", bounds.getX() + bounds.getWidth() - xOffset); generator.writeObjectField("y", bounds.getY() + bounds.getHeight() - yOffset); generator.writeEndObject(); generator.writeObjectFieldStart("upperLeft"); generator.writeObjectField("x", bounds.getX() - xOffset); generator.writeObjectField("y", bounds.getY() - yOffset); generator.writeEndObject(); generator.writeEndObject(); } private void writeAssociations(Process process, String elementId, JsonGenerator generator) throws IOException { for (Artifact artifact : process.getArtifacts()) { if (artifact instanceof Association) { Association association = (Association) artifact; if (association.getSourceRef().getId().equals(elementId)) { generator.writeStartObject(); generator.writeObjectField("resourceId", association.getId()); generator.writeEndObject(); } } } } private void marshallDataOutputAssociations(StringBuilder associationBuff, List<DataOutputAssociation> outputAssociations) { if (outputAssociations != null) { for (DataOutputAssociation dataout : outputAssociations) { if (dataout.getSourceRef().size() > 0) { String lhsAssociation = ((DataOutput) dataout.getSourceRef().get(0)).getName(); String rhsAssociation = dataout.getTargetRef().getId(); if (dataout.getTransformation() != null && dataout.getTransformation().getBody() != null) { rhsAssociation = encodeAssociationValue(dataout.getTransformation().getBody()); } if (lhsAssociation != null && lhsAssociation.length() > 0) { associationBuff.append("[dout]" + updateDataInputOutputDashes(lhsAssociation)).append("->") .append(rhsAssociation); associationBuff.append(","); } } } } } private void marshallDataInputAssociations(StringBuilder associationBuff, List<DataInputAssociation> inputAssociations) { if (inputAssociations != null) { for (DataInputAssociation datain : inputAssociations) { String lhsAssociation = ""; if (datain.getSourceRef() != null && datain.getSourceRef().size() > 0) { if (datain.getTransformation() != null && datain.getTransformation().getBody() != null) { lhsAssociation = datain.getTransformation().getBody(); } else { lhsAssociation = datain.getSourceRef().get(0).getId(); } } String rhsAssociation = ""; if (datain.getTargetRef() != null) { rhsAssociation = ((DataInput) datain.getTargetRef()).getName(); } //boolean isBiDirectional = false; boolean isAssignment = false; if (datain.getAssignment() != null && datain.getAssignment().size() > 0) { isAssignment = true; } if (isAssignment) { // only know how to deal with formal expressions if (datain.getAssignment().get(0).getFrom() instanceof FormalExpression) { String associationValue = ((FormalExpression) datain.getAssignment().get(0).getFrom()) .getBody(); if (associationValue == null) { associationValue = ""; } String replacer = encodeAssociationValue(updateDataInputOutputDashes(associationValue)); associationBuff.append("[din]" + rhsAssociation).append("=").append(replacer); associationBuff.append(","); } } else { if (lhsAssociation != null && lhsAssociation.length() > 0) { associationBuff.append("[din]" + lhsAssociation).append("->") .append(updateDataInputOutputDashes(rhsAssociation)); associationBuff.append(","); } } } } } protected void marshallSequenceFlow(SequenceFlow sequenceFlow, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset) throws JsonGenerationException, IOException { // dont marshal "dangling" sequence flow..better to just omit than fail if (sequenceFlow.getSourceRef() == null || sequenceFlow.getTargetRef() == null) { return; } Map<String, Object> properties = new LinkedHashMap<String, Object>(); // check null for sequence flow name if (sequenceFlow.getName() != null && !"".equals(sequenceFlow.getName())) { properties.put("name", unescapeXml(sequenceFlow.getName())); } else { properties.put("name", ""); } // overwrite name if elementname extension element is present String elementName = Utils.getMetaDataValue(sequenceFlow.getExtensionValues(), "elementname"); if (elementName != null) { properties.put("name", elementName); } if (sequenceFlow.getDocumentation() != null && sequenceFlow.getDocumentation().size() > 0) { properties.put("documentation", sequenceFlow.getDocumentation().get(0).getText()); } if (sequenceFlow.isIsImmediate()) { properties.put("isimmediate", "true"); } else { properties.put("isimmediate", "false"); } Expression conditionExpression = sequenceFlow.getConditionExpression(); try { if (conditionExpression instanceof FormalExpression) { if (((FormalExpression) conditionExpression).getBody() != null) { properties.put("conditionexpression", ((FormalExpression) conditionExpression).getBody().replaceAll("\n", "\\\\n")); } if (((FormalExpression) conditionExpression).getLanguage() != null) { String cd = ((FormalExpression) conditionExpression).getLanguage(); String cdStr = getScriptLanguageFormat(cd, "mvel"); properties.put("conditionexpressionlanguage", cdStr); } } } catch (Exception e) { _logger.info("Could not find conditionexpression for : " + conditionExpression); } boolean foundBgColor = false; boolean foundBrColor = false; boolean foundFontColor = false; boolean foundSelectable = false; Iterator<FeatureMap.Entry> iter = sequenceFlow.getAnyAttribute().iterator(); while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("priority")) { String priorityStr = String.valueOf(entry.getValue()); if (priorityStr != null) { try { Integer priorityInt = Integer.parseInt(priorityStr); if (priorityInt >= 1) { properties.put("priority", entry.getValue()); } else { _logger.error("Priority must be equal or greater than 1."); } } catch (NumberFormatException e) { _logger.error("Priority must be a number."); } } } if (entry.getEStructuralFeature().getName().equals("background-color") || entry.getEStructuralFeature().getName().equals("bgcolor")) { properties.put("bgcolor", entry.getValue()); foundBgColor = true; } if (entry.getEStructuralFeature().getName().equals("border-color") || entry.getEStructuralFeature().getName().equals("bordercolor")) { properties.put("bordercolor", entry.getValue()); foundBrColor = true; } if (entry.getEStructuralFeature().getName().equals("fontsize")) { properties.put("fontsize", entry.getValue()); foundBrColor = true; } if (entry.getEStructuralFeature().getName().equals("color") || entry.getEStructuralFeature().getName().equals("fontcolor")) { properties.put("fontcolor", entry.getValue()); foundFontColor = true; } if (entry.getEStructuralFeature().getName().equals("selectable")) { properties.put("isselectable", entry.getValue()); foundSelectable = true; } } if (!foundBgColor) { properties.put("bgcolor", defaultSequenceflowColor); } if (!foundBrColor) { properties.put("bordercolor", defaultSequenceflowColor); } if (!foundFontColor) { properties.put("fontcolor", defaultSequenceflowColor); } if (!foundSelectable) { properties.put("isselectable", "true"); } // simulation properties setSimulationProperties(sequenceFlow.getId(), properties); marshallProperties(properties, generator); generator.writeObjectFieldStart("stencil"); generator.writeObjectField("id", "SequenceFlow"); generator.writeEndObject(); generator.writeArrayFieldStart("childShapes"); generator.writeEndArray(); generator.writeArrayFieldStart("outgoing"); generator.writeStartObject(); generator.writeObjectField("resourceId", sequenceFlow.getTargetRef().getId()); generator.writeEndObject(); generator.writeEndArray(); Bounds sourceBounds = ((BPMNShape) findDiagramElement(plane, sequenceFlow.getSourceRef())).getBounds(); Bounds targetBounds = ((BPMNShape) findDiagramElement(plane, sequenceFlow.getTargetRef())).getBounds(); generator.writeArrayFieldStart("dockers"); generator.writeStartObject(); generator.writeObjectField("x", sourceBounds.getWidth() / 2); generator.writeObjectField("y", sourceBounds.getHeight() / 2); generator.writeEndObject(); List<Point> waypoints = ((BPMNEdge) findDiagramElement(plane, sequenceFlow)).getWaypoint(); for (int i = 1; i < waypoints.size() - 1; i++) { Point waypoint = waypoints.get(i); generator.writeStartObject(); generator.writeObjectField("x", waypoint.getX()); generator.writeObjectField("y", waypoint.getY()); generator.writeEndObject(); } generator.writeStartObject(); generator.writeObjectField("x", targetBounds.getWidth() / 2); generator.writeObjectField("y", targetBounds.getHeight() / 2); generator.writeEndObject(); generator.writeEndArray(); } private DiagramElement findDiagramElement(BPMNPlane plane, BaseElement baseElement) { DiagramElement result = _diagramElements.get(baseElement.getId()); if (result != null) { return result; } for (DiagramElement element : plane.getPlaneElement()) { if ((element instanceof BPMNEdge && ((BPMNEdge) element).getBpmnElement() == baseElement) || (element instanceof BPMNShape && ((BPMNShape) element).getBpmnElement() == baseElement)) { _diagramElements.put(baseElement.getId(), element); return element; } } _logger.info("Could not find BPMNDI information for " + baseElement); return null; } protected void marshallGlobalTask(GlobalTask globalTask, JsonGenerator generator) { if (globalTask instanceof GlobalBusinessRuleTask) { } else if (globalTask instanceof GlobalManualTask) { } else if (globalTask instanceof GlobalScriptTask) { } else if (globalTask instanceof GlobalUserTask) { } else { } } protected void marshallGlobalChoreographyTask(GlobalChoreographyTask callableElement, JsonGenerator generator) { throw new UnsupportedOperationException("TODO"); //TODO! } protected void marshallConversation(Conversation callableElement, JsonGenerator generator) { throw new UnsupportedOperationException("TODO"); //TODO! } protected void marshallChoreography(Choreography callableElement, JsonGenerator generator) { throw new UnsupportedOperationException("TODO"); //TODO! } protected void marshallProperties(Map<String, Object> properties, JsonGenerator generator) throws JsonGenerationException, IOException { generator.writeObjectFieldStart("properties"); for (Entry<String, Object> entry : properties.entrySet()) { generator.writeObjectField(entry.getKey(), String.valueOf(entry.getValue())); } generator.writeEndObject(); } protected void marshallArtifact(Artifact artifact, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, String preProcessingData, Definitions def) throws IOException { generator.writeStartObject(); generator.writeObjectField("resourceId", artifact.getId()); if (artifact instanceof Association) { marshallAssociation((Association) artifact, plane, generator, xOffset, yOffset, preProcessingData, def); } else if (artifact instanceof Group) { marshallGroup((Group) artifact, plane, generator, xOffset, yOffset, preProcessingData, def); } generator.writeEndObject(); } protected void marshallAssociation(Association association, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, String preProcessingData, Definitions def) throws JsonGenerationException, IOException { Map<String, Object> properties = new LinkedHashMap<String, Object>(); Iterator<FeatureMap.Entry> iter = association.getAnyAttribute().iterator(); boolean foundBrColor = false; while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (entry.getEStructuralFeature().getName().equals("type")) { properties.put("type", entry.getValue()); } if (entry.getEStructuralFeature().getName().equals("bordercolor")) { properties.put("bordercolor", entry.getValue()); foundBrColor = true; } } if (!foundBrColor) { properties.put("bordercolor", defaultSequenceflowColor); } if (association.getDocumentation() != null && association.getDocumentation().size() > 0) { properties.put("documentation", association.getDocumentation().get(0).getText()); } marshallProperties(properties, generator); generator.writeObjectFieldStart("stencil"); if (association.getAssociationDirection().equals(AssociationDirection.ONE)) { generator.writeObjectField("id", "Association_Unidirectional"); } else if (association.getAssociationDirection().equals(AssociationDirection.BOTH)) { generator.writeObjectField("id", "Association_Bidirectional"); } else { generator.writeObjectField("id", "Association_Undirected"); } generator.writeEndObject(); generator.writeArrayFieldStart("childShapes"); generator.writeEndArray(); generator.writeArrayFieldStart("outgoing"); generator.writeStartObject(); generator.writeObjectField("resourceId", association.getTargetRef().getId()); generator.writeEndObject(); generator.writeEndArray(); Bounds sourceBounds = ((BPMNShape) findDiagramElement(plane, association.getSourceRef())).getBounds(); Bounds targetBounds = null; float tbx = 0; float tby = 0; if (findDiagramElement(plane, association.getTargetRef()) instanceof BPMNShape) { targetBounds = ((BPMNShape) findDiagramElement(plane, association.getTargetRef())).getBounds(); } else if (findDiagramElement(plane, association.getTargetRef()) instanceof BPMNEdge) { // connect it to first waypoint on edge List<Point> waypoints = ((BPMNEdge) findDiagramElement(plane, association.getTargetRef())) .getWaypoint(); if (waypoints != null && waypoints.size() > 0) { tbx = waypoints.get(0).getX(); tby = waypoints.get(0).getY(); } } generator.writeArrayFieldStart("dockers"); generator.writeStartObject(); generator.writeObjectField("x", sourceBounds.getWidth() / 2); generator.writeObjectField("y", sourceBounds.getHeight() / 2); generator.writeEndObject(); List<Point> waypoints = ((BPMNEdge) findDiagramElement(plane, association)).getWaypoint(); for (int i = 1; i < waypoints.size() - 1; i++) { Point waypoint = waypoints.get(i); generator.writeStartObject(); generator.writeObjectField("x", waypoint.getX()); generator.writeObjectField("y", waypoint.getY()); generator.writeEndObject(); } if (targetBounds != null) { generator.writeStartObject(); // text annotations have to be treated specia if (association.getTargetRef() instanceof TextAnnotation) { generator.writeObjectField("x", 1); generator.writeObjectField("y", targetBounds.getHeight() / 2); } else { generator.writeObjectField("x", targetBounds.getWidth() / 2); generator.writeObjectField("y", targetBounds.getHeight() / 2); } generator.writeEndObject(); generator.writeEndArray(); } else { generator.writeStartObject(); generator.writeObjectField("x", tbx); generator.writeObjectField("y", tby); generator.writeEndObject(); generator.writeEndArray(); } } protected void marshallTextAnnotation(TextAnnotation textAnnotation, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, String preProcessingData, Definitions def, Map<String, Object> flowElementProperties) throws JsonGenerationException, IOException { flowElementProperties.put("name", textAnnotation.getText()); // overwrite name if elementname extension element is present String elementName = Utils.getMetaDataValue(textAnnotation.getExtensionValues(), "elementname"); if (elementName != null) { flowElementProperties.put("name", elementName); } if (textAnnotation.getDocumentation() != null && textAnnotation.getDocumentation().size() > 0) { flowElementProperties.put("documentation", textAnnotation.getDocumentation().get(0).getText()); } flowElementProperties.put("artifacttype", "Annotation"); marshallNode(textAnnotation, flowElementProperties, "TextAnnotation", plane, generator, xOffset, yOffset); } protected void marshallGroup(Group group, BPMNPlane plane, JsonGenerator generator, float xOffset, float yOffset, String preProcessingData, Definitions def) throws JsonGenerationException, IOException { Map<String, Object> properties = new LinkedHashMap<>(); if (group.getCategoryValueRef() != null && group.getCategoryValueRef().getValue() != null) { properties.put("name", unescapeXml(group.getCategoryValueRef().getValue())); } Documentation doc = getDocumentation(group); if (doc != null) { properties.put("documentation", doc.getText()); } marshallProperties(properties, generator); generator.writeObjectFieldStart("stencil"); generator.writeObjectField("id", "Group"); generator.writeEndObject(); generator.writeArrayFieldStart("childShapes"); generator.writeEndArray(); generator.writeArrayFieldStart("outgoing"); if (findOutgoingAssociation(plane, group) != null) { generator.writeStartObject(); generator.writeObjectField("resourceId", findOutgoingAssociation(plane, group).getId()); generator.writeEndObject(); } generator.writeEndArray(); Bounds bounds = ((BPMNShape) findDiagramElement(plane, group)).getBounds(); generator.writeObjectFieldStart("bounds"); generator.writeObjectFieldStart("lowerRight"); generator.writeObjectField("x", bounds.getX() + bounds.getWidth() - xOffset); generator.writeObjectField("y", bounds.getY() + bounds.getHeight() - yOffset); generator.writeEndObject(); generator.writeObjectFieldStart("upperLeft"); generator.writeObjectField("x", bounds.getX() - xOffset); generator.writeObjectField("y", bounds.getY() - yOffset); generator.writeEndObject(); generator.writeEndObject(); } private Documentation getDocumentation(BaseElement element) { if (element.getDocumentation() != null && element.getDocumentation().size() > 0) { return element.getDocumentation().get(0); } else { return null; } } protected Association findOutgoingAssociation(BPMNPlane plane, BaseElement baseElement) { Association result = _diagramAssociations.get(baseElement.getId()); if (result != null) { return result; } if (!(plane.getBpmnElement() instanceof Process)) { throw new IllegalArgumentException("Don't know how to get associations from a non-Process Diagram"); } Process process = (Process) plane.getBpmnElement(); for (Artifact artifact : process.getArtifacts()) { if (artifact instanceof Association) { Association association = (Association) artifact; if (association.getSourceRef() == baseElement) { _diagramAssociations.put(baseElement.getId(), association); return association; } } } return null; } protected List<Association> findOutgoingAssociations(BPMNPlane plane, BaseElement baseElement) { List<Association> retList = new ArrayList<Association>(); if (!(plane.getBpmnElement() instanceof Process)) { throw new IllegalArgumentException("Don't know how to get associations from a non-Process Diagram"); } Process process = (Process) plane.getBpmnElement(); for (Artifact artifact : process.getArtifacts()) { if (artifact instanceof Association) { Association association = (Association) artifact; if (association.getSourceRef() == baseElement) { retList.add(association); } } } return retList; } protected void marshallStencil(String stencilId, JsonGenerator generator) throws JsonGenerationException, IOException { generator.writeObjectFieldStart("stencil"); generator.writeObjectField("id", stencilId); generator.writeEndObject(); } private boolean isCustomElement(String taskType, String preProcessingData) { if (taskType != null && taskType.length() > 0 && preProcessingData != null && preProcessingData.length() > 0) { String[] preProcessingDataElements = preProcessingData.split(",\\s*"); for (String preProcessingDataElement : preProcessingDataElements) { if (taskType.equals(preProcessingDataElement)) { return true; } } } return false; } private String updateReassignmentAndNotificationInput(String inputStr, String type) { if (inputStr != null && inputStr.length() > 0) { String ret = ""; String[] parts = inputStr.split("\\^\\s*"); for (String nextPart : parts) { ret += nextPart + "@" + type + "^"; } if (ret.endsWith("^")) { ret = ret.substring(0, ret.length() - 1); } return ret; } else { return ""; } } private void findBoundaryEvents(FlowElementsContainer flc, List<BoundaryEvent> boundaryList) { for (FlowElement fl : flc.getFlowElements()) { if (fl instanceof BoundaryEvent) { boundaryList.add((BoundaryEvent) fl); } if (fl instanceof FlowElementsContainer) { findBoundaryEvents((FlowElementsContainer) fl, boundaryList); } } } private String getAnyAttributeValue(BaseElement el, String attrName) { if (el == null || attrName == null || attrName.isEmpty()) { return null; } if (el.getAnyAttribute() != null && el.getAnyAttribute().size() > 0) { Iterator<FeatureMap.Entry> iter = el.getAnyAttribute().iterator(); while (iter.hasNext()) { FeatureMap.Entry entry = iter.next(); if (attrName.equals(entry.getEStructuralFeature().getName())) { return entry.getValue().toString(); } } } return null; } private String encodeAssociationValue(String s) { if (s == null || s.isEmpty()) { return s; } try { return URLEncoder.encode(s, "UTF-8"); } catch (UnsupportedEncodingException e) { return s; } } private void extractCostParamsToProperties(ElementParameters eleType, Map<String, Object> properties) { CostParameters costParams = eleType.getCostParameters(); if (costParams != null) { if (costParams.getUnitCost() != null) { extractParamTypeToProperties("unitcost", costParams.getUnitCost().getParameterValue(), properties); } } } private void extractTimeParamsToProperties(ElementParameters eleType, Map<String, Object> properties) { TimeParameters timeParams = eleType.getTimeParameters(); if (timeParams != null) { Parameter processingTime = timeParams.getProcessingTime(); if (processingTime != null && processingTime.getParameterValue() != null && processingTime.getParameterValue().size() > 0) { ParameterValue paramValue = processingTime.getParameterValue().get(0); if (paramValue instanceof NormalDistributionType) { NormalDistributionType ndt = (NormalDistributionType) paramValue; properties.put("mean", ndt.getMean()); properties.put("standarddeviation", ndt.getStandardDeviation()); properties.put("distributiontype", "normal"); } else if (paramValue instanceof UniformDistributionType) { UniformDistributionType udt = (UniformDistributionType) paramValue; properties.put("min", udt.getMin()); properties.put("max", udt.getMax()); properties.put("distributiontype", "uniform"); } else if (paramValue instanceof PoissonDistributionType) { PoissonDistributionType pdt = (PoissonDistributionType) paramValue; properties.put("mean", pdt.getMean()); properties.put("distributiontype", "poisson"); } if (timeParams.getWaitTime() != null) { extractParamTypeToProperties("waittime", timeParams.getWaitTime().getParameterValue(), properties); } } } } private void extractControlParamsToProperties(ElementParameters eleType, Map<String, Object> properties) { ControlParameters controlParams = eleType.getControlParameters(); if (controlParams != null) { if (controlParams.getProbability() != null) { extractParamTypeToProperties("probability", controlParams.getProbability().getParameterValue(), properties); } } } private void extractResourceParamsToProperties(ElementParameters eleType, Map<String, Object> properties) { ResourceParameters resourceParams = eleType.getResourceParameters(); if (resourceParams != null) { if (resourceParams.getQuantity() != null) { extractParamTypeToProperties("quantity", resourceParams.getQuantity().getParameterValue(), properties); } if (resourceParams.getAvailability() != null) { extractParamTypeToProperties("workinghours", resourceParams.getAvailability().getParameterValue(), properties); } } } private void extractParamTypeToProperties(String paramName, EList<ParameterValue> parameterValues, Map<String, Object> properties) { if (parameterValues != null && parameterValues.size() > 0) { ParameterValue value = parameterValues.get(0); if (value != null && (value instanceof FloatingParameterType)) { properties.put(paramName, ((FloatingParameterType) value).getValue()); } } } private void setSimulationProperties(String elementId, Map<String, Object> properties) { if (_simulationScenario != null && _simulationScenario.getElementParameters() != null) { for (ElementParameters eleType : _simulationScenario.getElementParameters()) { if (eleType.getElementRef().equals(elementId)) { extractTimeParamsToProperties(eleType, properties); extractCostParamsToProperties(eleType, properties); extractControlParamsToProperties(eleType, properties); extractResourceParamsToProperties(eleType, properties); } } } } private String updateDataInputOutputDashes(String dataInputOutput) { return dataInputOutput.replaceAll("-", " "); } private List<EventDefinition> getEventDefinitionsForEvent(Event event) { List<EventDefinition> eventDefinitions = new ArrayList<>(); if (event != null && event instanceof CatchEvent) { CatchEvent catchEvent = (CatchEvent) event; eventDefinitions.addAll(catchEvent.getEventDefinitions()); eventDefinitions.addAll(catchEvent.getEventDefinitionRefs()); } else if (event != null && event instanceof ThrowEvent) { ThrowEvent throwEvent = (ThrowEvent) event; eventDefinitions.addAll(throwEvent.getEventDefinitions()); eventDefinitions.addAll(throwEvent.getEventDefinitionRefs()); } else { _logger.warn("Unable to get event definitions for event: " + event); } return eventDefinitions; } private void marshalCustomSLADueDateMetadata(final BaseElement element, final Map<String, Object> properties) { final String customSLADueDateMetaData = Utils.getMetaDataValue(element.getExtensionValues(), "customSLADueDate"); if (customSLADueDateMetaData != null && customSLADueDateMetaData.length() > 0) { properties.put("customsladuedate", customSLADueDateMetaData); } } }