/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.aries.blueprint.parser;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.Validator;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.aries.blueprint.ComponentDefinitionRegistry;
import org.apache.aries.blueprint.NamespaceHandler;
import org.apache.aries.blueprint.ParserContext;
import org.apache.aries.blueprint.reflect.BeanArgumentImpl;
import org.apache.aries.blueprint.reflect.BeanMetadataImpl;
import org.apache.aries.blueprint.reflect.BeanPropertyImpl;
import org.apache.aries.blueprint.reflect.CollectionMetadataImpl;
import org.apache.aries.blueprint.reflect.IdRefMetadataImpl;
import org.apache.aries.blueprint.reflect.MapEntryImpl;
import org.apache.aries.blueprint.reflect.MapMetadataImpl;
import org.apache.aries.blueprint.reflect.MetadataUtil;
import org.apache.aries.blueprint.reflect.PropsMetadataImpl;
import org.apache.aries.blueprint.reflect.RefMetadataImpl;
import org.apache.aries.blueprint.reflect.ReferenceListMetadataImpl;
import org.apache.aries.blueprint.reflect.ReferenceListenerImpl;
import org.apache.aries.blueprint.reflect.ReferenceMetadataImpl;
import org.apache.aries.blueprint.reflect.RegistrationListenerImpl;
import org.apache.aries.blueprint.reflect.ServiceMetadataImpl;
import org.apache.aries.blueprint.reflect.ServiceReferenceMetadataImpl;
import org.apache.aries.blueprint.reflect.ValueMetadataImpl;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
import org.osgi.service.blueprint.reflect.BeanArgument;
import org.osgi.service.blueprint.reflect.BeanMetadata;
import org.osgi.service.blueprint.reflect.BeanProperty;
import org.osgi.service.blueprint.reflect.CollectionMetadata;
import org.osgi.service.blueprint.reflect.ComponentMetadata;
import org.osgi.service.blueprint.reflect.IdRefMetadata;
import org.osgi.service.blueprint.reflect.MapEntry;
import org.osgi.service.blueprint.reflect.MapMetadata;
import org.osgi.service.blueprint.reflect.Metadata;
import org.osgi.service.blueprint.reflect.NonNullMetadata;
import org.osgi.service.blueprint.reflect.NullMetadata;
import org.osgi.service.blueprint.reflect.PropsMetadata;
import org.osgi.service.blueprint.reflect.RefMetadata;
import org.osgi.service.blueprint.reflect.ReferenceListMetadata;
import org.osgi.service.blueprint.reflect.ReferenceListener;
import org.osgi.service.blueprint.reflect.ReferenceMetadata;
import org.osgi.service.blueprint.reflect.RegistrationListener;
import org.osgi.service.blueprint.reflect.ServiceMetadata;
import org.osgi.service.blueprint.reflect.ServiceReferenceMetadata;
import org.osgi.service.blueprint.reflect.Target;
import org.osgi.service.blueprint.reflect.ValueMetadata;
import org.w3c.dom.Attr;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;

/**
 * TODO: javadoc
 *
 * @version $Rev: 1135256 $, $Date: 2011-06-13 21:09:27 +0100 (Mon, 13 Jun 2011) $
 */
public class Parser {

    public static final String BLUEPRINT_NAMESPACE = "http://www.osgi.org/xmlns/blueprint/v1.0.0";

    public static final String BLUEPRINT_ELEMENT = "blueprint";
    public static final String DESCRIPTION_ELEMENT = "description";
    public static final String TYPE_CONVERTERS_ELEMENT = "type-converters";
    public static final String BEAN_ELEMENT = "bean";
    public static final String ARGUMENT_ELEMENT = "argument";
    public static final String REF_ELEMENT = "ref";
    public static final String IDREF_ELEMENT = "idref";
    public static final String LIST_ELEMENT = "list";
    public static final String SET_ELEMENT = "set";
    public static final String MAP_ELEMENT = "map";
    public static final String ARRAY_ELEMENT = "array";
    public static final String PROPS_ELEMENT = "props";
    public static final String PROP_ELEMENT = "prop";
    public static final String PROPERTY_ELEMENT = "property";
    public static final String NULL_ELEMENT = "null";
    public static final String VALUE_ELEMENT = "value";
    public static final String SERVICE_ELEMENT = "service";
    public static final String REFERENCE_ELEMENT = "reference";
    public static final String REFERENCE_LIST_ELEMENT = "reference-list";
    public static final String INTERFACES_ELEMENT = "interfaces";
    public static final String REFERENCE_LISTENER_ELEMENT = "reference-listener";
    public static final String SERVICE_PROPERTIES_ELEMENT = "service-properties";
    public static final String REGISTRATION_LISTENER_ELEMENT = "registration-listener";
    public static final String ENTRY_ELEMENT = "entry";
    public static final String KEY_ELEMENT = "key";
    public static final String DEFAULT_ACTIVATION_ATTRIBUTE = "default-activation";
    public static final String DEFAULT_TIMEOUT_ATTRIBUTE = "default-timeout";
    public static final String DEFAULT_AVAILABILITY_ATTRIBUTE = "default-availability";
    public static final String NAME_ATTRIBUTE = "name";
    public static final String ID_ATTRIBUTE = "id";
    public static final String CLASS_ATTRIBUTE = "class";
    public static final String INDEX_ATTRIBUTE = "index";
    public static final String TYPE_ATTRIBUTE = "type";
    public static final String VALUE_ATTRIBUTE = "value";
    public static final String VALUE_REF_ATTRIBUTE = "value-ref";
    public static final String KEY_ATTRIBUTE = "key";
    public static final String KEY_REF_ATTRIBUTE = "key-ref";
    public static final String REF_ATTRIBUTE = "ref";
    public static final String COMPONENT_ID_ATTRIBUTE = "component-id";
    public static final String INTERFACE_ATTRIBUTE = "interface";
    public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";
    public static final String AUTO_EXPORT_ATTRIBUTE = "auto-export";
    public static final String RANKING_ATTRIBUTE = "ranking";
    public static final String TIMEOUT_ATTRIBUTE = "timeout";
    public static final String FILTER_ATTRIBUTE = "filter";
    public static final String COMPONENT_NAME_ATTRIBUTE = "component-name";
    public static final String AVAILABILITY_ATTRIBUTE = "availability";
    public static final String REGISTRATION_METHOD_ATTRIBUTE = "registration-method";
    public static final String UNREGISTRATION_METHOD_ATTRIBUTE = "unregistration-method";
    public static final String BIND_METHOD_ATTRIBUTE = "bind-method";
    public static final String UNBIND_METHOD_ATTRIBUTE = "unbind-method";
    public static final String KEY_TYPE_ATTRIBUTE = "key-type";
    public static final String VALUE_TYPE_ATTRIBUTE = "value-type";
    public static final String MEMBER_TYPE_ATTRIBUTE = "member-type";
    public static final String SCOPE_ATTRIBUTE = "scope";
    public static final String INIT_METHOD_ATTRIBUTE = "init-method";
    public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method";
    public static final String ACTIVATION_ATTRIBUTE = "activation";
    public static final String FACTORY_REF_ATTRIBUTE = "factory-ref";
    public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method";

    public static final String AUTO_EXPORT_DISABLED = "disabled";
    public static final String AUTO_EXPORT_INTERFACES = "interfaces";
    public static final String AUTO_EXPORT_CLASS_HIERARCHY = "class-hierarchy";
    public static final String AUTO_EXPORT_ALL = "all-classes";
    public static final String AUTO_EXPORT_DEFAULT = AUTO_EXPORT_DISABLED;
    public static final String RANKING_DEFAULT = "0";
    public static final String AVAILABILITY_MANDATORY = "mandatory";
    public static final String AVAILABILITY_OPTIONAL = "optional";
    public static final String AVAILABILITY_DEFAULT = AVAILABILITY_MANDATORY;
    public static final String TIMEOUT_DEFAULT = "300000";
    public static final String USE_SERVICE_OBJECT = "service-object";
    public static final String USE_SERVICE_REFERENCE = "service-reference";
    public static final String ACTIVATION_EAGER = "eager";
    public static final String ACTIVATION_LAZY = "lazy";
    public static final String ACTIVATION_DEFAULT = ACTIVATION_EAGER;
    
    private static DocumentBuilderFactory documentBuilderFactory;
    private static final NamespaceHandler missingNamespace = new NamespaceHandler() {
        @Override
        public Metadata parse(Element element, ParserContext context) {
            return null;
        }
        @Override
        public URL getSchemaLocation(String namespace) {
            return null;
        }
        @Override
        public Set<Class> getManagedClasses() {
            return null;
        }
        @Override
        public ComponentMetadata decorate(Node node, ComponentMetadata component,
                ParserContext context) {
            return component;
        }
    };

    private final List<Document> documents = new ArrayList<Document>();
    private ComponentDefinitionRegistry registry;
    private NamespaceHandlerSet handlers;
    private final String idPrefix;
    private final boolean ignoreUnknownNamespaces;
    private final Set<String> ids = new HashSet<String>();
    private int idCounter;
    private String defaultTimeout;
    private String defaultAvailability;
    private String defaultActivation;
    private Set<URI> namespaces;
    private Map<String, String> locations;

    public Parser() {
      this(null);
    }

    public Parser(String idPrefix) {
      this(idPrefix, false);
    }

    public Parser(String idPrefix, boolean ignoreUnknownNamespaces) {
      this.idPrefix = idPrefix == null ? "component-" : idPrefix;
      this.ignoreUnknownNamespaces = ignoreUnknownNamespaces;
    }

    /**
     * Parse an input stream for blueprint xml. 
     * @param inputStream The data to parse. The caller is responsible for closing the stream afterwards. 
     * @throws Exception on parse error
     */
    public void parse(InputStream inputStream) throws Exception { 
      parse(null, inputStream);
    }

    public void parse(String location, InputStream inputStream) throws Exception {
        InputSource inputSource = new InputSource(inputStream);
        inputSource.setSystemId(location);
        DocumentBuilder builder = getDocumentBuilderFactory().newDocumentBuilder();
        Document doc = builder.parse(inputSource);
        documents.add(doc);
    }

    /**
     * Parse blueprint xml referred to by a list of URLs
     * @param urls URLs to blueprint xml to parse
     * @throws Exception on parse error
     */
    public void parse(List<URL> urls) throws Exception {
        // Create document builder factory
        // Load documents
        for (URL url : urls) {
            InputStream inputStream = url.openStream();
            try {
                parse (url.toString(), inputStream);
            } finally {
                inputStream.close();
            }
        }
    }

    public Set<URI> getNamespaces() {
        if (this.namespaces == null) {
            Set<URI> namespaces = new LinkedHashSet<URI>();
            Map<String, String> locations = new HashMap<String, String>();
            for (Document doc : documents) {
                findNamespaces(namespaces, locations, doc);
            }
            this.namespaces = namespaces;
            this.locations = locations;
        }
        return this.namespaces;
    }

    public Map<String, String> getSchemaLocations() {
        getNamespaces();
        return locations;
    }

