|  | @@ -0,0 +1,617 @@
 | 
	
		
			
				|  |  | +package org.activiti.bpmn.converter;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import java.io.ByteArrayOutputStream;
 | 
	
		
			
				|  |  | +import java.io.IOException;
 | 
	
		
			
				|  |  | +import java.io.InputStreamReader;
 | 
	
		
			
				|  |  | +import java.io.OutputStreamWriter;
 | 
	
		
			
				|  |  | +import java.io.UnsupportedEncodingException;
 | 
	
		
			
				|  |  | +import java.util.ArrayList;
 | 
	
		
			
				|  |  | +import java.util.Collection;
 | 
	
		
			
				|  |  | +import java.util.HashMap;
 | 
	
		
			
				|  |  | +import java.util.List;
 | 
	
		
			
				|  |  | +import java.util.Map;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import javax.xml.XMLConstants;
 | 
	
		
			
				|  |  | +import javax.xml.stream.XMLInputFactory;
 | 
	
		
			
				|  |  | +import javax.xml.stream.XMLOutputFactory;
 | 
	
		
			
				|  |  | +import javax.xml.stream.XMLStreamException;
 | 
	
		
			
				|  |  | +import javax.xml.stream.XMLStreamReader;
 | 
	
		
			
				|  |  | +import javax.xml.stream.XMLStreamWriter;
 | 
	
		
			
				|  |  | +import javax.xml.transform.stax.StAXSource;
 | 
	
		
			
				|  |  | +import javax.xml.transform.stream.StreamSource;
 | 
	
		
			
				|  |  | +import javax.xml.validation.Schema;
 | 
	
		
			
				|  |  | +import javax.xml.validation.SchemaFactory;
 | 
	
		
			
				|  |  | +import javax.xml.validation.Validator;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +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.IOSpecificationParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.child.MultiInstanceParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.export.ActivitiListenerExport;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.export.BPMNDIExport;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.export.CollaborationExport;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.export.DataStoreExport;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.export.DefinitionsRootExport;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.export.MultiInstanceExport;
 | 
	
		
			
				|  |  | +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.DataStoreParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.parser.DefinitionsParser;
 | 
	
		
			
				|  |  | +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;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.parser.LaneParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.parser.MessageFlowParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.parser.MessageParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.parser.ParticipantParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.parser.PotentialStarterParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.parser.ProcessParser;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.converter.parser.ResourceParser;
 | 
	
		
			
				|  |  | +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;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.Artifact;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.Association;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.BaseElement;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.BooleanDataObject;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.BoundaryEvent;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.BpmnModel;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.DateDataObject;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.DoubleDataObject;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.EventSubProcess;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.FlowElement;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.FlowNode;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.IntegerDataObject;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.LongDataObject;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.Pool;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.Process;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.SequenceFlow;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.StringDataObject;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.SubProcess;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.TextAnnotation;
 | 
	
		
			
				|  |  | +import org.activiti.bpmn.model.Transaction;
 | 
	
		
			
				|  |  | +import org.apache.commons.lang3.StringUtils;
 | 
	
		
			
				|  |  | +import org.slf4j.Logger;
 | 
	
		
			
				|  |  | +import org.slf4j.LoggerFactory;
 | 
	
		
			
				|  |  | +import org.xml.sax.SAXException;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * @author Tijs Rademakers
 | 
	
		
			
				|  |  | + * @author Joram Barrez
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +public class MyBpmnXMLConverter implements BpmnXMLConstants {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected static final Logger LOGGER = LoggerFactory.getLogger(BpmnXMLConverter.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected static final String BPMN_XSD = "org/activiti/impl/bpmn/parser/BPMN20.xsd";
 | 
	
		
			
				|  |  | +    protected static final String DEFAULT_ENCODING = "UTF-8";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected static Map<String, BaseBpmnXMLConverter> convertersToBpmnMap = new HashMap<String, BaseBpmnXMLConverter>();
 | 
	
		
			
				|  |  | +    protected static Map<Class<? extends BaseElement>, BaseBpmnXMLConverter> convertersToXMLMap =
 | 
	
		
			
				|  |  | +            new HashMap<Class<? extends BaseElement>, BaseBpmnXMLConverter>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected ClassLoader classloader;
 | 
	
		
			
				|  |  | +    protected List<String> userTaskFormTypes;
 | 
	
		
			
				|  |  | +    protected List<String> startEventFormTypes;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected BpmnEdgeParser bpmnEdgeParser = new BpmnEdgeParser();
 | 
	
		
			
				|  |  | +    protected BpmnShapeParser bpmnShapeParser = new BpmnShapeParser();
 | 
	
		
			
				|  |  | +    protected DefinitionsParser definitionsParser = new DefinitionsParser();
 | 
	
		
			
				|  |  | +    protected DocumentationParser documentationParser = new DocumentationParser();
 | 
	
		
			
				|  |  | +    protected ExtensionElementsParser extensionElementsParser = new ExtensionElementsParser();
 | 
	
		
			
				|  |  | +    protected ImportParser importParser = new ImportParser();
 | 
	
		
			
				|  |  | +    protected InterfaceParser interfaceParser = new InterfaceParser();
 | 
	
		
			
				|  |  | +    protected ItemDefinitionParser itemDefinitionParser = new ItemDefinitionParser();
 | 
	
		
			
				|  |  | +    protected IOSpecificationParser ioSpecificationParser = new IOSpecificationParser();
 | 
	
		
			
				|  |  | +    protected DataStoreParser dataStoreParser = new DataStoreParser();
 | 
	
		
			
				|  |  | +    protected LaneParser laneParser = new LaneParser();
 | 
	
		
			
				|  |  | +    protected MessageParser messageParser = new MessageParser();
 | 
	
		
			
				|  |  | +    protected MessageFlowParser messageFlowParser = new MessageFlowParser();
 | 
	
		
			
				|  |  | +    protected MultiInstanceParser multiInstanceParser = new MultiInstanceParser();
 | 
	
		
			
				|  |  | +    protected ParticipantParser participantParser = new ParticipantParser();
 | 
	
		
			
				|  |  | +    protected PotentialStarterParser potentialStarterParser = new PotentialStarterParser();
 | 
	
		
			
				|  |  | +    protected ProcessParser processParser = new ProcessParser();
 | 
	
		
			
				|  |  | +    protected ResourceParser resourceParser = new ResourceParser();
 | 
	
		
			
				|  |  | +    protected SignalParser signalParser = new SignalParser();
 | 
	
		
			
				|  |  | +    protected SubProcessParser subProcessParser = new SubProcessParser();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    static {
 | 
	
		
			
				|  |  | +        // events
 | 
	
		
			
				|  |  | +        addConverter(new EndEventXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new StartEventXMLConverter());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // tasks
 | 
	
		
			
				|  |  | +        addConverter(new BusinessRuleTaskXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new ManualTaskXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new ReceiveTaskXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new ScriptTaskXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new ServiceTaskXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new SendTaskXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new UserTaskXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new TaskXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new CallActivityXMLConverter());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // gateways
 | 
	
		
			
				|  |  | +        addConverter(new EventGatewayXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new ExclusiveGatewayXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new InclusiveGatewayXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new ParallelGatewayXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new ComplexGatewayXMLConverter());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // connectors
 | 
	
		
			
				|  |  | +        addConverter(new SequenceFlowXMLConverter());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // catch, throw and boundary event
 | 
	
		
			
				|  |  | +        addConverter(new CatchEventXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new ThrowEventXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new BoundaryEventXMLConverter());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // artifacts
 | 
	
		
			
				|  |  | +        addConverter(new TextAnnotationXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new AssociationXMLConverter());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // data store reference
 | 
	
		
			
				|  |  | +        addConverter(new DataStoreReferenceXMLConverter());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // data objects
 | 
	
		
			
				|  |  | +        addConverter(new ValuedDataObjectXMLConverter(), StringDataObject.class);
 | 
	
		
			
				|  |  | +        addConverter(new ValuedDataObjectXMLConverter(), BooleanDataObject.class);
 | 
	
		
			
				|  |  | +        addConverter(new ValuedDataObjectXMLConverter(), IntegerDataObject.class);
 | 
	
		
			
				|  |  | +        addConverter(new ValuedDataObjectXMLConverter(), LongDataObject.class);
 | 
	
		
			
				|  |  | +        addConverter(new ValuedDataObjectXMLConverter(), DoubleDataObject.class);
 | 
	
		
			
				|  |  | +        addConverter(new ValuedDataObjectXMLConverter(), DateDataObject.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Alfresco types
 | 
	
		
			
				|  |  | +        addConverter(new AlfrescoStartEventXMLConverter());
 | 
	
		
			
				|  |  | +        addConverter(new AlfrescoUserTaskXMLConverter());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public static void addConverter(BaseBpmnXMLConverter converter) {
 | 
	
		
			
				|  |  | +        addConverter(converter, converter.getBpmnElementType());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public static void addConverter(BaseBpmnXMLConverter converter, Class<? extends BaseElement> elementType) {
 | 
	
		
			
				|  |  | +        convertersToBpmnMap.put(converter.getXMLElementName(), converter);
 | 
	
		
			
				|  |  | +        convertersToXMLMap.put(elementType, converter);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void setClassloader(ClassLoader classloader) {
 | 
	
		
			
				|  |  | +        this.classloader = classloader;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void setUserTaskFormTypes(List<String> userTaskFormTypes) {
 | 
	
		
			
				|  |  | +        this.userTaskFormTypes = userTaskFormTypes;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void setStartEventFormTypes(List<String> startEventFormTypes) {
 | 
	
		
			
				|  |  | +        this.startEventFormTypes = startEventFormTypes;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void validateModel(InputStreamProvider inputStreamProvider) throws Exception {
 | 
	
		
			
				|  |  | +        Schema schema = createSchema();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Validator validator = schema.newValidator();
 | 
	
		
			
				|  |  | +        validator.validate(new StreamSource(inputStreamProvider.getInputStream()));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public void validateModel(XMLStreamReader xmlStreamReader) throws Exception {
 | 
	
		
			
				|  |  | +        Schema schema = createSchema();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Validator validator = schema.newValidator();
 | 
	
		
			
				|  |  | +        validator.validate(new StAXSource(xmlStreamReader));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    protected Schema createSchema() throws SAXException {
 | 
	
		
			
				|  |  | +        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
 | 
	
		
			
				|  |  | +        Schema schema = null;
 | 
	
		
			
				|  |  | +        if (classloader != null) {
 | 
	
		
			
				|  |  | +            schema = factory.newSchema(classloader.getResource(BPMN_XSD));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (schema == null) {
 | 
	
		
			
				|  |  | +            schema = factory.newSchema(BpmnXMLConverter.class.getClassLoader().getResource(BPMN_XSD));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (schema == null) {
 | 
	
		
			
				|  |  | +            throw new XMLException("BPMN XSD could not be found");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return schema;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public BpmnModel convertToBpmnModel(InputStreamProvider inputStreamProvider, boolean validateSchema, boolean enableSafeBpmnXml) {
 | 
	
		
			
				|  |  | +        return convertToBpmnModel(inputStreamProvider, validateSchema, enableSafeBpmnXml, DEFAULT_ENCODING);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public BpmnModel convertToBpmnModel(InputStreamProvider inputStreamProvider, boolean validateSchema, boolean enableSafeBpmnXml, String encoding) {
 | 
	
		
			
				|  |  | +        XMLInputFactory xif = XMLInputFactory.newInstance();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (xif.isPropertySupported(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES)) {
 | 
	
		
			
				|  |  | +            xif.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (xif.isPropertySupported(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES)) {
 | 
	
		
			
				|  |  | +            xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (xif.isPropertySupported(XMLInputFactory.SUPPORT_DTD)) {
 | 
	
		
			
				|  |  | +            xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        InputStreamReader in = null;
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            in = new InputStreamReader(inputStreamProvider.getInputStream(), encoding);
 | 
	
		
			
				|  |  | +            XMLStreamReader xtr = xif.createXMLStreamReader(in);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                if (validateSchema) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    if (!enableSafeBpmnXml) {
 | 
	
		
			
				|  |  | +                        validateModel(inputStreamProvider);
 | 
	
		
			
				|  |  | +                    } else {
 | 
	
		
			
				|  |  | +                        validateModel(xtr);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    // The input stream is closed after schema validation
 | 
	
		
			
				|  |  | +                    in = new InputStreamReader(inputStreamProvider.getInputStream(), encoding);
 | 
	
		
			
				|  |  | +                    xtr = xif.createXMLStreamReader(in);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            } catch (Exception e) {
 | 
	
		
			
				|  |  | +                throw new XMLException(e.getMessage(), e);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // XML conversion
 | 
	
		
			
				|  |  | +            return convertToBpmnModel(xtr);
 | 
	
		
			
				|  |  | +        } catch (UnsupportedEncodingException e) {
 | 
	
		
			
				|  |  | +            throw new XMLException("The bpmn 2.0 xml is not UTF8 encoded", e);
 | 
	
		
			
				|  |  | +        } catch (XMLStreamException e) {
 | 
	
		
			
				|  |  | +            throw new XMLException("Error while reading the BPMN 2.0 XML", e);
 | 
	
		
			
				|  |  | +        } finally {
 | 
	
		
			
				|  |  | +            if (in != null) {
 | 
	
		
			
				|  |  | +                try {
 | 
	
		
			
				|  |  | +                    in.close();
 | 
	
		
			
				|  |  | +                } catch (IOException e) {
 | 
	
		
			
				|  |  | +                    LOGGER.debug("Problem closing BPMN input stream", e);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public BpmnModel convertToBpmnModel(XMLStreamReader xtr) {
 | 
	
		
			
				|  |  | +        BpmnModel model = new BpmnModel();
 | 
	
		
			
				|  |  | +        model.setStartEventFormTypes(startEventFormTypes);
 | 
	
		
			
				|  |  | +        model.setUserTaskFormTypes(userTaskFormTypes);
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            Process activeProcess = null;
 | 
	
		
			
				|  |  | +            List<SubProcess> activeSubProcessList = new ArrayList<SubProcess>();
 | 
	
		
			
				|  |  | +            while (xtr.hasNext()) {
 | 
	
		
			
				|  |  | +                try {
 | 
	
		
			
				|  |  | +                    xtr.next();
 | 
	
		
			
				|  |  | +                } catch (Exception e) {
 | 
	
		
			
				|  |  | +                    LOGGER.debug("Error reading XML document", e);
 | 
	
		
			
				|  |  | +                    throw new XMLException("Error reading XML", e);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (xtr.isEndElement() && ELEMENT_SUBPROCESS.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    activeSubProcessList.remove(activeSubProcessList.size() - 1);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (xtr.isEndElement() && ELEMENT_TRANSACTION.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    activeSubProcessList.remove(activeSubProcessList.size() - 1);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (xtr.isStartElement() == false) {
 | 
	
		
			
				|  |  | +                    continue;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (ELEMENT_DEFINITIONS.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    definitionsParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_RESOURCE.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    resourceParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_SIGNAL.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    signalParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_MESSAGE.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    messageParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_ERROR.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_ID))) {
 | 
	
		
			
				|  |  | +                        model.addError(xtr.getAttributeValue(null, ATTRIBUTE_ID),
 | 
	
		
			
				|  |  | +                                xtr.getAttributeValue(null, ATTRIBUTE_ERROR_CODE));
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_IMPORT.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    importParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_ITEM_DEFINITION.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    itemDefinitionParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_DATA_STORE.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    dataStoreParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_INTERFACE.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    interfaceParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_IOSPECIFICATION.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    ioSpecificationParser.parseChildElement(xtr, activeProcess, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_PARTICIPANT.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    participantParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_MESSAGE_FLOW.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    messageFlowParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_PROCESS.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    Process process = processParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +                    if (process != null) {
 | 
	
		
			
				|  |  | +                        activeProcess = process;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_POTENTIAL_STARTER.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    potentialStarterParser.parse(xtr, activeProcess);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_LANE.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    laneParser.parse(xtr, activeProcess, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_DOCUMENTATION.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    BaseElement parentElement = null;
 | 
	
		
			
				|  |  | +                    if (!activeSubProcessList.isEmpty()) {
 | 
	
		
			
				|  |  | +                        parentElement = activeSubProcessList.get(activeSubProcessList.size() - 1);
 | 
	
		
			
				|  |  | +                    } else if (activeProcess != null) {
 | 
	
		
			
				|  |  | +                        parentElement = activeProcess;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    documentationParser.parseChildElement(xtr, parentElement, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (activeProcess == null && ELEMENT_TEXT_ANNOTATION.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    String elementId = xtr.getAttributeValue(null, ATTRIBUTE_ID);
 | 
	
		
			
				|  |  | +                    TextAnnotation textAnnotation = (TextAnnotation) new TextAnnotationXMLConverter().convertXMLToElement(xtr, model);
 | 
	
		
			
				|  |  | +                    textAnnotation.setId(elementId);
 | 
	
		
			
				|  |  | +                    model.getGlobalArtifacts().add(textAnnotation);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (activeProcess == null && ELEMENT_ASSOCIATION.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    String elementId = xtr.getAttributeValue(null, ATTRIBUTE_ID);
 | 
	
		
			
				|  |  | +                    Association association = (Association) new AssociationXMLConverter().convertXMLToElement(xtr, model);
 | 
	
		
			
				|  |  | +                    association.setId(elementId);
 | 
	
		
			
				|  |  | +                    model.getGlobalArtifacts().add(association);
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_EXTENSIONS.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    extensionElementsParser.parse(xtr, activeSubProcessList, activeProcess, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_SUBPROCESS.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    subProcessParser.parse(xtr, activeSubProcessList, activeProcess);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_TRANSACTION.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    subProcessParser.parse(xtr, activeSubProcessList, activeProcess);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_DI_SHAPE.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    bpmnShapeParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else if (ELEMENT_DI_EDGE.equals(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                    bpmnEdgeParser.parse(xtr, model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    if (!activeSubProcessList.isEmpty() && ELEMENT_MULTIINSTANCE.equalsIgnoreCase(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                        multiInstanceParser.parseChildElement(xtr, activeSubProcessList.get(activeSubProcessList.size() - 1), model);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    } else if (convertersToBpmnMap.containsKey(xtr.getLocalName())) {
 | 
	
		
			
				|  |  | +                        if (activeProcess != null) {
 | 
	
		
			
				|  |  | +                            BaseBpmnXMLConverter converter = convertersToBpmnMap.get(xtr.getLocalName());
 | 
	
		
			
				|  |  | +                            converter.convertToBpmnModel(xtr, model, activeProcess, activeSubProcessList);
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (Process process : model.getProcesses()) {
 | 
	
		
			
				|  |  | +                for (Pool pool : model.getPools()) {
 | 
	
		
			
				|  |  | +                    if (process.getId().equals(pool.getProcessRef())) {
 | 
	
		
			
				|  |  | +                        pool.setExecutable(process.isExecutable());
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                processFlowElements(process.getFlowElements(), process);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } catch (XMLException e) {
 | 
	
		
			
				|  |  | +            throw e;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            LOGGER.error("Error processing BPMN document", e);
 | 
	
		
			
				|  |  | +            throw new XMLException("Error processing BPMN document", e);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return model;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void processFlowElements(Collection<FlowElement> flowElementList, BaseElement parentScope) {
 | 
	
		
			
				|  |  | +        for (FlowElement flowElement : flowElementList) {
 | 
	
		
			
				|  |  | +            if (flowElement instanceof SequenceFlow) {
 | 
	
		
			
				|  |  | +                SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
 | 
	
		
			
				|  |  | +                FlowNode sourceNode = getFlowNodeFromScope(sequenceFlow.getSourceRef(), parentScope);
 | 
	
		
			
				|  |  | +                if (sourceNode != null) {
 | 
	
		
			
				|  |  | +                    sourceNode.getOutgoingFlows().add(sequenceFlow);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                FlowNode targetNode = getFlowNodeFromScope(sequenceFlow.getTargetRef(), parentScope);
 | 
	
		
			
				|  |  | +                if (targetNode != null) {
 | 
	
		
			
				|  |  | +                    targetNode.getIncomingFlows().add(sequenceFlow);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            } else if (flowElement instanceof BoundaryEvent) {
 | 
	
		
			
				|  |  | +                BoundaryEvent boundaryEvent = (BoundaryEvent) flowElement;
 | 
	
		
			
				|  |  | +                FlowElement attachedToElement = getFlowNodeFromScope(boundaryEvent.getAttachedToRefId(), parentScope);
 | 
	
		
			
				|  |  | +                if (attachedToElement != null) {
 | 
	
		
			
				|  |  | +                    boundaryEvent.setAttachedToRef((Activity) attachedToElement);
 | 
	
		
			
				|  |  | +                    ((Activity) attachedToElement).getBoundaryEvents().add(boundaryEvent);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            } else if (flowElement instanceof SubProcess) {
 | 
	
		
			
				|  |  | +                SubProcess subProcess = (SubProcess) flowElement;
 | 
	
		
			
				|  |  | +                processFlowElements(subProcess.getFlowElements(), subProcess);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private FlowNode getFlowNodeFromScope(String elementId, BaseElement scope) {
 | 
	
		
			
				|  |  | +        FlowNode flowNode = null;
 | 
	
		
			
				|  |  | +        if (StringUtils.isNotEmpty(elementId)) {
 | 
	
		
			
				|  |  | +            if (scope instanceof Process) {
 | 
	
		
			
				|  |  | +                flowNode = (FlowNode) ((Process) scope).getFlowElement(elementId);
 | 
	
		
			
				|  |  | +            } else if (scope instanceof SubProcess) {
 | 
	
		
			
				|  |  | +                flowNode = (FlowNode) ((SubProcess) scope).getFlowElement(elementId);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return flowNode;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public byte[] convertToXML(BpmnModel model) {
 | 
	
		
			
				|  |  | +        return convertToXML(model, DEFAULT_ENCODING);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    public byte[] convertToXML(BpmnModel model, String encoding) {
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            XMLOutputFactory xof = XMLOutputFactory.newInstance();
 | 
	
		
			
				|  |  | +            OutputStreamWriter out = new OutputStreamWriter(outputStream, encoding);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            XMLStreamWriter writer = xof.createXMLStreamWriter(out);
 | 
	
		
			
				|  |  | +            XMLStreamWriter xtw = new IndentingXMLStreamWriter(writer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            DefinitionsRootExport.writeRootElement(model, xtw, encoding);
 | 
	
		
			
				|  |  | +            CollaborationExport.writePools(model, xtw);
 | 
	
		
			
				|  |  | +            DataStoreExport.writeDataStores(model, xtw);
 | 
	
		
			
				|  |  | +            SignalAndMessageDefinitionExport.writeSignalsAndMessages(model, xtw);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (Process process : model.getProcesses()) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (process.getFlowElements().isEmpty() && process.getLanes().isEmpty()) {
 | 
	
		
			
				|  |  | +                    // empty process, ignore it
 | 
	
		
			
				|  |  | +                    continue;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                ProcessExport.writeProcess(process, xtw);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                for (FlowElement flowElement : process.getFlowElements()) {
 | 
	
		
			
				|  |  | +                    createXML(flowElement, model, xtw);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                for (Artifact artifact : process.getArtifacts()) {
 | 
	
		
			
				|  |  | +                    createXML(artifact, model, xtw);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                // end process element
 | 
	
		
			
				|  |  | +                xtw.writeEndElement();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            BPMNDIExport.writeBPMNDI(model, xtw);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // end definitions root element
 | 
	
		
			
				|  |  | +            xtw.writeEndElement();
 | 
	
		
			
				|  |  | +            xtw.writeEndDocument();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            xtw.flush();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            outputStream.close();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            xtw.close();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return outputStream.toByteArray();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            LOGGER.error("Error writing BPMN XML", e);
 | 
	
		
			
				|  |  | +            throw new XMLException("Error writing BPMN XML", e);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void createXML(FlowElement flowElement, BpmnModel model, XMLStreamWriter xtw) throws Exception {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (flowElement instanceof SubProcess) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            SubProcess subProcess = (SubProcess) flowElement;
 | 
	
		
			
				|  |  | +            if (flowElement instanceof Transaction) {
 | 
	
		
			
				|  |  | +                xtw.writeStartElement(ELEMENT_TRANSACTION);
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                xtw.writeStartElement(ELEMENT_SUBPROCESS);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            xtw.writeAttribute(ATTRIBUTE_ID, subProcess.getId());
 | 
	
		
			
				|  |  | +            if (StringUtils.isNotEmpty(subProcess.getName())) {
 | 
	
		
			
				|  |  | +                xtw.writeAttribute(ATTRIBUTE_NAME, subProcess.getName());
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                xtw.writeAttribute(ATTRIBUTE_NAME, "subProcess");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (subProcess instanceof EventSubProcess) {
 | 
	
		
			
				|  |  | +                xtw.writeAttribute(ATTRIBUTE_TRIGGERED_BY, ATTRIBUTE_VALUE_TRUE);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            } else if (subProcess instanceof Transaction == false) {
 | 
	
		
			
				|  |  | +                if (subProcess.isAsynchronous()) {
 | 
	
		
			
				|  |  | +                    BpmnXMLUtil.writeQualifiedAttribute(ATTRIBUTE_ACTIVITY_ASYNCHRONOUS, ATTRIBUTE_VALUE_TRUE, xtw);
 | 
	
		
			
				|  |  | +                    if (subProcess.isNotExclusive()) {
 | 
	
		
			
				|  |  | +                        BpmnXMLUtil.writeQualifiedAttribute(ATTRIBUTE_ACTIVITY_EXCLUSIVE, ATTRIBUTE_VALUE_FALSE, xtw);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (StringUtils.isNotEmpty(subProcess.getDocumentation())) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                xtw.writeStartElement(ELEMENT_DOCUMENTATION);
 | 
	
		
			
				|  |  | +                xtw.writeCharacters(subProcess.getDocumentation());
 | 
	
		
			
				|  |  | +                xtw.writeEndElement();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            boolean didWriteExtensionStartElement = ActivitiListenerExport.writeListeners(subProcess, false, xtw);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            didWriteExtensionStartElement = BpmnXMLUtil.writeExtensionElements(subProcess, didWriteExtensionStartElement, model.getNamespaces(), xtw);
 | 
	
		
			
				|  |  | +            if (didWriteExtensionStartElement) {
 | 
	
		
			
				|  |  | +                // closing extensions element
 | 
	
		
			
				|  |  | +                xtw.writeEndElement();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            MultiInstanceExport.writeMultiInstance(subProcess, xtw);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (FlowElement subElement : subProcess.getFlowElements()) {
 | 
	
		
			
				|  |  | +                createXML(subElement, model, xtw);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (Artifact artifact : subProcess.getArtifacts()) {
 | 
	
		
			
				|  |  | +                createXML(artifact, model, xtw);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            xtw.writeEndElement();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            BaseBpmnXMLConverter converter = convertersToXMLMap.get(flowElement.getClass());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (converter == null) {
 | 
	
		
			
				|  |  | +                throw new XMLException("No converter for " + flowElement.getClass() + " found");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            converter.convertToXML(xtw, flowElement, model);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private void createXML(Artifact artifact, BpmnModel model, XMLStreamWriter xtw) throws Exception {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        BaseBpmnXMLConverter converter = convertersToXMLMap.get(artifact.getClass());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (converter == null) {
 | 
	
		
			
				|  |  | +            throw new XMLException("No converter for " + artifact.getClass() + " found");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        converter.convertToXML(xtw, artifact, model);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |