From 660641a9f2a3028fadfed7cfcc45f0df9fce05e1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Manuel=20Carrasco=20Mo=C3=B1ino?= Date: Sat, 28 Dec 2013 16:06:03 +0100 Subject: [PATCH] Implement generic interface for Binders so as we can use it in JS and JVM --- .../google/gwt/query/client/Properties.java | 33 +++++- .../query/client/builders/JsonBuilder.java | 26 +---- .../client/builders/JsonBuilderBase.java | 27 ++++- .../google/gwt/query/client/js/JsCache.java | 18 ++-- .../query/rebind/JsonBuilderGenerator.java | 6 +- .../google/gwt/query/vm/JsonFactoryJre.java | 101 ++++++++++++++---- .../client/dbinding/DataBindingTest.java | 4 + 7 files changed, 164 insertions(+), 51 deletions(-) diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java index 3d31e852..af671474 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java @@ -15,16 +15,16 @@ */ package com.google.gwt.query.client; +import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArrayMixed; -import com.google.gwt.core.client.GWT; import com.google.gwt.query.client.js.JsCache; import com.google.gwt.query.client.js.JsUtils; /** * JSO for accessing Javascript objective literals used by GwtQuery functions. */ -public class Properties extends JavaScriptObject { +public class Properties extends JavaScriptObject implements Binder { public static Properties create() { return JsCache.create().cast(); @@ -199,4 +199,33 @@ public class Properties extends JavaScriptObject { return c().length() == 0; } + public final J load(Object prp) { + c().clear(); + if (prp instanceof JsCache) { + c().copy((JsCache)prp); + } + return getBound(); + } + + public final J parse(String json) { + return load(JsUtils.parseJSON(json)); + } + + public final String[] getFieldNames() { + return c().keys(); + } + + public final String toJson() { + return toJsonString(); + } + + @SuppressWarnings("unchecked") + public final J getBound() { + return (J)this; + } + + public final String getName() { + return "jso"; + } + } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java index 596d5473..887695d3 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilder.java @@ -15,21 +15,13 @@ */ package com.google.gwt.query.client.builders; +import com.google.gwt.query.client.Binder; + /** * Tagging interface used to generate JsonBuilder classes. */ -public interface JsonBuilder { - - /** - * load a properties object. - */ - J load(Object prp); - - /** - * parses a json string and loads the resulting properties object. - */ - J parse(String json); +public interface JsonBuilder extends Binder { /** * parses a json string and loads the resulting properties object, @@ -41,21 +33,13 @@ public interface JsonBuilder { /** * Returns the wrapped object, normally a Properties jso in client * but can be used to return the underlying Json implementation in JVM + * @deprecated use asObject() instead */ J getProperties(); - /** - * return a list of field names. - */ - String[] getFieldNames(); - - /** - * return a string which represents the object with an alias for the className - */ - String toJson(); - /** * return the Json name for this class + * @deprecated use getName() instead; */ String getJsonName(); } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java index 66de0898..4ec95de8 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java @@ -26,16 +26,19 @@ public abstract class JsonBuilderBase> implements J protected Properties p = Properties.create(); @SuppressWarnings("unchecked") + @Override public J parse(String json) { return load(JsUtils.parseJSON(json)); } @SuppressWarnings("unchecked") + @Override public J parse(String json, boolean fix) { return fix ? parse(Properties.wrapPropertiesString(json)) : parse(json); } @SuppressWarnings("unchecked") + @Override public J load(Object prp) { assert prp == null || prp instanceof JavaScriptObject || prp instanceof String; if (prp != null && prp instanceof String) { @@ -51,7 +54,7 @@ public abstract class JsonBuilderBase> implements J if (r.length > 0 && r[0] instanceof JsonBuilder) { JsArray a = JavaScriptObject.createArray().cast(); for (T o : r) { - a.push(((JsonBuilder)o).getProperties()); + a.push(((JsonBuilder)o).getBound()); } p.set(n, a); } else { @@ -89,8 +92,28 @@ public abstract class JsonBuilderBase> implements J } @SuppressWarnings("unchecked") + @Override public Properties getProperties() { return p; } - + + @Override + public String toQueryString() { + return p.toQueryString(); + } + + @Override + public String getName() { + return getJsonName(); + } + + @SuppressWarnings("unchecked") + @Override + public Properties getBound() { + return p; + } + + public T get(Object key) { + return p.get(key); + } } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java index c8f00a6c..f10d998b 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java @@ -36,6 +36,12 @@ public class JsCache extends JavaScriptObject { if (ary) this.concat(ary); }-*/; + public final void copy(JsCache jso) { + for (String k : jso.keys()) { + put(k, jso.get(k)); + } + } + public final void pushAll(JavaScriptObject prevElem) { checkNull(); JsCache c = prevElem.cast(); @@ -47,14 +53,12 @@ public class JsCache extends JavaScriptObject { public final native void delete(Object name) /*-{ delete this[name]; }-*/; - - public final native void clear() /*-{ - if (this.length) { - for (i = this.length - 1; i >= 0; i--) - delete this[i]; - this.length = 0; + + public final void clear() { + for (String k : keys()) { + delete(k); } - }-*/; + } public final native boolean exists(Object name) /*-{ return !!this[name]; diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java index ead7ecd0..8a45c6f9 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java @@ -38,6 +38,7 @@ import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.query.client.Function; import com.google.gwt.query.client.Properties; +import com.google.gwt.query.client.Binder; import com.google.gwt.query.client.builders.JsonBuilder; import com.google.gwt.query.client.builders.JsonBuilderBase; import com.google.gwt.query.client.builders.JsonFactory; @@ -51,6 +52,7 @@ public class JsonBuilderGenerator extends Generator { static JClassType functionType; static JClassType jsonBuilderType; + static JClassType settingsType; static JClassType jsType; static JClassType listType; static JClassType stringType; @@ -82,6 +84,7 @@ public class JsonBuilderGenerator extends Generator { JClassType clazz = oracle.findType(requestedClass); jsonBuilderType = oracle.findType(JsonBuilder.class.getName()); + settingsType = oracle.findType(Binder.class.getName()); stringType = oracle.findType(String.class.getName()); jsType = oracle.findType(JavaScriptObject.class.getName()); listType = oracle.findType(List.class.getName()); @@ -101,7 +104,8 @@ public class JsonBuilderGenerator extends Generator { for (JMethod method : clazz.getInheritableMethods()) { String methName = method.getName(); //skip method from JsonBuilder - if(jsonBuilderType.findMethod(method.getName(), method.getParameterTypes()) != null) { + if(jsonBuilderType.findMethod(method.getName(), method.getParameterTypes()) != null || + settingsType.findMethod(method.getName(), method.getParameterTypes()) != null ) { continue; } diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java b/gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java index 49b5877f..ec115086 100644 --- a/gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java +++ b/gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java @@ -13,6 +13,7 @@ import java.util.List; import org.json.JSONArray; import org.json.JSONObject; +import com.google.gwt.query.client.Binder; import com.google.gwt.query.client.builders.JsonBuilder; import com.google.gwt.query.client.builders.JsonFactory; import com.google.gwt.query.client.builders.Name; @@ -125,7 +126,7 @@ public class JsonFactoryJre implements JsonFactory { } else if (o instanceof Date) { return obj != null ? obj.put(attr, ((Date) o).getTime()) : arr.put(((Date) o).getTime()); } else if (o instanceof JsonBuilder) { - return obj != null ? obj.put(attr, ((JsonBuilder) o).getProperties()) : arr.put(((JsonBuilder) o).getProperties()); + return obj != null ? obj.put(attr, ((JsonBuilder) o).getBound()) : arr.put(((JsonBuilder) o).getBound()); } else if (o.getClass().isArray() || o instanceof List) { Object[] arg; if (o.getClass().isArray()) { @@ -156,13 +157,23 @@ public class JsonFactoryJre implements JsonFactory { if ("getFieldNames".equals(mname)) { return JSONObject.getNames(jsonObject); - } else if ("getProperties".equals(mname)) { + } else if ("getName".equals(mname)) { + return JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass())); + } else if (mname.matches("getProperties|getBound")) { return jsonObject; } else if (largs > 0 && ("parse".equals(mname) || "load".equals(mname))) { jsonObject = new JSONObject(String.valueOf(args[0])); - } else if ("toString".equals(mname) || "toJson".equals(mname)) { + } else if (mname.matches("toString")) { + return jsonObject.toString(); + } else if (mname.matches("toJson")) { String jsonName = JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass())); - return "{\"" + jsonName + "\":"+ jsonObject.toString(); + return "{\"" + jsonName + "\":"+ jsonObject.toString() + "}"; + } else if ("toQueryString".equals(mname)) { + return param(jsonObject); + } else if (largs == 1 && mname.equals("get")) { + Class ret = method.getReturnType(); + attr = String.valueOf(args[0]); + return getValue(null, 0, jsonObject, attr, ret, method); } else if (largs == 0 || mname.startsWith("get")) { Class ret = method.getReturnType(); return getValue(null, 0, jsonObject, attr, ret, method); @@ -172,6 +183,70 @@ public class JsonFactoryJre implements JsonFactory { } return null; } + + private String deCapitalize(String s) { + return s != null && s.length() > 0 ? s.substring(0, 1).toLowerCase() + s.substring(1) : s; + } + + private String getDataBindingClassName(Class type) { + for (Class c : type.getInterfaces()) { + if (c.equals(JsonBuilder.class)) { + return type.getName(); + } else { + return getDataBindingClassName(c); + } + } + return null; + } + + private String param(JSONObject o) { + String ret = ""; + for (String k : JSONObject.getNames(o)) { + ret += ret.isEmpty() ? "" : "&"; + JSONObject p = null; + JSONArray a = null; + String s = null; + try { + a = o.getJSONArray(k); + } catch (Exception e) { + } + if (a != null) { + for (int i = 0, l = a.length(); i < l ; i++) { + ret += i > 0 ? "&" : ""; + try { + p = a.getJSONObject(i); + } catch (Exception e) { + try { + s = String.valueOf(a.get(i)); + } catch (Exception d) { + } + } + if (p != null) { + ret += k + "[]=" + p.toString(); + } else if (s != null){ + ret += k + "[]=" + s; + } + } + } else { + try { + p = o.getJSONObject(k); + } catch (Exception e) { + try { + s = String.valueOf(o.get(k)); + } catch (Exception d) { + } + } + if (p != null) { + ret += param(p); + } else if (s != null) { + if (!s.isEmpty() && !"null".equalsIgnoreCase(s)) { + ret += k + "=" + s; + } + } + } + } + return ret; + } } @SuppressWarnings("unchecked") @@ -185,19 +260,9 @@ public class JsonFactoryJre implements JsonFactory { InvocationHandler handler = new JsonBuilderHandler(); return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] {clz}, handler); } - - private static String deCapitalize(String s) { - return s != null && s.length() > 0 ? s.substring(0, 1).toLowerCase() + s.substring(1) : s; - } - - private static String getDataBindingClassName(Class type) { - for (Class c : type.getInterfaces()) { - if (c.equals(JsonBuilder.class)) { - return type.getName(); - } else { - return getDataBindingClassName(c); - } - } - return null; + + public Binder createBinder() { + InvocationHandler handler = new JsonBuilderHandler(); + return (Binder)Proxy.newProxyInstance(Binder.class.getClassLoader(), new Class[] {Binder.class}, handler); } } diff --git a/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTest.java b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTest.java index d6923a15..d94b706a 100644 --- a/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTest.java +++ b/gwtquery-core/src/test/java/com/google/gwt/query/client/dbinding/DataBindingTest.java @@ -107,5 +107,9 @@ public class DataBindingTest extends GWTTestCase { assertTrue(c.toJson().startsWith("{\"jsonExample\":{")); assertTrue(c.toJson().contains("\"items\":[{\"date\":")); + assertTrue(c.toQueryString().contains("t[]=bar")); + assertTrue(c.toQueryString().contains("a=2")); + + assertEquals(1, c.get("a").intValue()); } } \ No newline at end of file -- 2.39.5