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

org.lastaflute.di.helper.beans.impl.BeanDescImpl Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2015-2021 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 org.lastaflute.di.helper.beans.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.lastaflute.di.core.util.ClassPoolUtil;
import org.lastaflute.di.exception.EmptyRuntimeException;
import org.lastaflute.di.helper.beans.BeanDesc;
import org.lastaflute.di.helper.beans.PropertyDesc;
import org.lastaflute.di.helper.beans.annotation.ParameterName;
import org.lastaflute.di.helper.beans.exception.BeanConstructorNotFoundException;
import org.lastaflute.di.helper.beans.exception.BeanFieldNotFoundException;
import org.lastaflute.di.helper.beans.exception.BeanFieldSetAccessibleFailureException;
import org.lastaflute.di.helper.beans.exception.BeanIllegalDiiguException;
import org.lastaflute.di.helper.beans.exception.BeanMethodNotFoundException;
import org.lastaflute.di.helper.beans.exception.BeanNoClassDefFoundError;
import org.lastaflute.di.helper.beans.exception.BeanNoSuchFieldError;
import org.lastaflute.di.helper.beans.exception.BeanNoSuchMethodError;
import org.lastaflute.di.helper.beans.exception.BeanPropertyNotFoundException;
import org.lastaflute.di.helper.beans.factory.ParameterizedClassDescFactory;
import org.lastaflute.di.helper.log.LaLogger;
import org.lastaflute.di.util.ArrayMap;
import org.lastaflute.di.util.CaseInsensitiveMap;
import org.lastaflute.di.util.LdiClassUtil;
import org.lastaflute.di.util.LdiConstructorUtil;
import org.lastaflute.di.util.LdiDoubleConversionUtil;
import org.lastaflute.di.util.LdiFieldUtil;
import org.lastaflute.di.util.LdiFloatConversionUtil;
import org.lastaflute.di.util.LdiIntegerConversionUtil;
import org.lastaflute.di.util.LdiLongConversionUtil;
import org.lastaflute.di.util.LdiMethodUtil;
import org.lastaflute.di.util.LdiShortConversionUtil;
import org.lastaflute.di.util.LdiStringUtil;

import javassist.ClassPool;
import javassist.CtBehavior;
import javassist.CtClass;
import javassist.NotFoundException;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.ParameterAnnotationsAttribute;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.StringMemberValue;

/**
 * @author modified by jflute (originated in Seasar)
 */
public class BeanDescImpl implements BeanDesc {

    // ===================================================================================
    //                                                                          Definition
    //                                                                          ==========
    private static final LaLogger logger = LaLogger.getLogger(BeanDescImpl.class);
    private static final Object[] EMPTY_ARGS = new Object[0];
    private static final Class[] EMPTY_PARAM_TYPES = new Class[0];
    private static final String[] EMPTY_STRING_ARRAY = new String[0];
    private static final String PARAMETER_NAME_ANNOTATION = ParameterName.class.getName();

    // ===================================================================================
    //                                                                           Attribute
    //                                                                           =========
    private Class beanClass;
    private Constructor[] constructors;
    private Map, Type> typeVariables;
    private CaseInsensitiveMap propertyDescCache = new CaseInsensitiveMap();
    private Map methodsCache = new HashMap();
    private ArrayMap fieldCache = new ArrayMap();
    private ArrayMap> hiddenFieldCache; // lazy loaded
    private transient Set invalidPropertyNames = new HashSet();
    private Map, String[]> constructorParameterNamesCache;
    private Map methodParameterNamesCache;

    // ===================================================================================
    //                                                                         Constructor
    //                                                                         ===========
    public BeanDescImpl(Class beanClass) throws EmptyRuntimeException {
        if (beanClass == null) {
            throw new EmptyRuntimeException("beanClass");
        }
        try {
            this.beanClass = beanClass;
            constructors = beanClass.getConstructors();
            typeVariables = ParameterizedClassDescFactory.getTypeVariables(beanClass);
            setupPropertyDescs();
            setupMethods();
            setupFields();
        } catch (NoClassDefFoundError e) { // these catches are for e.g. nested class error
            throw new BeanNoClassDefFoundError("Failed to analyze the bean class: " + beanClass.getName(), e);
        } catch (NoSuchMethodError e) {
            throw new BeanNoSuchMethodError("Failed to analyze the bean class: " + beanClass.getName(), e);
        } catch (NoSuchFieldError e) {
            throw new BeanNoSuchFieldError("Failed to analyze the bean class: " + beanClass.getName(), e);
        }
    }

