/*
 * 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.dm.annotation.plugin.bnd;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.felix.dm.annotation.api.AdapterService;
import org.apache.felix.dm.annotation.api.AspectService;
import org.apache.felix.dm.annotation.api.BundleAdapterService;
import org.apache.felix.dm.annotation.api.BundleDependency;
import org.apache.felix.dm.annotation.api.Composition;
import org.apache.felix.dm.annotation.api.ConfigurationDependency;
import org.apache.felix.dm.annotation.api.Destroy;
import org.apache.felix.dm.annotation.api.Init;
import org.apache.felix.dm.annotation.api.ResourceAdapterService;
import org.apache.felix.dm.annotation.api.ResourceDependency;
import org.apache.felix.dm.annotation.api.Service;
import org.apache.felix.dm.annotation.api.ServiceDependency;
import org.apache.felix.dm.annotation.api.Start;
import org.apache.felix.dm.annotation.api.Stop;
import org.apache.felix.dm.annotation.api.TemporalServiceDependency;
import org.osgi.framework.Bundle;

import aQute.lib.osgi.Annotation;
import aQute.lib.osgi.ClassDataCollector;
import aQute.lib.osgi.Verifier;
import aQute.libg.reporter.Reporter;

/**
 * This is the scanner which does all the annotation parsing on a given class.
 * To start the parsing, just invoke the parseClassFileWithCollector and finish methods.
 * Once parsed, the corresponding component descriptors can be built using the "writeTo" method.
 */
public class AnnotationCollector extends ClassDataCollector
{
    private final static String A_INIT = "L" + Init.class.getName().replace('.', '/') + ";";
    private final static String A_START = "L" + Start.class.getName().replace('.', '/') + ";";
    private final static String A_STOP = "L" + Stop.class.getName().replace('.', '/') + ";";
    private final static String A_DESTROY = "L" + Destroy.class.getName().replace('.', '/') + ";";
    private final static String A_COMPOSITION = "L" + Composition.class.getName().replace('.', '/')
        + ";";
    private final static String A_SERVICE = "L" + Service.class.getName().replace('.', '/') + ";";
    private final static String A_SERVICE_DEP = "L"
        + ServiceDependency.class.getName().replace('.', '/') + ";";
    private final static String A_CONFIGURATION_DEPENDENCY = "L"
        + ConfigurationDependency.class.getName().replace('.', '/') + ";";
    private final static String A_TEMPORAL_SERVICE_DEPENDENCY = "L"
        + TemporalServiceDependency.class.getName().replace('.', '/') + ";";
    private final static String A_BUNDLE_DEPENDENCY = "L"
        + BundleDependency.class.getName().replace('.', '/') + ";";
    private final static String A_RESOURCE_DEPENDENCY = "L"
        + ResourceDependency.class.getName().replace('.', '/') + ";";
    private final static String A_ASPECT_SERVICE = "L"
        + AspectService.class.getName().replace('.', '/') + ";";
    private final static String A_ADAPTER_SERVICE = "L"
        + AdapterService.class.getName().replace('.', '/') + ";";
    private final static String A_BUNDLE_ADAPTER_SERVICE = "L"
        + BundleAdapterService.class.getName().replace('.', '/') + ";";
    private final static String A_RESOURCE_ADAPTER_SERVICE = "L"
        + ResourceAdapterService.class.getName().replace('.', '/') + ";";

    private Reporter m_reporter;
    private String m_className;
    private String[] m_interfaces;
    private boolean m_isField;
    private String m_field;
    private String m_method;
    private String m_descriptor;
    private Set<String> m_methods = new HashSet<String>();
    private List<Info> m_infos = new ArrayList<Info>(); // Last elem is either Service or AspectService
    private MetaType m_metaType;
    private String m_startMethod;
    private String m_stopMethod;
    private String m_initMethod;
    private String m_destroyMethod;
    private String m_compositionMethod;

    // Pattern used to parse the class parameter from the bind methods ("bind(Type)" or "bind(Map, Type)" or "bind(BundleContext, Type)"
    private final static Pattern m_bindClassPattern = Pattern.compile("\\((L[^;]+;)?L([^;]+);\\)V");

    // Pattern used to parse classes from class descriptors;
    private final static Pattern m_classPattern = Pattern.compile("L([^;]+);");

    // Pattern used to check if a method is void and does not take any params
    private final static Pattern m_voidMethodPattern = Pattern.compile("\\(\\)V");

