/**
   * 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);
  }
    public void startElement(String uri, String localName, String name, Attributes attributes)
        throws SAXException {
      // according to the spec, the elements should have the namespace,
      // except when the root element is the "component" element
      // So we check this for the first element, we receive.
      if (this.firstElement) {
        this.firstElement = false;
        if (localName.equals(COMPONENT) && "".equals(uri)) {
          this.overrideNamespace = NAMESPACE_URI_1_0;
        }
      }

      if (this.overrideNamespace != null && "".equals(uri)) {
        uri = this.overrideNamespace;
      }

      // however the spec also states that the inner elements
      // of a component are unqualified, so they don't have
      // the namespace - we allow both: with or without namespace!
      if (this.isComponent && "".equals(uri)) {
        uri = NAMESPACE_URI_1_0;
      }

      // from here on, uri has the namespace regardless of the used xml format
      if (NAMESPACE_URI_1_0.equals(uri)
          || NAMESPACE_URI_1_1.equals(uri)
          || NAMESPACE_URI_1_1_FELIX.equals(uri)) {

        if (NAMESPACE_URI_1_1.equals(uri)) {
          components.setSpecVersion(Constants.VERSION_1_1);
        } else if (NAMESPACE_URI_1_1_FELIX.equals(uri)) {
          components.setSpecVersion(Constants.VERSION_1_1_FELIX);
        }

        if (localName.equals(COMPONENT)) {
          this.isComponent = true;

          this.currentComponent = new Component();
          this.currentComponent.setName(attributes.getValue(COMPONENT_ATTR_NAME));

          // enabled attribute is optional
          if (attributes.getValue(COMPONENT_ATTR_ENABLED) != null) {
            this.currentComponent.setEnabled(
                Boolean.valueOf(attributes.getValue(COMPONENT_ATTR_ENABLED)));
          }

          // immediate attribute is optional
          if (attributes.getValue(COMPONENT_ATTR_IMMEDIATE) != null) {
            this.currentComponent.setImmediate(
                Boolean.valueOf(attributes.getValue(COMPONENT_ATTR_IMMEDIATE)));
          }

          this.currentComponent.setFactory(attributes.getValue(COMPONENT_ATTR_FACTORY));

          // check for version 1.1 attributes
          if (components.getSpecVersion() == Constants.VERSION_1_1) {
            this.currentComponent.setConfigurationPolicy(
                attributes.getValue(COMPONENT_ATTR_POLICY));
            this.currentComponent.setActivate(attributes.getValue(COMPONENT_ATTR_ACTIVATE));
            this.currentComponent.setDeactivate(attributes.getValue(COMPONENT_ATTR_DEACTIVATE));
            this.currentComponent.setModified(attributes.getValue(COMPONENT_ATTR_MODIFIED));
          }
        } else if (localName.equals(IMPLEMENTATION)) {
          // Set the implementation class name (mandatory)
          final Implementation impl = new Implementation();
          this.currentComponent.setImplementation(impl);
          impl.setClassname(attributes.getValue("class"));

        } else if (localName.equals(PROPERTY)) {

          // read the property, unless it is the service.pid
          // property which must not be inherited
          final String propName = attributes.getValue("name");
          if (!org.osgi.framework.Constants.SERVICE_PID.equals(propName)) {
            final Property prop = new Property();

            prop.setName(propName);
            prop.setType(attributes.getValue("type"));

            if (attributes.getValue("value") != null) {
              prop.setValue(attributes.getValue("value"));
              this.currentComponent.addProperty(prop);
            } else {
              // hold the property pending as we have a multi value
              this.pendingProperty = prop;
            }
            // check for abstract properties
            prop.setLabel(attributes.getValue("label"));
            prop.setDescription(attributes.getValue("description"));
            prop.setCardinality(attributes.getValue("cardinality"));
            final String pValue = attributes.getValue("private");
            if (pValue != null) {
              prop.setPrivate(Boolean.valueOf(pValue).booleanValue());
            }
          }

        } else if (localName.equals("properties")) {

          // TODO: implement the properties tag

        } else if (localName.equals(SERVICE)) {

          this.currentService = new Service();

          this.currentService.setServicefactory(attributes.getValue("servicefactory"));

          this.currentComponent.setService(this.currentService);

        } else if (localName.equals(INTERFACE)) {
          final Interface interf = new Interface();
          this.currentService.addInterface(interf);
          interf.setInterfacename(attributes.getValue("interface"));

        } else if (localName.equals(REFERENCE)) {
          final Reference ref = new Reference();

          ref.setName(attributes.getValue("name"));
          ref.setInterfacename(attributes.getValue("interface"));
          ref.setCardinality(attributes.getValue("cardinality"));
          ref.setPolicy(attributes.getValue("policy"));
          ref.setTarget(attributes.getValue("target"));
          ref.setBind(attributes.getValue("bind"));
          ref.setUnbind(attributes.getValue("unbind"));

          if (attributes.getValue("checked") != null) {
            ref.setChecked(Boolean.valueOf(attributes.getValue("checked")).booleanValue());
          }
          if (attributes.getValue("strategy") != null) {
            ref.setStrategy(attributes.getValue("strategy"));
          }

          this.currentComponent.addReference(ref);
        }
      }
    }