    // ===================================================================================
    //                                                                                Bean
    //                                                                                ====
    public Class getBeanClass() {
        return beanClass;
    }

    // ===================================================================================
    //                                                                   Property Handling
    //                                                                   =================
    public boolean hasPropertyDesc(String propertyName) {
        return propertyDescCache.get(propertyName) != null;
    }

    public PropertyDesc getPropertyDesc(String propertyName) throws BeanPropertyNotFoundException {
        final PropertyDesc pd = (PropertyDesc) propertyDescCache.get(propertyName);
        if (pd == null) {
            String msg = "Not found the bean property: " + beanClass.getName() + "@" + propertyName;
            throw new BeanPropertyNotFoundException(msg, beanClass, propertyName);
        }
        return pd;
    }

    private PropertyDesc getPropertyDesc0(String propertyName) {
        return (PropertyDesc) propertyDescCache.get(propertyName);
    }

    public PropertyDesc getPropertyDesc(int index) {
        return (PropertyDesc) propertyDescCache.get(index);
    }

    public int getPropertyDescSize() {
        return propertyDescCache.size();
    }

    // ===================================================================================
    //                                                                      Field Handling
    //                                                                      ==============
    public boolean hasField(String fieldName) {
        return fieldCache.get(fieldName) != null;
    }

    @Override
    public Field getField(String fieldName) {
        final Field field = fieldCache.get(fieldName);
        if (field == null) {
            throw new BeanFieldNotFoundException(beanClass, fieldName);
        }
        return field;
    }

    @Override
    public int getFieldSize() {
        return fieldCache.size();
    }

    // ===================================================================================
    //                                                                Constructor Handling
    //                                                                ====================
    @Override
    public Object newInstance(Object[] args) throws BeanConstructorNotFoundException {
        Constructor constructor = getSuitableConstructor(args);
        return LdiConstructorUtil.newInstance(constructor, args);
    }

    public Constructor getSuitableConstructor(Object[] args) throws BeanConstructorNotFoundException {
        if (args == null) {
            args = EMPTY_ARGS;
        }
        Constructor constructor = findSuitableConstructor(args);
        if (constructor != null) {
            return constructor;
        }
        constructor = findSuitableConstructorAdjustNumber(args);
        if (constructor != null) {
            return constructor;
        }
        throw new BeanConstructorNotFoundException(beanClass, args);
    }

    private Constructor findSuitableConstructor(Object[] args) {
        outerLoop: for (int i = 0; i < constructors.length; ++i) {
            Class[] paramTypes = constructors[i].getParameterTypes();
            if (paramTypes.length != args.length) {
                continue;
            }
            for (int j = 0; j < args.length; ++j) {
                if (args[j] == null || LdiClassUtil.isAssignableFrom(paramTypes[j], args[j].getClass())) {
                    continue;
                }
                continue outerLoop;
            }
            return constructors[i];
        }
        return null;
    }

    private Constructor findSuitableConstructorAdjustNumber(Object[] args) {
        outerLoop: for (int i = 0; i < constructors.length; ++i) {
            Class[] paramTypes = constructors[i].getParameterTypes();
            if (paramTypes.length != args.length) {
                continue;
            }
            for (int j = 0; j < args.length; ++j) {
                if (args[j] == null || LdiClassUtil.isAssignableFrom(paramTypes[j], args[j].getClass())
                        || adjustNumber(paramTypes, args, j)) {
                    continue;
                }
                continue outerLoop;
            }
            return constructors[i];
        }
        return null;
    }

    public Constructor getConstructor(final Class[] paramTypes) {
        for (int i = 0; i < constructors.length; ++i) {
            if (Arrays.equals(paramTypes, constructors[i].getParameterTypes())) {
                return constructors[i];
            }
        }
        throw new BeanConstructorNotFoundException(beanClass, paramTypes);
    }

    public String[] getConstructorParameterNames(final Class[] parameterTypes) {
        return getConstructorParameterNames(getConstructor(parameterTypes));
    }

    public String[] getConstructorParameterNames(final Constructor constructor) {
        if (constructorParameterNamesCache == null) {
            constructorParameterNamesCache = createConstructorParameterNamesCache();
        }
        if (!constructorParameterNamesCache.containsKey(constructor)) {
            throw new BeanConstructorNotFoundException(beanClass, constructor.getParameterTypes());
        }
        return (String[]) constructorParameterNamesCache.get(constructor);
    }

    private Map, String[]> createConstructorParameterNamesCache() {
        final Map, String[]> map = new HashMap, String[]>();
        final ClassPool pool = ClassPoolUtil.getClassPool(beanClass);
        for (int i = 0; i < constructors.length; ++i) {
            final Constructor constructor = constructors[i];
            if (constructor.getParameterTypes().length == 0) {
                map.put(constructor, EMPTY_STRING_ARRAY);
                continue;
            }
            final CtClass clazz = ClassPoolUtil.toCtClass(pool, constructor.getDeclaringClass());
            final CtClass[] parameterTypes = ClassPoolUtil.toCtClassArray(pool, constructor.getParameterTypes());
            try {
                final String[] names = getParameterNames(clazz.getDeclaredConstructor(parameterTypes));
                map.put(constructor, names);
            } catch (final NotFoundException e) {
                logger.log("WSSR0084", new Object[] { beanClass.getName(), constructor });
            }
        }
        return map;
    }

    // ===================================================================================
    //                                                                     Method Handling
    //                                                                     ===============
    public Object invoke(Object target, String methodName, Object[] args) {
        Method method = getSuitableMethod(methodName, args);
        return LdiMethodUtil.invoke(method, target, args);
    }

    public Method getMethod(final String methodName) {
        return getMethod(methodName, EMPTY_PARAM_TYPES);
    }

    public Method getMethodNoException(final String methodName) {
        return getMethodNoException(methodName, EMPTY_PARAM_TYPES);
    }

    public Method getMethod(final String methodName, final Class[] paramTypes) {
        Method method = getMethodNoException(methodName, paramTypes);
        if (method != null) {
            return method;
        }
        throw new BeanMethodNotFoundException(beanClass, methodName, paramTypes);
    }

    public Method getMethodNoException(final String methodName, final Class[] paramTypes) {
        final Method[] methods = (Method[]) methodsCache.get(methodName);
        if (methods == null) {
            return null;
        }
        for (int i = 0; i < methods.length; ++i) {
            if (Arrays.equals(paramTypes, methods[i].getParameterTypes())) {
                return methods[i];
            }
        }
        return null;
    }

    public Method[] getMethods(String methodName) throws BeanMethodNotFoundException {
        Method[] methods = (Method[]) methodsCache.get(methodName);
        if (methods == null) {
            throw new BeanMethodNotFoundException(beanClass, methodName, null);
        }
        return methods;
    }

    public boolean hasMethod(String methodName) {
        return methodsCache.get(methodName) != null;
    }

    public String[] getMethodNames() {
        return (String[]) methodsCache.keySet().toArray(new String[methodsCache.size()]);
    }

    public String[] getMethodParameterNamesNoException(final String methodName, final Class[] parameterTypes) {
        return getMethodParameterNamesNoException(getMethod(methodName, parameterTypes));
    }

    public String[] getMethodParameterNames(final String methodName, final Class[] parameterTypes) {
        return getMethodParameterNames(getMethod(methodName, parameterTypes));
    }

    public String[] getMethodParameterNames(final Method method) {
        String[] names = getMethodParameterNamesNoException(method);
        if (names == null || names.length != method.getParameterTypes().length) {
            throw new BeanIllegalDiiguException();
        }
        return names;
    }

    public String[] getMethodParameterNamesNoException(final Method method) {
        if (methodParameterNamesCache == null) {
            methodParameterNamesCache = createMethodParameterNamesCache();
        }
        if (!methodParameterNamesCache.containsKey(method)) {
            throw new BeanMethodNotFoundException(beanClass, method.getName(), method.getParameterTypes());
        }
        return (String[]) methodParameterNamesCache.get(method);
    }

