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

org.xillium.base.util.Objects Maven / Gradle / Ivy

There is a newer version: 1.2.2
Show newest version
package org.xillium.base.util;

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;
import java.util.regex.*;
import org.xillium.base.Functor;
import org.xillium.base.beans.Beans;
import org.xillium.base.type.typeinfo;


/**
 * Utility class to manipulate deep object properties using a path like notation.
 */
public abstract class Objects {
    private static final Pattern ARRAY_INDEX = Pattern.compile("(.*)\\[([^]]+)\\]");

    /**
     * Reports a property.
     *
     * @param object the target object
     * @param name a dot-separated path to the property
     * @return the property value
     * @throws NoSuchFieldException if the property is not found
     */
    public static Object getProperty(Object object, String name) throws NoSuchFieldException {
        try {
            Matcher matcher = ARRAY_INDEX.matcher(name);
            if (matcher.matches()) {
                object = getProperty(object, matcher.group(1));
                if (object.getClass().isArray()) {
                    return Array.get(object, Integer.parseInt(matcher.group(2)));
                } else {
                    return ((List)object).get(Integer.parseInt(matcher.group(2)));
                }
            } else {
                int dot = name.lastIndexOf('.');
                if (dot > 0) {
                    object = getProperty(object, name.substring(0, dot));
                    name = name.substring(dot + 1);
                }
                return Beans.getKnownField(object.getClass(), name).get(object);
            }
        } catch (NoSuchFieldException x) {
            throw x;
        } catch (Exception x) {
            throw new IllegalArgumentException(x.getMessage() + ": " + name, x);
        }
    }

    /**
     * Updates a property.
     *
     * @param object the target object
     * @param name a dot-separated path to the property
     * @param text a String representation of the new value
     * @throws NoSuchFieldException if the property is not found
     * @throws IllegalArgumentException if the value expression is invalid or can't be assigned to the property
     */
    @SuppressWarnings("unchecked")
    public static void setProperty(Object object, String name, String text) throws NoSuchFieldException {
        try {
            // need to get to the field for any typeinfo annotation, so here we go ...
            int length = name.lastIndexOf('.');
            if (length > 0) {
                object = getProperty(object, name.substring(0, length));
                name = name.substring(length + 1);
            }
            length = name.length();

            Matcher matcher = ARRAY_INDEX.matcher(name);
            for (Matcher m = matcher; m.matches(); m = ARRAY_INDEX.matcher(name)) {
                name = m.group(1);
            }
            Field field = Beans.getKnownField(object.getClass(), name);

            if (name.length() != length) {
                int index = Integer.parseInt(matcher.group(2));
                object = getProperty(object, matcher.group(1));
                if (object.getClass().isArray()) {
                    Array.set(object, index, new ValueOf(object.getClass().getComponentType(), field.getAnnotation(typeinfo.class)).invoke(text));
                } else {
                    ((List)object).set(index, new ValueOf(field.getAnnotation(typeinfo.class).value()[0]).invoke(text));
                }
            } else {
                field.set(object, new ValueOf(field.getType(), field.getAnnotation(typeinfo.class)).invoke(text));
            }
        } catch (NoSuchFieldException x) {
            throw x;
        } catch (Exception x) {
            throw new IllegalArgumentException(x.getMessage() + ": " + name, x);
        }
    }

    /**
     * Concatenates several reference arrays.
     *
     * @param  the type of the elements in the array
     * @param first the first array
     * @param rest the rest of the arrays
     * @return a single array containing all elements in all arrays
     */
    @SafeVarargs
    public static  T[] concat(T[] first, T[]... rest) {
        int length = first.length;
        for (T[] array : rest) {
            length += array.length;
        }
        T[] result = Arrays.copyOf(first, length);
        int offset = first.length;
        for (T[] array : rest) {
            System.arraycopy(array, 0, result, offset, array.length);
            offset += array.length;
        }
        return result;
    }

    /**
     * Concatenates several int arrays.
     *
     * @param first the first array
     * @param rest the rest of the arrays
     * @return a single array containing all elements in all arrays
     */
    public static int[] concat(int[] first, int[]... rest) {
        int length = first.length;
        for (int[] array : rest) {
            length += array.length;
        }
        int[] result = Arrays.copyOf(first, length);
        int offset = first.length;
        for (int[] array : rest) {
            System.arraycopy(array, 0, result, offset, array.length);
            offset += array.length;
        }
        return result;
    }

    /**
     * Appends more elements into an array to form a new array.
     */
//  public static  T[] append(T[] array, T... elements) {
//      T[] result = Arrays.copyOf(array, array.length + elements.length);
//      System.arraycopy(elements, 0, result, array.length, elements.length);
//      return result;
//  }

    /**
     * Stores array elements along with more individuals into a new Object[].
     *
     * @param  the type of the elements in the array
     * @param array an array
     * @param elements a list of elements
     * @return an {@code Object} array containing all elements
     */
    public static  Object[] store(T[] array, Object... elements) {
        Object[] result = new Object[array.length + elements.length];
        System.arraycopy(array, 0, result, 0, array.length);
        System.arraycopy(elements, 0, result, array.length, elements.length);
        return result;
    }

    /**
     * Invokes a functor over all elements in an array, and returns the results in a provided array.
     * 
     *  result = functor(array)
     * 
     *
     * @param  the result type of the functor
     * @param  the type of the elements in the array
     * @param result an array to store functor return values
     * @param array an array
     * @param functor a functor
     * @return an array containing invocation results
     */
    public static  R[] apply(R[] result, T[] array, Functor functor) {
        for (int i = 0; i < array.length; ++i) result[i] = functor.invoke(array[i]);
        return result;
    }

    /**
     * Parses an array of Strings as int's, and returns the produced values in a new array.
     */
//  public static int[] parse(String[] text) {
//      int[] array = new int[text.length];
//      for (int i = 0; i < array.length; ++i) {
//          array[i] = Integer.parseInt(text[i]);
//      }
//      return array;
//  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy