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(); element.setXmlRowNumber(location.getLineNumber()); element.setXmlColumnNumber(location.getColumnNumber()); } public static void addXMLLocation(GraphicInfo graphicInfo, XMLStreamReader xtr) { Location location = xtr.getLocation(); graphicInfo.setXmlRowNumber(location.getLineNumber()); 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); } } public static void writeQualifiedAttribute(String attributeName, String value, XMLStreamWriter xtw) throws Exception { if (StringUtils.isNotEmpty(value)) { xtw.writeAttribute(ACTIVITI_EXTENSIONS_PREFIX, ACTIVITI_EXTENSIONS_NAMESPACE, attributeName, value); } } 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)) { StringCharacterIterator iterator = new StringCharacterIterator(s); char c = iterator.first(); StringBuilder strb = new StringBuilder(); boolean insideExpression = false; while (c != StringCharacterIterator.DONE) { if (c == '{' || c == '$') { insideExpression = true; } else if (c == '}') { insideExpression = false; } else if (c == ',' && !insideExpression) { result.add(strb.toString().trim()); strb.delete(0, strb.length()); } if (c != ',' || (insideExpression)) { strb.append(c); } c = iterator.next(); } if (strb.length() > 0) { result.add(strb.toString().trim()); } } return result; } public static String convertToDelimitedString(List stringList) { StringBuilder resultString = new StringBuilder(); for (String result : stringList) { if (resultString.length() > 0) { resultString.append(","); } resultString.append(result); } return resultString.toString(); } }