    private Map createMethodParameterNamesCache() {
        final Map map = new HashMap();
        final ClassPool pool = ClassPoolUtil.getClassPool(beanClass);
        for (final Iterator it = methodsCache.values().iterator(); it.hasNext();) {
            final Method[] methods = (Method[]) it.next();
            for (int i = 0; i < methods.length; ++i) {
                final Method method = methods[i];
                if (method.getParameterTypes().length == 0) {
                    map.put(methods[i], EMPTY_STRING_ARRAY);
                    continue;
                }
                final CtClass clazz = ClassPoolUtil.toCtClass(pool, method.getDeclaringClass());
                final CtClass[] parameterTypes = ClassPoolUtil.toCtClassArray(pool, method.getParameterTypes());
                try {
                    final String[] names = getParameterNames(clazz.getDeclaredMethod(method.getName(), parameterTypes));
                    map.put(methods[i], names);
                } catch (final NotFoundException e) {
                    logger.log("WSSR0085", new Object[] { beanClass.getName(), method });
                }
            }
        }
        return map;
    }

    private String[] getParameterNames(final CtBehavior behavior) throws NotFoundException {
        final MethodInfo methodInfo = behavior.getMethodInfo();
        final ParameterAnnotationsAttribute attribute =
                (ParameterAnnotationsAttribute) methodInfo.getAttribute(ParameterAnnotationsAttribute.visibleTag);
        if (attribute == null) {
            return null;
        }
        final int numParameters = behavior.getParameterTypes().length;
        final String[] parameterNames = new String[numParameters];
        final Annotation[][] annotationsArray = attribute.getAnnotations();
        if (annotationsArray == null || annotationsArray.length != numParameters) {
            return null;
        }
        for (int i = 0; i < numParameters; ++i) {
            final String parameterName = getParameterName(annotationsArray[i]);
            if (parameterName == null) {
                return null;
            }
            parameterNames[i] = parameterName;
        }
        return parameterNames;
    }

    private String getParameterName(final Annotation[] annotations) {
        Annotation nameAnnotation = null;
        for (int i = 0; i < annotations.length; ++i) {
            final Annotation annotation = annotations[i];
            if (PARAMETER_NAME_ANNOTATION.equals(annotation.getTypeName())) {
                nameAnnotation = annotation;
                break;
            }
        }
        if (nameAnnotation == null) {
            return null;
        }
        return ((StringMemberValue) nameAnnotation.getMemberValue("value")).getValue();
    }

    // ===================================================================================
    //                                                                     Set up Property
    //                                                                     ===============
    protected void setupPropertyDescs() {
        final Method[] methods = beanClass.getMethods();
        for (int i = 0; i < methods.length; i++) {
            final Method method = methods[i];
            if (LdiMethodUtil.isBridgeMethod(method) || LdiMethodUtil.isSyntheticMethod(method)) {
                continue;
            }
            final String methodName = method.getName();
            if (methodName.startsWith("get")) {
                if (method.getParameterTypes().length != 0 || methodName.equals("getClass") || method.getReturnType() == void.class) {
                    continue;
                }
                final String propertyName = decapitalizePropertyName(methodName.substring(3));
                setupReadMethod(method, propertyName);
            } else if (methodName.startsWith("is")) {
                if (method.getParameterTypes().length != 0
                        || !method.getReturnType().equals(Boolean.TYPE) && !method.getReturnType().equals(Boolean.class)) {
                    continue;
                }
                final String propertyName = decapitalizePropertyName(methodName.substring(2));
                setupReadMethod(method, propertyName);
            } else if (methodName.startsWith("set")) {
                if (method.getParameterTypes().length != 1 || methodName.equals("setClass") || method.getReturnType() != void.class) {
                    continue;
                }
                final String propertyName = decapitalizePropertyName(methodName.substring(3));
                setupWriteMethod(method, propertyName);
            }
        }
        for (Iterator i = invalidPropertyNames.iterator(); i.hasNext();) {
            propertyDescCache.remove(i.next());
        }
        invalidPropertyNames.clear();
    }

    private static String decapitalizePropertyName(String name) {
        if (LdiStringUtil.isEmpty(name)) {
            return name;
        }
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isUpperCase(name.charAt(0))) {
            return name;
        }
        final char[] chars = name.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }

    private void addPropertyDesc(PropertyDesc propertyDesc) throws EmptyRuntimeException {
        if (propertyDesc == null) {
            throw new EmptyRuntimeException("propertyDesc");
        }
        propertyDescCache.put(propertyDesc.getPropertyName(), propertyDesc);
    }

    private void setupReadMethod(Method readMethod, String propertyName) {
        final Class propertyType = readMethod.getReturnType();
        final PropertyDesc propDesc = getPropertyDesc0(propertyName);
        if (propDesc != null) {
            if (!propDesc.getPropertyType().equals(propertyType)) {
                invalidPropertyNames.add(propertyName);
            } else {
                propDesc.setReadMethod(readMethod);
            }
        } else {
            addPropertyDesc(new PropertyDescImpl(propertyName, propertyType, readMethod, null, null, this));
        }
    }

    private void setupWriteMethod(Method writeMethod, String propertyName) {
        final Class propertyType = writeMethod.getParameterTypes()[0];
        final PropertyDesc propDesc = getPropertyDesc0(propertyName);
        if (propDesc != null) {
            if (!propDesc.getPropertyType().equals(propertyType)) {
                invalidPropertyNames.add(propertyName);
            } else {
                propDesc.setWriteMethod(writeMethod);
            }
        } else {
            addPropertyDesc(new PropertyDescImpl(propertyName, propertyType, null, writeMethod, null, this));
        }
    }

    private Method getSuitableMethod(String methodName, Object[] args) throws BeanMethodNotFoundException {
        if (args == null) {
            args = EMPTY_ARGS;
        }
        final Method[] methods = getMethods(methodName);
        Method method = findSuitableMethod(methods, args);
        if (method != null) {
            return method;
        }
        method = findSuitableMethodAdjustNumber(methods, args);
        if (method != null) {
            return method;
        }
        throw new BeanMethodNotFoundException(beanClass, methodName, args);
    }

    private Method findSuitableMethod(Method[] methods, Object[] args) {
        outerLoop: for (int i = 0; i < methods.length; ++i) {
            final Class[] paramTypes = methods[i].getParameterTypes();
            if (paramTypes.length != args.length) {
                continue;
            }
            for (int j = 0; j < args.length; ++j) {
                if (args[j] == null || LdiClassUtil.isAssignableFrom(paramTypes[j], args[j].getClass())) {
                    continue;
                }
                continue outerLoop;
            }
            return methods[i];
        }
        return null;
    }

    private Method findSuitableMethodAdjustNumber(Method[] methods, Object[] args) {
        outerLoop: for (int i = 0; i < methods.length; ++i) {
            Class[] paramTypes = methods[i].getParameterTypes();
            if (paramTypes.length != args.length) {
                continue;
            }
            for (int j = 0; j < args.length; ++j) {
                if (args[j] == null || LdiClassUtil.isAssignableFrom(paramTypes[j], args[j].getClass())
                        || adjustNumber(paramTypes, args, j)) {
                    continue;
                }
                continue outerLoop;
            }
            return methods[i];
        }
        return null;
    }

    // ===================================================================================
    //                                                                      Set up Methods
    //                                                                      ==============
    protected void setupMethods() {
        ArrayMap> methodListMap = new ArrayMap>();
        Method[] methods = beanClass.getMethods();
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            if (LdiMethodUtil.isBridgeMethod(method) || LdiMethodUtil.isSyntheticMethod(method)) {
                continue;
            }
            String methodName = method.getName();
            List list = (List) methodListMap.get(methodName);
            if (list == null) {
                list = new ArrayList();
                methodListMap.put(methodName, list);
            }
            list.add(method);
        }
        for (int i = 0; i < methodListMap.size(); ++i) {
            List methodList = (List) methodListMap.get(i);
            methodsCache.put((String) methodListMap.getKey(i), methodList.toArray(new Method[methodList.size()]));
        }
    }

    // ===================================================================================
    //                                                                       Set up Fields
    //                                                                       =============
    protected void setupFields() {
        setupFields(beanClass);
    }

    private void setupFields(Class targetClass) {
        if (targetClass.isInterface()) {
            setupFieldsByInterface(targetClass);
        } else {
            setupFieldsByClass(targetClass);
        }
    }

    private void setupFieldsByInterface(Class interfaceClass) {
        addFields(interfaceClass);
        final Class[] interfaces = interfaceClass.getInterfaces();
        for (int i = 0; i < interfaces.length; ++i) {
            setupFieldsByInterface(interfaces[i]);
        }
    }

    private void setupFieldsByClass(Class targetClass) {
        addFields(targetClass);
        final Class[] interfaces = targetClass.getInterfaces();
        for (int i = 0; i < interfaces.length; ++i) {
            setupFieldsByInterface(interfaces[i]);
        }
        final Class superClass = targetClass.getSuperclass();
        if (superClass != Object.class && superClass != null) {
            setupFieldsByClass(superClass);
        }
    }

    private void addFields(Class clazz) {
        final Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; ++i) {
            final Field field = fields[i];
            final String fname = field.getName();
            if (!fieldCache.containsKey(fname)) {
                beAccessible(field);
                fieldCache.put(fname, field);
                if (LdiFieldUtil.isInstanceField(field)) {
                    if (hasPropertyDesc(fname)) {
                        final PropertyDesc pd = getPropertyDesc(field.getName());
                        pd.setField(field);
                    } else if (LdiFieldUtil.isPublicField(field)) {
                        final PropertyDesc pd = new PropertyDescImpl(field.getName(), field.getType(), null, null, field, this);
                        propertyDescCache.put(fname, pd);
                    }
                }
            } else { // hidden field (to inject them)
                beAccessible(field);
                if (hiddenFieldCache == null) {
                    hiddenFieldCache = new ArrayMap>();
                }
                List hiddenFieldList = hiddenFieldCache.get(fname);
                if (hiddenFieldList == null) {
                    hiddenFieldList = new ArrayList(2);
                    hiddenFieldCache.put(fname, hiddenFieldList);
                }
                hiddenFieldList.add(field);
            }
        }
    }

    private void beAccessible(Field field) {
        if (isExceptPrivateAccessible(field)) {
            return;
        }
        try {
            field.setAccessible(true);
        } catch (RuntimeException e) { // for Java9 headache
            String msg = "Failed to set accessible to the field: " + field;
            throw new BeanFieldSetAccessibleFailureException(msg, beanClass, field, e);
        }
    }

    private boolean isExceptPrivateAccessible(Field field) {
        // to avoid warning of JDK-internal access at Java11
        // Lasta Di does not need private access to the classes
        final String fqcn = field.getDeclaringClass().getName();
        return fqcn.startsWith("java.") || fqcn.startsWith("jdk.") || fqcn.startsWith("com.sun.") || fqcn.startsWith("sun.");
    }

    // ===================================================================================
    //                                                                        Field Access
    //                                                                        ============
    @Override
    public Object getFieldValue(String fieldName, Object target) throws BeanFieldNotFoundException {
        return LdiFieldUtil.get(getField(fieldName), target);
    }

    @Override
    public Field getField(int index) {
        return fieldCache.get(index);
    }

    public List getHiddenFieldList(String fieldName) {
        if (hiddenFieldCache != null) {
            final List fieldList = hiddenFieldCache.get(fieldName);
            if (fieldList != null) {
                return Collections.unmodifiableList(fieldList);
            }
        }
        return Collections.emptyList();
    }

    // ===================================================================================
    //                                                                        Assist Logic
    //                                                                        ============
    private static boolean adjustNumber(Class[] paramTypes, Object[] args, int index) {
        if (paramTypes[index].isPrimitive()) {
            if (paramTypes[index] == int.class) {
                args[index] = LdiIntegerConversionUtil.toInteger(args[index]);
                return true;
            } else if (paramTypes[index] == double.class) {
                args[index] = LdiDoubleConversionUtil.toDouble(args[index]);
                return true;
            } else if (paramTypes[index] == long.class) {
                args[index] = LdiLongConversionUtil.toLong(args[index]);
                return true;
            } else if (paramTypes[index] == short.class) {
                args[index] = LdiShortConversionUtil.toShort(args[index]);
                return true;
            } else if (paramTypes[index] == float.class) {
                args[index] = LdiFloatConversionUtil.toFloat(args[index]);
                return true;
            }
        } else {
            if (paramTypes[index] == Integer.class) {
                args[index] = LdiIntegerConversionUtil.toInteger(args[index]);
                return true;
            } else if (paramTypes[index] == Double.class) {
                args[index] = LdiDoubleConversionUtil.toDouble(args[index]);
                return true;
            } else if (paramTypes[index] == Long.class) {
                args[index] = LdiLongConversionUtil.toLong(args[index]);
                return true;
            } else if (paramTypes[index] == Short.class) {
                args[index] = LdiShortConversionUtil.toShort(args[index]);
                return true;
            } else if (paramTypes[index] == Float.class) {
                args[index] = LdiFloatConversionUtil.toFloat(args[index]);
                return true;
            }
        }
        return false;
    }

    // ===================================================================================
    //                                                                            Accessor
    //                                                                            ========
    Map, Type> getTypeVariables() {
        return typeVariables;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy