/*
 * 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.felix.scr.impl.metadata;


import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.felix.scr.impl.helper.Logger;
import org.osgi.service.component.ComponentException;
import org.osgi.service.log.LogService;


/**
 * This class holds the information associated to a component in the descriptor *  */
public class ComponentMetadata
{
    // Configuration required for component activation (since DS 1.1)
    public static final String CONFIGURATION_POLICY_REQUIRE = "require";

    // Configuration not provided to component (since DS 1.1)
    public static final String CONFIGURATION_POLICY_IGNORE = "ignore";

    // Configuration optional (default) (since DS 1.1)
    public static final String CONFIGURATION_POLICY_OPTIONAL = "optional";

    // set of valid configuration policy settings
    private static final Set CONFIGURATION_POLICY_VALID;

    // marker value indicating duplicate implementation class setting
    private static final String IMPLEMENTATION_CLASS_DUPLICATE = "icd";

    // marker value indicating duplicate service setting
    private static final ServiceMetadata SERVICE_DUPLICATE = new ServiceMetadata();

    // the namespace code of the namespace declaring this component, this is
    // one of the XmlHandler.DS_VERSION_* constants
    private final int m_namespaceCode;

    // 112.4.3: A Globally unique component name (required)
    private String m_name;

    // 112.4.3: Controls whether the component is enabled when the bundle is started. (optional, default is true).
    private boolean m_enabled = true;

    // 112.4.3: Factory identified. If set to a non empty string, it indicates that the component is a factory component (optional).
    private String m_factory = null;

    // 112.4.3: Controls whether component configurations must be immediately activated after becoming
    // satisfied or whether activation should be delayed. (optional, default value depends
    // on whether the component has a service element or not).
    private Boolean m_immediate = null;

    // 112.4.4 Implementation Element (required)
    private String m_implementationClassName = null;

    // 112.5.8 activate can be specified (since DS 1.1)
    private String m_activate = null;

    // 112.5.8 whether activate has been specified
    private boolean m_activateDeclared = false;

    // 112.5.12 deactivate can be specified (since DS 1.1)
    private String m_deactivate = null;

    // 112.5.12 whether deactivate has been specified
    private boolean m_deactivateDeclared = false;

    // 112.??.?? modified method (configuration update, since DS 1.1)
    private String m_modified = null;

    // 112.4.3 configuration-policy (since DS 1.1)
    private String m_configurationPolicy = null;

    // Associated properties (0..*)
    private Dictionary m_properties = new Hashtable();

    // List of Property metadata - used while building the meta data
    // while validating the properties contained in the PropertyMetadata
    // instances are copied to the m_properties Dictionary while this
    // list will be cleared
    private List m_propertyMetaData = new ArrayList();

    // Provided services (0..1)
    private ServiceMetadata m_service = null;

    // List of service references, (required services 0..*)
    private List m_references = new ArrayList();

    // Flag that is set once the component is verified (its properties cannot be changed)
    private boolean m_validated = false;

    static
    {
        CONFIGURATION_POLICY_VALID = new TreeSet();
        CONFIGURATION_POLICY_VALID.add( CONFIGURATION_POLICY_IGNORE );
        CONFIGURATION_POLICY_VALID.add( CONFIGURATION_POLICY_OPTIONAL );
        CONFIGURATION_POLICY_VALID.add( CONFIGURATION_POLICY_REQUIRE );
    }


    public ComponentMetadata( int namespaceCode )
    {
        this.m_namespaceCode = namespaceCode;
    }

    /////////////////////////////////////////// SETTERS //////////////////////////////////////

    /**
     * Setter for the name
     *
     * @param name
     */
    public void setName( String name )
    {
        if ( m_validated )
        {
            return;
        }
        m_name = name;
    }


    /**
     * Setter for the enabled property
     *
     * @param enabled
     */
    public void setEnabled( boolean enabled )
    {
        if ( m_validated )
        {
            return;
        }
        m_enabled = enabled;
    }


    /**
     *
     * @param factoryIdentifier
     */
    public void setFactoryIdentifier( String factoryIdentifier )
    {
        if ( m_validated )
        {
            return;
        }
        m_factory = factoryIdentifier;
    }


    /**
     * Setter for the immediate property
     *
     * @param immediate
     */
    public void setImmediate( boolean immediate )
    {
        if ( m_validated )
        {
            return;
        }
        m_immediate = immediate ? Boolean.TRUE : Boolean.FALSE;
    }


    /**
     * Sets the name of the implementation class
     *
     * @param implementationClassName a class name
     */
    public void setImplementationClassName( String implementationClassName )
    {
        if ( m_validated )
        {
            return;
        }

        // set special flag value if implementation class is already set
        if ( m_implementationClassName != null )
        {
            m_implementationClassName = IMPLEMENTATION_CLASS_DUPLICATE;
        }
        else
        {
            m_implementationClassName = implementationClassName;
        }
    }


