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.net.URLEncoder; 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)); /** * Appends the given set of parameters to the given query string * @param queryBuilder The query url string to append the parameters * @param parameters The parameters to append */ public static void appendUrlWithQueryParameters(StringBuilder queryBuilder, Map<String, Object> parameters) { //perform parameter validation if (null == queryBuilder) throw new IllegalArgumentException("Given value for parameter \"queryBuilder\" is invalid."); if (null == parameters) return; //does the query string already has parameters boolean hasParams = (queryBuilder.indexOf("?") > 0) || (queryBuilder.indexOf("http") != 0); if (!hasParams) queryBuilder.append('?'); encodeObjectAsQueryString("", parameters, queryBuilder); } /** * Encodes a given object to url encoded string * @param name * @param obj * @param objBuilder */ private static void encodeObjectAsQueryString(String name, Object obj, StringBuilder objBuilder) { try { if (obj == null) return; Map<String, Object> objectMap = new LinkedHashMap<String, Object>(); objectToMap(name, obj, objectMap, new HashSet<Integer>()); boolean hasParam = false; for (Map.Entry<String, Object> pair : objectMap.entrySet()) { String paramKeyValPair; //ignore nulls Object value = pair.getValue(); if (value == null) continue; hasParam = true; //load element value as string paramKeyValPair = String.format("%s=%s&", pair.getKey(), tryUrlEncode(value.toString())); objBuilder.append(paramKeyValPair); } //remove the last & if (hasParam) { objBuilder.setLength(objBuilder.length() - 1); } } catch (Exception ex) { } } /** * 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) { } } } } /** * Tries Url encode using UTF-8 * @param value The value to url encode * @return */ private static String tryUrlEncode(String value) { try { return URLEncoder.encode(value, "UTF-8"); } catch (Exception ex) { return value; } } /** * 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); } }