Example usage for java.lang.reflect Method getParameterCount

List of usage examples for java.lang.reflect Method getParameterCount

Introduction

In this page you can find the example usage for java.lang.reflect Method getParameterCount.

Prototype

public int getParameterCount() 

Source Link

Usage

From source file:org.springframework.beans.factory.support.ConstructorResolver.java

/**
 * Instantiate the bean using a named factory method. The method may be static, if the
 * bean definition parameter specifies a class, rather than a "factory-bean", or
 * an instance variable on a factory object itself configured using Dependency Injection.
 * <p>Implementation requires iterating over the static or instance methods with the
 * name specified in the RootBeanDefinition (the method may be overloaded) and trying
 * to match with the parameters. We don't have the types attached to constructor args,
 * so trial and error is the only way to go here. The explicitArgs array may contain
 * argument values passed in programmatically via the corresponding getBean method.
 * @param beanName the name of the bean//from   ww w . j av a2s  . c o m
 * @param mbd the merged bean definition for the bean
 * @param explicitArgs argument values passed in programmatically via the getBean
 * method, or {@code null} if none (-> use constructor argument values from bean definition)
 * @return a BeanWrapper for the new instance
 */
public BeanWrapper instantiateUsingFactoryMethod(final String beanName, final RootBeanDefinition mbd,
        @Nullable final Object[] explicitArgs) {

    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);

    Object factoryBean;
    Class<?> factoryClass;
    boolean isStatic;

    String factoryBeanName = mbd.getFactoryBeanName();
    if (factoryBeanName != null) {
        if (factoryBeanName.equals(beanName)) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "factory-bean reference points back to the same bean definition");
        }
        factoryBean = this.beanFactory.getBean(factoryBeanName);
        if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
            throw new ImplicitlyAppearedSingletonException();
        }
        factoryClass = factoryBean.getClass();
        isStatic = false;
    } else {
        // It's a static factory method on the bean class.
        if (!mbd.hasBeanClass()) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "bean definition declares neither a bean class nor a factory-bean reference");
        }
        factoryBean = null;
        factoryClass = mbd.getBeanClass();
        isStatic = true;
    }

    Method factoryMethodToUse = null;
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;

    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    } else {
        Object[] argsToResolve = null;
        synchronized (mbd.constructorArgumentLock) {
            factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
            if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                // Found a cached factory method...
                argsToUse = mbd.resolvedConstructorArguments;
                if (argsToUse == null) {
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }
        if (argsToResolve != null) {
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
        }
    }

    if (factoryMethodToUse == null || argsToUse == null) {
        // Need to determine the factory method...
        // Try all methods with this name to see if they match the given arguments.
        factoryClass = ClassUtils.getUserClass(factoryClass);

        Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
        List<Method> candidateSet = new ArrayList<>();
        for (Method candidate : rawCandidates) {
            if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                candidateSet.add(candidate);
            }
        }
        Method[] candidates = candidateSet.toArray(new Method[0]);
        AutowireUtils.sortFactoryMethods(candidates);

        ConstructorArgumentValues resolvedValues = null;
        boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        int minTypeDiffWeight = Integer.MAX_VALUE;
        Set<Method> ambiguousFactoryMethods = null;

        int minNrOfArgs;
        if (explicitArgs != null) {
            minNrOfArgs = explicitArgs.length;
        } else {
            // We don't have arguments passed in programmatically, so we need to resolve the
            // arguments specified in the constructor arguments held in the bean definition.
            if (mbd.hasConstructorArgumentValues()) {
                ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                resolvedValues = new ConstructorArgumentValues();
                minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
            } else {
                minNrOfArgs = 0;
            }
        }

        LinkedList<UnsatisfiedDependencyException> causes = null;

        for (Method candidate : candidates) {
            Class<?>[] paramTypes = candidate.getParameterTypes();

            if (paramTypes.length >= minNrOfArgs) {
                ArgumentsHolder argsHolder;

                if (explicitArgs != null) {
                    // Explicit arguments given -> arguments length must match exactly.
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }
                    argsHolder = new ArgumentsHolder(explicitArgs);
                } else {
                    // Resolved constructor arguments: type conversion and/or autowiring necessary.
                    try {
                        String[] paramNames = null;
                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                        if (pnd != null) {
                            paramNames = pnd.getParameterNames(candidate);
                        }
                        argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes,
                                paramNames, candidate, autowiring, candidates.length == 1);
                    } catch (UnsatisfiedDependencyException ex) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName
                                    + "': " + ex);
                        }
                        // Swallow and try next overloaded factory method.
                        if (causes == null) {
                            causes = new LinkedList<>();
                        }
                        causes.add(ex);
                        continue;
                    }
                }

                int typeDiffWeight = (mbd.isLenientConstructorResolution()
                        ? argsHolder.getTypeDifferenceWeight(paramTypes)
                        : argsHolder.getAssignabilityWeight(paramTypes));
                // Choose this factory method if it represents the closest match.
                if (typeDiffWeight < minTypeDiffWeight) {
                    factoryMethodToUse = candidate;
                    argsHolderToUse = argsHolder;
                    argsToUse = argsHolder.arguments;
                    minTypeDiffWeight = typeDiffWeight;
                    ambiguousFactoryMethods = null;
                }
                // Find out about ambiguity: In case of the same type difference weight
                // for methods with the same number of parameters, collect such candidates
                // and eventually raise an ambiguity exception.
                // However, only perform that check in non-lenient constructor resolution mode,
                // and explicitly ignore overridden methods (with the same parameter signature).
                else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight
                        && !mbd.isLenientConstructorResolution()
                        && paramTypes.length == factoryMethodToUse.getParameterCount()
                        && !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {
                    if (ambiguousFactoryMethods == null) {
                        ambiguousFactoryMethods = new LinkedHashSet<>();
                        ambiguousFactoryMethods.add(factoryMethodToUse);
                    }
                    ambiguousFactoryMethods.add(candidate);
                }
            }
        }

        if (factoryMethodToUse == null) {
            if (causes != null) {
                UnsatisfiedDependencyException ex = causes.removeLast();
                for (Exception cause : causes) {
                    this.beanFactory.onSuppressedException(cause);
                }
                throw ex;
            }
            List<String> argTypes = new ArrayList<>(minNrOfArgs);
            if (explicitArgs != null) {
                for (Object arg : explicitArgs) {
                    argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
                }
            } else if (resolvedValues != null) {
                Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
                valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
                valueHolders.addAll(resolvedValues.getGenericArgumentValues());
                for (ValueHolder value : valueHolders) {
                    String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType())
                            : (value.getValue() != null ? value.getValue().getClass().getSimpleName()
                                    : "null"));
                    argTypes.add(argType);
                }
            }
            String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "No matching factory method found: "
                            + (mbd.getFactoryBeanName() != null
                                    ? "factory bean '" + mbd.getFactoryBeanName() + "'; "
                                    : "")
                            + "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. "
                            + "Check that a method with the specified name "
                            + (minNrOfArgs > 0 ? "and arguments " : "") + "exists and that it is "
                            + (isStatic ? "static" : "non-static") + ".");
        } else if (void.class == factoryMethodToUse.getReturnType()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid factory method '"
                    + mbd.getFactoryMethodName() + "': needs to have a non-void return type!");
        } else if (ambiguousFactoryMethods != null) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Ambiguous factory method matches found in bean '" + beanName + "' "
                            + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): "
                            + ambiguousFactoryMethods);
        }

        if (explicitArgs == null && argsHolderToUse != null) {
            argsHolderToUse.storeCache(mbd, factoryMethodToUse);
        }
    }

    try {
        Object beanInstance;

        if (System.getSecurityManager() != null) {
            final Object fb = factoryBean;
            final Method factoryMethod = factoryMethodToUse;
            final Object[] args = argsToUse;
            beanInstance = AccessController.doPrivileged(
                    (PrivilegedAction<Object>) () -> this.beanFactory.getInstantiationStrategy()
                            .instantiate(mbd, beanName, this.beanFactory, fb, factoryMethod, args),
                    this.beanFactory.getAccessControlContext());
        } else {
            beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(mbd, beanName,
                    this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);
        }

        bw.setBeanInstance(beanInstance);
        return bw;
    } catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean instantiation via factory method failed", ex);
    }
}

From source file:ca.oson.json.Oson.java

private <T> T setSingleMapValue(T obj, Class<T> valueType, Object singleMapValue, Class singleMapValueType) {
    if (obj == null || valueType == null || singleMapValue == null || singleMapValueType == null) {
        return obj;
    }//  www.ja v a2  s  . com

    //check all methods
    // and invoke the right one
    // public static InetAddress getByName(String host)
    //Map<String, Method> setters = getSetters(valueType);
    for (Method method : valueType.getDeclaredMethods()) {
        if (method.getParameterCount() == 1) {
            if (ObjectUtil.isSameDataType(method.getParameterTypes()[0], singleMapValueType)) {
                Object object = ObjectUtil.getMethodValue(obj, method, singleMapValue);

                if (object != null && valueType.isAssignableFrom(object.getClass())) {
                    return (T) object;
                }
            }

        }

    }

    return obj;
}

From source file:ca.oson.json.Oson.java

private <T> void processMethods(Class<T> valueType, String fullName) {
    //      Stream<Method> stream = Arrays.stream(valueType.getDeclaredMethods());
    //      while (valueType != null && valueType != Object.class) {
    //         stream = Stream.concat(stream, Arrays.stream(valueType
    //               .getSuperclass().getDeclaredMethods()));
    //         valueType = (Class<T>) valueType.getSuperclass();
    //      }/*w ww.j  av a2 s . c  o  m*/

    Map<String, Method> setters = new LinkedHashMap<>();
    Map<String, Method> getters = new LinkedHashMap<>();
    Map<String, Method> others = new LinkedHashMap<>();

    String name;
    boolean notSetGetOnly = !getSetGetOnly();
    boolean completed = false;
    Class classType = valueType;
    int depth = 0;
    while (!completed && classType != null && classType != Object.class) {
        //for (Method method: stream.collect(Collectors.toList())) {
        for (Method method : classType.getDeclaredMethods()) {
            name = method.getName();

            if (name.startsWith("set")) {
                if (name.length() > 3 && method.getParameterCount() == 1) {
                    setters.put(name.substring(3).toLowerCase(), method);
                } else {
                    others.put(name.toLowerCase(), method);
                }

            } else if (name.startsWith("get")) {
                if (name.length() > 3 && method.getParameterCount() == 0
                        && !void.class.equals(method.getReturnType())) {
                    getters.put(name.substring(3).toLowerCase(), method);
                } else {
                    others.put(name.toLowerCase(), method);
                }

            } else if (notSetGetOnly && method.getParameterCount() == 0
                    && !void.class.equals(method.getReturnType())) {
                getters.put(name.toLowerCase(), method);

            } else if (notSetGetOnly && method.getParameterCount() == 1) {
                setters.put(name.toLowerCase(), method);

            } else {
                others.put(name.toLowerCase(), method);
            }
        }

        if (depth > 1 && (getters.size() > 0 || setters.size() > 0)) {
            completed = true;
        } else {
            classType = classType.getSuperclass();
            depth++;
        }
    }

    Map<String, Method>[] all = new HashMap[3];

    all[METHOD.GET.value] = getters;
    all[METHOD.SET.value] = setters;
    all[METHOD.OTHER.value] = others;
    cachedMethods.put(fullName, all);
}