    // Pattern used to check if a method returns an array of Objects
    private final static Pattern m_methodCompoPattern = Pattern.compile("\\(\\)\\[Ljava/lang/Object;");

    // List of component descriptor entry types
    enum EntryTypes
    {
        Service, 
        AspectService,
        AdapterService,
        BundleAdapterService,
        ResourceAdapterService,
        ServiceDependency, 
        TemporalServiceDependency, 
        ConfigurationDependency,
        BundleDependency,
        ResourceDependency
    };

    // List of component descriptor parameters
    enum Params
    {
        init, 
        start, 
        stop, 
        destroy, 
        impl, 
        provide, 
        properties, 
        factory, 
        factoryMethod, 
        composition, 
        service, 
        filter, 
        defaultImpl, 
        required, 
        added, 
        changed,
        removed,
        autoConfig, 
        pid, 
        propagate, 
        updated, 
        timeout,
        adapterService,
        adapterProperties,
        adapteeService,
        adapteeFilter,
        stateMask,
        ranking
    };

    /**
     * This class represents a parsed DependencyManager component descriptor entry.
     * (either a Service, a ServiceDependency, or a ConfigurationDependency descriptor entry).
     */
    private class Info
    {
        /** The component descriptor entry type: either Service, (Temporal)ServiceDependency, or ConfigurationDependency */
        EntryTypes m_entry;

        /** The component descriptor entry parameters (init/start/stop ...) */
        Map<Params, Object> m_params = new HashMap<Params, Object>();

        /**
         * Makes a new component descriptor entry.
         * @param entry the component descriptor entry type (either Service, ServiceDependency, or ConfigurationDependency)
         */
        Info(EntryTypes entry)
        {
            m_entry = entry;
        }

        /**
         * Returns a string representation for the given component descriptor line entry.
         */
        @Override
        public String toString()
        {
            StringBuilder sb = new StringBuilder();
            sb.append(m_entry);
            sb.append(":").append(" ");
            for (Map.Entry<Params, Object> e : m_params.entrySet())
            {
                sb.append(e.getKey());
                sb.append("=");
                sb.append(e.getValue());
                sb.append("; ");
            }
            return sb.toString();
        }

        /**
         * Adds a parameter to this component descriptor entry.
         * @param param the param name
         * @param value the param value
         */
        void addParam(Params param, String value)
        {
            String old = (String) m_params.get(param);
            if (old != null)
            {
                value = old + "," + value;
            }
            m_params.put(param, value);
        }

        /**
         * Adds an annotation parameter to this component descriptor entry.
         * @param annotation the annotation where the parameter has been parsed
         * @param param the param name
         * @param def the default value to add, if the param is not present in the parsed annotation.
         */
        void addParam(Annotation annotation, Params param, Object def)
        {
            Object value = annotation.get(param.toString());
            if (value == null && def != null)
            {
                value = def;
            }
            if (value != null)
            {
                if (value instanceof Object[])
                {
                    for (Object v : ((Object[]) value))
                    {
                        addParam(param, v.toString());
                    }
                }
                else
                {
                    addParam(param, value.toString());
                }
            }
        }

        /**
         * Adds a annotation parameter of type 'class' to this component descriptor entry.
         * The parsed class parameter has the format "Lfull.package.ClassName;"
         * @param annotation the annotation where the class parameter has been parsed
         * @param param the annotation class param name
         * @param def the default class name to add if the param is not present in the parsed annotation.
         */
        void addClassParam(Annotation annotation, Params param, Object def)
        {
            Pattern pattern = m_classPattern;
            Object value = annotation.get(param.toString());
            if (value == null && def != null)
            {
                value = def;
                pattern = null;
            }
            if (value != null)
            {
                if (value instanceof Object[])
                {
                    for (Object v : ((Object[]) value))
                    {
                        if (pattern != null)
                        {
                            v = parseClass(v.toString(), pattern, 1);
                        }
                        addParam(param, v.toString());
                    }
                }
                else
                {
                    if (pattern != null)
                    {
                        value = parseClass(value.toString(), pattern, 1);
                    }
                    addParam(param, value.toString());
                }
            }

        }
    }

    /**
     * Makes a new Collector for parsing a given class.
     * @param reporter the object used to report logs.
     */
    public AnnotationCollector(Reporter reporter, MetaType metaType)
    {
        m_reporter = reporter;
        m_metaType = metaType;
    }

