All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.weld.util.reflection.DeclaredMemberIndexer Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2013, Red Hat, Inc., and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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 org.jboss.weld.util.reflection;

import static org.jboss.weld.util.reflection.Reflections.cast;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;

import org.jboss.weld.util.Preconditions;

/**
 *
 * @author Martin Kouba
 */
public final class DeclaredMemberIndexer {

    private static final ConstructorComparator CONSTRUCTOR_COMPARATOR_INSTANCE = new ConstructorComparator();

    private static final MethodComparator METHOD_COMPARATOR_INSTANCE = new MethodComparator();

    private static final FieldComparator FIELD_COMPARATOR_INSTANCE = new FieldComparator();

    private DeclaredMemberIndexer() {
    }

    /**
     * @param field
     * @return the index for the given field
     */
    public static int getIndexForField(Field field) {
        Preconditions.checkNotNull(field);
        return getIndexForMember(field, getDeclaredFields(field.getDeclaringClass()));
    }

    /**
     * @param index
     * @param declaringClass
     * @return the declared field for the given index and declaring class
     * @throws IndexOutOfBoundsException if the index is out of range
     */
    public static Field getFieldForIndex(int index, Class declaringClass) {
        return getDeclaredFields(declaringClass).get(index);
    }

    /**
     * @param method
     * @return the index for the given method
     */
    public static int getIndexForMethod(Method method) {
        Preconditions.checkNotNull(method);
        return getIndexForMember(method, getDeclaredMethods(method.getDeclaringClass()));
    }

    /**
     * @param index
     * @param declaringClass
     * @return the declared method for the given index and declaring class
     * @throws IndexOutOfBoundsException if the index is out of range
     */
    public static Method getMethodForIndex(int index, Class declaringClass) {
        return getDeclaredMethods(declaringClass).get(index);
    }

    /**
     * @param constructor
     * @return the index for the given constructor
     */
    public static int getIndexForConstructor(Constructor constructor) {
        Preconditions.checkNotNull(constructor);
        return getIndexForMember(constructor, getDeclaredConstructors(constructor.getDeclaringClass()));
    }

    /**
     * @param index
     * @param declaringClass
     * @return the declared constructor for the given index and declaring class
     * @throws IndexOutOfBoundsException if the index is out of range
     */
    public static  Constructor getConstructorForIndex(int index, Class declaringClass) {
        return cast(getDeclaredConstructors(declaringClass).get(index));
    }

    private static  int getIndexForMember(T declaredMember, List declaredMembers) {

        for (ListIterator iterator = declaredMembers.listIterator(); iterator.hasNext();) {
            T member = iterator.next();
            if (member.equals(declaredMember)) {
                return iterator.previousIndex();
            }
        }
        // This should never happen
        throw new IllegalStateException("No matching declared member found for: " + declaredMember);
    }

    /**
     * @param declaringClass
     * @return the ordered list of declared fields for the given class
     */
    public static List getDeclaredFields(Class declaringClass) {
        Preconditions.checkNotNull(declaringClass);
        List declaredFields = Arrays.asList(declaringClass.getDeclaredFields());
        Collections.sort(declaredFields, FIELD_COMPARATOR_INSTANCE);
        return declaredFields;
    }

    /**
     * @param declaringClass
     * @return the ordered list of declared methods for the given class
     */
    public static List getDeclaredMethods(Class declaringClass) {
        Preconditions.checkNotNull(declaringClass);
        List declaredMethods = Arrays.asList(declaringClass.getDeclaredMethods());
        Collections.sort(declaredMethods, METHOD_COMPARATOR_INSTANCE);
        return declaredMethods;
    }

    /**
     * @param declaringClass
     * @return the ordered list of declared constructors for the given class
     */
    public static List> getDeclaredConstructors(Class declaringClass) {
        Preconditions.checkNotNull(declaringClass);
        List> declaredConstructors = Arrays.asList(declaringClass.getDeclaredConstructors());
        Collections.sort(declaredConstructors, CONSTRUCTOR_COMPARATOR_INSTANCE);
        return declaredConstructors;
    }

    private static int compareParamTypes(Class[] paramTypes1, Class[] paramTypes2) {

        // First compare the number of parameters
        if (paramTypes1.length != paramTypes2.length) {
            return paramTypes1.length - paramTypes2.length;
        }

        // Then compare the FCQNs of the parameter types
        for (int i = 0; i < paramTypes1.length; i++) {
            if (!paramTypes1[i].getName().equals(paramTypes2[i].getName())) {
                return paramTypes1[i].getName().compareTo(paramTypes2[i].getName());
            }
        }
        // This should never happen - constructors cannot have the same param
        // types and methods are ordered by name first
        return 0;
    }

    private static class ConstructorComparator implements Comparator>, Serializable {

        private static final long serialVersionUID = 4694814949925290433L;

        @Override
        public int compare(Constructor c1, Constructor c2) {
            return compareParamTypes(c1.getParameterTypes(), c2.getParameterTypes());
        }
    }

    private static class MethodComparator implements Comparator, Serializable {

        private static final long serialVersionUID = -2254993285161908832L;

        @Override
        public int compare(Method m1, Method m2) {
            // First compare the names
            if (!m1.getName().equals(m2.getName())) {
                return m1.getName().compareTo(m2.getName());
            }
            // Then compare the parameters
            return compareParamTypes(m1.getParameterTypes(), m2.getParameterTypes());
        }
    }

    private static class FieldComparator implements Comparator, Serializable {

        private static final long serialVersionUID = -1417596921060498760L;

        @Override
        public int compare(Field o1, Field o2) {
            return o1.getName().compareTo(o2.getName());
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy