/*
 * 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.scrplugin.om;

import java.util.*;

import org.apache.felix.scrplugin.tags.*;
import org.apache.maven.plugin.MojoExecutionException;

/**
 * <code>Component</code>
 * is a described component.
 *
 */
public class Component extends AbstractObject {

    /** The name of the component. */
    protected String name;

    /** Is this component enabled? */
    protected Boolean enabled;

    /** Is this component immediately started. */
    protected Boolean immediate;

    /** The factory. */
    protected String factory;

    /** The implementation. */
    protected Implementation implementation;

    /** All properties. */
    protected List properties = new ArrayList();

    /** The corresponding service. */
    protected Service service;

    /** The references. */
    protected List references = new ArrayList();

    /** Is this an abstract description? */
    protected boolean isAbstract;

    /** Is this a descriptor to be ignored ? */
    protected boolean isDs;

    /**
     * Default constructor.
     */
    public Component() {
        this(null);
    }

    /**
     * Constructor from java source.
     */
    public Component(JavaTag t) {
        super(t);
    }

    /**
     * Return the associated java class description
     */
    public JavaClassDescription getJavaClassDescription() {
        if ( this.tag != null ) {
            return this.tag.getJavaClassDescription();
        }
        return null;
    }

    /**
     * @return All properties of this component.
     */
    public List getProperties() {
        return this.properties;
    }

    public void setProperties(List properties) {
        this.properties = properties;
    }

    public void addProperty(Property property) {
        this.properties.add(property);
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getFactory() {
        return this.factory;
    }

    public void setFactory(String factory) {
        this.factory = factory;
    }

    public Boolean isEnabled() {
        return this.enabled;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }

    public Boolean isImmediate() {
        return this.immediate;
    }

    public void setImmediate(Boolean immediate) {
        this.immediate = immediate;
    }

    public Implementation getImplementation() {
        return this.implementation;
    }

    public void setImplementation(Implementation implementation) {
        this.implementation = implementation;
    }

    public Service getService() {
        return this.service;
    }

    public void setService(Service service) {
        this.service = service;
    }

    public List getReferences() {
        return this.references;
    }

    public void setReferences(List references) {
        this.references = references;
    }

    public void addReference(Reference ref) {
        this.references.add(ref);
    }

    public boolean isAbstract() {
        return this.isAbstract;
    }

    public void setAbstract(boolean isAbstract) {
        this.isAbstract = isAbstract;
    }

    public boolean isDs() {
        return isDs;
    }

    public void setDs(boolean isDs) {
        this.isDs = isDs;
    }

    /**
     * Validate the component description.
     * If errors occur a message is added to the issues list,
     * warnings can be added to the warnings list.
     */
    public void validate(List issues, List warnings)
    throws MojoExecutionException {

        // nothing to check if this is ignored
        if (!isDs()) {
            return;
        }

        final JavaClassDescription javaClass = this.tag.getJavaClassDescription();
        if (javaClass == null) {
            issues.add(this.getMessage("Tag not declared in a Java Class"));
        } else {

            // if the service is abstract, we do not validate everything
            if ( !this.isAbstract ) {
                // ensure non-abstract, public class
                if (!javaClass.isPublic()) {
                    issues.add(this.getMessage("Class must be public: " + javaClass.getName()));
                }
                if (javaClass.isAbstract() || javaClass.isInterface()) {
                    issues.add(this.getMessage("Class must be concrete class (not abstract or interface) : " + javaClass.getName()));
                }

                // no errors so far, let's continue
                if ( issues.size() == 0 ) {
                    // check activate and deactivate methods
                    this.checkLifecycleMethod(javaClass, "activate", warnings);
                    this.checkLifecycleMethod(javaClass, "deactivate", warnings);

                    // ensure public default constructor
                    boolean constructorFound = true;
                    JavaMethod[] methods = javaClass.getMethods();
                    for (int i = 0; methods != null && i < methods.length; i++) {
                        if (methods[i].isConstructor()) {
                            // if public default, succeed
                            if (methods[i].isPublic()
                                && (methods[i].getParameters() == null || methods[i].getParameters().length == 0)) {
                                constructorFound = true;
                                break;
                            }

                            // non-public/non-default constructor found, must have explicit
                            constructorFound = false;
                        }
                    }
                    if (!constructorFound) {
                        issues.add(this.getMessage("Class must have public default constructor: " + javaClass.getName()));
                    }

                    // verify properties
                    for (Iterator pi = this.getProperties().iterator(); pi.hasNext();) {
                        Property prop = (Property) pi.next();
                        prop.validate(issues, warnings);
                    }

                    // verify service
                    boolean isServiceFactory = false;
                    if (this.getService() != null) {
                        if ( this.getService().getInterfaces().size() == 0 ) {
                            issues.add(this.getMessage("Service interface information is missing for @scr.service tag"));
                        }
                        this.getService().validate(issues, warnings);
                        isServiceFactory = Boolean.valueOf(this.getService().getServicefactory()).booleanValue();
                    }

                    // serviceFactory must not be true for immediate of component factory
                    if (isServiceFactory && this.isImmediate() != null && this.isImmediate().booleanValue() && this.getFactory() != null) {
                        issues.add(this.getMessage("Component must not be a ServiceFactory, if immediate and/or component factory: " + javaClass.getName()));
                    }

                    // verify references
                    for (Iterator ri = this.getReferences().iterator(); ri.hasNext();) {
                        final Reference ref = (Reference) ri.next();
                        ref.validate(issues, warnings);
                    }
                }
            }
        }
    }

    /**
     * Check for existence of lifecycle methods.
     * @param javaClass The java class to inspect.
     * @param methodName The method name.
     * @param warnings The list of warnings used to add new warnings.
     */
    protected void checkLifecycleMethod(JavaClassDescription javaClass, String methodName, List warnings)
    throws MojoExecutionException {
        final JavaMethod method = javaClass.getMethodBySignature(methodName, new String[] {"org.osgi.service.component.ComponentContext"});
        if ( method != null ) {
            // check protected
            if (method.isPublic()) {
                warnings.add(this.getMessage("Lifecycle method " + method.getName() + " should be declared protected"));
            } else if (!method.isProtected()) {
                warnings.add(this.getMessage("Lifecycle method " + method.getName() + " has wrong qualifier, public or protected required"));
            }
        } else {
            // if no method is found, we check for any method with that name
            final JavaMethod[] methods = javaClass.getMethods();
            for(int i=0; i<methods.length; i++) {
                if ( methodName.equals(methods[i].getName()) ) {

                    if ( methods[i].getParameters().length != 1 ) {
                        warnings.add(this.getMessage("Lifecycle method " + methods[i].getName() + " has wrong number of arguments"));
                    } else {
                        warnings.add(this.getMessage("Lifecycle method " + methods[i].getName() + " has wrong argument " + methods[i].getParameters()[0].getType()));
                    }
                }
            }
        }
    }
}
