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

com.x5.util.ObjectDataMap Maven / Gradle / Ivy

There is a newer version: 3.6.2
Show newest version
package com.x5.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * ObjectDataMap
 *
 * Box POJO/Bean/DataCapsule inside a Map.  When accessed, pry into object
 * using reflection/introspection/capsule-export and pull out all public
 * member fields/properties.
 * Convert field names from camelCase to lower_case_with_underscores
 * Convert bean properties from getSomeProperty() to some_property
 *  or isVeryHappy() to is_very_happy
 *
 * Values returned are copies, frozen at time of first access.
 *
 */
@SuppressWarnings("rawtypes")
public class ObjectDataMap implements Map
{
    private Map pickle = null;
    private Object object;
    private boolean isBean = false;

    private static final Map EMPTY_MAP = new HashMap();

    private static final HashSet> WRAPPER_TYPES = getWrapperTypes();

    private static HashSet> getWrapperTypes()
    {
        HashSet> ret = new HashSet>();
        ret.add(Boolean.class);
        ret.add(Character.class);
        ret.add(Byte.class);
        ret.add(Short.class);
        ret.add(Integer.class);
        ret.add(Long.class);
        ret.add(Float.class);
        ret.add(Double.class);
        ret.add(Void.class);
        return ret;
    }

    public static boolean isWrapperType(Class clazz)
    {
        return WRAPPER_TYPES.contains(clazz);
    }

    public ObjectDataMap(Object pojo)
    {
        this.object = pojo;
    }

    private void init()
    {
        if (pickle == null) {
            pickle = mapify(object);
            // prevent multiple expensive calls to mapify
            // when result is null
            if (pickle == null) {
                pickle = EMPTY_MAP;
            }
        }
    }

    public static ObjectDataMap wrapBean(Object bean)
    {
        if (bean == null) return null;
        ObjectDataMap boxedBean = new ObjectDataMap(bean);
        boxedBean.isBean = true;

        return boxedBean;
    }

    @SuppressWarnings("unused")
    private Map mapify(Object pojo)
    {
        if (pojo instanceof DataCapsule) {
            return mapifyCapsule((DataCapsule)pojo);
        } else if (isBean) {
            try {
                // java.beans.* is missing on android.
                // Test for existence before use...
                try {
                    Class beanClass = Class.forName("java.beans.Introspector");
                    return StandardIntrospector.mapifyBean(pojo);
                } catch (ClassNotFoundException e) {
                    try {
                        Class madrobotClass = Class.forName("com.madrobot.beans.Introspector");
                        return MadRobotIntrospector.mapifyBean(pojo);
                    } catch (ClassNotFoundException e2) {
                        // soldier on, treat as pojo
                    }
                }
            } catch (IntrospectionException e) {
                // hmm, not a bean after all...
            }
        }

        Field[] fields = pojo.getClass().getDeclaredFields();
        Map pickle = null;

        for (int i=0; i();
                // convert isActive to is_active
                paramName = splitCamelCase(paramName);
                storeValue(pickle, paramClass, paramName, paramValue, isBean);
            }
        }

        return pickle;
    }

    private Map mapifyCapsule(DataCapsule capsule)
    {
        DataCapsuleReader reader = DataCapsuleReader.getReader(capsule);

        String[] tags = reader.getColumnLabels(null);
        Object[] data = reader.extractData(capsule);

        pickle = new HashMap();
        for (int i=0; i pickle, Class paramClass,
                            String paramName, Object paramValue, boolean isBean)
    {
        if (paramClass.isArray() || paramValue instanceof List) {
            pickle.put(paramName, paramValue);
        } else if (paramClass == String.class) {
            pickle.put(paramName, paramValue);
        } else if (paramValue instanceof Boolean) {
            if (((Boolean)paramValue).booleanValue()) {
                pickle.put(paramName, "TRUE");
            }
        } else if (paramClass.isPrimitive() || isWrapperType(paramClass)) {
            pickle.put(paramName, paramValue.toString());
        } else {
            // box all non-primitive object member fields
            // in their own ObjectDataMap wrapper.
            // lazy init guarantees no infinite recursion here.
            ObjectDataMap boxedParam = isBean ? wrapBean(paramValue) : new ObjectDataMap(paramValue);
            pickle.put(paramName, boxedParam);
        }

    }

    // splitCamelCase converts SimpleXMLStuff to Simple_XML_Stuff
    public static String splitCamelCase(String s)
    {
       return s.replaceAll(
          String.format("%s|%s|%s",
             "(?<=[A-Z])(?=[A-Z][a-z])",
             "(?<=[^A-Z])(?=[A-Z])",
             "(?<=[A-Za-z])(?=[^A-Za-z])"
          ),
          "_"
       ).toLowerCase();
    }

    public int size()
    {
        init();
        return pickle.size();
    }

    public boolean isEmpty()
    {
        init();
        return pickle.isEmpty();
    }

    public boolean containsKey(Object key)
    {
        init();
        return pickle.containsKey(key);
    }

    public boolean containsValue(Object value)
    {
        init();
        return pickle.containsValue(value);
    }

    public Object get(Object key)
    {
        init();
        return pickle.get(key);
    }

    public Object put(Object key, Object value)
    {
        // unsupported
        return null;
    }

    public Object remove(Object key)
    {
        // unsupported
        return null;
    }

    public void putAll(Map m)
    {
        // unsupported
    }

    public void clear()
    {
        // unsupported
    }

    public Set keySet()
    {
        init();
        return pickle.keySet();
    }

    public Collection values()
    {
        init();
        return pickle.values();
    }

    public Set entrySet()
    {
        init();
        return pickle.entrySet();
    }

    private static class IntrospectionException extends Exception
    {
        private static final long serialVersionUID = 8890979383599687484L;
    }

    private static class StandardIntrospector
    {
        private static Map mapifyBean(Object bean)
        throws IntrospectionException
        {
            PropertyDescriptor[] properties = null;
            try {
                BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
                properties = beanInfo.getPropertyDescriptors();
            } catch (java.beans.IntrospectionException e) {
                throw new IntrospectionException();
            }

            if (properties == null) return null;

            Map pickle = null;

            // copy properties into hashtable
            for (PropertyDescriptor property : properties) {
                Class paramClass = property.getPropertyType();
                Method getter = property.getReadMethod();
                try {
                    Object paramValue = getter.invoke(bean, (Object[])null);

                    if (paramValue != null) {
                        // converts isActive() to is_active
                        // converts getBookTitle() to book_title
                        String paramName = property.getName();
                        paramName = splitCamelCase(paramName);
                        if (paramValue instanceof Boolean) {
                            paramName = "is_"+paramName;
                        }

                        if (pickle == null) pickle = new HashMap();

                        storeValue(pickle, paramClass, paramName, paramValue, true);
                    }
                } catch (InvocationTargetException e) {
                } catch (IllegalAccessException e) {
                }
            }

            return pickle;
        }
    }

    // mad robot provides a stopgap introspection library for android projects
    private static class MadRobotIntrospector
    {
        private static Map mapifyBean(Object bean)
        throws IntrospectionException
        {
            com.madrobot.beans.PropertyDescriptor[] properties = null;
            try {
                com.madrobot.beans.BeanInfo beanInfo = com.madrobot.beans.Introspector.getBeanInfo(bean.getClass());
                properties = beanInfo.getPropertyDescriptors();
            } catch (com.madrobot.beans.IntrospectionException e) {
                throw new IntrospectionException();
            }

            if (properties == null) return null;

            Map pickle = null;

            // copy properties into hashtable
            for (com.madrobot.beans.PropertyDescriptor property : properties) {
                Class paramClass = property.getPropertyType();
                Method getter = property.getReadMethod();
                try {
                    Object paramValue = getter.invoke(bean, (Object[])null);

                    if (paramValue != null) {
                        // converts isActive() to is_active
                        // converts getBookTitle() to book_title
                        String paramName = property.getName();
                        paramName = splitCamelCase(paramName);
                        if (paramValue instanceof Boolean) {
                            paramName = "is_"+paramName;
                        }

                        if (pickle == null) pickle = new HashMap();

                        storeValue(pickle, paramClass, paramName, paramValue, true);
                    }
                } catch (InvocationTargetException e) {
                } catch (IllegalAccessException e) {
                }
            }

            return pickle;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy