/*
 * 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;


import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

import org.apache.felix.scr.impl.parser.KXml2SAXHandler;
import org.apache.felix.scr.impl.parser.ParseException;
import org.osgi.framework.Bundle;


/**
 *
 *
 */
public class XmlHandler implements KXml2SAXHandler
{

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

    // the bundle containing the XML resource being parsed
    private Bundle m_bundle;

    // A reference to the current component
    private ComponentMetadata m_currentComponent;

    // The current service
    private ServiceMetadata m_currentService;

    // A list of component descriptors contained in the file
    private List m_components = new ArrayList();

    // PropertyMetaData whose value attribute is missing, hence has element data
    private PropertyMetadata m_pendingProperty;

    /** Flag for detecting the first element. */
    protected boolean firstElement = true;

    /** Override namespace. */
    protected String overrideNamespace;

    /** Flag for elements inside a component element */
    protected boolean isComponent = false;


    // creates an instance with the bundle owning the component descriptor
    // file parsed by this instance
    XmlHandler( Bundle bundle )
    {
        m_bundle = bundle;
    }


    /**
     * Method called when a tag opens
     *
     * @param   uri
     * @param   localName
     * @param   attrib
     * @exception   ParseException
    **/
    public void startElement( String uri, String localName, Properties attrib ) throws ParseException
    {
        // according to the spec, the elements should have the namespace,
        // except when the root element is the "component" element
        // So we check this for the first element, we receive.
        if ( firstElement )
        {
            firstElement = false;
            if ( localName.equals( "component" ) && "".equals( uri ) )
            {
                overrideNamespace = NAMESPACE_URI;
            }
        }

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

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

        // from now on uri points to the namespace
        if ( NAMESPACE_URI.equals( uri ) )
        {
            try
            {

                // 112.4.3 Component Element
                if ( localName.equals( "component" ) )
                {
                    this.isComponent = true;

                    // Create a new ComponentMetadata
                    m_currentComponent = new ComponentMetadata();

                    // name attribute is mandatory
                    m_currentComponent.setName( attrib.getProperty( "name" ) );

                    // enabled attribute is optional
                    if ( attrib.getProperty( "enabled" ) != null )
                    {
                        m_currentComponent.setEnabled( attrib.getProperty( "enabled" ).equals( "true" ) );
                    }

                    // immediate attribute is optional
                    if ( attrib.getProperty( "immediate" ) != null )
                    {
                        m_currentComponent.setImmediate( attrib.getProperty( "immediate" ).equals( "true" ) );
                    }

                    // factory attribute is optional
                    if ( attrib.getProperty( "factory" ) != null )
                    {
                        m_currentComponent.setFactoryIdentifier( attrib.getProperty( "factory" ) );
                    }

                    // Add this component to the list
                    m_components.add( m_currentComponent );
                }

                // 112.4.4 Implementation
                else if ( localName.equals( "implementation" ) )
                {
                    // Set the implementation class name (mandatory)
                    m_currentComponent.setImplementationClassName( attrib.getProperty( "class" ) );
                }
                // 112.4.5 [...] Property Elements
                else if ( localName.equals( "property" ) )
                {
                    PropertyMetadata prop = new PropertyMetadata();

                    // name attribute is mandatory
                    prop.setName( attrib.getProperty( "name" ) );

                    // type attribute is optional
                    if ( attrib.getProperty( "type" ) != null )
                    {
                        prop.setType( attrib.getProperty( "type" ) );
                    }

                    // 112.4.5: If the value attribute is specified, the body of the element is ignored.
                    if ( attrib.getProperty( "value" ) != null )
                    {
                        prop.setValue( attrib.getProperty( "value" ) );
                        m_currentComponent.addProperty( prop );
                    }
                    else
                    {
                        // hold the metadata pending
                        m_pendingProperty = prop;
                    }
                }
                // 112.4.5 Properties [...] Elements
                else if ( localName.equals( "properties" ) )
                {
                    readPropertiesEntry( attrib.getProperty( "entry" ) );
                }
                // 112.4.6 Service Element
                else if ( localName.equals( "service" ) )
                {

                    m_currentService = new ServiceMetadata();

                    // servicefactory attribute is optional
                    if ( attrib.getProperty( "servicefactory" ) != null )
                    {
                        m_currentService.setServiceFactory( attrib.getProperty( "servicefactory" ).equals( "true" ) );
                    }

                    m_currentComponent.setService( m_currentService );
                }
                else if ( localName.equals( "provide" ) )
                {
                    m_currentService.addProvide( attrib.getProperty( "interface" ) );
                }

                // 112.4.7 Reference element
                else if ( localName.equals( "reference" ) )
                {
                    ReferenceMetadata ref = new ReferenceMetadata();
                    ref.setName( attrib.getProperty( "name" ) );
                    ref.setInterface( attrib.getProperty( "interface" ) );

                    // Cardinality
                    if ( attrib.getProperty( "cardinality" ) != null )
                    {
                        ref.setCardinality( attrib.getProperty( "cardinality" ) );
                    }

                    if ( attrib.getProperty( "policy" ) != null )
                    {
                        ref.setPolicy( attrib.getProperty( "policy" ) );
                    }

                    //if
                    ref.setTarget( attrib.getProperty( "target" ) );
                    ref.setBind( attrib.getProperty( "bind" ) );
                    ref.setUnbind( attrib.getProperty( "unbind" ) );

                    m_currentComponent.addDependency( ref );
                }
            }
            catch ( Exception ex )
            {
                ex.printStackTrace();
                throw new ParseException( "Exception during parsing", ex );
            }
        }
    }


    /**
    * Method called when a tag closes
    *
    * @param   uri
    * @param   localName
    */
    public void endElement( String uri, String localName )
    {
        if ( overrideNamespace != null && "".equals( uri ) )
        {
            uri = overrideNamespace;
        }

        if ( this.isComponent && "".equals(uri) )
        {
            uri = NAMESPACE_URI;
        }

        if ( NAMESPACE_URI.equals( uri ) )
        {
            if ( localName.equals( "component" ) )
            {
                this.isComponent = false;
                // When the closing tag for a component is found, the component is validated to check if
                // the implementation class has been set
                m_currentComponent.validate();
            }
            else if ( localName.equals( "property" ) && m_pendingProperty != null )
            {
                // 112.4.5 body expected to contain property value
                // if so, the m_pendingProperty field would be null
                // currently, we just ignore this situation
                m_pendingProperty = null;
            }
        }
    }


    /**
    * Called to retrieve the service descriptors
    *
    * @return   A list of service descriptors
    */
    List getComponentMetadataList()
    {
        return m_components;
    }


    /**
     * @see org.apache.felix.scr.impl.parser.KXml2SAXHandler#characters(java.lang.String)
     */
    public void characters( String text )
    {
        // 112.4.5 If the value attribute is not specified, the body must contain one or more values
        if ( m_pendingProperty != null )
        {
            m_pendingProperty.setValues( text );
            m_currentComponent.addProperty( m_pendingProperty );
            m_pendingProperty = null;
        }
    }


    /**
     * @see org.apache.felix.scr.impl.parser.KXml2SAXHandler#processingInstruction(java.lang.String, java.lang.String)
     */
    public void processingInstruction( String target, String data )
    {
        // Not used
    }


    /**
     * @see org.apache.felix.scr.impl.parser.KXml2SAXHandler#setLineNumber(int)
     */
    public void setLineNumber( int lineNumber )
    {
        // Not used
    }


    /**
     * @see org.apache.felix.scr.impl.parser.KXml2SAXHandler#setColumnNumber(int)
     */
    public void setColumnNumber( int columnNumber )
    {
        // Not used
    }


    /**
     * Reads the name property file from the bundle owning this descriptor. All
     * properties read from the properties file are added to the current
     * component's property meta data list.
     *
     * @param entryName The name of the bundle entry containing the propertes
     *      to be added. This must not be <code>null</code>.
     *
     * @throws ParseException If the entry name is <code>null</code> or no
     *      entry with the given name exists in the bundle or an error occurrs
     *      reading the properties file.
     */
    private void readPropertiesEntry( String entryName ) throws ParseException
    {
        if ( entryName == null )
        {
            throw new ParseException( "Missing entry attribute of properties element", null );
        }

        URL entryURL = m_bundle.getEntry( entryName );
        if ( entryURL == null )
        {
            throw new ParseException( "Missing bundle entry " + entryName, null );
        }

        Properties props = new Properties();
        InputStream entryStream = null;
        try
        {
            entryStream = entryURL.openStream();
            props.load( entryStream );
        }
        catch ( IOException ioe )
        {
            throw new ParseException( "Failed to read properties entry " + entryName, ioe );
        }
        finally
        {
            if ( entryStream != null )
            {
                try
                {
                    entryStream.close();
                }
                catch ( IOException ignore )
                {
                    // don't care
                }
            }
        }

        // create PropertyMetadata for the properties from the file
        for ( Iterator pi = props.entrySet().iterator(); pi.hasNext(); )
        {
            Map.Entry pEntry = ( Map.Entry ) pi.next();
            PropertyMetadata prop = new PropertyMetadata();
            prop.setName( String.valueOf( pEntry.getKey() ) );
            prop.setValue( String.valueOf( pEntry.getValue() ) );
            m_currentComponent.addProperty( prop );
        }
    }
}