    private void findNamespaces(Set<URI> namespaces, Map<String, String> locations, Node node) {
        if (node instanceof Element || node instanceof Attr) {
            String ns = node.getNamespaceURI();
            if ("http://www.w3.org/2001/XMLSchema-instance".equals(ns)
                    && node instanceof Attr
                    && "schemaLocation".equals(node.getLocalName())) {
                String val = ((Attr) node).getValue();
                List<String> locs = new ArrayList<String>(Arrays.asList(val.split("\\s+")));
                locs.remove("");
                for (int i = 0; i < locs.size() / 2; i++) {
                    locations.put(locs.get(i * 2), locs.get(i * 2 + 1));
                }
            } else if (ns != null && !isBlueprintNamespace(ns) && !isIgnorableAttributeNamespace(ns)) {
                namespaces.add(URI.create(ns));
            } else if (ns == null && //attributes from blueprint are unqualified as per schema.
                       node instanceof Attr &&
                       SCOPE_ATTRIBUTE.equals(node.getNodeName()) &&
                       ((Attr)node).getOwnerElement() != null && //should never occur from parsed doc.
                       BLUEPRINT_NAMESPACE.equals(((Attr)node).getOwnerElement().getNamespaceURI()) &&
                       BEAN_ELEMENT.equals(((Attr)node).getOwnerElement().getLocalName()) ){
                //Scope attribute is special case, as may contain namespace usage within its value.
                
                URI scopeNS = getNamespaceForAttributeValue(node);
                if(scopeNS!=null){
                    namespaces.add(scopeNS);
                }
            }
        }
        NamedNodeMap nnm = node.getAttributes();
        if(nnm!=null){
            for(int i = 0; i< nnm.getLength() ; i++){
                findNamespaces(namespaces, locations, nnm.item(i));
            }
        }
        NodeList nl = node.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            findNamespaces(namespaces, locations, nl.item(i));
        }
    }

    public void populate(NamespaceHandlerSet handlers,
                         ComponentDefinitionRegistry registry) {
        this.handlers = handlers;
        this.registry = registry;
        if (this.documents == null) {
            throw new IllegalStateException("Documents should be parsed before populating the registry");
        }
        // Parse components
        for (Document doc : this.documents) {
            loadComponents(doc);
        }
    }

    public void validate(Schema schema) {
        validate(schema, null);
    }

    public void validate(Schema schema, ErrorHandler errorHandler) {
        try {
            Validator validator = schema.newValidator();
            if (errorHandler != null) {
                validator.setErrorHandler(errorHandler);
            }
            for (Document doc : this.documents) {
                validator.validate(new DOMSource(doc));
            }
        } catch (Exception e) {
            throw new ComponentDefinitionException("Unable to validate xml", e);
        }
    }

    public void validatePsvi(Schema schema) {
        try {
            // In order to support validation with the built-in xml parser
            // from the JDK, we can't use Validator.validate(source, result)
            // as it fails with an exception, see
            //   https://issues.apache.org/jira/browse/XERCESJ-1212
            // This was fixed in xerces 2.9.0 years ago but still is not
            // included in my JDK.
            List<String> locations = new ArrayList<String>();
            for (Document doc : documents) {
                locations.add(doc.getDocumentURI());
            }
            List<Document> validated = new ArrayList<Document>();
            for (String location : locations) {
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                factory.setNamespaceAware(true);
                factory.setSchema(schema);
                DocumentBuilder builder = factory.newDocumentBuilder();
                InputSource inputSource = new InputSource(location);
                Document doc = builder.parse(inputSource);
                validated.add(doc);
            }
            this.documents.clear();
            this.documents.addAll(validated);
        } catch (Exception e) {
            throw new ComponentDefinitionException("Unable to validate xml", e);
        }
    }

    private void loadComponents(Document doc) {
        defaultTimeout = TIMEOUT_DEFAULT;
        defaultAvailability = AVAILABILITY_DEFAULT;
        defaultActivation = ACTIVATION_DEFAULT;
        Element root = doc.getDocumentElement();
        if (!isBlueprintNamespace(root.getNamespaceURI()) ||
                !nodeNameEquals(root, BLUEPRINT_ELEMENT)) {
            throw new ComponentDefinitionException("Root element must be {" + BLUEPRINT_NAMESPACE + "}" + BLUEPRINT_ELEMENT + " element");
        }
        // Parse global attributes
        if (root.hasAttribute(DEFAULT_ACTIVATION_ATTRIBUTE)) {
            defaultActivation = root.getAttribute(DEFAULT_ACTIVATION_ATTRIBUTE);
        }
        if (root.hasAttribute(DEFAULT_TIMEOUT_ATTRIBUTE)) {
            defaultTimeout = root.getAttribute(DEFAULT_TIMEOUT_ATTRIBUTE);
        }
        if (root.hasAttribute(DEFAULT_AVAILABILITY_ATTRIBUTE)) {
            defaultAvailability = root.getAttribute(DEFAULT_AVAILABILITY_ATTRIBUTE);
        }
        
        // Parse custom attributes
        handleCustomAttributes(root.getAttributes(), null);

        // Parse elements
        // Break into 2 loops to ensure we scan the blueprint elements before
        // This is needed so that when we process the custom element, we know
        // the component definition registry has populated all blueprint components.
        NodeList nl = root.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element element = (Element) node;
                String namespaceUri = element.getNamespaceURI();
                if (isBlueprintNamespace(namespaceUri)) {
                    parseBlueprintElement(element);
                } 
            }
        }
        
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element element = (Element) node;
                String namespaceUri = element.getNamespaceURI();
                if (!isBlueprintNamespace(namespaceUri)) {
                    Metadata component = parseCustomElement(element, null);
                    if (component != null) {
                        if (!(component instanceof ComponentMetadata)) {
                            throw new ComponentDefinitionException("Expected a ComponentMetadata to be returned when parsing element " + element.getNodeName());
                        }
                        registry.registerComponentDefinition((ComponentMetadata) component);
                    }
                } 
            }
        }
    }

    public <T> T parseElement(Class<T> type, ComponentMetadata enclosingComponent, Element element) {
        if (BeanArgument.class.isAssignableFrom(type)) {
            return type.cast(parseBeanArgument(enclosingComponent, element));
        } else if (BeanProperty.class.isAssignableFrom(type)) {
            return type.cast(parseBeanProperty(enclosingComponent, element));
        } else if (MapEntry.class.isAssignableFrom(type)) {
            return type.cast(parseMapEntry(element, enclosingComponent, null, null));
        } else if (MapMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseMap(element, enclosingComponent));
        } else if (BeanMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseBeanMetadata(element, enclosingComponent == null));
        } else if (NullMetadata.class.isAssignableFrom(type)) {
            return type.cast(NullMetadata.NULL);
        } else if (CollectionMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseCollection(Collection.class, element, enclosingComponent));
        } else if (PropsMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseProps(element));
        } else if (ReferenceMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseReference(element, enclosingComponent == null));
        } else if (ReferenceListMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseRefList(element, enclosingComponent == null));
        } else if (ServiceMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseService(element, enclosingComponent == null));
        } else if (IdRefMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseIdRef(element));
        } else if (RefMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseRef(element));
        } else if (ValueMetadata.class.isAssignableFrom(type)) {
            return type.cast(parseValue(element, null));
        } else if (ReferenceListener.class.isAssignableFrom(type)) {
            return type.cast(parseServiceListener(element, enclosingComponent));
        } else if (Metadata.class.isAssignableFrom(type)) {
            return type.cast(parseValueGroup(element, enclosingComponent, null, true));
        } else {
            throw new ComponentDefinitionException("Unknown type to parse element: " + type.getName());
        }
    }

    private void parseBlueprintElement(Element element) {
        if (nodeNameEquals(element, DESCRIPTION_ELEMENT)) {
            // Ignore description
        } else if (nodeNameEquals(element, TYPE_CONVERTERS_ELEMENT)) {
            parseTypeConverters(element);
        } else if (nodeNameEquals(element, BEAN_ELEMENT)) {
            ComponentMetadata component = parseBeanMetadata(element, true);
            registry.registerComponentDefinition(component);
        } else if (nodeNameEquals(element, SERVICE_ELEMENT)) {
            ComponentMetadata service = parseService(element, true);
            registry.registerComponentDefinition(service);
        } else if (nodeNameEquals(element, REFERENCE_ELEMENT)) {
            ComponentMetadata reference = parseReference(element, true);
            registry.registerComponentDefinition(reference);
        } else if (nodeNameEquals(element, REFERENCE_LIST_ELEMENT) ) {
            ComponentMetadata references = parseRefList(element, true);
            registry.registerComponentDefinition(references);
        } else {
            throw new ComponentDefinitionException("Unknown element " + element.getNodeName() + " in namespace " + BLUEPRINT_NAMESPACE);
        }
    }

    private void parseTypeConverters(Element element) {
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                Object target = null;
                if (isBlueprintNamespace(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, BEAN_ELEMENT)) {
                        target = parseBeanMetadata(e, true);
                    } else if (nodeNameEquals(e, REF_ELEMENT)) {
                        String componentName = e.getAttribute(COMPONENT_ID_ATTRIBUTE);
                        target = new RefMetadataImpl(componentName);
                    } else if (nodeNameEquals(e, REFERENCE_ELEMENT)) {
                        target = parseReference(e, true);
                    }
                } else {
                    target = parseCustomElement(e, null);
                }
                if (!(target instanceof Target)) {
                    throw new ComponentDefinitionException("Metadata parsed for element " + e.getNodeName() + " can not be used as a type converter");
                }
                registry.registerTypeConverter((Target) target);
            }
        }
    }
    
    /**
     * Takes an Attribute Node containing a namespace prefix qualified attribute value, and resolves the namespace using the DOM Node.<br> 
     *  
     * @param attrNode The DOM Node with the qualified attribute value.
     * @return The URI if one is resolvable, or null if the attr is null, or not namespace prefixed. (or not a DOM Attribute Node)
     * @throws ComponentDefinitionException if the namespace prefix in the attribute value cannot be resolved.
     */
    private URI getNamespaceForAttributeValue(Node attrNode) throws ComponentDefinitionException {
        URI uri = null;
        if(attrNode!=null && (attrNode instanceof Attr)){
            Attr attr = (Attr)attrNode;
            String attrValue = attr.getValue();
            if(attrValue!=null && attrValue.indexOf(":")!=-1){
                String parts[] = attrValue.split(":");
                String uriStr = attr.getOwnerElement().lookupNamespaceURI(parts[0]);
                if(uriStr!=null){
                    uri = URI.create(uriStr);
                }else{
                    throw new ComponentDefinitionException("Unsupported attribute namespace prefix "+parts[0]+" "+attr);
                }
            }
        }
        return uri;
    }
    
    /**
     * Takes an Attribute Node for the scope, and returns the value.<br> 
     *  
     * @param attrNode The DOM Node with the attribute value.
     * @return The scope as a stringified value. It should be either the value <code>prototype</code>,
     * <code>singleton</code>, or a namespace qualified value, e.g. {http://foo}bar
     * @throws ComponentDefinitionException if the namespace prefix in the attribute value cannot be resolved.
     */
    private String getScope(Node attrNode) throws ComponentDefinitionException {
        String scope = null;
        if(attrNode!=null && (attrNode instanceof Attr)){
            Attr attr = (Attr)attrNode;
            String attrValue = attr.getValue();
            if(attrValue!=null && attrValue.indexOf(":")!=-1){
                String[] parts = attrValue.split(":");
                String prefix = parts[0];
                String localName = parts[1];
                String namespaceURI = attr.getOwnerElement().lookupNamespaceURI(prefix);
                if(namespaceURI!=null){
                    scope = new QName(namespaceURI, localName).toString();
                }else{
                    throw new ComponentDefinitionException("Unable to determine namespace binding for prefix, " + prefix);
                }
            }
            else {
                scope = attrValue;
            }
        }
        return scope;
    }
    
    /**
     * Tests if a scope attribute value is a custom scope, and if so invokes
     * the appropriate namespace handler, passing the blueprint scope node. 
     * <p> 
     * Currently this tests for custom scope by looking for the presence of
     * a ':' char within the scope attribute value. This is valid as long as
     * the blueprint schema continues to restrict that custom scopes should
     * require that characters presence.
     * <p>
     *  
     * @param scope Value of scope attribute
     * @param bean DOM element for bean associated to this scope 
     * @return Metadata as processed by NS Handler.
     * @throws ComponentDefinitionException if an undeclared prefix is used, 
     *           if a namespace handler is unavailable for a resolved prefix, 
     *           or if the resolved prefix results as the blueprint namespace.
     */
    private ComponentMetadata handleCustomScope(Node scope, Element bean, ComponentMetadata metadata){
        URI scopeNS = getNamespaceForAttributeValue(scope);
        if(scopeNS!=null && !BLUEPRINT_NAMESPACE.equals(scopeNS.toString())){
            NamespaceHandler nsHandler = getNamespaceHandler(scopeNS);
            ParserContextImpl context = new ParserContextImpl(this, registry, metadata, scope);
            metadata = nsHandler.decorate(scope, metadata, context);
        }else if(scopeNS!=null){
            throw new ComponentDefinitionException("Custom scopes cannot use the blueprint namespace "+scope);
        }
        return metadata;
    }

    private ComponentMetadata parseBeanMetadata(Element element, boolean topElement) {
        BeanMetadataImpl metadata = new BeanMetadataImpl();
        if (topElement) {
            metadata.setId(getId(element));
            if (element.hasAttribute(SCOPE_ATTRIBUTE)) {
                metadata.setScope(getScope(element.getAttributeNode(SCOPE_ATTRIBUTE)));
                if (!metadata.getScope().equals(BeanMetadata.SCOPE_SINGLETON)) {
                    if (element.hasAttribute(ACTIVATION_ATTRIBUTE)) {
                        if (element.getAttribute(ACTIVATION_ATTRIBUTE).equals(ACTIVATION_EAGER)) {
                            throw new ComponentDefinitionException("A <bean> with a prototype or custom scope can not have an eager activation");
                        }
                    }
                    metadata.setActivation(ComponentMetadata.ACTIVATION_LAZY);
                } else {
                    metadata.setActivation(parseActivation(element));
                }
            } else {
                metadata.setActivation(parseActivation(element));
            }
        } else {
            metadata.setActivation(ComponentMetadata.ACTIVATION_LAZY);
        }
        if (element.hasAttribute(CLASS_ATTRIBUTE)) {
            metadata.setClassName(element.getAttribute(CLASS_ATTRIBUTE));
        }
        if (element.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
            metadata.setDependsOn(parseList(element.getAttribute(DEPENDS_ON_ATTRIBUTE)));
        }
        if (element.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
            metadata.setInitMethod(element.getAttribute(INIT_METHOD_ATTRIBUTE));
        }
        if (element.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
            metadata.setDestroyMethod(element.getAttribute(DESTROY_METHOD_ATTRIBUTE));
        }
        if (element.hasAttribute(FACTORY_REF_ATTRIBUTE)) {
            metadata.setFactoryComponent(new RefMetadataImpl(element.getAttribute(FACTORY_REF_ATTRIBUTE)));
        }
        if (element.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
            String factoryMethod = element.getAttribute(FACTORY_METHOD_ATTRIBUTE);
            metadata.setFactoryMethod(factoryMethod);
        }

        // Do some validation
        if (metadata.getClassName() == null && metadata.getFactoryComponent() == null) {
            throw new ComponentDefinitionException("Bean class or factory-ref must be specified");
        }
        if (metadata.getFactoryComponent() != null && metadata.getFactoryMethod() == null) {
            throw new ComponentDefinitionException("factory-method is required when factory-component is set");
        }
        if (MetadataUtil.isPrototypeScope(metadata) && metadata.getDestroyMethod() != null) {
            throw new ComponentDefinitionException("destroy-method must not be set for a <bean> with a prototype scope");
        }

        // Parse elements
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (isBlueprintNamespace(node.getNamespaceURI())) {                
                    if (nodeNameEquals(node, ARGUMENT_ELEMENT)) {
                        metadata.addArgument(parseBeanArgument(metadata, e));
                    } else if (nodeNameEquals(node, PROPERTY_ELEMENT)) {
                        metadata.addProperty(parseBeanProperty(metadata, e));
                    }
                }
            }
        }

        MetadataUtil.validateBeanArguments(metadata.getArguments());
        
        ComponentMetadata m = metadata;
        
        // Parse custom scopes
        m = handleCustomScope(element.getAttributeNode(SCOPE_ATTRIBUTE), element, m);
        
        // Parse custom attributes
        m = handleCustomAttributes(element.getAttributes(), m);
        
        // Parse custom elements;
        m = handleCustomElements(element, m);
        
        return m;
    }

    public BeanProperty parseBeanProperty(ComponentMetadata enclosingComponent, Element element) {
        String name = element.hasAttribute(NAME_ATTRIBUTE) ? element.getAttribute(NAME_ATTRIBUTE) : null;
        Metadata value = parseArgumentOrPropertyValue(element, enclosingComponent);
        return new BeanPropertyImpl(name, value);
    }

    private BeanArgument parseBeanArgument(ComponentMetadata enclosingComponent, Element element) {
        int index = element.hasAttribute(INDEX_ATTRIBUTE) ? Integer.parseInt(element.getAttribute(INDEX_ATTRIBUTE)) : -1;
        String type = element.hasAttribute(TYPE_ATTRIBUTE) ? element.getAttribute(TYPE_ATTRIBUTE) : null;
        Metadata value = parseArgumentOrPropertyValue(element, enclosingComponent);
        return new BeanArgumentImpl(value, type, index);
    }

    private ComponentMetadata parseService(Element element, boolean topElement) {
        ServiceMetadataImpl service = new ServiceMetadataImpl();
        boolean hasInterfaceNameAttribute = false;
        if (topElement) {
            service.setId(getId(element));
            service.setActivation(parseActivation(element));
        } else {
            service.setActivation(ComponentMetadata.ACTIVATION_LAZY);
        }
        if (element.hasAttribute(INTERFACE_ATTRIBUTE)) {
            service.setInterfaceNames(Collections.singletonList(element.getAttribute(INTERFACE_ATTRIBUTE)));
            hasInterfaceNameAttribute = true;
        }
        if (element.hasAttribute(REF_ATTRIBUTE)) {
            service.setServiceComponent(new RefMetadataImpl(element.getAttribute(REF_ATTRIBUTE)));
        }
        if (element.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
            service.setDependsOn(parseList(element.getAttribute(DEPENDS_ON_ATTRIBUTE)));
        }
        String autoExport = element.hasAttribute(AUTO_EXPORT_ATTRIBUTE) ? element.getAttribute(AUTO_EXPORT_ATTRIBUTE) : AUTO_EXPORT_DEFAULT;
        if (AUTO_EXPORT_DISABLED.equals(autoExport)) {
            service.setAutoExport(ServiceMetadata.AUTO_EXPORT_DISABLED);
        } else if (AUTO_EXPORT_INTERFACES.equals(autoExport)) {
            service.setAutoExport(ServiceMetadata.AUTO_EXPORT_INTERFACES);
        } else if (AUTO_EXPORT_CLASS_HIERARCHY.equals(autoExport)) {
            service.setAutoExport(ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY);
        } else if (AUTO_EXPORT_ALL.equals(autoExport)) {
            service.setAutoExport(ServiceMetadata.AUTO_EXPORT_ALL_CLASSES);
        } else {
            throw new ComponentDefinitionException("Illegal value (" + autoExport + ") for " + AUTO_EXPORT_ATTRIBUTE + " attribute");
        }
        String ranking = element.hasAttribute(RANKING_ATTRIBUTE) ? element.getAttribute(RANKING_ATTRIBUTE) : RANKING_DEFAULT;
        try {
            service.setRanking(Integer.parseInt(ranking));
        } catch (NumberFormatException e) {
            throw new ComponentDefinitionException("Attribute " + RANKING_ATTRIBUTE + " must be a valid integer (was: " + ranking + ")");
        }
        // Parse elements
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (isBlueprintNamespace(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, INTERFACES_ELEMENT)) {
                        if (hasInterfaceNameAttribute) {
                            throw new ComponentDefinitionException("Only one of " + INTERFACE_ATTRIBUTE + " attribute or " + INTERFACES_ELEMENT + " element must be used");
                        }
                        service.setInterfaceNames(parseInterfaceNames(e));
                    } else if (nodeNameEquals(e, SERVICE_PROPERTIES_ELEMENT)) {
                        List<MapEntry> entries = parseServiceProperties(e, service).getEntries();
                        service.setServiceProperties(entries); 
                    } else if (nodeNameEquals(e, REGISTRATION_LISTENER_ELEMENT)) {
                        service.addRegistrationListener(parseRegistrationListener(e, service));
                    } else if (nodeNameEquals(e, BEAN_ELEMENT)) {
                        if (service.getServiceComponent() != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + BEAN_ELEMENT + " element, " + REFERENCE_ELEMENT + " element or " + REF_ELEMENT + " element can be set");
                        }
                        service.setServiceComponent((Target) parseBeanMetadata(e, false));
                    } else if (nodeNameEquals(e, REF_ELEMENT)) {
                        if (service.getServiceComponent() != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + BEAN_ELEMENT + " element, " + REFERENCE_ELEMENT + " element or " + REF_ELEMENT + " element can be set");
                        }
                        String component = e.getAttribute(COMPONENT_ID_ATTRIBUTE);
                        if (component == null || component.length() == 0) {
                            throw new ComponentDefinitionException("Element " + REF_ELEMENT + " must have a valid " + COMPONENT_ID_ATTRIBUTE + " attribute");
                        }
                        service.setServiceComponent(new RefMetadataImpl(component));                   
                    } else if (nodeNameEquals(e, REFERENCE_ELEMENT)) {
                        if (service.getServiceComponent() != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + BEAN_ELEMENT + " element, " + REFERENCE_ELEMENT + " element or " + REF_ELEMENT + " element can be set");
                        }
                        service.setServiceComponent((Target) parseReference(e, false));
                    }
                }
            }
        }
        // Check service
        if (service.getServiceComponent() == null) {
            throw new ComponentDefinitionException("One of " + REF_ATTRIBUTE + " attribute, " + BEAN_ELEMENT + " element, " + REFERENCE_ELEMENT + " element or " + REF_ELEMENT + " element must be set");
        }
        // Check interface
        if (service.getAutoExport() == ServiceMetadata.AUTO_EXPORT_DISABLED && service.getInterfaces().isEmpty()) {
            throw new ComponentDefinitionException(INTERFACE_ATTRIBUTE + " attribute or " + INTERFACES_ELEMENT + " element must be set when " + AUTO_EXPORT_ATTRIBUTE + " is set to " + AUTO_EXPORT_DISABLED);
        }
        // Check for non-disabled auto-exports and interfaces
        if (service.getAutoExport() != ServiceMetadata.AUTO_EXPORT_DISABLED && !service.getInterfaces().isEmpty()) {
            throw new ComponentDefinitionException(INTERFACE_ATTRIBUTE + " attribute or  " + INTERFACES_ELEMENT + " element must not be set when " + AUTO_EXPORT_ATTRIBUTE + " is set to anything else than " + AUTO_EXPORT_DISABLED);
        }
        ComponentMetadata s = service;
        
        // Parse custom attributes
        s = handleCustomAttributes(element.getAttributes(), s);

        // Parse custom elements;
        s = handleCustomElements(element, s);
        
        return s;
    }

    private CollectionMetadata parseArray(Element element, ComponentMetadata enclosingComponent) {
        return parseCollection(Object[].class, element, enclosingComponent);
    }

    private CollectionMetadata parseList(Element element, ComponentMetadata enclosingComponent) {
        return parseCollection(List.class, element, enclosingComponent);
    }

    private CollectionMetadata parseSet(Element element, ComponentMetadata enclosingComponent) {
        return parseCollection(Set.class, element, enclosingComponent);
    }

    private CollectionMetadata parseCollection(Class collectionType, Element element, ComponentMetadata enclosingComponent) {
        // Parse attributes
        String valueType = element.hasAttribute(VALUE_TYPE_ATTRIBUTE) ? element.getAttribute(VALUE_TYPE_ATTRIBUTE) : null;
        // Parse elements
        List<Metadata> list = new ArrayList<Metadata>();
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Metadata val = parseValueGroup((Element) node, enclosingComponent, null, true);
                list.add(val);
            }
        }
        return new CollectionMetadataImpl(collectionType, valueType, list);
    }

    public PropsMetadata parseProps(Element element) {
        // Parse elements
        List<MapEntry> entries = new ArrayList<MapEntry>();
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (isBlueprintNamespace(e.getNamespaceURI()) && nodeNameEquals(e, PROP_ELEMENT)) {
                    entries.add(parseProperty(e));
                }
            }
        }
        return new PropsMetadataImpl(entries);
    }

    private MapEntry parseProperty(Element element) {
        // Parse attributes
        if (!element.hasAttribute(KEY_ATTRIBUTE)) {
            throw new ComponentDefinitionException(KEY_ATTRIBUTE + " attribute is required");
        }
        String value;
        if (element.hasAttribute(VALUE_ATTRIBUTE)) {
            value = element.getAttribute(VALUE_ATTRIBUTE);
        } else {
            value = getTextValue(element);
        }
        String key = element.getAttribute(KEY_ATTRIBUTE);
        return new MapEntryImpl(new ValueMetadataImpl(key), new ValueMetadataImpl(value));
    }

    public MapMetadata parseMap(Element element, ComponentMetadata enclosingComponent) {
        // Parse attributes
        String keyType = element.hasAttribute(KEY_TYPE_ATTRIBUTE) ? element.getAttribute(KEY_TYPE_ATTRIBUTE) : null;
        String valueType = element.hasAttribute(VALUE_TYPE_ATTRIBUTE) ? element.getAttribute(VALUE_TYPE_ATTRIBUTE) : null;
        // Parse elements
        List<MapEntry> entries = new ArrayList<MapEntry>();
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (nodeNameEquals(e, ENTRY_ELEMENT)) {
                    entries.add(parseMapEntry(e, enclosingComponent, null, null));
                }
            }
        }
        return new MapMetadataImpl(keyType, valueType, entries);
    }

    private MapEntry parseMapEntry(Element element, ComponentMetadata enclosingComponent, String keyType, String valueType) {
        // Parse attributes
        String key = element.hasAttribute(KEY_ATTRIBUTE) ? element.getAttribute(KEY_ATTRIBUTE) : null;
        String keyRef = element.hasAttribute(KEY_REF_ATTRIBUTE) ? element.getAttribute(KEY_REF_ATTRIBUTE) : null;
        String value = element.hasAttribute(VALUE_ATTRIBUTE) ? element.getAttribute(VALUE_ATTRIBUTE) : null;
        String valueRef = element.hasAttribute(VALUE_REF_ATTRIBUTE) ? element.getAttribute(VALUE_REF_ATTRIBUTE) : null;
        // Parse elements
        NonNullMetadata keyValue = null;
        Metadata valValue = null;
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (nodeNameEquals(e, KEY_ELEMENT)) {
                    keyValue = parseMapKeyEntry(e, enclosingComponent, keyType);
                } else {
                    valValue = parseValueGroup(e, enclosingComponent, valueType, true);
                }
            }
        }
        // Check key
        if (keyValue != null && (key != null || keyRef != null) || (keyValue == null && key == null && keyRef == null)) {
            throw new ComponentDefinitionException("Only and only one of " + KEY_ATTRIBUTE + " attribute, " + KEY_REF_ATTRIBUTE + " attribute or " + KEY_ELEMENT + " element must be set");
        } else if (keyValue == null && key != null) {
            keyValue = new ValueMetadataImpl(key, keyType);
        } else if (keyValue == null /*&& keyRef != null*/) {
            keyValue = new RefMetadataImpl(keyRef);
        }
        // Check value
        if (valValue != null && (value != null || valueRef != null) || (valValue == null && value == null && valueRef == null)) {
            throw new ComponentDefinitionException("Only and only one of " + VALUE_ATTRIBUTE + " attribute, " + VALUE_REF_ATTRIBUTE + " attribute or sub element must be set");
        } else if (valValue == null && value != null) {
            valValue = new ValueMetadataImpl(value, valueType);
        } else if (valValue == null /*&& valueRef != null*/) {
            valValue = new RefMetadataImpl(valueRef);
        }
        return new MapEntryImpl(keyValue, valValue);
    }

    private NonNullMetadata parseMapKeyEntry(Element element, ComponentMetadata enclosingComponent, String keyType) {
        NonNullMetadata keyValue = null;
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (keyValue != null) {
                    // TODO: throw an exception
                }
                keyValue = (NonNullMetadata) parseValueGroup(e, enclosingComponent, keyType, false);
                break;
            }
        }
        if (keyValue == null) {
            // TODO: throw an exception
        }
        return keyValue;
    }
    
    public MapMetadata parseServiceProperties(Element element, ComponentMetadata enclosingComponent) {
        // TODO: need to handle this better
        MapMetadata map = parseMap(element, enclosingComponent);
        handleCustomElements(element, enclosingComponent);
        return map;
    }
    
    public RegistrationListener parseRegistrationListener(Element element, ComponentMetadata enclosingComponent) {
        RegistrationListenerImpl listener = new RegistrationListenerImpl();
        Metadata listenerComponent = null;
        // Parse attributes
        if (element.hasAttribute(REF_ATTRIBUTE)) {
            listenerComponent = new RefMetadataImpl(element.getAttribute(REF_ATTRIBUTE));
        }
        String registrationMethod = null;
        if (element.hasAttribute(REGISTRATION_METHOD_ATTRIBUTE)) {
            registrationMethod = element.getAttribute(REGISTRATION_METHOD_ATTRIBUTE);
            listener.setRegistrationMethod(registrationMethod);
        }
        String unregistrationMethod = null;
        if (element.hasAttribute(UNREGISTRATION_METHOD_ATTRIBUTE)) {
            unregistrationMethod = element.getAttribute(UNREGISTRATION_METHOD_ATTRIBUTE);
            listener.setUnregistrationMethod(unregistrationMethod);
        }
        if (registrationMethod == null && unregistrationMethod == null) {
            throw new ComponentDefinitionException("One of " + REGISTRATION_METHOD_ATTRIBUTE + " or " + UNREGISTRATION_METHOD_ATTRIBUTE + " must be set");
        }
        // Parse elements
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (isBlueprintNamespace(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, REF_ELEMENT)) {
                        if (listenerComponent != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BEAN_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                        }
                        String component = e.getAttribute(COMPONENT_ID_ATTRIBUTE);
                        if (component == null || component.length() == 0) {
                            throw new ComponentDefinitionException("Element " + REF_ELEMENT + " must have a valid " + COMPONENT_ID_ATTRIBUTE + " attribute");
                        }
                        listenerComponent = new RefMetadataImpl(component);
                    } else if (nodeNameEquals(e, BEAN_ELEMENT)) {
                        if (listenerComponent != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BEAN_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                        }
                        listenerComponent = parseBeanMetadata(e, false);
                    } else if (nodeNameEquals(e, REFERENCE_ELEMENT)) {
                        if (listenerComponent != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BEAN_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                        }
                        listenerComponent = parseReference(e, false);
                    } else if (nodeNameEquals(e, SERVICE_ELEMENT)) {
                        if (listenerComponent != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BEAN_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                        }
                        listenerComponent = parseService(e, false);
                    }
                } else {
                    if (listenerComponent != null) {
                        throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BEAN_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                    }
                    listenerComponent = parseCustomElement(e, enclosingComponent);
                }
            }
        }
        if (listenerComponent == null) {
            throw new ComponentDefinitionException("One of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BEAN_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element must be set");
        }
        listener.setListenerComponent((Target) listenerComponent);
        return listener;
    }

    private ComponentMetadata parseReference(Element element, boolean topElement) {       
        ReferenceMetadataImpl reference = new ReferenceMetadataImpl();
        if (topElement) {
            reference.setId(getId(element));
        }
        parseReference(element, reference, topElement);
        String timeout = element.hasAttribute(TIMEOUT_ATTRIBUTE) ? element.getAttribute(TIMEOUT_ATTRIBUTE) : this.defaultTimeout;
        try {
            reference.setTimeout(Long.parseLong(timeout));
        } catch (NumberFormatException e) {
            throw new ComponentDefinitionException("Attribute " + TIMEOUT_ATTRIBUTE + " must be a valid long (was: " + timeout + ")");
        }
        
        ComponentMetadata r = reference;

        // Parse custom attributes
        r = handleCustomAttributes(element.getAttributes(), r);

        // Parse custom elements;
        r = handleCustomElements(element, r);
        
        return r;
    }

    public String getDefaultTimeout() {
        return defaultTimeout;
    }

    public String getDefaultAvailability() {
        return defaultAvailability;
    }

    public String getDefaultActivation() {
        return defaultActivation;
    }

    private ComponentMetadata parseRefList(Element element, boolean topElement) {
        ReferenceListMetadataImpl references = new ReferenceListMetadataImpl();
        if (topElement) {
            references.setId(getId(element));
        }
        if (element.hasAttribute(MEMBER_TYPE_ATTRIBUTE)) {
            String memberType = element.getAttribute(MEMBER_TYPE_ATTRIBUTE);
            if (USE_SERVICE_OBJECT.equals(memberType)) {
                references.setMemberType(ReferenceListMetadata.USE_SERVICE_OBJECT);
            } else if (USE_SERVICE_REFERENCE.equals(memberType)) {
                references.setMemberType(ReferenceListMetadata.USE_SERVICE_REFERENCE);
            }
        } else {
            references.setMemberType(ReferenceListMetadata.USE_SERVICE_OBJECT);
        }
        parseReference(element, references, topElement);

        ComponentMetadata r = references;
        
        // Parse custom attributes
        r = handleCustomAttributes(element.getAttributes(), r);

        // Parse custom elements;
        r = handleCustomElements(element, r);
        
        return r;
    }

    private void parseReference(Element element, ServiceReferenceMetadataImpl reference, boolean topElement) {
        // Parse attributes
        if (topElement) {
            reference.setActivation(parseActivation(element));
        } else {
            reference.setActivation(ComponentMetadata.ACTIVATION_LAZY);
        }
        if (element.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
            reference.setDependsOn(parseList(element.getAttribute(DEPENDS_ON_ATTRIBUTE)));
        }
        if (element.hasAttribute(INTERFACE_ATTRIBUTE)) {
            reference.setInterface(element.getAttribute(INTERFACE_ATTRIBUTE));
        }
        if (element.hasAttribute(FILTER_ATTRIBUTE)) {
            reference.setFilter(element.getAttribute(FILTER_ATTRIBUTE));
        }
        if (element.hasAttribute(COMPONENT_NAME_ATTRIBUTE)) {
            reference.setComponentName(element.getAttribute(COMPONENT_NAME_ATTRIBUTE));
        }
        String availability = element.hasAttribute(AVAILABILITY_ATTRIBUTE) ? element.getAttribute(AVAILABILITY_ATTRIBUTE) : defaultAvailability;
        if (AVAILABILITY_MANDATORY.equals(availability)) {
            reference.setAvailability(ServiceReferenceMetadata.AVAILABILITY_MANDATORY);
        } else if (AVAILABILITY_OPTIONAL.equals(availability)) {
            reference.setAvailability(ServiceReferenceMetadata.AVAILABILITY_OPTIONAL);
        } else {
            throw new ComponentDefinitionException("Illegal value for " + AVAILABILITY_ATTRIBUTE + " attribute: " + availability);
        }
        // Parse elements
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (isBlueprintNamespace(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, REFERENCE_LISTENER_ELEMENT)) {
                        reference.addServiceListener(parseServiceListener(e, reference));
                    }
                }
            }
        }
    }

    private ReferenceListener parseServiceListener(Element element, ComponentMetadata enclosingComponent) {
        ReferenceListenerImpl listener = new ReferenceListenerImpl();
        Metadata listenerComponent = null;
        // Parse attributes
        if (element.hasAttribute(REF_ATTRIBUTE)) {
            listenerComponent = new RefMetadataImpl(element.getAttribute(REF_ATTRIBUTE));
        }
        String bindMethodName = null;
        String unbindMethodName = null;
        if (element.hasAttribute(BIND_METHOD_ATTRIBUTE)) {
            bindMethodName = element.getAttribute(BIND_METHOD_ATTRIBUTE);
            listener.setBindMethod(bindMethodName);
        }
        if (element.hasAttribute(UNBIND_METHOD_ATTRIBUTE)) {
            unbindMethodName = element.getAttribute(UNBIND_METHOD_ATTRIBUTE);
            listener.setUnbindMethod(unbindMethodName);
        }
        if (bindMethodName == null && unbindMethodName == null) {
            throw new ComponentDefinitionException("One of " + BIND_METHOD_ATTRIBUTE + " or " + UNBIND_METHOD_ATTRIBUTE + " must be set");
        }
        // Parse elements
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (isBlueprintNamespace(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, REF_ELEMENT)) {
                        if (listenerComponent != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BLUEPRINT_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                        }
                        String component = e.getAttribute(COMPONENT_ID_ATTRIBUTE);
                        if (component == null || component.length() == 0) {
                            throw new ComponentDefinitionException("Element " + REF_ELEMENT + " must have a valid " + COMPONENT_ID_ATTRIBUTE + " attribute");
                        }
                        listenerComponent = new RefMetadataImpl(component);
                    } else if (nodeNameEquals(e, BEAN_ELEMENT)) {
                        if (listenerComponent != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BLUEPRINT_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                        }
                        listenerComponent = parseBeanMetadata(e, false);
                    } else if (nodeNameEquals(e, REFERENCE_ELEMENT)) {
                        if (listenerComponent != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BLUEPRINT_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                        }
                        listenerComponent = parseReference(e, false);
                    } else if (nodeNameEquals(e, SERVICE_ELEMENT)) {
                        if (listenerComponent != null) {
                            throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BLUEPRINT_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                        }
                        listenerComponent = parseService(e, false);
                    }
                } else {
                    if (listenerComponent != null) {
                        throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BLUEPRINT_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element can be set");
                    }
                    listenerComponent = parseCustomElement(e, enclosingComponent);
                }
            }
        }
        if (listenerComponent == null) {
            throw new ComponentDefinitionException("One of " + REF_ATTRIBUTE + " attribute, " + REF_ELEMENT + ", " + BLUEPRINT_ELEMENT + ", " + REFERENCE_ELEMENT + ", " + SERVICE_ELEMENT + " or custom element must be set");
        }
        listener.setListenerComponent((Target) listenerComponent);
        return listener;
    }

    public List<String> parseInterfaceNames(Element element) {
        List<String> interfaceNames = new ArrayList<String>();
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (nodeNameEquals(e, VALUE_ELEMENT)) {
                    String v = getTextValue(e).trim();
                    if (interfaceNames.contains(v)) {
                        throw new ComponentDefinitionException("The element " + INTERFACES_ELEMENT + " should not contain the same interface twice");
                    }
                    interfaceNames.add(getTextValue(e));
                } else {
                    throw new ComponentDefinitionException("Unsupported element " + e.getNodeName() + " inside an " + INTERFACES_ELEMENT + " element");
                }
            }
        }
        return interfaceNames;
    }

    private Metadata parseArgumentOrPropertyValue(Element element, ComponentMetadata enclosingComponent) {
        Metadata [] values = new Metadata[3];
        
        if (element.hasAttribute(REF_ATTRIBUTE)) {
            values[0] = new RefMetadataImpl(element.getAttribute(REF_ATTRIBUTE));
        } 
        
        if (element.hasAttribute(VALUE_ATTRIBUTE)) {
            values[1] = new ValueMetadataImpl(element.getAttribute(VALUE_ATTRIBUTE));
        } 
        
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                Element e = (Element) node;
                if (isBlueprintNamespace(node.getNamespaceURI()) && nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
                    // Ignore description elements
                } else {
                    values[2] = parseValueGroup(e, enclosingComponent, null, true);                    
                    break;
                }
            }
        }
        
        Metadata value = null;
        for (Metadata v : values) {
            if (v != null) {
                if (value == null) {
                    value = v;
                } else {
                    throw new ComponentDefinitionException("Only one of " + REF_ATTRIBUTE + " attribute, " + VALUE_ATTRIBUTE + " attribute or sub element must be set");
                }
            }
        }

        if (value == null) {
            throw new ComponentDefinitionException("One of " + REF_ATTRIBUTE + " attribute, " + VALUE_ATTRIBUTE + " attribute or sub element must be set");
        }
        
        return value;
    }

    private Metadata parseValueGroup(Element element, ComponentMetadata enclosingComponent, String collectionType, boolean allowNull) {
        if (isBlueprintNamespace(element.getNamespaceURI())) {
            if (nodeNameEquals(element, BEAN_ELEMENT)) {
                return parseBeanMetadata(element, false);
            } else if (nodeNameEquals(element, REFERENCE_ELEMENT)) {
                return parseReference(element, false);
            } else if (nodeNameEquals(element, SERVICE_ELEMENT)) {
                return parseService(element, false);
            } else if (nodeNameEquals(element, REFERENCE_LIST_ELEMENT) ) {
                return parseRefList(element, false);
            } else if (nodeNameEquals(element, NULL_ELEMENT) && allowNull) {
                return NullMetadata.NULL;
            } else if (nodeNameEquals(element, VALUE_ELEMENT)) {
                return parseValue(element, collectionType);
            } else if (nodeNameEquals(element, REF_ELEMENT)) {
                return parseRef(element);
            } else if (nodeNameEquals(element, IDREF_ELEMENT)) {
                return parseIdRef(element);
            } else if (nodeNameEquals(element, LIST_ELEMENT)) {
                return parseList(element, enclosingComponent);
            } else if (nodeNameEquals(element, SET_ELEMENT)) {
                return parseSet(element, enclosingComponent);
            } else if (nodeNameEquals(element, MAP_ELEMENT)) {
                return parseMap(element, enclosingComponent);
            } else if (nodeNameEquals(element, PROPS_ELEMENT)) {
                return parseProps(element);
            } else if (nodeNameEquals(element, ARRAY_ELEMENT)) {
                return parseArray(element, enclosingComponent);
            } else {
                throw new ComponentDefinitionException("Unknown blueprint element " + element.getNodeName());
            }
        } else {
            return parseCustomElement(element, enclosingComponent);
        }
    }

    private ValueMetadata parseValue(Element element, String collectionType) {
        String type;
        if (element.hasAttribute(TYPE_ATTRIBUTE)) {
            type = element.getAttribute(TYPE_ATTRIBUTE);
        } else {
            type = collectionType;
        }
        return new ValueMetadataImpl(getTextValue(element), type);
    }

    private RefMetadata parseRef(Element element) {
        String component = element.getAttribute(COMPONENT_ID_ATTRIBUTE);
        if (component == null || component.length() == 0) {
            throw new ComponentDefinitionException("Element " + REF_ELEMENT + " must have a valid " + COMPONENT_ID_ATTRIBUTE + " attribute");
        }
        return new RefMetadataImpl(component);
    }
    private Metadata parseIdRef(Element element) {
        String component = element.getAttribute(COMPONENT_ID_ATTRIBUTE);
        if (component == null || component.length() == 0) {
            throw new ComponentDefinitionException("Element " + IDREF_ELEMENT + " must have a valid " + COMPONENT_ID_ATTRIBUTE + " attribute");
        }
        return new IdRefMetadataImpl(component);
    }

    private int parseActivation(Element element) {
        String initialization = element.hasAttribute(ACTIVATION_ATTRIBUTE) ? element.getAttribute(ACTIVATION_ATTRIBUTE) : defaultActivation;
        if (ACTIVATION_EAGER.equals(initialization)) {
            return ComponentMetadata.ACTIVATION_EAGER;
        } else if (ACTIVATION_LAZY.equals(initialization)) {
            return ComponentMetadata.ACTIVATION_LAZY;
        } else {
            throw new ComponentDefinitionException("Attribute " + ACTIVATION_ATTRIBUTE + " must be equal to " + ACTIVATION_EAGER + " or " + ACTIVATION_LAZY);
        }
    }
    
    private ComponentMetadata handleCustomAttributes(NamedNodeMap attributes, ComponentMetadata enclosingComponent) {
        if (attributes != null) {
            for (int i = 0; i < attributes.getLength(); i++) {
                Node node = attributes.item(i);
                //attr is custom if it has a namespace, and it isnt blueprint, or the xmlns ns. 
                //blueprint ns would be an error, as blueprint attrs are unqualified.
                if (node instanceof Attr && 
                    node.getNamespaceURI() != null && 
                    !isBlueprintNamespace(node.getNamespaceURI()) &&
                    !isIgnorableAttributeNamespace(node.getNamespaceURI()) ) {
                    enclosingComponent = decorateCustomNode(node, enclosingComponent);
                }
            }
        }
        return enclosingComponent;
    }
    
    private ComponentMetadata handleCustomElements(Element element, ComponentMetadata enclosingComponent) {
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                if (!isBlueprintNamespace(node.getNamespaceURI())) {
                    enclosingComponent = decorateCustomNode(node, enclosingComponent);
                }
            }
        }
        return enclosingComponent;
    }
    
    private ComponentMetadata decorateCustomNode(Node node, ComponentMetadata enclosingComponent) {
        NamespaceHandler handler = getNamespaceHandler(node);
        ParserContextImpl context = new ParserContextImpl(this, registry, enclosingComponent, node);
        return handler.decorate(node, enclosingComponent, context);
    }

    private Metadata parseCustomElement(Element element, ComponentMetadata enclosingComponent) {
        NamespaceHandler handler = getNamespaceHandler(element);
        ParserContextImpl context = new ParserContextImpl(this, registry, enclosingComponent, element);
        return handler.parse(element, context);
    }

    private NamespaceHandler getNamespaceHandler(Node node) {
        URI ns = URI.create(node.getNamespaceURI());
        return getNamespaceHandler(ns);
    }

    public NamespaceHandler getNamespaceHandler(URI uri) {
        if (handlers == null) {
            throw new ComponentDefinitionException("Unsupported node (namespace handler registry is not set): " + uri);
        }
        NamespaceHandler handler = this.handlers.getNamespaceHandler(uri);
        if (handler == null) {
            if (ignoreUnknownNamespaces) {
                return missingNamespace;
            }
            throw new ComponentDefinitionException("Unsupported node namespace: " + uri);
        }
        return handler;
    }

    public String generateId() {
        String id;
        do {
            id = "." + idPrefix + ++idCounter;
        } while (ids.contains(id));
        ids.add(id);
        return id;        
    }
    
    public String getId(Element element) {
        String id;
        if (element.hasAttribute(ID_ATTRIBUTE)) {
            id = element.getAttribute(ID_ATTRIBUTE);
            ids.add(id);
        } else {
            id = generateId();
        }
        return id;
    }

    public static boolean isBlueprintNamespace(String ns) {
        return BLUEPRINT_NAMESPACE.equals(ns);
    }

    /**
     * Test if this namespace uri does not require a Namespace Handler.<p>
     * 
     * @param ns URI to be tested.
     * @return true if the uri does not require a namespace handler.
     */
    public static boolean isIgnorableAttributeNamespace(String ns) {
        return XMLConstants.RELAXNG_NS_URI.equals(ns) ||
               XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(ns) || 
               XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(ns) ||
               XMLConstants.W3C_XPATH_DATATYPE_NS_URI.equals(ns) ||
               XMLConstants.W3C_XPATH_DATATYPE_NS_URI.equals(ns) ||
               XMLConstants.XML_DTD_NS_URI.equals(ns) ||
               XMLConstants.XML_NS_URI.equals(ns) || 
               XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(ns);
    }
    
    private static boolean nodeNameEquals(Node node, String name) {
        return (name.equals(node.getNodeName()) || name.equals(node.getLocalName()));
    }

    private static List<String> parseList(String list) {
        String[] items = list.split(" ");
        List<String> set = new ArrayList<String>();
        for (String item : items) {
            item = item.trim();
            if (item.length() > 0) {
                set.add(item);
            }
        }
        return set;                   
    }

    private static String getTextValue(Element element) {
        StringBuffer value = new StringBuffer();
        NodeList nl = element.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node item = nl.item(i);
            if ((item instanceof CharacterData && !(item instanceof Comment)) || item instanceof EntityReference) {
                value.append(item.getNodeValue());
            }
        }
        return value.toString();
    }

    private static DocumentBuilderFactory getDocumentBuilderFactory() {
        if (documentBuilderFactory == null) {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            try {
                dbf.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, true);
                dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            } catch (ParserConfigurationException ex) {
                throw new ComponentDefinitionException("Unable to create the document builder", ex);
            }
            documentBuilderFactory = dbf;
        }
        return documentBuilderFactory;
    }
}
