@Test
  @DiagramResource(
      "org/camunda/bpm/modeler/test/ui/change/FieldInjectionAddElementToExtension.bpmn")
  public void testAddFieldElementOnlyWithNameToExistingFieldsWithAttributes() {
    final ServiceTask serviceTask =
        findBusinessObjectById(diagram, "ServiceTask_1", ServiceTask.class);

    List<FieldType> fieldTypeList = ExtensionUtil.getExtensions(serviceTask, FieldType.class);
    assertThat(fieldTypeList).hasSize(2);

    final FieldType fieldType = modelFactory.createFieldType();
    fieldType.setName("myFieldElement");

    ExtensionChangeFilter filter = new ExtensionChangeFilter(serviceTask, FIELD_TYPE_FEATURE);
    CustomResourceSetListener listener = new CustomResourceSetListener(serviceTask, filter);
    listener.register();

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            ExtensionUtil.addExtension(serviceTask, FIELD_TYPE_FEATURE, fieldType);
          }
        });

    assertThat(listener.getCapturedEvents()).hasSize(1);

    fieldTypeList = ExtensionUtil.getExtensions(serviceTask, FieldType.class);
    assertThat(fieldTypeList).hasSize(3);
  }
  @Test
  @DiagramResource(
      "org/camunda/bpm/modeler/test/core/utils/ExtensionUtilTest.testGetExtensionAttributeValues.bpmn")
  public void testUpdateExtension() {
    final CallActivity callActivity1 =
        findBusinessObjectById(diagram, "CallActivity_1", CallActivity.class);

    Object valueBefore = ExtensionUtil.getExtension(callActivity1, RETRY_CYCLE_FEATURE, "text");

    assertThat(valueBefore).isEqualTo("R3/PT10S");

    final FailedJobRetryTimeCycleType retryCycle = foxFactory.createFailedJobRetryTimeCycleType();
    retryCycle.setText("R3/PT200000S");

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            ExtensionUtil.updateExtension(callActivity1, RETRY_CYCLE_FEATURE, retryCycle);
          }
        });

    Object valueAfter = ExtensionUtil.getExtension(callActivity1, RETRY_CYCLE_FEATURE, "text");

    assertThat(valueAfter).isEqualTo("R3/PT200000S");
  }
  @Test
  @DiagramResource(
      "org/camunda/bpm/modeler/test/ui/change/FormFieldEditAndRemoveChangeSupportTest.bpmn")
  public void testFormFieldPropertyElementRemove() {
    final UserTask userTask = findBusinessObjectById(diagram, "UserTask_1", UserTask.class);

    List<FormDataType> formDataTypeList = ExtensionUtil.getExtensions(userTask, FormDataType.class);
    assertThat(formDataTypeList).hasSize(1);

    EList<FormFieldType> formFieldList = formDataTypeList.get(0).getFormField();
    assertThat(formFieldList).hasSize(1);

    final FormFieldType formFieldType = formFieldList.get(0);
    assertThat(formFieldType).isNotNull();

    assertThat(formFieldType.getProperties().getProperty()).isNotNull();

    AnyNestedChangeFilter filter =
        new AnyNestedChangeFilter(formFieldType, FORM_FIELD_PROPERTIES_FEATURE);
    CustomResourceSetListener listener = new CustomResourceSetListener(formFieldType, filter);
    listener.register();

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            formFieldType.getProperties().getProperty().remove(0);
          }
        });

    assertThat(listener.getCapturedEvents()).hasSize(1);
  }
  @Test
  @DiagramResource("org/camunda/bpm/modeler/test/ui/change/FormFieldChangeSupportTest.bpmn")
  public void testFormFieldElementUpdate() {
    final UserTask userTask = findBusinessObjectById(diagram, "UserTask_1", UserTask.class);

    List<FormDataType> formDataTypeList = ExtensionUtil.getExtensions(userTask, FormDataType.class);
    assertThat(formDataTypeList).hasSize(1);

    final EList<FormFieldType> formFieldList = formDataTypeList.get(0).getFormField();
    assertThat(formFieldList).hasSize(1);

    AnyNestedChangeFilter filter = new AnyNestedChangeFilter(userTask, FORM_DATA_FEATURE);
    CustomResourceSetListener listener = new CustomResourceSetListener(userTask, filter);
    listener.register();

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            formFieldList.get(0).setId("newValue");
          }
        });

    assertThat(listener.getCapturedEvents()).hasSize(1);
  }
  @Test
  @DiagramResource("org/camunda/bpm/modeler/test/ui/change/FormDataAddChangeSupportTest.bpmn")
  public void testFormDataAndFormFieldElementAdd() {
    final UserTask userTask = findBusinessObjectById(diagram, "UserTask_1", UserTask.class);

    List<FormDataType> formDataTypeList = ExtensionUtil.getExtensions(userTask, FormDataType.class);
    assertThat(formDataTypeList).isEmpty();

    AnyNestedChangeFilter filter = new AnyNestedChangeFilter(userTask, FORM_DATA_FEATURE);
    CustomResourceSetListener listener = new CustomResourceSetListener(userTask, filter);
    listener.register();

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            // add form data with form field
            FormDataType formData = ModelFactory.eINSTANCE.createFormDataType();
            ExtensionUtil.addExtension(userTask, FORM_DATA_FEATURE, formData);

            FormFieldType formField = ModelFactory.eINSTANCE.createFormFieldType();
            formField.setId("test");
            formField.setType("string");
            formData.getFormField().add(formField);
          }
        });

    assertThat(listener.getCapturedEvents()).hasSize(1);
  }
  @Test
  @DiagramResource("org/camunda/bpm/modeler/test/ui/change/FormFieldChangeSupportTest.bpmn")
  public void testFormFieldValueElementAdd() {
    final UserTask userTask = findBusinessObjectById(diagram, "UserTask_1", UserTask.class);

    List<FormDataType> formDataTypeList = ExtensionUtil.getExtensions(userTask, FormDataType.class);
    assertThat(formDataTypeList).hasSize(1);

    EList<FormFieldType> formFieldList = formDataTypeList.get(0).getFormField();
    assertThat(formFieldList).hasSize(1);

    final FormFieldType formFieldType = formFieldList.get(0);
    assertThat(formFieldType).isNotNull();

    FeatureChangeFilter filter = new FeatureChangeFilter(formFieldType, FORM_FIELD_VALUE_FEATURE);
    CustomResourceSetListener listener = new CustomResourceSetListener(formFieldType, filter);
    listener.register();

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            ValueType formFieldValueType = ModelFactory.eINSTANCE.createValueType();
            formFieldValueType.setId("test");
            formFieldValueType.setName("test");
            formFieldType.getValue().add(formFieldValueType);
          }
        });

    assertThat(listener.getCapturedEvents()).hasSize(1);
  }
  @Test
  @DiagramResource("org/camunda/bpm/modeler/test/ui/change/ChangeSupportTest.testBase.bpmn")
  public void testExtensionElementNestedAttributeUnset() {
    final CallActivity callActivity1 =
        findBusinessObjectById(diagram, "CallActivity_1", CallActivity.class);

    // add stuff
    final InType type = addCallActivityInType(callActivity1);

    ExtensionChangeFilter filter = new ExtensionChangeFilter(callActivity1, IN_FEATURE);
    CustomResourceSetListener listener = new CustomResourceSetListener(callActivity1, filter);
    listener.register();

    List<InType> inTypes = ExtensionUtil.getExtensions(callActivity1, InType.class);
    assertThat(inTypes).hasSize(1);

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            type.eUnset(modelPackage.getInType_Source());
          }
        });

    assertThat(listener.getCapturedEvents()).hasSize(1);
  }
  @Test
  @DiagramResource("org/camunda/bpm/modeler/test/ui/change/ChangeSupportTest.testBase.bpmn")
  public void testExtensionElementUpdate() {
    final Task task1 = findBusinessObjectById(diagram, "Task_1", Task.class);

    ExtensionChangeFilter filter = new ExtensionChangeFilter(task1, RETRY_CYCLE_FEATURE);
    CustomResourceSetListener listener = new CustomResourceSetListener(task1, filter);

    listener.register();

    final FailedJobRetryTimeCycleType retryCycle = foxFactory.createFailedJobRetryTimeCycleType();
    retryCycle.setText("R3/PT10S");

    // assert that feature is set
    assertThat(ExtensionUtil.getExtension(task1, RETRY_CYCLE_FEATURE, "text")).isNotNull();

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            ExtensionUtil.updateExtension(task1, RETRY_CYCLE_FEATURE, retryCycle);
          }
        });

    assertThat(listener.getCapturedEvents()).hasSize(1);
  }
  @Test
  @DiagramResource("org/camunda/bpm/modeler/test/ui/change/ChangeSupportTest.testBase.bpmn")
  public void testExtensionElementRemoveAndCleanExtensionAttributeValues() {
    final Task task1 = findBusinessObjectById(diagram, "Task_1", Task.class);

    // assert that feature is set
    assertThat(ExtensionUtil.getExtension(task1, RETRY_CYCLE_FEATURE, "text")).isNotNull();

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            ExtensionUtil.removeExtensionByFeature(task1, RETRY_CYCLE_FEATURE);
          }
        });

    ExtensionChangeFilter filter = new ExtensionChangeFilter(task1, RETRY_CYCLE_FEATURE);
    CustomResourceSetListener listener = new CustomResourceSetListener(task1, filter);
    listener.register();

    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            AttributeUtil.clearEmptyExtensionElements(task1);
          }
        });

    assertThat(listener.getCapturedEvents()).hasSize(1);
  }
  @Test
  @DiagramResource(
      "org/camunda/bpm/modeler/test/core/utils/ExtensionUtilTest.testAddAndRemoveExtensions.bpmn")
  public void testAddAndRemoveExtensionsToOutType() {
    final CallActivity callActivity =
        findBusinessObjectById(diagram, "callActivity", CallActivity.class);

    List<ExtensionAttributeValue> extensionAttributeValues =
        ExtensionUtil.getExtensionAttributeValues(callActivity);
    assertThat(extensionAttributeValues).hasSize(0);

    // add <camunda:out source="test" target="test"/>
    final OutType sourceOutType = modelFactory.createOutType();
    sourceOutType.setSource("test");
    sourceOutType.setTarget("test");

    addCallActivityExtension(callActivity, CALL_ACTIVITY_OUT_TYPE, sourceOutType);

    Object value = ExtensionUtil.getExtension(callActivity, CALL_ACTIVITY_OUT_TYPE, "source");
    assertThat(value).isEqualTo("test");

    // add <camunda:out source="test2" target="test2"/>
    final OutType source2OutType = modelFactory.createOutType();
    source2OutType.setSource("test2");
    source2OutType.setTarget("test2");

    addCallActivityExtension(callActivity, CALL_ACTIVITY_OUT_TYPE, source2OutType);

    // add <camunda:out variables="all"/>
    final OutType variablesOutType = modelFactory.createOutType();
    variablesOutType.setVariables(ALL_VARIABLES_VALUE);

    addCallActivityExtension(callActivity, CALL_ACTIVITY_OUT_TYPE, variablesOutType);

    value = ExtensionUtil.getExtension(callActivity, CALL_ACTIVITY_OUT_TYPE, "variables");
    assertThat(value).isEqualTo(ALL_VARIABLES_VALUE);

    List<OutType> extensions = ExtensionUtil.getExtensions(callActivity, OutType.class);
    assertThat(extensions).hasSize(3);

    // remove outType source="test2" extension
    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            ExtensionUtil.removeExtensionByValue(
                callActivity, CALL_ACTIVITY_OUT_TYPE, OUT_TYPE_SOURCE, "test2");
          }
        });

    extensions = ExtensionUtil.getExtensions(callActivity, OutType.class);
    assertThat(extensions).hasSize(2);

    value = ExtensionUtil.getExtension(callActivity, CALL_ACTIVITY_OUT_TYPE, "source");
    assertThat(value).isEqualTo("test");

    extensionAttributeValues = ExtensionUtil.getExtensionAttributeValues(callActivity);
    assertThat(extensionAttributeValues).hasSize(1);
  }
  @Test
  @DiagramResource(
      "org/camunda/bpm/modeler/test/core/utils/ExtensionUtilTest.testGetExtensionOutOfManyOutTypes.bpmn")
  public void testGetExtensionOutOfManyOutTypes() {
    final CallActivity callActivity =
        findBusinessObjectById(diagram, "callActivity", CallActivity.class);

    List<ExtensionAttributeValue> extensionAttributeValues =
        ExtensionUtil.getExtensionAttributeValues(callActivity);
    assertThat(extensionAttributeValues).hasSize(1);

    Object variablesValue =
        ExtensionUtil.getExtension(callActivity, CALL_ACTIVITY_OUT_TYPE, "variables");

    assertThat(variablesValue).isEqualTo("all");

    List<OutType> extensions = ExtensionUtil.getExtensions(callActivity, OutType.class);
    assertThat(extensions).hasSize(4);
  }
  @Test
  @DiagramResource(
      "org/camunda/bpm/modeler/test/core/utils/ExtensionUtilTest.testGetExtensionAttributeValues.bpmn")
  public void testGetExtensionAttribute() {
    final CallActivity callActivity1 =
        findBusinessObjectById(diagram, "CallActivity_1", CallActivity.class);

    Object value = ExtensionUtil.getExtension(callActivity1, RETRY_CYCLE_FEATURE, "text");

    assertThat(value).isEqualTo("R3/PT10S");
  }
  @Test
  @DiagramResource
  public void testGetExtensionAttributeValues() {
    CallActivity callActivity1 =
        (CallActivity) Util.findBusinessObjectById(diagram, "CallActivity_1");

    assertThat(callActivity1).isNotNull();

    List<ExtensionAttributeValue> callActivity1ExtensionValues =
        ExtensionUtil.getExtensionAttributeValues(callActivity1);

    assertThat(callActivity1ExtensionValues).hasSize(1);

    Task task1 = (Task) Util.findBusinessObjectById(diagram, "Task_1");

    List<ExtensionAttributeValue> task1ExtensionValues =
        ExtensionUtil.getExtensionAttributeValues(task1);

    assertThat(task1ExtensionValues).hasSize(0);
  }
  @Test
  @DiagramResource(
      "org/camunda/bpm/modeler/test/core/utils/ExtensionUtilTest.testAddAndRemoveExtensions.bpmn")
  public void testAddAndRemoveExtensionsToInType() {
    final CallActivity callActivity =
        findBusinessObjectById(diagram, "callActivity", CallActivity.class);

    List<ExtensionAttributeValue> extensionAttributeValues =
        ExtensionUtil.getExtensionAttributeValues(callActivity);
    assertThat(extensionAttributeValues).hasSize(0);

    // add <camunda:in source="test" target="test"/>
    final InType sourceInType = modelFactory.createInType();
    sourceInType.setSource("test");
    sourceInType.setTarget("test");

    addCallActivityExtension(callActivity, CALL_ACTIVITY_IN_TYPE, sourceInType);

    Object value = ExtensionUtil.getExtension(callActivity, CALL_ACTIVITY_IN_TYPE, "source");
    assertThat(value).isEqualTo("test");

    // add <camunda:in source="test2" target="test2"/>
    final InType source2InType = modelFactory.createInType();
    source2InType.setSource("test2");
    source2InType.setTarget("test2");

    addCallActivityExtension(callActivity, CALL_ACTIVITY_IN_TYPE, source2InType);

    // add <camunda:in businessKey="#{execution.processBusinessKey}"/>
    final InType businessKeyInType = modelFactory.createInType();
    businessKeyInType.setBusinessKey(BUSINESS_KEY_EXPRESSION);

    addCallActivityExtension(callActivity, CALL_ACTIVITY_IN_TYPE, businessKeyInType);

    value = ExtensionUtil.getExtension(callActivity, CALL_ACTIVITY_IN_TYPE, "businessKey");
    assertThat(value).isEqualTo(BUSINESS_KEY_EXPRESSION);

    // add <camunda:in variables="all"/>
    final InType variablesInType = modelFactory.createInType();
    variablesInType.setVariables(ALL_VARIABLES_VALUE);

    addCallActivityExtension(callActivity, CALL_ACTIVITY_IN_TYPE, variablesInType);

    value = ExtensionUtil.getExtension(callActivity, CALL_ACTIVITY_IN_TYPE, "variables");
    assertThat(value).isEqualTo(ALL_VARIABLES_VALUE);

    List<InType> extensions = ExtensionUtil.getExtensions(callActivity, InType.class);
    assertThat(extensions).hasSize(4);

    // remove inType businessKey extension
    transactionalExecute(
        new RecordingCommand(editingDomain) {

          @Override
          protected void doExecute() {
            ExtensionUtil.removeExtensionByValue(
                callActivity, CALL_ACTIVITY_IN_TYPE, IN_TYPE_BUSINESS_KEY, BUSINESS_KEY_EXPRESSION);
          }
        });

    extensions = ExtensionUtil.getExtensions(callActivity, InType.class);
    assertThat(extensions).hasSize(3);

    value = ExtensionUtil.getExtension(callActivity, CALL_ACTIVITY_IN_TYPE, "businessKey");
    assertThat(value).isNull();

    extensionAttributeValues = ExtensionUtil.getExtensionAttributeValues(callActivity);
    assertThat(extensionAttributeValues).hasSize(1);
  }