From ee2f460c2c0752d4a86b48abae6e7bb92f1be3b3 Mon Sep 17 00:00:00 2001 From: tijsrademakers Date: Thu, 10 Oct 2013 10:01:29 +0200 Subject: [PATCH] Fix for extension elements for process, sub process, lanes, pools etc --- .../bpmn/converter/BaseBpmnXMLConverter.java | 211 +++--------------- .../bpmn/converter/BpmnXMLConverter.java | 22 +- .../CompensateEventDefinitionParser.java | 2 + .../child/ErrorEventDefinitionParser.java | 2 + .../converter/child/FlowNodeRefParser.java | 36 +++ .../child/MessageEventDefinitionParser.java | 3 + .../child/SignalEventDefinitionParser.java | 2 + .../child/TerminateEventDefinitionParser.java | 3 + .../bpmn/converter/child/TimeCycleParser.java | 36 +++ .../bpmn/converter/child/TimeDateParser.java | 36 +++ .../converter/child/TimeDurationParser.java | 36 +++ .../child/TimerEventDefinitionParser.java | 23 +- .../bpmn/converter/export/ProcessExport.java | 6 +- .../parser/ExtensionElementsParser.java | 60 +++++ .../parser/ItemDefinitionParser.java | 1 + .../bpmn/converter/parser/LaneParser.java | 13 +- .../bpmn/converter/parser/MessageParser.java | 1 + .../bpmn/converter/parser/SignalParser.java | 1 + .../bpmn/converter/util/BpmnXMLUtil.java | 210 +++++++++++++++++ .../xml/CustomExtensionsConverterTest.java | 31 ++- .../xml/InCompleteSignalConverterTest.java | 1 - .../test/resources/customextensionsmodel.bpmn | 28 +++ .../examples/task/StandaloneTaskTest.java | 10 +- 23 files changed, 533 insertions(+), 241 deletions(-) create mode 100644 modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/FlowNodeRefParser.java create mode 100644 modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeCycleParser.java create mode 100644 modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeDateParser.java create mode 100644 modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeDurationParser.java create mode 100644 modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/ExtensionElementsParser.java diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/BaseBpmnXMLConverter.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/BaseBpmnXMLConverter.java index 48a8cc7966..876d4e010d 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/BaseBpmnXMLConverter.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/BaseBpmnXMLConverter.java @@ -21,23 +21,6 @@ import javax.xml.stream.XMLStreamWriter; import org.activiti.bpmn.constants.BpmnXMLConstants; import org.activiti.bpmn.converter.child.BaseChildElementParser; -import org.activiti.bpmn.converter.child.CancelEventDefinitionParser; -import org.activiti.bpmn.converter.child.CompensateEventDefinitionParser; -import org.activiti.bpmn.converter.child.ConditionExpressionParser; -import org.activiti.bpmn.converter.child.DataInputAssociationParser; -import org.activiti.bpmn.converter.child.DataOutputAssociationParser; -import org.activiti.bpmn.converter.child.DocumentationParser; -import org.activiti.bpmn.converter.child.ErrorEventDefinitionParser; -import org.activiti.bpmn.converter.child.ExecutionListenerParser; -import org.activiti.bpmn.converter.child.FieldExtensionParser; -import org.activiti.bpmn.converter.child.FormPropertyParser; -import org.activiti.bpmn.converter.child.IOSpecificationParser; -import org.activiti.bpmn.converter.child.MessageEventDefinitionParser; -import org.activiti.bpmn.converter.child.MultiInstanceParser; -import org.activiti.bpmn.converter.child.SignalEventDefinitionParser; -import org.activiti.bpmn.converter.child.TaskListenerParser; -import org.activiti.bpmn.converter.child.TerminateEventDefinitionParser; -import org.activiti.bpmn.converter.child.TimerEventDefinitionParser; import org.activiti.bpmn.converter.export.ActivitiListenerExport; import org.activiti.bpmn.converter.export.MultiInstanceExport; import org.activiti.bpmn.converter.util.BpmnXMLUtil; @@ -47,8 +30,6 @@ import org.activiti.bpmn.model.BaseElement; import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.ErrorEventDefinition; import org.activiti.bpmn.model.EventDefinition; -import org.activiti.bpmn.model.ExtensionAttribute; -import org.activiti.bpmn.model.ExtensionElement; import org.activiti.bpmn.model.FlowElement; import org.activiti.bpmn.model.FormProperty; import org.activiti.bpmn.model.FormValue; @@ -75,34 +56,9 @@ public abstract class BaseBpmnXMLConverter implements BpmnXMLConstants { protected BpmnModel model; protected Process activeProcess; protected Map childElementParsers = new HashMap(); - private static Map genericChildParserMap = new HashMap(); protected boolean didWriteExtensionStartElement = false; - static { - addGenericParser(new CancelEventDefinitionParser()); - addGenericParser(new CompensateEventDefinitionParser()); - addGenericParser(new ConditionExpressionParser()); - addGenericParser(new DataInputAssociationParser()); - addGenericParser(new DataOutputAssociationParser()); - addGenericParser(new DocumentationParser()); - addGenericParser(new ErrorEventDefinitionParser()); - addGenericParser(new ExecutionListenerParser()); - addGenericParser(new FieldExtensionParser()); - addGenericParser(new FormPropertyParser()); - addGenericParser(new IOSpecificationParser()); - addGenericParser(new MessageEventDefinitionParser()); - addGenericParser(new MultiInstanceParser()); - addGenericParser(new SignalEventDefinitionParser()); - addGenericParser(new TaskListenerParser()); - addGenericParser(new TerminateEventDefinitionParser()); - addGenericParser(new TimerEventDefinitionParser()); - } - - private static void addGenericParser(BaseChildElementParser parser) { - genericChildParserMap.put(parser.getElementName(), parser); - } - public void convertToBpmnModel(XMLStreamReader xtr, BpmnModel model, Process activeProcess, List activeSubProcessList) throws Exception { @@ -203,19 +159,7 @@ public abstract class BaseBpmnXMLConverter implements BpmnXMLConstants { writeExtensionChildElements(baseElement, xtw); didWriteExtensionStartElement = writeListeners(baseElement, xtw); - - if (baseElement.getExtensionElements().size() > 0) { - if (didWriteExtensionStartElement == false) { - xtw.writeStartElement(ELEMENT_EXTENSIONS); - didWriteExtensionStartElement = true; - } - Map namespaceMap = new HashMap(); - for (List extensionElements : baseElement.getExtensionElements().values()) { - for (ExtensionElement extensionElement : extensionElements) { - writeExtensionElement(extensionElement, namespaceMap, xtw); - } - } - } + didWriteExtensionStartElement = BpmnXMLUtil.writeExtensionElements(baseElement, didWriteExtensionStartElement, xtw); if (didWriteExtensionStartElement) { xtw.writeEndElement(); @@ -245,71 +189,10 @@ public abstract class BaseBpmnXMLConverter implements BpmnXMLConstants { protected void parseChildElements(String elementName, BaseElement parentElement, XMLStreamReader xtr) throws Exception { Map childParsers = new HashMap(); - childParsers.putAll(genericChildParserMap); if (childElementParsers != null) { childParsers.putAll(childElementParsers); } - - boolean inExtensionElements = false; - boolean readyWithChildElements = false; - while (readyWithChildElements == false && xtr.hasNext()) { - xtr.next(); - if (xtr.isStartElement()) { - if (ELEMENT_EXTENSIONS.equals(xtr.getLocalName())) { - inExtensionElements = true; - } else if (childParsers.containsKey(xtr.getLocalName())) { - childParsers.get(xtr.getLocalName()).parseChildElement(xtr, parentElement, model); - } else if (inExtensionElements) { - ExtensionElement extensionElement = parseExtensionElement(xtr); - parentElement.addExtensionElement(extensionElement); - } - - } else if (xtr.isEndElement()) { - if (ELEMENT_EXTENSIONS.equals(xtr.getLocalName())) { - inExtensionElements = false; - } else if (elementName.equalsIgnoreCase(xtr.getLocalName())) { - readyWithChildElements = true; - } - } - } - } - - protected ExtensionElement parseExtensionElement(XMLStreamReader xtr) throws Exception { - ExtensionElement extensionElement = new ExtensionElement(); - extensionElement.setName(xtr.getLocalName()); - if (StringUtils.isNotEmpty(xtr.getNamespaceURI())) { - extensionElement.setNamespace(xtr.getNamespaceURI()); - } - if (StringUtils.isNotEmpty(xtr.getPrefix())) { - extensionElement.setNamespacePrefix(xtr.getPrefix()); - } - - for (int i = 0; i < xtr.getAttributeCount(); i++) { - ExtensionAttribute extensionAttribute = new ExtensionAttribute(); - extensionAttribute.setName(xtr.getAttributeLocalName(i)); - extensionAttribute.setValue(xtr.getAttributeValue(i)); - extensionAttribute.setNamespace(xtr.getAttributeNamespace(i)); - if (StringUtils.isNotEmpty(xtr.getAttributePrefix(i))) { - extensionAttribute.setNamespacePrefix(xtr.getAttributePrefix(i)); - } - extensionElement.addAttribute(extensionAttribute); - } - - boolean readyWithExtensionElement = false; - while (readyWithExtensionElement == false && xtr.hasNext()) { - xtr.next(); - if (xtr.isCharacters()) { - if (StringUtils.isNotEmpty(xtr.getText().trim())) { - extensionElement.setElementText(xtr.getText().trim()); - } - } else if (xtr.isStartElement()) { - ExtensionElement childExtensionElement = parseExtensionElement(xtr); - extensionElement.addChildElement(childExtensionElement); - } else if (xtr.isEndElement() && extensionElement.getName().equalsIgnoreCase(xtr.getLocalName())) { - readyWithExtensionElement = true; - } - } - return extensionElement; + BpmnXMLUtil.parseChildElements(elementName, parentElement, xtr, childParsers, model); } protected boolean parseAsync(XMLStreamReader xtr) { @@ -353,69 +236,6 @@ public abstract class BaseBpmnXMLConverter implements BpmnXMLConstants { // To XML converter convenience methods - protected void writeExtensionElement(ExtensionElement extensionElement, Map namespaceMap, XMLStreamWriter xtw) throws Exception { - if (StringUtils.isNotEmpty(extensionElement.getName())) { - Map localNamespaceMap = new HashMap(); - if (StringUtils.isNotEmpty(extensionElement.getNamespace())) { - if (StringUtils.isNotEmpty(extensionElement.getNamespacePrefix())) { - xtw.writeStartElement(extensionElement.getNamespacePrefix(), extensionElement.getName(), extensionElement.getNamespace()); - - if (namespaceMap.containsKey(extensionElement.getNamespacePrefix()) == false || - namespaceMap.get(extensionElement.getNamespacePrefix()).equals(extensionElement.getNamespace()) == false) { - - xtw.writeNamespace(extensionElement.getNamespacePrefix(), extensionElement.getNamespace()); - namespaceMap.put(extensionElement.getNamespacePrefix(), extensionElement.getNamespace()); - localNamespaceMap.put(extensionElement.getNamespacePrefix(), extensionElement.getNamespace()); - } - } else { - xtw.writeStartElement(extensionElement.getNamespace(), extensionElement.getName()); - } - } else { - xtw.writeStartElement(extensionElement.getName()); - } - - for (List attributes : extensionElement.getAttributes().values()) { - for (ExtensionAttribute attribute : attributes) { - if (StringUtils.isNotEmpty(attribute.getName()) && attribute.getValue() != null) { - if (StringUtils.isNotEmpty(attribute.getNamespace())) { - if (StringUtils.isNotEmpty(attribute.getNamespacePrefix())) { - - if (namespaceMap.containsKey(attribute.getNamespacePrefix()) == false || - namespaceMap.get(attribute.getNamespacePrefix()).equals(attribute.getNamespace()) == false) { - - xtw.writeNamespace(attribute.getNamespacePrefix(), attribute.getNamespace()); - namespaceMap.put(attribute.getNamespacePrefix(), attribute.getNamespace()); - } - - xtw.writeAttribute(attribute.getNamespacePrefix(), attribute.getNamespace(), attribute.getName(), attribute.getValue()); - } else { - xtw.writeAttribute(attribute.getNamespace(), attribute.getName(), attribute.getValue()); - } - } else { - xtw.writeAttribute(attribute.getName(), attribute.getValue()); - } - } - } - } - - if (extensionElement.getElementText() != null) { - xtw.writeCharacters(extensionElement.getElementText()); - } else { - for (List childElements : extensionElement.getChildElements().values()) { - for (ExtensionElement childElement : childElements) { - writeExtensionElement(childElement, namespaceMap, xtw); - } - } - } - - for (String prefix : localNamespaceMap.keySet()) { - namespaceMap.remove(prefix); - } - - xtw.writeEndElement(); - } - } - protected String convertToDelimitedString(List stringList) { return BpmnXMLUtil.convertToDelimitedString(stringList); } @@ -496,7 +316,10 @@ public abstract class BaseBpmnXMLConverter implements BpmnXMLConstants { protected void writeTimerDefinition(TimerEventDefinition timerDefinition, XMLStreamWriter xtw) throws Exception { xtw.writeStartElement(ELEMENT_EVENT_TIMERDEFINITION); - + boolean didWriteExtensionStartElement = BpmnXMLUtil.writeExtensionElements(timerDefinition, false, xtw); + if (didWriteExtensionStartElement) { + xtw.writeEndElement(); + } if (StringUtils.isNotEmpty(timerDefinition.getTimeDate())) { xtw.writeStartElement(ATTRIBUTE_TIMER_DATE); xtw.writeCharacters(timerDefinition.getTimeDate()); @@ -518,7 +341,11 @@ public abstract class BaseBpmnXMLConverter implements BpmnXMLConstants { protected void writeSignalDefinition(SignalEventDefinition signalDefinition, XMLStreamWriter xtw) throws Exception { xtw.writeStartElement(ELEMENT_EVENT_SIGNALDEFINITION); - writeDefaultAttribute(ATTRIBUTE_SIGNAL_REF, signalDefinition.getSignalRef(), xtw); + writeDefaultAttribute(ATTRIBUTE_SIGNAL_REF, signalDefinition.getSignalRef(), xtw); + boolean didWriteExtensionStartElement = BpmnXMLUtil.writeExtensionElements(signalDefinition, false, xtw); + if (didWriteExtensionStartElement) { + xtw.writeEndElement(); + } xtw.writeEndElement(); } @@ -541,18 +368,30 @@ public abstract class BaseBpmnXMLConverter implements BpmnXMLConstants { } } } - writeDefaultAttribute(ATTRIBUTE_MESSAGE_REF, messageRef, xtw); + writeDefaultAttribute(ATTRIBUTE_MESSAGE_REF, messageRef, xtw); + boolean didWriteExtensionStartElement = BpmnXMLUtil.writeExtensionElements(messageDefinition, false, xtw); + if (didWriteExtensionStartElement) { + xtw.writeEndElement(); + } xtw.writeEndElement(); } protected void writeErrorDefinition(ErrorEventDefinition errorDefinition, XMLStreamWriter xtw) throws Exception { xtw.writeStartElement(ELEMENT_EVENT_ERRORDEFINITION); - writeDefaultAttribute(ATTRIBUTE_ERROR_REF, errorDefinition.getErrorCode(), xtw); + writeDefaultAttribute(ATTRIBUTE_ERROR_REF, errorDefinition.getErrorCode(), xtw); + boolean didWriteExtensionStartElement = BpmnXMLUtil.writeExtensionElements(errorDefinition, false, xtw); + if (didWriteExtensionStartElement) { + xtw.writeEndElement(); + } xtw.writeEndElement(); } protected void writeTerminateDefinition(TerminateEventDefinition terminateDefinition, XMLStreamWriter xtw) throws Exception { xtw.writeStartElement(ELEMENT_EVENT_TERMINATEDEFINITION); + boolean didWriteExtensionStartElement = BpmnXMLUtil.writeExtensionElements(terminateDefinition, false, xtw); + if (didWriteExtensionStartElement) { + xtw.writeEndElement(); + } xtw.writeEndElement(); } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/BpmnXMLConverter.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/BpmnXMLConverter.java index 8282d1cb5f..9f2cdb1066 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/BpmnXMLConverter.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/BpmnXMLConverter.java @@ -39,7 +39,6 @@ import org.activiti.bpmn.constants.BpmnXMLConstants; import org.activiti.bpmn.converter.alfresco.AlfrescoStartEventXMLConverter; import org.activiti.bpmn.converter.alfresco.AlfrescoUserTaskXMLConverter; import org.activiti.bpmn.converter.child.DocumentationParser; -import org.activiti.bpmn.converter.child.ExecutionListenerParser; import org.activiti.bpmn.converter.child.IOSpecificationParser; import org.activiti.bpmn.converter.child.MultiInstanceParser; import org.activiti.bpmn.converter.export.ActivitiListenerExport; @@ -51,6 +50,7 @@ import org.activiti.bpmn.converter.export.ProcessExport; import org.activiti.bpmn.converter.export.SignalAndMessageDefinitionExport; import org.activiti.bpmn.converter.parser.BpmnEdgeParser; import org.activiti.bpmn.converter.parser.BpmnShapeParser; +import org.activiti.bpmn.converter.parser.ExtensionElementsParser; import org.activiti.bpmn.converter.parser.ImportParser; import org.activiti.bpmn.converter.parser.InterfaceParser; import org.activiti.bpmn.converter.parser.ItemDefinitionParser; @@ -60,6 +60,7 @@ import org.activiti.bpmn.converter.parser.PotentialStarterParser; import org.activiti.bpmn.converter.parser.ProcessParser; import org.activiti.bpmn.converter.parser.SignalParser; import org.activiti.bpmn.converter.parser.SubProcessParser; +import org.activiti.bpmn.converter.util.BpmnXMLUtil; import org.activiti.bpmn.converter.util.InputStreamProvider; import org.activiti.bpmn.exceptions.XMLException; import org.activiti.bpmn.model.Activity; @@ -313,6 +314,7 @@ public class BpmnXMLConverter implements BpmnXMLConstants { pool.setId(xtr.getAttributeValue(null, ATTRIBUTE_ID)); pool.setName(xtr.getAttributeValue(null, ATTRIBUTE_NAME)); pool.setProcessRef(xtr.getAttributeValue(null, ATTRIBUTE_PROCESS_REF)); + BpmnXMLUtil.parseChildElements(ELEMENT_PARTICIPANT, pool, xtr, model); model.getPools().add(pool); } @@ -327,7 +329,7 @@ public class BpmnXMLConverter implements BpmnXMLConstants { new PotentialStarterParser().parse(xtr, activeProcess); } else if (ELEMENT_LANE.equals(xtr.getLocalName())) { - new LaneParser().parse(xtr, activeProcess); + new LaneParser().parse(xtr, activeProcess, model); } else if (ELEMENT_DOCUMENTATION.equals(xtr.getLocalName())) { @@ -339,32 +341,24 @@ public class BpmnXMLConverter implements BpmnXMLConstants { } new DocumentationParser().parseChildElement(xtr, parentElement, model); + } else if (ELEMENT_EXTENSIONS.equals(xtr.getLocalName())) { + new ExtensionElementsParser().parse(xtr, activeSubProcessList, activeProcess, model); + } else if (ELEMENT_SUBPROCESS.equals(xtr.getLocalName())) { - new SubProcessParser().parse(xtr, activeSubProcessList, activeProcess); } else if (ELEMENT_TRANSACTION.equals(xtr.getLocalName())) { - new SubProcessParser().parse(xtr, activeSubProcessList, activeProcess); } else if (ELEMENT_DI_SHAPE.equals(xtr.getLocalName())) { - new BpmnShapeParser().parse(xtr, model); } else if (ELEMENT_DI_EDGE.equals(xtr.getLocalName())) { - new BpmnEdgeParser().parse(xtr, model); - } else if (activeSubProcessList.size() == 0 && ELEMENT_EXECUTION_LISTENER.equals(xtr.getLocalName())) { - - new ExecutionListenerParser().parseChildElement(xtr, activeProcess, model); - } else { - if (activeSubProcessList.size() > 0 && ELEMENT_EXECUTION_LISTENER.equalsIgnoreCase(xtr.getLocalName())) { - new ExecutionListenerParser().parseChildElement(xtr, activeSubProcessList.get(activeSubProcessList.size() - 1), model); - - } else if (activeSubProcessList.size() > 0 && ELEMENT_MULTIINSTANCE.equalsIgnoreCase(xtr.getLocalName())) { + if (activeSubProcessList.size() > 0 && ELEMENT_MULTIINSTANCE.equalsIgnoreCase(xtr.getLocalName())) { new MultiInstanceParser().parseChildElement(xtr, activeSubProcessList.get(activeSubProcessList.size() - 1), model); diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/CompensateEventDefinitionParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/CompensateEventDefinitionParser.java index bf5c0912a4..74e57db9f5 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/CompensateEventDefinitionParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/CompensateEventDefinitionParser.java @@ -40,6 +40,8 @@ public class CompensateEventDefinitionParser extends BaseChildElementParser { eventDefinition.setWaitForCompletion(Boolean.parseBoolean(xtr.getAttributeValue(null, ATTRIBUTE_COMPENSATE_WAITFORCOMPLETION))); } + BpmnXMLUtil.parseChildElements(ELEMENT_EVENT_COMPENSATEDEFINITION, eventDefinition, xtr, model); + ((Event) parentElement).getEventDefinitions().add(eventDefinition); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/ErrorEventDefinitionParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/ErrorEventDefinitionParser.java index 79ee1347be..b03c256dde 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/ErrorEventDefinitionParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/ErrorEventDefinitionParser.java @@ -41,6 +41,8 @@ public class ErrorEventDefinitionParser extends BaseChildElementParser { model.addProblem("errorRef is required for an error event", xtr); } + BpmnXMLUtil.parseChildElements(ELEMENT_EVENT_ERRORDEFINITION, eventDefinition, xtr, model); + ((Event) parentElement).getEventDefinitions().add(eventDefinition); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/FlowNodeRefParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/FlowNodeRefParser.java new file mode 100644 index 0000000000..db0d243499 --- /dev/null +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/FlowNodeRefParser.java @@ -0,0 +1,36 @@ +/* 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.activiti.bpmn.converter.child; + +import javax.xml.stream.XMLStreamReader; + +import org.activiti.bpmn.model.BaseElement; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.Lane; + +/** + * @author Tijs Rademakers + */ +public class FlowNodeRefParser extends BaseChildElementParser { + + public String getElementName() { + return ATTRIBUTE_FLOWNODE_REF; + } + + public void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception { + if (parentElement instanceof Lane == false) return; + + Lane lane = (Lane) parentElement; + lane.getFlowReferences().add(xtr.getElementText()); + } +} diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/MessageEventDefinitionParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/MessageEventDefinitionParser.java index a758f43721..52a81f3794 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/MessageEventDefinitionParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/MessageEventDefinitionParser.java @@ -54,6 +54,9 @@ public class MessageEventDefinitionParser extends BaseChildElementParser { model.addProblem("Invalid 'messageRef': no message with id '" + eventDefinition.getMessageRef() + "' found.", xtr); } } + + BpmnXMLUtil.parseChildElements(ELEMENT_EVENT_MESSAGEDEFINITION, eventDefinition, xtr, model); + ((Event) parentElement).getEventDefinitions().add(eventDefinition); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/SignalEventDefinitionParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/SignalEventDefinitionParser.java index 881bb35770..fb813980b0 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/SignalEventDefinitionParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/SignalEventDefinitionParser.java @@ -44,6 +44,8 @@ public class SignalEventDefinitionParser extends BaseChildElementParser { model.addProblem("signalEventDefinition does not have required property 'signalRef'", xtr); } + BpmnXMLUtil.parseChildElements(ELEMENT_EVENT_SIGNALDEFINITION, eventDefinition, xtr, model); + ((Event) parentElement).getEventDefinitions().add(eventDefinition); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TerminateEventDefinitionParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TerminateEventDefinitionParser.java index bdfef42115..b8481a0626 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TerminateEventDefinitionParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TerminateEventDefinitionParser.java @@ -35,6 +35,9 @@ public class TerminateEventDefinitionParser extends BaseChildElementParser { TerminateEventDefinition eventDefinition = new TerminateEventDefinition(); BpmnXMLUtil.addXMLLocation(eventDefinition, xtr); + + BpmnXMLUtil.parseChildElements(ELEMENT_EVENT_TERMINATEDEFINITION, eventDefinition, xtr, model); + ((Event) parentElement).getEventDefinitions().add(eventDefinition); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeCycleParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeCycleParser.java new file mode 100644 index 0000000000..bfd027590a --- /dev/null +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeCycleParser.java @@ -0,0 +1,36 @@ +/* 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.activiti.bpmn.converter.child; + +import javax.xml.stream.XMLStreamReader; + +import org.activiti.bpmn.model.BaseElement; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.TimerEventDefinition; + +/** + * @author Tijs Rademakers + */ +public class TimeCycleParser extends BaseChildElementParser { + + public String getElementName() { + return ATTRIBUTE_TIMER_CYCLE; + } + + public void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception { + if (parentElement instanceof TimerEventDefinition == false) return; + + TimerEventDefinition eventDefinition = (TimerEventDefinition) parentElement; + eventDefinition.setTimeCycle(xtr.getElementText()); + } +} diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeDateParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeDateParser.java new file mode 100644 index 0000000000..ad841a3029 --- /dev/null +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeDateParser.java @@ -0,0 +1,36 @@ +/* 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.activiti.bpmn.converter.child; + +import javax.xml.stream.XMLStreamReader; + +import org.activiti.bpmn.model.BaseElement; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.TimerEventDefinition; + +/** + * @author Tijs Rademakers + */ +public class TimeDateParser extends BaseChildElementParser { + + public String getElementName() { + return ATTRIBUTE_TIMER_DATE; + } + + public void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception { + if (parentElement instanceof TimerEventDefinition == false) return; + + TimerEventDefinition eventDefinition = (TimerEventDefinition) parentElement; + eventDefinition.setTimeDate(xtr.getElementText()); + } +} diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeDurationParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeDurationParser.java new file mode 100644 index 0000000000..d60d30f285 --- /dev/null +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimeDurationParser.java @@ -0,0 +1,36 @@ +/* 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.activiti.bpmn.converter.child; + +import javax.xml.stream.XMLStreamReader; + +import org.activiti.bpmn.model.BaseElement; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.TimerEventDefinition; + +/** + * @author Tijs Rademakers + */ +public class TimeDurationParser extends BaseChildElementParser { + + public String getElementName() { + return ATTRIBUTE_TIMER_DURATION; + } + + public void parseChildElement(XMLStreamReader xtr, BaseElement parentElement, BpmnModel model) throws Exception { + if (parentElement instanceof TimerEventDefinition == false) return; + + TimerEventDefinition eventDefinition = (TimerEventDefinition) parentElement; + eventDefinition.setTimeDuration(xtr.getElementText()); + } +} diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimerEventDefinitionParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimerEventDefinitionParser.java index 3fd232a0e7..a4bdb72d46 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimerEventDefinitionParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/child/TimerEventDefinitionParser.java @@ -34,28 +34,7 @@ public class TimerEventDefinitionParser extends BaseChildElementParser { TimerEventDefinition eventDefinition = new TimerEventDefinition(); BpmnXMLUtil.addXMLLocation(eventDefinition, xtr); - try { - while (xtr.hasNext()) { - xtr.next(); - if (xtr.isStartElement() && ATTRIBUTE_TIMER_DURATION.equalsIgnoreCase(xtr.getLocalName())) { - eventDefinition.setTimeDuration(xtr.getElementText()); - break; - - } else if (xtr.isStartElement() && ATTRIBUTE_TIMER_DATE.equalsIgnoreCase(xtr.getLocalName())) { - eventDefinition.setTimeDate(xtr.getElementText()); - break; - - } else if (xtr.isStartElement() && ATTRIBUTE_TIMER_CYCLE.equalsIgnoreCase(xtr.getLocalName())) { - eventDefinition.setTimeCycle(xtr.getElementText()); - break; - - } else if (xtr.isEndElement() && ELEMENT_EVENT_TIMERDEFINITION.equalsIgnoreCase(xtr.getLocalName())) { - break; - } - } - } catch (Exception e) { - LOGGER.warn("Error parsing timer event definition", e); - } + BpmnXMLUtil.parseChildElements(ELEMENT_EVENT_TIMERDEFINITION, eventDefinition, xtr, model); ((Event) parentElement).getEventDefinitions().add(eventDefinition); } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/export/ProcessExport.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/export/ProcessExport.java index abeee5808a..2ac7a7ef73 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/export/ProcessExport.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/export/ProcessExport.java @@ -49,8 +49,10 @@ public class ProcessExport implements BpmnXMLConstants { xtw.writeEndElement(); } - boolean wroteListener = ActivitiListenerExport.writeListeners(process, false, xtw); - if (wroteListener) { + boolean didWriteExtensionStartElement = ActivitiListenerExport.writeListeners(process, false, xtw); + didWriteExtensionStartElement = BpmnXMLUtil.writeExtensionElements(process, didWriteExtensionStartElement, xtw); + + if (didWriteExtensionStartElement) { // closing extensions element xtw.writeEndElement(); } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/ExtensionElementsParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/ExtensionElementsParser.java new file mode 100644 index 0000000000..ed36a78f07 --- /dev/null +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/ExtensionElementsParser.java @@ -0,0 +1,60 @@ +/* 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.activiti.bpmn.converter.parser; + +import java.util.List; + +import javax.xml.stream.XMLStreamReader; + +import org.activiti.bpmn.constants.BpmnXMLConstants; +import org.activiti.bpmn.converter.child.ExecutionListenerParser; +import org.activiti.bpmn.converter.util.BpmnXMLUtil; +import org.activiti.bpmn.model.BaseElement; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.ExtensionElement; +import org.activiti.bpmn.model.Process; +import org.activiti.bpmn.model.SubProcess; + +/** + * @author Tijs Rademakers + */ +public class ExtensionElementsParser implements BpmnXMLConstants { + + public void parse(XMLStreamReader xtr, List activeSubProcessList, Process activeProcess, BpmnModel model) throws Exception { + BaseElement parentElement = null; + if (activeSubProcessList.size() > 0) { + parentElement = activeSubProcessList.get(activeSubProcessList.size() - 1); + + } else { + parentElement = activeProcess; + } + + boolean readyWithChildElements = false; + while (readyWithChildElements == false && xtr.hasNext()) { + xtr.next(); + if (xtr.isStartElement()) { + if (ELEMENT_EXECUTION_LISTENER.equals(xtr.getLocalName())) { + new ExecutionListenerParser().parseChildElement(xtr, activeProcess, model); + } else { + ExtensionElement extensionElement = BpmnXMLUtil.parseExtensionElement(xtr); + parentElement.addExtensionElement(extensionElement); + } + + } else if (xtr.isEndElement()) { + if (ELEMENT_EXTENSIONS.equals(xtr.getLocalName())) { + readyWithChildElements = true; + } + } + } + } +} diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/ItemDefinitionParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/ItemDefinitionParser.java index c5872d3587..3ee0000810 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/ItemDefinitionParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/ItemDefinitionParser.java @@ -45,6 +45,7 @@ public class ItemDefinitionParser implements BpmnXMLConstants { item.setStructureRef(structureRef); item.setItemKind(xtr.getAttributeValue(null, ATTRIBUTE_ITEM_KIND)); + BpmnXMLUtil.parseChildElements(ELEMENT_ITEM_DEFINITION, item, xtr, model); model.addItemDefinition(itemDefinitionId, item); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/LaneParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/LaneParser.java index 65bd894334..be0145661d 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/LaneParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/LaneParser.java @@ -16,6 +16,7 @@ import javax.xml.stream.XMLStreamReader; import org.activiti.bpmn.constants.BpmnXMLConstants; import org.activiti.bpmn.converter.util.BpmnXMLUtil; +import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.Lane; import org.activiti.bpmn.model.Process; @@ -24,21 +25,13 @@ import org.activiti.bpmn.model.Process; */ public class LaneParser implements BpmnXMLConstants { - public void parse(XMLStreamReader xtr, Process activeProcess) throws Exception { + public void parse(XMLStreamReader xtr, Process activeProcess, BpmnModel model) throws Exception { Lane lane = new Lane(); BpmnXMLUtil.addXMLLocation(lane, xtr); lane.setId(xtr.getAttributeValue(null, ATTRIBUTE_ID)); lane.setName(xtr.getAttributeValue(null, ATTRIBUTE_NAME)); lane.setParentProcess(activeProcess); activeProcess.getLanes().add(lane); - - while (xtr.hasNext()) { - xtr.next(); - if (xtr.isStartElement() && ATTRIBUTE_FLOWNODE_REF.equalsIgnoreCase(xtr.getLocalName())) { - lane.getFlowReferences().add(xtr.getElementText()); - } else if(xtr.isEndElement() && ELEMENT_LANE.equalsIgnoreCase(xtr.getLocalName())) { - break; - } - } + BpmnXMLUtil.parseChildElements(ELEMENT_LANE, lane, xtr, model); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/MessageParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/MessageParser.java index 1810fda0fa..82bd6d57f2 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/MessageParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/MessageParser.java @@ -32,6 +32,7 @@ public class MessageParser implements BpmnXMLConstants { String itemRef = parseItemRef(xtr.getAttributeValue(null, ATTRIBUTE_ITEM_REF), model); Message message = new Message(messageId, messageName, itemRef); BpmnXMLUtil.addXMLLocation(message, xtr); + BpmnXMLUtil.parseChildElements(ELEMENT_MESSAGE, message, xtr, model); model.addMessage(message); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/SignalParser.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/SignalParser.java index 36de45c718..b63e54aa61 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/SignalParser.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/parser/SignalParser.java @@ -52,6 +52,7 @@ public class SignalParser implements BpmnXMLConstants { } BpmnXMLUtil.addXMLLocation(signal, xtr); + BpmnXMLUtil.parseChildElements(ELEMENT_SIGNAL, signal, xtr, model); model.addSignal(signal); } } diff --git a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/util/BpmnXMLUtil.java b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/util/BpmnXMLUtil.java index 525b280279..daf53101ad 100644 --- a/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/util/BpmnXMLUtil.java +++ b/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter/util/BpmnXMLUtil.java @@ -2,18 +2,75 @@ package org.activiti.bpmn.converter.util; import java.text.StringCharacterIterator; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.xml.stream.Location; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import org.activiti.bpmn.constants.BpmnXMLConstants; +import org.activiti.bpmn.converter.child.BaseChildElementParser; +import org.activiti.bpmn.converter.child.CancelEventDefinitionParser; +import org.activiti.bpmn.converter.child.CompensateEventDefinitionParser; +import org.activiti.bpmn.converter.child.ConditionExpressionParser; +import org.activiti.bpmn.converter.child.DataInputAssociationParser; +import org.activiti.bpmn.converter.child.DataOutputAssociationParser; +import org.activiti.bpmn.converter.child.DocumentationParser; +import org.activiti.bpmn.converter.child.ErrorEventDefinitionParser; +import org.activiti.bpmn.converter.child.ExecutionListenerParser; +import org.activiti.bpmn.converter.child.FieldExtensionParser; +import org.activiti.bpmn.converter.child.FlowNodeRefParser; +import org.activiti.bpmn.converter.child.FormPropertyParser; +import org.activiti.bpmn.converter.child.IOSpecificationParser; +import org.activiti.bpmn.converter.child.MessageEventDefinitionParser; +import org.activiti.bpmn.converter.child.MultiInstanceParser; +import org.activiti.bpmn.converter.child.SignalEventDefinitionParser; +import org.activiti.bpmn.converter.child.TaskListenerParser; +import org.activiti.bpmn.converter.child.TerminateEventDefinitionParser; +import org.activiti.bpmn.converter.child.TimeCycleParser; +import org.activiti.bpmn.converter.child.TimeDateParser; +import org.activiti.bpmn.converter.child.TimeDurationParser; +import org.activiti.bpmn.converter.child.TimerEventDefinitionParser; import org.activiti.bpmn.model.BaseElement; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.bpmn.model.ExtensionAttribute; +import org.activiti.bpmn.model.ExtensionElement; import org.activiti.bpmn.model.GraphicInfo; import org.apache.commons.lang3.StringUtils; public class BpmnXMLUtil implements BpmnXMLConstants { + + private static Map genericChildParserMap = new HashMap(); + + static { + addGenericParser(new CancelEventDefinitionParser()); + addGenericParser(new CompensateEventDefinitionParser()); + addGenericParser(new ConditionExpressionParser()); + addGenericParser(new DataInputAssociationParser()); + addGenericParser(new DataOutputAssociationParser()); + addGenericParser(new DocumentationParser()); + addGenericParser(new ErrorEventDefinitionParser()); + addGenericParser(new ExecutionListenerParser()); + addGenericParser(new FieldExtensionParser()); + addGenericParser(new FormPropertyParser()); + addGenericParser(new IOSpecificationParser()); + addGenericParser(new MessageEventDefinitionParser()); + addGenericParser(new MultiInstanceParser()); + addGenericParser(new SignalEventDefinitionParser()); + addGenericParser(new TaskListenerParser()); + addGenericParser(new TerminateEventDefinitionParser()); + addGenericParser(new TimerEventDefinitionParser()); + addGenericParser(new TimeDateParser()); + addGenericParser(new TimeCycleParser()); + addGenericParser(new TimeDurationParser()); + addGenericParser(new FlowNodeRefParser()); + } + + private static void addGenericParser(BaseChildElementParser parser) { + genericChildParserMap.put(parser.getElementName(), parser); + } public static void addXMLLocation(BaseElement element, XMLStreamReader xtr) { Location location = xtr.getLocation(); @@ -27,6 +84,80 @@ public class BpmnXMLUtil implements BpmnXMLConstants { graphicInfo.setXmlColumnNumber(location.getColumnNumber()); } + public static void parseChildElements(String elementName, BaseElement parentElement, XMLStreamReader xtr, BpmnModel model) throws Exception { + parseChildElements(elementName, parentElement, xtr, null, model); + } + + public static void parseChildElements(String elementName, BaseElement parentElement, XMLStreamReader xtr, + Map childParsers, BpmnModel model) throws Exception { + + if (childParsers == null) { + childParsers = new HashMap(); + } + childParsers.putAll(genericChildParserMap); + + boolean inExtensionElements = false; + boolean readyWithChildElements = false; + while (readyWithChildElements == false && xtr.hasNext()) { + xtr.next(); + if (xtr.isStartElement()) { + if (ELEMENT_EXTENSIONS.equals(xtr.getLocalName())) { + inExtensionElements = true; + } else if (childParsers.containsKey(xtr.getLocalName())) { + childParsers.get(xtr.getLocalName()).parseChildElement(xtr, parentElement, model); + } else if (inExtensionElements) { + ExtensionElement extensionElement = BpmnXMLUtil.parseExtensionElement(xtr); + parentElement.addExtensionElement(extensionElement); + } + + } else if (xtr.isEndElement()) { + if (ELEMENT_EXTENSIONS.equals(xtr.getLocalName())) { + inExtensionElements = false; + } else if (elementName.equalsIgnoreCase(xtr.getLocalName())) { + readyWithChildElements = true; + } + } + } + } + + public static ExtensionElement parseExtensionElement(XMLStreamReader xtr) throws Exception { + ExtensionElement extensionElement = new ExtensionElement(); + extensionElement.setName(xtr.getLocalName()); + if (StringUtils.isNotEmpty(xtr.getNamespaceURI())) { + extensionElement.setNamespace(xtr.getNamespaceURI()); + } + if (StringUtils.isNotEmpty(xtr.getPrefix())) { + extensionElement.setNamespacePrefix(xtr.getPrefix()); + } + + for (int i = 0; i < xtr.getAttributeCount(); i++) { + ExtensionAttribute extensionAttribute = new ExtensionAttribute(); + extensionAttribute.setName(xtr.getAttributeLocalName(i)); + extensionAttribute.setValue(xtr.getAttributeValue(i)); + extensionAttribute.setNamespace(xtr.getAttributeNamespace(i)); + if (StringUtils.isNotEmpty(xtr.getAttributePrefix(i))) { + extensionAttribute.setNamespacePrefix(xtr.getAttributePrefix(i)); + } + extensionElement.addAttribute(extensionAttribute); + } + + boolean readyWithExtensionElement = false; + while (readyWithExtensionElement == false && xtr.hasNext()) { + xtr.next(); + if (xtr.isCharacters()) { + if (StringUtils.isNotEmpty(xtr.getText().trim())) { + extensionElement.setElementText(xtr.getText().trim()); + } + } else if (xtr.isStartElement()) { + ExtensionElement childExtensionElement = parseExtensionElement(xtr); + extensionElement.addChildElement(childExtensionElement); + } else if (xtr.isEndElement() && extensionElement.getName().equalsIgnoreCase(xtr.getLocalName())) { + readyWithExtensionElement = true; + } + } + return extensionElement; + } + public static void writeDefaultAttribute(String attributeName, String value, XMLStreamWriter xtw) throws Exception { if (StringUtils.isNotEmpty(value) && "null".equalsIgnoreCase(value) == false) { xtw.writeAttribute(attributeName, value); @@ -39,6 +170,85 @@ public class BpmnXMLUtil implements BpmnXMLConstants { } } + public static boolean writeExtensionElements(BaseElement baseElement, boolean didWriteExtensionStartElement, XMLStreamWriter xtw) throws Exception { + if (baseElement.getExtensionElements().size() > 0) { + if (didWriteExtensionStartElement == false) { + xtw.writeStartElement(ELEMENT_EXTENSIONS); + didWriteExtensionStartElement = true; + } + Map namespaceMap = new HashMap(); + for (List extensionElements : baseElement.getExtensionElements().values()) { + for (ExtensionElement extensionElement : extensionElements) { + writeExtensionElement(extensionElement, namespaceMap, xtw); + } + } + } + return didWriteExtensionStartElement; + } + + protected static void writeExtensionElement(ExtensionElement extensionElement, Map namespaceMap, XMLStreamWriter xtw) throws Exception { + if (StringUtils.isNotEmpty(extensionElement.getName())) { + Map localNamespaceMap = new HashMap(); + if (StringUtils.isNotEmpty(extensionElement.getNamespace())) { + if (StringUtils.isNotEmpty(extensionElement.getNamespacePrefix())) { + xtw.writeStartElement(extensionElement.getNamespacePrefix(), extensionElement.getName(), extensionElement.getNamespace()); + + if (namespaceMap.containsKey(extensionElement.getNamespacePrefix()) == false || + namespaceMap.get(extensionElement.getNamespacePrefix()).equals(extensionElement.getNamespace()) == false) { + + xtw.writeNamespace(extensionElement.getNamespacePrefix(), extensionElement.getNamespace()); + namespaceMap.put(extensionElement.getNamespacePrefix(), extensionElement.getNamespace()); + localNamespaceMap.put(extensionElement.getNamespacePrefix(), extensionElement.getNamespace()); + } + } else { + xtw.writeStartElement(extensionElement.getNamespace(), extensionElement.getName()); + } + } else { + xtw.writeStartElement(extensionElement.getName()); + } + + for (List attributes : extensionElement.getAttributes().values()) { + for (ExtensionAttribute attribute : attributes) { + if (StringUtils.isNotEmpty(attribute.getName()) && attribute.getValue() != null) { + if (StringUtils.isNotEmpty(attribute.getNamespace())) { + if (StringUtils.isNotEmpty(attribute.getNamespacePrefix())) { + + if (namespaceMap.containsKey(attribute.getNamespacePrefix()) == false || + namespaceMap.get(attribute.getNamespacePrefix()).equals(attribute.getNamespace()) == false) { + + xtw.writeNamespace(attribute.getNamespacePrefix(), attribute.getNamespace()); + namespaceMap.put(attribute.getNamespacePrefix(), attribute.getNamespace()); + } + + xtw.writeAttribute(attribute.getNamespacePrefix(), attribute.getNamespace(), attribute.getName(), attribute.getValue()); + } else { + xtw.writeAttribute(attribute.getNamespace(), attribute.getName(), attribute.getValue()); + } + } else { + xtw.writeAttribute(attribute.getName(), attribute.getValue()); + } + } + } + } + + if (extensionElement.getElementText() != null) { + xtw.writeCharacters(extensionElement.getElementText()); + } else { + for (List childElements : extensionElement.getChildElements().values()) { + for (ExtensionElement childElement : childElements) { + writeExtensionElement(childElement, namespaceMap, xtw); + } + } + } + + for (String prefix : localNamespaceMap.keySet()) { + namespaceMap.remove(prefix); + } + + xtw.writeEndElement(); + } + } + public static List parseDelimitedList(String s) { List result = new ArrayList(); if (StringUtils.isNotEmpty(s)) { diff --git a/modules/activiti-bpmn-converter/src/test/java/org/activiti/editor/language/xml/CustomExtensionsConverterTest.java b/modules/activiti-bpmn-converter/src/test/java/org/activiti/editor/language/xml/CustomExtensionsConverterTest.java index c719e3a5f3..d3782588e9 100644 --- a/modules/activiti-bpmn-converter/src/test/java/org/activiti/editor/language/xml/CustomExtensionsConverterTest.java +++ b/modules/activiti-bpmn-converter/src/test/java/org/activiti/editor/language/xml/CustomExtensionsConverterTest.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Map; import org.activiti.bpmn.model.ActivitiListener; +import org.activiti.bpmn.model.BoundaryEvent; import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.ExtensionAttribute; import org.activiti.bpmn.model.ExtensionElement; @@ -16,12 +17,13 @@ import org.activiti.bpmn.model.FieldExtension; import org.activiti.bpmn.model.FlowElement; import org.activiti.bpmn.model.ImplementationType; import org.activiti.bpmn.model.ServiceTask; +import org.activiti.bpmn.model.TimerEventDefinition; import org.junit.Test; public class CustomExtensionsConverterTest extends AbstractConverterTest { @Test - public void connvertXMLToModel() throws Exception { + public void convertXMLToModel() throws Exception { BpmnModel bpmnModel = readXMLFile(); validateModel(bpmnModel); } @@ -39,6 +41,11 @@ public class CustomExtensionsConverterTest extends AbstractConverterTest { } private void validateModel(BpmnModel model) { + List listeners = model.getMainProcess().getExecutionListeners(); + validateExecutionListeners(listeners); + Map> extensionElementMap = model.getMainProcess().getExtensionElements(); + validateExtensionElements(extensionElementMap); + FlowElement flowElement = model.getMainProcess().getFlowElement("servicetask"); assertNotNull(flowElement); assertTrue(flowElement instanceof ServiceTask); @@ -56,7 +63,22 @@ public class CustomExtensionsConverterTest extends AbstractConverterTest { assertEquals("testField2", field.getFieldName()); assertEquals("${test}", field.getExpression()); - List listeners = serviceTask.getExecutionListeners(); + listeners = serviceTask.getExecutionListeners(); + validateExecutionListeners(listeners); + + extensionElementMap = serviceTask.getExtensionElements(); + validateExtensionElements(extensionElementMap); + + assertEquals(1, serviceTask.getBoundaryEvents().size()); + BoundaryEvent boundaryEvent = serviceTask.getBoundaryEvents().get(0); + assertEquals("timerEvent", boundaryEvent.getId()); + assertEquals(1, boundaryEvent.getEventDefinitions().size()); + assertTrue(boundaryEvent.getEventDefinitions().get(0) instanceof TimerEventDefinition); + extensionElementMap = boundaryEvent.getEventDefinitions().get(0).getExtensionElements(); + validateExtensionElements(extensionElementMap); + } + + protected void validateExecutionListeners(List listeners) { assertEquals(3, listeners.size()); ActivitiListener listener = (ActivitiListener) listeners.get(0); assertTrue(ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(listener.getImplementationType())); @@ -70,8 +92,9 @@ public class CustomExtensionsConverterTest extends AbstractConverterTest { assertTrue(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(listener.getImplementationType())); assertEquals("${delegateExpression}", listener.getImplementation()); assertEquals("start", listener.getEvent()); - - Map> extensionElementMap = serviceTask.getExtensionElements(); + } + + protected void validateExtensionElements(Map> extensionElementMap ) { assertEquals(1, extensionElementMap.size()); List extensionElements = extensionElementMap.get("test"); diff --git a/modules/activiti-bpmn-converter/src/test/java/org/activiti/editor/language/xml/InCompleteSignalConverterTest.java b/modules/activiti-bpmn-converter/src/test/java/org/activiti/editor/language/xml/InCompleteSignalConverterTest.java index f373247054..a7b67dd797 100644 --- a/modules/activiti-bpmn-converter/src/test/java/org/activiti/editor/language/xml/InCompleteSignalConverterTest.java +++ b/modules/activiti-bpmn-converter/src/test/java/org/activiti/editor/language/xml/InCompleteSignalConverterTest.java @@ -33,6 +33,5 @@ public class InCompleteSignalConverterTest extends AbstractConverterTest { List problems = model.getProblems(); assertNotNull(problems); assertEquals(1, problems.size()); - System.out.println(problems.get(0)); } } diff --git a/modules/activiti-bpmn-converter/src/test/resources/customextensionsmodel.bpmn b/modules/activiti-bpmn-converter/src/test/resources/customextensionsmodel.bpmn index 4a56effb96..53b4e658ce 100644 --- a/modules/activiti-bpmn-converter/src/test/resources/customextensionsmodel.bpmn +++ b/modules/activiti-bpmn-converter/src/test/resources/customextensionsmodel.bpmn @@ -4,6 +4,19 @@ xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test"> + + + + + + + test + + + + + + @@ -23,6 +36,21 @@ + + + + + + test + + + + + + + ${cronExpression} + + diff --git a/modules/activiti-engine/src/test/java/org/activiti/examples/task/StandaloneTaskTest.java b/modules/activiti-engine/src/test/java/org/activiti/examples/task/StandaloneTaskTest.java index 7c8c16b4f8..12df5c7510 100644 --- a/modules/activiti-engine/src/test/java/org/activiti/examples/task/StandaloneTaskTest.java +++ b/modules/activiti-engine/src/test/java/org/activiti/examples/task/StandaloneTaskTest.java @@ -48,15 +48,21 @@ public class StandaloneTaskTest extends PluggableActivitiTestCase { taskService.addCandidateUser(taskId, "kermit"); taskService.addCandidateUser(taskId, "gonzo"); - // Retrieve task list for jbarrez + // Retrieve task list for kermit List tasks = taskService.createTaskQuery().taskCandidateUser("kermit").list(); assertEquals(1, tasks.size()); assertEquals("testTask", tasks.get(0).getName()); - // Retrieve task list for tbaeyens + // Retrieve task list for gonzo tasks = taskService.createTaskQuery().taskCandidateUser("gonzo").list(); assertEquals(1, tasks.size()); assertEquals("testTask", tasks.get(0).getName()); + + task.setName("Update name"); + taskService.saveTask(task); + tasks = taskService.createTaskQuery().taskCandidateUser("kermit").list(); + assertEquals(1, tasks.size()); + assertEquals("Update name", tasks.get(0).getName()); // Claim task taskService.claim(taskId, "kermit"); -- GitLab