reflect.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.6.0).
003  * Copyright (c) 2007-2014 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019  */
020 package org.jenetics.internal.util;
021 
022 import java.lang.reflect.Method;
023 import java.util.ArrayList;
024 import java.util.Collections;
025 import java.util.Deque;
026 import java.util.LinkedList;
027 import java.util.List;
028 
029 import org.jenetics.util.StaticObject;
030 
031 /**
032  * Helper methods concerning Java reflection.
033  *
034  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
035  @version 1.6 &mdash; <em>$Date: 2014-02-02 $</em>
036  @since 1.6
037  */
038 public class reflect extends StaticObject {
039     private reflect() {}
040 
041     /**
042      * Return all declared classes of the given class, with arbitrary nested
043      * level.
044      *
045      @param cls the class for which the declared classes are retrieved.
046      @return all nested classes
047      */
048     public static List<Class<?>> allDeclaredClasses(final Class<?> cls) {
049         final Deque<Class<?>> stack = new LinkedList<>();
050         stack.addFirst(cls);
051 
052         final List<Class<?>> result = new ArrayList<>();
053         while (!stack.isEmpty()) {
054             final Class<?>[] classes = stack.pollFirst().getDeclaredClasses();
055             for (final Class<?> c : classes) {
056                 result.add(c);
057                 stack.addFirst(c);
058             }
059         }
060 
061         return Collections.unmodifiableList(result);
062     }
063 
064     /**
065      * Returns a Method object that reflects the specified public member method
066      * of the class or interface represented by this Class object.
067      *
068      @param type the class for getting the desired method.
069      @param name the method name
070      @param parameterTypes the method parameter types.
071      @return the method, or {@code null} if no such method can be found.
072      */
073     public static Method getMethod(
074         final Class<?> type,
075         final String name,
076         Class<?>[] parameterTypes
077     ) {
078         Method method = null;
079         final Method[] methods = type.getMethods();
080 
081         for (int i = 0; i < methods.length && method == null; ++i) {
082             if (name.equals(methods[i].getName()) &&
083                 equals(parameterTypes, methods[i].getParameterTypes()))
084             {
085                 method = methods[i];
086             }
087         }
088 
089         return method;
090     }
091 
092     private static boolean equals(final Class<?>[] p1, final Class<?>[] p2) {
093         boolean equals = p1.length == p2.length;
094         for (int i = 0; i < p1.length && equals; ++i) {
095             equals = toClassType(p1[i]) == toClassType(p2[i]);
096         }
097 
098         return equals;
099     }
100 
101     private static Class<?> toClassType(final Class<?> type) {
102         switch (type.getCanonicalName()) {
103             case "void"return Void.class;
104             case "boolean"return Boolean.class;
105             case "byte"return Byte.class;
106             case "char"return Character.class;
107             case "short"return Short.class;
108             case "int"return Integer.class;
109             case "long"return Long.class;
110             case "float"return Float.class;
111             case "double"return Double.class;
112             defaultreturn type;
113         }
114     }
115 
116     /**
117      * Return the class of the given value or the value if it is already from
118      * the type {@code Class}.
119      *
120      @param value the value to get the class from.
121      @return the class from the given value, or {@code value} if it is already
122      *         a {@code Class}.
123      */
124     public static Class<?> classOf(final Object value) {
125         return value instanceof Class<?> ? (Class<?>)value : value.getClass();
126     }
127 
128 }