/**
   * Generate the xml top level element and start streaming the components.
   *
   * @param components
   * @param contentHandler
   * @throws SAXException
   */
  protected static void generateXML(
      Components components, ContentHandler contentHandler, boolean isScrPrivateFile)
      throws SAXException {
    // detect namespace to use
    final String namespace;
    if (components.getSpecVersion() == Constants.VERSION_1_0) {
      namespace = NAMESPACE_URI_1_0;
    } else if (components.getSpecVersion() == Constants.VERSION_1_1) {
      namespace = NAMESPACE_URI_1_1;
    } else {
      namespace = NAMESPACE_URI_1_1_FELIX;
    }
    contentHandler.startDocument();
    contentHandler.startPrefixMapping(PREFIX, namespace);

    // wrapper element to generate well formed xml
    contentHandler.startElement(
        "",
        ComponentDescriptorIO.COMPONENTS,
        ComponentDescriptorIO.COMPONENTS,
        new AttributesImpl());
    IOUtils.newline(contentHandler);

    for (final Component component : components.getComponents()) {
      if (component.isDs()) {
        generateXML(namespace, component, contentHandler, isScrPrivateFile);
      }
    }
    // end wrapper element
    contentHandler.endElement(
        "", ComponentDescriptorIO.COMPONENTS, ComponentDescriptorIO.COMPONENTS);
    IOUtils.newline(contentHandler);
    contentHandler.endPrefixMapping(PREFIX);
    contentHandler.endDocument();
  }
  /**
   * Write the xml for a {@link Component}.
   *
   * @param component
   * @param contentHandler
   * @throws SAXException
   */
  protected static void generateXML(
      final String namespace,
      final Component component,
      final ContentHandler contentHandler,
      final boolean isScrPrivateFile)
      throws SAXException {
    final AttributesImpl ai = new AttributesImpl();
    IOUtils.addAttribute(ai, COMPONENT_ATTR_ENABLED, component.isEnabled());
    IOUtils.addAttribute(ai, COMPONENT_ATTR_IMMEDIATE, component.isImmediate());
    IOUtils.addAttribute(ai, COMPONENT_ATTR_NAME, component.getName());
    IOUtils.addAttribute(ai, COMPONENT_ATTR_FACTORY, component.getFactory());

    // attributes new in 1.1
    if (NAMESPACE_URI_1_1.equals(namespace) || NAMESPACE_URI_1_1_FELIX.equals(namespace)) {
      IOUtils.addAttribute(ai, COMPONENT_ATTR_POLICY, component.getConfigurationPolicy());
      IOUtils.addAttribute(ai, COMPONENT_ATTR_ACTIVATE, component.getActivate());
      IOUtils.addAttribute(ai, COMPONENT_ATTR_DEACTIVATE, component.getDeactivate());
      IOUtils.addAttribute(ai, COMPONENT_ATTR_MODIFIED, component.getModified());
    }

    IOUtils.indent(contentHandler, 1);
    contentHandler.startElement(
        namespace, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME, ai);
    IOUtils.newline(contentHandler);
    generateXML(component.getImplementation(), contentHandler);
    if (component.getService() != null) {
      generateXML(component.getService(), contentHandler);
    }
    if (component.getProperties() != null) {
      for (final Property property : component.getProperties()) {
        generateXML(property, contentHandler, isScrPrivateFile);
      }
    }
    if (component.getReferences() != null) {
      for (final Reference reference : component.getReferences()) {
        generateXML(namespace, reference, contentHandler, isScrPrivateFile);
      }
    }
    IOUtils.indent(contentHandler, 1);
    contentHandler.endElement(
        namespace, ComponentDescriptorIO.COMPONENT, ComponentDescriptorIO.COMPONENT_QNAME);
    IOUtils.newline(contentHandler);
  }
 /**
  * Write the xml for a {@link Service}.
  *
  * @param service
  * @param contentHandler
  * @throws SAXException
  */
 protected static void generateXML(Service service, ContentHandler contentHandler)
     throws SAXException {
   final AttributesImpl ai = new AttributesImpl();
   IOUtils.addAttribute(ai, "servicefactory", String.valueOf(service.isServicefactory()));
   IOUtils.indent(contentHandler, 2);
   contentHandler.startElement(
       INNER_NAMESPACE_URI,
       ComponentDescriptorIO.SERVICE,
       ComponentDescriptorIO.SERVICE_QNAME,
       ai);
   if (service.getInterfaces() != null && service.getInterfaces().size() > 0) {
     IOUtils.newline(contentHandler);
     for (final Interface interf : service.getInterfaces()) {
       generateXML(interf, contentHandler);
     }
     IOUtils.indent(contentHandler, 2);
   }
   contentHandler.endElement(
       INNER_NAMESPACE_URI, ComponentDescriptorIO.SERVICE, ComponentDescriptorIO.SERVICE_QNAME);
   IOUtils.newline(contentHandler);
 }
 /**
  * Write the xml for a {@link Property}.
  *
  * @param property
  * @param contentHandler
  * @throws SAXException
  */
 protected static void generateXML(
     Property property, ContentHandler contentHandler, boolean isScrPrivateFile)
     throws SAXException {
   final AttributesImpl ai = new AttributesImpl();
   IOUtils.addAttribute(ai, "name", property.getName());
   IOUtils.addAttribute(ai, "type", property.getType());
   IOUtils.addAttribute(ai, "value", property.getValue());
   // we have to write more information if this is our scr private file
   if (isScrPrivateFile) {
     IOUtils.addAttribute(ai, "private", String.valueOf(property.isPrivate()));
     if (property.getLabel() != null) {
       IOUtils.addAttribute(ai, "label", String.valueOf(property.getLabel()));
     }
     if (property.getDescription() != null) {
       IOUtils.addAttribute(ai, "description", String.valueOf(property.getDescription()));
     }
     if (property.getCardinality() != null) {
       IOUtils.addAttribute(ai, "cardinality", String.valueOf(property.getCardinality()));
     }
   }
   IOUtils.indent(contentHandler, 2);
   contentHandler.startElement(
       INNER_NAMESPACE_URI,
       ComponentDescriptorIO.PROPERTY,
       ComponentDescriptorIO.PROPERTY_QNAME,
       ai);
   if (property.getMultiValue() != null && property.getMultiValue().length > 0) {
     // generate a new line first
     IOUtils.text(contentHandler, "\n");
     for (int i = 0; i < property.getMultiValue().length; i++) {
       IOUtils.indent(contentHandler, 3);
       IOUtils.text(contentHandler, property.getMultiValue()[i]);
       IOUtils.newline(contentHandler);
     }
     IOUtils.indent(contentHandler, 2);
   }
   contentHandler.endElement(
       INNER_NAMESPACE_URI, ComponentDescriptorIO.PROPERTY, ComponentDescriptorIO.PROPERTY_QNAME);
   IOUtils.newline(contentHandler);
 }
 /**
  * Write the xml for a {@link Interface}.
  *
  * @param interf
  * @param contentHandler
  * @throws SAXException
  */
 protected static void generateXML(Interface interf, ContentHandler contentHandler)
     throws SAXException {
   final AttributesImpl ai = new AttributesImpl();
   IOUtils.addAttribute(ai, "interface", interf.getInterfacename());
   IOUtils.indent(contentHandler, 3);
   contentHandler.startElement(
       INNER_NAMESPACE_URI,
       ComponentDescriptorIO.INTERFACE,
       ComponentDescriptorIO.INTERFACE_QNAME,
       ai);
   contentHandler.endElement(
       INNER_NAMESPACE_URI,
       ComponentDescriptorIO.INTERFACE,
       ComponentDescriptorIO.INTERFACE_QNAME);
   IOUtils.newline(contentHandler);
 }
 /**
  * Write the xml for a {@link Implementation}.
  *
  * @param implementation
  * @param contentHandler
  * @throws SAXException
  */
 protected static void generateXML(Implementation implementation, ContentHandler contentHandler)
     throws SAXException {
   final AttributesImpl ai = new AttributesImpl();
   IOUtils.addAttribute(ai, "class", implementation.getClassame());
   IOUtils.indent(contentHandler, 2);
   contentHandler.startElement(
       INNER_NAMESPACE_URI,
       ComponentDescriptorIO.IMPLEMENTATION,
       ComponentDescriptorIO.IMPLEMENTATION_QNAME,
       ai);
   contentHandler.endElement(
       INNER_NAMESPACE_URI,
       ComponentDescriptorIO.IMPLEMENTATION,
       ComponentDescriptorIO.IMPLEMENTATION_QNAME);
   IOUtils.newline(contentHandler);
 }
  /**
   * Write the xml for a {@link Reference}.
   *
   * @param reference
   * @param contentHandler
   * @throws SAXException
   */
  protected static void generateXML(
      final String namespace,
      Reference reference,
      ContentHandler contentHandler,
      boolean isScrPrivateFile)
      throws SAXException {
    final AttributesImpl ai = new AttributesImpl();
    IOUtils.addAttribute(ai, "name", reference.getName());
    IOUtils.addAttribute(ai, "interface", reference.getInterfacename());
    IOUtils.addAttribute(ai, "cardinality", reference.getCardinality());
    IOUtils.addAttribute(ai, "policy", reference.getPolicy());
    IOUtils.addAttribute(ai, "target", reference.getTarget());
    IOUtils.addAttribute(ai, "bind", reference.getBind());
    IOUtils.addAttribute(ai, "unbind", reference.getUnbind());

    // attributes new in 1.1-felix (FELIX-1893)
    if (NAMESPACE_URI_1_1_FELIX.equals(namespace)) {
      IOUtils.addAttribute(ai, "updated", reference.getUpdated());
    }

    if (isScrPrivateFile) {
      IOUtils.addAttribute(ai, "checked", String.valueOf(reference.isChecked()));
      IOUtils.addAttribute(ai, "strategy", reference.getStrategy());
    }
    IOUtils.indent(contentHandler, 2);
    contentHandler.startElement(
        INNER_NAMESPACE_URI,
        ComponentDescriptorIO.REFERENCE,
        ComponentDescriptorIO.REFERENCE_QNAME,
        ai);
    contentHandler.endElement(
        INNER_NAMESPACE_URI,
        ComponentDescriptorIO.REFERENCE,
        ComponentDescriptorIO.REFERENCE_QNAME);
    IOUtils.newline(contentHandler);
  }