Package org.activiti.bpmn.converter

Source Code of org.activiti.bpmn.converter.BpmnXMLConverter

/* 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;

import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;

import org.activiti.bpmn.constants.BpmnXMLConstants;
import org.activiti.bpmn.converter.child.DocumentationParser;
import org.activiti.bpmn.converter.child.ExecutionListenerParser;
import org.activiti.bpmn.converter.child.MultiInstanceParser;
import org.activiti.bpmn.converter.parser.BpmnEdgeParser;
import org.activiti.bpmn.converter.parser.BpmnShapeParser;
import org.activiti.bpmn.converter.parser.SubProcessParser;
import org.activiti.bpmn.exceptions.XMLException;
import org.activiti.bpmn.model.Activity;
import org.activiti.bpmn.model.AssociationModel;
import org.activiti.bpmn.model.BaseElement;
import org.activiti.bpmn.model.BoundaryEvent;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.Event;
import org.activiti.bpmn.model.EventDefinition;
import org.activiti.bpmn.model.EventSubProcess;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.bpmn.model.Lane;
import org.activiti.bpmn.model.Message;
import org.activiti.bpmn.model.MessageEventDefinition;
import org.activiti.bpmn.model.Pool;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.Signal;
import org.activiti.bpmn.model.SignalEventDefinition;
import org.activiti.bpmn.model.SubProcess;
import org.apache.commons.lang.StringUtils;

/**
* @author Tijs Rademakers
*/
public class BpmnXMLConverter implements BpmnXMLConstants {

  protected static final Logger LOGGER = Logger.getLogger(BpmnXMLConverter.class.getName());
 
  public List<AssociationModel> associationModels = new ArrayList<AssociationModel>();
  public Map<String, GraphicInfo> labelLocationMap = new HashMap<String, GraphicInfo>();
 
  private static Map<String, Class<? extends BaseBpmnXMLConverter>> convertersToBpmnMap =
      new HashMap<String, Class<? extends BaseBpmnXMLConverter>>();
  private static Map<Class<? extends BaseElement>, Class<? extends BaseBpmnXMLConverter>> convertersToXMLMap =
      new HashMap<Class<? extends BaseElement>, Class<? extends BaseBpmnXMLConverter>>();
 
  static {
    // events
    addConverter(EndEventXMLConverter.getXMLType(), EndEventXMLConverter.getBpmnElementType(), EndEventXMLConverter.class);
    addConverter(StartEventXMLConverter.getXMLType(), StartEventXMLConverter.getBpmnElementType(), StartEventXMLConverter.class);
   
    // tasks
    addConverter(BusinessRuleTaskXMLConverter.getXMLType(), BusinessRuleTaskXMLConverter.getBpmnElementType(), BusinessRuleTaskXMLConverter.class);
    addConverter(ManualTaskXMLConverter.getXMLType(), ManualTaskXMLConverter.getBpmnElementType(), ManualTaskXMLConverter.class);
    addConverter(ReceiveTaskXMLConverter.getXMLType(), ReceiveTaskXMLConverter.getBpmnElementType(), ReceiveTaskXMLConverter.class);
    addConverter(ScriptTaskXMLConverter.getXMLType(), ScriptTaskXMLConverter.getBpmnElementType(), ScriptTaskXMLConverter.class);
    addConverter(ServiceTaskXMLConverter.getXMLType(), ServiceTaskXMLConverter.getBpmnElementType(), ServiceTaskXMLConverter.class);
    addConverter(UserTaskXMLConverter.getXMLType(), UserTaskXMLConverter.getBpmnElementType(), UserTaskXMLConverter.class);
    addConverter(CallActivityXMLConverter.getXMLType(), CallActivityXMLConverter.getBpmnElementType(), CallActivityXMLConverter.class);
   
    // gateways
    addConverter(EventGatewayXMLConverter.getXMLType(), EventGatewayXMLConverter.getBpmnElementType(), EventGatewayXMLConverter.class);
    addConverter(ExclusiveGatewayXMLConverter.getXMLType(), ExclusiveGatewayXMLConverter.getBpmnElementType(), ExclusiveGatewayXMLConverter.class);
    addConverter(InclusiveGatewayXMLConverter.getXMLType(), InclusiveGatewayXMLConverter.getBpmnElementType(), InclusiveGatewayXMLConverter.class);
    addConverter(ParallelGatewayXMLConverter.getXMLType(), ParallelGatewayXMLConverter.getBpmnElementType(), ParallelGatewayXMLConverter.class);
   
    // connectors
    addConverter(SequenceFlowXMLConverter.getXMLType(), SequenceFlowXMLConverter.getBpmnElementType(), SequenceFlowXMLConverter.class);
   
    // catch, throw and boundary event
    addConverter(CatchEventXMLConverter.getXMLType(), CatchEventXMLConverter.getBpmnElementType(), CatchEventXMLConverter.class);
    addConverter(ThrowEventXMLConverter.getXMLType(), ThrowEventXMLConverter.getBpmnElementType(), ThrowEventXMLConverter.class);
    addConverter(BoundaryEventXMLConverter.getXMLType(), BoundaryEventXMLConverter.getBpmnElementType(), BoundaryEventXMLConverter.class);
  }
 
