public ServiceTaskExpressionActivityBehavior createServiceTaskExpressionActivityBehavior(
     ServiceTask serviceTask) {
   Expression expression = expressionManager.createExpression(serviceTask.getImplementation());
   Expression skipExpression;
   if (StringUtils.isNotEmpty(serviceTask.getSkipExpression())) {
     skipExpression = expressionManager.createExpression(serviceTask.getSkipExpression());
   } else {
     skipExpression = null;
   }
   return new ServiceTaskExpressionActivityBehavior(
       expression, skipExpression, serviceTask.getResultVariableName());
 }
 public ServiceTaskDelegateExpressionActivityBehavior
     createServiceTaskDelegateExpressionActivityBehavior(ServiceTask serviceTask) {
   Expression delegateExpression =
       expressionManager.createExpression(serviceTask.getImplementation());
   Expression skipExpression;
   if (StringUtils.isNotEmpty(serviceTask.getSkipExpression())) {
     skipExpression = expressionManager.createExpression(serviceTask.getSkipExpression());
   } else {
     skipExpression = null;
   }
   return new ServiceTaskDelegateExpressionActivityBehavior(
       delegateExpression,
       skipExpression,
       createFieldDeclarations(serviceTask.getFieldExtensions()));
 }
  protected FlowElement convertJsonToElement(
      JsonNode elementNode, JsonNode modelNode, Map<String, JsonNode> shapeMap) {
    ServiceTask task = new ServiceTask();
    if (StringUtils.isNotEmpty(getPropertyValueAsString(PROPERTY_SERVICETASK_CLASS, elementNode))) {
      task.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
      task.setImplementation(getPropertyValueAsString(PROPERTY_SERVICETASK_CLASS, elementNode));

    } else if (StringUtils.isNotEmpty(
        getPropertyValueAsString(PROPERTY_SERVICETASK_EXPRESSION, elementNode))) {
      task.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
      task.setImplementation(
          getPropertyValueAsString(PROPERTY_SERVICETASK_EXPRESSION, elementNode));

    } else if (StringUtils.isNotEmpty(
        getPropertyValueAsString(PROPERTY_SERVICETASK_DELEGATE_EXPRESSION, elementNode))) {
      task.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
      task.setImplementation(
          getPropertyValueAsString(PROPERTY_SERVICETASK_DELEGATE_EXPRESSION, elementNode));
    }

    if (StringUtils.isNotEmpty(
        getPropertyValueAsString(PROPERTY_SERVICETASK_RESULT_VARIABLE, elementNode))) {
      task.setResultVariableName(
          getPropertyValueAsString(PROPERTY_SERVICETASK_RESULT_VARIABLE, elementNode));
    }

    JsonNode fieldsNode = getProperty(PROPERTY_SERVICETASK_FIELDS, elementNode);
    if (fieldsNode != null) {
      JsonNode itemsArrayNode = fieldsNode.get(EDITOR_PROPERTIES_GENERAL_ITEMS);
      if (itemsArrayNode != null) {
        for (JsonNode itemNode : itemsArrayNode) {
          JsonNode nameNode = itemNode.get(PROPERTY_SERVICETASK_FIELD_NAME);
          if (nameNode != null && StringUtils.isNotEmpty(nameNode.asText())) {

            FieldExtension field = new FieldExtension();
            field.setFieldName(nameNode.asText());
            if (StringUtils.isNotEmpty(
                getValueAsString(PROPERTY_SERVICETASK_FIELD_VALUE, itemNode))) {
              field.setStringValue(getValueAsString(PROPERTY_SERVICETASK_FIELD_VALUE, itemNode));
            } else if (StringUtils.isNotEmpty(
                getValueAsString(PROPERTY_SERVICETASK_FIELD_EXPRESSION, itemNode))) {
              field.setExpression(
                  getValueAsString(PROPERTY_SERVICETASK_FIELD_EXPRESSION, itemNode));
            }
            task.getFieldExtensions().add(field);
          }
        }
      }
    }

    return task;
  }
  private CustomServiceTask findCustomServiceTask(ServiceTask serviceTask) {
    CustomServiceTask result = null;
    if (serviceTask.isExtended()) {

      final List<CustomServiceTask> customServiceTasks =
          ExtensionUtil.getCustomServiceTasks(
              ActivitiUiUtil.getProjectFromDiagram(getDiagramTypeProvider().getDiagram()));

      for (final CustomServiceTask customServiceTask : customServiceTasks) {
        if (serviceTask.getExtensionId().equals(customServiceTask.getId())) {
          result = customServiceTask;
          break;
        }
      }
    }
    return result;
  }
 protected void setPropertyFieldValue(String name, ServiceTask task, ObjectNode propertiesNode) {
   for (FieldExtension extension : task.getFieldExtensions()) {
     if (name.substring(8).equalsIgnoreCase(extension.getFieldName())) {
       if (StringUtils.isNotEmpty(extension.getStringValue())) {
         setPropertyValue(name, extension.getStringValue(), propertiesNode);
       } else if (StringUtils.isNotEmpty(extension.getExpression())) {
         setPropertyValue(name, extension.getExpression(), propertiesNode);
       }
     }
   }
 }
  @Override
  protected void writeExtensionChildElements(BaseElement element, XMLStreamWriter xtw)
      throws Exception {
    ServiceTask serviceTask = (ServiceTask) element;

    if (serviceTask.getCustomProperties().size() > 0) {
      for (CustomProperty customProperty : serviceTask.getCustomProperties()) {

        if (StringUtils.isEmpty(customProperty.getSimpleValue())) {
          continue;
        }

        if (didWriteExtensionStartElement == false) {
          xtw.writeStartElement(ELEMENT_EXTENSIONS);
          didWriteExtensionStartElement = true;
        }
        xtw.writeStartElement(
            ACTIVITI_EXTENSIONS_PREFIX, ELEMENT_FIELD, ACTIVITI_EXTENSIONS_NAMESPACE);
        xtw.writeAttribute(ATTRIBUTE_FIELD_NAME, customProperty.getName());
        if ((customProperty.getSimpleValue().contains("${")
                || customProperty.getSimpleValue().contains("#{"))
            && customProperty.getSimpleValue().contains("}")) {

          xtw.writeStartElement(
              ACTIVITI_EXTENSIONS_PREFIX,
              ATTRIBUTE_FIELD_EXPRESSION,
              ACTIVITI_EXTENSIONS_NAMESPACE);
        } else {
          xtw.writeStartElement(
              ACTIVITI_EXTENSIONS_PREFIX, ELEMENT_FIELD_STRING, ACTIVITI_EXTENSIONS_NAMESPACE);
        }
        xtw.writeCharacters(customProperty.getSimpleValue());
        xtw.writeEndElement();
        xtw.writeEndElement();
      }
    } else {
      didWriteExtensionStartElement =
          FieldExtensionExport.writeFieldExtensions(
              serviceTask.getFieldExtensions(), didWriteExtensionStartElement, xtw);
    }
  }
 protected void addField(String name, JsonNode elementNode, ServiceTask task) {
   FieldExtension field = new FieldExtension();
   field.setFieldName(name.substring(8));
   String value = getPropertyValueAsString(name, elementNode);
   if (StringUtils.isNotEmpty(value)) {
     if ((value.contains("${") || value.contains("#{")) && value.contains("}")) {
       field.setExpression(value);
     } else {
       field.setStringValue(value);
     }
     task.getFieldExtensions().add(field);
   }
 }
 public ClassDelegate createClassDelegateServiceTask(ServiceTask serviceTask) {
   Expression skipExpression;
   if (StringUtils.isNotEmpty(serviceTask.getSkipExpression())) {
     skipExpression = expressionManager.createExpression(serviceTask.getSkipExpression());
   } else {
     skipExpression = null;
   }
   return new ClassDelegate(
       serviceTask.getId(),
       serviceTask.getImplementation(),
       createFieldDeclarations(serviceTask.getFieldExtensions()),
       skipExpression,
       serviceTask.getMapExceptions());
 }
  private void drawFlowElements(
      Collection<FlowElement> elementList,
      Map<String, GraphicInfo> locationMap,
      ContainerShape parentShape,
      Process process) {

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

    List<FlowElement> noDIList = new ArrayList<FlowElement>();
    for (FlowElement flowElement : elementList) {

      if (flowElement instanceof SequenceFlow) {
        continue;
      }

      AddContext context = new AddContext(new AreaContext(), flowElement);
      IAddFeature addFeature = featureProvider.getAddFeature(context);

      if (addFeature == null) {
        System.out.println("Element not supported: " + flowElement);
        return;
      }

      GraphicInfo graphicInfo = locationMap.get(flowElement.getId());
      if (graphicInfo == null) {

        noDIList.add(flowElement);

      } else {

        context.setNewObject(flowElement);
        context.setSize((int) graphicInfo.getWidth(), (int) graphicInfo.getHeight());

        ContainerShape parentContainer = null;
        if (parentShape instanceof Diagram) {
          parentContainer = getParentContainer(flowElement.getId(), process, (Diagram) parentShape);
        } else {
          parentContainer = parentShape;
        }

        context.setTargetContainer(parentContainer);
        if (parentContainer instanceof Diagram == false) {
          Point location = getLocation(parentContainer);
          context.setLocation(
              (int) graphicInfo.getX() - location.x, (int) graphicInfo.getY() - location.y);
        } else {
          context.setLocation((int) graphicInfo.getX(), (int) graphicInfo.getY());
        }

        if (flowElement instanceof ServiceTask) {

          ServiceTask serviceTask = (ServiceTask) flowElement;

          if (serviceTask.isExtended()) {

            CustomServiceTask targetTask = findCustomServiceTask(serviceTask);

            if (targetTask != null) {

              for (FieldExtension field : serviceTask.getFieldExtensions()) {
                CustomProperty customFieldProperty = new CustomProperty();
                customFieldProperty.setName(field.getFieldName());
                if (StringUtils.isNotEmpty(field.getExpression())) {
                  customFieldProperty.setSimpleValue(field.getExpression());
                } else {
                  customFieldProperty.setSimpleValue(field.getStringValue());
                }
                serviceTask.getCustomProperties().add(customFieldProperty);
              }

              serviceTask.getFieldExtensions().clear();
            }
          }
        }

        if (flowElement instanceof BoundaryEvent) {
          BoundaryEvent boundaryEvent = (BoundaryEvent) flowElement;
          if (boundaryEvent.getAttachedToRef() != null) {
            ContainerShape container =
                (ContainerShape)
                    featureProvider.getPictogramElementForBusinessObject(
                        boundaryEvent.getAttachedToRef());

            if (container != null) {
              AddContext boundaryContext = new AddContext(new AreaContext(), boundaryEvent);
              boundaryContext.setTargetContainer(container);
              Point location = getLocation(container);
              boundaryContext.setLocation(
                  (int) graphicInfo.getX() - location.x, (int) graphicInfo.getY() - location.y);

              if (addFeature.canAdd(boundaryContext)) {
                PictogramElement newBoundaryContainer = addFeature.add(boundaryContext);
                // featureProvider.link(newBoundaryContainer, new Object[] { boundaryEvent });
              }
            }
          }
        } else if (addFeature.canAdd(context)) {
          PictogramElement newContainer = addFeature.add(context);
          featureProvider.link(newContainer, new Object[] {flowElement});

          if (flowElement instanceof SubProcess) {
            drawFlowElements(
                ((SubProcess) flowElement).getFlowElements(),
                locationMap,
                (ContainerShape) newContainer,
                process);
          }
        }
      }
    }

    for (FlowElement flowElement : noDIList) {
      if (flowElement instanceof BoundaryEvent) {
        ((BoundaryEvent) flowElement).getAttachedToRef().getBoundaryEvents().remove(flowElement);
      } else {
        elementList.remove(flowElement);
      }
    }
  }
  @SuppressWarnings({"rawtypes", "unchecked"})
  protected void drawFlowElements(
      Collection<FlowElement> elementList,
      Map<String, GraphicInfo> locationMap,
      ContainerShape parentShape,
      Process process) {

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

    List<FlowElement> noDIList = new ArrayList<FlowElement>();
    for (FlowElement flowElement : elementList) {

      if (flowElement instanceof SequenceFlow) {
        continue;
      }

      AddContext context = new AddContext(new AreaContext(), flowElement);
      IAddFeature addFeature = featureProvider.getAddFeature(context);

      if (addFeature == null) {
        System.out.println("Element not supported: " + flowElement);
        return;
      }

      GraphicInfo graphicInfo = locationMap.get(flowElement.getId());
      if (graphicInfo == null) {

        noDIList.add(flowElement);

      } else {

        context.setNewObject(flowElement);
        context.setSize((int) graphicInfo.getWidth(), (int) graphicInfo.getHeight());
        ContainerShape parentContainer = null;
        if (parentShape instanceof Diagram) {
          parentContainer = getParentContainer(flowElement.getId(), process, (Diagram) parentShape);
        } else {
          parentContainer = parentShape;
        }

        context.setTargetContainer(parentContainer);
        if (parentContainer instanceof Diagram == false) {
          Point location = getLocation(parentContainer);
          context.setLocation(
              (int) graphicInfo.getX() - location.x, (int) graphicInfo.getY() - location.y);
        } else {
          context.setLocation((int) graphicInfo.getX(), (int) graphicInfo.getY());
        }

        if (flowElement instanceof ServiceTask) {

          ServiceTask serviceTask = (ServiceTask) flowElement;

          if (serviceTask.isExtended()) {

            CustomServiceTask targetTask = findCustomServiceTask(serviceTask);

            if (targetTask != null) {

              for (FieldExtension field : serviceTask.getFieldExtensions()) {
                CustomProperty customFieldProperty = new CustomProperty();
                customFieldProperty.setName(field.getFieldName());
                if (StringUtils.isNotEmpty(field.getExpression())) {
                  customFieldProperty.setSimpleValue(field.getExpression());
                } else {
                  customFieldProperty.setSimpleValue(field.getStringValue());
                }
                serviceTask.getCustomProperties().add(customFieldProperty);
              }

              serviceTask.getFieldExtensions().clear();
            }
          }

        } else if (flowElement instanceof UserTask) {

          UserTask userTask = (UserTask) flowElement;

          if (userTask.isExtended()) {

            CustomUserTask targetTask = findCustomUserTask(userTask);

            if (targetTask != null) {

              final List<Class<CustomUserTask>> classHierarchy =
                  new ArrayList<Class<CustomUserTask>>();
              final List<String> fieldInfoObjects = new ArrayList<String>();

              Class clazz = targetTask.getClass();
              classHierarchy.add(clazz);

              boolean hierarchyOpen = true;
              while (hierarchyOpen) {
                clazz = clazz.getSuperclass();
                if (CustomUserTask.class.isAssignableFrom(clazz)) {
                  classHierarchy.add(clazz);
                } else {
                  hierarchyOpen = false;
                }
              }

              for (final Class<CustomUserTask> currentClass : classHierarchy) {
                for (final Field field : currentClass.getDeclaredFields()) {
                  if (field.isAnnotationPresent(Property.class)) {
                    fieldInfoObjects.add(field.getName());
                  }
                }
              }

              for (String fieldName : userTask.getExtensionElements().keySet()) {
                if (fieldInfoObjects.contains(fieldName)) {
                  CustomProperty customFieldProperty = new CustomProperty();
                  customFieldProperty.setName(fieldName);
                  customFieldProperty.setSimpleValue(
                      userTask.getExtensionElements().get(fieldName).get(0).getElementText());
                  userTask.getCustomProperties().add(customFieldProperty);
                }
              }

              for (String fieldName : fieldInfoObjects) {
                userTask.getExtensionElements().remove(fieldName);
              }
            }
          }
        }

        if (flowElement instanceof BoundaryEvent) {
          BoundaryEvent boundaryEvent = (BoundaryEvent) flowElement;
          if (boundaryEvent.getAttachedToRef() != null) {
            ContainerShape container =
                (ContainerShape)
                    featureProvider.getPictogramElementForBusinessObject(
                        boundaryEvent.getAttachedToRef());

            if (container != null) {
              AddContext boundaryContext = new AddContext(new AreaContext(), boundaryEvent);
              boundaryContext.setTargetContainer(container);
              Point location = getLocation(container);
              boundaryContext.setLocation(
                  (int) graphicInfo.getX() - location.x, (int) graphicInfo.getY() - location.y);

              if (addFeature.canAdd(boundaryContext)) {
                addFeature.add(boundaryContext);
              }
            }
          }
        } else if (addFeature.canAdd(context)) {
          PictogramElement newContainer = addFeature.add(context);
          featureProvider.link(newContainer, new Object[] {flowElement});

          if (flowElement instanceof SubProcess) {
            drawFlowElements(
                ((SubProcess) flowElement).getFlowElements(),
                locationMap,
                (ContainerShape) newContainer,
                process);
          }
        }
      }
    }

    for (FlowElement flowElement : noDIList) {
      if (flowElement instanceof BoundaryEvent) {
        ((BoundaryEvent) flowElement).getAttachedToRef().getBoundaryEvents().remove(flowElement);
      } else {
        // do not remove Data Objects
        if (flowElement instanceof DataObject == false) {
          elementList.remove(flowElement);
        }
      }
    }
  }
  @Override
  protected void writeAdditionalAttributes(BaseElement element, XMLStreamWriter xtw)
      throws Exception {

    ServiceTask serviceTask = (ServiceTask) element;

    if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(serviceTask.getImplementationType())) {
      writeQualifiedAttribute(ATTRIBUTE_TASK_SERVICE_CLASS, serviceTask.getImplementation(), xtw);
    } else if (ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(
        serviceTask.getImplementationType())) {
      writeQualifiedAttribute(
          ATTRIBUTE_TASK_SERVICE_EXPRESSION, serviceTask.getImplementation(), xtw);
    } else if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(
        serviceTask.getImplementationType())) {
      writeQualifiedAttribute(
          ATTRIBUTE_TASK_SERVICE_DELEGATEEXPRESSION, serviceTask.getImplementation(), xtw);
    }

    if (StringUtils.isNotEmpty(serviceTask.getResultVariableName())) {
      writeQualifiedAttribute(
          ATTRIBUTE_TASK_SERVICE_RESULTVARIABLE, serviceTask.getResultVariableName(), xtw);
    }
    if (StringUtils.isNotEmpty(serviceTask.getType())) {
      writeQualifiedAttribute(ATTRIBUTE_TYPE, serviceTask.getType(), xtw);
    }
    if (StringUtils.isNotEmpty(serviceTask.getExtensionId())) {
      writeQualifiedAttribute(
          ATTRIBUTE_TASK_SERVICE_EXTENSIONID, serviceTask.getExtensionId(), xtw);
    }
  }
  @Override
  protected BaseElement convertXMLToElement(XMLStreamReader xtr) throws Exception {
    ServiceTask serviceTask = new ServiceTask();
    BpmnXMLUtil.addXMLLocation(serviceTask, xtr);
    if (StringUtils.isNotEmpty(
        xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_CLASS))) {
      serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
      serviceTask.setImplementation(
          xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_CLASS));

    } else if (StringUtils.isNotEmpty(
        xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_EXPRESSION))) {
      serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
      serviceTask.setImplementation(
          xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_EXPRESSION));

    } else if (StringUtils.isNotEmpty(
        xtr.getAttributeValue(
            ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_DELEGATEEXPRESSION))) {
      serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
      serviceTask.setImplementation(
          xtr.getAttributeValue(
              ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_DELEGATEEXPRESSION));

    } else if ("##WebService".equals(xtr.getAttributeValue(null, ATTRIBUTE_TASK_IMPLEMENTATION))) {
      serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_WEBSERVICE);
      serviceTask.setOperationRef(
          parseOperationRef(xtr.getAttributeValue(null, ATTRIBUTE_TASK_OPERATION_REF), model));
    }

    serviceTask.setResultVariableName(
        xtr.getAttributeValue(
            ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_RESULTVARIABLE));
    if (StringUtils.isEmpty(serviceTask.getResultVariableName())) {
      serviceTask.setResultVariableName(
          xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, "resultVariable"));
    }

    if (StringUtils.isNotEmpty(serviceTask.getResultVariableName())
        && (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(serviceTask.getImplementationType())
            || ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(
                serviceTask.getImplementationType()))) {

      model.addProblem(
          "'resultVariableName' not supported for service tasks using 'class' or 'delegateExpression",
          xtr);
    }

    serviceTask.setType(xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TYPE));
    serviceTask.setExtensionId(
        xtr.getAttributeValue(ACTIVITI_EXTENSIONS_NAMESPACE, ATTRIBUTE_TASK_SERVICE_EXTENSIONID));

    parseChildElements(getXMLElementName(), serviceTask, xtr);

    return serviceTask;
  }
 // We do not want a hard dependency on Camel, hence we return ActivityBehavior and instantiate
 // the delegate instance using a string instead of the Class itself.
 public ActivityBehavior createCamelActivityBehavior(
     ServiceTask serviceTask, BpmnModel bpmnModel) {
   return createCamelActivityBehavior(serviceTask, serviceTask.getFieldExtensions(), bpmnModel);
 }
 public MailActivityBehavior createMailActivityBehavior(ServiceTask serviceTask) {
   return createMailActivityBehavior(serviceTask.getId(), serviceTask.getFieldExtensions());
 }
  protected void convertElementToJson(ObjectNode propertiesNode, FlowElement flowElement) {
    ServiceTask serviceTask = (ServiceTask) flowElement;

    if ("mail".equalsIgnoreCase(serviceTask.getType())) {

      setPropertyFieldValue(PROPERTY_MAILTASK_TO, serviceTask, propertiesNode);
      setPropertyFieldValue(PROPERTY_MAILTASK_FROM, serviceTask, propertiesNode);
      setPropertyFieldValue(PROPERTY_MAILTASK_SUBJECT, serviceTask, propertiesNode);
      setPropertyFieldValue(PROPERTY_MAILTASK_CC, serviceTask, propertiesNode);
      setPropertyFieldValue(PROPERTY_MAILTASK_BCC, serviceTask, propertiesNode);
      setPropertyFieldValue(PROPERTY_MAILTASK_TEXT, serviceTask, propertiesNode);
      setPropertyFieldValue(PROPERTY_MAILTASK_HTML, serviceTask, propertiesNode);
      setPropertyFieldValue(PROPERTY_MAILTASK_CHARSET, serviceTask, propertiesNode);

    } else {

      if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(
          serviceTask.getImplementationType())) {
        propertiesNode.put(PROPERTY_SERVICETASK_CLASS, serviceTask.getImplementation());
      } else if (ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(
          serviceTask.getImplementationType())) {
        propertiesNode.put(PROPERTY_SERVICETASK_EXPRESSION, serviceTask.getImplementation());
      } else if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(
          serviceTask.getImplementationType())) {
        propertiesNode.put(
            PROPERTY_SERVICETASK_DELEGATE_EXPRESSION, serviceTask.getImplementation());
      }

      if (StringUtils.isNotEmpty(serviceTask.getResultVariableName())) {
        propertiesNode.put(
            PROPERTY_SERVICETASK_RESULT_VARIABLE, serviceTask.getResultVariableName());
      }

      addFieldExtensions(serviceTask.getFieldExtensions(), propertiesNode);
    }
  }
 public ShellActivityBehavior createShellActivityBehavior(ServiceTask serviceTask) {
   List<FieldDeclaration> fieldDeclarations =
       createFieldDeclarations(serviceTask.getFieldExtensions());
   return (ShellActivityBehavior)
       ClassDelegate.instantiateDelegate(ShellActivityBehavior.class, fieldDeclarations);
 }
  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);
  }
  @Override
  public Object[] create(ICreateContext context) {
    ServiceTask newServiceTask = new ServiceTask();
    newServiceTask.setName("Service Task");
    newServiceTask.setExtensionId(customServiceTaskId);
    newServiceTask.setAsynchronous(true);

    // Process custom service tasks
    if (newServiceTask.isExtended()) {

      CustomServiceTask targetTask = findCustomServiceTask(newServiceTask);

      if (targetTask != null) {

        // What should happen if the class contain more than one annotations?
        switch (targetTask.getDelegateType()) {
          case JAVA_DELEGATE_CLASS:
            newServiceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
            newServiceTask.setImplementation(targetTask.getDelegateSpecification());
            break;
          case EXPRESSION:
            newServiceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
            newServiceTask.setImplementation(targetTask.getDelegateSpecification());
            break;
          case JAVA_DELEGATE_EXPRESSION:
            newServiceTask.setImplementationType(
                ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
            newServiceTask.setImplementation(targetTask.getDelegateSpecification());
            break;
        }

        newServiceTask.setName(targetTask.getName());
      }
    }

    addObjectToContainer(context, newServiceTask, newServiceTask.getName());

    return new Object[] {newServiceTask};
  }