private void removeDeselectedDomainValues(Attribute attribute, Set<Integer> values) {
   EList<String> deselectedDomainValues = attribute.getDeselectedDomainValues();
   Domain domain = attribute.getDomain();
   for (String valueString : deselectedDomainValues) {
     int deselectedValue = FeatureModelHelper.getDomainValueForString(valueString, domain);
     Integer deselected = Integer.valueOf(deselectedValue);
     values.remove(deselected);
   }
 }
  private IntegerVariable getOrCreateVariable(Attribute attribute) {
    String attributeName = attribute.getName();
    String featureId = attribute.getFeature().getId();
    String identifier = attributeValue;

    String[] parts = new String[] {identifier, featureId, attributeName};

    String attributeId = concatenate(parts, attributeDelimiter);

    IntegerVariable integerVariable = nodeVariables.get(attributeId);
    if (integerVariable == null) {
      integerVariable = createAttributeValueVariable(attribute, attributeId);
      nodeVariables.put(attributeId, integerVariable);
    }
    return integerVariable;
  }
  private Constraint getMemberConstraint(Attribute attribute) {
    Constraint memberConstraint = null;

    IntegerVariable attributeValueVariable = getOrCreateVariable(attribute);

    // if attribute value is set, then the according attribute value must be
    // set
    if (FeatureModelHelper.isAttributeValueSet(attribute)) {
      int value = FeatureModelHelper.getAttributeValue(attribute);
      memberConstraint = Choco.eq(value, attributeValueVariable);
    } else {
      // check domain values
      Domain domain = attribute.getDomain();

      if (domain instanceof NumericalDomain) {
        NumericalDomain numericalDomain = (NumericalDomain) domain;
        // value of attribute must be in one of the intervals.
        int[] values = getNumericalValues(numericalDomain, attribute);
        memberConstraint = Choco.member(attributeValueVariable, values);

      } else if (domain instanceof DiscreteDomain) {
        DiscreteDomain discreteDomain = (DiscreteDomain) domain;
        int[] domainValues = discreteDomainValues.get(discreteDomain.getId());
        memberConstraint = Choco.member(attributeValueVariable, domainValues);
      }
    }
    return memberConstraint;
  }
  private void transformAttribute(Attribute attribute) {
    // 0: attribute is disabled if feature is disabled
    // 1: attribute is enabled if feature is selected
    IntegerVariable featureVariable = getOrCreateVariable(attribute.getFeature());

    Constraint memberConstraint = getMemberConstraint(attribute);

    // if feature is enabled, then attribute value must be in bounds
    Constraint featureEnabled = Choco.eq(featureVariable, 1);
    Constraint checkAttribute = Choco.implies(featureEnabled, memberConstraint);
    getModel().addConstraint(checkAttribute);

    IntegerVariable attributeVariable = getOrCreateVariable(attribute);

    Constraint featureDisabled = Choco.eq(featureVariable, 0);
    Constraint attrDisabled = Choco.eq(attributeVariable, attributeDisabled);

    Constraint disabledAttr = Choco.ifOnlyIf(featureDisabled, attrDisabled);
    getModel().addConstraint(disabledAttr);
  }
  private IntegerVariable createAttributeValueVariable(Attribute attribute, String attributeId) {
    // String attrOptions = "cp:no_decision";
    String attrOptions = "";
    IntegerVariable attributeVariable = null;

    // (1) if attribute value is set, then attribute can either be this value or the disabled
    // attribute value
    if (FeatureModelHelper.isAttributeValueSet(attribute)) {
      int value = FeatureModelHelper.getAttributeValue(attribute);
      int[] attributeValues = new int[] {value, attributeDisabled};
      attributeVariable = Choco.makeIntVar(attributeId, attributeValues, attrOptions);
    } else {

      Domain attributeDomain = attribute.getDomain();

      // (2) if attribute domain is discrete
      if (attributeDomain instanceof DiscreteDomain) {
        DiscreteDomain discreteDomain = (DiscreteDomain) attributeDomain;
        int[] domainValues = getDomainValues(attribute, discreteDomain);
        attributeVariable = Choco.makeIntVar(attributeId, domainValues, attrOptions);

        // todo: check numerical domain and use intervals instead
        // (3) if attribute domain is integer
      } else if (attributeDomain instanceof NumericalDomain) {
        NumericalDomain numericalDomain = (NumericalDomain) attributeDomain;
        int lowestBoundofNumericalDomain = getLowestBoundofNumericalDomain(numericalDomain);
        int highestBoundofNumericalDomain = getHighestBoundofNumericalDomain(numericalDomain);
        if (lowestBoundofNumericalDomain > attributeDisabled) {
          lowestBoundofNumericalDomain = attributeDisabled;
        }
        attributeVariable =
            Choco.makeIntVar(
                attributeId,
                lowestBoundofNumericalDomain,
                highestBoundofNumericalDomain,
                attrOptions);
      }
    }
    return attributeVariable;
  }