private void parseRemoteSite(
      XMLExtendedStreamReader reader,
      PathAddress relayAddress,
      Map<PathAddress, ModelNode> operations)
      throws XMLStreamException {
    String site = require(reader, XMLAttribute.NAME);
    PathAddress address = relayAddress.append(RemoteSiteResourceDefinition.pathElement(site));
    ModelNode operation = Util.createAddOperation(address);
    operations.put(address, operation);

    String cluster = null;

    for (int i = 0; i < reader.getAttributeCount(); i++) {
      String value = reader.getAttributeValue(i);
      XMLAttribute attribute = XMLAttribute.forName(reader.getAttributeLocalName(i));
      switch (attribute) {
        case NAME:
          {
            // Already parsed
            break;
          }
        case STACK:
          {
            if (this.schema.since(JGroupsSchema.VERSION_3_0)) {
              throw ParseUtils.unexpectedAttribute(reader, i);
            }
            readAttribute(
                reader, i, operation, RemoteSiteResourceDefinition.DeprecatedAttribute.STACK);
            break;
          }
        case CLUSTER:
          {
            if (this.schema.since(JGroupsSchema.VERSION_3_0)) {
              throw ParseUtils.unexpectedAttribute(reader, i);
            }
            cluster = value;
            break;
          }
        case CHANNEL:
          {
            if (this.schema.since(JGroupsSchema.VERSION_3_0)) {
              readAttribute(reader, i, operation, RemoteSiteResourceDefinition.Attribute.CHANNEL);

              // We need to populate the deprecated STACK attribute so that we have enough context
              // for transforming the add operation
              PathAddress subsystemAddress =
                  PathAddress.pathAddress(JGroupsSubsystemResourceDefinition.PATH);
              PathAddress channelAddress =
                  subsystemAddress.append(ChannelResourceDefinition.pathElement(value));
              ModelNode channelOperation = operations.get(channelAddress);
              if (channelOperation != null) {
                String stack;
                if (channelOperation.hasDefined(
                    ChannelResourceDefinition.Attribute.STACK.getDefinition().getName())) {
                  stack =
                      channelOperation
                          .get(ChannelResourceDefinition.Attribute.STACK.getDefinition().getName())
                          .asString();
                } else {
                  stack =
                      operations
                          .get(subsystemAddress)
                          .get(
                              JGroupsSubsystemResourceDefinition.Attribute.DEFAULT_STACK
                                  .getDefinition()
                                  .getName())
                          .asString();
                }
                setAttribute(
                    reader,
                    stack,
                    operation,
                    RemoteSiteResourceDefinition.DeprecatedAttribute.STACK);
              }
              break;
            }
          }
        default:
          {
            throw ParseUtils.unexpectedAttribute(reader, i);
          }
      }
    }

    if (this.schema.since(JGroupsSchema.VERSION_3_0)) {
      if (!operation.hasDefined(
          RemoteSiteResourceDefinition.Attribute.CHANNEL.getDefinition().getName())) {
        throw ParseUtils.missingRequired(reader, EnumSet.of(XMLAttribute.CHANNEL));
      }
    } else {
      if (!operation.hasDefined(
          RemoteSiteResourceDefinition.DeprecatedAttribute.STACK.getDefinition().getName())) {
        throw ParseUtils.missingRequired(reader, EnumSet.of(XMLAttribute.STACK));
      }
      String channel = (cluster != null) ? cluster : site;
      setAttribute(reader, channel, operation, RemoteSiteResourceDefinition.Attribute.CHANNEL);

      // We need to create a corresponding channel add operation
      PathAddress subsystemAddress =
          PathAddress.pathAddress(JGroupsSubsystemResourceDefinition.PATH);
      PathAddress channelAddress =
          subsystemAddress.append(ChannelResourceDefinition.pathElement(channel));
      ModelNode channelOperation = Util.createAddOperation(channelAddress);
      String stack =
          operation
              .get(RemoteSiteResourceDefinition.DeprecatedAttribute.STACK.getDefinition().getName())
              .asString();
      setAttribute(reader, stack, channelOperation, ChannelResourceDefinition.Attribute.STACK);
      operations.put(channelAddress, channelOperation);
    }

    ParseUtils.requireNoContent(reader);
  }
  @SuppressWarnings("deprecation")
  @Override
  public void readElement(XMLExtendedStreamReader reader, List<ModelNode> result)
      throws XMLStreamException {

    Map<PathAddress, ModelNode> operations = new LinkedHashMap<>();

    PathAddress address = PathAddress.pathAddress(JGroupsSubsystemResourceDefinition.PATH);
    ModelNode operation = Util.createAddOperation(address);
    operations.put(address, operation);

    if (!this.schema.since(JGroupsSchema.VERSION_3_0)) {
      String defaultStack = require(reader, XMLAttribute.DEFAULT_STACK);
      setAttribute(
          reader,
          defaultStack,
          operation,
          JGroupsSubsystemResourceDefinition.Attribute.DEFAULT_STACK);
    }

    while (reader.hasNext() && (reader.nextTag() != XMLStreamConstants.END_ELEMENT)) {
      XMLElement element = XMLElement.forName(reader.getLocalName());
      switch (element) {
        case CHANNELS:
          {
            if (this.schema.since(JGroupsSchema.VERSION_3_0)) {
              this.parseChannels(reader, address, operations);
              break;
            }
          }
        case STACKS:
          {
            if (this.schema.since(JGroupsSchema.VERSION_3_0)) {
              this.parseStacks(reader, address, operations);
              break;
            }
          }
        case STACK:
          {
            if (!this.schema.since(JGroupsSchema.VERSION_3_0)) {
              this.parseStack(reader, address, operations);
              break;
            }
          }
        default:
          {
            throw ParseUtils.unexpectedElement(reader);
          }
      }
    }

    // Version prior to 4_0 schema did not require stack being defined,
    // thus iterate over channel add operations and set the stack explicitly.
    if (!this.schema.since(JGroupsSchema.VERSION_4_0)) {
      ModelNode defaultStack =
          operation.get(
              JGroupsSubsystemResourceDefinition.Attribute.DEFAULT_STACK.getDefinition().getName());

      for (Map.Entry<PathAddress, ModelNode> entry : operations.entrySet()) {
        PathAddress opAddr = entry.getKey();
        if (opAddr
            .getLastElement()
            .getKey()
            .equals(ChannelResourceDefinition.WILDCARD_PATH.getKey())) {
          ModelNode op = entry.getValue();
          if (!op.hasDefined(ChannelResourceDefinition.Attribute.STACK.getDefinition().getName())) {
            op.get(ChannelResourceDefinition.Attribute.STACK.getDefinition().getName())
                .set(defaultStack);
          }
        }
      }
    }

    result.addAll(operations.values());
  }