  private static void addConverter(String elementName, Class<? extends BaseElement> elementClass,
      Class<? extends BaseBpmnXMLConverter> converter) {
   
    convertersToBpmnMap.put(elementName, converter);
    convertersToXMLMap.put(elementClass, converter);
  }

  public BpmnModel convertToBpmnModel(XMLStreamReader xtr) {
    BpmnModel model = new BpmnModel();
    try {
      boolean processExtensionAvailable = false;
      Process activeProcess = null;
      List<SubProcess> activeSubProcessList = new ArrayList<SubProcess>();
      while (xtr.hasNext()) {
        try {
          xtr.next();
        } catch(Exception e) {
          LOGGER.log(Level.SEVERE, "Error reading XML document", e);
          return model;
        }

        if (xtr.isEndElement()  && ELEMENT_SUBPROCESS.equalsIgnoreCase(xtr.getLocalName())) {
          activeSubProcessList.remove(activeSubProcessList.size() - 1);
        }

        if (xtr.isStartElement() == false)
          continue;

        if ("definitions".equalsIgnoreCase(xtr.getLocalName())) {

          model.setTargetNamespace(xtr.getAttributeValue(null, TARGET_NAMESPACE_ATTRIBUTE));
       
        } else if (ELEMENT_SIGNAL.equalsIgnoreCase(xtr.getLocalName())) {
         
          if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_ID))) {
            String signalId = xtr.getAttributeValue(null, ATTRIBUTE_ID);
            String signalName = xtr.getAttributeValue(null, ATTRIBUTE_NAME);
            model.addSignal(signalId, signalName);
          }
         
        } else if (ELEMENT_MESSAGE.equalsIgnoreCase(xtr.getLocalName())) {
         
          if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_ID))) {
            String messageId = xtr.getAttributeValue(null, ATTRIBUTE_ID);
            String messageName = xtr.getAttributeValue(null, ATTRIBUTE_NAME);
            model.addMessage(messageId, messageName);
          }
         
        } else if (ELEMENT_PARTICIPANT.equalsIgnoreCase(xtr.getLocalName())) {
         
          if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_ID))) {
            Pool pool = new Pool();
            pool.setId(xtr.getAttributeValue(null, ATTRIBUTE_ID));
            pool.setName(xtr.getAttributeValue(null, ATTRIBUTE_NAME));
            pool.setProcessRef(xtr.getAttributeValue(null, ATTRIBUTE_PROCESS_REF));
            model.getPools().add(pool);
          }

        } else if (ELEMENT_PROCESS.equalsIgnoreCase(xtr.getLocalName())) {
         
          if (StringUtils.isNotEmpty(xtr.getAttributeValue(null, ATTRIBUTE_ID))) {
            String processId = xtr.getAttributeValue(null, ATTRIBUTE_ID);
            processExtensionAvailable = true;
            Process process = new Process();
            process.setId(processId);
            process.setName(xtr.getAttributeValue(null, ATTRIBUTE_NAME));
            model.getProcesses().add(process);
            activeProcess = process; 
          }
         
        } else if ("lane".equalsIgnoreCase(xtr.getLocalName())) {
          Lane lane = new Lane();
          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() && "flowNodeRef".equalsIgnoreCase(xtr.getLocalName())) {
              lane.getFlowReferences().add(xtr.getElementText());
            } else if(xtr.isEndElement() && "lane".equalsIgnoreCase(xtr.getLocalName())) {
              break;
            }
          }
         
         
        } else if (ELEMENT_DOCUMENTATION.equalsIgnoreCase(xtr.getLocalName())) {
         
          BaseElement parentElement = null;
          if(activeSubProcessList.size() > 0) {
            parentElement = activeSubProcessList.get(activeSubProcessList.size() - 1);
          } else if(activeProcess != null) {
            parentElement = activeProcess;
          }
          new DocumentationParser().parseChildElement(xtr, parentElement);
       
        } else if (ELEMENT_SUBPROCESS.equalsIgnoreCase(xtr.getLocalName())) {
         
          new SubProcessParser().parse(xtr, activeSubProcessList, activeProcess);
         
        } else if (ELEMENT_DI_SHAPE.equalsIgnoreCase(xtr.getLocalName())) {
         
          new BpmnShapeParser().parse(xtr, model);
       
        } else if (ELEMENT_DI_EDGE.equalsIgnoreCase(xtr.getLocalName())) {
         
          new BpmnEdgeParser().parse(xtr, model);

        } else if (processExtensionAvailable == true && ELEMENT_EXECUTION_LISTENER.equalsIgnoreCase(xtr.getLocalName())) {
         
          new ExecutionListenerParser().parseChildElement(xtr, activeProcess);

        } else {

          processExtensionAvailable = false;

          if (activeSubProcessList.size() > 0 && ELEMENT_EXTENSIONS.equalsIgnoreCase(xtr.getLocalName())) {
            new ExecutionListenerParser().parseChildElement(xtr, activeSubProcessList.get(activeSubProcessList.size() - 1));

          } else if (activeSubProcessList.size() > 0 && ELEMENT_MULTIINSTANCE.equalsIgnoreCase(xtr.getLocalName())) {
           
            new MultiInstanceParser().parseChildElement(xtr, activeSubProcessList.get(activeSubProcessList.size() - 1));
           
          } else if (convertersToBpmnMap.containsKey(xtr.getLocalName())) {
            Class<? extends BaseBpmnXMLConverter> converter = convertersToBpmnMap.get(xtr.getLocalName());
            converter.newInstance().convertToBpmnModel(xtr, model, activeProcess, activeSubProcessList);
          }
        }
      }

      processFlowElements(model.getMainProcess().getFlowElements(), model.getMainProcess());

    } catch (Exception e) {
      LOGGER.log(Level.SEVERE, "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;
        FlowElement sourceElement = getFlowElementFromScope(sequenceFlow.getSourceRef(), parentScope);
        if (sourceElement != null) {
          sourceElement.addOutgoingFlow(sequenceFlow);
        }
      } else if (flowElement instanceof BoundaryEvent) {
        BoundaryEvent boundaryEvent = (BoundaryEvent) flowElement;
        FlowElement attachedToElement = getFlowElementFromScope(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 FlowElement getFlowElementFromScope(String elementId, BaseElement scope) {
    FlowElement flowElement = null;
    if (scope instanceof Process) {
      flowElement = ((Process) scope).getFlowElement(elementId);
    } else if (scope instanceof SubProcess) {
      flowElement = ((SubProcess) scope).getFlowElement(elementId);
    }
    return flowElement;
  }
 
  public byte[] convertToXML(BpmnModel model) {
    try {

      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     
      XMLOutputFactory xof = XMLOutputFactory.newInstance();
      OutputStreamWriter out = new OutputStreamWriter(outputStream, "UTF-8");

      XMLStreamWriter writer = xof.createXMLStreamWriter(out);
      XMLStreamWriter xtw = new IndentingXMLStreamWriter(writer);

      xtw.writeStartDocument("UTF-8", "1.0");

      // start definitions root element
      xtw.writeStartElement("definitions");
      xtw.setDefaultNamespace(BPMN2_NAMESPACE);
      xtw.writeDefaultNamespace(BPMN2_NAMESPACE);
      xtw.writeNamespace(XSI_PREFIX, XSI_NAMESPACE);
      xtw.writeNamespace(ACTIVITI_EXTENSIONS_PREFIX, ACTIVITI_EXTENSIONS_NAMESPACE);
      xtw.writeNamespace(BPMNDI_PREFIX, BPMNDI_NAMESPACE);
      xtw.writeNamespace(OMGDC_PREFIX, OMGDC_NAMESPACE);
      xtw.writeNamespace(OMGDI_PREFIX, OMGDI_NAMESPACE);
      xtw.writeAttribute(TYPE_LANGUAGE_ATTRIBUTE, SCHEMA_NAMESPACE);
      xtw.writeAttribute(EXPRESSION_LANGUAGE_ATTRIBUTE, XPATH_NAMESPACE);
      xtw.writeAttribute(TARGET_NAMESPACE_ATTRIBUTE, PROCESS_NAMESPACE);
     
      for (FlowElement flowElement : model.getMainProcess().getFlowElements()) {
        if (flowElement instanceof Event) {
          Event event = (Event) flowElement;
          if (event.getEventDefinitions().size() > 0) {
            EventDefinition eventDefinition = event.getEventDefinitions().get(0);
            if (eventDefinition instanceof SignalEventDefinition) {
              SignalEventDefinition signalEvent = (SignalEventDefinition) eventDefinition;
              if (model.containsSignalId(signalEvent.getSignalRef()) == false) {
                model.addSignal(signalEvent.getSignalRef(), signalEvent.getSignalRef());
              }
             
            } else if (eventDefinition instanceof MessageEventDefinition) {
              MessageEventDefinition messageEvent = (MessageEventDefinition) eventDefinition;
              if (model.containsMessageId(messageEvent.getMessageRef()) == false) {
                model.addMessage(messageEvent.getMessageRef(), messageEvent.getMessageRef());
              }
            }
          }
        }
      }
     
      for (Signal signal : model.getSignals()) {
        xtw.writeStartElement(ELEMENT_SIGNAL);
        xtw.writeAttribute(ATTRIBUTE_ID, signal.getId());
        xtw.writeAttribute(ATTRIBUTE_NAME, signal.getName());
        xtw.writeEndElement();
      }
     
      for (Message message : model.getMessages()) {
        xtw.writeStartElement(ELEMENT_MESSAGE);
        xtw.writeAttribute(ATTRIBUTE_ID, message.getId());
        xtw.writeAttribute(ATTRIBUTE_NAME, message.getName());
        xtw.writeEndElement();
      }
     
      if(model.getPools().size() > 0) {
        xtw.writeStartElement(ELEMENT_COLLABORATION);
        xtw.writeAttribute(ATTRIBUTE_ID, "Collaboration");
        for (Pool pool : model.getPools()) {
          xtw.writeStartElement(ELEMENT_PARTICIPANT);
          xtw.writeAttribute(ATTRIBUTE_ID, pool.getId());
          if(StringUtils.isNotEmpty(pool.getName())) {
            xtw.writeAttribute(ATTRIBUTE_NAME, pool.getName());
          }
          xtw.writeAttribute(ATTRIBUTE_PROCESS_REF, pool.getProcessRef());
          xtw.writeEndElement();
        }
        xtw.writeEndElement();
      }
     
      // start process element
      xtw.writeStartElement(ELEMENT_PROCESS);
      xtw.writeAttribute(ATTRIBUTE_ID, model.getMainProcess().getId());
     
      if(StringUtils.isNotEmpty(model.getMainProcess().getName())) {
        xtw.writeAttribute(ATTRIBUTE_NAME, model.getMainProcess().getName());
      }
     
      xtw.writeAttribute(ATTRIBUTE_PROCESS_EXECUTABLE, ATTRIBUTE_VALUE_TRUE);
     
      if (StringUtils.isNotEmpty(model.getMainProcess().getDocumentation())) {

        xtw.writeStartElement(ELEMENT_DOCUMENTATION);
        xtw.writeCharacters(model.getMainProcess().getDocumentation());
        xtw.writeEndElement();
      }
     
      for (FlowElement flowElement : model.getMainProcess().getFlowElements()) {
        createXML(flowElement, xtw);
      }
     
      // end process element
      xtw.writeEndElement();

      // BPMN DI information
      xtw.writeStartElement(BPMNDI_PREFIX, ELEMENT_DI_DIAGRAM, BPMNDI_NAMESPACE);
      xtw.writeAttribute(ATTRIBUTE_ID, "BPMNDiagram_" + model.getMainProcess().getId());

      xtw.writeStartElement(BPMNDI_PREFIX, ELEMENT_DI_PLANE, BPMNDI_NAMESPACE);
      xtw.writeAttribute(ATTRIBUTE_DI_BPMNELEMENT, model.getMainProcess().getId());
      xtw.writeAttribute(ATTRIBUTE_ID, "BPMNPlane_" + model.getMainProcess().getId());
     
      for (String elementId : model.getLocationMap().keySet()) {
        xtw.writeStartElement(BPMNDI_PREFIX, ELEMENT_DI_SHAPE, BPMNDI_NAMESPACE);
        xtw.writeAttribute(ATTRIBUTE_DI_BPMNELEMENT, elementId);
        xtw.writeAttribute(ATTRIBUTE_ID, "BPMNShape_" + elementId);
       
        GraphicInfo graphicInfo = model.getGraphicInfo(elementId);
        xtw.writeStartElement(OMGDC_PREFIX, ELEMENT_DI_BOUNDS, OMGDC_NAMESPACE);
        xtw.writeAttribute(ATTRIBUTE_DI_HEIGHT, "" + graphicInfo.height);
        xtw.writeAttribute(ATTRIBUTE_DI_WIDTH, "" + graphicInfo.width);
        xtw.writeAttribute(ATTRIBUTE_DI_X, "" + graphicInfo.x);
        xtw.writeAttribute(ATTRIBUTE_DI_Y, "" + graphicInfo.y);
        xtw.writeEndElement();
       
        xtw.writeEndElement();
      }
     
      for (String elementId : model.getFlowLocationMap().keySet()) {
        xtw.writeStartElement(BPMNDI_PREFIX, ELEMENT_DI_EDGE, BPMNDI_NAMESPACE);
        xtw.writeAttribute(ATTRIBUTE_DI_BPMNELEMENT, elementId);
        xtw.writeAttribute(ATTRIBUTE_ID, "BPMNEdge_" + elementId);
       
        List<GraphicInfo> graphicInfoList = model.getFlowLocationGraphicInfo(elementId);
        for (GraphicInfo graphicInfo : graphicInfoList) {
          xtw.writeStartElement(OMGDI_PREFIX, ELEMENT_DI_WAYPOINT, OMGDI_NAMESPACE);
          xtw.writeAttribute(ATTRIBUTE_DI_X, "" + graphicInfo.x);
          xtw.writeAttribute(ATTRIBUTE_DI_Y, "" + graphicInfo.y);
          xtw.writeEndElement();
        }
       
        xtw.writeEndElement();
      }
     
      // end BPMN DI elements
      xtw.writeEndElement();
      xtw.writeEndElement();

      // end definitions root element
      xtw.writeEndElement();
      xtw.writeEndDocument();

      xtw.flush();

      outputStream.close();

      xtw.close();
     
      return outputStream.toByteArray();
     
    } catch (Exception e) {
      LOGGER.log(Level.SEVERE, "Error writing BPMN XML", e);
      throw new XMLException("Error writing BPMN XML", e);
    }
  }

  private void createXML(FlowElement flowElement, XMLStreamWriter xtw) throws Exception {
   
    if (flowElement instanceof SubProcess) {
     
      SubProcess subProcess = (SubProcess) flowElement;
      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, "true");
      }
     
      if (StringUtils.isNotEmpty(subProcess.getDocumentation())) {

        xtw.writeStartElement(ELEMENT_DOCUMENTATION);
        xtw.writeCharacters(subProcess.getDocumentation());
        xtw.writeEndElement();
      }
     
      for (FlowElement subElement : subProcess.getFlowElements()) {
        createXML(subElement, xtw);
      }
     
      xtw.writeEndElement();
     
    } else {
   
      Class<? extends BaseBpmnXMLConverter> converter = convertersToXMLMap.get(flowElement.getClass());
     
      if (converter == null) {
        throw new XMLException("No converter for " + flowElement.getClass() + " found");
      }
     
      converter.newInstance().convertToXML(xtw, flowElement);
    }
  }
}
TOP

Related Classes of org.activiti.bpmn.converter.BpmnXMLConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.