/**
 * 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.compendium.cm;

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.w3c.dom.CharacterData;
import org.w3c.dom.Comment;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.apache.aries.blueprint.ComponentDefinitionRegistry;
import org.apache.aries.blueprint.NamespaceHandler;
import org.apache.aries.blueprint.ParserContext;
import org.apache.aries.blueprint.container.Parser;
import org.apache.aries.blueprint.container.ParserContextImpl;
import org.apache.aries.blueprint.container.ServiceListener;
import org.apache.aries.blueprint.ext.ExtNamespaceHandler;
import org.apache.aries.blueprint.ext.PlaceholdersUtils;
import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
import org.apache.aries.blueprint.mutable.MutableCollectionMetadata;
import org.apache.aries.blueprint.mutable.MutableComponentMetadata;
import org.apache.aries.blueprint.mutable.MutableIdRefMetadata;
import org.apache.aries.blueprint.mutable.MutableMapMetadata;
import org.apache.aries.blueprint.mutable.MutableRefMetadata;
import org.apache.aries.blueprint.mutable.MutableValueMetadata;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
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.MapMetadata;
import org.osgi.service.blueprint.reflect.Metadata;
import org.osgi.service.blueprint.reflect.RefMetadata;
import org.osgi.service.blueprint.reflect.RegistrationListener;
import org.osgi.service.blueprint.reflect.ServiceMetadata;
import org.osgi.service.blueprint.reflect.ValueMetadata;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Namespace handler for the Config Admin service.
 * This handler will parse the various elements defined and populate / modify the registry
 * accordingly.
 *
 * @see CmManagedProperties
 * @see CmManagedServiceFactory
 * @see CmProperties
 * @see CmPropertyPlaceholder
 *
 * @version $Rev: 896324 $, $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $
 */
public class CmNamespaceHandler implements NamespaceHandler {

    public static final String BLUEPRINT_NAMESPACE = "http://www.osgi.org/xmlns/blueprint/v1.0.0";
    public static final String BLUEPRINT_CM_NAMESPACE = "http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0";

    public static final String PROPERTY_PLACEHOLDER_ELEMENT = "property-placeholder";
    public static final String MANAGED_PROPERTIES_ELEMENT = "managed-properties";
    public static final String MANAGED_SERVICE_FACTORY_ELEMENT = "managed-service-factory";
    public static final String CM_PROPERTIES_ELEMENT = "cm-properties";
    public static final String DEFAULT_PROPERTIES_ELEMENT = "default-properties";
    public static final String PROPERTY_ELEMENT = "property";
    public static final String INTERFACES_ELEMENT = "interfaces";
    public static final String VALUE_ELEMENT = "value";
    public static final String MANAGED_COMPONENT_ELEMENT = "managed-component";

    public static final String ID_ATTRIBUTE = "id";
    public static final String PERSISTENT_ID_ATTRIBUTE = "persistent-id";
    public static final String PLACEHOLDER_PREFIX_ATTRIBUTE = "placeholder-prefix";
    public static final String PLACEHOLDER_SUFFIX_ATTRIBUTE = "placeholder-suffix";
    public static final String DEFAULTS_REF_ATTRIBUTE = "defaults-ref";
    public static final String UPDATE_STRATEGY_ATTRIBUTE = "update-strategy";
    public static final String UPDATE_METHOD_ATTRIBUTE = "update-method";
    public static final String FACTORY_PID_ATTRIBUTE = "factory-pid";
    public static final String AUTO_EXPORT_ATTRIBUTE = "auto-export";
    public static final String RANKING_ATTRIBUTE = "ranking";
    public static final String INTERFACE_ATTRIBUTE = "interface";
    public static final String UPDATE_ATTRIBUTE = "update";

    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";

    private static final String MANAGED_OBJECT_MANAGER_NAME = "org.apache.aries.managedObjectManager";
    
    private static final Logger LOGGER = LoggerFactory.getLogger(CmNamespaceHandler.class);

    // This property is static but it should be ok since there will be only a single instance
    // of this class for the bundle
    private static ConfigurationAdmin configAdmin;

    private int idCounter;

    public int getIdCounter() {
        return idCounter;
    }

    public void setIdCounter(int idCounter) {
        this.idCounter = idCounter;
    }

    public static ConfigurationAdmin getConfigAdmin() {
        return configAdmin;
    }

    public void setConfigAdmin(ConfigurationAdmin configAdmin) {
        this.configAdmin = configAdmin;
    }

