home | career | drupal | java | mac | mysql | perl | scala | uml | unix

Groovy example source code file (Inspector.java)

This example Groovy source code file (Inspector.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Groovy tags/keywords

class, class, groovy, inspector, io, java, membercomparator, not_applicable, not_applicable, object, object, propertyvalue, reflection, string, string, stringbuffer, util

The Groovy Inspector.java source code

/*
 * Copyright 2003-2007 the original author or authors.
 *
 * 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 groovy.inspect;

import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.lang.MetaMethod;
import groovy.lang.PropertyValue;
import org.codehaus.groovy.reflection.CachedClass;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.InvokerHelper;

import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * The Inspector provides a unified access to an object's
 * information that can be determined by introspection.
 *
 * @author Dierk Koenig
 */
public class Inspector {
    protected Object objectUnderInspection;

    // Indexes to retrieve Class Property information
    public static final int CLASS_PACKAGE_IDX = 0;
    public static final int CLASS_CLASS_IDX = 1;
    public static final int CLASS_INTERFACE_IDX = 2;
    public static final int CLASS_SUPERCLASS_IDX = 3;
    public static final int CLASS_OTHER_IDX = 4;

    // Indexes to retrieve field and method information
    public static final int MEMBER_ORIGIN_IDX = 0;
    public static final int MEMBER_MODIFIER_IDX = 1;
    public static final int MEMBER_DECLARER_IDX = 2;
    public static final int MEMBER_TYPE_IDX = 3;
    public static final int MEMBER_NAME_IDX = 4;
    public static final int MEMBER_PARAMS_IDX = 5;
    public static final int MEMBER_VALUE_IDX = 5;
    public static final int MEMBER_EXCEPTIONS_IDX = 6;

    public static final String NOT_APPLICABLE = "n/a";
    public static final String GROOVY = "GROOVY";
    public static final String JAVA = "JAVA";

    /**
     * @param objectUnderInspection must not be null
     */
    public Inspector(Object objectUnderInspection) {
        if (null == objectUnderInspection) {
            throw new IllegalArgumentException("argument must not be null");
        }
        this.objectUnderInspection = objectUnderInspection;
    }

    /**
     * Get the Class Properties of the object under inspection.
     *
     * @return String array to be indexed by the CLASS_xxx_IDX constants
     */
    public String[] getClassProps() {
        String[] result = new String[CLASS_OTHER_IDX + 1];
        Package pack = getClassUnderInspection().getPackage();
        result[CLASS_PACKAGE_IDX] = "package " + ((pack == null) ? NOT_APPLICABLE : pack.getName());
        String modifiers = Modifier.toString(getClassUnderInspection().getModifiers());
        result[CLASS_CLASS_IDX] = modifiers + " class " + shortName(getClassUnderInspection());
        result[CLASS_INTERFACE_IDX] = "implements ";
        Class[] interfaces = getClassUnderInspection().getInterfaces();
        for (Class anInterface : interfaces) {
            result[CLASS_INTERFACE_IDX] += shortName(anInterface) + " ";
        }
        result[CLASS_SUPERCLASS_IDX] = "extends " + shortName(getClassUnderInspection().getSuperclass());
        result[CLASS_OTHER_IDX] = "is Primitive: " + getClassUnderInspection().isPrimitive()
                + ", is Array: " + getClassUnderInspection().isArray()
                + ", is Groovy: " + isGroovy();
        return result;
    }

    public boolean isGroovy() {
        return GroovyObject.class.isAssignableFrom(getClassUnderInspection());
    }

    /**
     * Gets the object being inspected.
     *
     * @return the object
     */
    public Object getObject() {
        return objectUnderInspection;
    }

    /**
     * Get info about usual Java instance and class Methods as well as Constructors.
     *
     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
     */
    public Object[] getMethods() {
        Method[] methods = getClassUnderInspection().getMethods();
        Constructor[] ctors = getClassUnderInspection().getConstructors();
        Object[] result = new Object[methods.length + ctors.length];
        int resultIndex = 0;
        for (; resultIndex < methods.length; resultIndex++) {
            Method method = methods[resultIndex];
            result[resultIndex] = methodInfo(method);
        }
        for (int i = 0; i < ctors.length; i++, resultIndex++) {
            Constructor ctor = ctors[i];
            result[resultIndex] = methodInfo(ctor);
        }
        return result;
    }

    /**
     * Get info about instance and class Methods that are dynamically added through Groovy.
     *
     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
     */
    public Object[] getMetaMethods() {
        MetaClass metaClass = InvokerHelper.getMetaClass(objectUnderInspection);
        List metaMethods = metaClass.getMetaMethods();
        Object[] result = new Object[metaMethods.size()];
        int i = 0;
        for (Iterator iter = metaMethods.iterator(); iter.hasNext(); i++) {
            MetaMethod metaMethod = (MetaMethod) iter.next();
            result[i] = methodInfo(metaMethod);
        }
        return result;
    }

    /**
     * Get info about usual Java public fields incl. constants.
     *
     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
     */
    public Object[] getPublicFields() {
        Field[] fields = getClassUnderInspection().getFields();
        Object[] result = new Object[fields.length];
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            result[i] = fieldInfo(field);
        }
        return result;
    }

    /**
     * Get info about Properties (Java and Groovy alike).
     *
     * @return Array of StringArrays that can be indexed with the MEMBER_xxx_IDX constants
     */
    public Object[] getPropertyInfo() {
        List props = DefaultGroovyMethods.getMetaPropertyValues(objectUnderInspection);
        Object[] result = new Object[props.size()];
        int i = 0;
        for (Iterator iter = props.iterator(); iter.hasNext(); i++) {
            PropertyValue pv = (PropertyValue) iter.next();
            result[i] = fieldInfo(pv);
        }
        return result;
    }

    protected String[] fieldInfo(Field field) {
        String[] result = new String[MEMBER_VALUE_IDX + 1];
        result[MEMBER_ORIGIN_IDX] = JAVA;
        result[MEMBER_MODIFIER_IDX] = Modifier.toString(field.getModifiers());
        result[MEMBER_DECLARER_IDX] = shortName(field.getDeclaringClass());
        result[MEMBER_TYPE_IDX] = shortName(field.getType());
        result[MEMBER_NAME_IDX] = field.getName();
        try {
            result[MEMBER_VALUE_IDX] = InvokerHelper.inspect(field.get(objectUnderInspection));
        } catch (IllegalAccessException e) {
            result[MEMBER_VALUE_IDX] = NOT_APPLICABLE;
        }
        return withoutNulls(result);
    }

    protected String[] fieldInfo(PropertyValue pv) {
        String[] result = new String[MEMBER_VALUE_IDX + 1];
        result[MEMBER_ORIGIN_IDX] = GROOVY;
        result[MEMBER_MODIFIER_IDX] = "public";
        result[MEMBER_DECLARER_IDX] = NOT_APPLICABLE;
        result[MEMBER_TYPE_IDX] = shortName(pv.getType());
        result[MEMBER_NAME_IDX] = pv.getName();
        try {
            result[MEMBER_VALUE_IDX] = InvokerHelper.inspect(pv.getValue());
        } catch (Exception e) {
            result[MEMBER_VALUE_IDX] = NOT_APPLICABLE;
        }
        return withoutNulls(result);
    }

    protected Class getClassUnderInspection() {
        return objectUnderInspection.getClass();
    }

    public static String shortName(Class clazz) {
        if (null == clazz) return NOT_APPLICABLE;
        String className = clazz.getName();
        if (null == clazz.getPackage()) return className;
        String packageName = clazz.getPackage().getName();
        int offset = packageName.length();
        if (offset > 0) offset++;
        className = className.substring(offset);
        return className;
    }

    protected String[] methodInfo(Method method) {
        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
        int mod = method.getModifiers();
        result[MEMBER_ORIGIN_IDX] = JAVA;
        result[MEMBER_DECLARER_IDX] = shortName(method.getDeclaringClass());
        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
        result[MEMBER_NAME_IDX] = method.getName();
        result[MEMBER_TYPE_IDX] = shortName(method.getReturnType());
        Class[] params = method.getParameterTypes();
        StringBuffer sb = new StringBuffer();
        for (int j = 0; j < params.length; j++) {
            sb.append(shortName(params[j]));
            if (j < (params.length - 1)) sb.append(", ");
        }
        result[MEMBER_PARAMS_IDX] = sb.toString();
        sb.setLength(0);
        Class[] exceptions = method.getExceptionTypes();
        for (int k = 0; k < exceptions.length; k++) {
            sb.append(shortName(exceptions[k]));
            if (k < (exceptions.length - 1)) sb.append(", ");
        }
        result[MEMBER_EXCEPTIONS_IDX] = sb.toString();
        return withoutNulls(result);
    }

    protected String[] methodInfo(Constructor ctor) {
        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
        int mod = ctor.getModifiers();
        result[MEMBER_ORIGIN_IDX] = JAVA;
        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
        result[MEMBER_DECLARER_IDX] = shortName(ctor.getDeclaringClass());
        result[MEMBER_TYPE_IDX] = shortName(ctor.getDeclaringClass());
        result[MEMBER_NAME_IDX] = ctor.getName();
        Class[] params = ctor.getParameterTypes();
        StringBuffer sb = new StringBuffer();
        for (int j = 0; j < params.length; j++) {
            sb.append(shortName(params[j]));
            if (j < (params.length - 1)) sb.append(", ");
        }
        result[MEMBER_PARAMS_IDX] = sb.toString();
        sb.setLength(0);
        Class[] exceptions = ctor.getExceptionTypes();
        for (int k = 0; k < exceptions.length; k++) {
            sb.append(shortName(exceptions[k]));
            if (k < (exceptions.length - 1)) sb.append(", ");
        }
        result[MEMBER_EXCEPTIONS_IDX] = sb.toString();
        return withoutNulls(result);
    }

    protected String[] methodInfo(MetaMethod method) {
        String[] result = new String[MEMBER_EXCEPTIONS_IDX + 1];
        int mod = method.getModifiers();
        result[MEMBER_ORIGIN_IDX] = GROOVY;
        result[MEMBER_MODIFIER_IDX] = Modifier.toString(mod);
        result[MEMBER_DECLARER_IDX] = shortName(method.getDeclaringClass().getTheClass());
        result[MEMBER_TYPE_IDX] = shortName(method.getReturnType());
        result[MEMBER_NAME_IDX] = method.getName();
        CachedClass[] params = method.getParameterTypes();
        StringBuffer sb = new StringBuffer();
        for (int j = 0; j < params.length; j++) {
            sb.append(shortName(params[j].getTheClass()));
            if (j < (params.length - 1)) sb.append(", ");
        }
        result[MEMBER_PARAMS_IDX] = sb.toString();
        result[MEMBER_EXCEPTIONS_IDX] = NOT_APPLICABLE; // no exception info for Groovy MetaMethods
        return withoutNulls(result);
    }

    protected String[] withoutNulls(String[] toNormalize) {
        for (int i = 0; i < toNormalize.length; i++) {
            String s = toNormalize[i];
            if (null == s) toNormalize[i] = NOT_APPLICABLE;
        }
        return toNormalize;
    }

    public static void print(Object[] memberInfo) {
        print(System.out, memberInfo);
    }

    static void print(final PrintStream out, Object[] memberInfo) {
        for (int i = 0; i < memberInfo.length; i++) {
            String[] metaMethod = (String[]) memberInfo[i];
            out.print(i + ":\t");
            for (String s : metaMethod) {
                out.print(s + " ");
            }
            out.println("");
        }
    }

    public static Collection sort(List<Object> memberInfo) {
        Collections.sort(memberInfo, new MemberComparator());
        return memberInfo;
    }

    public static class MemberComparator implements Comparator<Object> {
        public int compare(Object a, Object b) {
            String[] aStr = (String[]) a;
            String[] bStr = (String[]) b;
            int result = aStr[Inspector.MEMBER_NAME_IDX].compareTo(bStr[Inspector.MEMBER_NAME_IDX]);
            if (0 != result) return result;
            result = aStr[Inspector.MEMBER_TYPE_IDX].compareTo(bStr[Inspector.MEMBER_TYPE_IDX]);
            if (0 != result) return result;
            result = aStr[Inspector.MEMBER_PARAMS_IDX].compareTo(bStr[Inspector.MEMBER_PARAMS_IDX]);
            if (0 != result) return result;
            result = aStr[Inspector.MEMBER_DECLARER_IDX].compareTo(bStr[Inspector.MEMBER_DECLARER_IDX]);
            if (0 != result) return result;
            result = aStr[Inspector.MEMBER_MODIFIER_IDX].compareTo(bStr[Inspector.MEMBER_MODIFIER_IDX]);
            if (0 != result) return result;
            result = aStr[Inspector.MEMBER_ORIGIN_IDX].compareTo(bStr[Inspector.MEMBER_ORIGIN_IDX]);
            return result;
        }
    }
}

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy Inspector.java source code file:

new blog posts

 

Copyright 1998-2014 Alvin Alexander, alvinalexander.com
All Rights Reserved.