test_class.declarator: metadata
test_class.modifier: private
test_class.original_string: private Metadata metadata;
test_class.type: Metadata
test_class.var_name: metadata
test_class.declarator: address
test_class.modifier: private
test_class.original_string: private ResourceAddress address;
test_class.type: ResourceAddress
test_class.var_name: address
test_class.declarator: operationFactory
test_class.modifier: private
test_class.original_string: private OperationFactory operationFactory;
test_class.type: OperationFactory
test_class.var_name: operationFactory
test_class.file: core/src/test/java/org/jboss/hal/core/OperationFactoryTest.java
test_class.identifier: OperationFactoryTest
test_case.body: @Test
      public void alternativesWithConflicts2() {
          // Turn elytron 'off'
          Composite composite = operationFactory.fromChangeSet(address,
                  ImmutableMap.of("elytron-enabled", false, "security-domain", "foo"), metadata);
  
          assertEquals(6, composite.size());
          assertUndefine(composite, "security-application");
          assertUndefine(composite, "security-domain-and-application");
          assertUndefine(composite, "elytron-enabled");
          assertUndefine(composite, "authentication-context");
          assertUndefine(composite, "authentication-context-and-application");
          assertWrite(composite, "security-domain", "foo");
      }
test_case.class_method_signature: OperationFactoryTest.alternativesWithConflicts2()
test_case.full_signature: @Test public void alternativesWithConflicts2()
test_case.identifier: alternativesWithConflicts2
test_case.invocations: fromChangeSet of assertEquals size assertUndefine assertUndefine assertUndefine assertUndefine assertUndefine assertWrite
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void alternativesWithConflicts2()
focal_class.declarator: logger = LoggerFactory.getLogger(OperationFactory.class)
focal_class.modifier: private static final
focal_class.original_string: private static final Logger logger = LoggerFactory.getLogger(OperationFactory.class);
focal_class.type: Logger
focal_class.var_name: logger
focal_class.declarator: nameFn
focal_class.modifier: private final
focal_class.original_string: private final Function<String, String> nameFn;
focal_class.type: Function<String, String>
focal_class.var_name: nameFn
focal_class.file: core/src/main/java/org/jboss/hal/core/OperationFactory.java
focal_class.identifier: OperationFactory
focal_class.class_method_signature: OperationFactory.OperationFactory()
focal_class.full_signature: public  OperationFactory()
focal_class.identifier: OperationFactory
focal_class.modifiers: public
focal_class.parameters: ()
focal_class.signature:  OperationFactory()
focal_class.class_method_signature: OperationFactory.OperationFactory(Function<String, String> nameFn)
focal_class.full_signature: public  OperationFactory(Function<String, String> nameFn)
focal_class.identifier: OperationFactory
focal_class.modifiers: public
focal_class.parameters: (Function<String, String> nameFn)
focal_class.signature:  OperationFactory(Function<String, String> nameFn)
focal_class.class_method_signature: OperationFactory.fromChangeSet(ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata)
focal_class.full_signature: public Composite fromChangeSet(ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata)
focal_class.identifier: fromChangeSet
focal_class.modifiers: public
focal_class.parameters: (ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata)
focal_class.return: Composite
focal_class.signature: Composite fromChangeSet(ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata)
focal_class.class_method_signature: OperationFactory.resetResource(ResourceAddress address, Set<String> attributes,
              Metadata metadata)
focal_class.full_signature:  Composite resetResource(ResourceAddress address, Set<String> attributes,
              Metadata metadata)
focal_class.identifier: resetResource
focal_class.parameters: (ResourceAddress address, Set<String> attributes,
              Metadata metadata)
focal_class.return: Composite
focal_class.signature: Composite resetResource(ResourceAddress address, Set<String> attributes,
              Metadata metadata)