From source file:ca.oson.json.Oson.java

<T> T newInstance(Map<String, Object> map, Class<T> valueType) {
    InstanceCreator creator = getTypeAdapter(valueType);

    if (creator != null) {
        return (T) creator.createInstance(valueType);
    }//from w  ww  .ja v a2s . co  m

    T obj = null;

    if (valueType != null) {
        obj = (T) getDefaultValue(valueType);
        if (obj != null) {
            return obj;
        }
    }

    if (map == null) {
        return null;
    }

    // @JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = As.PROPERTY, property = "@class")
    //@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = As.PROPERTY, property = "@class")
    String JsonClassType = null;

    if (valueType != null) {
        if (getAnnotationSupport()) {
            for (Annotation annotation : valueType.getAnnotations()) {
                if (annotation instanceof JsonTypeInfo) {
                    JsonTypeInfo jsonTypeInfo = (JsonTypeInfo) annotation;
                    JsonTypeInfo.Id use = jsonTypeInfo.use();
                    JsonTypeInfo.As as = jsonTypeInfo.include();
                    if ((use == JsonTypeInfo.Id.MINIMAL_CLASS || use == JsonTypeInfo.Id.CLASS)
                            && as == As.PROPERTY) {
                        JsonClassType = jsonTypeInfo.property();
                    }
                }
            }
        }
    }
    if (JsonClassType == null) {
        JsonClassType = getJsonClassType();
    }

    String className = null;
    if (map.containsKey(JsonClassType)) {
        className = map.get(JsonClassType).toString();
    }

    Class<T> classType = getClassType(className);

    //  && (valueType == null || valueType.isAssignableFrom(classType) || Map.class.isAssignableFrom(valueType))
    if (classType != null) {
        valueType = classType;
    }

    if (valueType == null) {
        return (T) map; // or null, which is better?
    }

    Constructor<?>[] constructors = null;

    Class implClass = null;
    if (valueType.isInterface() || Modifier.isAbstract(valueType.getModifiers())) {
        implClass = DeSerializerUtil.implementingClass(valueType.getName());
    }

    if (implClass != null) {
        constructors = implClass.getDeclaredConstructors();
    } else {
        constructors = valueType.getDeclaredConstructors();//.getConstructors();
    }

    Object singleMapValue = null;
    Class singleMapValueType = null;
    if (map.size() == 1) {
        singleMapValue = map.get(valueType.getName());

        if (singleMapValue != null) {
            singleMapValueType = singleMapValue.getClass();

            if (singleMapValueType == String.class) {
                singleMapValue = StringUtil.unquote(singleMapValue.toString(), isEscapeHtml());
            }

            try {
                if (valueType == Locale.class) {
                    Constructor constructor = null;
                    String[] parts = ((String) singleMapValue).split("_");
                    if (parts.length == 1) {
                        constructor = valueType.getConstructor(String.class);
                        constructor.setAccessible(true);
                        obj = (T) constructor.newInstance(singleMapValue);
                    } else if (parts.length == 2) {
                        constructor = valueType.getConstructor(String.class, String.class);
                        constructor.setAccessible(true);
                        obj = (T) constructor.newInstance(parts);
                    } else if (parts.length == 3) {
                        constructor = valueType.getConstructor(String.class, String.class, String.class);
                        constructor.setAccessible(true);
                        obj = (T) constructor.newInstance(parts);
                    }

                    if (obj != null) {
                        return obj;
                    }
                }
            } catch (Exception e) {
            }

            Map<Class, Constructor> cmaps = new HashMap<>();
            for (Constructor constructor : constructors) {
                //Class[] parameterTypes = constructor.getParameterTypes();

                int parameterCount = constructor.getParameterCount();
                if (parameterCount == 1) {

                    Class[] types = constructor.getParameterTypes();

                    cmaps.put(types[0], constructor);
                }
            }

            if (cmaps.size() > 0) {
                Constructor constructor = null;

                if ((cmaps.containsKey(Boolean.class) || cmaps.containsKey(boolean.class))
                        && BooleanUtil.isBoolean(singleMapValue.toString())) {
                    constructor = cmaps.get(Boolean.class);
                    if (constructor == null) {
                        constructor = cmaps.get(boolean.class);
                    }
                    if (constructor != null) {
                        try {
                            constructor.setAccessible(true);
                            obj = (T) constructor
                                    .newInstance(BooleanUtil.string2Boolean(singleMapValue.toString()));

                            if (obj != null) {
                                return obj;
                            }
                        } catch (Exception e) {
                        }
                    }

                } else if (StringUtil.isNumeric(singleMapValue.toString())) {

                    Class[] classes = new Class[] { int.class, Integer.class, long.class, Long.class,
                            double.class, Double.class, Byte.class, byte.class, Short.class, short.class,
                            Float.class, float.class, BigDecimal.class, BigInteger.class, AtomicInteger.class,
                            AtomicLong.class, Number.class };

                    for (Class cls : classes) {
                        constructor = cmaps.get(cls);

                        if (constructor != null) {
                            try {
                                obj = (T) constructor.newInstance(NumberUtil.getNumber(singleMapValue, cls));

                                if (obj != null) {
                                    return obj;
                                }
                            } catch (Exception e) {
                            }
                        }
                    }

                } else if (StringUtil.isArrayOrList(singleMapValue.toString())
                        || singleMapValue.getClass().isArray()
                        || Collection.class.isAssignableFrom(singleMapValue.getClass())) {
                    for (Entry<Class, Constructor> entry : cmaps.entrySet()) {
                        Class cls = entry.getKey();
                        constructor = entry.getValue();

                        if (cls.isArray() || Collection.class.isAssignableFrom(cls)) {
                            Object listObject = null;
                            if (singleMapValue instanceof String) {
                                JSONArray objArray = new JSONArray(singleMapValue.toString());
                                listObject = (List) fromJsonMap(objArray);
                            } else {
                                listObject = singleMapValue;
                            }

                            FieldData objectDTO = new FieldData(listObject, cls, true);
                            listObject = json2Object(objectDTO);
                            if (listObject != null) {
                                try {
                                    obj = (T) constructor.newInstance(listObject);
                                    if (obj != null) {
                                        return obj;
                                    }
                                } catch (Exception e) {
                                }
                            }
                        }

                    }

                }

                for (Entry<Class, Constructor> entry : cmaps.entrySet()) {
                    Class cls = entry.getKey();
                    constructor = entry.getValue();
                    try {
                        obj = (T) constructor.newInstance(singleMapValue);
                        if (obj != null) {
                            return obj;
                        }
                    } catch (Exception e) {
                    }
                }

            }

        }
    }

    if (implClass != null) {
        valueType = implClass;
    }

    try {
        obj = valueType.newInstance();

        if (obj != null) {
            return setSingleMapValue(obj, valueType, singleMapValue, singleMapValueType);
        }

    } catch (InstantiationException | IllegalAccessException e) {
        //e.printStackTrace();
    }

    ///*
    for (Constructor constructor : constructors) {
        //Class[] parameterTypes = constructor.getParameterTypes();

        int parameterCount = constructor.getParameterCount();
        if (parameterCount > 0) {
            constructor.setAccessible(true);

            Annotation[] annotations = constructor.getDeclaredAnnotations(); // getAnnotations();

            for (Annotation annotation : annotations) {
                boolean isJsonCreator = false;
                if (annotation instanceof JsonCreator) {
                    isJsonCreator = true;
                } else if (annotation instanceof ca.oson.json.annotation.FieldMapper) {
                    ca.oson.json.annotation.FieldMapper fieldMapper = (ca.oson.json.annotation.FieldMapper) annotation;

                    if (fieldMapper.jsonCreator() == BOOLEAN.TRUE) {
                        isJsonCreator = true;
                    }
                }

                if (isJsonCreator) {
                    Parameter[] parameters = constructor.getParameters();
                    String[] parameterNames = ObjectUtil.getParameterNames(parameters);

                    //parameterCount = parameters.length;
                    Object[] parameterValues = new Object[parameterCount];
                    int i = 0;
                    for (String parameterName : parameterNames) {
                        parameterValues[i] = getParameterValue(map, valueType, parameterName,
                                parameters[i].getType());
                        i++;
                    }

                    try {
                        obj = (T) constructor.newInstance(parameterValues);

                        if (obj != null) {
                            return setSingleMapValue(obj, valueType, singleMapValue, singleMapValueType);
                        }

                    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                            | InvocationTargetException e) {
                        //e.printStackTrace();
                    }
                }
            }

        } else {
            try {
                constructor.setAccessible(true);
                obj = (T) constructor.newInstance();

                if (obj != null) {
                    return setSingleMapValue(obj, valueType, singleMapValue, singleMapValueType);
                }

            } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException e) {
                //e.printStackTrace();
            }

        }
    }
    //*/

    // try again
    for (Constructor constructor : constructors) {
        int parameterCount = constructor.getParameterCount();
        if (parameterCount > 0) {
            constructor.setAccessible(true);

            try {
                List<String> parameterNames = ObjectUtil.getParameterNames(constructor);

                if (parameterNames != null && parameterNames.size() > 0) {
                    Class[] parameterTypes = constructor.getParameterTypes();

                    int length = parameterTypes.length;
                    if (length == parameterNames.size()) {
                        Object[] parameterValues = new Object[length];
                        Object parameterValue;
                        for (int i = 0; i < length; i++) {
                            parameterValues[i] = getParameterValue(map, valueType, parameterNames.get(i),
                                    parameterTypes[i]);
                        }

                        try {
                            obj = (T) constructor.newInstance(parameterValues);
                            if (obj != null) {
                                return setSingleMapValue(obj, valueType, singleMapValue, singleMapValueType);
                            }

                        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                                | InvocationTargetException e) {
                            //e.printStackTrace();
                        }

                    }
                }

            } catch (IOException e1) {
                // e1.printStackTrace();
            }
        }
    }

    // try more
    for (Constructor constructor : constructors) {
        int parameterCount = constructor.getParameterCount();
        if (parameterCount > 0) {
            constructor.setAccessible(true);

            Class[] parameterTypes = constructor.getParameterTypes();
            List<String> parameterNames;
            try {
                parameterNames = ObjectUtil.getParameterNames(constructor);

                if (parameterNames != null) {
                    int length = parameterTypes.length;

                    if (length > parameterNames.size()) {
                        length = parameterNames.size();
                    }

                    Object[] parameterValues = new Object[length];
                    for (int i = 0; i < length; i++) {
                        parameterValues[i] = getParameterValue(map, valueType, parameterNames.get(i),
                                parameterTypes[i]);
                    }

                    obj = (T) constructor.newInstance(parameterValues);
                    if (obj != null) {
                        return setSingleMapValue(obj, valueType, singleMapValue, singleMapValueType);
                    }
                }

            } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException | IOException e) {
                //e.printStackTrace();
            }
        }
    }

    // try more
    try {
        Method[] methods = valueType.getMethods(); // .getMethod("getInstance", null);

        List<Method> methodList = new ArrayList<>();

        if (methods != null) {
            for (Method method : methods) {
                String methodName = method.getName();

                if (methodName.equals("getInstance") || methodName.equals("newInstance")
                        || methodName.equals("createInstance") || methodName.equals("factory")) {
                    Class returnType = method.getReturnType();

                    if (valueType.isAssignableFrom(returnType) && Modifier.isStatic(method.getModifiers())) {
                        int parameterCount = method.getParameterCount();
                        if (parameterCount == 0) {
                            try {
                                obj = ObjectUtil.getMethodValue(null, method);
                                if (obj != null) {
                                    return setSingleMapValue(obj, valueType, singleMapValue,
                                            singleMapValueType);
                                }

                            } catch (IllegalArgumentException e) {
                                // TODO Auto-generated catch block
                                //e.printStackTrace();
                            }

                        } else {
                            methodList.add(method);
                        }

                    }
                }
            }

            for (Method method : methodList) {
                try {
                    int parameterCount = method.getParameterCount();
                    Object[] parameterValues = new Object[parameterCount];
                    Object parameterValue;
                    int i = 0;
                    Class[] parameterTypes = method.getParameterTypes();

                    String[] parameterNames = ObjectUtil.getParameterNames(method);

                    if (parameterCount == 1 && valueType != null && singleMapValue != null
                            && singleMapValueType != null) {

                        if (ObjectUtil.isSameDataType(parameterTypes[0], singleMapValueType)) {
                            try {
                                obj = ObjectUtil.getMethodValue(null, method, singleMapValue);
                                if (obj != null) {
                                    return obj;
                                }

                            } catch (IllegalArgumentException ex) {
                                //ex.printStackTrace();
                            }

                        }

                    } else if (parameterNames != null && parameterNames.length == parameterCount) {
                        for (String parameterName : ObjectUtil.getParameterNames(method)) {
                            parameterValues[i] = getParameterValue(map, valueType, parameterName,
                                    parameterTypes[i]);
                            i++;
                        }

                    } else {
                        // try annotation
                        Parameter[] parameters = method.getParameters();
                        parameterNames = ObjectUtil.getParameterNames(parameters);
                        parameterCount = parameters.length;
                        parameterValues = new Object[parameterCount];
                        i = 0;
                        for (String parameterName : parameterNames) {
                            parameterValues[i] = getParameterValue(map, valueType, parameterName,
                                    parameterTypes[i]);
                            i++;
                        }
                    }

                    obj = ObjectUtil.getMethodValue(null, method, parameterValues);

                    if (obj != null) {
                        return setSingleMapValue(obj, valueType, singleMapValue, singleMapValueType);
                    }

                } catch (IOException | IllegalArgumentException e) {
                    //e.printStackTrace();
                }
            }

        }

    } catch (SecurityException e) {
        // e.printStackTrace();
    }

    // try all static methods, if the return type is correct, get it as the final object
    Method[] methods = valueType.getDeclaredMethods();
    for (Method method : methods) {
        if (Modifier.isStatic(method.getModifiers())) {
            Class returnType = method.getReturnType();

            if (valueType.isAssignableFrom(returnType)) {
                try {
                    Object[] parameterValues = null;

                    int parameterCount = method.getParameterCount();
                    if (parameterCount > 0) {
                        if (parameterCount == 1 && map.size() == 1 && singleMapValue != null
                                && singleMapValueType != null) {
                            if (ObjectUtil.isSameDataType(method.getParameterTypes()[0], singleMapValueType)) {
                                obj = ObjectUtil.getMethodValue(null, method, singleMapValueType);
                                if (obj != null) {
                                    return obj;
                                }
                            }
                        }

                        parameterValues = new Object[parameterCount];
                        Object parameterValue;
                        int i = 0;
                        Class[] parameterTypes = method.getParameterTypes();

                        String[] parameterNames = ObjectUtil.getParameterNames(method);
                        if (parameterNames != null && parameterNames.length == parameterCount) {
                            for (String parameterName : ObjectUtil.getParameterNames(method)) {
                                parameterValues[i] = getParameterValue(map, valueType, parameterName,
                                        parameterTypes[i]);
                                i++;
                            }

                        } else {
                            // try annotation
                            Parameter[] parameters = method.getParameters();
                            parameterNames = ObjectUtil.getParameterNames(parameters);
                            parameterCount = parameters.length;
                            parameterValues = new Object[parameterCount];
                            i = 0;
                            for (String parameterName : parameterNames) {
                                parameterValues[i] = getParameterValue(map, valueType, parameterName,
                                        parameterTypes[i]);
                                i++;
                            }
                        }
                    }

                    obj = ObjectUtil.getMethodValue(obj, method, parameterValues);
                    if (obj != null) {
                        return setSingleMapValue(obj, valueType, singleMapValue, singleMapValueType);
                    }

                } catch (IOException | IllegalArgumentException e) {
                    //e.printStackTrace();
                }

            }
        }

    }

    return null;
}