/*
 * 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.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);
            documentBuilderFactory = dbf;
        }
        return documentBuilderFactory;
    }
}
