private void writeTextExtraction(XMLExtendedStreamWriter writer, ModelNode repository)
      throws XMLStreamException {
    if (has(repository, ModelKeys.TEXT_EXTRACTOR)) {
      writer.writeStartElement(Element.TEXT_EXTRACTORS.getLocalName());
      if (repository.hasDefined(ModelKeys.TEXT_EXTRACTORS_THREAD_POOL_NAME)) {
        writer.writeAttribute(
            Attribute.THREAD_POOL_NAME.getLocalName(),
            repository.get(ModelKeys.TEXT_EXTRACTORS_THREAD_POOL_NAME).asString());
      }
      if (repository.hasDefined(ModelKeys.TEXT_EXTRACTORS_MAX_POOL_SIZE)) {
        writer.writeAttribute(
            Attribute.MAX_POOL_SIZE.getLocalName(),
            repository.get(ModelKeys.TEXT_EXTRACTORS_MAX_POOL_SIZE).asString());
      }
      for (Property extractor : repository.get(ModelKeys.TEXT_EXTRACTOR).asPropertyList()) {
        writer.writeStartElement(Element.TEXT_EXTRACTOR.getLocalName());
        writer.writeAttribute(Attribute.NAME.getLocalName(), extractor.getName());
        ModelNode prop = extractor.getValue();
        ModelAttributes.TEXT_EXTRACTOR_CLASSNAME.marshallAsAttribute(prop, writer);
        ModelAttributes.MODULE.marshallAsAttribute(prop, writer);

        // Write out the extra properties ...
        if (has(prop, ModelKeys.PROPERTIES)) {
          ModelNode properties = prop.get(ModelKeys.PROPERTIES);
          for (Property property : properties.asPropertyList()) {
            writer.writeAttribute(property.getName(), property.getValue().asString());
          }
        }
        writer.writeEndElement();
      }
      writer.writeEndElement();
    }
  }
  private void writeIndexProviders(XMLExtendedStreamWriter writer, ModelNode repository)
      throws XMLStreamException {
    if (has(repository, ModelKeys.INDEX_PROVIDER)) {
      writer.writeStartElement(Element.INDEX_PROVIDERS.getLocalName());
      ModelNode providerNode = repository.get(ModelKeys.INDEX_PROVIDER);
      for (Property provider : providerNode.asPropertyList()) {
        writer.writeStartElement(Element.INDEX_PROVIDER.getLocalName());
        writer.writeAttribute(Attribute.NAME.getLocalName(), provider.getName());
        ModelNode prop = provider.getValue();
        ModelAttributes.CLASSNAME.marshallAsAttribute(prop, writer);
        ModelAttributes.MODULE.marshallAsAttribute(prop, writer);
        ModelAttributes.RELATIVE_TO.marshallAsAttribute(prop, writer);
        ModelAttributes.PATH.marshallAsAttribute(prop, writer);

        // Write out the extra properties ...
        if (has(prop, ModelKeys.PROPERTIES)) {
          ModelNode properties = prop.get(ModelKeys.PROPERTIES);
          for (Property property : properties.asPropertyList()) {
            writer.writeAttribute(property.getName(), property.getValue().asString());
          }
        }
        writer.writeEndElement();
      }
      writer.writeEndElement();
    }
  }
  private void writeSequencing(XMLExtendedStreamWriter writer, ModelNode repository)
      throws XMLStreamException {
    if (has(repository, ModelKeys.SEQUENCER)) {
      writer.writeStartElement(Element.SEQUENCERS.getLocalName());
      if (repository.hasDefined(ModelKeys.SEQUENCERS_THREAD_POOL_NAME)) {
        writer.writeAttribute(
            Attribute.THREAD_POOL_NAME.getLocalName(),
            repository.get(ModelKeys.SEQUENCERS_THREAD_POOL_NAME).asString());
      }
      if (repository.hasDefined(ModelKeys.SEQUENCERS_MAX_POOL_SIZE)) {
        writer.writeAttribute(
            Attribute.MAX_POOL_SIZE.getLocalName(),
            repository.get(ModelKeys.SEQUENCERS_MAX_POOL_SIZE).asString());
      }

      ModelNode sequencerNode = repository.get(ModelKeys.SEQUENCER);

      for (Property sequencer : sequencerNode.asPropertyList()) {
        writer.writeStartElement(Element.SEQUENCER.getLocalName());
        writer.writeAttribute(Attribute.NAME.getLocalName(), sequencer.getName());
        ModelNode prop = sequencer.getValue();
        ModelAttributes.SEQUENCER_CLASSNAME.marshallAsAttribute(prop, writer);
        ModelAttributes.MODULE.marshallAsAttribute(prop, writer);

        // Write out the extra properties ...
        if (has(prop, ModelKeys.PROPERTIES)) {
          ModelNode properties = prop.get(ModelKeys.PROPERTIES);
          for (Property property : properties.asPropertyList()) {
            writer.writeAttribute(property.getName(), property.getValue().asString());
          }
        }
        if (has(prop, ModelKeys.PATH_EXPRESSIONS)) {
          List<ModelNode> pathExpressions = prop.get(ModelKeys.PATH_EXPRESSIONS).asList();
          switch (pathExpressions.size()) {
            case 0:
              break;
            case 1:
              ModelNode pathExpression = pathExpressions.iterator().next();
              writer.writeAttribute(
                  Attribute.PATH_EXPRESSION.getLocalName(), pathExpression.asString());
              break;
            default:
              for (ModelNode pathExpr : pathExpressions) {
                writer.writeStartElement(Element.PATH_EXPRESSION.getLocalName());
                writer.writeCharacters(pathExpr.asString());
                writer.writeEndElement();
              }
          }
        }
        writer.writeEndElement();
      }
      writer.writeEndElement();
    }
  }
  private void writeExternalSources(XMLExtendedStreamWriter writer, ModelNode repository)
      throws XMLStreamException {
    if (has(repository, ModelKeys.SOURCE)) {
      writer.writeStartElement(Element.EXTERNAL_SOURCES.getLocalName());
      ModelNode externalSourceNode = repository.get(ModelKeys.SOURCE);
      for (Property externalSource : externalSourceNode.asPropertyList()) {
        writer.writeStartElement(Element.SOURCE.getLocalName());
        writer.writeAttribute(Attribute.NAME.getLocalName(), externalSource.getName());

        ModelNode prop = externalSource.getValue();
        ModelAttributes.CONNECTOR_CLASSNAME.marshallAsAttribute(prop, writer);
        ModelAttributes.MODULE.marshallAsAttribute(prop, writer);
        ModelAttributes.CACHE_TTL_SECONDS.marshallAsAttribute(prop, writer);
        ModelAttributes.QUERYABLE.marshallAsAttribute(prop, writer);
        ModelAttributes.READONLY.marshallAsAttribute(prop, writer);
        ModelAttributes.EXPOSE_AS_WORKSPACE.marshallAsAttribute(prop, writer);

        // Write out the extra properties ...
        if (has(prop, ModelKeys.PROPERTIES)) {
          ModelNode properties = prop.get(ModelKeys.PROPERTIES);
          for (Property property : properties.asPropertyList()) {
            writer.writeAttribute(property.getName(), property.getValue().asString());
          }
        }

        if (has(prop, ModelKeys.PROJECTIONS)) {
          List<ModelNode> projections = prop.get(ModelKeys.PROJECTIONS).asList();
          for (ModelNode projection : projections) {
            writer.writeStartElement(Element.PROJECTION.getLocalName());
            writer.writeCharacters(projection.asString());
            writer.writeEndElement();
          }
        }
        writer.writeEndElement();
      }
      writer.writeEndElement();
    }
  }
  private void writeAuthenticators(XMLExtendedStreamWriter writer, ModelNode repository)
      throws XMLStreamException {
    if (has(repository, ModelKeys.AUTHENTICATOR)) {
      writer.writeStartElement(Element.AUTHENTICATORS.getLocalName());
      for (Property authenticator : repository.get(ModelKeys.AUTHENTICATOR).asPropertyList()) {
        writer.writeStartElement(Element.AUTHENTICATOR.getLocalName());
        writer.writeAttribute(Attribute.NAME.getLocalName(), authenticator.getName());
        ModelNode prop = authenticator.getValue();
        ModelAttributes.AUTHENTICATOR_CLASSNAME.marshallAsAttribute(prop, writer);
        ModelAttributes.MODULE.marshallAsAttribute(prop, writer);

        // Write out the extra properties ...
        if (has(prop, ModelKeys.PROPERTIES)) {
          ModelNode properties = prop.get(ModelKeys.PROPERTIES);
          for (Property property : properties.asPropertyList()) {
            writer.writeAttribute(property.getName(), property.getValue().asString());
          }
        }
        writer.writeEndElement();
      }
      writer.writeEndElement();
    }
  }
  private void writeBinaryStorageModel(
      XMLExtendedStreamWriter writer, String storageType, ModelNode storage)
      throws XMLStreamException {
    if (ModelKeys.FILE_BINARY_STORAGE.equals(storageType)) {
      // This is the default, but there is no default value for the ModelAttributes.PATH (which is
      // required),
      // which means we always have to write this out. If it is the default binary storage, then
      // there
      // won't even be a 'binary-storage=BINARIES' model node.
      writer.writeStartElement(Element.FILE_BINARY_STORAGE.getLocalName());
      ModelAttributes.MINIMUM_BINARY_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MINIMUM_STRING_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.PATH.marshallAsAttribute(storage, false, writer);
      ModelAttributes.RELATIVE_TO.marshallAsAttribute(storage, false, writer);
      ModelAttributes.STORE_NAME.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MIME_TYPE_DETECTION.marshallAsAttribute(storage, false, writer);
      writer.writeEndElement();
    } else if (ModelKeys.CACHE_BINARY_STORAGE.equals(storageType)) {
      writer.writeStartElement(Element.CACHE_BINARY_STORAGE.getLocalName());
      ModelAttributes.MINIMUM_BINARY_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MINIMUM_STRING_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.DATA_CACHE_NAME.marshallAsAttribute(storage, false, writer);
      ModelAttributes.METADATA_CACHE_NAME.marshallAsAttribute(storage, false, writer);
      ModelAttributes.CHUNK_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.CACHE_CONFIG.marshallAsAttribute(storage, false, writer);
      ModelAttributes.STORE_NAME.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MIME_TYPE_DETECTION.marshallAsAttribute(storage, false, writer);
      writer.writeEndElement();
    } else if (ModelKeys.DB_BINARY_STORAGE.equals(storageType)) {
      writer.writeStartElement(Element.DB_BINARY_STORAGE.getLocalName());
      ModelAttributes.MINIMUM_BINARY_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MINIMUM_STRING_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.DATA_SOURCE_JNDI_NAME.marshallAsAttribute(storage, false, writer);
      ModelAttributes.STORE_NAME.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MIME_TYPE_DETECTION.marshallAsAttribute(storage, false, writer);
      writer.writeEndElement();
    } else if (ModelKeys.COMPOSITE_BINARY_STORAGE.equals(storageType)) {
      writer.writeStartElement(Element.COMPOSITE_BINARY_STORAGE.getLocalName());
      ModelAttributes.MINIMUM_BINARY_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MINIMUM_STRING_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.STORE_NAME.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MIME_TYPE_DETECTION.marshallAsAttribute(storage, false, writer);

      writeNestedStoresOfType(
          storage, ModelKeys.NESTED_STORAGE_TYPE_FILE, ModelKeys.FILE_BINARY_STORAGE, writer);
      writeNestedStoresOfType(
          storage, ModelKeys.NESTED_STORAGE_TYPE_CACHE, ModelKeys.CACHE_BINARY_STORAGE, writer);
      writeNestedStoresOfType(
          storage, ModelKeys.NESTED_STORAGE_TYPE_DB, ModelKeys.DB_BINARY_STORAGE, writer);
      writeNestedStoresOfType(
          storage, ModelKeys.NESTED_STORAGE_TYPE_CUSTOM, ModelKeys.CUSTOM_BINARY_STORAGE, writer);

      writer.writeEndElement();
    } else if (ModelKeys.CUSTOM_BINARY_STORAGE.equals(storageType)) {
      writer.writeStartElement(Element.CUSTOM_BINARY_STORAGE.getLocalName());
      ModelAttributes.MINIMUM_BINARY_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MINIMUM_STRING_SIZE.marshallAsAttribute(storage, false, writer);
      ModelAttributes.STORE_NAME.marshallAsAttribute(storage, false, writer);
      ModelAttributes.MIME_TYPE_DETECTION.marshallAsAttribute(storage, false, writer);
      for (String key : storage.keys()) {
        if (key.equals(ModelKeys.CLASSNAME)) {
          ModelAttributes.CLASSNAME.marshallAsAttribute(storage, false, writer);
        } else if (key.equals(ModelKeys.MODULE)) {
          ModelAttributes.MODULE.marshallAsAttribute(storage, false, writer);
        } else {
          writer.writeAttribute(key, storage.get(key).asString());
        }
      }
      writer.writeEndElement();
    }
  }