    /**
     * Sets the configuration policy
     *
     * @param configurationPolicy configuration policy
     * @since 1.2.0 (DS 1.1)
     */
    public void setConfigurationPolicy( String configurationPolicy )
    {
        if ( m_validated )
        {
            return;
        }
        m_configurationPolicy = configurationPolicy;
    }


    /**
     * Sets the name of the activate method
     *
     * @param activate a method name
     * @since 1.2.0 (DS 1.1)
     */
    public void setActivate( String activate )
    {
        if ( m_validated )
        {
            return;
        }
        m_activate = activate;
        m_activateDeclared = true;
    }


    /**
     * Sets the name of the deactivate method
     *
     * @param deactivate a method name
     * @since 1.2.0 (DS 1.1)
     */
    public void setDeactivate( String deactivate )
    {
        if ( m_validated )
        {
            return;
        }
        m_deactivate = deactivate;
        m_deactivateDeclared = true;
    }


    /**
     * Sets the name of the modified method
     *
     * @param modified a method name
     * @since 1.2.0 (DS 1.1)
     */
    public void setModified( String modified )
    {
        if ( m_validated )
        {
            return;
        }
        m_modified = modified;
    }


    /**
     * Used to add a property to the instance
     *
     * @param newProperty a property metadata object
     */
    public void addProperty( PropertyMetadata newProperty )
    {
        if ( m_validated )
        {
            return;
        }
        if ( newProperty == null )
        {
            throw new IllegalArgumentException( "Cannot add a null property" );
        }
        m_propertyMetaData.add( newProperty );
    }


    /**
     * Used to set a ServiceMetadata object.
     *
     * @param service a ServiceMetadata
     */
    public void setService( ServiceMetadata service )
    {
        if ( m_validated )
        {
            return;
        }

        // set special flag value if implementation class is already set
        if ( m_service != null )
        {
            m_service = SERVICE_DUPLICATE;
        }
        else
        {
            m_service = service;
        }
    }


    /**
     * Used to add a reference metadata to the component
     *
     * @param newReference a new ReferenceMetadata to be added
     */
    public void addDependency( ReferenceMetadata newReference )
    {
        if ( m_validated )
        {
            return;
        }
        if ( newReference == null )
        {
            throw new IllegalArgumentException( "Cannot add a null ReferenceMetadata" );
        }
        m_references.add( newReference );
    }


    /////////////////////////////////////////// GETTERS //////////////////////////////////////

    /**
     * Returns the namespace code of the namespace of the component element
     * declaring this component. This is one of the XmlHandler.DS_VERSION_*
     * constants.
     */
    public int getNamespaceCode()
    {
        return m_namespaceCode;
    }


    /**
     * Returns <code>true</code> if the metadata declaration has used the
     * Declarative Services version 1.1 namespace or a later namespace.
     */
    public boolean isDS11()
    {
        return getNamespaceCode() >= XmlHandler.DS_VERSION_1_1;
    }


    /**
     * Returns <code>true</code> if the metadata declaration has used the
     * Declarative Services version 1.1-felixnamespace or a later namespace.
     *
     * @see <a href="https://issues.apache.org/jira/browse/FELIX-1893">FELIX-1893</a>
     */
    public boolean isDS11Felix()
    {
        return getNamespaceCode() >= XmlHandler.DS_VERSION_1_1_FELIX;
    }


    /**
     * Returns the name of the component
     *
     * @return A string containing the name of the component
     */
    public String getName()
    {
        /*
         * Generally the default value for the name (the implementation class
         * name) is set by the validate method if the descriptor declares a
         * DS 1.1 or newer component. This method, though, is called before
         * validate is called to reserve the component name. To properly
         * support this reservation even in the absence of the name attribute
         * this method should just return the implementation class name in
         * this case and leave the actual version validation to the validate
         * method. See also FELIX-2325.
         */

        if (m_name != null) {
            return m_name;
        }

        // return the implementation class name if the name is not set
        return getImplementationClassName();
    }


    /**
     * Returns the value of the enabled flag
     *
     * @return a boolean containing the value of the enabled flag
     */
    public boolean isEnabled()
    {
        return m_enabled;
    }


    /**
     * Returns the factory identifier
     *
     * @return A string containing a factory identifier or null
     */
    public String getFactoryIdentifier()
    {
        return m_factory;
    }


    /**
     * Returns the flag that defines the activation policy for the component.
     * <p>
     * This method may only be trusted after this instance has been validated
     * by the {@link #validate()} call. Else it will either return the value
     * of an explicitly set "immediate" attribute or return false if a service
     * element or the factory attribute is set or true otherwise. This latter
     * default value deduction may be unsafe while the descriptor has not been
     * completely read.
     *
     * @return a boolean that defines the activation policy
     */
    public boolean isImmediate()
    {
        // return explicit value if known
        if ( m_immediate != null )
        {
            return m_immediate.booleanValue();
        }

        // deduce default from service element and factory attribute presence
        return m_service == null && m_factory == null;
    }


