Java tutorial
//package com.java2s; //License from project: Open Source License import java.io.File; import java.io.InvalidObjectException; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import com.fasterxml.jackson.annotation.JsonGetter; public class Main { /** * List of classes that are wrapped directly. This information is need when * traversing object trees for reference matching */ private static final Set<Class> WRAPPER_TYPES = new HashSet( Arrays.asList(Boolean.class, Character.class, Byte.class, Short.class, String.class, Integer.class, Long.class, Float.class, Double.class, Void.class, File.class)); /** * Prepares Array style form fields from a given array of values * @param value Value for the form fields * @return Dictionary of form fields created from array elements */ public static Map<String, Object> prepareFormFields(Object value) { Map<String, Object> formFields = new LinkedHashMap<String, Object>(); if (value != null) { try { objectToMap("", value, formFields, new HashSet<Integer>()); } catch (Exception ex) { } } return formFields; } /** * Converts a given object to a form encoded map * @param objName Name of the object * @param obj The object to convert into a map * @param objectMap The object map to populate * @param processed List of objects hashCodes that are already parsed * @throws InvalidObjectException */ private static void objectToMap(String objName, Object obj, Map<String, Object> objectMap, HashSet<Integer> processed) throws InvalidObjectException { //null values need not to be processed if (obj == null) return; //wrapper types are autoboxed, so reference checking is not needed if (!isWrapperType(obj.getClass())) { //avoid infinite recursion if (processed.contains(obj.hashCode())) return; processed.add(obj.hashCode()); } //process arrays if (obj instanceof Collection<?>) { //process array if ((objName == null) || (objName.isEmpty())) throw new InvalidObjectException("Object name cannot be empty"); Collection<?> array = (Collection<?>) obj; //append all elements in the array into a string int index = 0; for (Object element : array) { //load key value pair String key = String.format("%s[%d]", objName, index++); loadKeyValuePairForEncoding(key, element, objectMap, processed); } } else if (obj instanceof Map) { //process map Map<?, ?> map = (Map<?, ?>) obj; //append all elements in the array into a string for (Map.Entry<?, ?> pair : map.entrySet()) { String attribName = pair.getKey().toString(); String key = attribName; if ((objName != null) && (!objName.isEmpty())) { key = String.format("%s[%s]", objName, attribName); } loadKeyValuePairForEncoding(key, pair.getValue(), objectMap, processed); } } else { //process objects // invoke getter methods Method[] methods = obj.getClass().getMethods(); for (Method method : methods) { //is a getter? if ((method.getParameterTypes().length != 0) || (!method.getName().startsWith("get"))) continue; //get json attribute name Annotation getterAnnotation = method.getAnnotation(JsonGetter.class); if (getterAnnotation == null) continue; //load key name String attribName = ((JsonGetter) getterAnnotation).value(); String key = attribName; if ((objName != null) && (!objName.isEmpty())) { key = String.format("%s[%s]", objName, attribName); } try { //load key value pair Object value = method.invoke(obj); loadKeyValuePairForEncoding(key, value, objectMap, processed); } catch (Exception ex) { } } // load fields Field[] fields = obj.getClass().getFields(); for (Field field : fields) { //load key name String attribName = field.getName(); String key = attribName; if ((objName != null) && (!objName.isEmpty())) { key = String.format("%s[%s]", objName, attribName); } try { //load key value pair Object value = field.get(obj); loadKeyValuePairForEncoding(key, value, objectMap, processed); } catch (Exception ex) { } } } } /** * Checks if the given class can be wrapped directly * @param clazz The given class * @return true if the given class is an autoboxed class e.g., Integer */ private static boolean isWrapperType(Class clazz) { return WRAPPER_TYPES.contains(clazz) || clazz.isPrimitive() || clazz.isEnum(); } /** * While processing objects to map, decides whether to perform recursion or load value * @param key The key to used for creating key value pair * @param value The value to process against the given key * @param objectMap The object map to process with key value pair * @param processed List of processed objects hashCodes * @throws InvalidObjectException */ private static void loadKeyValuePairForEncoding(String key, Object value, Map<String, Object> objectMap, HashSet<Integer> processed) throws InvalidObjectException { if (value == null) return; if (isWrapperType(value.getClass())) objectMap.put(key, value); else objectToMap(key, value, objectMap, processed); } }