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

org.valkyriercp.util.ObjectUtils Maven / Gradle / Ivy

There is a newer version: 1.3
Show newest version
package org.valkyriercp.util;

import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.*;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.valkyriercp.binding.form.FormModel;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Utility class for dealing with objects.
 *
 * @author Julio Argüello (JAF)
 */
public final class ObjectUtils {

    /**
     * The logger.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ObjectUtils.class);

    /**
     * Utility classes should have a private constructor.
     */
    private ObjectUtils() {

        super();
    }

    /**
     * Gets the value of a given property into a given bean.
     *
     * @param 
     *            the bean type.
     * @param bean
     *            the bean itself.
     * @param propertyName
     *            the property name.
     *
     * @return the property value.
     *
     * @see #getPropertyValue(Object, String, Class)
     */
    public static  Object getPropertyValue(Q bean, String propertyName) {

        return ObjectUtils.getPropertyValue(bean, propertyName, Object.class);
    }

    /**
     * Gets the value of a given property into a given bean.
     *
     * @param 
     *            the property type.
     * @param 
     *            the bean type.
     * @param bean
     *            the bean itself.
     * @param propertyName
     *            the property name.
     * @param propertyType
     *            the property type.
     * @return the property value.
     *
     * @see PropertyAccessorFactory
     */
    @SuppressWarnings("unchecked")
    public static  T getPropertyValue(Q bean, String propertyName, Class propertyType) {

        Assert.notNull(bean, "bean");
        Assert.notNull(propertyName, "propertyName");

        final PropertyAccessor propertyAccessor = PropertyAccessorFactory.forDirectFieldAccess(bean);

        try {
            Assert.isAssignable(propertyType, propertyAccessor.getPropertyType(propertyName));
        } catch (InvalidPropertyException e) {
            throw new IllegalStateException("Invalid property \"" + propertyName + "\"", e);
        }

        return (T) propertyAccessor.getPropertyValue(propertyName);
    }

    /**
     * Makes a shallow copy of the source object into the target one.
     * 

* This method differs from {@link ReflectionUtils#shallowCopyFieldState(Object, Object)} this doesn't require * source and target objects to share the same class hierarchy. * * @param source * the source object. * @param target * the target object. */ public static void shallowCopy(Object source, Object target) { ObjectUtils.doShallowCopy(source, target, Boolean.TRUE); } /** * Makes a shallow copy of the source object into the target one excluding properties not in * propertyNames. *

* This method differs from {@link ReflectionUtils#shallowCopyFieldState(Object, Object)} this doesn't require * source and target objects to share the same class hierarchy. * * @param source * the source object. * @param target * the target object. * @param propertyNames * the property names to be processed. Never mind if property names are invalid, in such a case are * ignored. */ public static void shallowCopy(Object source, Object target, final String... propertyNames) { ObjectUtils.doShallowCopy(source, target, Boolean.FALSE, propertyNames); } /** * Get all declared fields on the leaf class and all superclasses. Leaf class methods are included first. * * @param leafClass * the leaf class. * @return all declared fields. * * @see ReflectionUtils#getAllDeclaredMethods(Class) since is the same approach as this one. */ public static Field[] getAllDeclaredFields(Class leafClass) { Assert.notNull(leafClass, "leafClass"); final List fields = new ArrayList(32); ReflectionUtils.doWithFields(leafClass, new ReflectionUtils.FieldCallback() { @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { fields.add(field); } }); return fields.toArray(new Field[fields.size()]); } /** * Method based on * {@link org.apache.commons.collections.ListUtils#isEqualList(java.util.Collection, java.util.Collection)} rewrote * for performance reasons. *

* Basically employs {@link ObjectUtils#equals(Object, Object)} instead of {@link #equals(Object)} since the first * one checks identity before calling equals. * * @param * the type of the elements in the list. * @param list1 * the first list, may be null * @param list2 * the second list, may be null * * @return whether the lists are equal by value comparison */ public static Boolean isEqualList(List list1, List list2) { if (list1 == list2) { return Boolean.TRUE; } else if ((list1 == null) || (list2 == null) || (list1.size() != list2.size())) { return Boolean.FALSE; } final Iterator itr1 = list1.iterator(); final Iterator itr2 = list2.iterator(); Object obj1 = null; Object obj2 = null; while (itr1.hasNext() && itr2.hasNext()) { obj1 = itr1.next(); obj2 = itr2.next(); if (!(obj1 == null ? obj2 == null : org.apache.commons.lang.ObjectUtils.equals(obj1, obj2))) { return Boolean.FALSE; } } return !(itr1.hasNext() || itr2.hasNext()); } /** * This is a utility method for getting raw objects that may have been proxied. It is intended to be used in cases * where raw implementations are needed rather than working with interfaces which they implement. * * @param bean * the potential proxy. * @return the most inner unwrapped bean. * * @see #unwrapProxy(Object, Boolean) * @since 20101223 thanks to BLUE-34 */ public static Object unwrapProxy(Object bean) { return ObjectUtils.unwrapProxy(bean, Boolean.TRUE); } /** * This is a utility method for getting raw objects that may have been proxied. It is intended to be used in cases * where raw implementations are needed rather than working with interfaces which they implement. * * @param bean * the potential proxy. * @param recursive * whether to procceeed recursively through nested proxies. * @return the unwrapped bean or null if target bean is null. If recursive * parameter is true then returns the most inner unwrapped bean, otherwise the nearest target * bean is returned. * * Based on this Spring forum topic. * @see Advised * @since 20101223 thanks to BLUE-34 */ public static Object unwrapProxy(Object bean, Boolean recursive) { Assert.notNull(recursive, "recursive"); Object unwrapped = bean; // If the given object is a proxy, set the return value as the object being proxied, otherwise return the given // object if ((bean != null) && (bean instanceof Advised) && (AopUtils.isAopProxy(bean))) { final Advised advised = (Advised) bean; try { final Object target = advised.getTargetSource().getTarget(); unwrapped = recursive ? ObjectUtils.unwrapProxy(target, recursive) : target; } catch (Exception e) { unwrapped = bean; ObjectUtils.LOGGER.warn("Failure unwrapping \"" + bean + "\".", e); } } return unwrapped; } /** * Makes a shallow copy of the source object into the target one excluding properties not in * propertyNames unless allProperties is true. *

* This method differs from {@link ReflectionUtils#shallowCopyFieldState(Object, Object)} this doesn't require * source and target objects to share the same class hierarchy. * * @param source * the source object. * @param target * the target object. * @param allProperties * if true then propertyNames will be ignored and all properties processed. * @param propertyNames * the property names to be processed. Never mind if property names are invalid, in such a case are * ignored. */ private static void doShallowCopy(Object source, Object target, final Boolean allProperties, final String... propertyNames) { Assert.notNull(source, "source"); Assert.notNull(target, "target"); Assert.notNull(allProperties, "allProperties"); Assert.notNull(propertyNames, "propertyNames"); final PropertyAccessor sourceAccessor = PropertyAccessorFactory.forDirectFieldAccess(source); final PropertyAccessor targetAccessor = PropertyAccessorFactory.forDirectFieldAccess(target); // Try to copy every property ReflectionUtils.doWithFields(source.getClass(), new ReflectionUtils.FieldCallback() { /** * {@inheritDoc} */ @Override public void doWith(Field field) { // throws IllegalArgumentException, IllegalAccessException { final String fieldName = field.getName(); Boolean proceed = !Modifier.isFinal(field.getModifiers()); proceed &= (targetAccessor.isWritableProperty(fieldName)); proceed &= (allProperties | ArrayUtils.contains(propertyNames, fieldName)); if (proceed) { final Object value = sourceAccessor.getPropertyValue(fieldName); targetAccessor.setPropertyValue(fieldName, value); } } }); } /** * This method tries to map the values of the given object on the valueModels of the formModel. Instead of * setting the object as a backing object, all valueModels are processed one by one and the corresponding * property value is fetched from the objectToMap and set on that valueModel. This triggers the usual * buffering etc. just as if the user entered the values. * * @param formModel * @param objectToMap */ public static void mapObjectOnFormModel(FormModel formModel, Object objectToMap) { BeanWrapper beanWrapper = new BeanWrapperImpl(objectToMap); for (String fieldName : (Set) formModel.getFieldNames()) { try { formModel.getValueModel(fieldName).setValue(beanWrapper.getPropertyValue(fieldName)); } catch (BeansException be) { // silently ignoring, just mapping values, so if there's one missing, don't bother } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy