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

com.poiji.util.ReflectUtil Maven / Gradle / Ivy

package com.poiji.util;

import com.poiji.annotation.ExcelCellRange;
import com.poiji.bind.mapping.Data;
import com.poiji.exception.IllegalCastException;
import com.poiji.exception.PoijiException;
import com.poiji.exception.PoijiInstantiationException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class ReflectUtil {
    public static  T newInstanceOf(Class type) {
        T obj;
        try {
            Constructor constructor = type.getDeclaredConstructor();
            if (!constructor.isAccessible()) {
                constructor.setAccessible(true);
            }
            obj = constructor.newInstance();
        } catch (Exception ex) {
            throw new PoijiInstantiationException("Cannot create a new instance of " + type.getName(), ex);
        }

        return obj;
    }

    public static  T newInstanceOf(Data data) {
        final Class type = data.getDeclaringClass();
        if (type == null) {
            return null;
        }
        return newInstanceOf(type, data);
    }

    public static  T newInstanceOf(Class type, Data data) {
        try {
            final Constructor constructor = ConstructorSelector.selectConstructor(type);
            if (constructor.getParameterCount() == 0) {
                return createInstanceUsingDefaultConstructor(data, constructor);
            } else {
                return createInstanceUsingParameterizedConstructor(data, constructor);
            }
        } catch (PoijiInstantiationException exception) {
            throw exception;
        } catch (Exception ex) {
            throw new PoijiInstantiationException("Cannot create a new instance of " + type.getName(), ex);
        }
    }

    private static  T createInstanceUsingParameterizedConstructor(Data data, Constructor constructor) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        final Object[] parameters = defineConstructorParameters(data, constructor);
        final T instance = (T) constructor.newInstance(parameters);
        fillPreCreatedProperties(data, instance);
        return instance;
    }

    private static  void fillPreCreatedProperties(Data data, T instance) throws IllegalAccessException {
        for (Map.Entry entry : data.entrySet()) {
            final Field field = entry.getKey();
            final Class fieldType = field.getType();
            if (fieldType.isAssignableFrom(Map.class)) {
                final Map property = (Map) field.get(instance);
                property.putAll((Map) entry.getValue());
            } else if (fieldType.isAssignableFrom(Collection.class)) {
                final Collection property = (Collection) field.get(instance);
                property.addAll((Collection) entry.getValue());
            }
        }
    }

    private static Object[] defineConstructorParameters(Data data, Constructor constructor) {
        final Object[] constructorFields = ConstructorFieldMapper.getConstructorFields(constructor);
        final int count = constructorFields.length;
        final Object[] parameters = new Object[count];
        for (int i = 0; i < count; i++) {
            final Object parameter = constructorFields[i];
            if (parameter != null && parameter.getClass()  == Field.class) {
                final Field field = (Field) parameter;
                final Object value = data.remove(field);
                if (value instanceof List) {
                    instantiateListElements((List) value);
                }
                parameters[i] = value;
            } else {
                parameters[i] = parameter;
            }
        }
        return parameters;
    }

    private static void instantiateListElements(List list) {
        for (int j = 0; j < list.size(); j++) {
            final Object element = list.get(j);
            if (element.getClass() == Data.class) {
                list.set(j, newInstanceOf((Data) element));
            }
        }
    }

    private static  T createInstanceUsingDefaultConstructor(Data data, Constructor constructor) throws InstantiationException, IllegalAccessException, InvocationTargetException {
        final T instance = (T) constructor.newInstance();
        for (Map.Entry entry : data.entrySet()) {
            entry.getKey().set(instance, getValue(entry));
        }
        return instance;
    }

    private static Object getValue(Map.Entry entry) {
        final Object value = entry.getValue();
        if (value != null && value.getClass() == Data.class) {
            final Class type = entry.getKey().getType();
            return newInstanceOf(type, (Data) value);
        } else if (value instanceof Collection){
            final Collection valueCollection = (Collection) value;
            if (valueCollection.iterator().next().getClass() == Data.class) {
                final Collection result = (Collection) newInstanceOf(value.getClass());
                final Collection dataCollection = (Collection) valueCollection;
                for (Data data : dataCollection) {
                    result.add(newInstanceOf(data));
                }
                return result;
            } else {
                return valueCollection;
            }
        }
        return value;
    }

    /**
     * Finds a particular annotation on a class and checks subtypes marked with ExcelCellRange recursively.
     * 

* Recursively does not refer to super classes. */ public static Collection findRecursivePoijiAnnotations(Class typeToInspect, Class annotationType) { List annotations = new ArrayList<>(); for (Field field : typeToInspect.getDeclaredFields()) { Annotation excelCellRange = field.getAnnotation(ExcelCellRange.class); if (excelCellRange != null) { annotations.addAll(findRecursivePoijiAnnotations(field.getType(), annotationType)); } else { A fieldAnnotation = field.getAnnotation(annotationType); if (fieldAnnotation != null) { annotations.add(fieldAnnotation); } } } return annotations; } public static void setFieldData(Field field, Object o, Object instance) { try { setAccessible(field); field.set(instance, o); } catch (IllegalAccessException e) { throw new IllegalCastException("Unexpected cast type {" + o + "} of field" + field.getName()); } } public static void setAccessible(Field field) { if (!field.isAccessible()) { field.setAccessible(true); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy