/**
   * Tests whether the refactoring merges the constants of two enumerations correctly. The generated
   * enumeration must contain the constants from all variants.
   *
   * @throws Exception In case of an unexpected exception.
   */
  @Test
  public void testRefactorCaseEnumerationAddEnumConstant() throws Exception {
    VariationPoint vp =
        RefactoringTestUtil.getEnumerationAddEnumConstantCase(VariabilityType.OPTXOR);
    IfStaticConfigClassEnumerationInMemberContainer refactoring =
        new IfStaticConfigClassEnumerationInMemberContainer();
    refactoring.refactor(vp, null);

    // location has one member (the enumeration)
    MemberContainer vpLocation =
        (MemberContainer) ((JaMoPPJavaSoftwareElement) vp.getLocation()).getJamoppElement();
    assertThat(vpLocation.getMembers().size(), equalTo(1));

    // member is an enumeration
    assertThat(vpLocation.getMembers().get(0), instanceOf(Enumeration.class));

    Enumeration enumeration = (Enumeration) vpLocation.getMembers().get(0);

    // enumeration has the correct name and the two constants from the base and the integration
    assertThat(enumeration.getName(), equalTo("A"));
    assertThat(enumeration.getConstants().size(), equalTo(2));
    assertThat(enumeration.getConstants().get(0).getName(), anyOf(equalTo("A"), equalTo("B")));
    assertThat(enumeration.getConstants().get(1).getName(), anyOf(equalTo("A"), equalTo("B")));
    assertThat(
        enumeration.getConstants().get(0).getName(),
        not(equalTo(enumeration.getConstants().get(1).getName())));

    // verify correct VPM
    RefactoringTestUtil.assertValidVPM(vp);
  }
  /**
   * Tests whether the refactoring
   *
   * @throws Exception In case of an unexpected exception.
   */
  @Test
  public void testRefactorCaseMethodAddDifferentParam() throws Exception {
    VariationPoint vp = RefactoringTestUtil.getMethodAddDifferentParamCase(VariabilityType.OPTXOR);
    IfStaticConfigClassMethod refactoring = new IfStaticConfigClassMethod();
    refactoring.refactor(vp, null);

    // location has two methods
    Class vpLocation = (Class) ((JaMoPPJavaSoftwareElement) vp.getLocation()).getJamoppElement();
    assertThat(vpLocation.getMethods().size(), equalTo(2));

    Method firstMethod = vpLocation.getMethods().get(0);
    Method secondMethod = vpLocation.getMethods().get(1);

    // assert number of parameters
    assertThat(firstMethod.getParameters().size(), anyOf(equalTo(1), equalTo(2)));
    assertThat(secondMethod.getParameters().size(), anyOf(equalTo(1), equalTo(2)));
    assertThat(
        firstMethod.getParameters().size(), not(equalTo(secondMethod.getParameters().size())));

    // assert method names and return types
    assertThat(firstMethod.getName(), equalTo("someMethod"));
    assertThat(secondMethod.getName(), equalTo("someMethod"));
    assertThat(firstMethod.getTypeReference(), instanceOf(Void.class));
    assertThat(secondMethod.getTypeReference(), instanceOf(Void.class));

    // verify correct VPM
    RefactoringTestUtil.assertValidVPM(vp);
  }
 /**
  * Executes the given replacement associated with the variation point. This is quite time
  * consuming because the replacement is carried out in a generic way. If possible, try to provide
  * another specialized implementation for the technology-specific refactorings.
  *
  * @param replacement The replacement to be executed.
  * @param variationPoint The associated variation point.
  */
 protected void executeReplacement(
     Map.Entry<EObject, EObject> replacement, VariationPoint variationPoint) {
   LOGGER.debug(
       String.format("Replacing %s with %s.", replacement.getKey(), replacement.getValue()));
   ReplacementUtil.replaceCrossReferences(
       replacement.getKey(), replacement.getValue(), variationPoint.eResource().getResourceSet());
 }
  /**
   * Tests whether the refactoring
   *
   * @throws Exception In case of an unexpected exception.
   */
  @Test
  public void testRefactorCaseMethodAddSameParam() throws Exception {
    VariationPoint vp = RefactoringTestUtil.getMethodAddSameParamCase(VariabilityType.OPTXOR);
    IfStaticConfigClassMethod refactoring = new IfStaticConfigClassMethod();
    refactoring.refactor(vp, null);

    // location has one method
    Class vpLocation = (Class) ((JaMoPPJavaSoftwareElement) vp.getLocation()).getJamoppElement();
    assertThat(vpLocation.getMethods().size(), equalTo(1));

    // assert number of parameters
    assertThat(vpLocation.getMethods().get(0).getParameters().size(), equalTo(0));

    // assert method name and return type
    assertThat(vpLocation.getMethods().get(0).getTypeReference(), instanceOf(Void.class));

    // verify correct VPM
    RefactoringTestUtil.assertValidVPM(vp);
  }
 @Override
 public List<Resource> refactor(
     VariationPoint variationPoint, Map<String, Object> refactoringConfigurations) {
   new ResourceProcessorService().processVPBeforeFullyAutomatedRefactoring(variationPoint);
   List<Resource> changedResources =
       refactorFullyAutomated(variationPoint, refactoringConfigurations);
   fixVPMAfterRefactoring(variationPoint);
   variationPoint.setRefactored(true);
   return changedResources;
 }
  /**
   * Fixes the VPM after the refactoring has been carried out. This is necessary because the
   * elements referenced by the VPM might have been replaced during the refactoring. This leads to
   * dangling references and an invalid VPM. Fixing is done by applying the recorded changes.
   * Changes are recorded by the protected helper methods of this class.
   *
   * @param variationPoint The variation point to fix.
   */
  private void fixVPMAfterRefactoring(VariationPoint variationPoint) {

    /**
     * The information we collect: - Replacements between an original and a replacement - Newly
     * created elements corresponding to a specific variant
     *
     * <p>What we do: - calculate the transitive closure of replacements to become independent from
     * execution order - partition the stored replacements in replacements that - A: shall be
     * applied - B: are already contained by a newly created element - Apply A - Delete B from the
     * variation point (as it is already included in a newly created element) - Add the newly
     * created elements to the VPM
     */
    Map<EObject, EObject> replacementsClosure = calculateTransitiveClosure(replacements);

    PartitionedReplacements partitionedReplacements =
        partitionReplacements(replacementsClosure, variantSpecificelements);

    for (Map.Entry<EObject, EObject> replacement : partitionedReplacements.getApply()) {
      executeReplacement(replacement, variationPoint);
    }

    for (Map.Entry<EObject, EObject> replacement : partitionedReplacements.getDelete()) {
      LOGGER.debug(String.format("Removing %s from VP.", replacement.getKey()));
      removeSoftwareElement(replacement.getKey(), variationPoint);
    }

    for (Map.Entry<String, Set<EObject>> variantSpecifics : variantSpecificelements.entrySet()) {
      final String variantId = variantSpecifics.getKey();
      Variant variant =
          Iterables.find(
              variationPoint.getVariants(),
              new Predicate<Variant>() {
                @Override
                public boolean apply(Variant arg0) {
                  return variantId.equals(arg0.getId());
                }
              });
      if (variant == null) {
        LOGGER.warn(
            "Elements have been registered to the invalid variant ID "
                + variantId
                + ". Ignoring the entries.");
        continue;
      }

      for (EObject eobject : variantSpecifics.getValue()) {
        SoftwareElement swElement = createSoftwareElement(eobject);
        if (swElement == null) {
          LOGGER.warn(
              "We were unable to create a SoftwareElement for the EObject " + eobject + ".");
        }
        variant.getImplementingElements().add(swElement);
      }
    }
  }
 private void removeSoftwareElement(EObject eobject, VariationPoint variationPoint) {
   for (Variant variant : variationPoint.getVariants()) {
     Iterator<SoftwareElement> swElementIterator = variant.getImplementingElements().iterator();
     while (swElementIterator.hasNext()) {
       if (swElementIterator.next().getWrappedElement() == eobject) {
         swElementIterator.remove();
         return;
       }
     }
   }
 }
 /**
  *
  * <!-- begin-user-doc -->
  * <!-- end-user-doc -->
  *
  * @generated
  */
 public VariationPoint getTarget() {
   if (target != null && target.eIsProxy()) {
     InternalEObject oldTarget = (InternalEObject) target;
     target = (VariationPoint) eResolveProxy(oldTarget);
     if (target != oldTarget) {
       if (eNotificationRequired())
         eNotify(
             new ENotificationImpl(
                 this,
                 Notification.RESOLVE,
                 RefinementPackage.REFINEMENT_REASON__TARGET,
                 oldTarget,
                 target));
     }
   }
   return target;
 }
 /**
  *
  * <!-- begin-user-doc -->
  * <!-- end-user-doc -->
  *
  * @generated
  */
 public VariationPoint getSource() {
   if (source != null && source.eIsProxy()) {
     InternalEObject oldSource = (InternalEObject) source;
     source = (VariationPoint) eResolveProxy(oldSource);
     if (source != oldSource) {
       if (eNotificationRequired())
         eNotify(
             new ENotificationImpl(
                 this,
                 Notification.RESOLVE,
                 RefinementPackage.REFINEMENT_REASON__SOURCE,
                 oldSource,
                 source));
     }
   }
   return source;
 }