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

com.manydesigns.elements.util.ReflectionUtil Maven / Gradle / Ivy

There is a newer version: 5.3.4
Show newest version
/*
 * Copyright (C) 2005-2019 ManyDesigns srl.  All rights reserved.
 * http://www.manydesigns.com/
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package com.manydesigns.elements.util;

import com.manydesigns.elements.fields.FieldUtils;
import com.manydesigns.elements.reflection.ClassAccessor;
import com.manydesigns.elements.reflection.PropertyAccessor;
import org.json.JSONObject;
import org.json.JSONStringer;
import org.json.JSONWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

/**
 * @author Paolo Predonzani     - [email protected]
 * @author Angelo Lupo          - [email protected]
 * @author Giampiero Granatella - [email protected]
 * @author Alessio Stalla       - [email protected]
 */
public class ReflectionUtil {
    public static final String copyright =
            "Copyright (C) 2005-2019 ManyDesigns srl";


    //**************************************************************************
    // Static fields and initialization
    //**************************************************************************

    public final static Logger logger =
            LoggerFactory.getLogger(ReflectionUtil.class);

    //**************************************************************************
    // Utility methods
    //**************************************************************************

    public static Class loadClass(String className) {
        try {
            Class aClass = Class.forName(className);
            logger.debug("Loaded class: {}", aClass);
            return aClass;
        } catch (Throwable e) {
            logger.debug("Could not load class: {}", className);
            return null;
        }
    }

    public static Constructor getConstructor(String className,
                                             Class... argClasses) {
        return getConstructor(loadClass(className), argClasses);
    }

    public static Constructor getConstructor(Class aClass,
                                             Class... argClasses) {
        try {
            Constructor constructor = aClass.getConstructor(argClasses);
            logger.debug("Found constructor: {}", constructor);
            return constructor;
        } catch (Throwable e) {
            logger.debug("Could not find construtor for class: {}", aClass);
            return null;
        }
    }

    public static Constructor getBestMatchConstructor(Class aClass,
                                                      Class... argClasses) {
        for (Constructor current : aClass.getConstructors()) {
            Class[] parameterTypes = current.getParameterTypes();
            if (parameterTypes.length != argClasses.length) {
                continue;
            }
            boolean matches = true;
            for (int i = 0; i < argClasses.length; i++) {
                Class paramaterType = parameterTypes[i];
                Class argClass = argClasses[i];
                matches = matches && paramaterType.isAssignableFrom(argClass);
            }
            if (matches) {
                return current;
            }
        }
        logger.debug("Could not find best match construtor for class: {}", aClass);
        return null;
    }

    public static Object newInstance(String className) {
        return newInstance(loadClass(className));
    }

    public static Object newInstance(Class aClass) {
        Constructor constructor = getConstructor(aClass);
        return newInstance(constructor);
    }

    public static Object newInstance(Constructor constructor, Object... args) {
        try {
            return constructor.newInstance(args);
        } catch (Throwable e) {
            logger.debug("Could not instanciate class constructor: {}",
                    constructor);
            return null;
        }
    }

    public static InputStream getResourceAsStream(String resourceName) {
        return ReflectionUtil.class.getClassLoader().getResourceAsStream(resourceName);
    }

    public static JSONWriter propertyAccessorToJson(JSONStringer js, PropertyAccessor accessor) {
        js.object();
        js.key("name").value(accessor.getName());
        js.key("type").value(accessor.getType().getName());
        js.key("modifiers").array();
        int modifiers = accessor.getModifiers();
        if(Modifier.isAbstract(modifiers)) {
            js.value("abstract");
        }
        if(Modifier.isFinal(modifiers)) {
            js.value("final");
        }
        if(Modifier.isPrivate(modifiers)) {
            js.value("private");
        }
        if(Modifier.isProtected(modifiers)) {
            js.value("protected");
        }
        if(Modifier.isPublic(modifiers)) {
            js.value("public");
        }
        js.endArray();
        js.key("label").value(FieldUtils.getLabel(accessor));
        js.key("annotations").array();
        for(Annotation ann : accessor.getAnnotations()) {
            annotationToJson(js, ann);
        }
        js.endArray();
        return js.endObject();
    }

    public static void annotationToJson(JSONStringer js, Annotation ann) {
        js.object();
        Class annotationType = ann.annotationType();
        js.key("type").value(annotationType.getName());
        js.key("properties").object();
        for (Method method : annotationType.getDeclaredMethods()) {
            try {
                Object propertyValue = method.invoke(ann);
                js.key(method.getName());
                annotationPropertyValueAsJson(js, propertyValue);
            } catch (Exception e) {
                logger.warn("Exception reading annotation property, skipping", e);
            }
        }
        js.endObject();
        js.endObject();
    }

    public static void annotationPropertyValueAsJson(JSONStringer js, Object propertyValue) {
        if(propertyValue instanceof Annotation) {
            annotationToJson(js, (Annotation) propertyValue);
        } else if(propertyValue instanceof Class) {
            js.value(propertyValue.toString());
        } else if(propertyValue != null && propertyValue.getClass().isArray()) {
            js.array();
            //TODO handle primitive arrays. Elements annotations only have String[] arrays currently.
            for (Object element : (Object[]) propertyValue) {
                annotationPropertyValueAsJson(js, element);
            }
            js.endArray();
        } else {
            js.value(propertyValue);
        }
    }

    public static JSONWriter classAccessorToJson(ClassAccessor accessor, JSONStringer js) {
        js.object();
        js.key("name").value(accessor.getName());
        js.key("keyProperties").array();
        for(PropertyAccessor p : accessor.getKeyProperties()) {
            js.value(p.getName());
        }
        js.endArray();
        js.key("properties").array();
        for(PropertyAccessor p : accessor.getProperties()) {
            propertyAccessorToJson(js, p);
        }
        js.endArray();
        js.key("annotations").array();
        for(Annotation ann : accessor.getAnnotations()) {
            annotationToJson(js, ann);
        }
        js.endArray();
        return js.endObject();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy