/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed 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 android.signature.cts;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Represents class descriptions loaded from a jdiff xml file.  Used
 * for CTS SignatureTests.
 */
public class JDiffClassDescription {
    /** Indicates that the class is an annotation. */
    private static final int CLASS_MODIFIER_ANNOTATION = 0x00002000;
    /** Indicates that the class is an enum. */
    private static final int CLASS_MODIFIER_ENUM       = 0x00004000;

    /** Indicates that the method is a bridge method. */
    private static final int METHOD_MODIFIER_BRIDGE    = 0x00000040;
    /** Indicates that the method is takes a variable number of arguments. */
    private static final int METHOD_MODIFIER_VAR_ARGS  = 0x00000080;
    /** Indicates that the method is a synthetic method. */
    private static final int METHOD_MODIFIER_SYNTHETIC = 0x00001000;

    public enum JDiffType {
        INTERFACE, CLASS
    }

    @SuppressWarnings("unchecked")
    private Class<?> mClass;
    // A map of field name to field of the fields contained in {@code mClass}
    private Map<String, Field> mClassFieldMap;

    private String mPackageName;
    private String mShortClassName;

    /**
     * Package name + short class name
     */
    private String mAbsoluteClassName;

    private int mModifier;

    private String mExtendedClass;
    private List<String> implInterfaces = new ArrayList<String>();
    private List<JDiffField> jDiffFields = new ArrayList<JDiffField>();
    private List<JDiffMethod> jDiffMethods = new ArrayList<JDiffMethod>();
    private List<JDiffConstructor> jDiffConstructors = new ArrayList<JDiffConstructor>();

    private ResultObserver mResultObserver;
    private JDiffType mClassType;

    /**
     * Creates a new JDiffClassDescription.
     *
     * @param pkg the java package this class will end up in.
     * @param className the name of the class.
     */
    public JDiffClassDescription(String pkg, String className) {
        this(pkg, className, new ResultObserver() {
            @Override
            public void notifyFailure(FailureType type, String name, String errorMessage) {
                // This is a null result observer that doesn't do anything.
            }
        });
    }

    /**
     * Creates a new JDiffClassDescription with the specified results
     * observer.
     *
     * @param pkg the java package this class belongs in.
     * @param className the name of the class.
     * @param resultObserver the resultObserver to get results with.
     */
    public JDiffClassDescription(String pkg, String className, ResultObserver resultObserver) {
        mPackageName = pkg;
        mShortClassName = className;
        mResultObserver = resultObserver;
    }

    /**
     * adds implemented interface name.
     *
     * @param iname name of interface
     */
    public void addImplInterface(String iname) {
        implInterfaces.add(iname);
    }

    /**
     * Adds a field.
     *
     * @param field the field to be added.
     */
    public void addField(JDiffField field) {
        jDiffFields.add(field);
    }

    /**
     * Adds a method.
     *
     * @param method the method to be added.
     */
    public void addMethod(JDiffMethod method) {
        jDiffMethods.add(method);
    }

    /**
     * Adds a constructor.
     *
     * @param tc the constructor to be added.
     */
    public void addConstructor(JDiffConstructor tc) {
        jDiffConstructors.add(tc);
    }

    static String convertModifiersToAccessLevel(int modifiers) {
        if ((modifiers & Modifier.PUBLIC) != 0) {
            return "public";
        } else if ((modifiers & Modifier.PRIVATE) != 0) {
            return "private";
        } else if ((modifiers & Modifier.PROTECTED) != 0) {
            return "protected";
        } else {
            // package protected
            return "";
        }
    }

