K-V pairs to java bean re-map

Time to time you need on your projects to remap Key-Value pairs to regular java beans. One really nasty solution to this task is to do it manually. Yea, it works but this approach is not flexible and more over it is error prone. Mapping each field is hard coded and when adding, remove or modify them you have to correct all hard-coded mappings what is really awkward.
Another approach is to use some K-V to bean re-mapper for example ObjectMapper from JASON Jackson library or commons beanutils offer some possibilities as well.
If for some reason you cannot use these libraries e.g. legal problem or simply you don’t find implementation which suits your needs then it is time for your implementation.
Following example implementation re-map to primitives and enums from string representation. Some highlights: java 1.6 doesn’t offer any way how to find the wrapper class for primitives, wrap any problem (Exception) to base RuntimeException is not a good approach. In case of real usage it is suggested to change this. In the context of this example I think it’s fajn.

public class KVBeanRemaper {
    private static final Map wrappers = new HashMap();

    static {
        wrappers.put(byte.class, Byte.class);
        wrappers.put(short.class, Short.class);
        wrappers.put(int.class, Integer.class);
        wrappers.put(long.class, Long.class);
        wrappers.put(float.class, Float.class);
        wrappers.put(double.class, Double.class);
        wrappers.put(boolean.class, Boolean.class);
    }

    public static  T remap(Map keyValue, final Class classMapTo) {

        final Set dataToMap = new HashSet(keyValue.keySet());
        final Field[] fields;

        T res;
        try {
            res = classMapTo.newInstance();
            fields = classMapTo.getDeclaredFields();

            for (Field f : fields) {
                if (!dataToMap.contains(f.getName())) {
                    continue;
                } else {
                    final String key = f.getName();

                    if (f.getType().isEnum()) {
                        findAccessMethod(true, f, classMapTo).invoke(res,
                                Enum.valueOf((Class) f.getType(), keyValue.get(key).toString().toUpperCase()));
                        dataToMap.remove(key);
                    } else if (wrappers.containsKey(f.getType()) || f.getType() == String.class) {
                        Class c = f.getType();
                        if (c.isPrimitive()) {
                            c = wrappers.get(c);
                        }
                        findAccessMethod(true, f, classMapTo).invoke(res, c.cast(keyValue.get(key)));
                        dataToMap.remove(key);
                    }
                }
            }
        } catch (Exception ex) {
            throw new RuntimeException("Error while remapping", ex);
        }
        if (dataToMap.size() > 0) {
            throw new RuntimeException("Complete fieldset hasn't been remapped");
        }
        return res;
    }

    private static Method findAccessMethod(boolean setter, final Field field, final Class klazz) throws IntrospectionException {
        PropertyDescriptor pd = new PropertyDescriptor(field.getName(), klazz);
        if (setter) {
            return pd.getWriteMethod();
        } else {
            return pd.getReadMethod();
        }
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s