Package org.activiti.editor.language.json.converter

Source Code of org.activiti.editor.language.json.converter.BpmnJsonConverter

/* 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.editor.language.json.converter;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import math.geom2d.Point2D;
import math.geom2d.conic.Circle2D;
import math.geom2d.line.Line2D;
import math.geom2d.polygon.Polyline2D;

import org.activiti.bpmn.model.ActivitiListener;
import org.activiti.bpmn.model.Activity;
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.EventListener;
import org.activiti.bpmn.model.FieldExtension;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowElementsContainer;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.GraphicInfo;
import org.activiti.bpmn.model.ImplementationType;
import org.activiti.bpmn.model.IntegerDataObject;
import org.activiti.bpmn.model.ItemDefinition;
import org.activiti.bpmn.model.Lane;
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.ValuedDataObject;
import org.activiti.editor.constants.EditorJsonConstants;
import org.activiti.editor.constants.StencilConstants;
import org.activiti.editor.language.json.converter.util.JsonConverterUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
* @author Tijs Rademakers
*/
public class BpmnJsonConverter implements EditorJsonConstants, StencilConstants, ActivityProcessor {
 
  protected static final Logger LOGGER = LoggerFactory.getLogger(BpmnJsonConverter.class);
 
  protected ObjectMapper objectMapper = new ObjectMapper();
 
  protected static Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap =
      new HashMap<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>>();
 
  protected static Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap =
      new HashMap<String, Class<? extends BaseBpmnJsonConverter>>();
 
  private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
 
  static {
   
    // start and end events
    StartEventJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    EndEventJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
   
    // connectors
    SequenceFlowJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
   
    // task types
    BusinessRuleTaskJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    MailTaskJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    ManualTaskJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    ReceiveTaskJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    ScriptTaskJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    ServiceTaskJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    UserTaskJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    CallActivityJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
   
    // gateways
    ExclusiveGatewayJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    InclusiveGatewayJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    ParallelGatewayJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    EventGatewayJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
   
    // scope constructs
    SubProcessJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
    EventSubProcessJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
   
    // catch events
    CatchEventJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
   
    // throw events
    ThrowEventJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
   
    // boundary events
    BoundaryEventJsonConverter.fillTypes(convertersToBpmnMap, convertersToJsonMap);
  }
 
  private static final List<String> DI_CIRCLES = new ArrayList<String>();
  private static final List<String> DI_RECTANGLES = new ArrayList<String>();
  private static final List<String> DI_GATEWAY = new ArrayList<String>();
 
  static {
    DI_CIRCLES.add(STENCIL_EVENT_START_ERROR);
    DI_CIRCLES.add(STENCIL_EVENT_START_MESSAGE);
    DI_CIRCLES.add(STENCIL_EVENT_START_NONE);
    DI_CIRCLES.add(STENCIL_EVENT_START_TIMER);
   
    DI_CIRCLES.add(STENCIL_EVENT_BOUNDARY_ERROR);
    DI_CIRCLES.add(STENCIL_EVENT_BOUNDARY_SIGNAL);
    DI_CIRCLES.add(STENCIL_EVENT_BOUNDARY_TIMER);
    DI_CIRCLES.add(STENCIL_EVENT_BOUNDARY_MESSAGE);
   
    DI_CIRCLES.add(STENCIL_EVENT_CATCH_MESSAGE);
    DI_CIRCLES.add(STENCIL_EVENT_CATCH_SIGNAL);
    DI_CIRCLES.add(STENCIL_EVENT_CATCH_TIMER);
   
    DI_CIRCLES.add(STENCIL_EVENT_THROW_NONE);
    DI_CIRCLES.add(STENCIL_EVENT_THROW_SIGNAL);
   
    DI_CIRCLES.add(STENCIL_EVENT_END_NONE);
    DI_CIRCLES.add(STENCIL_EVENT_END_ERROR);
   
    DI_RECTANGLES.add(STENCIL_CALL_ACTIVITY);
    DI_RECTANGLES.add(STENCIL_SUB_PROCESS);
    DI_RECTANGLES.add(STENCIL_EVENT_SUB_PROCESS);
    DI_RECTANGLES.add(STENCIL_TASK_BUSINESS_RULE);
    DI_RECTANGLES.add(STENCIL_TASK_MAIL);
    DI_RECTANGLES.add(STENCIL_TASK_MANUAL);
    DI_RECTANGLES.add(STENCIL_TASK_RECEIVE);
    DI_RECTANGLES.add(STENCIL_TASK_SCRIPT);
    DI_RECTANGLES.add(STENCIL_TASK_SERVICE);
    DI_RECTANGLES.add(STENCIL_TASK_USER);
   
    DI_GATEWAY.add(STENCIL_GATEWAY_EVENT);
    DI_GATEWAY.add(STENCIL_GATEWAY_EXCLUSIVE);
    DI_GATEWAY.add(STENCIL_GATEWAY_INCLUSIVE);
    DI_GATEWAY.add(STENCIL_GATEWAY_PARALLEL);
  }

  public ObjectNode convertToJson(BpmnModel model) {
    ObjectNode modelNode = objectMapper.createObjectNode();
    modelNode.put("bounds", BpmnJsonConverterUtil.createBoundsNode(1485, 1050, 0, 0));
    modelNode.put("resourceId", "canvas");
   
    ObjectNode stencilNode = objectMapper.createObjectNode();
    stencilNode.put("id", "BPMNDiagram");
    modelNode.put("stencil", stencilNode);
   
    ObjectNode stencilsetNode = objectMapper.createObjectNode();
    stencilsetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
    stencilsetNode.put("url", "../editor/stencilsets/bpmn2.0/bpmn2.0.json");
    modelNode.put("stencilset", stencilsetNode);
   
    ArrayNode shapesArrayNode = objectMapper.createArrayNode();
   
    Process mainProcess = model.getMainProcess();
   
    ObjectNode propertiesNode = objectMapper.createObjectNode();
    if (StringUtils.isNotEmpty(mainProcess.getId())) {
      propertiesNode.put(PROPERTY_PROCESS_ID, mainProcess.getId());
    }
    if (StringUtils.isNotEmpty(mainProcess.getName())) {
      propertiesNode.put(PROPERTY_NAME, mainProcess.getName());
    }
    if (mainProcess.isExecutable() == false) {
      propertiesNode.put(PROPERTY_PROCESS_EXECUTABLE, PROPERTY_VALUE_NO);
    }
   
    propertiesNode.put(PROPERTY_PROCESS_NAMESPACE, model.getTargetNamespace());
   
    convertListenersToJson(mainProcess.getEventListeners(), propertiesNode);
   
    if (StringUtils.isNotEmpty(mainProcess.getDocumentation())) {
      propertiesNode.put(PROPERTY_DOCUMENTATION, mainProcess.getDocumentation());
    }

    if (!mainProcess.getDataObjects().isEmpty()) {
      convertDataPropertiesToJson(mainProcess.getDataObjects(), propertiesNode);
    }
   
    modelNode.put(EDITOR_SHAPE_PROPERTIES, propertiesNode);
   
    if (!model.getPools().isEmpty()) {
      for (Pool pool : model.getPools()) {
        GraphicInfo poolGraphicInfo = model.getGraphicInfo(pool.getId());
        ObjectNode poolNode = BpmnJsonConverterUtil.createChildShape(pool.getId(), STENCIL_POOL,
            poolGraphicInfo.getX() + poolGraphicInfo.getWidth(), poolGraphicInfo.getY() + poolGraphicInfo.getHeight(), poolGraphicInfo.getX(), poolGraphicInfo.getY());
        shapesArrayNode.add(poolNode);
        ObjectNode poolPropertiesNode = objectMapper.createObjectNode();
        poolPropertiesNode.put(PROPERTY_OVERRIDE_ID, pool.getId());
        poolPropertiesNode.put(PROPERTY_PROCESS_ID, pool.getProcessRef());
        if (pool.isExecutable() == false) {
          poolPropertiesNode.put(PROPERTY_PROCESS_EXECUTABLE, PROPERTY_VALUE_NO);
        }
        if (StringUtils.isNotEmpty(pool.getName())) {
          poolPropertiesNode.put(PROPERTY_NAME, pool.getName());
        }
        poolNode.put(EDITOR_SHAPE_PROPERTIES, poolPropertiesNode);
        poolNode.put(EDITOR_OUTGOING, objectMapper.createArrayNode());
       
        ArrayNode laneShapesArrayNode = objectMapper.createArrayNode();
        poolNode.put(EDITOR_CHILD_SHAPES, laneShapesArrayNode);
       
        Process process = model.getProcess(pool.getId());
        if (process != null) {
         
          processFlowElements(process.findFlowElementsOfType(SequenceFlow.class), model, shapesArrayNode, poolGraphicInfo.getX(), poolGraphicInfo.getY());
         
          for (Lane lane : process.getLanes()) {
            GraphicInfo laneGraphicInfo = model.getGraphicInfo(lane.getId());
            ObjectNode laneNode = BpmnJsonConverterUtil.createChildShape(lane.getId(), STENCIL_LANE,
                laneGraphicInfo.getX() + laneGraphicInfo.getWidth(), laneGraphicInfo.getY() + laneGraphicInfo.getHeight(),
                laneGraphicInfo.getX(), laneGraphicInfo.getY());
            laneShapesArrayNode.add(laneNode);
            ObjectNode lanePropertiesNode = objectMapper.createObjectNode();
            lanePropertiesNode.put(PROPERTY_OVERRIDE_ID, lane.getId());
            if (StringUtils.isNotEmpty(lane.getName())) {
              lanePropertiesNode.put(PROPERTY_NAME, lane.getName());
            }
            laneNode.put(EDITOR_SHAPE_PROPERTIES, lanePropertiesNode);
           
            ArrayNode elementShapesArrayNode = objectMapper.createArrayNode();
            laneNode.put(EDITOR_CHILD_SHAPES, elementShapesArrayNode);
            laneNode.put(EDITOR_OUTGOING, objectMapper.createArrayNode());
           
            for (FlowElement flowElement : process.getFlowElements()) {
              if (lane.getFlowReferences().contains(flowElement.getId())) {
                Class<? extends BaseBpmnJsonConverter> converter = convertersToJsonMap.get(flowElement.getClass());
                if (converter != null) {
                  try {
                    converter.newInstance().convertToJson(flowElement, this, model, elementShapesArrayNode,
                        laneGraphicInfo.getX(), laneGraphicInfo.getY());
                  } catch (Exception e) {
                    LOGGER.error("Error converting {}", flowElement, e);
                  }
                }
              }
            }
          }
        }
       
      }
    } else {
      processFlowElements(model.getMainProcess().getFlowElements(), model, shapesArrayNode, 0.0, 0.0);
    }
   
    modelNode.put(EDITOR_CHILD_SHAPES, shapesArrayNode);
    return modelNode;
  }
 
  @Override
  public void processFlowElements(Collection<? extends FlowElement> flowElements, BpmnModel model, ArrayNode shapesArrayNode,
      double subProcessX, double subProcessY) {
   
    for (FlowElement flowElement : flowElements) {
      Class<? extends BaseBpmnJsonConverter> converter = convertersToJsonMap.get(flowElement.getClass());
      if (converter != null) {
        try {
          converter.newInstance().convertToJson(flowElement, this, model, shapesArrayNode,
              subProcessX, subProcessY);
        } catch (Exception e) {
          LOGGER.error("Error converting {}", flowElement, e);
        }
      }
    }
  }
 
