Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

JsonBuilderHandler.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. package com.google.gwt.query.vm;
  2. import com.google.gwt.query.client.Function;
  3. import com.google.gwt.query.client.IsProperties;
  4. import com.google.gwt.query.client.Properties;
  5. import com.google.gwt.query.client.builders.JsonBuilder;
  6. import com.google.gwt.query.client.builders.Name;
  7. import com.google.gwt.query.rebind.JsonBuilderGenerator;
  8. import com.google.gwt.query.vm.JsonFactoryJre.JreJsonFunction;
  9. import java.lang.reflect.Array;
  10. import java.lang.reflect.InvocationHandler;
  11. import java.lang.reflect.Method;
  12. import java.lang.reflect.ParameterizedType;
  13. import java.lang.reflect.Type;
  14. import java.util.ArrayList;
  15. import java.util.Date;
  16. import java.util.HashSet;
  17. import java.util.Hashtable;
  18. import java.util.List;
  19. import elemental.json.Json;
  20. import elemental.json.JsonArray;
  21. import elemental.json.JsonBoolean;
  22. import elemental.json.JsonNull;
  23. import elemental.json.JsonNumber;
  24. import elemental.json.JsonObject;
  25. import elemental.json.JsonString;
  26. import elemental.json.JsonValue;
  27. public class JsonBuilderHandler implements InvocationHandler {
  28. static JsonFactoryJre jsonFactory = new JsonFactoryJre();
  29. private JsonObject jsonObject;
  30. public JsonBuilderHandler() {
  31. jsonObject = Json.createObject();
  32. }
  33. public JsonBuilderHandler(JsonObject j) {
  34. jsonObject = j;
  35. }
  36. public JsonBuilderHandler(String payload) throws Throwable {
  37. jsonObject = Json.parse(payload);
  38. }
  39. @SuppressWarnings("unchecked")
  40. private <T> Object jsonArrayToList(JsonArray j, Class<T> ctype, boolean isArray) {
  41. List<T> l = new ArrayList<T>();
  42. for (int i = 0; j != null && i < j.length(); i++) {
  43. l.add((T) getValue(j, i, null, null, ctype, null));
  44. }
  45. return l.isEmpty() ? null : isArray ? l.toArray((T[]) Array.newInstance(ctype, l.size())) : l;
  46. }
  47. private Double toDouble(String attr, JsonArray arr, int idx, JsonObject obj) {
  48. try {
  49. return obj != null ? obj.getNumber(attr) : arr.getNumber(idx);
  50. } catch (Exception e) {
  51. return Double.valueOf(0d);
  52. }
  53. }
  54. private Object getValue(JsonArray arr, int idx, JsonObject obj, String attr, Class<?> clz,
  55. Method method) {
  56. if (clz.equals(Boolean.class) || clz == Boolean.TYPE) {
  57. try {
  58. return obj != null ? obj.getBoolean(attr) : arr.getBoolean(idx);
  59. } catch (Exception e) {
  60. return Boolean.FALSE;
  61. }
  62. } else if (clz.equals(Date.class)) {
  63. return new Date((long) (obj != null ? obj.getNumber(attr) : arr.getNumber(idx)));
  64. } else if (clz.equals(Byte.class) || clz == Byte.TYPE) {
  65. return toDouble(attr, arr, idx, obj).byteValue();
  66. } else if (clz.equals(Short.class) || clz == Short.TYPE) {
  67. return toDouble(attr, arr, idx, obj).shortValue();
  68. } else if (clz.equals(Integer.class) || clz == Integer.TYPE) {
  69. return toDouble(attr, arr, idx, obj).intValue();
  70. } else if (clz.equals(Double.class) || clz == Double.TYPE) {
  71. return toDouble(attr, arr, idx, obj);
  72. } else if (clz.equals(Float.class) || clz == Float.TYPE) {
  73. return toDouble(attr, arr, idx, obj).floatValue();
  74. } else if (clz.equals(Long.class) || clz == Long.TYPE) {
  75. return toDouble(attr, arr, idx, obj).longValue();
  76. }
  77. Object ret = obj != null ? obj.get(attr) : arr.get(idx);
  78. if (ret instanceof JreJsonFunction || clz.equals(Function.class)) {
  79. return ret != null && ret instanceof JreJsonFunction ? ((JreJsonFunction) ret).getFunction()
  80. : null;
  81. } else if (ret instanceof JsonNull) {
  82. return null;
  83. } else if (ret instanceof JsonString) {
  84. return ((JsonString) ret).asString();
  85. } else if (ret instanceof JsonBoolean) {
  86. return ((JsonBoolean) ret).asBoolean();
  87. } else if (ret instanceof JsonNumber) {
  88. return toDouble(attr, arr, idx, obj);
  89. } else if (ret instanceof JsonArray || clz.isArray() || clz.equals(List.class)) {
  90. Class<?> ctype = Object.class;
  91. if (clz.isArray()) {
  92. ctype = clz.getComponentType();
  93. } else {
  94. Type returnType = method.getGenericReturnType();
  95. if (returnType instanceof ParameterizedType) {
  96. ctype = (Class<?>) ((ParameterizedType) returnType).getActualTypeArguments()[0];
  97. }
  98. }
  99. return jsonArrayToList(obj.getArray(attr), ctype, clz.isArray());
  100. } else if (ret instanceof JsonObject) {
  101. if (clz == Object.class) {
  102. return jsonFactory.createBinder((JsonObject) ret);
  103. } else if (IsProperties.class.isAssignableFrom(clz) && !clz.isAssignableFrom(ret.getClass())) {
  104. return jsonFactory.create(clz, (JsonObject) ret);
  105. }
  106. }
  107. return ret;
  108. }
  109. private <T> JsonArray listToJsonArray(Object... l) throws Throwable {
  110. JsonArray ret = Json.createArray();
  111. for (Object o : l) {
  112. setValue(ret, null, null, o);
  113. }
  114. return ret;
  115. }
  116. private Object setValue(JsonArray jsArr, JsonObject jsObj, String attr, Object val) {
  117. if (val == null) {
  118. return Json.createNull();
  119. }
  120. try {
  121. Class<?> valClaz = JsonValue.class;
  122. if (val instanceof Number) {
  123. val = ((Number) val).doubleValue();
  124. valClaz = Double.TYPE;
  125. } else if (val instanceof Boolean) {
  126. valClaz = Boolean.TYPE;
  127. } else if (val instanceof Date) {
  128. val = ((Date) val).getTime();
  129. valClaz = Double.TYPE;
  130. } else if (val instanceof String) {
  131. valClaz = String.class;
  132. } else if (val instanceof IsProperties) {
  133. val = ((IsProperties) val).getDataImpl();
  134. } else if (val.getClass().isArray() || val instanceof List) {
  135. val =
  136. listToJsonArray(val.getClass().isArray() ? (Object[]) val : ((List<?>) val).toArray());
  137. } else if (val instanceof Function) {
  138. val = new JreJsonFunction((Function) val);
  139. }
  140. if (jsObj != null) {
  141. Method mth = jsObj.getClass().getMethod("put", String.class, valClaz);
  142. mth.invoke(jsObj, new Object[] {attr, val});
  143. return jsObj;
  144. } else {
  145. Method mth = jsArr.getClass().getMethod("set", Integer.TYPE, valClaz);
  146. mth.invoke(jsArr, new Object[] {new Integer(jsArr.length()), val});
  147. return jsArr;
  148. }
  149. } catch (Throwable e) {
  150. e.printStackTrace();
  151. }
  152. return null;
  153. }
  154. @Override
  155. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  156. String mname = method.getName();
  157. Class<?>[] classes = method.getParameterTypes();
  158. int largs = classes.length;
  159. Name name = method.getAnnotation(Name.class);
  160. String attr = name != null ? name.value() : methodName2AttrName(mname);
  161. if ("getFieldNames".equals(mname)) {
  162. return jsonObject.keys();
  163. } else if ("as".equals(mname)) {
  164. @SuppressWarnings("unchecked")
  165. Class<? extends JsonBuilder> clz = (Class<? extends JsonBuilder>) args[0];
  166. return jsonFactory.create(clz, jsonObject);
  167. } else if ("getJsonName".equals(mname)) {
  168. return JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass()));
  169. } else if (mname.matches("getProperties|getDataImpl")) {
  170. return jsonObject;
  171. } else if (largs > 0 && ("parse".equals(mname) || "load".equals(mname))) {
  172. String json = String.valueOf(args[0]);
  173. if (largs > 1 && Boolean.TRUE.equals(args[1])) {
  174. json = Properties.wrapPropertiesString(json);
  175. }
  176. jsonObject = Json.parse(json);
  177. } else if ("strip".equals(mname)) {
  178. stripProxy((JsonBuilder) proxy);
  179. } else if (mname.matches("toString")) {
  180. return jsonObject.toString();
  181. } else if (mname.matches("toJsonWithName")) {
  182. String jsonName =
  183. JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass()));
  184. return "{\"" + jsonName + "\":" + jsonObject.toString() + "}";
  185. } else if (mname.matches("toJson")) {
  186. return jsonObject.toString();
  187. } else if ("toQueryString".equals(mname)) {
  188. return param(jsonObject);
  189. } else if (largs == 1 && mname.equals("get")) {
  190. Class<?> ret = method.getReturnType();
  191. attr = String.valueOf(args[0]);
  192. return getValue(null, 0, jsonObject, attr, ret, method);
  193. } else if (largs == 0 || mname.startsWith("get")) {
  194. Class<?> ret = method.getReturnType();
  195. return getValue(null, 0, jsonObject, attr, ret, method);
  196. } else if (largs == 2 && mname.equals("set")) {
  197. setValue(null, jsonObject, String.valueOf(args[0]), args[1]);
  198. return proxy;
  199. } else if (largs == 1 || mname.startsWith("set")) {
  200. setValue(null, jsonObject, attr, args[0]);
  201. return proxy;
  202. }
  203. return null;
  204. }
  205. public String methodName2AttrName(String s) {
  206. return deCapitalize(s.replaceFirst("^[gs]et", ""));
  207. }
  208. private String deCapitalize(String s) {
  209. return s != null && s.length() > 0 ? s.substring(0, 1).toLowerCase() + s.substring(1) : s;
  210. }
  211. /*
  212. * This method removes all the json which is not mapped into a
  213. * method inside the JsonBuilder Object.
  214. * Also if the proxy contains another JsonBuilder in their methods
  215. * the method strip() is called.
  216. */
  217. private void stripProxy(JsonBuilder proxy) throws Throwable {
  218. Class<?> type = proxy.getClass().getInterfaces()[0];
  219. HashSet<String> validAttrs = getAttributeNames(type.getMethods());
  220. Hashtable<String, Method> ispropertyGetters = getJsonBuilders(type.getMethods());
  221. for (String key : jsonObject.keys()) {
  222. String name = methodName2AttrName(key);
  223. if (!validAttrs.contains(name)) {
  224. jsonObject.remove(key);
  225. continue;
  226. }
  227. Method ispropertyGetter = ispropertyGetters.get(name);
  228. if (ispropertyGetter != null) {
  229. ((IsProperties) invoke(proxy, ispropertyGetter, new Object[] {})).strip();
  230. }
  231. }
  232. }
  233. private String getDataBindingClassName(Class<?> type) {
  234. for (Class<?> c : type.getInterfaces()) {
  235. if (c.equals(JsonBuilder.class)) {
  236. return type.getName();
  237. } else {
  238. return getDataBindingClassName(c);
  239. }
  240. }
  241. return null;
  242. }
  243. private String param(JsonObject o) {
  244. String ret = "";
  245. for (String k : o.keys()) {
  246. ret += ret.isEmpty() ? "" : "&";
  247. JsonValue v = o.get(k);
  248. if (v instanceof JsonArray) {
  249. for (int i = 0, l = ((JsonArray) v).length(); i < l; i++) {
  250. ret += i > 0 ? "&" : "";
  251. JsonValue e = ((JsonArray) v).get(i);
  252. ret += k + "[]=" + e.toJson();
  253. }
  254. } else {
  255. if (v != null && !(v instanceof JsonNull)) {
  256. ret += k + "=" + v.toJson();
  257. }
  258. }
  259. }
  260. return ret;
  261. }
  262. private HashSet<String> getAttributeNames(Method[] methods) {
  263. HashSet<String> valid = new HashSet<String>();
  264. if (methods == null || methods.length == 0) {
  265. return valid;
  266. }
  267. for (Method m : methods) {
  268. String attr = methodName2AttrName(m.getName());
  269. Name annotation = m.getAnnotation(Name.class);
  270. if (annotation != null) {
  271. attr = annotation.value();
  272. }
  273. valid.add(attr);
  274. }
  275. return valid;
  276. }
  277. private Hashtable<String, Method> getJsonBuilders(Method[] methods) {
  278. Hashtable<String, Method> ispropertyGetters = new Hashtable<String, Method>();
  279. if (methods == null || methods.length == 0) {
  280. return ispropertyGetters;
  281. }
  282. for (Method m : methods) {
  283. Class<?>[] classes = m.getParameterTypes();
  284. boolean isJsonBuilder =
  285. classes.length == 0 && IsProperties.class.isAssignableFrom(m.getReturnType());
  286. if (isJsonBuilder) {
  287. String attr = methodName2AttrName(m.getName());
  288. ispropertyGetters.put(attr, m);
  289. }
  290. }
  291. return ispropertyGetters;
  292. }
  293. }