    /**
     * Returns the log reporter.
     * @return the log reporter.
     */
    public Reporter getReporter()
    {
        return m_reporter;
    }

    /**
     * Parses the name of the class.
     * @param access the class access
     * @param name the class name (package are "/" separated).
     */
    @Override
    public void classBegin(int access, String name)
    {
        m_className = name.replace('/', '.');
        m_reporter.trace("class name: " + m_className);
    }

    /**
     * Parses the implemented interfaces ("/" separated).
     */
    @Override
    public void implementsInterfaces(String[] interfaces)
    {
        m_interfaces = new String[interfaces.length];
        for (int i = 0; i < interfaces.length; i++)
        {
            m_interfaces[i] = interfaces[i].replace('/', '.');
        }
        m_reporter.trace("implements: %s", Arrays.toString(m_interfaces));
    }

    /**
     * Parses a method. Always invoked BEFORE eventual method annotation.
     */
    @Override
    public void method(int access, String name, String descriptor)
    {
        m_reporter.trace("Parsed method %s, descriptor=%s", name, descriptor);
        m_isField = false;
        m_method = name;
        m_descriptor = descriptor;
        m_methods.add(name + descriptor);
    }

    /**
     * Parses a field. Always invoked BEFORE eventual field annotation
     */
    @Override
    public void field(int access, String name, String descriptor)
    {
        m_reporter.trace("Parsed field %s, descriptor=%s", name, descriptor);
        m_isField = true;
        m_field = name;
        m_descriptor = descriptor;
    }

    /** 
     * An annotation has been parsed. Always invoked AFTER the "method"/"field"/"classBegin" callbacks. 
     */
    @Override
    public void annotation(Annotation annotation)
    {
        m_reporter.trace("Parsed annotation: %s", annotation);
        
        if (annotation.getName().equals(A_SERVICE))
        {
            parseServiceAnnotation(annotation);
        } 
        else if (annotation.getName().equals(A_ASPECT_SERVICE))
        {
            parseAspectService(annotation);
        }
        else if (annotation.getName().equals(A_ADAPTER_SERVICE))
        {
            parseAdapterService(annotation);
        }
        else if (annotation.getName().equals(A_BUNDLE_ADAPTER_SERVICE))
        {
            parseBundleAdapterService(annotation);
        }
        else if (annotation.getName().equals(A_RESOURCE_ADAPTER_SERVICE))
        {
            parseResourceAdapterService(annotation);
        }
        else if (annotation.getName().equals(A_INIT))
        {
            checkMethod(m_voidMethodPattern);
            m_initMethod = m_method;
        }
        else if (annotation.getName().equals(A_START))
        {
            checkMethod(m_voidMethodPattern);
            m_startMethod = m_method;
        }
        else if (annotation.getName().equals(A_STOP))
        {
            checkMethod(m_voidMethodPattern);
            m_stopMethod = m_method;
        }
        else if (annotation.getName().equals(A_DESTROY))
        {
            checkMethod(m_voidMethodPattern);
            m_destroyMethod = m_method;
        }
        else if (annotation.getName().equals(A_COMPOSITION))
        {
            checkMethod(m_methodCompoPattern);
            m_compositionMethod = m_method;
        }
        else if (annotation.getName().equals(A_SERVICE_DEP))
        {
            parseServiceDependencyAnnotation(annotation, false);
        }
        else if (annotation.getName().equals(A_CONFIGURATION_DEPENDENCY))
        {
            parseConfigurationDependencyAnnotation(annotation);
        }
        else if (annotation.getName().equals(A_TEMPORAL_SERVICE_DEPENDENCY))
        {
            parseServiceDependencyAnnotation(annotation, true);
        } 
        else if (annotation.getName().equals(A_BUNDLE_DEPENDENCY)) 
        {
            parseBundleDependencyAnnotation(annotation);
        }
        else if (annotation.getName().equals(A_RESOURCE_DEPENDENCY)) 
        {
            parseRersourceDependencyAnnotation(annotation);
        }
    }

    /**
     * Parses a Service annotation.
     * @param annotation The Service annotation.
     */
    private void parseServiceAnnotation(Annotation annotation)
    {
        Info info = new Info(EntryTypes.Service);
        m_infos.add(info);

        // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
        addCommonServiceParams(info);
        
        // impl attribute
        info.addParam(Params.impl, m_className);

        // properties attribute
        parseParameters(annotation, Params.properties, info);

        // provide attribute
        info.addClassParam(annotation, Params.provide, m_interfaces);

        // factory attribute
        info.addClassParam(annotation, Params.factory, null);

        // factoryMethod attribute
        info.addParam(annotation, Params.factoryMethod, null);
    }

    private void addCommonServiceParams(Info info)
    {
        if (m_initMethod != null) {
            info.addParam(Params.init, m_initMethod);
        }
        
        if (m_startMethod != null) {
            info.addParam(Params.start, m_startMethod);
        }
        
        if (m_stopMethod != null) {
            info.addParam(Params.stop, m_stopMethod);
        }
        
        if (m_destroyMethod != null) {
            info.addParam(Params.destroy, m_destroyMethod);
        }
        
        // Register Composition method
        if (m_compositionMethod != null) {
            info.addParam(Params.composition, m_compositionMethod);
        }        
    }

    /**
     * Parses a ServiceDependency or a TemporalServiceDependency Annotation.
     * @param annotation the ServiceDependency Annotation.
     */
    private void parseServiceDependencyAnnotation(Annotation annotation, boolean temporal)
    {
        Info info = new Info(temporal ? EntryTypes.TemporalServiceDependency
            : EntryTypes.ServiceDependency);
        m_infos.add(info);

        // service attribute
        String service = annotation.get(Params.service.toString());
        if (service != null)
        {
            service = parseClass(service, m_classPattern, 1);
        }
        else
        {
            if (m_isField)
            {
                service = parseClass(m_descriptor, m_classPattern, 1);
            }
            else
            {
                service = parseClass(m_descriptor, m_bindClassPattern, 2);
            }
        }
        info.addParam(Params.service, service);

        // autoConfig attribute
        if (m_isField)
        {
            info.addParam(Params.autoConfig, m_field);
        }

        // filter attribute
        String filter = annotation.get(Params.filter.toString());
        if (filter != null)
        {
            Verifier.verifyFilter(filter, 0);
            info.addParam(Params.filter, filter);
        }

        // defaultImpl attribute
        info.addClassParam(annotation, Params.defaultImpl, null);

        // added callback
        info.addParam(annotation, Params.added, (!m_isField) ? m_method : null);

        if (temporal)
        {
            // timeout attribute (only valid if parsing a temporal service dependency)
            info.addParam(annotation, Params.timeout, null);
        }
        else
        {
            // required attribute (not valid if parsing a temporal service dependency)
            info.addParam(annotation, Params.required, null);

            // changed callback
            info.addParam(annotation, Params.changed, null);

            // removed callback
            info.addParam(annotation, Params.removed, null);
        }
    }

    /**
     * Parses a ConfigurationDependency annotation.
     * @param annotation the ConfigurationDependency annotation.
     */
    private void parseConfigurationDependencyAnnotation(Annotation annotation)
    {
        Info info = new Info(EntryTypes.ConfigurationDependency);
        m_infos.add(info);

        // pid attribute
        info.addParam(annotation, Params.pid, m_className);

        // propagate attribute
        info.addParam(annotation, Params.propagate, null);

        // Property Meta Types
        if (annotation.get("metadata") != null)
        {
            String propertiesPid = get(annotation, "pid", m_className);
            String propertiesHeading = annotation.get("heading");
            String propertiesDesc = annotation.get("description");

            MetaType.OCD ocd = new MetaType.OCD(propertiesPid, propertiesHeading, propertiesDesc);
            for (Object p : (Object[]) annotation.get("metadata"))
            {
                Annotation property = (Annotation) p;
                String heading = property.get("heading");
                String id = property.get("id");
                String type = (String) property.get("type");
                type = (type != null) ? parseClass(type, m_classPattern, 1) : null;
                Object[] defaults = (Object[]) property.get("defaults");
                String description = property.get("description");
                Integer cardinality = property.get("cardinality");
                Boolean required = property.get("required");

                MetaType.AD ad = new MetaType.AD(id, type, defaults, heading, description,
                    cardinality, required);
                Object[] options = property.get("options");
                if (options != null)
                {
                    for (Object o : (Object[]) property.get("options"))
                    {
                        Annotation option = (Annotation) o;
                        ad.add(new MetaType.Option((String) option.get("name"),
                            (String) option.get("value")));
                    }
                }
                ocd.add(ad);
            }

            m_metaType.add(ocd);
            MetaType.Designate designate = new MetaType.Designate(propertiesPid);
            m_metaType.add(designate);
            m_reporter.warning("Parsed MetaType Properties from class " + m_className);
        }
    }

    /**
     * Parses an AspectService annotation.
     * @param annotation
     */
    private void parseAspectService(Annotation annotation)
    {
        Info info = new Info(EntryTypes.AspectService);
        m_infos.add(info);        

        // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
        addCommonServiceParams(info);
        
        // factory attribute
        info.addClassParam(annotation, Params.factory, null);

        // factoryMethod attribute
        info.addParam(annotation, Params.factoryMethod, null);
        
        // Parse service filter
        String filter = annotation.get(Params.filter.toString());
        if (filter != null) {
            Verifier.verifyFilter(filter, 0);
            info.addParam(Params.filter, filter);
        }
        
        // Parse service aspect ranking
        Integer ranking = annotation.get(Params.ranking.toString());
        info.addParam(Params.ranking, ranking.toString());
                
        // Generate Aspect Implementation
        info.addParam(Params.impl, m_className);
        
        // Parse Aspect properties.
        parseParameters(annotation, Params.properties, info);
        
        // Parse service interface this aspect is applying to
        Object service = annotation.get(Params.service.toString());
        if (service == null) {
            if (m_interfaces == null)
            {
                throw new IllegalStateException("Invalid AspectService annotation: " +
                    "the service attribute has not been set and the class " + m_className + " does not implement any interfaces");
            }
            if (m_interfaces.length != 1) 
            {
                throw new IllegalStateException("Invalid AspectService annotation: " +
                    "the service attribute has not been set and the class " + m_className + " implements more than one interface");
            }
            
            info.addParam(Params.service, m_interfaces[0]);
        } else
        {
            checkClassImplements(annotation, Params.service);
            info.addClassParam(annotation, Params.service, null);
        }
    }

    /**
     * Parses an AspectService annotation.
     * @param annotation
     */
    private void parseAdapterService(Annotation annotation) 
    {
        Info info = new Info(EntryTypes.AdapterService);
        m_infos.add(info);
        
        // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
        addCommonServiceParams(info);
        
        // Generate Adapter Implementation
        info.addParam(Params.impl, m_className);
      
        // Parse adaptee filter
        String adapteeFilter = annotation.get(Params.adapteeFilter.toString());
        if (adapteeFilter != null)
        {
            Verifier.verifyFilter(adapteeFilter, 0);
            info.addParam(Params.adapteeFilter, adapteeFilter);
        }
        
        // Parse the mandatory adapted service interface.
        info.addClassParam(annotation, Params.adapteeService, null);
        
        // Parse Adapter properties.
        parseParameters(annotation, Params.adapterProperties, info);

        // Parse the optional adapter service (use directly implemented interface by default).
        Object adapterService = annotation.get(Params.adapterService.toString());
        if (adapterService == null) {
            if (m_interfaces == null)
            {
                throw new IllegalStateException("Invalid AdapterService annotation: " +
                    "the adapterService attribute has not been set and the class " + m_className + 
                    " does not implement any interfaces");
            }
            if (m_interfaces.length != 1) 
            {
                throw new IllegalStateException("Invalid AdapterService annotation: " +
                    "the adapterService attribute has not been set and the class " + m_className +
                    " implements more than one interface");
            }
            
            info.addParam(Params.adapterService, m_interfaces[0]);
        } else 
        {
            checkClassImplements(annotation, Params.adapterService);
            info.addClassParam(annotation, Params.adapterService, null);
        }
    }

    /**
     * Parses a BundleAdapterService annotation.
     * @param annotation
     */
    private void parseBundleAdapterService(Annotation annotation)
    {
        Info info = new Info(EntryTypes.BundleAdapterService);
        m_infos.add(info);
        
        // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
        addCommonServiceParams(info);
        
        // Generate Adapter Implementation
        info.addParam(Params.impl, m_className);
      
        // Parse bundle filter
        String filter = annotation.get(Params.filter.toString());
        if (filter != null)
        {
            Verifier.verifyFilter(filter, 0);
            info.addParam(Params.filter, filter);
        }
        
        // Parse stateMask attribute
        info.addParam(annotation, Params.stateMask, new Integer(Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE));
        
        // Parse Adapter properties.
        parseParameters(annotation, Params.properties, info);

        // Parse the optional adapter service (use directly implemented interface by default).
        Object service = annotation.get(Params.service.toString());
        if (service == null) {
            if (m_interfaces == null)
            {
                throw new IllegalStateException("Invalid BundleAdapterService annotation: " +
                    "the service attribute has not been set and the class " + m_className + 
                    " does not implement any interfaces");
            }
            if (m_interfaces.length != 1) 
            {
                throw new IllegalStateException("Invalid AdapterService annotation: " +
                    "the service attribute has not been set and the class " + m_className +
                    " implements more than one interface");
            }
            
            info.addParam(Params.service, m_interfaces[0]);
        } else 
        {
            checkClassImplements(annotation, Params.service);
            info.addClassParam(annotation, Params.service, null);
        }
        
        // Parse propagate attribute
        info.addParam(annotation, Params.propagate, Boolean.FALSE);
    }