  public BpmnModel convertToBpmnModel(JsonNode modelNode) {
    BpmnModel bpmnModel = new BpmnModel();
    Map<String, JsonNode> shapeMap = new HashMap<String, JsonNode>();
    Map<String, JsonNode> sourceRefMap = new HashMap<String, JsonNode>();
    Map<String, JsonNode> edgeMap = new HashMap<String, JsonNode>();
    Map<String, List<JsonNode>> sourceAndTargetMap = new HashMap<String, List<JsonNode>>();
    readShapeDI(modelNode, 0, 0, shapeMap, sourceRefMap, bpmnModel);
    filterAllEdges(modelNode, edgeMap, sourceAndTargetMap, shapeMap, sourceRefMap);
    readEdgeDI(edgeMap, sourceAndTargetMap, bpmnModel);
   
    ArrayNode shapesArrayNode = (ArrayNode) modelNode.get(EDITOR_CHILD_SHAPES);
   
    boolean emptyPoolFound = true;
    // first create the pool structure
    for (JsonNode shapeNode : shapesArrayNode) {
      String stencilId = BpmnJsonConverterUtil.getStencilId(shapeNode);
      if (STENCIL_POOL.equals(stencilId)) {
        Pool pool = new Pool();
        pool.setId(BpmnJsonConverterUtil.getElementId(shapeNode));
        pool.setName(JsonConverterUtil.getPropertyValueAsString(PROPERTY_NAME, shapeNode));
        pool.setProcessRef(JsonConverterUtil.getPropertyValueAsString(PROPERTY_PROCESS_ID, shapeNode));
        pool.setExecutable(JsonConverterUtil.getPropertyValueAsBoolean(PROPERTY_PROCESS_EXECUTABLE, shapeNode, true));
        bpmnModel.getPools().add(pool);
       
        Process process = new Process();
        process.setId(pool.getProcessRef());
        process.setName(pool.getName());
        process.setExecutable(pool.isExecutable());
        bpmnModel.addProcess(process);
       
        processJsonElements(shapesArrayNode, modelNode, process, shapeMap);
       
        ArrayNode laneArrayNode = (ArrayNode) shapeNode.get(EDITOR_CHILD_SHAPES);
        for (JsonNode laneNode : laneArrayNode) {
          // should be a lane, but just check to be certain
          String laneStencilId = BpmnJsonConverterUtil.getStencilId(laneNode);
          if (STENCIL_LANE.equals(laneStencilId)) {
            emptyPoolFound = false;
            Lane lane = new Lane();
            lane.setId(BpmnJsonConverterUtil.getElementId(laneNode));
            lane.setName(JsonConverterUtil.getPropertyValueAsString(PROPERTY_NAME, laneNode));
            lane.setParentProcess(process);
            process.getLanes().add(lane);
           
            processJsonElements(laneNode.get(EDITOR_CHILD_SHAPES), modelNode, lane, shapeMap);
          }
        }
      }
    }
   
    if (emptyPoolFound) {
     
      JsonNode processIdNode = JsonConverterUtil.getProperty(PROPERTY_PROCESS_ID, modelNode);
      Process process = new Process();
      bpmnModel.getProcesses().add(process);
      if (processIdNode != null && StringUtils.isNotEmpty(processIdNode.asText())) {
        process.setId(processIdNode.asText());
      }
     
      JsonNode processNameNode = JsonConverterUtil.getProperty(PROPERTY_NAME, modelNode);
      if (processNameNode != null && StringUtils.isNotEmpty(processNameNode.asText())) {
        process.setName(processNameNode.asText());
      }
     
      JsonNode processExecutableNode = JsonConverterUtil.getProperty(PROPERTY_PROCESS_EXECUTABLE, modelNode);
      if (processExecutableNode != null && StringUtils.isNotEmpty(processExecutableNode.asText())) {
        process.setExecutable(JsonConverterUtil.getPropertyValueAsBoolean(PROPERTY_PROCESS_EXECUTABLE, modelNode));
      }
     
      JsonNode processTargetNamespace = JsonConverterUtil.getProperty(PROPERTY_PROCESS_NAMESPACE, modelNode);
      if (processTargetNamespace != null && StringUtils.isNotEmpty(processTargetNamespace.asText())) {
        bpmnModel.setTargetNamespace(processTargetNamespace.asText());
      }
     
      JsonNode processExecutionListenerNode = modelNode.get(EDITOR_SHAPE_PROPERTIES).get(PROPERTY_EXECUTION_LISTENERS);
      if (processExecutionListenerNode != null && StringUtils.isNotEmpty(processExecutionListenerNode.asText())){
        process.setExecutionListeners(convertJsonToListeners(processExecutionListenerNode));
      }
     
      JsonNode processEventListenerNode = modelNode.get(EDITOR_SHAPE_PROPERTIES).get(PROPERTY_EVENT_LISTENERS);
      if (processEventListenerNode != null){
        process.setEventListeners(convertJsonToEventListeners(processEventListenerNode));
      }
     
      JsonNode processDataPropertiesNode = modelNode.get(EDITOR_SHAPE_PROPERTIES).get(PROPERTY_DATA_PROPERTIES);

      if (processDataPropertiesNode != null) {
        List<ValuedDataObject> dataObjects = convertJsonToDataProperties(processDataPropertiesNode, process);
        process.setDataObjects(dataObjects);
        process.getFlowElements().addAll(dataObjects);
      }

      processJsonElements(shapesArrayNode, modelNode, process, shapeMap);
    }
   
    // sequence flows are now all on root level
    Map<String, SubProcess> subShapesMap = new HashMap<String, SubProcess>();
    for (Process process : bpmnModel.getProcesses()) {
      for (FlowElement flowElement : process.findFlowElementsOfType(SubProcess.class)) {
        SubProcess subProcess = (SubProcess) flowElement;
        fillSubShapes(subShapesMap, subProcess);
      }
     
      if (!subShapesMap.isEmpty()) {
        List<String> removeSubFlowsList = new ArrayList<String>();
        List<SequenceFlow> sequenceFlowList = process.findFlowElementsOfType(SequenceFlow.class);
        for (FlowElement flowElement : sequenceFlowList) {
          SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
          if (process.getFlowElement(flowElement.getId()) != null && subShapesMap.containsKey(sequenceFlow.getSourceRef())) {
            SubProcess subProcess = subShapesMap.get(sequenceFlow.getSourceRef());
            subProcess.addFlowElement(sequenceFlow);
            removeSubFlowsList.add(sequenceFlow.getId());
          }
        }
        for (String flowId : removeSubFlowsList) {
          process.removeFlowElement(flowId);
        }
      }
    }
   
    // boundary events only contain attached ref id
    for (Process process : bpmnModel.getProcesses()) {
      postProcessElements(process, process.getFlowElements());
    }
   
    return bpmnModel;
  }
 