    /**
     * Returns the name of the implementation class
     *
     * @return the name of the implementation class
     */
    public String getImplementationClassName()
    {
        return m_implementationClassName;
    }


    /**
     * Returns the configuration Policy
     *
     * @return the configuration policy
     * @since 1.2.0 (DS 1.1)
     */
    public String getConfigurationPolicy()
    {
        return m_configurationPolicy;
    }


    /**
     * Returns the name of the activate method
     *
     * @return the name of the activate method
     * @since 1.2.0 (DS 1.1)
     */
    public String getActivate()
    {
        return m_activate;
    }


    /**
     * Returns whether the activate method has been declared in the descriptor
     * or not.
     *
     * @return whether the activate method has been declared in the descriptor
     *      or not.
     * @since 1.2.0 (DS 1.1)
     */
    public boolean isActivateDeclared()
    {
        return m_activateDeclared;
    }


    /**
     * Returns the name of the deactivate method
     *
     * @return the name of the deactivate method
     * @since 1.2.0 (DS 1.1)
     */
    public String getDeactivate()
    {
        return m_deactivate;
    }


    /**
     * Returns whether the deactivate method has been declared in the descriptor
     * or not.
     *
     * @return whether the deactivate method has been declared in the descriptor
     *      or not.
     * @since 1.2.0 (DS 1.1)
     */
    public boolean isDeactivateDeclared()
    {
        return m_deactivateDeclared;
    }


    /**
     * Returns the name of the modified method
     *
     * @return the name of the modified method
     * @since 1.2.0 (DS 1.1)
     */
    public String getModified()
    {
        return m_modified;
    }


    /**
     * Returns the associated ServiceMetadata
     *
     * @return a ServiceMetadata object or null if the Component does not provide any service
     */
    public ServiceMetadata getServiceMetadata()
    {
        return m_service;
    }


    /**
     * Returns the properties.
     *
     * @return the properties as a Dictionary
     */
    public Dictionary getProperties()
    {
        return m_properties;
    }


    /**
     * Returns the list of property meta data.
     * <b>Note: This method is intended for unit testing only</b>
     *
     * @return the list of property meta data.
     */
    List getPropertyMetaData()
    {
        return m_propertyMetaData;
    }


    /**
     * Returns the dependency descriptors
     *
     * @return a Collection of dependency descriptors
     */
    public List getDependencies()
    {
        return m_references;
    }


    /**
     * Test to see if this service is a factory
     *
     * @return true if it is a factory, false otherwise
     */
    public boolean isFactory()
    {
        return m_factory != null;
    }


    /**
     * Returns <code>true</code> if the configuration policy is configured to
     * {@link #CONFIGURATION_POLICY_REQUIRE}.
     */
    public boolean isConfigurationRequired()
    {
        return CONFIGURATION_POLICY_REQUIRE.equals( m_configurationPolicy );
    }


    /**
     * Returns <code>true</code> if the configuration policy is configured to
     * {@link #CONFIGURATION_POLICY_IGNORE}.
     */
    public boolean isConfigurationIgnored()
    {
        return CONFIGURATION_POLICY_IGNORE.equals( m_configurationPolicy );
    }


    /**
     * Returns <code>true</code> if the configuration policy is configured to
     * {@link #CONFIGURATION_POLICY_OPTIONAL}.
     */
    public boolean isConfigurationOptional()
    {
        return CONFIGURATION_POLICY_OPTIONAL.equals( m_configurationPolicy );
    }


    /**
     * Method used to verify if the semantics of this metadata are correct
     */
    public void validate( Logger logger )
    {
        // nothing to do if already validated
        if ( m_validated )
        {
            return;
        }

        // 112.10 The name of the component is required
        if ( m_name == null )
        {
            // 112.4.3 name is optional defaulting to implementation class name since DS 1.1
            if ( m_namespaceCode < XmlHandler.DS_VERSION_1_1 )
            {
                throw new ComponentException( "The component name has not been set" );
            }
            setName( getImplementationClassName() );
        }

        // 112.10 There must be one implementation element and the class atribute is required
        if ( m_implementationClassName == null )
        {
            throw validationFailure( "Implementation class name missing" );
        }
        else if ( m_implementationClassName == IMPLEMENTATION_CLASS_DUPLICATE )
        {
            throw validationFailure( "Implementation element must occur exactly once" );
        }

        // 112.4.3 configuration-policy (since DS 1.1)
        if ( m_configurationPolicy == null )
        {
            // default if not specified or pre DS 1.1
            m_configurationPolicy = CONFIGURATION_POLICY_OPTIONAL;
        }
        else if ( m_namespaceCode < XmlHandler.DS_VERSION_1_1 )
        {
            logger.log( LogService.LOG_WARNING, "Ignoring configuration policy, DS 1.1 or later namespace required",
                this, null );
            m_configurationPolicy = CONFIGURATION_POLICY_OPTIONAL;
        }
        else if ( !CONFIGURATION_POLICY_VALID.contains( m_configurationPolicy ) )
        {
            throw validationFailure( "Configuration policy must be one of " + CONFIGURATION_POLICY_VALID );
        }

        // 112.5.8 activate can be specified (since DS 1.1)
        if ( m_activate == null )
        {
            // default if not specified or pre DS 1.1
            m_activate = "activate";
        }
        else if ( m_namespaceCode < XmlHandler.DS_VERSION_1_1 )
        {
            // DS 1.0 cannot declare the activate method, assume default and undeclared
            logger.log( LogService.LOG_WARNING,
                "Ignoring activate method declaration, DS 1.1 or later namespace required", this, null );
            m_activate = "activate";
            m_activateDeclared = false;
        }

        // 112.5.12 deactivate can be specified (since DS 1.1)
        if ( m_deactivate == null )
        {
            // default if not specified or pre DS 1.1
            m_deactivate = "deactivate";
        }
        else if ( m_namespaceCode < XmlHandler.DS_VERSION_1_1 )
        {
            // DS 1.0 cannot declare the deactivate method, assume default and undeclared
            logger.log( LogService.LOG_WARNING,
                "Ignoring deactivate method declaration, DS 1.1 or later namespace required", this, null );
            m_deactivate = "deactivate";
            m_deactivateDeclared = false;
        }

        // 112.??.?? modified can be specified (since DS 1.1)
        if ( m_modified != null && m_namespaceCode < XmlHandler.DS_VERSION_1_1 )
        {
            // require new namespace if modified is specified
            logger.log( LogService.LOG_WARNING,
                "Ignoring modified method declaration, DS 1.1 or later namespace required", this, null );
            m_modified = null;
        }

        // Next check if the properties are valid (and extract property values)
        Iterator propertyIterator = m_propertyMetaData.iterator();
        while ( propertyIterator.hasNext() )
        {
            PropertyMetadata propMeta = ( PropertyMetadata ) propertyIterator.next();
            propMeta.validate( this );
            m_properties.put( propMeta.getName(), propMeta.getValue() );
        }
        m_propertyMetaData.clear();

        // Check that the provided services are valid too
        if ( m_service == SERVICE_DUPLICATE )
        {
            throw validationFailure( "Service element must occur at most once" );
        }
        else if ( m_service != null )
        {
            m_service.validate( this );
        }

        // Check that the references are ok
        HashSet refs = new HashSet();
        Iterator referenceIterator = m_references.iterator();
        while ( referenceIterator.hasNext() )
        {
            ReferenceMetadata refMeta = ( ReferenceMetadata ) referenceIterator.next();
            refMeta.validate( this, logger );

            // flag duplicates
            if ( !refs.add( refMeta.getName() ) )
            {
                logger.log( LogService.LOG_WARNING, "Detected duplicate reference name: ''{0}''", new Object[]
                    { refMeta.getName() }, this, null );
            }
        }

        // verify value of immediate attribute if set
        if ( m_immediate != null )
        {
            if ( isImmediate() )
            {
                // FELIX-593: 112.4.3 clarification, immediate is false for factory
                if ( isFactory() )
                {
                    throw validationFailure( "Factory cannot be immediate" );
                }
            }
            else
            {
                // 112.2.3 A delayed component specifies a service, is not specified to be a factory component
                // and does not have the immediate attribute of the component element set to true.
                // FELIX-593: 112.4.3 clarification, immediate may be true for factory
                if ( m_service == null && !isFactory() )
                {
                    throw validationFailure( "Delayed must provide a service or be a factory" );
                }
            }
        }

        // 112.4.6 The serviceFactory attribute (of a provided service) must not be true if
        // the component is a factory component or an immediate component
        if ( m_service != null )
        {
            if ( m_service.isServiceFactory() && ( isFactory() || isImmediate() ) )
            {
                throw validationFailure( "ServiceFactory cannot be factory or immediate" );
            }
        }

        m_validated = true;
        // TODO: put a similar flag on the references and the services
    }


    /**
     * Returns a <code>ComponentException</code> for this compeonent with the
     * given explanation for failure.
     *
     * @param reason The explanation for failing to validate this component.
     */
    ComponentException validationFailure( String reason )
    {
        return new ComponentException( "Component " + getName() + " validation failed: " + reason );
    }
}
