org.xmlsh.util.JavaUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.xmlsh.util.JavaUtils.java

Source

/**
 * $Id: $
 * $Date: $
 *
 */

package org.xmlsh.util;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.XdmAtomicValue;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XdmValue;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.xmlsh.core.CoreException;
import org.xmlsh.core.InvalidArgumentException;
import org.xmlsh.core.XValue;
import org.xmlsh.sh.shell.SerializeOpts;
import org.xmlsh.sh.shell.Shell;

public class JavaUtils {

    private static Set<String> mReserved;
    private static Logger mLogger = LogManager.getLogger();

    // Words that could not make valid class names so cant otherwise be used as commands or functions

    static {
        mReserved = new HashSet<String>();
        mReserved.add("class");
        mReserved.add("boolean");
        mReserved.add("int");
        mReserved.add("double");
        mReserved.add("true");
        mReserved.add("false");
        mReserved.add("long");
        mReserved.add("char");
        mReserved.add("null");
        mReserved.add("float");
        mReserved.add("byte");
        mReserved.add("short");
        mReserved.add("package");
        mReserved.add("new");

    }

    public static boolean isReserved(String n) {
        return mReserved.contains(n);
    }

    public static XValue newXValue(Class<?> cls, List<XValue> args) throws InstantiationException,
            IllegalAccessException, IllegalArgumentException, InvocationTargetException, CoreException {
        Constructor<?>[] constructors = cls.getConstructors();
        return newXValue(cls, constructors, args);

    }

    public static XValue newXValue(Class<?> cls, Constructor<?>[] constructors, List<XValue> args)
            throws CoreException, InstantiationException, IllegalAccessException, IllegalArgumentException,
            InvocationTargetException {
        Constructor<?> c = getBestMatch(args, constructors);
        if (c == null)
            throw new InvalidArgumentException(
                    "No construtor match found for: " + cls.getName() + "(" + getArgClassesString(args) + ")");

        Object obj = c.newInstance(getArgs(c.getParameterTypes(), args));
        return XValue.newXValue(null, obj);
    }

    public static XValue newXValue(String classname, List<XValue> args, ClassLoader classloader) throws Exception {
        Class<?> cls = findClass(classname, classloader);
        return newXValue(cls, args);

    }

    public static Class<?> findClass(String classname, ClassLoader classloader) throws ClassNotFoundException {
        Class<?> cls = Class.forName(classname, true, classloader);
        return cls;
    }