focal_class.class_method_signature: OperationFactory.isNullOrEmpty(Object value)
focal_class.full_signature: private boolean isNullOrEmpty(Object value)
focal_class.identifier: isNullOrEmpty
focal_class.modifiers: private
focal_class.parameters: (Object value)
focal_class.return: boolean
focal_class.signature: boolean isNullOrEmpty(Object value)
focal_class.class_method_signature: OperationFactory.undefineAttribute(ResourceAddress address, String name)
focal_class.full_signature: private Operation undefineAttribute(ResourceAddress address, String name)
focal_class.identifier: undefineAttribute
focal_class.modifiers: private
focal_class.parameters: (ResourceAddress address, String name)
focal_class.return: Operation
focal_class.signature: Operation undefineAttribute(ResourceAddress address, String name)
focal_class.class_method_signature: OperationFactory.writeAttribute(ResourceAddress address, String name, Object value,
              ResourceDescription resourceDescription)
focal_class.full_signature: private Operation writeAttribute(ResourceAddress address, String name, Object value,
              ResourceDescription resourceDescription)
focal_class.identifier: writeAttribute
focal_class.modifiers: private
focal_class.parameters: (ResourceAddress address, String name, Object value,
              ResourceDescription resourceDescription)
focal_class.return: Operation
focal_class.signature: Operation writeAttribute(ResourceAddress address, String name, Object value,
              ResourceDescription resourceDescription)
focal_class.class_method_signature: OperationFactory.attributeName(String name)
focal_class.full_signature: private String attributeName(String name)
focal_class.identifier: attributeName
focal_class.modifiers: private
focal_class.parameters: (String name)
focal_class.return: String
focal_class.signature: String attributeName(String name)
focal_class.class_method_signature: OperationFactory.asValueNode(String name, Object value, ResourceDescription resourceDescription)
focal_class.full_signature: private ModelNode asValueNode(String name, Object value, ResourceDescription resourceDescription)
focal_class.identifier: asValueNode
focal_class.modifiers: private
focal_class.parameters: (String name, Object value, ResourceDescription resourceDescription)
focal_class.return: ModelNode
focal_class.signature: ModelNode asValueNode(String name, Object value, ResourceDescription resourceDescription)
focal_method.body: public Composite fromChangeSet(ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata) {
  
          // TODO Is it safe to always use ATTRIBUTES as path when calling ResourceDescription methods?
          Map<String, Operation> operations = new HashMap<>();
          HashMap<String, Object> localChanges = new HashMap<>(changeSet);
          ResourceDescription resourceDescription = metadata.getDescription();
  
          // look for alternatives
          Set<String> conflicts = new HashSet<>();
          Map<String, List<String>> allAlternatives = localChanges.keySet().stream()
                  .filter(name -> {
                      Object value = changeSet.get(name);
                      return !isNullOrEmpty(value);
                  })
                  .collect(toMap(identity(), name -> resourceDescription.findAlternatives(ATTRIBUTES, name)));
          allAlternatives.forEach((attribute, alternatives) -> {
  
              logger.debug("Alternatives resolution for {} -> [{}]", attribute, String.join(", ", alternatives));
              HashSet<String> intersection = new HashSet<>(alternatives);
              intersection.retainAll(changeSet.keySet());
              if (intersection.isEmpty()) {
  
                  // the easy part: no conflicts
                  alternatives.forEach(alternative -> {
                      boolean alternativeDoesntExist = resourceDescription.findAttribute(ATTRIBUTES, alternative) == null;
                      if (resourceDescription.isDeprecated(ATTRIBUTES, alternative) || alternativeDoesntExist) {
                          logger.debug("Skip undefine operations for deprecated or non-existent alternative {}",
                                  alternative);
                      } else {
                          logger.debug("Add undefine operations for alternative {}", alternative);
                          operations.putIfAbsent(alternative, undefineAttribute(address, alternative));
                          List<String> requires = resourceDescription.findRequires(ATTRIBUTES, alternative);
                          if (!requires.isEmpty()) {
                              logger.debug("Add undefine operations for attributes which require {}: [{}]", alternative,
                                      String.join(", ", requires));
                              requires.forEach(r -> operations.putIfAbsent(r, undefineAttribute(address, r)));
                          }
                      }
                  });
  
              } else {
                  // possible conflicts: one or more alternatives are also in the change-set
                  // just collect for now and resolve later
                  conflicts.add(attribute);
                  conflicts.addAll(intersection);
                  logger.debug("Record conflict {} <-> [{}]", attribute, String.join(", ", intersection));
              }
  
              alternatives.forEach(localChanges::remove);
          });
  
          if (!conflicts.isEmpty()) {
              // try to resolve conflicts: only one of the conflicting attributes must have a value other than
              // null, empty or default
              logger.debug("Try to resolve conflicts between alternatives [{}]", String.join(", ", conflicts));
              Map<Boolean, List<String>> resolution = conflicts.stream().collect(groupingBy(conflict -> {
                  Object value = changeSet.get(conflict);
                  return isNullOrEmpty(value) || resourceDescription.isDefaultValue(ATTRIBUTES, conflict, value);
              }));
              List<String> undefine = resolution.getOrDefault(true, Collections.emptyList());
              List<String> write = resolution.getOrDefault(false, Collections.emptyList());
              if (write.size() > 1) {
                  logger.error(
                          "More than one conflicting alternative attribute which is not null, empty or default: [{}]. This should have been caught by a form validation. Adding the write operations anyway to get an appropriate error message from the server.",
                          String.join(", ", write));
              }
  
              logger.debug("Add undefine operations for [{}], write operation for [{}]",
                      String.join(", ", undefine), String.join(", ", write));
              undefine.forEach(u -> {
                  operations.putIfAbsent(u, undefineAttribute(address, u));
                  localChanges.remove(u);
                  // process requires of the current undefine attribute
                  List<String> requires = resourceDescription.findRequires(ATTRIBUTES, u);
                  requires.forEach(ur -> {
                      operations.putIfAbsent(ur, undefineAttribute(address, ur));
                      localChanges.remove(ur);
                  });
              });
  
              write.forEach(w -> {
                  operations.putIfAbsent(w, writeAttribute(address, w, changeSet.get(w), resourceDescription));
                  localChanges.remove(w);
                  List<String> writeAlternatives = resourceDescription.findAlternatives(ATTRIBUTES, w);
                  // process alternatives of the current write attribute
                  writeAlternatives.forEach(wa -> {
                      operations.putIfAbsent(wa, undefineAttribute(address, wa));
                      localChanges.remove(wa);
                  });
              });
          }
  
          // handle the remaining attributes
          logger.debug("Process remaining attributes [{}]", String.join(", ", localChanges.keySet()));
          localChanges.forEach((name, value) ->
                  operations.putIfAbsent(name, writeAttribute(address, name, value, resourceDescription)));
          return new Composite(operations.values().stream().filter(Objects::nonNull).collect(toList()));
      }
focal_method.class_method_signature: OperationFactory.fromChangeSet(ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata)
focal_method.full_signature: public Composite fromChangeSet(ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata)
focal_method.identifier: fromChangeSet
focal_method.invocations: getDescription collect filter stream keySet get isNullOrEmpty toMap identity findAlternatives forEach debug join retainAll keySet isEmpty forEach findAttribute isDeprecated debug debug putIfAbsent undefineAttribute findRequires isEmpty debug join forEach putIfAbsent undefineAttribute add addAll debug join forEach isEmpty debug join collect stream groupingBy get isNullOrEmpty isDefaultValue getOrDefault emptyList getOrDefault emptyList size error join debug join join forEach putIfAbsent undefineAttribute remove findRequires forEach putIfAbsent undefineAttribute remove forEach putIfAbsent writeAttribute get remove findAlternatives forEach putIfAbsent undefineAttribute remove debug join keySet forEach putIfAbsent writeAttribute collect filter stream values toList
focal_method.modifiers: public
focal_method.parameters: (ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata)
focal_method.return: Composite
focal_method.signature: Composite fromChangeSet(ResourceAddress address, Map<String, Object> changeSet,
              Metadata metadata)