@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);
    }
  }
  private void validateModel(BpmnModel model) {
    FlowElement flowElement = model.getMainProcess().getFlowElementMap().get("usertask");
    assertNotNull(flowElement);
    assertTrue(flowElement instanceof UserTask);
    assertEquals("usertask", flowElement.getId());
    UserTask userTask = (UserTask) flowElement;
    assertEquals("usertask", userTask.getId());
    assertEquals("User task", userTask.getName());
    assertEquals("testKey", userTask.getFormKey());
    assertEquals("40", userTask.getPriority());
    assertEquals("2012-11-01", userTask.getDueDate());

    assertEquals("kermit", userTask.getAssignee());
    assertEquals(2, userTask.getCandidateUsers().size());
    assertTrue(userTask.getCandidateUsers().contains("kermit"));
    assertTrue(userTask.getCandidateUsers().contains("fozzie"));
    assertEquals(2, userTask.getCandidateGroups().size());
    assertTrue(userTask.getCandidateGroups().contains("management"));
    assertTrue(userTask.getCandidateGroups().contains("sales"));

    List<FormProperty> formProperties = userTask.getFormProperties();
    assertEquals(2, formProperties.size());
    FormProperty formProperty = formProperties.get(0);
    assertEquals("formId", formProperty.getId());
    assertEquals("formName", formProperty.getName());
    assertEquals("string", formProperty.getType());
    assertEquals("variable", formProperty.getVariable());
    assertEquals("${expression}", formProperty.getExpression());
    formProperty = formProperties.get(1);
    assertEquals("formId2", formProperty.getId());
    assertEquals("anotherName", formProperty.getName());
    assertEquals("long", formProperty.getType());
    assertTrue(StringUtils.isEmpty(formProperty.getVariable()));
    assertTrue(StringUtils.isEmpty(formProperty.getExpression()));

    List<ActivitiListener> listeners = userTask.getTaskListeners();
    assertEquals(3, listeners.size());
    ActivitiListener listener = (ActivitiListener) listeners.get(0);
    assertTrue(
        ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(listener.getImplementationType()));
    assertEquals("org.test.TestClass", listener.getImplementation());
    assertEquals("create", listener.getEvent());
    listener = (ActivitiListener) listeners.get(1);
    assertTrue(
        ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(listener.getImplementationType()));
    assertEquals("${someExpression}", listener.getImplementation());
    assertEquals("assignment", listener.getEvent());
    listener = (ActivitiListener) listeners.get(2);
    assertTrue(
        ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(
            listener.getImplementationType()));
    assertEquals("${someDelegateExpression}", listener.getImplementation());
    assertEquals("complete", listener.getEvent());
  }
  protected void writeListeners(BaseElement element, XMLStreamWriter xtw) throws Exception {
    List<ActivitiListener> listenerList = null;
    String xmlElementName = ELEMENT_EXECUTION_LISTENER;
    if (element instanceof UserTask) {
      listenerList = ((UserTask) element).getTaskListeners();
      xmlElementName = ELEMENT_TASK_LISTENER;
    } else if (element instanceof Activity) {
      listenerList = ((Activity) element).getExecutionListeners();
    } else if (element instanceof Process) {
      listenerList = ((Process) element).getExecutionListeners();
    } else if (element instanceof SequenceFlow) {
      listenerList = ((SequenceFlow) element).getExecutionListeners();
    }

    if (listenerList != null) {

      for (ActivitiListener listener : listenerList) {

        if (StringUtils.isNotEmpty(listener.getEvent())) {

          if (didWriteExtensionStartElement == false) {
            xtw.writeStartElement(ELEMENT_EXTENSIONS);
            didWriteExtensionStartElement = true;
          }

          xtw.writeStartElement(
              ACTIVITI_EXTENSIONS_PREFIX, xmlElementName, ACTIVITI_EXTENSIONS_NAMESPACE);
          writeDefaultAttribute(ATTRIBUTE_LISTENER_EVENT, listener.getEvent(), xtw);

          if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(
              listener.getImplementationType())) {
            writeDefaultAttribute(ATTRIBUTE_LISTENER_CLASS, listener.getImplementation(), xtw);
          } else if (ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(
              listener.getImplementationType())) {
            writeDefaultAttribute(ATTRIBUTE_LISTENER_EXPRESSION, listener.getImplementation(), xtw);
          } else if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(
              listener.getImplementationType())) {
            writeDefaultAttribute(
                ATTRIBUTE_LISTENER_DELEGATEEXPRESSION, listener.getImplementation(), xtw);
          }

          xtw.writeEndElement();
        }
      }
    }
  }
  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);
    }
  }
  /**
   * Creates the dialog's contents
   *
   * @param shell the dialog window
   */
  private void createContents(final Shell shell) {
    FormLayout layout = new FormLayout();
    layout.marginHeight = 5;
    layout.marginWidth = 5;
    shell.setLayout(layout);
    FormData data;

    eventDropDown = new Combo(shell, SWT.DROP_DOWN | SWT.BORDER);
    for (String event : getEventList()) {
      eventDropDown.add(event);
    }

    if (savedListener != null && savedListener.getEvent() != null) {
      eventDropDown.setText(savedListener.getEvent());
    } else {
      eventDropDown.setText(getDefaultEvent());
    }
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(0, VSPACE);
    eventDropDown.setLayoutData(data);

    createLabel(shell, "Event", eventDropDown);

    Composite radioTypeComposite = new Composite(shell, SWT.NULL);
    radioTypeComposite.setBackground(shell.getBackground());
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(eventDropDown, VSPACE);
    radioTypeComposite.setLayoutData(data);
    radioTypeComposite.setLayout(new RowLayout());

    classTypeButton = new Button(radioTypeComposite, SWT.RADIO);
    classTypeButton.setText("Java class");
    classTypeButton.addSelectionListener(
        new SelectionListener() {

          @Override
          public void widgetSelected(SelectionEvent event) {
            enableClassType();
          }

          @Override
          public void widgetDefaultSelected(SelectionEvent event) {}
        });
    expressionTypeButton = new Button(radioTypeComposite, SWT.RADIO);
    expressionTypeButton.setText("Expression");
    expressionTypeButton.addSelectionListener(
        new SelectionListener() {

          @Override
          public void widgetSelected(SelectionEvent event) {
            enableExpressionType();
          }

          @Override
          public void widgetDefaultSelected(SelectionEvent event) {}
        });

    delegateExpressionTypeButton = new Button(radioTypeComposite, SWT.RADIO);
    delegateExpressionTypeButton.setText("Delegate expression");
    delegateExpressionTypeButton.addSelectionListener(
        new SelectionListener() {

          @Override
          public void widgetSelected(SelectionEvent event) {
            enableDelegateExpressionType();
          }

          @Override
          public void widgetDefaultSelected(SelectionEvent event) {}
        });

    if (PreferencesUtil.getBooleanPreference(Preferences.ALFRESCO_ENABLE)) {
      alfrescoExecutionTypeButton = new Button(radioTypeComposite, SWT.RADIO);
      alfrescoExecutionTypeButton.setText("Alfresco execution script");
      alfrescoExecutionTypeButton.addSelectionListener(
          new SelectionListener() {

            @Override
            public void widgetSelected(SelectionEvent event) {
              enableAlfrescoType(false);
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent event) {}
          });

      alfrescoTaskTypeButton = new Button(radioTypeComposite, SWT.RADIO);
      alfrescoTaskTypeButton.setText("Alfresco task script");
      alfrescoTaskTypeButton.addSelectionListener(
          new SelectionListener() {

            @Override
            public void widgetSelected(SelectionEvent event) {
              enableAlfrescoType(true);
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent event) {}
          });
    }

    createLabel(shell, "Type", radioTypeComposite);

    classNameText = new Text(shell, SWT.BORDER);
    if (savedListener != null
        && ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(
            savedListener.getImplementationType())) {
      classNameText.setText(savedListener.getImplementation());
    } else {
      classNameText.setText("");
    }
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(70, 0);
    data.top = new FormAttachment(radioTypeComposite, 10);
    classNameText.setEnabled(false);
    classNameText.setLayoutData(data);

    classSelectButton = new Button(shell, SWT.PUSH);
    classSelectButton.setText("Select class");
    data = new FormData();
    data.left = new FormAttachment(classNameText, 0);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(classNameText, -4, SWT.TOP);
    classSelectButton.setLayoutData(data);
    classSelectButton.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent evt) {
            Shell shell = classNameText.getShell();
            try {
              SelectionDialog dialog =
                  JavaUI.createTypeDialog(
                      shell,
                      new ProgressMonitorDialog(shell),
                      SearchEngine.createWorkspaceScope(),
                      IJavaElementSearchConstants.CONSIDER_CLASSES,
                      false);

              if (dialog.open() == SelectionDialog.OK) {
                Object[] result = dialog.getResult();
                String className = ((IType) result[0]).getFullyQualifiedName();

                if (className != null) {
                  classNameText.setText(className);
                }
              }
            } catch (Exception ex) {
              ex.printStackTrace();
            }
          }
        });

    classSelectLabel = createLabel(shell, "Service class", expressionText);

    expressionText = new Text(shell, SWT.BORDER);
    if (savedListener != null
        && ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(
            savedListener.getImplementationType())) {
      expressionText.setText(savedListener.getImplementation());
    } else {
      expressionText.setText("");
    }
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(radioTypeComposite, VSPACE);
    expressionText.setLayoutData(data);

    expressionLabel = createLabel(shell, "Expression", expressionText);

    delegateExpressionText = new Text(shell, SWT.BORDER);
    if (savedListener != null
        && ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(
            savedListener.getImplementationType())) {
      delegateExpressionText.setText(savedListener.getImplementation());
    } else {
      delegateExpressionText.setText("");
    }
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(radioTypeComposite, VSPACE);
    delegateExpressionText.setLayoutData(data);

    delegateExpressionLabel = createLabel(shell, "Delegate expression", delegateExpressionText);

    scriptText = new Text(shell, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL);
    data = new FormData(SWT.DEFAULT, 100);
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(radioTypeComposite, VSPACE);
    scriptText.setLayoutData(data);

    scriptLabel = createLabel(shell, "Script", scriptText);

    runAsText = new Text(shell, SWT.BORDER);
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(scriptText, VSPACE);
    runAsText.setLayoutData(data);
    runAsLabel = createLabel(shell, "Run as", runAsText);

    scriptProcessorText = new Text(shell, SWT.BORDER);
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(runAsText, VSPACE);
    scriptProcessorText.setLayoutData(data);
    scriptProcessorLabel = createLabel(shell, "Script processor", scriptProcessorText);

    if (savedListener != null
        && (AlfrescoUserTask.ALFRESCO_SCRIPT_TASK_LISTENER.equalsIgnoreCase(
                savedListener.getImplementation())
            || AlfrescoScriptTask.ALFRESCO_SCRIPT_EXECUTION_LISTENER.equalsIgnoreCase(
                savedListener.getImplementation()))) {

      List<FieldExtension> extensionList = savedListener.getFieldExtensions();
      String script = "";
      String runAs = "";
      String scriptProcessor = "";
      for (FieldExtension fieldExtension : extensionList) {
        if ("script".equalsIgnoreCase(fieldExtension.getFieldName())) {
          if (StringUtils.isNotEmpty(fieldExtension.getStringValue())) {
            script = fieldExtension.getStringValue();
          }
        } else if ("runAs".equalsIgnoreCase(fieldExtension.getFieldName())) {
          if (StringUtils.isNotEmpty(fieldExtension.getStringValue())) {
            runAs = fieldExtension.getStringValue();
          }
        } else if ("scriptProcessor".equalsIgnoreCase(fieldExtension.getFieldName())) {
          if (StringUtils.isNotEmpty(fieldExtension.getStringValue())) {
            scriptProcessor = fieldExtension.getStringValue();
          }
        }
      }
      scriptText.setText(script);
      runAsText.setText(runAs);
      scriptProcessorText.setText(scriptProcessor);

    } else {
      scriptText.setText("");
      runAsText.setText("");
      scriptProcessorText.setText("");
    }

    Composite extensionsComposite = new Composite(shell, SWT.WRAP);
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(100, 0);
    data.top = new FormAttachment(expressionText, 15);
    extensionsComposite.setLayoutData(data);
    GridLayout fieldLayout = new GridLayout();
    fieldLayout.marginTop = 0;
    fieldLayout.numColumns = 1;
    extensionsComposite.setLayout(fieldLayout);
    fieldEditor = new FieldExtensionEditor("fieldEditor", extensionsComposite);
    fieldEditor
        .getLabelControl(extensionsComposite)
        .setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
    if (savedListener != null
        && savedListener.getFieldExtensions() != null
        && savedListener.getFieldExtensions().size() > 0) {
      fieldEditor.initializeModel(savedListener.getFieldExtensions());
    }

    extensionLabel = createLabel(shell, "Fields", extensionsComposite);

    // Create the cancel button and add a handler
    // so that pressing it will set input to null
    Button cancel = new Button(shell, SWT.PUSH);
    cancel.setText("Cancel");
    data = new FormData();
    data.left = new FormAttachment(0, 120);
    data.right = new FormAttachment(50, 0);
    data.top = new FormAttachment(extensionsComposite, 20);
    cancel.setLayoutData(data);
    cancel.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent event) {
            shell.close();
          }
        });

    Button ok = new Button(shell, SWT.PUSH);
    ok.setText("OK");
    data = new FormData();
    data.left = new FormAttachment(0, 0);
    data.right = new FormAttachment(cancel, -HSPACE);
    data.top = new FormAttachment(cancel, 0, SWT.TOP);
    ok.setLayoutData(data);
    ok.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent event) {
            if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(implementationType)
                && (StringUtils.isEmpty(classNameText.getText()))
                && AlfrescoUserTask.ALFRESCO_SCRIPT_TASK_LISTENER.equalsIgnoreCase(implementation)
                    == false
                && AlfrescoScriptTask.ALFRESCO_SCRIPT_EXECUTION_LISTENER.equalsIgnoreCase(
                        implementation)
                    == false) {

              MessageDialog.openError(shell, "Validation error", "Class name must be filled.");
              return;
            }
            if (ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(implementationType)
                && (StringUtils.isEmpty(expressionText.getText()))) {
              MessageDialog.openError(shell, "Validation error", "Expression must be filled.");
              return;
            }
            if (ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION.equals(implementationType)
                && (StringUtils.isEmpty(delegateExpressionText.getText()))) {
              MessageDialog.openError(
                  shell, "Validation error", "Delegate expression must be filled.");
              return;
            }
            eventName = eventDropDown.getText();
            if (AlfrescoUserTask.ALFRESCO_SCRIPT_TASK_LISTENER.equalsIgnoreCase(implementation)
                || AlfrescoScriptTask.ALFRESCO_SCRIPT_EXECUTION_LISTENER.equalsIgnoreCase(
                    implementation)) {

              script = scriptText.getText();
              runAs = runAsText.getText();
              scriptProcessor = scriptProcessorText.getText();

            } else if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(implementationType)) {
              implementation = classNameText.getText();
            } else if (ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(
                implementationType)) {
              implementation = expressionText.getText();
            } else {
              implementation = delegateExpressionText.getText();
            }
            fieldExtensionList = new ArrayList<FieldExtension>();
            if (fieldEditor.getItems() != null) {
              for (TableItem tableItem : fieldEditor.getItems()) {
                FieldExtension fieldModel = new FieldExtension();
                fieldModel.setFieldName(tableItem.getText(0));
                fieldModel.setStringValue(tableItem.getText(1));
                fieldModel.setExpression(tableItem.getText(2));
                fieldExtensionList.add(fieldModel);
              }
            }
            shell.close();
          }
        });

    // Set the OK button as the default, so
    // user can type input and press Enter
    // to dismiss
    shell.setDefaultButton(ok);

    if (savedListener == null || savedListener.getImplementationType() == null) {
      classTypeButton.setSelection(true);
      enableClassType();
    } else if (PreferencesUtil.getBooleanPreference(Preferences.ALFRESCO_ENABLE)
        && AlfrescoUserTask.ALFRESCO_SCRIPT_TASK_LISTENER.equalsIgnoreCase(
            savedListener.getImplementation())) {
      alfrescoTaskTypeButton.setSelection(true);
      enableAlfrescoType(true);
    } else if (PreferencesUtil.getBooleanPreference(Preferences.ALFRESCO_ENABLE)
        && AlfrescoScriptTask.ALFRESCO_SCRIPT_EXECUTION_LISTENER.equalsIgnoreCase(
            savedListener.getImplementation())) {
      alfrescoExecutionTypeButton.setSelection(true);
      enableAlfrescoType(false);
    } else if (ImplementationType.IMPLEMENTATION_TYPE_CLASS.equals(
        savedListener.getImplementationType())) {
      classTypeButton.setSelection(true);
      enableClassType();
    } else if (ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION.equals(
        savedListener.getImplementationType())) {
      expressionTypeButton.setSelection(true);
      enableExpressionType();
    } else {
      delegateExpressionTypeButton.setSelection(true);
      enableDelegateExpressionType();
    }
  }