  @Override
  public void processJsonElements(JsonNode shapesArrayNode, JsonNode modelNode,
      BaseElement parentElement, Map<String, JsonNode> shapeMap) {
   
    for (JsonNode shapeNode : shapesArrayNode) {
      Class<? extends BaseBpmnJsonConverter> converter = convertersToBpmnMap.get(BpmnJsonConverterUtil.getStencilId(shapeNode));
      if (converter != null) {
        try {
          converter.newInstance().convertToBpmnModel(shapeNode, modelNode, this, parentElement, shapeMap);
        } catch (Exception e) {
          LOGGER.error("Error converting {}", BpmnJsonConverterUtil.getStencilId(shapeNode), e);
        }
      }
    }
  }
 
  private List<ActivitiListener> convertJsonToListeners(JsonNode listenersNode) {
    List<ActivitiListener> executionListeners = new ArrayList<ActivitiListener>();
   
    try {
      listenersNode = objectMapper.readTree(listenersNode.asText());
    } catch (Exception e) {
      LOGGER.info("Listeners node can not be read", e);
    }
     
    JsonNode itemsArrayNode = listenersNode.get(EDITOR_PROPERTIES_GENERAL_ITEMS);
    if (itemsArrayNode != null) {
      for (JsonNode itemNode : itemsArrayNode) {
        JsonNode typeNode = itemNode.get(PROPERTY_EXECUTION_LISTENER_EVENT);
        if (typeNode != null && StringUtils.isNotEmpty(typeNode.asText())) {

          ActivitiListener listener = new ActivitiListener();
          listener.setEvent(typeNode.asText());
          if (StringUtils.isNotEmpty(itemNode.get(PROPERTY_EXECUTION_LISTENER_CLASS).asText())) {
            listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
            listener.setImplementation(itemNode.get(PROPERTY_EXECUTION_LISTENER_CLASS).asText());
          } else if (StringUtils.isNotEmpty(itemNode.get(PROPERTY_EXECUTION_LISTENER_EXPRESSION).asText())) {
            listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
            listener.setImplementation(itemNode.get(PROPERTY_EXECUTION_LISTENER_EXPRESSION).asText());
          } else if (StringUtils.isNotEmpty(itemNode.get(PROPERTY_EXECUTION_LISTENER_DELEGATEEXPRESSION).asText())) {
            listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
            listener.setImplementation(itemNode.get(PROPERTY_EXECUTION_LISTENER_DELEGATEEXPRESSION).asText());
          }
         
          // resolve the listener feild
          JsonNode listenerFieldsNode = null;
          JsonNode listenerFieldsArrayNode = null;
          listenerFieldsNode = itemNode.get(PROPERTY_EXECUTION_LISTENER_FIELDS);
          if (listenerFieldsNode != null && StringUtils.isNotEmpty(listenerFieldsNode.asText()) && !("undefined".equals(listenerFieldsNode.asText()))){
            if(listenerFieldsNode.isValueNode()){
              try{
                listenerFieldsNode = objectMapper.readTree(listenerFieldsNode.asText());
              } catch(Exception e){
                LOGGER.info("Listener fields node can not be read", e);
              }
            }
          }
          if (listenerFieldsNode != null) {
            listenerFieldsArrayNode = listenerFieldsNode.get(EDITOR_PROPERTIES_GENERAL_ITEMS);
            List<FieldExtension> fields = new ArrayList<FieldExtension>();
            if (listenerFieldsArrayNode != null) {
              for (JsonNode fieldNode : listenerFieldsArrayNode){
                JsonNode fieldNameNode = fieldNode.get(PROPERTY_EXECUTION_LISTENER_FIELD_NAME);
                if (fieldNameNode != null && StringUtils.isNotEmpty(fieldNameNode.asText())){
                  FieldExtension field = new FieldExtension();
                  field.setFieldName(fieldNameNode.asText());
                  field.setStringValue(getValueAsString(PROPERTY_EXECUTION_LISTENER_FIELD_VALUE, fieldNode));
                  field.setExpression(getValueAsString(PROPERTY_EXECUTION_LISTENER_EXPRESSION, fieldNode));
                  fields.add(field);
                }
              }
            }
            listener.setFieldExtensions(fields);
          }
         
          executionListeners.add(listener);
        }
      }
    }
    return executionListeners;
  }
 
  private String getValueAsString(String name, JsonNode objectNode) {
    String propertyValue = null;
    JsonNode propertyNode = objectNode.get(name);
    if (propertyNode != null && "null".equalsIgnoreCase(propertyNode.asText()) == false) {
      propertyValue = propertyNode.asText();
    }
    return propertyValue;
  }
 