    /**
     * Parses a BundleAdapterService annotation.
     * @param annotation
     */
    private void parseResourceAdapterService(Annotation annotation)
    {
        Info info = new Info(EntryTypes.ResourceAdapterService);
        m_infos.add(info);
        
        // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
        addCommonServiceParams(info);
        
        // Generate Adapter Implementation
        info.addParam(Params.impl, m_className);
      
        // Parse resource filter
        String filter = annotation.get(Params.filter.toString());
        if (filter != null)
        {
            Verifier.verifyFilter(filter, 0);
            info.addParam(Params.filter, filter);
        }
                
        // Parse Adapter properties.
        parseParameters(annotation, Params.properties, info);

        // Parse the optional adapter service (use directly implemented interface by default).
        Object service = annotation.get(Params.service.toString());
        if (service == null) {
            if (m_interfaces == null)
            {
                throw new IllegalStateException("Invalid ResourceAdapterService annotation: " +
                    "the service attribute has not been set and the class " + m_className + 
                    " does not implement any interfaces");
            }
            if (m_interfaces.length != 1) 
            {
                throw new IllegalStateException("Invalid ResourceAdapterService annotation: " +
                    "the service attribute has not been set and the class " + m_className +
                    " implements more than one interface");
            }
            
            info.addParam(Params.service, m_interfaces[0]);
        } else 
        {
            checkClassImplements(annotation, Params.service);
            info.addClassParam(annotation, Params.service, null);
        }
        
        // Parse propagate attribute
        info.addParam(annotation, Params.propagate, Boolean.FALSE);
    }

    private void parseBundleDependencyAnnotation(Annotation annotation)
    {
        Info info = new Info(EntryTypes.BundleDependency);
        m_infos.add(info);

        String filter = annotation.get(Params.filter.toString());
        if (filter != null)
        {
            Verifier.verifyFilter(filter, 0);
            info.addParam(Params.filter, filter);
        }

        info.addParam(annotation, Params.added, m_method);
        info.addParam(annotation, Params.changed, null); // TODO check if "changed" callback exists
        info.addParam(annotation, Params.removed, null); // TODO check if "removed" callback exists
        info.addParam(annotation, Params.required, null);
        info.addParam(annotation, Params.stateMask, null);
        info.addParam(annotation, Params.propagate, null);
    }
    
    private void parseRersourceDependencyAnnotation(Annotation annotation)
    {
        Info info = new Info(EntryTypes.ResourceDependency);
        m_infos.add(info);

        String filter = annotation.get(Params.filter.toString());
        if (filter != null)
        {
            Verifier.verifyFilter(filter, 0);
            info.addParam(Params.filter, filter);
        }

        info.addParam(annotation, Params.added, m_method);
        info.addParam(annotation, Params.changed, null); // TODO check if "changed" callback exists
        info.addParam(annotation, Params.removed, null); // TODO check if "removed" callback exists
        info.addParam(annotation, Params.required, null);
        info.addParam(annotation, Params.propagate, null);        
    }

    /**
     * Checks if an annotation attribute references an implemented interface. 
     * @param annotation the parsed annotation
     * @param attribute an annotation attribute that references an interface this class must
     * implement.
     */
    private void checkClassImplements(Annotation annotation, Params attribute)
    {
        String iface = annotation.get(attribute.toString());
        iface = parseClass(iface, m_classPattern, 1);
        
        if (m_interfaces != null)
        {
            for (String implemented : m_interfaces)
            {
                if (implemented.equals(iface))
                {
                    return;
                }
            }
        }

        throw new IllegalArgumentException("Class " + m_className + " does not implement the "
            + iface + " interface.");
    }
    
    /**
     * Parses a Param annotation (which represents a list of key-value pari).
     * @param annotation the annotation where the Param annotation is defined
     * @param attribute the attribute name which is of Param type
     * @param info the Info object where the parsed attributes are written
     */
    private void parseParameters(Annotation annotation, Params attribute, Info info) {
        Object[] parameters = annotation.get(attribute.toString());
        if (parameters != null)
        {
            for (Object p : parameters)
            {
                Annotation a = (Annotation) p; 
                String prop = a.get("name") + ":" + a.get("value");
                info.addParam(attribute, prop);
            }
        }
    }
    
    /**
     * Parses a class.
     * @param clazz the class to be parsed (the package is "/" separated).
     * @param pattern the pattern used to match the class.
     * @param group the pattern group index where the class can be retrieved.
     * @return the parsed class.
     */
    private String parseClass(String clazz, Pattern pattern, int group)
    {
        Matcher matcher = pattern.matcher(clazz);
        if (matcher.matches())
        {
            return matcher.group(group).replace("/", ".");
        }
        else
        {
            m_reporter.warning("Invalid class descriptor: %s", clazz);
            throw new IllegalArgumentException("Invalid class descriptor: " + clazz);
        }
    }

    /**
     * Checks if a method descriptor matches a given pattern. 
     * @param pattern the pattern used to check the method signature descriptor
     * @throws IllegalArgumentException if the method signature descriptor does not match the given pattern.
     */
    private void checkMethod(Pattern pattern)
    {
        Matcher matcher = pattern.matcher(m_descriptor);
        if (!matcher.matches())
        {
            m_reporter.warning("Invalid method %s : wrong signature: %s", m_method, m_descriptor);
            throw new IllegalArgumentException("Invalid method " + m_method + ", wrong signature: "
                + m_descriptor);
        }
    }
    
    /**
     * Checks if the class is annotated with some given annotations. Notice that the Service
     * is always parsed at end of parsing, so, we have to check the last element of our m_infos
     * List.
     * @return true if one of the provided annotations has been found from the parsed class.
     */
    private void checkServiceDeclared(EntryTypes ... types) {
        boolean ok = false;
        if (m_infos.size() > 0)
        {
            for (EntryTypes type : types)
            {
                if (m_infos.get(m_infos.size() - 1).m_entry == type)
                {
                    ok = true;
                    break;
                }
            }
        }

        if (!ok)
        {
            throw new IllegalStateException(
                ": the class must be annotated with either one of the following types: "
                    + Arrays.toString(types));
        }
    }

    /**
     * Get an annotation attribute, and return a default value if its not present.
     * @param <T> the type of the variable which is assigned to the return value of this method.
     * @param properties The annotation we are parsing
     * @param name the attribute name to get from the annotation
     * @param defaultValue the default value to return if the attribute is not found in the annotation
     * @return the annotation attribute value, or the defaultValue if not found
     */
    private <T> T get(Annotation properties, String name, T defaultValue)
    {
        T value = (T) properties.get(name);
        return value != null ? value : defaultValue;
    }

    /**
     * Finishes up the class parsing. This method must be called once the parseClassFileWithCollector method has returned.
     * @return true if some annotations have been parsed, false if not.
     */
    public boolean finish()
    {
        if (m_infos.size() == 0)
        {
            return false;
        }

        // We must have at least a Service or an AspectService annotation.
        checkServiceDeclared(EntryTypes.Service, EntryTypes.AspectService, EntryTypes.AdapterService, EntryTypes.BundleAdapterService,
            EntryTypes.ResourceAdapterService);

        StringBuilder sb = new StringBuilder();
        sb.append("Parsed annotation for class ");
        sb.append(m_className);
        for (int i = m_infos.size() - 1; i >= 0; i--)
        {
            sb.append("\n\t").append(m_infos.get(i).toString());
        }
        m_reporter.warning(sb.toString());
        return true;
    }

    /**
     * Writes the generated component descriptor in the given print writer.
     * The first line must be the service (@Service or AspectService).
     * @param pw the writer where the component descriptor will be written.
     */
    public void writeTo(PrintWriter pw)
    {
        // The last element our our m_infos list contains either the Service, or the AspectService descriptor.
        for (int i = m_infos.size() - 1; i >= 0; i--)
        {
            pw.println(m_infos.get(i).toString());
        }
    }
}