    static String convertModifersToModifierString(int modifiers) {
        StringBuffer sb = new StringBuffer();
        boolean isFirst = true;

        // order taken from Java Language Spec, sections 8.1.1, 8.3.1, and 8.4.3
        if ((modifiers & Modifier.ABSTRACT) != 0) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(" ");
            }
            sb.append("abstract");
        }
        if ((modifiers & Modifier.STATIC) != 0) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(" ");
            }
            sb.append("static");
        }
        if ((modifiers & Modifier.FINAL) != 0) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(" ");
            }
            sb.append("final");
        }
        if ((modifiers & Modifier.TRANSIENT) != 0) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(" ");
            }
            sb.append("transient");
        }
        if ((modifiers & Modifier.VOLATILE) != 0) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(" ");
            }
            sb.append("volatile");
        }
        if ((modifiers & Modifier.SYNCHRONIZED) != 0) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(" ");
            }
            sb.append("synchronized");
        }
        if ((modifiers & Modifier.NATIVE) != 0) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(" ");
            }
            sb.append("native");
        }
        if ((modifiers & Modifier.STRICT) != 0) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append(" ");
            }
            sb.append("strictfp");
        }

        return sb.toString();
    }

    public abstract static class JDiffElement {
        final String mName;
        int mModifier;

        public JDiffElement(String name, int modifier) {
            mName = name;
            mModifier = modifier;
        }
    }

    /**
     * Represents a  field.
     */
    public static final class JDiffField extends JDiffElement {
        private String mFieldType;

        public JDiffField(String name, String fieldType, int modifier) {
            super(name, modifier);

            mFieldType = fieldType;
        }

        /**
         * Make a readable string according to the class name specified.
         *
         * @param className The specified class name.
         * @return A readable string to represent this field along with the class name.
         */
        public String toReadableString(String className) {
            return className + "#" + mName + "(" + mFieldType + ")";
        }

        public String toSignatureString() {
            StringBuffer sb = new StringBuffer();

            // access level
            String accesLevel = convertModifiersToAccessLevel(mModifier);
            if (!"".equals(accesLevel)) {
                sb.append(accesLevel).append(" ");
            }

            String modifierString = convertModifersToModifierString(mModifier);
            if (!"".equals(modifierString)) {
                sb.append(modifierString).append(" ");
            }

            sb.append(mFieldType).append(" ");

            sb.append(mName);

            return sb.toString();
        }
    }

    /**
     * Represents a method.
     */
    public static class JDiffMethod extends JDiffElement {
        protected String mReturnType;
        protected ArrayList<String> mParamList;
        protected ArrayList<String> mExceptionList;

        public JDiffMethod(String name, int modifier, String returnType) {
            super(name, modifier);

            if (returnType == null) {
                mReturnType = "void";
            } else {
                mReturnType = scrubJdiffParamType(returnType);
            }

            mParamList = new ArrayList<String>();
            mExceptionList = new ArrayList<String>();
        }

        /**
         * Adds a parameter.
         *
         * @param param parameter type
         */
        public void addParam(String param) {
            mParamList.add(scrubJdiffParamType(param));
        }

        /**
         * Adds an exception.
         *
         * @param exceptionName name of exception
         */
        public void addException(String exceptionName) {
            mExceptionList.add(exceptionName);
        }

        /**
         * Makes a readable string according to the class name specified.
         *
         * @param className The specified class name.
         * @return A readable string to represent this method along with the class name.
         */
        public String toReadableString(String className) {
            return className + "#" + mName + "(" + convertParamList(mParamList) + ")";
        }

        /**
         * Converts a parameter array to a string
         *
         * @param params the array to convert
         * @return converted parameter string
         */
        private static String convertParamList(final ArrayList<String> params) {

            StringBuffer paramList = new StringBuffer();

            if (params != null) {
                for (String str : params) {
                    paramList.append(str + ", ");
                }
                if (params.size() > 0) {
                    paramList.delete(paramList.length() - 2, paramList.length());
                }
            }

            return paramList.toString();
        }

        public String toSignatureString() {
            StringBuffer sb = new StringBuffer();

            // access level
            String accesLevel = convertModifiersToAccessLevel(mModifier);
            if (!"".equals(accesLevel)) {
                sb.append(accesLevel).append(" ");
            }

            String modifierString = convertModifersToModifierString(mModifier);
            if (!"".equals(modifierString)) {
                sb.append(modifierString).append(" ");
            }

            String returnType = getReturnType();
            if (!"".equals(returnType)) {
                sb.append(returnType).append(" ");
            }

            sb.append(mName);
            sb.append("(");
            for (int x = 0; x < mParamList.size(); x++) {
                sb.append(mParamList.get(x));
                if (x + 1 != mParamList.size()) {
                    sb.append(", ");
                }
            }
            sb.append(")");

            // does it throw?
            if (mExceptionList.size() > 0) {
                sb.append(" throws ");
                for (int x = 0; x < mExceptionList.size(); x++) {
                    sb.append(mExceptionList.get(x));
                    if (x + 1 != mExceptionList.size()) {
                        sb.append(", ");
                    }
                }
            }

            return sb.toString();
        }

        /**
         * Gets the return type.
         *
         * @return the return type of this method.
         */
        protected String getReturnType() {
            return mReturnType;
        }
    }

    /**
     * Represents a constructor.
     */
    public static final class JDiffConstructor extends JDiffMethod {
        public JDiffConstructor(String name, int modifier) {
            super(name, modifier, null);
        }

        public JDiffConstructor(String name, String[] param, int modifier) {
            super(name, modifier, null);

            for (int i = 0; i < param.length; i++) {
                addParam(param[i]);
            }
        }

        /**
         * Gets the return type.
         *
         * @return the return type of this method.
         */
        @Override
        protected String getReturnType() {
            // Constructors have no return type.
            return "";
        }
    }

    /**
     * Checks test class's name, modifier, fields, constructors, and
     * methods.
     */
    public void checkSignatureCompliance() {
        checkClassCompliance();
        if (mClass != null) {
            mClassFieldMap = buildFieldMap(mClass);
            checkFieldsCompliance();
            checkConstructorCompliance();
            checkMethodCompliance();
        } else {
            mClassFieldMap = null;
        }
    }

    /**
     * Checks to ensure that the modifiers value for two methods are
     * compatible.
     *
     * Allowable differences are:
     *   - synchronized is allowed to be removed from an apiMethod
     *     that has it
     *   - the native modified is ignored
     *
     * @param apiMethod the method read from the api file.
     * @param reflectedMethod the method found via reflections.
     */
    private boolean areMethodModifiedCompatibile(JDiffMethod apiMethod ,
            Method reflectedMethod) {

        // If the apiMethod isn't synchronized
        if (((apiMethod.mModifier & Modifier.SYNCHRONIZED) == 0) &&
                // but the reflected method is
                ((reflectedMethod.getModifiers() & Modifier.SYNCHRONIZED) != 0)) {
            // that is a problem
            return false;
        }

        // Mask off NATIVE since it is a don't care.  Also mask off
        // SYNCHRONIZED since we've already handled that check.
        int mod1 = reflectedMethod.getModifiers() & ~(Modifier.NATIVE | Modifier.SYNCHRONIZED);
        int mod2 = apiMethod.mModifier & ~(Modifier.NATIVE | Modifier.SYNCHRONIZED);

        // We can ignore FINAL for final classes
        if ((mModifier & Modifier.FINAL) != 0) {
            mod1 &= ~Modifier.FINAL;
            mod2 &= ~Modifier.FINAL;
        }

        return mod1 == mod2;
    }

    /**
     * Checks that the method found through reflection matches the
     * specification from the API xml file.
     */
    private void checkMethodCompliance() {
        for (JDiffMethod method : jDiffMethods) {
            try {
                // this is because jdiff think a method in an interface is not abstract
                if (JDiffType.INTERFACE.equals(mClassType)) {
                    method.mModifier |= Modifier.ABSTRACT;
                }

                Method m = findMatchingMethod(method);
                if (m == null) {
                    mResultObserver.notifyFailure(FailureType.MISSING_METHOD,
                            method.toReadableString(mAbsoluteClassName),
                            "No method with correct signature found:" +
                            method.toSignatureString());
                } else {
                    if (m.isVarArgs()) {
                        method.mModifier |= METHOD_MODIFIER_VAR_ARGS;
                    }
                    if (m.isBridge()) {
                        method.mModifier |= METHOD_MODIFIER_BRIDGE;
                    }
                    if (m.isSynthetic()) {
                        method.mModifier |= METHOD_MODIFIER_SYNTHETIC;
                    }

                    // FIXME: A workaround to fix the final mismatch on enumeration
                    if (mClass.isEnum() && method.mName.equals("values")) {
                        return;
                    }

                    if (!areMethodModifiedCompatibile(method, m)) {
                        mResultObserver.notifyFailure(FailureType.MISMATCH_METHOD,
                                method.toReadableString(mAbsoluteClassName),
                                "Non-compatible method found when looking for " +
                                method.toSignatureString());
                    }
                }
            } catch (Exception e) {
                loge("Got exception when checking method compliance", e);
                mResultObserver.notifyFailure(FailureType.CAUGHT_EXCEPTION,
                        method.toReadableString(mAbsoluteClassName),
                "Exception!");
            }
        }
    }

    /**
     * Checks if the two types of methods are the same.
     *
     * @param jDiffMethod the jDiffMethod to compare
     * @param method the reflected method to compare
     * @return true, if both methods are the same
     */
    private boolean matches(JDiffMethod jDiffMethod, Method method) {
        // If the method names aren't equal, the methods can't match.
        if (jDiffMethod.mName.equals(method.getName())) {
            String jdiffReturnType = jDiffMethod.mReturnType;
            String reflectionReturnType = typeToString(method.getGenericReturnType());
            List<String> jdiffParamList = jDiffMethod.mParamList;

            // Next, compare the return types of the two methods.  If
            // they aren't equal, the methods can't match.
            if (jdiffReturnType.equals(reflectionReturnType)) {
                Type[] params = method.getGenericParameterTypes();
                // Next, check the method parameters.  If they have
                // different number of parameters, the two methods
                // can't match.
                if (jdiffParamList.size() == params.length) {
                    // If any of the parameters don't match, the
                    // methods can't match.
                    for (int i = 0; i < jdiffParamList.size(); i++) {
                        if (!compareParam(jdiffParamList.get(i), params[i])) {
                            return false;
                        }
                    }
                    // We've passed all the tests, the methods do
                    // match.
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Finds the reflected method specified by the method description.
     *
     * @param method description of the method to find
     * @return the reflected method, or null if not found.
     */
    @SuppressWarnings("unchecked")
    private Method findMatchingMethod(JDiffMethod method) {
        Method[] methods = mClass.getDeclaredMethods();

        for (Method m : methods) {
            if (matches(method, m)) {
                return m;
            }
        }

        return null;
    }

    /**
     * Compares the parameter from the API and the parameter from
     * reflection.
     *
     * @param jdiffParam param parsed from the API xml file.
     * @param reflectionParamType param gotten from the Java reflection.
     * @return True if the two params match, otherwise return false.
     */
    private static boolean compareParam(String jdiffParam, Type reflectionParamType) {
        if (jdiffParam == null) {
            return false;
        }

        String reflectionParam = typeToString(reflectionParamType);
        // Most things aren't varargs, so just do a simple compare
        // first.
        if (jdiffParam.equals(reflectionParam)) {
            return true;
        }

        // Check for varargs.  jdiff reports varargs as ..., while
        // reflection reports them as []
        int jdiffParamEndOffset = jdiffParam.indexOf("...");
        int reflectionParamEndOffset = reflectionParam.indexOf("[]");
        if (jdiffParamEndOffset != -1 && reflectionParamEndOffset != -1) {
            jdiffParam = jdiffParam.substring(0, jdiffParamEndOffset);
            reflectionParam = reflectionParam.substring(0, reflectionParamEndOffset);
            return jdiffParam.equals(reflectionParam);
        }

        return false;
    }

    /**
     * Checks whether the constructor parsed from API xml file and
     * Java reflection are compliant.
     */
    @SuppressWarnings("unchecked")
    private void checkConstructorCompliance() {
        for (JDiffConstructor con : jDiffConstructors) {
            try {
                Constructor<?> c = findMatchingConstructor(con);
                if (c == null) {
                    mResultObserver.notifyFailure(FailureType.MISSING_METHOD,
                            con.toReadableString(mAbsoluteClassName),
                            "No method with correct signature found:" +
                            con.toSignatureString());
                } else {
                    if (c.isVarArgs()) {// some method's parameter are variable args
                        con.mModifier |= METHOD_MODIFIER_VAR_ARGS;
                    }
                    if (c.getModifiers() != con.mModifier) {
                        mResultObserver.notifyFailure(
                                FailureType.MISMATCH_METHOD,
                                con.toReadableString(mAbsoluteClassName),
                                "Non-compatible method found when looking for " +
                                con.toSignatureString());
                    }
                }
            } catch (Exception e) {
                loge("Got exception when checking constructor compliance", e);
                mResultObserver.notifyFailure(FailureType.CAUGHT_EXCEPTION,
                        con.toReadableString(mAbsoluteClassName),
                "Exception!");
            }
        }
    }

    /**
     * Searches available constructor.
     *
     * @param jdiffDes constructor description to find.
     * @return reflected constructor, or null if not found.
     */
    @SuppressWarnings("unchecked")
    private Constructor<?> findMatchingConstructor(JDiffConstructor jdiffDes) {
        for (Constructor<?> c : mClass.getDeclaredConstructors()) {
            Type[] params = c.getGenericParameterTypes();
            boolean isStaticClass = ((mClass.getModifiers() & Modifier.STATIC) != 0);

            int startParamOffset = 0;
            int numberOfParams = params.length;

            // non-static inner class -> skip implicit parent pointer
            // as first arg
            if (mClass.isMemberClass() && !isStaticClass && params.length >= 1) {
                startParamOffset = 1;
                --numberOfParams;
            }

            ArrayList<String> jdiffParamList = jdiffDes.mParamList;
            if (jdiffParamList.size() == numberOfParams) {
                boolean isFound = true;
                // i counts jdiff params, j counts reflected params
                int i = 0;
                int j = startParamOffset;
                while (i < jdiffParamList.size()) {
                    if (!compareParam(jdiffParamList.get(i), params[j])) {
                        isFound = false;
                        break;
                    }
                    ++i;
                    ++j;
                }
                if (isFound) {
                    return c;
                }
            }
        }
        return null;
    }

    /**
     * Checks all fields in test class for compliance with the API
     * xml.
     */
    @SuppressWarnings("unchecked")
    private void checkFieldsCompliance() {
        for (JDiffField field : jDiffFields) {
            try {
                Field f = findMatchingField(field);
                if (f == null) {
                    mResultObserver.notifyFailure(FailureType.MISSING_FIELD,
                            field.toReadableString(mAbsoluteClassName),
                            "No field with correct signature found:" +
                            field.toSignatureString());
                } else if (f.getModifiers() != field.mModifier) {
                    mResultObserver.notifyFailure(FailureType.MISMATCH_FIELD,
                            field.toReadableString(mAbsoluteClassName),
                            "Non-compatible field modifiers found when looking for " +
                            field.toSignatureString());
                } else if (!f.getType().getCanonicalName().equals(field.mFieldType)) {
                    // type name does not match, but this might be a generic
                    String genericTypeName = null;
                    Type type = f.getGenericType();
                    if (type != null) {
                        genericTypeName = type instanceof Class ? ((Class) type).getName() :
                            type.toString().replace('$', '.');
                    }
                    if (genericTypeName == null || !genericTypeName.equals(field.mFieldType)) {
                        mResultObserver.notifyFailure(
                                FailureType.MISMATCH_FIELD,
                                field.toReadableString(mAbsoluteClassName),
                                "Non-compatible field type found when looking for " +
                                field.toSignatureString());
                    }
                }

            } catch (Exception e) {
                loge("Got exception when checking field compliance", e);
                mResultObserver.notifyFailure(
                        FailureType.CAUGHT_EXCEPTION,
                        field.toReadableString(mAbsoluteClassName),
                        "Exception!");
            }
        }
    }

    /**
     * Finds the reflected field specified by the field description.
     *
     * @param field the field description to find
     * @return the reflected field, or null if not found.
     */
    private Field findMatchingField(JDiffField field) {
        return mClassFieldMap.get(field.mName);
    }

    /**
     * Checks if the class under test has compliant modifiers compared to the API.
     *
     * @return true if modifiers are compliant.
     */
    private boolean checkClassModifiersCompliance() {
        int reflectionModifier = mClass.getModifiers();
        int apiModifier = mModifier;

        // If the api class isn't abstract
        if (((apiModifier & Modifier.ABSTRACT) == 0) &&
                // but the reflected class is
                ((reflectionModifier & Modifier.ABSTRACT) != 0) &&
                // and it isn't an enum
                !isEnumType()) {
            // that is a problem
            return false;
        }
        // ABSTRACT check passed, so mask off ABSTRACT
        reflectionModifier &= ~Modifier.ABSTRACT;
        apiModifier &= ~Modifier.ABSTRACT;

        if (isAnnotation()) {
            reflectionModifier &= ~CLASS_MODIFIER_ANNOTATION;
        }
        if (mClass.isInterface()) {
            reflectionModifier &= ~(Modifier.INTERFACE);
        }
        if (isEnumType() && mClass.isEnum()) {
            reflectionModifier &= ~CLASS_MODIFIER_ENUM;
        }

        return ((reflectionModifier == apiModifier) &&
                (isEnumType() == mClass.isEnum()));
    }

    /**
     * Checks if the class under test is compliant with regards to
     * annnotations when compared to the API.
     *
     * @return true if the class is compliant
     */
    private boolean checkClassAnnotationCompliace() {
        if (mClass.isAnnotation()) {
            // check annotation
            for (String inter : implInterfaces) {
                if ("java.lang.annotation.Annotation".equals(inter)) {
                    return true;
                }
            }
            return false;
        }
        return true;
    }

    /**
     * Checks if the class under test extends the proper classes
     * according to the API.
     *
     * @return true if the class is compliant.
     */
    private boolean checkClassExtendsCompliance() {
        // Nothing to check if it doesn't extend anything.
        if (mExtendedClass != null) {
            Class<?> superClass = mClass.getSuperclass();

            while (superClass != null) {
                if (superClass.getCanonicalName().equals(mExtendedClass)) {
                    return true;
                }
                superClass = superClass.getSuperclass();
            }
            // Couldn't find a matching superclass.
            return false;
        }
        return true;
    }

    /**
     * Checks if the class under test implements the proper interfaces
     * according to the API.
     *
     * @return true if the class is compliant
     */
    private boolean checkClassImplementsCompliance() {
        Class<?>[] interfaces = mClass.getInterfaces();
        Set<String> interFaceSet = new HashSet<String>();

        for (Class<?> c : interfaces) {
            interFaceSet.add(c.getCanonicalName());
        }

        for (String inter : implInterfaces) {
            if (!interFaceSet.contains(inter)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Checks that the class found through reflection matches the
     * specification from the API xml file.
     */
    @SuppressWarnings("unchecked")
    private void checkClassCompliance() {
        try {
            mAbsoluteClassName = mPackageName + "." + mShortClassName;
            mClass = findMatchingClass();

            if (mClass == null) {
                // No class found, notify the observer according to the class type
                if (JDiffType.INTERFACE.equals(mClassType)) {
                    mResultObserver.notifyFailure(FailureType.MISSING_INTERFACE,
                            mAbsoluteClassName,
                            "Classloader is unable to find " + mAbsoluteClassName);
                } else {
                    mResultObserver.notifyFailure(FailureType.MISSING_CLASS,
                            mAbsoluteClassName,
                            "Classloader is unable to find " + mAbsoluteClassName);
                }

                return;
            }
            if (!checkClassModifiersCompliance()) {
                logMismatchInterfaceSignature(mAbsoluteClassName,
                        "Non-compatible class found when looking for " +
                        toSignatureString());
                return;
            }

            if (!checkClassAnnotationCompliace()) {
                logMismatchInterfaceSignature(mAbsoluteClassName,
                "Annotation mismatch");
                return;
            }

            if (!mClass.isAnnotation()) {
                // check father class
                if (!checkClassExtendsCompliance()) {
                    logMismatchInterfaceSignature(mAbsoluteClassName,
                    "Extends mismatch");
                    return;
                }

                // check implements interface
                if (!checkClassImplementsCompliance()) {
                    logMismatchInterfaceSignature(mAbsoluteClassName,
                    "Implements mismatch");
                    return;
                }
            }
        } catch (Exception e) {
            loge("Got exception when checking field compliance", e);
            mResultObserver.notifyFailure(
                    FailureType.CAUGHT_EXCEPTION,
                    mAbsoluteClassName,
                    "Exception!");
        }
    }


    /**
     * Convert the class into a printable signature string.
     *
     * @return the signature string
     */
    public String toSignatureString() {
        StringBuffer sb = new StringBuffer();

        String accessLevel = convertModifiersToAccessLevel(mModifier);
        if (!"".equals(accessLevel)) {
            sb.append(accessLevel).append(" ");
        }
        if (!JDiffType.INTERFACE.equals(mClassType)) {
            String modifierString = convertModifersToModifierString(mModifier);
            if (!"".equals(modifierString)) {
                sb.append(modifierString).append(" ");
            }
            sb.append("class ");
        } else {
            sb.append("interface ");
        }
        // class name
        sb.append(mShortClassName);

        // does it extends something?
        if (mExtendedClass != null) {
            sb.append(" extends ").append(mExtendedClass).append(" ");
        }

        // implements something?
        if (implInterfaces.size() > 0) {
            sb.append(" implements ");
            for (int x = 0; x < implInterfaces.size(); x++) {
                String interf = implInterfaces.get(x);
                sb.append(interf);
                // if not last elements
                if (x + 1 != implInterfaces.size()) {
                    sb.append(", ");
                }
            }
        }
        return sb.toString();
    }

    private void logMismatchInterfaceSignature(String classFullName, String errorMessage) {
        if (JDiffType.INTERFACE.equals(mClassType)) {
            mResultObserver.notifyFailure(FailureType.MISMATCH_INTERFACE,
                    classFullName,
                    errorMessage);
        } else {
            mResultObserver.notifyFailure(FailureType.MISMATCH_CLASS,
                    classFullName,
                    errorMessage);
        }
    }

    /**
     * Sees if the class under test is actually an enum.
     *
     * @return true if this class is enum
     */
    private boolean isEnumType() {
        return "java.lang.Enum".equals(mExtendedClass);
    }

    /**
     * Finds the reflected class for the class under test.
     *
     * @return the reflected class, or null if not found.
     */
    @SuppressWarnings("unchecked")
    private Class<?> findMatchingClass() {
        // even if there are no . in the string, split will return an
        // array of length 1
        String[] classNameParts = mShortClassName.split("\\.");
        String currentName = mPackageName + "." + classNameParts[0];

        try {
            // Check to see if the class we're looking for is the top
            // level class.
            Class<?> clz = Class.forName(currentName,
                    false,
                    this.getClass().getClassLoader());
            if (clz.getCanonicalName().equals(mAbsoluteClassName)) {
                return clz;
            }

            // Then it must be an inner class.
            for (int x = 1; x < classNameParts.length; x++) {
                clz = findInnerClassByName(clz, classNameParts[x]);
                if (clz == null) {
                    return null;
                }
                if (clz.getCanonicalName().equals(mAbsoluteClassName)) {
                    return clz;
                }
            }
        } catch (ClassNotFoundException e) {
            loge("ClassNotFoundException for " + mPackageName + "." + mShortClassName, e);
            return null;
        }
        return null;
    }

    /**
     * Searches the class for the specified inner class.
     *
     * @param clz the class to search in.
     * @param simpleName the simpleName of the class to find
     * @returns the class being searched for, or null if it can't be found.
     */
    private Class<?> findInnerClassByName(Class<?> clz, String simpleName) {
        for (Class<?> c : clz.getDeclaredClasses()) {
            if (c.getSimpleName().equals(simpleName)) {
                return c;
            }
        }
        return null;
    }

    /**
     * Sees if the class under test is actually an annotation.
     *
     * @return true if this class is Annotation.
     */
    private boolean isAnnotation() {
        if (implInterfaces.contains("java.lang.annotation.Annotation")) {
            return true;
        }
        return false;
    }

    /**
     * Gets the class name for the class under test.
     *
     * @return the class name.
     */
    public String getClassName() {
        return mShortClassName;
    }

    /**
     * Sets the modifier for the class under test.
     *
     * @param modifier the modifier
     */
    public void setModifier(int modifier) {
        mModifier = modifier;
    }

    /**
     * Sets the return type for the class under test.
     *
     * @param type the return type
     */
    public void setType(JDiffType type) {
        mClassType = type;
    }

    /**
     * Sets the class that is beign extended for the class under test.
     *
     * @param extendsClass the class being extended.
     */
    public void setExtendsClass(String extendsClass) {
        mExtendedClass = extendsClass;
    }

    /**
     * Registers a ResultObserver to process the output from the
     * compliance testing done in this class.
     *
     * @param resultObserver the observer to register.
     */
    public void registerResultObserver(ResultObserver resultObserver) {
        mResultObserver = resultObserver;
    }

    /**
     * Converts WildcardType array into a jdiff compatible string..
     * This is a helper function for typeToString.
     *
     * @param types array of types to format.
     * @return the jdiff formatted string.
     */
    private static String concatWildcardTypes(Type[] types) {
        StringBuffer sb = new StringBuffer();
        int elementNum = 0;
        for (Type t : types) {
            sb.append(typeToString(t));
            if (++elementNum < types.length) {
                sb.append(" & ");
            }
        }
        return sb.toString();
    }

    /**
     * Converts a Type into a jdiff compatible String.  The returned
     * types from this function should match the same Strings that
     * jdiff is providing to us.
     *
     * @param type the type to convert.
     * @return the jdiff formatted string.
     */
    private static String typeToString(Type type) {
        if (type instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) type;

            StringBuffer sb = new StringBuffer();
            sb.append(typeToString(pt.getRawType()));
            sb.append("<");

            int elementNum = 0;
            Type[] types = pt.getActualTypeArguments();
            for (Type t : types) {
                sb.append(typeToString(t));
                if (++elementNum < types.length) {
                    sb.append(", ");
                }
            }

            sb.append(">");
            return sb.toString();
        } else if (type instanceof TypeVariable) {
            return ((TypeVariable<?>) type).getName();
        } else if (type instanceof Class) {
            return ((Class<?>) type).getCanonicalName();
        } else if (type instanceof GenericArrayType) {
            String typeName = typeToString(((GenericArrayType) type).getGenericComponentType());
            return typeName + "[]";
        } else if (type instanceof WildcardType) {
            WildcardType wt = (WildcardType) type;
            Type[] lowerBounds = wt.getLowerBounds();
            if (lowerBounds.length == 0) {
                String name = "? extends " + concatWildcardTypes(wt.getUpperBounds());

                // Special case for ?
                if (name.equals("? extends java.lang.Object")) {
                    return "?";
                } else {
                    return name;
                }
            } else {
                String name = concatWildcardTypes(wt.getUpperBounds()) +
                " super " +
                concatWildcardTypes(wt.getLowerBounds());
                // Another special case for ?
                name = name.replace("java.lang.Object", "?");
                return name;
            }
        } else {
            throw new RuntimeException("Got an unknown java.lang.Type");
        }
    }

    /**
     * Cleans up jdiff parameters to canonicalize them.
     *
     * @param paramType the parameter from jdiff.
     * @return the scrubbed version of the parameter.
     */
    private static String scrubJdiffParamType(String paramType) {
        // <? extends java.lang.Object and <?> are the same, so
        // canonicalize them to one form.
        return paramType.replace("<? extends java.lang.Object>", "<?>");
    }

    /**
     * Scan a class (an its entire inheritance chain) for fields.
     *
     * @return a {@link Map} of fieldName to {@link Field}
     */
    private static Map<String, Field> buildFieldMap(Class testClass) {
        Map<String, Field> fieldMap = new HashMap<String, Field>();
        // Scan the superclass
        if (testClass.getSuperclass() != null) {
            fieldMap.putAll(buildFieldMap(testClass.getSuperclass()));
        }

        // Scan the interfaces
        for (Class interfaceClass : testClass.getInterfaces()) {
            fieldMap.putAll(buildFieldMap(interfaceClass));
        }

        // Check the fields in the test class
        for (Field field : testClass.getDeclaredFields()) {
            fieldMap.put(field.getName(), field);
        }

        return fieldMap;
    }

    private static void loge(String message, Exception exception) {
        System.err.println(String.format("%s: %s", message, exception));
    }
}