    public URL getSchemaLocation(String namespace) {
        return getClass().getResource("blueprint-cm.xsd");
    }

    public Set<Class> getManagedClasses() {
        return new HashSet<Class>(Arrays.asList(
                CmPropertyPlaceholder.class,
                CmManagedServiceFactory.class,
                CmManagedProperties.class,
                CmProperties.class
        ));
    }

    public Metadata parse(Element element, ParserContext context) {
        LOGGER.debug("Parsing element {{}}{}", element.getNamespaceURI(), element.getLocalName());
        ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
        registerManagedObjectManager(context, registry);
        if (nodeNameEquals(element, PROPERTY_PLACEHOLDER_ELEMENT)) {
            return parsePropertyPlaceholder(context, element);
        } else if (nodeNameEquals(element, MANAGED_SERVICE_FACTORY_ELEMENT)) {
            return parseManagedServiceFactory(context, element);
        } else {
            throw new ComponentDefinitionException("Unsupported element: " + element.getNodeName());
        }
    }

    public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) {
        LOGGER.debug("Decorating node {{}}{}", node.getNamespaceURI(), node.getLocalName());
        ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
        registerManagedObjectManager(context, registry);
        if (node instanceof Element) {
            if (nodeNameEquals(node, MANAGED_PROPERTIES_ELEMENT)) {
                return decorateManagedProperties(context, (Element) node, component);
            } else if (nodeNameEquals(node, CM_PROPERTIES_ELEMENT)) {
                return decorateCmProperties(context, (Element) node, component);
            } else {
                throw new ComponentDefinitionException("Unsupported element: " + node.getNodeName());
            }
        } else {
            throw new ComponentDefinitionException("Illegal use of blueprint cm namespace");
        }
    }

    private ComponentMetadata parsePropertyPlaceholder(ParserContext context, Element element) {
        MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
        metadata.setProcessor(true);
        metadata.setId(getId(context, element));
        metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
        metadata.setRuntimeClass(CmPropertyPlaceholder.class);
        metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
        metadata.addProperty("configAdmin", createConfigAdminProxy(context));
        metadata.addProperty("persistentId", createValue(context, element.getAttribute(PERSISTENT_ID_ATTRIBUTE)));
        String prefix = element.hasAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
                                    ? element.getAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
                                    : "${";
        metadata.addProperty("placeholderPrefix", createValue(context, prefix));
        String suffix = element.hasAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
                                    ? element.getAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
                                    : "}";
        metadata.addProperty("placeholderSuffix", createValue(context, suffix));
        String defaultsRef = element.hasAttribute(DEFAULTS_REF_ATTRIBUTE) ? element.getAttribute(DEFAULTS_REF_ATTRIBUTE) : null;
        if (defaultsRef != null) {
            metadata.addProperty("defaultProperties", createRef(context, defaultsRef));
        }
        String ignoreMissingLocations = element.hasAttributeNS(ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE, ExtNamespaceHandler.IGNORE_MISSING_LOCATIONS_ATTRIBUTE)
                ? element.getAttributeNS(ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE, ExtNamespaceHandler.IGNORE_MISSING_LOCATIONS_ATTRIBUTE) : null;
        if (ignoreMissingLocations != null) {
            metadata.addProperty("ignoreMissingLocations", createValue(context, ignoreMissingLocations));
        }
        String systemProperties = element.hasAttributeNS(ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE, ExtNamespaceHandler.SYSTEM_PROPERTIES_ATTRIBUTE)
                ? element.getAttributeNS(ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE, ExtNamespaceHandler.SYSTEM_PROPERTIES_ATTRIBUTE) : null;
        if (systemProperties == null) {
            systemProperties = ExtNamespaceHandler.SYSTEM_PROPERTIES_NEVER;
        }
        metadata.addProperty("systemProperties", createValue(context, systemProperties));
        // Parse elements
        List<String> locations = 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 (BLUEPRINT_CM_NAMESPACE.equals(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, DEFAULT_PROPERTIES_ELEMENT)) {
                        if (defaultsRef != null) {
                            throw new ComponentDefinitionException("Only one of " + DEFAULTS_REF_ATTRIBUTE + " attribute or " + DEFAULT_PROPERTIES_ELEMENT + " element is allowed");
                        }
                        Metadata props = parseDefaultProperties(context, metadata, e);
                        metadata.addProperty("defaultProperties", props);
                    }
                } else if (ExtNamespaceHandler.BLUEPRINT_EXT_NAMESPACE.equals(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, ExtNamespaceHandler.LOCATION_ELEMENT)) {
                        locations.add(getTextValue(e));
                    }
                }
            }
        }
        if (!locations.isEmpty()) {
            metadata.addProperty("locations", createList(context, locations));
        }

        PlaceholdersUtils.validatePlaceholder(metadata, context.getComponentDefinitionRegistry());
        
        return metadata;
    }

    private Metadata parseDefaultProperties(ParserContext context, MutableBeanMetadata enclosingComponent, Element element) {
        MutableMapMetadata props = context.createMetadata(MutableMapMetadata.class);
        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 (BLUEPRINT_CM_NAMESPACE.equals(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, PROPERTY_ELEMENT)) {
                        BeanProperty prop = context.parseElement(BeanProperty.class, enclosingComponent, e);
                        props.addEntry(createValue(context, prop.getName(), String.class.getName()), prop.getValue());
                    }
                }
            }
        }
        return props;
    }

    private ComponentMetadata parseManagedServiceFactory(ParserContext context, Element element) {
        String id = getId(context, element);

        MutableBeanMetadata factoryMetadata = context.createMetadata(MutableBeanMetadata.class);
        generateIdIfNeeded(context, factoryMetadata);
        factoryMetadata.addProperty("id", createValue(context, factoryMetadata.getId()));
        factoryMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
        factoryMetadata.setRuntimeClass(CmManagedServiceFactory.class);
        factoryMetadata.setInitMethod("init");
        factoryMetadata.setDestroyMethod("destroy");
        factoryMetadata.addProperty("configAdmin", createConfigAdminProxy(context));
        factoryMetadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
        factoryMetadata.addProperty("factoryPid", createValue(context, element.getAttribute(FACTORY_PID_ATTRIBUTE)));
        String autoExport = element.hasAttribute(AUTO_EXPORT_ATTRIBUTE) ? element.getAttribute(AUTO_EXPORT_ATTRIBUTE) : AUTO_EXPORT_DEFAULT;
        if (AUTO_EXPORT_DISABLED.equals(autoExport)) {
            autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_DISABLED);
        } else if (AUTO_EXPORT_INTERFACES.equals(autoExport)) {
            autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_INTERFACES);
        } else if (AUTO_EXPORT_CLASS_HIERARCHY.equals(autoExport)) {
            autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY);
        } else if (AUTO_EXPORT_ALL.equals(autoExport)) {
            autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_ALL_CLASSES);
        } else {
            throw new ComponentDefinitionException("Illegal value (" + autoExport + ") for " + AUTO_EXPORT_ATTRIBUTE + " attribute");
        }
        factoryMetadata.addProperty("autoExport", createValue(context, autoExport));
        String ranking = element.hasAttribute(RANKING_ATTRIBUTE) ? element.getAttribute(RANKING_ATTRIBUTE) : RANKING_DEFAULT;
        factoryMetadata.addProperty("ranking", createValue(context, ranking));

        List<String> interfaces = null;
        if (element.hasAttribute(INTERFACE_ATTRIBUTE)) {
            interfaces = Collections.singletonList(element.getAttribute(INTERFACE_ATTRIBUTE));
            factoryMetadata.addProperty("interfaces", createList(context, interfaces));
        }

        Parser parser = getParser(context);
        
        // Parse elements
        List<RegistrationListener> listeners = new ArrayList<RegistrationListener>();
        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 (interfaces != null) {
                            throw new ComponentDefinitionException("Only one of " + Parser.INTERFACE_ATTRIBUTE + " attribute or " + INTERFACES_ELEMENT + " element must be used");
                        }
                        interfaces = parseInterfaceNames(e);
                        factoryMetadata.addProperty("interfaces", createList(context, interfaces));                    
                    } else if (nodeNameEquals(e, Parser.SERVICE_PROPERTIES_ELEMENT)) { 
                        MapMetadata map = parser.parseServiceProperties(e, factoryMetadata);
                        factoryMetadata.addProperty("serviceProperties", map);
                    } else if (nodeNameEquals(e, Parser.REGISTRATION_LISTENER_ELEMENT)) {
                        listeners.add(parser.parseRegistrationListener(e, factoryMetadata));
                    }
                } else if (BLUEPRINT_CM_NAMESPACE.equals(e.getNamespaceURI())) {
                    if (nodeNameEquals(e, MANAGED_COMPONENT_ELEMENT)) {
                        MutableBeanMetadata managedComponent = context.parseElement(MutableBeanMetadata.class, null, e);
                        generateIdIfNeeded(context, managedComponent);
                        managedComponent.setScope(BeanMetadata.SCOPE_PROTOTYPE);
                        // destroy-method on managed-component has different signature than on regular beans
                        // so we'll handle it differently
                        String destroyMethod = managedComponent.getDestroyMethod();
                        if (destroyMethod != null) {
                            factoryMetadata.addProperty("componentDestroyMethod", createValue(context, destroyMethod));
                            managedComponent.setDestroyMethod(null);
                        }
                        context.getComponentDefinitionRegistry().registerComponentDefinition(managedComponent);
                        factoryMetadata.addProperty("managedComponentName", createIdRef(context, managedComponent.getId()));
                    }
                }
            }
        }

        MutableCollectionMetadata listenerCollection = context.createMetadata(MutableCollectionMetadata.class);
        listenerCollection.setCollectionClass(List.class);
        for (RegistrationListener listener : listeners) {
            MutableBeanMetadata bean = context.createMetadata(MutableBeanMetadata.class);
            bean.setRuntimeClass(ServiceListener.class);
            bean.addProperty("listener", listener.getListenerComponent());
            bean.addProperty("registerMethod", createValue(context, listener.getRegistrationMethod()));
            bean.addProperty("unregisterMethod", createValue(context, listener.getUnregistrationMethod()));
            listenerCollection.addValue(bean);
        }
        factoryMetadata.addProperty("listeners", listenerCollection);
        
        context.getComponentDefinitionRegistry().registerComponentDefinition(factoryMetadata);
        
        MutableBeanMetadata mapMetadata = context.createMetadata(MutableBeanMetadata.class);
        mapMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
        mapMetadata.setId(id);
        mapMetadata.setFactoryComponent(createRef(context, factoryMetadata.getId()));
        mapMetadata.setFactoryMethod("getServiceMap");
        return mapMetadata;
    }

    private ComponentMetadata decorateCmProperties(ParserContext context, Element element, ComponentMetadata component) {
        generateIdIfNeeded(context, ((MutableComponentMetadata) component));
        MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
        metadata.setProcessor(true);
        metadata.setId(getId(context, element));
        metadata.setRuntimeClass(CmProperties.class);
        String persistentId = element.getAttribute(PERSISTENT_ID_ATTRIBUTE);
        // if persistentId is "" the cm-properties element in nested in managed-service-factory
        // and the configuration object will come from the factory. So we only really need to register
        // ManagedService if the persistentId is not an empty string.
        if (persistentId.length() > 0) {
            metadata.setInitMethod("init");
            metadata.setDestroyMethod("destroy");
        }
        metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
        metadata.addProperty("configAdmin", createConfigAdminProxy(context));
        metadata.addProperty("managedObjectManager", createRef(context, MANAGED_OBJECT_MANAGER_NAME));
        metadata.addProperty("persistentId", createValue(context, persistentId));
        if (element.hasAttribute(UPDATE_ATTRIBUTE)) {
            metadata.addProperty("update", createValue(context, element.getAttribute(UPDATE_ATTRIBUTE)));
        }
        metadata.addProperty("serviceId", createIdRef(context, component.getId()));
        context.getComponentDefinitionRegistry().registerComponentDefinition(metadata);
        return component;
    }

    private ComponentMetadata decorateManagedProperties(ParserContext context, Element element, ComponentMetadata component) {
        if (!(component instanceof MutableBeanMetadata)) {
            throw new ComponentDefinitionException("Element " + MANAGED_PROPERTIES_ELEMENT + " must be used inside a <bp:bean> element");
        }
        generateIdIfNeeded(context, ((MutableBeanMetadata) component));
        MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
        metadata.setProcessor(true);
        metadata.setId(getId(context, element));
        metadata.setRuntimeClass(CmManagedProperties.class);
        String persistentId = element.getAttribute(PERSISTENT_ID_ATTRIBUTE);
        // if persistentId is "" the managed properties element in nested in managed-service-factory
        // and the configuration object will come from the factory. So we only really need to register
        // ManagedService if the persistentId is not an empty string.
        if (persistentId.length() > 0) {
            metadata.setInitMethod("init");
            metadata.setDestroyMethod("destroy");
        }
        metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
        metadata.addProperty("configAdmin", createConfigAdminProxy(context));
        metadata.addProperty("managedObjectManager", createRef(context, MANAGED_OBJECT_MANAGER_NAME));
        metadata.addProperty("persistentId", createValue(context, persistentId));
        String updateStrategy = element.getAttribute(UPDATE_STRATEGY_ATTRIBUTE);
        if (updateStrategy != null) {
            metadata.addProperty("updateStrategy", createValue(context, updateStrategy));
        }
        if (element.hasAttribute(UPDATE_METHOD_ATTRIBUTE)) {
            metadata.addProperty("updateMethod", createValue(context, element.getAttribute(UPDATE_METHOD_ATTRIBUTE)));
        } else if ("component-managed".equals(updateStrategy)) {
            throw new ComponentDefinitionException(UPDATE_METHOD_ATTRIBUTE + " attribute must be set when " + UPDATE_STRATEGY_ATTRIBUTE + " is set to 'component-managed'");
        }
        metadata.addProperty("beanName", createIdRef(context, component.getId()));
        context.getComponentDefinitionRegistry().registerComponentDefinition(metadata);
        return component;
    }

    /**
     * Create a reference to the ConfigurationAdmin service if not already done
     * and add it to the registry.
     *
     * @param context the parser context
     * @return a metadata pointing to the config admin
     */
    private Metadata createConfigAdminProxy(ParserContext context) {
        MutableBeanMetadata bean = context.createMetadata(MutableBeanMetadata.class);
        bean.setRuntimeClass(CmNamespaceHandler.class);
        bean.setFactoryMethod("getConfigAdmin");
        bean.setActivation(MutableBeanMetadata.ACTIVATION_LAZY);
        bean.setScope(MutableBeanMetadata.SCOPE_PROTOTYPE);
        return bean;
    }

    private void registerManagedObjectManager(ParserContext context, ComponentDefinitionRegistry registry) {
        if (registry.getComponentDefinition(MANAGED_OBJECT_MANAGER_NAME) == null) {
            MutableBeanMetadata beanMetadata = context.createMetadata(MutableBeanMetadata.class);
            beanMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
            beanMetadata.setId(MANAGED_OBJECT_MANAGER_NAME);
            beanMetadata.setRuntimeClass(ManagedObjectManager.class);            
            registry.registerComponentDefinition(beanMetadata);
        }
    }
    
    private static ValueMetadata createValue(ParserContext context, String value) {
        return createValue(context, value, null);
    }

    private static ValueMetadata createValue(ParserContext context, String value, String type) {
        MutableValueMetadata m = context.createMetadata(MutableValueMetadata.class);
        m.setStringValue(value);
        m.setType(type);
        return m;
    }

    private static RefMetadata createRef(ParserContext context, String value) {
        MutableRefMetadata m = context.createMetadata(MutableRefMetadata.class);
        m.setComponentId(value);
        return m;
    }

    private static IdRefMetadata createIdRef(ParserContext context, String value) {
        MutableIdRefMetadata m = context.createMetadata(MutableIdRefMetadata.class);
        m.setComponentId(value);
        return m;
    }

    private static CollectionMetadata createList(ParserContext context, List<String> list) {
        MutableCollectionMetadata m = context.createMetadata(MutableCollectionMetadata.class);
        m.setCollectionClass(List.class);
        m.setValueType(String.class.getName());
        for (String v : list) {
            m.addValue(createValue(context, v, String.class.getName()));
        }
        return m;
    }

    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 boolean nodeNameEquals(Node node, String name) {
        return (name.equals(node.getNodeName()) || name.equals(node.getLocalName()));
    }

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

    public String getId(ParserContext context, Element element) {
        if (element.hasAttribute(ID_ATTRIBUTE)) {
            return element.getAttribute(ID_ATTRIBUTE);
        } else {
            return generateId(context);
        }
    }

    public void generateIdIfNeeded(ParserContext context, MutableComponentMetadata metadata) {
        if (metadata.getId() == null) {
            metadata.setId(generateId(context));
        }
    }

    private String generateId(ParserContext context) {
        String id;
        do {
            id = ".cm-" + ++idCounter;
        } while (context.getComponentDefinitionRegistry().containsComponentDefinition(id));
        return id;
    }
    
    private Parser getParser(ParserContext ctx) {
        if (ctx instanceof ParserContextImpl) {
            return ((ParserContextImpl) ctx).getParser();
        }
        throw new RuntimeException("Unable to get parser");
    }

    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;
    }

}
