@Override
 protected Object getModelValueForTable(Object businessObject) {
   if (businessObject instanceof BaseElement) {
     BaseElement baseElement = (BaseElement) businessObject;
     return baseElement.getDocumentations();
   }
   return null;
 }
 @Override
 protected void storeTableValueInModel(Object businessObject) {
   List<Documentation> newDocs = null;
   if (businessObject instanceof BaseElement) {
     ((BaseElement) businessObject).setDocumentations((new ArrayList<Documentation>(newDocs)));
   }
 }
  private PictogramElement addContainerElement(
      BaseElement element, BpmnMemoryModel model, ContainerShape parent) {
    GraphicInfo graphicInfo = model.getBpmnModel().getGraphicInfo(element.getId());
    if (graphicInfo == null) {
      return null;
    }

    final IFeatureProvider featureProvider = getDiagramTypeProvider().getFeatureProvider();

    AddContext context = new AddContext(new AreaContext(), element);
    IAddFeature addFeature = featureProvider.getAddFeature(context);
    context.setNewObject(element);
    context.setSize((int) graphicInfo.getWidth(), (int) graphicInfo.getHeight());
    context.setTargetContainer(parent);

    int x = (int) graphicInfo.getX();
    int y = (int) graphicInfo.getY();

    if (parent instanceof Diagram == false) {
      x = x - parent.getGraphicsAlgorithm().getX();
      y = y - parent.getGraphicsAlgorithm().getY();
    }

    context.setLocation(x, y);

    PictogramElement pictElement = null;
    if (addFeature.canAdd(context)) {
      pictElement = addFeature.add(context);
      featureProvider.link(pictElement, new Object[] {element});
    }

    return pictElement;
  }
  protected Map<String, String> getDataObjectAttributes(BaseElement dObj) {
    Map<String, String> attributes = null;

    if (null != dObj) {
      List<ExtensionElement> attributesExtension =
          dObj.getExtensionElements().get(ELEMENT_DATA_ATTRIBUTES);

      if (null != attributesExtension && !attributesExtension.isEmpty()) {
        attributes = new HashMap<String, String>();
        List<ExtensionElement> attributeExtensions =
            attributesExtension.get(0).getChildElements().get(ELEMENT_DATA_ATTRIBUTE);

        for (ExtensionElement attributeExtension : attributeExtensions) {
          attributes.put(
              attributeExtension.getAttributeValue(YOURCO_EXTENSIONS_NAMESPACE, ATTRIBUTE_NAME),
              attributeExtension.getAttributeValue(YOURCO_EXTENSIONS_NAMESPACE, ATTRIBUTE_VALUE));
        }
      }
    }
    return attributes;
  }
  protected Localization getLocalization(BaseElement dObj) {
    List<ExtensionElement> i18lnExtension =
        dObj.getExtensionElements().get(ELEMENT_I18LN_LOCALIZATION);

    if (!i18lnExtension.isEmpty()) {
      Map<String, List<ExtensionAttribute>> extensionAttributes =
          i18lnExtension.get(0).getAttributes();
      localization.setLabeledEntityIdForName(
          extensionAttributes.get(ATTRIBUTE_DATA_LABELED_ENTITY_ID_FOR_NAME).get(0).getValue());
      localization.setLabeledEntityIdForDescription(
          extensionAttributes
              .get(ATTRIBUTE_DATA_LABELED_ENTITY_ID_FOR_DESCRIPTION)
              .get(0)
              .getValue());
      localization.setResourceBundleKeyForName(
          extensionAttributes.get(ATTRIBUTE_DATA_RESOURCE_BUNDLE_KEY_FOR_NAME).get(0).getValue());
      localization.setResourceBundleKeyForDescription(
          extensionAttributes
              .get(ATTRIBUTE_DATA_RESOURCE_BUNDLE_KEY_FOR_DESCRIPTION)
              .get(0)
              .getValue());
    }
    return localization;
  }
  public void convertToJson(
      BaseElement baseElement,
      ActivityProcessor processor,
      BpmnModel model,
      FlowElementsContainer container,
      ArrayNode shapesArrayNode,
      double subProcessX,
      double subProcessY) {

    this.model = model;
    this.processor = processor;
    this.subProcessX = subProcessX;
    this.subProcessY = subProcessY;
    this.shapesArrayNode = shapesArrayNode;
    GraphicInfo graphicInfo = model.getGraphicInfo(baseElement.getId());

    String stencilId = null;
    if (baseElement instanceof ServiceTask) {
      ServiceTask serviceTask = (ServiceTask) baseElement;
      if ("mail".equalsIgnoreCase(serviceTask.getType())) {
        stencilId = STENCIL_TASK_MAIL;
      } else if ("camel".equalsIgnoreCase(serviceTask.getType())) {
        stencilId = STENCIL_TASK_CAMEL;
      } else if ("mule".equalsIgnoreCase(serviceTask.getType())) {
        stencilId = STENCIL_TASK_MULE;
      } else {
        stencilId = getStencilId(baseElement);
      }
    } else {
      stencilId = getStencilId(baseElement);
    }

    flowElementNode =
        BpmnJsonConverterUtil.createChildShape(
            baseElement.getId(),
            stencilId,
            graphicInfo.getX() - subProcessX + graphicInfo.getWidth(),
            graphicInfo.getY() - subProcessY + graphicInfo.getHeight(),
            graphicInfo.getX() - subProcessX,
            graphicInfo.getY() - subProcessY);
    shapesArrayNode.add(flowElementNode);
    ObjectNode propertiesNode = objectMapper.createObjectNode();
    propertiesNode.put(PROPERTY_OVERRIDE_ID, baseElement.getId());

    if (baseElement instanceof FlowElement) {
      FlowElement flowElement = (FlowElement) baseElement;
      if (StringUtils.isNotEmpty(flowElement.getName())) {
        propertiesNode.put(PROPERTY_NAME, flowElement.getName());
      }

      if (StringUtils.isNotEmpty(flowElement.getDocumentation())) {
        propertiesNode.put(PROPERTY_DOCUMENTATION, flowElement.getDocumentation());
      }
    }

    convertElementToJson(propertiesNode, baseElement);

    flowElementNode.put(EDITOR_SHAPE_PROPERTIES, propertiesNode);
    ArrayNode outgoingArrayNode = objectMapper.createArrayNode();

    if (baseElement instanceof FlowNode) {
      FlowNode flowNode = (FlowNode) baseElement;
      for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {
        outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(sequenceFlow.getId()));
      }

      for (MessageFlow messageFlow : model.getMessageFlows().values()) {
        if (messageFlow.getSourceRef().equals(flowNode.getId())) {
          outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(messageFlow.getId()));
        }
      }
    }

    if (baseElement instanceof Activity) {

      Activity activity = (Activity) baseElement;
      for (BoundaryEvent boundaryEvent : activity.getBoundaryEvents()) {
        outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(boundaryEvent.getId()));
      }

      propertiesNode.put(PROPERTY_ASYNCHRONOUS, activity.isAsynchronous());
      propertiesNode.put(PROPERTY_EXCLUSIVE, !activity.isNotExclusive());

      if (activity.getLoopCharacteristics() != null) {
        MultiInstanceLoopCharacteristics loopDef = activity.getLoopCharacteristics();
        if (StringUtils.isNotEmpty(loopDef.getLoopCardinality())
            || StringUtils.isNotEmpty(loopDef.getInputDataItem())
            || StringUtils.isNotEmpty(loopDef.getCompletionCondition())) {

          if (loopDef.isSequential() == false) {
            propertiesNode.put(PROPERTY_MULTIINSTANCE_TYPE, "Parallel");
          } else {
            propertiesNode.put(PROPERTY_MULTIINSTANCE_TYPE, "Sequential");
          }

          if (StringUtils.isNotEmpty(loopDef.getLoopCardinality())) {
            propertiesNode.put(PROPERTY_MULTIINSTANCE_CARDINALITY, loopDef.getLoopCardinality());
          }
          if (StringUtils.isNotEmpty(loopDef.getInputDataItem())) {
            propertiesNode.put(PROPERTY_MULTIINSTANCE_COLLECTION, loopDef.getInputDataItem());
          }
          if (StringUtils.isNotEmpty(loopDef.getElementVariable())) {
            propertiesNode.put(PROPERTY_MULTIINSTANCE_VARIABLE, loopDef.getElementVariable());
          }
          if (StringUtils.isNotEmpty(loopDef.getCompletionCondition())) {
            propertiesNode.put(PROPERTY_MULTIINSTANCE_CONDITION, loopDef.getCompletionCondition());
          }
        }
      }

      if (activity instanceof UserTask) {
        BpmnJsonConverterUtil.convertListenersToJson(
            ((UserTask) activity).getTaskListeners(), false, propertiesNode);
      }

      BpmnJsonConverterUtil.convertListenersToJson(
          activity.getExecutionListeners(), true, propertiesNode);

      if (CollectionUtils.isNotEmpty(activity.getDataInputAssociations())) {
        for (DataAssociation dataAssociation : activity.getDataInputAssociations()) {
          if (model.getFlowElement(dataAssociation.getSourceRef()) != null) {
            createDataAssociation(dataAssociation, true, activity);
          }
        }
      }

      if (CollectionUtils.isNotEmpty(activity.getDataOutputAssociations())) {
        for (DataAssociation dataAssociation : activity.getDataOutputAssociations()) {
          if (model.getFlowElement(dataAssociation.getTargetRef()) != null) {
            createDataAssociation(dataAssociation, false, activity);
            outgoingArrayNode.add(
                BpmnJsonConverterUtil.createResourceNode(dataAssociation.getId()));
          }
        }
      }
    }

    for (Artifact artifact : container.getArtifacts()) {
      if (artifact instanceof Association) {
        Association association = (Association) artifact;
        if (StringUtils.isNotEmpty(association.getSourceRef())
            && association.getSourceRef().equals(baseElement.getId())) {
          outgoingArrayNode.add(BpmnJsonConverterUtil.createResourceNode(association.getId()));
        }
      }
    }

    if (baseElement instanceof DataStoreReference) {
      for (Process process : model.getProcesses()) {
        processDataStoreReferences(process, baseElement.getId(), outgoingArrayNode);
      }
    }

    flowElementNode.put("outgoing", outgoingArrayNode);
  }
  public void convertToBpmnModel(
      JsonNode elementNode,
      JsonNode modelNode,
      ActivityProcessor processor,
      BaseElement parentElement,
      Map<String, JsonNode> shapeMap,
      BpmnModel bpmnModel) {

    this.processor = processor;
    this.model = bpmnModel;

    BaseElement baseElement = convertJsonToElement(elementNode, modelNode, shapeMap);
    baseElement.setId(BpmnJsonConverterUtil.getElementId(elementNode));

    if (baseElement instanceof FlowElement) {
      FlowElement flowElement = (FlowElement) baseElement;
      flowElement.setName(getPropertyValueAsString(PROPERTY_NAME, elementNode));
      flowElement.setDocumentation(getPropertyValueAsString(PROPERTY_DOCUMENTATION, elementNode));

      BpmnJsonConverterUtil.convertJsonToListeners(elementNode, flowElement);

      if (baseElement instanceof Activity) {
        Activity activity = (Activity) baseElement;
        activity.setAsynchronous(getPropertyValueAsBoolean(PROPERTY_ASYNCHRONOUS, elementNode));
        activity.setNotExclusive(!getPropertyValueAsBoolean(PROPERTY_EXCLUSIVE, elementNode));

        String multiInstanceType =
            getPropertyValueAsString(PROPERTY_MULTIINSTANCE_TYPE, elementNode);
        String multiInstanceCardinality =
            getPropertyValueAsString(PROPERTY_MULTIINSTANCE_CARDINALITY, elementNode);
        String multiInstanceCollection =
            getPropertyValueAsString(PROPERTY_MULTIINSTANCE_COLLECTION, elementNode);
        String multiInstanceCondition =
            getPropertyValueAsString(PROPERTY_MULTIINSTANCE_CONDITION, elementNode);

        if (StringUtils.isNotEmpty(multiInstanceType)
            && "none".equalsIgnoreCase(multiInstanceType) == false) {

          String multiInstanceVariable =
              getPropertyValueAsString(PROPERTY_MULTIINSTANCE_VARIABLE, elementNode);

          MultiInstanceLoopCharacteristics multiInstanceObject =
              new MultiInstanceLoopCharacteristics();
          if ("sequential".equalsIgnoreCase(multiInstanceType)) {
            multiInstanceObject.setSequential(true);
          } else {
            multiInstanceObject.setSequential(false);
          }
          multiInstanceObject.setLoopCardinality(multiInstanceCardinality);
          multiInstanceObject.setInputDataItem(multiInstanceCollection);
          multiInstanceObject.setElementVariable(multiInstanceVariable);
          multiInstanceObject.setCompletionCondition(multiInstanceCondition);
          activity.setLoopCharacteristics(multiInstanceObject);
        }

      } else if (baseElement instanceof Gateway) {
        JsonNode flowOrderNode = getProperty(PROPERTY_SEQUENCEFLOW_ORDER, elementNode);
        if (flowOrderNode != null) {
          flowOrderNode = BpmnJsonConverterUtil.validateIfNodeIsTextual(flowOrderNode);
          JsonNode orderArray = flowOrderNode.get("sequenceFlowOrder");
          if (orderArray != null && orderArray.size() > 0) {
            for (JsonNode orderNode : orderArray) {
              ExtensionElement orderElement = new ExtensionElement();
              orderElement.setName("EDITOR_FLOW_ORDER");
              orderElement.setElementText(orderNode.asText());
              flowElement.addExtensionElement(orderElement);
            }
          }
        }
      }
    }

    if (baseElement instanceof FlowElement) {
      FlowElement flowElement = (FlowElement) baseElement;
      if (flowElement instanceof SequenceFlow) {
        ExtensionElement idExtensionElement = new ExtensionElement();
        idExtensionElement.setName("EDITOR_RESOURCEID");
        idExtensionElement.setElementText(elementNode.get(EDITOR_SHAPE_ID).asText());
        flowElement.addExtensionElement(idExtensionElement);
      }

      if (parentElement instanceof Process) {
        ((Process) parentElement).addFlowElement(flowElement);

      } else if (parentElement instanceof SubProcess) {
        ((SubProcess) parentElement).addFlowElement(flowElement);

      } else if (parentElement instanceof Lane) {
        Lane lane = (Lane) parentElement;
        lane.getFlowReferences().add(flowElement.getId());
        lane.getParentProcess().addFlowElement(flowElement);
      }

    } else if (baseElement instanceof Artifact) {
      Artifact artifact = (Artifact) baseElement;
      if (parentElement instanceof Process) {
        ((Process) parentElement).addArtifact(artifact);

      } else if (parentElement instanceof SubProcess) {
        ((SubProcess) parentElement).addArtifact(artifact);

      } else if (parentElement instanceof Lane) {
        Lane lane = (Lane) parentElement;
        lane.getFlowReferences().add(artifact.getId());
        lane.getParentProcess().addArtifact(artifact);
      }
    }
  }
  public void convertToXML(XMLStreamWriter xtw, BaseElement baseElement, BpmnModel model)
      throws Exception {
    xtw.writeStartElement(getXMLElementName());
    boolean didWriteExtensionStartElement = false;
    writeDefaultAttribute(ATTRIBUTE_ID, baseElement.getId(), xtw);
    if (baseElement instanceof FlowElement) {
      writeDefaultAttribute(ATTRIBUTE_NAME, ((FlowElement) baseElement).getName(), xtw);
    }

    if (baseElement instanceof Activity) {
      final Activity activity = (Activity) baseElement;
      if (activity.isAsynchronous()) {
        writeQualifiedAttribute(ATTRIBUTE_ACTIVITY_ASYNCHRONOUS, ATTRIBUTE_VALUE_TRUE, xtw);
        if (activity.isNotExclusive()) {
          writeQualifiedAttribute(ATTRIBUTE_ACTIVITY_EXCLUSIVE, ATTRIBUTE_VALUE_FALSE, xtw);
        }
      }
      if (StringUtils.isNotEmpty(activity.getDefaultFlow())) {
        FlowElement defaultFlowElement = model.getFlowElement(activity.getDefaultFlow());
        if (defaultFlowElement != null && defaultFlowElement instanceof SequenceFlow) {
          writeDefaultAttribute(ATTRIBUTE_DEFAULT, activity.getDefaultFlow(), xtw);
        }
      }
    }

    if (baseElement instanceof Gateway) {
      final Gateway gateway = (Gateway) baseElement;
      if (gateway.isAsynchronous()) {
        writeQualifiedAttribute(ATTRIBUTE_ACTIVITY_ASYNCHRONOUS, ATTRIBUTE_VALUE_TRUE, xtw);
        if (gateway.isNotExclusive()) {
          writeQualifiedAttribute(ATTRIBUTE_ACTIVITY_EXCLUSIVE, ATTRIBUTE_VALUE_FALSE, xtw);
        }
      }
      if (StringUtils.isNotEmpty(gateway.getDefaultFlow())) {
        FlowElement defaultFlowElement = model.getFlowElement(gateway.getDefaultFlow());
        if (defaultFlowElement != null && defaultFlowElement instanceof SequenceFlow) {
          writeDefaultAttribute(ATTRIBUTE_DEFAULT, gateway.getDefaultFlow(), xtw);
        }
      }
    }

    writeAdditionalAttributes(baseElement, model, xtw);

    if (baseElement instanceof FlowElement) {
      final FlowElement flowElement = (FlowElement) baseElement;
      if (StringUtils.isNotEmpty(flowElement.getDocumentation())) {

        xtw.writeStartElement(ELEMENT_DOCUMENTATION);
        xtw.writeCharacters(flowElement.getDocumentation());
        xtw.writeEndElement();
      }
    }

    didWriteExtensionStartElement =
        writeExtensionChildElements(baseElement, didWriteExtensionStartElement, xtw);
    didWriteExtensionStartElement = writeListeners(baseElement, didWriteExtensionStartElement, xtw);
    didWriteExtensionStartElement =
        BpmnXMLUtil.writeExtensionElements(baseElement, didWriteExtensionStartElement, xtw);

    if (didWriteExtensionStartElement) {
      xtw.writeEndElement();
    }

    if (baseElement instanceof Activity) {
      final Activity activity = (Activity) baseElement;
      MultiInstanceExport.writeMultiInstance(activity, xtw);
    }

    writeAdditionalChildElements(baseElement, model, xtw);

    xtw.writeEndElement();
  }