Ver código fonte

#37 javadoc: reflection

Ranides Atterwim 3 anos atrás
pai
commit
28447da821

+ 65 - 1
assira.core/src/main/java/net/ranides/assira/reflection/util/ClassPredicate.java

@@ -4,10 +4,20 @@ import net.ranides.assira.text.Wildcard;
 
 import java.util.function.Predicate;
 
+/**
+ * Extension of Predicate, for Class.
+ * Defines few helper methods for matching class by name, type, inner class etc
+ */
 public interface ClassPredicate extends Predicate<Class<?>> {
 
+    /**
+     * Predicate accepting everything
+     */
     ClassPredicate ANY = c -> true;
 
+    /**
+     * Predicate accepting nothing
+     */
     ClassPredicate NONE = c -> false;
 
     @Override
@@ -25,28 +35,82 @@ public interface ClassPredicate extends Predicate<Class<?>> {
         return c -> test(c) || other.test(c);
     }
 
+    /**
+     * Predicate "OR" composition:
+     * returns new predicate which matches additional classes by name
+     *
+     * @param wildcard wildcard
+     * @return ClassPredicate
+     */
+    default ClassPredicate accept(String wildcard) {
+        Wildcard w = Wildcard.compile(wildcard);
+        return or(c -> w.test(c.getName()));
+    }
+
+    /**
+     * Predicate "OR" composition:
+     * returns new predicate which matches additional classes by name
+     *
+     * @param predicate predicate
+     * @return ClassPredicate
+     */
     default ClassPredicate accept(Predicate<String> predicate) {
         return or(c -> predicate.test(c.getName()));
     }
 
+    /**
+     * Predicate "OR" composition:
+     * returns new predicate which matches additionally provided class
+     *
+     * @param type type
+     * @return ClassPredicate
+     */
     default ClassPredicate accept(Class<?> type) {
         return or(c -> type.equals(c));
     }
 
+    /**
+     * Predicate "OR" composition:
+     * returns new predicate which matches inner classes declared inside provided class
+     *
+     * @param type type
+     * @return ClassPredicate
+     */
     default ClassPredicate acceptInner(Class<?> type) {
         String inner = type.getName() + "$";
         return or(c -> c.getName().startsWith(inner));
     }
 
+    /**
+     * Predicate "AND" composition:
+     * returns new predicate which rejects classes by name
+     *
+     * @param wildcard wildcard
+     * @return ClassPredicate
+     */
     default ClassPredicate reject(String wildcard) {
         Wildcard w = Wildcard.compile(wildcard);
-        return or(c -> w.test(c.getName()));
+        return and(c -> w.test(c.getName()));
     }
 
+    /**
+     * Predicate "AND" composition:
+     * returns new predicate which rejects additionally provided class
+     *
+     * @param type type
+     * @return ClassPredicate
+     */
     default ClassPredicate reject(Class<?> type) {
         return and(c -> !type.equals(c));
     }
 
+    /**
+     * Predicate "AND" composition:
+     * returns new predicate which rejects inner classes declared inside provided class
+     *
+     * @param type type
+     * @return ClassPredicate
+     */
     default ClassPredicate rejectInner(Class<?> type) {
         String inner = type.getName() + "$";
         return and(c -> !c.getName().startsWith(inner));

+ 119 - 10
assira.core/src/main/java/net/ranides/assira/reflection/util/ClassTraits.java

@@ -14,6 +14,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
 /**
+ * Utility methods for type checking
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
@@ -22,46 +23,112 @@ public final class ClassTraits {
     
     private static final int ACCESS_ANY = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
 
+    /**
+     * Returns true if clazz represents primitive (unboxed) type
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isPrimitive(Class<?> clazz) {
         return clazz.isPrimitive();
     }
-    
+
+    /**
+     * Returns true if clazz represents array of primitive (unboxed) type
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isPrimitiveArray(Class<?> clazz) {
         return clazz.isArray() && isPrimitive(clazz.getComponentType());
     }
 
+    /**
+     * Returns true if clazz has "static" attribute
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isStatic(Class<?> clazz) {
         return Modifier.isStatic(clazz.getModifiers());
     }
 
+    /**
+     * Returns true if clazz has "public" attribute
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isPublic(Class<?> clazz) {
         return Modifier.isPublic(clazz.getModifiers());
     }
 
+    /**
+     * Returns true if clazz has "protected" attribute
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isProtected(Class<?> clazz) {
         return Modifier.isProtected(clazz.getModifiers());
     }
-    
-    public static boolean isPackage(Class<?> member) {
-        return 0 == (member.getModifiers() & ACCESS_ANY);
+
+    /**
+     * Returns true if clazz has "package scope" attribute
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
+    public static boolean isPackage(Class<?> clazz) {
+        return 0 == (clazz.getModifiers() & ACCESS_ANY);
     }
 
+    /**
+     * Returns true if clazz has "private" attribute
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isPrivate(Class<?> clazz) {
         return Modifier.isPrivate(clazz.getModifiers());
     }
 
+    /**
+     * Returns true if clazz is interface
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isInterface(Class<?> clazz) {
         return Modifier.isInterface(clazz.getModifiers());
     }
 
+    /**
+     * Returns true if clazz has "final" attribute
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isFinal(Class<?> clazz) {
         return Modifier.isFinal(clazz.getModifiers());
     }
 
+    /**
+     * Returns true if clazz has "abstract" attribute
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isAbstract(Class<?> clazz) {
         return Modifier.isAbstract(clazz.getModifiers());
     }
-    
+
+    /**
+     * Returns true if clazz represents primitive, but boxed type (e.g. Integer)
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isBoxed(Class<?> clazz) {
         return
             Byte.class.equals(clazz) ||
@@ -74,11 +141,23 @@ public final class ClassTraits {
             Boolean.class.equals(clazz) ||
             Void.class.equals(clazz);
     }
-    
+
+    /**
+     * Returns true if clazz represents boolean type (boxed or unboxed)
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isBool(Class<?> clazz) {
         return boolean.class.equals(clazz) || Boolean.class.equals(clazz);
     }
 
+    /**
+     * Returns true if clazz represents any numerical type (boxed or unboxed)
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isNumber(Class<?> clazz) {
         return
             byte.class.equals(clazz) ||
@@ -95,7 +174,13 @@ public final class ClassTraits {
             Double.class.equals(clazz) ||
             Number.class.isAssignableFrom(clazz);
     }
-    
+
+    /**
+     * Returns true if clazz represents any integer type (boxed or unboxed)
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isInteger(Class<?> clazz) {
         return
             byte.class.equals(clazz) ||
@@ -110,11 +195,26 @@ public final class ClassTraits {
             AtomicLong.class.equals(clazz) ||
             BigInteger.class.equals(clazz);
     }
-    
+
+    /**
+     * Returns true if clazz represents "void" or "Void"
+     *
+     * @param clazz clazz
+     * @return boolean
+     */
     public static boolean isVoid(Class<?> clazz) {
         return clazz.equals(void.class) || clazz.equals(Void.class);
     }
-    
+
+    /**
+     * Returns true, if "ssuper" is super class of "type".
+     * Supports boxing operation.
+     * Does not support generic types, works with raw types.
+     *
+     * @param ssuper ssuper
+     * @param type type
+     * @return boolean
+     */
     @SuppressWarnings("PMD.CyclomaticComplexity")
     public static boolean isSuper(Class<?> ssuper, Class<?> type) {
         if (ssuper.equals(boolean.class) || ssuper.equals(Boolean.class)) {
@@ -137,7 +237,16 @@ public final class ClassTraits {
             return ssuper.isAssignableFrom(type) || ssuper.isAssignableFrom(ClassUtils.box(type));
         }
     }
-    
+
+    /**
+     * Returns true, if each element from "supers" is super class of according element from "types".
+     * Supports boxing operation.
+     * Does not support generic types, works with raw types.
+     *
+     * @param supers supers
+     * @param types types
+     * @return boolean
+     */
     public static boolean isSuper(Class<?>[] supers, Class<?>[] types) {
         if(supers.length != types.length) {
             return false;

+ 110 - 9
assira.core/src/main/java/net/ranides/assira/reflection/util/ClassUtils.java

@@ -15,12 +15,22 @@ import java.util.Optional;
 import java.util.function.Function;
 
 /**
+ * Utility methods for type transformation
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
 @UtilityClass
 public final class ClassUtils {
 
+    /**
+     * Tries to cast provided object. Returns none if impossible.
+     * Does not throw ClassCastException
+     *
+     * @param type type
+     * @param value value
+     * @param <T> T
+     * @return optional
+     */
     @SuppressWarnings("unchecked")
     public static <T> Optional<T> cast(IClass<T> type, Object value) {
         if(value != null && type.isInstance(value)) {
@@ -30,6 +40,15 @@ public final class ClassUtils {
         }
     }
 
+    /**
+     * Tries to cast provided object. Returns none if impossible.
+     * Does not throw ClassCastException
+     *
+     * @param type type
+     * @param value value
+     * @param <T> T
+     * @return optional
+     */
     @SuppressWarnings("unchecked")
     public static <T> Optional<T> cast(Class<T> type, Object value) {
         if(value != null && type.isInstance(value)) {
@@ -39,28 +58,78 @@ public final class ClassUtils {
         }
     }
 
+    /**
+     * Returns function which casts object into type.
+     * Function does not throw ClassCastException but returns empty optional if cast is impossible.
+     *
+     * @param type type
+     * @param <T> T
+     * @return Function
+     */
     public static <T> Function<Object, Optional<T>> cast(IClass<T> type) {
         return value -> cast(type, value);
     }
 
+    /**
+     * Returns function which casts object into type.
+     * Function does not throw ClassCastException but returns empty optional if cast is impossible.
+     *
+     * @param type type
+     * @param <T> T
+     * @return Function
+     */
     public static <T> Function<Object, Optional<T>> cast(Class<T> type) {
         return value -> cast(type, value);
     }
 
+    /**
+     * If "source" is subclass of "target" returns target class.
+     * Returns empty optional otherwise.
+     *
+     * @param target target
+     * @param source source
+     * @param <T> T
+     * @return Optional
+     */
     @SuppressWarnings({"rawtypes", "unchecked"})
     public static <T> Optional<Class<? extends T>> asSubclass(Class<T> target, Class<?> source) {
         return (Optional)Optional.ofNullable(source).filter(target::isAssignableFrom);
     }
 
+    /**
+     * If "source" is subclass of "target" returns target class.
+     * Returns empty optional otherwise.
+     *
+     * @param target target
+     * @param source source
+     * @param <T> T
+     * @return Optional
+     */
     @SuppressWarnings({"rawtypes", "unchecked"})
     public static <T> Optional<IClass<? extends T>> asSubclass(IClass<T> target, IClass<?> source) {
         return (Optional)Optional.ofNullable(source).filter(target::isSuper);
     }
-    
+
+    /**
+     * If this class is primitive type, returns boxed type.
+     * Returns input parameter otherwise.
+     *
+     * @param ic ic
+     * @param <S> S
+     * @return class
+     */
     public static <S> IClass<S> box(IClass<S> ic) {
         return ic.attributes().has(IAttribute.PRIMITIVE) ? IClass.typeinfo(box(ic.raw())) : ic;
     }
 
+    /**
+     * If this class is primitive type, returns boxed type.
+     * Returns input parameter otherwise.
+     *
+     * @param clazz clazz
+     * @param <S> S
+     * @return class
+     */
     @SuppressWarnings({"PMD", "unchecked"})
     public static <S> Class<S> box(Class<S> clazz) {
         if (byte.class.equals(clazz)) {
@@ -85,11 +154,27 @@ public final class ClassUtils {
             return clazz;
         }
     }
-    
+
+    /**
+     * If this class is boxed primitive type, returns unboxed type.
+     * Returns input parameter otherwise.
+     *
+     * @param ic ic
+     * @param <S> S
+     * @return class
+     */
     public static <S> IClass<S> unbox(IClass<S> ic) {
         return ic.attributes().has(IAttribute.BOXED) ? IClass.typeinfo(unbox(ic.raw())) : ic;
     }
 
+    /**
+     * If this class is boxed primitive type, returns unboxed type.
+     * Returns input parameter otherwise.
+     *
+     * @param clazz clazz
+     * @param <S> S
+     * @return class
+     */
     @SuppressWarnings({"PMD", "unchecked"})
     public static <S> Class<S> unbox(Class<S> clazz) {
         if (Byte.class.equals(clazz)) {
@@ -116,8 +201,9 @@ public final class ClassUtils {
     }
 
     /**
-     * Sprawdza, czy podany obiekt {@code get} jest instancją klasy {@code ssuper}.
-     * Uwzględnia autoboxing argumentów.
+     * Checks if provided object is instance of "type"
+     * It supports autoboxing.
+     *
      * @param type type
      * @param value value
      * @return boolean
@@ -127,11 +213,12 @@ public final class ClassUtils {
     }
 
     /**
-     * Sprawdza, czy odpowiednie obiekty z tablicy {@code values} są istancjami
-     * odpowiednich klas z tablicy {@code supers}. Uwzględnia autoboxing argumentów.
-     * @param type
-     * @param values
-     * @return
+     * Checks if objects from provided arrays are instance of according type from "type" array.
+     * It supports autoboxing.
+     *
+     * @param type type
+     * @param values values
+     * @return boolean
      */
     public static boolean isInstance(Class<?>[] type, Object[] values) {
         if(type.length != values.length) {
@@ -143,6 +230,12 @@ public final class ClassUtils {
         return true;
     }
 
+    /**
+     * Returns true if default classloader already loaded class with provided fully qualified name.
+     *
+     * @param name name
+     * @return boolean
+     */
     public static boolean isLoaded(String name) {
         for(ClassLoader c = ClassLoaderUtils.getDefault(); c!=null; c=c.getParent()) {
             if(null != MethodUtils.invoke(Li.FIND_LOADED_CLASS, c, name) ) {
@@ -152,6 +245,14 @@ public final class ClassUtils {
         return false;
     }
 
+    /**
+     * Uses default classloader to resolve provided fully qualified name.
+     * Returns empty optional if class is not found.
+     * Does not throw exceptions.
+     *
+     * @param type type
+     * @return Optional
+     */
     public static Optional<Class<?>> forName(String type) {
         try {
             return Optional.of(Class.forName(type, true, ClassLoaderUtils.getDefault()));

+ 84 - 9
assira.core/src/main/java/net/ranides/assira/reflection/util/MemberTraits.java

@@ -13,6 +13,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 
 /**
+ * Helper functions for checking reflective member features
  *
  * @author ranides
  */
@@ -21,60 +22,133 @@ public final class MemberTraits {
     
     private static final int ACCESS_ANY = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE;
 
+    /**
+     * Returns true if member has "volatile" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isVolatile(Member member) {
         return Modifier.isVolatile(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "transient" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isTransient(Member member) {
         return Modifier.isTransient(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "synchronized" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isSynchronized(Member member) {
         return Modifier.isSynchronized(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "strict" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isStrict(Member member) {
         return Modifier.isStrict(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "static" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isStatic(Member member) {
         return Modifier.isStatic(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "public" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isPublic(Member member) {
         return Modifier.isPublic(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "protected" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isProtected(Member member) {
         return Modifier.isProtected(member.getModifiers());
     }
-    
+
+    /**
+     * Returns true if member has "package" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isPackage(Member member) {
         return 0 == (member.getModifiers() & ACCESS_ANY);
     }
 
+    /**
+     * Returns true if member has "private" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isPrivate(Member member) {
         return Modifier.isPrivate(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "native" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isNative(Member member) {
         return Modifier.isNative(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "final" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isFinal(Member member) {
         return Modifier.isFinal(member.getModifiers());
     }
 
+    /**
+     * Returns true if member has "abstract" attribute
+     *
+     * @param member member
+     * @return boolean
+     */
     public static boolean isAbstract(Member member) {
         return Modifier.isAbstract(member.getModifiers());
     }
     
     /**
-     * Sprawdza czy podana metoda może być traktowana jako getter 
-     * (np {@code getValue}). Akceptuje gettery o nazwie w formie {@code isEnabled}, 
-     * o ile zwracają typ {@code bool} .
-     * @param method
-     * @return
+     * Returns true if provided method can be used as "getter".
+     * Accepts getters with a name "getValue".
+     * For boolean type accepts "isEnabled" form.
+     *
+     * @param method method
+     * @return boolean
      */
     public static boolean isGetter(Member method) { 
         return (method instanceof Method) && isGetter((Method)method);
@@ -109,9 +183,10 @@ public final class MemberTraits {
     }
     
     /**
-     * Sprawdza czy podana metoda może być traktowana jako setter.
-     * @param method
-     * @return
+     * Returns true if provided method can be used as "setter".
+     *
+     * @param method method
+     * @return boolean
      */
     public static boolean isSetter(Member method) { 
         return (method instanceof Method) && isSetter((Method)method);

+ 42 - 12
assira.core/src/main/java/net/ranides/assira/reflection/util/MethodUtils.java

@@ -16,6 +16,7 @@ import java.util.Arrays;
 import net.ranides.assira.reflection.*;
 
 /**
+ * Helper functions for reflective method invocation and inspection
  *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
  */
@@ -23,11 +24,12 @@ import net.ranides.assira.reflection.*;
 public final class MethodUtils {
 
     /**
-     * Sprawdza, czy podana metoda jest nadpisana przez metodę (override). Cały dowcip
-     * to obsługa metod package-scope, które może przeładować klasa z tego samego
-     * pakietu, a z innego nie.
-     * @param candidate 
-     * @param original 
+     * Returns true if "candidate" method overrides "original" declared in base class.
+     *
+     * Supports edge case where package-scope method can be overriden only by subclass from the same package.
+     *
+     * @param candidate candidate
+     * @param original original
      * @return 
      */
     public static boolean overrides(Method original, Method candidate) {
@@ -55,11 +57,16 @@ public final class MethodUtils {
     }
     
     /**
-     * Wywołuje na rzecz obiektu podaną metodę. 
-     * @param that
-     * @param method
-     * @param arguments
-     * @return
+     * Calls non-static method passing "that" as "this" argument.
+     *
+     * Throws IReflectiveException.CallException if method throws exception.
+     * Throws IReflectiveException.AbnormalException if illegal access is thrown.
+     * Throws IReflectiveException if other error occurs.
+     *
+     * @param that that
+     * @param method method
+     * @param arguments arguments
+     * @return Object
      */
     public static Object invoke(Method method, Object that, Object... arguments) {
         if(that == null && !MemberTraits.isStatic(method)) {
@@ -76,7 +83,18 @@ public final class MethodUtils {
             throw new IReflectiveException(cause);
         }
     }
-    
+
+    /**
+     * Creates new object by invoking provided constructor.
+     *
+     * Throws IReflectiveException.CallException if method throws exception.
+     * Throws IReflectiveException.AbnormalException if illegal access is thrown.
+     * Throws IReflectiveException if other error occurs.
+     *
+     * @param ctor ctor
+     * @param arguments arguments
+     * @return Object
+     */
     public static Object invoke(Constructor<?> ctor, Object... arguments) {
         try {
             return ctor.newInstance(arguments);
@@ -88,7 +106,19 @@ public final class MethodUtils {
             throw new IReflectiveException(cause);
         }
     }
-	
+
+    /**
+     * Calls non-static method passing "that" as "this" argument.
+     * Uses {@link #invoke(Method, Object, Object...)} method.
+     *
+     * It casts returned value using unchecked type inference.
+     *
+     * @param method method
+     * @param that that
+     * @param arguments arguments
+     * @param <T> T
+     * @return T
+     */
 	@SuppressWarnings("unchecked")
 	public static <T> T $invoke(Method method, Object that, Object... arguments) {
 		return (T)invoke(method, that, arguments);

+ 1 - 1
assira.core/src/test/java/net/ranides/assira/reflection/impl/AClassesTest.java

@@ -339,7 +339,7 @@ public class AClassesTest {
         
     }
     
-    private static AClasses iclist() {
+    private static IClasses iclist() {
         return FElements.newClasses(new IClass<?>[]{STRING, I_INTEGER, I_NUMBER, T_INTERFACE, ANNOTATED_1, ANNOTATED_2});
     }