    public static <T> T newObject(Class<T> cls, Object... args) throws InvalidArgumentException,
            InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        @SuppressWarnings("unchecked")
        Constructor<T>[] constructors = (Constructor<T>[]) cls.getConstructors();
        Constructor<T> c = getBestConstructor(constructors, args);
        if (c == null)
            throw new InvalidArgumentException("Cannot find constructor for: " + cls.getName());
        return c.newInstance(args);
    }

    public static XValue callStatic(String classname, String methodName, List<XValue> args, ClassLoader classloader)
            throws Exception {
        Class<?> cls = findClass(classname, classloader);
        Method m = getBestMatch(cls, methodName, args, true);

        if (m == null)
            throw new InvalidArgumentException("No method match found for: " + classname + "." + methodName + "("
                    + getArgClassesString(args) + ")");

        return callStaticMethod(m, args);
    }

    public static XValue callStaticMethod(Method m, List<XValue> args)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, CoreException {
        Object obj = m.invoke(null, getArgs(m.getParameterTypes(), args));
        // Special case for null - use formal return type to cast to right XValue type
        if (obj == null) {
            if (String.class.isAssignableFrom(m.getReturnType()))
                return XValue.newXValue((String) null);
            else
                return XValue.newXValue(null, (Object) null);
        }

        return XValue.newXValue(null, obj);
    }

    public static String getArgClassesString(List<XValue> args) {
        StringBuffer sb = new StringBuffer();
        for (XValue arg : args) {
            if (sb.length() > 0)
                sb.append(",");
            sb.append(arg.asObject().getClass().getName());

        }
        return sb.toString();
    }

    public static XValue callMethod(XValue instance, String methodName, List<XValue> args, ClassLoader classloader)
            throws Exception {
        Class<?> cls = instance.asObject().getClass();
        Method m = getBestMatch(cls, methodName, args, false);

        if (m == null)
            throw new InvalidArgumentException("No method match found for: " + cls.getName() + "." + methodName);

        return callMethod(m, instance.asObject(), args);
    }

    public static XValue callMethod(Method m, Object instance, List<XValue> args)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, CoreException {
        Object obj = m.invoke(instance, getArgs(m.getParameterTypes(), args));

        // Special case for null - use formal return type to cast to right XValue type
        if (obj == null) {
            if (String.class.isAssignableFrom(m.getReturnType()))
                return XValue.newXValue((String) null);
            else
                return XValue.newXValue(null, (Object) null);
        }

        return XValue.newXValue(null, obj);
    }

    public static Method getBestMatch(Class<?> cls, String methodName, List<XValue> args, boolean bStatic)
            throws CoreException {

        return getBestMatch(cls.getMethods(), methodName, args, bStatic);
    }

    public static Method getBestMatch(Method[] methods, String methodName, List<XValue> args, boolean bStatic)
            throws CoreException {

        Method best = null;
        int bestConversions = 0;

        for (Method m : methods) {
            int conversions = 0;
            if (m.getName().equals(methodName)) {
                boolean isStatic = (m.getModifiers() & Modifier.STATIC) == Modifier.STATIC;
                if (bStatic && !isStatic)
                    continue;

                Class<?>[] params = m.getParameterTypes();
                if (params.length == args.size()) {
                    int i = 0;
                    for (XValue arg : args) {
                        int conversion = arg.canConvert(params[i]);
                        if (conversion < 0)
                            break;
                        i++;
                        conversions += conversion;
                    }
                    if (i == params.length) {

                        if (best == null || conversions < bestConversions) {
                            best = m;
                            bestConversions = conversions;
                        }
                    }

                }

            }

        }
        return best;

    }

    public static Object[] getArgs(Class<?>[] params, List<XValue> args) throws CoreException {

        Object[] ret = new Object[params.length];
        int i = 0;
        for (XValue arg : args) {
            ret[i] = arg.convert(params[i]);
            i++;
        }

        return ret;

    }

    public static Object[] convertObjects(Class<?>[] params, List<Object> args) throws CoreException,
            InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        Object[] ret = new Object[params.length];
        int i = 0;
        for (Object arg : args) {
            ret[i] = convert(arg, params[i]);
            i++;
        }

        return ret;

    }

    public static Constructor<?> getBestMatch(List<XValue> args, Constructor<?>[] constructors)
            throws CoreException {

        Constructor<?> best = null;
        int bestConversions = 0;

        // TODO how to choose best match

        for (Constructor<?> c : constructors) {
            Class<?>[] params = c.getParameterTypes();
            if (params.length == args.size()) {
                int conversions = 0;
                int i = 0;
                for (XValue arg : args) {
                    int convert = arg.canConvert(params[i]);
                    if (convert < 0)
                        break;
                    conversions += convert;
                    i++;
                }
                if (i == params.length) {
                    // Find best match
                    if (best == null || conversions < bestConversions) {
                        best = c;
                        bestConversions = conversions;

                    }

                }

            }

        }
        return best;
    }

    public static <T> Constructor<T> getBestConstructor(Constructor<T>[] constructors, Object... argValues)
            throws InvalidArgumentException {

        Constructor<T> best = null;
        int bestConversions = 0;

        // TODO how to choose best match

        for (Constructor<T> c : constructors) {
            Class<?>[] params = c.getParameterTypes();
            if (params.length == argValues.length) {
                int conversions = 0;
                int i = 0;
                for (Object obj : argValues) {
                    int convert = canConvertObject(obj, params[i]);
                    if (convert < 0)
                        break;
                    conversions += convert;
                    i++;
                }
                if (i == params.length) {
                    // Find best match
                    if (best == null || conversions < bestConversions) {
                        best = c;
                        bestConversions = conversions;

                    }
                }
            }

        }
        return best;
    }

    public static int hasBeanConstructor(Class<?> targetClass, Class<?> sourceClass)
            throws InvalidArgumentException {

        Constructor<?> c = getBeanConstructor(targetClass, sourceClass);
        if (c == null)
            return -1;

        if (c.getParameterTypes()[0].isAssignableFrom(sourceClass))
            return 3;
        else
            return 4;
    }

    // Does the target hava a single method constructor from a convertable source
    public static Constructor<?> getBeanConstructor(Class<?> targetClass, Class<?> sourceClass)
            throws InvalidArgumentException {
        try {
            Constructor<?> c = targetClass.getConstructor(sourceClass);
            if (c != null)
                return c;

        } catch (NoSuchMethodException | SecurityException e) {
            mLogger.info("Exception getting constructors for: " + targetClass.getName(), e);
            return null;
        }

        Constructor<?>[] cs = targetClass.getConstructors();

        for (Constructor<?> c : cs) {
            Class<?>[] params = c.getParameterTypes();
            if (params.length == 1) {
                int convert = canConvertClass(sourceClass, params[0]);
                if (convert >= 0)
                    return c;
            }
        }
        return null;
    }

    static private final Class<?> mNumberWrappers[] = new Class<?>[] { Integer.class, Long.class, Byte.class,
            Short.class, Number.class, AtomicInteger.class, AtomicLong.class, BigDecimal.class, BigInteger.class,
            Double.class, Float.class };

    public static boolean isWrappedOrPrimativeNumber(Class<?> c) {
        if (c == null)
            return false;
        if (c.isPrimitive() && !(c == Void.TYPE || c == Boolean.TYPE))
            return true;
        for (Class<?> w : mNumberWrappers)
            if (c.isAssignableFrom(w))
                return true;

        return false;
    }

    public static Class<?> fromPrimativeName(String name) {

        switch (name) {
        case "boolean":
            return java.lang.Boolean.TYPE;
        case "char":
            return java.lang.Character.TYPE;
        case "byte":
            return java.lang.Byte.TYPE;
        case "short":
            return java.lang.Short.TYPE;
        case "int":
            return java.lang.Integer.TYPE;
        case "long":
            return java.lang.Long.TYPE;
        case "float":
            return java.lang.Float.TYPE;
        case "double":
            return java.lang.Double.TYPE;
        case "void":
            return java.lang.Void.TYPE;
        default:
            return null;
        }

    }

    public static <T> T convert(Object value, Class<T> targetClass) throws InvalidArgumentException {

        assert (targetClass != null);

        assert (value != null);
        if (targetClass.isInstance(value))
            return targetClass.cast(value);

        Class<?> sourceClass = value.getClass();

        // Asking for an XdmValue class
        if (XdmValue.class.isAssignableFrom(targetClass)) {
            if (value instanceof XdmNode)
                return (T) (XdmValue) value;

            if (targetClass.isAssignableFrom(XdmAtomicValue.class)) {

                // Try some smart conversions of all types XdmAtomicValue knows
                if (value instanceof Boolean)
                    return (T) new XdmAtomicValue(((Boolean) value).booleanValue());
                else if (value instanceof Double)
                    return (T) new XdmAtomicValue(((Double) value).doubleValue());
                else if (value instanceof Float)
                    return (T) new XdmAtomicValue(((Float) value).floatValue());

                else if (value instanceof BigDecimal)
                    return (T) new XdmAtomicValue((BigDecimal) value);
                else if (value instanceof BigDecimal)
                    return (T) new XdmAtomicValue((BigDecimal) value);

                else if (value instanceof URI)
                    return (T) new XdmAtomicValue((URI) value);
                else if (value instanceof Long)
                    return (T) new XdmAtomicValue((Long) value);
                else if (value instanceof QName)
                    return (T) new XdmAtomicValue((QName) value);

                // Still wanting an xdm value
            }

            if (isAtomic(value))
                return (T) new XdmAtomicValue(value.toString());

        }

        boolean bAtomic = isAtomic(value);
        Class<?> vclass = value.getClass();

        if (targetClass.isPrimitive() && bAtomic) {

            /* Try to match non-primative types
            */
            if (targetClass == Integer.TYPE) {
                if (vclass == Long.class)
                    value = Integer.valueOf(((Long) value).intValue());
                else if (vclass == Short.class)
                    value = Integer.valueOf(((Short) value).intValue());
                else if (vclass == Byte.class)
                    value = Integer.valueOf(((Byte) value).intValue());
                else
                    value = Integer.valueOf(value.toString());

            } else if (targetClass == Long.TYPE) {
                if (vclass == Integer.class)
                    value = Long.valueOf(((Integer) value).intValue());
                else if (vclass == Short.class)
                    value = Long.valueOf(((Short) value).intValue());
                else if (vclass == Byte.class)
                    value = Long.valueOf(((Byte) value).intValue());
                value = Long.valueOf(value.toString());

            }

            else if (targetClass == Short.TYPE) {
                if (vclass == Integer.class)
                    value = Short.valueOf((short) ((Integer) value).intValue());
                else if (vclass == Long.class)
                    value = Short.valueOf((short) ((Long) value).intValue());
                else if (vclass == Byte.class)
                    value = Short.valueOf((short) ((Byte) value).intValue());
                value = Short.valueOf(value.toString());

            }

            else if (targetClass == Byte.TYPE) {
                if (vclass == Integer.class)
                    value = Byte.valueOf((byte) ((Integer) value).intValue());
                else if (vclass == Long.class)
                    value = Byte.valueOf((byte) ((Long) value).intValue());
                else if (vclass == Short.class)
                    value = Byte.valueOf((byte) ((Short) value).intValue());
                value = Byte.valueOf(value.toString());
            } else
                ; // skip

            return (T) value;
        }

        // Bean constructor

        Constructor<?> cnst = getBeanConstructor(targetClass, sourceClass);
        if (cnst != null)
            try {
                return (T) cnst.newInstance(convert(value, cnst.getParameterTypes()[0]));
            } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException e) {

                mLogger.debug("Exception converting argument for constructor", e);
            }

        // Cast through string

        String svalue = value.toString();

        if (targetClass == Integer.class)
            value = Integer.valueOf(svalue);
        else if (targetClass == Long.class)
            value = Long.valueOf(svalue);
        else if (targetClass == Short.class)
            value = Short.valueOf(svalue);
        else if (targetClass == Float.class)
            value = Float.valueOf(svalue);
        else if (targetClass == Double.class)
            value = Double.valueOf(svalue);
        else
            value = null;

        return (T) value;

    }

    public static Object getFieldValue(String classname, XValue instance, String fieldName, ClassLoader classloader)
            throws InvalidArgumentException, SecurityException, NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException, ClassNotFoundException {
        Class<?> cls = findClass(classname, classloader);
        return getFieldValue(cls, instance == null ? null : instance.asObject(), fieldName, classloader);
    }

    public static Object getFieldValue(Class<?> cls, Object instance, String fieldName, ClassLoader classloader)
            throws InvalidArgumentException, SecurityException, NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException, ClassNotFoundException {
        assert (cls != null);
        assert (fieldName != null);

        Field f = cls.getField(fieldName);

        if (f == null)
            throw new InvalidArgumentException("No field match found for: " + cls.getName() + "." + fieldName);

        Object obj = f.get(instance == null ? null : instance);
        return obj;
    }

    public static int canConvertClass(Class<?> sourceClass, Class<?> targetClass) throws InvalidArgumentException {

        assert (targetClass != null);
        if (targetClass == null)
            return -1;

        // Null case
        if (sourceClass == null) {

            if (XdmValue.class.isAssignableFrom(targetClass))
                return 3;
            return -1;
        }
        // Equal class
        if (sourceClass.equals(targetClass))
            return 0;

        // Directly assignable
        if (targetClass.isAssignableFrom(sourceClass))
            return 1;

        boolean sourceNum = isWrappedOrPrimativeNumber(sourceClass);
        boolean targetNum = isWrappedOrPrimativeNumber(targetClass);

        // Boxable 
        // int <-> Integer
        if (sourceNum && targetNum)
            return 2;

        boolean soruceString = isStringClass(sourceClass);

        // TypeFamily conversion TO XdmValue 
        if (XdmValue.class.isAssignableFrom(targetClass)) {
            if (XdmNode.class.isAssignableFrom(sourceClass))
                return 1;
            if (XdmAtomicValue.class.isAssignableFrom(sourceClass))
                return 2;

            if (sourceNum || soruceString || isBooleanClass(sourceClass))
                return 3;
            if (isAtomic(sourceClass))
                return 3;
        }

        boolean targetString = isStringClass(targetClass);
        if (targetClass.isPrimitive() && soruceString)
            // convert string to primative, yes
            return 4;

        if (targetString)
            return 5;

        int c = hasBeanConstructor(targetClass, sourceClass);
        if (c >= 0)
            return 5 + c;

        return -1;

    }

    public static int canConvertObject(Object sourceObject, Class<?> targetClass) throws InvalidArgumentException {
        return canConvertClass(sourceObject.getClass(), targetClass);
    }

    public static Class<?> convertToClass(XValue arg, Shell shell) throws CoreException {
        return convertToClass(arg, shell.getClassLoader(null));

    }

    public static Class<?> convertToClass(XValue arg, ClassLoader classLoader) {
        if (arg.isAtomic() && arg.isString())
            try {
                return findClass(arg.toString(), classLoader);
            } catch (ClassNotFoundException e) {
                mLogger.catching(e);
                return null;
            }
        Object obj = arg.asObject();
        if (obj instanceof Class)
            return (Class<?>) obj;
        return obj.getClass();

    }

    public static byte[] toByteArray(Object value, SerializeOpts opts) throws UnsupportedEncodingException {
        return value.toString().getBytes(opts.getOutput_text_encoding());

    }

    public static int getSize(Object obj) {
        if (obj == null)

            if (obj instanceof Collection)
                return ((Collection<?>) obj).size();
        if (obj instanceof Array)
            Array.getLength(obj);

        return 1;

    }

    public static boolean isNullClass(Class<?> cls) {
        return cls == null;
    }

    public static boolean isContainer(Object obj) {
        return isContainerClass(obj.getClass());
    }

    public static boolean isContainerClass(Class<?> cls) {
        if (cls == null)
            return false;
        if (Collection.class.isAssignableFrom(cls) || Array.class.isAssignableFrom(cls))
            return true;
        return false;

    }

    public static boolean isArrayClass(Class<?> cls) {
        if (cls == null)
            return false;
        if (List.class.isAssignableFrom(cls) || Array.class.isAssignableFrom(cls))
            return true;
        return false;

    }

    public static boolean isObjectClass(Class<?> cls) {
        if (cls == null)
            return false;
        return (!isAtomicClass(cls));

    }

    public static boolean isBooleanClass(Class<?> c) {
        return c == Boolean.TYPE || Boolean.class.isAssignableFrom(c);

    }

    //DAL: TODO: See 1.3
    public static boolean isStringClass(Class<?> cls) {

        return String.class.isAssignableFrom(cls) || CharSequence.class.isAssignableFrom(cls);

    }

    public static boolean isAtomicClass(Class<?> cls) {
        return cls.isEnum() || isWrappedOrPrimativeNumber(cls) || isStringClass(cls);

    }

    public static boolean isClassClass(Class<?> cls) {
        return Class.class.isAssignableFrom(cls);
    }

    public static Object stringConcat(Object o, Object that) {

        return o.toString() + that.toString();
    }

    public static boolean isNumber(String v) {
        return toNumber(v, null) != null;
    }

    // Is a or attomic collection type that is empty 
    public static boolean isEmpty(Object value) {

        if (isAtomic(value))
            return isAtomicEmpty(value);
        else
            return isObjectEmpty(value);

    }

    public static boolean isObjectEmpty(Object value) {

        if (value instanceof Collection)
            return ((Collection<?>) value).isEmpty();
        if (value instanceof Map)
            return ((Map<?, ?>) value).isEmpty();
        if (value.getClass().isArray())
            return Array.getLength(value) == 0;
        return false;
    }

    private static boolean isAtomicEmpty(Object value) {
        return value == null || value.toString().isEmpty();

    }

    private static boolean isAtomic(Object value) {
        return isAtomicClass(value.getClass());
    }

    public static void setNameIndexedValue(Object obj, String ind, Object object) throws NoSuchFieldException,
            SecurityException, InvalidArgumentException, IllegalArgumentException, IllegalAccessException {
        Field f = obj.getClass().getField(ind);
        if (f == null)
            throw new InvalidArgumentException("No field match found for: " + getClassName(obj) + "." + ind);
        f.set(obj, object);
    }

    public static String getClassName(Object obj) {
        assert (obj != null);
        if (obj == null)
            return "";
        return obj.getClass().getName();
    }

    @SuppressWarnings("rawtypes")
    public static void setNamePositionalValue(Object obj, int index, Object object)
            throws InvalidArgumentException {
        if (obj.getClass().isArray()) {
            Array.set(obj, index, object);
        } else if (obj instanceof List) {
            ((List) obj).set(index, object);
        } else
            throw new InvalidArgumentException("No positional index for class: " + getClassName(obj));
    }

    public static boolean isArrayOf(Object value, Class<?> cls) {
        return value.getClass().isArray() && cls.isAssignableFrom(value.getClass().getComponentType());
    }

    public static Object getIndexValue(Object obj, int index) {
        Object res = null;
        if (obj.getClass().isArray()) {
            res = Array.get(obj, index);
        } else if (obj instanceof List) {
            res = ((List<?>) obj).get(index);
        }
        return res;
    }

    public static <T> List<T> getValues(Object obj) {

        if (obj.getClass().isArray()) {
            Object array = obj;
            int len = ArrayUtils.getLength(array);
            ArrayList<T> list = new ArrayList<>(len);
            for (int i = 0; i < len; i++)
                list.add((T) Array.get(array, i));

            return list;
        }
        if (obj instanceof Collection) {
            @SuppressWarnings({ "rawtypes", "unchecked" })
            Collection<T> c = ((Collection) obj);
            ArrayList<T> list = new ArrayList<>(c.size());
            list.addAll(c);
            return list;

        }
        return (List<T>) Collections.singletonList(obj);

    }

    public static boolean isCollection(Object obj) {
        return obj instanceof Collection;
    }

    public static String simpleTypeName(Object value) {
        if (value == null)
            return "null";
        Class<?> cls = value.getClass();
        if (isStringClass(cls))
            return "string";
        if (isArrayClass(cls))
            return "array";

        if (isWrappedOrPrimativeNumber(cls))
            return "number";
        return "object";

    }

    public static boolean hasKey(Object obj, String key) {
        if (obj instanceof Map)
            return ((Map) obj).containsKey(key);
        return false;

    }

    public static Object getNameIndexValue(Object obj, String ind) throws CoreException {
        if (obj instanceof Map)
            return ((Map) obj).get(ind);

        try {
            return getFieldValue(obj.getClass(), obj, ind, null);
        } catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException
                | ClassNotFoundException e) {
            Util.wrapCoreException("Exception getting value from java class: " + obj.getClass().getName(), e);
        }
        return null;

    }

    public static boolean isList(Object obj) {
        return isArrayClass(obj.getClass()) || obj instanceof List;
    }

    public static Package convertToPackage(XValue arg) {
        if (arg.isAtomic() && arg.isString())
            return Package.getPackage(arg.toString());
        Object obj = arg.asObject();
        if (obj instanceof Package)
            return (Package) arg.asObject();
        return null;

    }

    public static String convertToCamelCase(String name) {
        if (name.indexOf('-') < 0)
            return name;

        String parts[] = name.split("-");
        if (parts.length == 1)
            return name;

        StringBuilder result = new StringBuilder(name.length());

        for (String p : parts) {
            if (p.length() == 0)
                continue;

            if (result.length() == 0)
                result.append(p);
            else {
                result.append(Character.toUpperCase(p.charAt(0)));
                result.append(p.substring(1));
            }

        }

        return result.toString();

    }

    public static String convertFromCamelCase(String name) {
        StringBuilder result = new StringBuilder(name.length());
        for (char c : name.toCharArray()) {
            if (Character.isUpperCase(c)) {
                result.append('-');
                result.append(Character.toLowerCase(c));
            } else
                result.append(c);
        }
        return result.toString();
    }

    public static <T> List<T> uniqueList(List<T> list) {
        if (list == null)
            return null;
        Set<T> set = new HashSet<T>(list);
        if (set.size() == list.size())
            return list;

        set.clear();
        List<T> alist = new ArrayList<>(set.size());
        for (T item : list) {
            if (set.contains(item))
                continue;
            set.add(item);
            alist.add(item);
        }
        return alist;

    }

    public static Class<?> getContainedType(Object value) {

        Class<?> c = getClass(value);

        return c.getComponentType();

    }

    public static Class<?> getClass(Object value) {
        assert (value != null);
        if (value instanceof Class)
            return (Class<?>) value;
        return value.getClass();
    }

    public static boolean isContainerOf(Object obj, Class<?> c) {
        assert (obj != null);
        return isArrayOf(obj, c) || isCollectionOf(obj, c);
    }

    public static Number toNumber(String v, Number def) {
        try {
            if (Util.isInt(v, true))
                return Long.parseLong(v);
            return Double.parseDouble(v);
        } catch (NumberFormatException e) {
            // silent
            return def;
        }
    }

    public static boolean isCollectionOf(Object obj, Class<?> c) {
        if (obj instanceof Collection) {
            Collection col = (Collection<?>) obj;
            if (col.isEmpty())
                return true; // sure WTF
            return ClassUtils.isAssignable(col.iterator().next().getClass(), c);

        }

        return false;

    }

    public static String toGetterName(String f) {

        return "get" + toFirstUpperCase(f);

    }

    public static String toSetterName(String f) {

        return "set" + toFirstUpperCase(f);

    }

    protected static String toFirstUpperCase(String f) {
        return Character.toUpperCase(f.charAt(0)) + f.substring(1);
    }

}

//
//
//Copyright (C) 2008-2014 David A. Lee.
//
//The contents of this file are subject to the "Simplified BSD License" (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.opensource.org/licenses/bsd-license.php 
//
//Software distributed under the License is distributed on an "AS IS" basis,
//WITHOUT WARRANTY OF ANY KIND, either express or implied.
//See the License for the specific language governing rights and limitations under the License.
//
//The Original Code is: all this file.
//
//The Initial Developer of the Original Code is David A. Lee
//
//Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
//
//Contributor(s): none.
//