  private List<EventListener> convertJsonToEventListeners(JsonNode listenersNode) {
    List<EventListener> eventListeners = new ArrayList<EventListener>();
    if (StringUtils.isEmpty(listenersNode.asText())) return eventListeners;
    try {
      listenersNode = objectMapper.readTree(listenersNode.asText());
    } catch (Exception e) {
      LOGGER.info("Event listeners node can not be read", e);
    }
     
    JsonNode itemsArrayNode = listenersNode.get(EDITOR_PROPERTIES_GENERAL_ITEMS);
    if (itemsArrayNode != null) {
      for (JsonNode itemNode : itemsArrayNode) {
        EventListener listener = new EventListener();
        if (isNotEmpty(PROPERTY_EVENT_LISTENER_EVENTS, itemNode)) {
          listener.setEvents(itemNode.get(PROPERTY_EVENT_LISTENER_EVENTS).asText());
        }
       
        if (isNotEmpty(PROPERTY_EVENT_LISTENER_ENTITY_TYPE, itemNode)) {
          listener.setEntityType(itemNode.get(PROPERTY_EVENT_LISTENER_ENTITY_TYPE).asText());
        }
       
        if (isNotEmpty(PROPERTY_EVENT_LISTENER_CLASS, itemNode)) {
          listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
          listener.setImplementation(itemNode.get(PROPERTY_EVENT_LISTENER_CLASS).asText());
        } else if (isNotEmpty(PROPERTY_EVENT_LISTENER_DELEGATEEXPRESSION, itemNode)) {
          listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
          listener.setImplementation(itemNode.get(PROPERTY_EVENT_LISTENER_DELEGATEEXPRESSION).asText());
        } else if (isNotEmpty(PROPERTY_EVENT_LISTENER_THROW_EVENT, itemNode)) {
          String throwEventType = itemNode.get(PROPERTY_EVENT_LISTENER_THROW_EVENT).asText();
          if(PROPERTY_EVENT_LISTENER_THROW_SIGNAL.equals(throwEventType)) {
            listener.setImplementation(itemNode.get(PROPERTY_EVENT_LISTENER_THROW_REFERENCE).asText());
            listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_THROW_SIGNAL_EVENT);
          else if(PROPERTY_EVENT_LISTENER_THROW_GLOBAL_SIGNAL.equals(throwEventType)) {
            listener.setImplementation(itemNode.get(PROPERTY_EVENT_LISTENER_THROW_REFERENCE).asText());
            listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_THROW_GLOBAL_SIGNAL_EVENT);
          else if(PROPERTY_EVENT_LISTENER_THROW_MESSAGE.equals(throwEventType)) {
            listener.setImplementation(itemNode.get(PROPERTY_EVENT_LISTENER_THROW_REFERENCE).asText());
            listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_THROW_MESSAGE_EVENT);
          } else if(PROPERTY_EVENT_LISTENER_THROW_ERROR.equals(throwEventType)) {
            listener.setImplementation(itemNode.get(PROPERTY_EVENT_LISTENER_THROW_REFERENCE).asText());
            listener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_THROW_ERROR_EVENT);
          } else {
            // Not a valid throw event type, ignore this listener definition
            listener = null;
          }
        } else {
          // No properties have been provided to have a valid implementation
          listener = null;
        }

        if(listener != null) {
          eventListeners.add(listener);
        }
      }
    }
    return eventListeners;
  }
 
  protected List<ValuedDataObject> convertJsonToDataProperties(JsonNode objectNode, BaseElement element) {
    List<ValuedDataObject> dataObjects = new ArrayList<ValuedDataObject>();

    if (objectNode != null) {
      if (objectNode.isValueNode() && StringUtils.isNotEmpty(objectNode.asText())) {
        try {
          objectNode = objectMapper.readTree(objectNode.asText());
        } catch (Exception e) {
          LOGGER.info("Data properties node cannot be read", e);
        }
      }

      JsonNode itemsArrayNode = objectNode.get(EDITOR_PROPERTIES_GENERAL_ITEMS);
      if (itemsArrayNode != null) {
        for (JsonNode dataNode : itemsArrayNode) {

          JsonNode dataIdNode = dataNode.get(PROPERTY_DATA_ID);
          if (dataIdNode != null && StringUtils.isNotEmpty(dataIdNode.asText())) {
            ValuedDataObject dataObject = null;
            ItemDefinition itemSubjectRef = new ItemDefinition();
            String dataType = dataNode.get(PROPERTY_DATA_TYPE).asText();

            if (dataType.equals("string")) {
              dataObject = new StringDataObject();
            } else if (dataType.equals("int")) {
              dataObject = new IntegerDataObject();
            } else if (dataType.equals("long")) {
              dataObject = new LongDataObject();
            } else if (dataType.equals("double")) {
              dataObject = new DoubleDataObject();
            } else if (dataType.equals("boolean")) {
              dataObject = new BooleanDataObject();
            } else if (dataType.equals("datetime")) {
              dataObject = new DateDataObject();
            } else {
              LOGGER.error("Error converting {}", dataIdNode.asText());
            }

            if (null != dataObject) {
              dataObject.setId(dataIdNode.asText());
              dataObject.setName(dataNode.get(PROPERTY_DATA_NAME).asText());

              itemSubjectRef.setStructureRef("xsd:" + dataType);
              dataObject.setItemSubjectRef(itemSubjectRef);

              if (dataObject instanceof DateDataObject) {
                try {
                  dataObject.setValue(sdf.parse(dataNode.get(PROPERTY_DATA_VALUE).asText()));
                } catch (Exception e) {
                  LOGGER.error("Error converting {}", dataObject.getName(), e);
                }
              } else {
                dataObject.setValue(dataNode.get(PROPERTY_DATA_VALUE).asText());
              }

              dataObjects.add(dataObject);
            }
          }
        }
      }
    }
    return dataObjects;
  }

  protected void convertDataPropertiesToJson(List<ValuedDataObject> dataObjects, ObjectNode propertiesNode) {
    ObjectNode dataPropertiesNode = objectMapper.createObjectNode();
    ArrayNode itemsNode = objectMapper.createArrayNode();

    for (ValuedDataObject dObj : dataObjects) {
      ObjectNode propertyItemNode = objectMapper.createObjectNode();
      propertyItemNode.put(PROPERTY_DATA_ID, dObj.getId());
      propertyItemNode.put(PROPERTY_DATA_NAME, dObj.getName());

      String itemSubjectRefQName = dObj.getItemSubjectRef().getStructureRef();
      // remove namespace prefix
      String dataType = itemSubjectRefQName.substring(itemSubjectRefQName.indexOf(':') + 1);
      propertyItemNode.put(PROPERTY_DATA_TYPE, dataType);

      Object dObjValue = dObj.getValue();
      String value = new String();
      if (null == dObjValue)
      {
        propertyItemNode.put(PROPERTY_DATA_VALUE, "");
      }
      else
      {
        if ("datetime". equals(dataType)) {
          value = sdf.format(dObjValue);
        } else {
          value = new String(dObjValue.toString());
        }
        propertyItemNode.put(PROPERTY_DATA_VALUE, value.toString());
      }

      itemsNode.add(propertyItemNode);
    }

    dataPropertiesNode.put("totalCount", itemsNode.size());
    dataPropertiesNode.put(EDITOR_PROPERTIES_GENERAL_ITEMS, itemsNode);
    propertiesNode.put("dataproperties", dataPropertiesNode);
  }
 
  private boolean isNotEmpty(String propertyName, JsonNode node) {
    JsonNode value = node.get(propertyName);
    if(value != null) {
      return StringUtils.isNotEmpty(value.asText());
    }
    return false;
  }
 
  private void fillSubShapes(Map<String, SubProcess> subShapesMap, SubProcess subProcess) {
    for (FlowElement flowElement : subProcess.getFlowElements()) {
      if (flowElement instanceof SubProcess) {
        SubProcess childSubProcess = (SubProcess) flowElement;
        fillSubShapes(subShapesMap, childSubProcess);
      } else {
        subShapesMap.put(flowElement.getId(), subProcess);
      }
    }
  }
 
 
  private void postProcessElements(FlowElementsContainer process, Collection<FlowElement> flowElementList) {
   
    for (FlowElement flowElement : flowElementList) {
     
      if (flowElement instanceof BoundaryEvent) {
        BoundaryEvent boundaryEvent = (BoundaryEvent) flowElement;
        Activity activity = retrieveAttachedRefObject(boundaryEvent.getAttachedToRefId(), process.getFlowElements());
       
        if (activity == null) {
          LOGGER.warn("Boundary event " + boundaryEvent.getId() + " is not attached to any activity");
        } else {
          boundaryEvent.setAttachedToRef(activity);
          activity.getBoundaryEvents().add(boundaryEvent);
        }
      } else if (flowElement instanceof SubProcess) {
        SubProcess subProcess = (SubProcess) flowElement;
        postProcessElements(subProcess, subProcess.getFlowElements());
      } else if (flowElement instanceof SequenceFlow) {
      SequenceFlow sequenceFlow = (SequenceFlow) flowElement;
      FlowElement sourceFlowElement = process.getFlowElement(sequenceFlow.getSourceRef()) ;
      if(sourceFlowElement instanceof FlowNode) {
        ((FlowNode) sourceFlowElement).getOutgoingFlows().add(sequenceFlow);
      }
      FlowElement targerFlowElement = process.getFlowElement(sequenceFlow.getTargetRef()) ;
      if(targerFlowElement instanceof FlowNode) {
        ((FlowNode) targerFlowElement).getIncomingFlows().add(sequenceFlow);
      }
    }
    }
  }
  
  private Activity retrieveAttachedRefObject(String attachedToRefId, Collection<FlowElement> flowElementList) {
    for (FlowElement flowElement : flowElementList) {
      if (attachedToRefId.equals(flowElement.getId())) {
        return (Activity) flowElement;
      } else if (flowElement instanceof SubProcess) {
        SubProcess subProcess = (SubProcess) flowElement;
        Activity activity = retrieveAttachedRefObject(attachedToRefId, subProcess.getFlowElements());
        if (activity != null) {
          return activity;
        }
      }
    }
    return null;
  }
 
  private void readShapeDI(JsonNode objectNode, double parentX, double parentY,
      Map<String, JsonNode> shapeMap, Map<String, JsonNode> sourceRefMap, BpmnModel bpmnModel) {
   
    if (objectNode.get(EDITOR_CHILD_SHAPES) != null) {
      for (JsonNode jsonChildNode : objectNode.get(EDITOR_CHILD_SHAPES)) {
       
        String stencilId = BpmnJsonConverterUtil.getStencilId(jsonChildNode);
        if (STENCIL_SEQUENCE_FLOW.equals(stencilId) == false) {
         
          GraphicInfo graphicInfo = new GraphicInfo();
         
          JsonNode boundsNode = jsonChildNode.get(EDITOR_BOUNDS);
          ObjectNode upperLeftNode = (ObjectNode) boundsNode.get(EDITOR_BOUNDS_UPPER_LEFT);
          graphicInfo.setX(upperLeftNode.get(EDITOR_BOUNDS_X).asDouble() + parentX);
          graphicInfo.setY(upperLeftNode.get(EDITOR_BOUNDS_Y).asDouble() + parentY);
         
          ObjectNode lowerRightNode = (ObjectNode) boundsNode.get(EDITOR_BOUNDS_LOWER_RIGHT);
          graphicInfo.setWidth(lowerRightNode.get(EDITOR_BOUNDS_X).asDouble() - graphicInfo.getX() + parentX);
          graphicInfo.setHeight(lowerRightNode.get(EDITOR_BOUNDS_Y).asDouble() - graphicInfo.getY() + parentY);
         
          String childShapeId = jsonChildNode.get(EDITOR_SHAPE_ID).asText();
          bpmnModel.addGraphicInfo(BpmnJsonConverterUtil.getElementId(jsonChildNode), graphicInfo);
         
          shapeMap.put(childShapeId, jsonChildNode);
         
          ArrayNode outgoingNode = (ArrayNode) jsonChildNode.get("outgoing");
          if (outgoingNode != null && outgoingNode.size() > 0) {
            for (JsonNode outgoingChildNode : outgoingNode) {
              JsonNode resourceNode = outgoingChildNode.get(EDITOR_SHAPE_ID);
              if (resourceNode != null) {
                sourceRefMap.put(resourceNode.asText(), jsonChildNode);
              }
            }
          }
         
          readShapeDI(jsonChildNode, graphicInfo.getX(), graphicInfo.getY(), shapeMap, sourceRefMap, bpmnModel);
        }
      }
    }
  }
 
  private void filterAllEdges(JsonNode objectNode,
      Map<String, JsonNode> edgeMap, Map<String, List<JsonNode>> sourceAndTargetMap,
      Map<String, JsonNode> shapeMap, Map<String, JsonNode> sourceRefMap) {
   
    if (objectNode.get(EDITOR_CHILD_SHAPES) != null) {
      for (JsonNode jsonChildNode : objectNode.get(EDITOR_CHILD_SHAPES)) {
       
        ObjectNode childNode = (ObjectNode) jsonChildNode;
        String stencilId = BpmnJsonConverterUtil.getStencilId(childNode);
        if (STENCIL_SUB_PROCESS.equals(stencilId)) {
          filterAllEdges(childNode, edgeMap, sourceAndTargetMap, shapeMap, sourceRefMap);
         
        } else if (STENCIL_SEQUENCE_FLOW.equals(stencilId)) {
         
          String childEdgeId = BpmnJsonConverterUtil.getElementId(childNode);
          String targetRefId = childNode.get("target").get(EDITOR_SHAPE_ID).asText();
          List<JsonNode> sourceAndTargetList = new ArrayList<JsonNode>();
          sourceAndTargetList.add(sourceRefMap.get(childNode.get(EDITOR_SHAPE_ID).asText()));
          sourceAndTargetList.add(shapeMap.get(targetRefId));
         
          edgeMap.put(childEdgeId, childNode);
          sourceAndTargetMap.put(childEdgeId, sourceAndTargetList);
        }
      }
    }
  }
 
  public void convertListenersToJson(List<EventListener> eventListeners, ObjectNode propertiesNode) {
    ObjectNode listenersNode = objectMapper.createObjectNode();
    ArrayNode itemsNode = objectMapper.createArrayNode();
    for (EventListener listener : eventListeners) {
      ObjectNode propertyItemNode = objectMapper.createObjectNode();
     
      propertyItemNode.put(PROPERTY_EVENT_LISTENER_EVENTS, listener.getEvents());
      propertyItemNode.put(PROPERTY_EVENT_LISTENER_ENTITY_TYPE, listener.getEntityType());
     
      if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(listener.getImplementationType())) {
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_CLASS, listener.getImplementation());
      } else if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(listener.getImplementationType())) {
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_DELEGATEEXPRESSION, listener.getImplementation());
      } else if(ImplementationType.IMPLEMENTATION_TYPE_THROW_SIGNAL_EVENT.equals(listener.getImplementationType())) {
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_THROW_EVENT, PROPERTY_EVENT_LISTENER_THROW_SIGNAL);
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_THROW_REFERENCE, listener.getImplementation());
      } else if(ImplementationType.IMPLEMENTATION_TYPE_THROW_GLOBAL_SIGNAL_EVENT.equals(listener.getImplementationType())) {
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_THROW_EVENT, PROPERTY_EVENT_LISTENER_THROW_GLOBAL_SIGNAL);
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_THROW_REFERENCE, listener.getImplementation());
      } else if(ImplementationType.IMPLEMENTATION_TYPE_THROW_MESSAGE_EVENT.equals(listener.getImplementationType())) {
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_THROW_EVENT, PROPERTY_EVENT_LISTENER_THROW_MESSAGE);
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_THROW_REFERENCE, listener.getImplementation());
      } else if(ImplementationType.IMPLEMENTATION_TYPE_THROW_ERROR_EVENT.equals(listener.getImplementationType())) {
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_THROW_EVENT, PROPERTY_EVENT_LISTENER_THROW_ERROR);
        propertyItemNode.put(PROPERTY_EVENT_LISTENER_THROW_REFERENCE, listener.getImplementation());
      }
      itemsNode.add(propertyItemNode);
    }
   
    listenersNode.put("totalCount", itemsNode.size());
    listenersNode.put(EDITOR_PROPERTIES_GENERAL_ITEMS, itemsNode);
    propertiesNode.put(PROPERTY_EVENT_LISTENERS, listenersNode);
  }
 
  private void readEdgeDI(Map<String, JsonNode> edgeMap, Map<String, List<JsonNode>> sourceAndTargetMap, BpmnModel bpmnModel) {
    for (String edgeId : edgeMap.keySet()) {
     
      JsonNode edgeNode = edgeMap.get(edgeId);
      List<JsonNode> sourceAndTargetList = sourceAndTargetMap.get(edgeId);
     
      JsonNode sourceRefNode = sourceAndTargetList.get(0);
      JsonNode targetRefNode = sourceAndTargetList.get(1);
     
      if (sourceRefNode == null) {
        LOGGER.info("Skipping edge {} because source ref is null", edgeId);
        continue;
      }
     
      if (targetRefNode == null) {
        LOGGER.info("Skipping edge {} because target ref is null", edgeId);
        continue;
      }
     
      JsonNode dockersNode = edgeNode.get(EDITOR_DOCKERS);
      double sourceDockersX = dockersNode.get(0).get(EDITOR_BOUNDS_X).doubleValue();
      double sourceDockersY = dockersNode.get(0).get(EDITOR_BOUNDS_Y).doubleValue();
     
      GraphicInfo sourceInfo = bpmnModel.getGraphicInfo(BpmnJsonConverterUtil.getElementId(sourceRefNode));
      GraphicInfo targetInfo = bpmnModel.getGraphicInfo(BpmnJsonConverterUtil.getElementId(targetRefNode));
     
      /*JsonNode sourceRefBoundsNode = sourceRefNode.get(EDITOR_BOUNDS);
      BoundsLocation sourceRefUpperLeftLocation = getLocation(EDITOR_BOUNDS_UPPER_LEFT, sourceRefBoundsNode);
      BoundsLocation sourceRefLowerRightLocation = getLocation(EDITOR_BOUNDS_LOWER_RIGHT, sourceRefBoundsNode);
     
      JsonNode targetRefBoundsNode = targetRefNode.get(EDITOR_BOUNDS);
      BoundsLocation targetRefUpperLeftLocation = getLocation(EDITOR_BOUNDS_UPPER_LEFT, targetRefBoundsNode);
      BoundsLocation targetRefLowerRightLocation = getLocation(EDITOR_BOUNDS_LOWER_RIGHT, targetRefBoundsNode);*/
     
      double sourceRefLineX = sourceInfo.getX() + sourceDockersX;
      double sourceRefLineY = sourceInfo.getY() + sourceDockersY;
     
      double nextPointInLineX;
      double nextPointInLineY;
     
      nextPointInLineX = dockersNode.get(1).get(EDITOR_BOUNDS_X).doubleValue();
      nextPointInLineY = dockersNode.get(1).get(EDITOR_BOUNDS_Y).doubleValue();
      if (dockersNode.size() == 2) {
        nextPointInLineX += targetInfo.getX();
        nextPointInLineY += targetInfo.getY();
      }
     
      Line2D firstLine = new Line2D(sourceRefLineX, sourceRefLineY, nextPointInLineX, nextPointInLineY);
     
      String sourceRefStencilId = BpmnJsonConverterUtil.getStencilId(sourceRefNode);
      String targetRefStencilId = BpmnJsonConverterUtil.getStencilId(targetRefNode);
     
      List<GraphicInfo> graphicInfoList = new ArrayList<GraphicInfo>();
     
      if (DI_CIRCLES.contains(sourceRefStencilId)) {
        Circle2D eventCircle = new Circle2D(sourceInfo.getX() + sourceDockersX,
            sourceInfo.getY() + sourceDockersY, sourceDockersX);
       
        Collection<Point2D> intersections = eventCircle.intersections(firstLine);
        Point2D intersection = intersections.iterator().next();
        graphicInfoList.add(createGraphicInfo(intersection.getX(), intersection.getY()));
     
      } else if (DI_RECTANGLES.contains(sourceRefStencilId)) {
        Polyline2D rectangle = createRectangle(sourceInfo);
       
        Collection<Point2D> intersections = rectangle.intersections(firstLine);
        Point2D intersection = intersections.iterator().next();
        graphicInfoList.add(createGraphicInfo(intersection.getX(), intersection.getY()));
     
      } else if (DI_GATEWAY.contains(sourceRefStencilId)) {
        Polyline2D gatewayRectangle = createGateway(sourceInfo);
       
        Collection<Point2D> intersections = gatewayRectangle.intersections(firstLine);
        Point2D intersection = intersections.iterator().next();
        graphicInfoList.add(createGraphicInfo(intersection.getX(), intersection.getY()));
      }
     
      Line2D lastLine = null;
     
      if (dockersNode.size() > 2) {
        for(int i = 1; i < dockersNode.size() - 1; i++) {
          double x = dockersNode.get(i).get(EDITOR_BOUNDS_X).doubleValue();
          double y = dockersNode.get(i).get(EDITOR_BOUNDS_Y).doubleValue();
          graphicInfoList.add(createGraphicInfo(x, y));
        }
       
        double startLastLineX = dockersNode.get(dockersNode.size() - 2).get(EDITOR_BOUNDS_X).doubleValue();
        double startLastLineY = dockersNode.get(dockersNode.size() - 2).get(EDITOR_BOUNDS_Y).doubleValue();
       
        double endLastLineX = dockersNode.get(dockersNode.size() - 1).get(EDITOR_BOUNDS_X).doubleValue();
        double endLastLineY = dockersNode.get(dockersNode.size() - 1).get(EDITOR_BOUNDS_Y).doubleValue();
       
        endLastLineX += targetInfo.getX();
        endLastLineY += targetInfo.getY();
       
        lastLine = new Line2D(startLastLineX, startLastLineY, endLastLineX, endLastLineY);
       
      } else {
        lastLine = firstLine;
      }
     
      if (DI_RECTANGLES.contains(targetRefStencilId)) {
        Polyline2D rectangle = createRectangle(targetInfo);
       
        Collection<Point2D> intersections = rectangle.intersections(lastLine);
        Point2D intersection = intersections.iterator().next();
        graphicInfoList.add(createGraphicInfo(intersection.getX(), intersection.getY()));
       
      } else if (DI_CIRCLES.contains(targetRefStencilId)) {
       
        double targetDockersX = dockersNode.get(dockersNode.size() - 1).get(EDITOR_BOUNDS_X).doubleValue();
        double targetDockersY = dockersNode.get(dockersNode.size() - 1).get(EDITOR_BOUNDS_Y).doubleValue();
       
        Circle2D eventCircle = new Circle2D(targetInfo.getX() + targetDockersX,
            targetInfo.getY() + targetDockersY, targetDockersX);
       
        Collection<Point2D> intersections = eventCircle.intersections(lastLine);
        Point2D intersection = intersections.iterator().next();
        graphicInfoList.add(createGraphicInfo(intersection.getX(), intersection.getY()));
       
      } else if (DI_GATEWAY.contains(targetRefStencilId)) {
        Polyline2D gatewayRectangle = createGateway(targetInfo);
       
        Collection<Point2D> intersections = gatewayRectangle.intersections(lastLine);
        Point2D intersection = intersections.iterator().next();
        graphicInfoList.add(createGraphicInfo(intersection.getX(), intersection.getY()));
      }
     
      bpmnModel.addFlowGraphicInfoList(edgeId, graphicInfoList);
    }
  }
 
  private Polyline2D createRectangle(GraphicInfo graphicInfo) {
    Polyline2D rectangle = new Polyline2D(new Point2D(graphicInfo.getX(), graphicInfo.getY()),
        new Point2D(graphicInfo.getX() + graphicInfo.getWidth(), graphicInfo.getY()),
        new Point2D(graphicInfo.getX() + graphicInfo.getWidth(), graphicInfo.getY() + graphicInfo.getHeight()),
        new Point2D(graphicInfo.getX(), graphicInfo.getY() + graphicInfo.getHeight()),
        new Point2D(graphicInfo.getX(), graphicInfo.getY()));
    return rectangle;
  }
 
  private Polyline2D createGateway(GraphicInfo graphicInfo) {
   
    double middleX = graphicInfo.getX() + (graphicInfo.getWidth() / 2);
    double middleY = graphicInfo.getY() + (graphicInfo.getHeight() / 2);
   
    Polyline2D gatewayRectangle = new Polyline2D(new Point2D(graphicInfo.getX(), middleY),
        new Point2D(middleX, graphicInfo.getY()),
        new Point2D(graphicInfo.getX() + graphicInfo.getWidth(), middleY),
        new Point2D(middleX, graphicInfo.getY() + graphicInfo.getHeight()),
        new Point2D(graphicInfo.getX(), middleY));
   
    return gatewayRectangle;
  }
 
  private GraphicInfo createGraphicInfo(double x, double y) {
    GraphicInfo graphicInfo = new GraphicInfo();
    graphicInfo.setX(x);
    graphicInfo.setY(y);
    return graphicInfo;
  }
}
TOP

Related Classes of org.activiti.editor.language.json.converter.BpmnJsonConverter

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.