Conflicts: gwtquery-core/src/main/java/com/google/gwt/query/client/IsProperties.java gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.javatags/gwtquery-project-1.4.3
@@ -13,6 +13,8 @@ | |||
*/ | |||
package com.google.gwt.query.client; | |||
import static com.google.gwt.query.client.GQuery.$; | |||
import static com.google.gwt.query.client.GQuery.document; | |||
import static com.google.gwt.query.client.plugins.QueuePlugin.Queue; | |||
import com.google.gwt.core.client.GWT; | |||
@@ -52,6 +54,7 @@ import com.google.gwt.query.client.plugins.Widgets; | |||
import com.google.gwt.query.client.plugins.ajax.Ajax; | |||
import com.google.gwt.query.client.plugins.ajax.Ajax.Settings; | |||
import com.google.gwt.query.client.plugins.deferred.Deferred; | |||
import com.google.gwt.query.client.plugins.deferred.PromiseFunction; | |||
import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing; | |||
import com.google.gwt.query.client.plugins.events.EventsListener; | |||
import com.google.gwt.query.client.plugins.widgets.WidgetsUtils; | |||
@@ -3799,6 +3802,30 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> { | |||
return as(Queue).queue(queueName, f); | |||
} | |||
/** | |||
* Specify a function to execute when the DOM is fully loaded. | |||
* | |||
* While JavaScript provides the load event for executing code when a page is rendered, this event | |||
* is not seen if we attach an event listener after the document has been loaded. | |||
* This guarantees that our gwt code will be executed either it's executed synchronously before the | |||
* DOM has been rendered (ie: single script linker in header) or asynchronously. | |||
*/ | |||
public Promise ready(Function... fncs) { | |||
return new PromiseFunction() { | |||
public void f(final com.google.gwt.query.client.Promise.Deferred dfd) { | |||
if ("complete" == $(document).prop("readyState")) { | |||
dfd.resolve(); | |||
} else { | |||
$(document).on("load", new Function() { | |||
public void f() { | |||
dfd.resolve(); | |||
} | |||
}); | |||
} | |||
} | |||
}.done(fncs); | |||
} | |||
/** | |||
* Removes all matched elements from the DOM. | |||
*/ |
@@ -30,6 +30,14 @@ public interface IsProperties { | |||
* parses a json string and loads the resulting properties object. | |||
*/ | |||
<T extends IsProperties> T parse(String json); | |||
/** | |||
* Removes the extra JSON and leaves only the setters/getters described | |||
* in the JsonBuilder interface. | |||
* If the object contains another IsProperties attributes the method strip() | |||
* is called on them. | |||
*/ | |||
<T extends IsProperties> T strip(); | |||
/** | |||
* Returns the underlying object, normally a Properties jso in client |
@@ -176,9 +176,9 @@ public class Properties extends JavaScriptObject implements IsProperties { | |||
/** | |||
* Adds a new native js function to the properties object. | |||
* This native function will wrap the passed java Function. | |||
* | |||
* | |||
* Its useful for exporting or importing to javascript. | |||
* | |||
* | |||
*/ | |||
public final native <T> void setFunction(T name, Function f) /*-{ | |||
if (!f) return; | |||
@@ -218,6 +218,11 @@ public class Properties extends JavaScriptObject implements IsProperties { | |||
} | |||
return getDataImpl(); | |||
} | |||
@SuppressWarnings("unchecked") | |||
public final <J extends IsProperties> J strip() { | |||
return (J)this; | |||
} | |||
public final <J extends IsProperties> J parse(String json) { | |||
return load(JsUtils.parseJSON(json)); |
@@ -19,8 +19,13 @@ import com.google.gwt.core.client.JavaScriptObject; | |||
import com.google.gwt.core.client.JsArray; | |||
import com.google.gwt.query.client.IsProperties; | |||
import com.google.gwt.query.client.Properties; | |||
import com.google.gwt.query.client.js.JsCache; | |||
import com.google.gwt.query.client.js.JsObjectArray; | |||
import com.google.gwt.query.client.js.JsUtils; | |||
import com.google.gwt.user.client.Window; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
/** | |||
* Common class for all JsonBuilder implementations. | |||
@@ -30,6 +35,7 @@ import com.google.gwt.query.client.js.JsUtils; | |||
public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements JsonBuilder { | |||
protected Properties p = Properties.create(); | |||
protected String[] fieldNames = new String[] {}; | |||
@SuppressWarnings("unchecked") | |||
@Override | |||
@@ -43,6 +49,20 @@ public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements J | |||
return fix ? parse(Properties.wrapPropertiesString(json)) : parse(json); | |||
} | |||
@SuppressWarnings("unchecked") | |||
@Override | |||
public J strip() { | |||
List<String> names = Arrays.asList(getFieldNames()); | |||
for (String jsonName : p.getFieldNames()) { | |||
// TODO: figure out a way so as we can generate some marks in generated class in | |||
// order to call getters to return JsonBuilder object given an an attribute name | |||
if (!names.contains(jsonName)) { | |||
p.<JsCache>cast().delete(jsonName); | |||
} | |||
} | |||
return (J)this; | |||
} | |||
@SuppressWarnings("unchecked") | |||
@Override | |||
public J load(Object prp) { | |||
@@ -142,4 +162,8 @@ public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements J | |||
public <T extends JsonBuilder> T as(Class<T> clz) { | |||
return p.as(clz); | |||
} | |||
public final String[] getFieldNames() { | |||
return fieldNames; | |||
} | |||
} |
@@ -365,7 +365,7 @@ public class JsUtils { | |||
* Check is a javascript object can be cast to an Element. | |||
*/ | |||
public static native boolean isElement(Object o) /*-{ | |||
return o && o.nodeType && o.nodeName ? true : false; | |||
return !!o && 'nodeType' in o && 'nodeName' in o; | |||
}-*/; | |||
/** |
@@ -143,7 +143,7 @@ public class JsonBuilderGenerator extends Generator { | |||
for (Iterator<String> it = attrs.iterator(); it.hasNext();) { | |||
ret += (ret.isEmpty() ? "" : ",") + "\"" + it.next() + "\""; | |||
} | |||
sw.println("public final String[] getFieldNames() {return new String[]{" + ret + "};}"); | |||
sw.println("{ fieldNames = new String[]{" + ret + "}; }"); | |||
} | |||
public void generateMethod(SourceWriter sw, JMethod method, String name, TreeLogger logger) |
@@ -0,0 +1,328 @@ | |||
package com.google.gwt.query.vm; | |||
import com.google.gwt.query.client.Function; | |||
import com.google.gwt.query.client.IsProperties; | |||
import com.google.gwt.query.client.Properties; | |||
import com.google.gwt.query.client.builders.JsonBuilder; | |||
import com.google.gwt.query.client.builders.Name; | |||
import com.google.gwt.query.rebind.JsonBuilderGenerator; | |||
import com.google.gwt.query.vm.JsonFactoryJre.JreJsonFunction; | |||
import java.lang.reflect.Array; | |||
import java.lang.reflect.InvocationHandler; | |||
import java.lang.reflect.Method; | |||
import java.lang.reflect.ParameterizedType; | |||
import java.lang.reflect.Type; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.HashSet; | |||
import java.util.Hashtable; | |||
import java.util.List; | |||
import elemental.json.Json; | |||
import elemental.json.JsonArray; | |||
import elemental.json.JsonBoolean; | |||
import elemental.json.JsonNull; | |||
import elemental.json.JsonNumber; | |||
import elemental.json.JsonObject; | |||
import elemental.json.JsonString; | |||
import elemental.json.JsonValue; | |||
public class JsonBuilderHandler implements InvocationHandler { | |||
static JsonFactoryJre jsonFactory = new JsonFactoryJre(); | |||
private JsonObject jsonObject; | |||
public JsonBuilderHandler() { | |||
jsonObject = Json.createObject(); | |||
} | |||
public JsonBuilderHandler(JsonObject j) { | |||
jsonObject = j; | |||
} | |||
public JsonBuilderHandler(String payload) throws Throwable { | |||
jsonObject = Json.parse(payload); | |||
} | |||
@SuppressWarnings("unchecked") | |||
private <T> Object jsonArrayToList(JsonArray j, Class<T> ctype, boolean isArray) { | |||
List<T> l = new ArrayList<T>(); | |||
for (int i = 0; j != null && i < j.length(); i++) { | |||
l.add((T) getValue(j, i, null, null, ctype, null)); | |||
} | |||
return l.isEmpty() ? null : isArray ? l.toArray((T[]) Array.newInstance(ctype, l.size())) : l; | |||
} | |||
private Double toDouble(String attr, JsonArray arr, int idx, JsonObject obj) { | |||
try { | |||
return obj != null ? obj.getNumber(attr) : arr.getNumber(idx); | |||
} catch (Exception e) { | |||
return Double.valueOf(0d); | |||
} | |||
} | |||
private Object getValue(JsonArray arr, int idx, JsonObject obj, String attr, Class<?> clz, | |||
Method method) { | |||
if (clz.equals(Boolean.class) || clz == Boolean.TYPE) { | |||
try { | |||
return obj != null ? obj.getBoolean(attr) : arr.getBoolean(idx); | |||
} catch (Exception e) { | |||
return Boolean.FALSE; | |||
} | |||
} else if (clz.equals(Date.class)) { | |||
return new Date((long) (obj != null ? obj.getNumber(attr) : arr.getNumber(idx))); | |||
} else if (clz.equals(Byte.class) || clz == Byte.TYPE) { | |||
return toDouble(attr, arr, idx, obj).byteValue(); | |||
} else if (clz.equals(Short.class) || clz == Short.TYPE) { | |||
return toDouble(attr, arr, idx, obj).shortValue(); | |||
} else if (clz.equals(Integer.class) || clz == Integer.TYPE) { | |||
return toDouble(attr, arr, idx, obj).intValue(); | |||
} else if (clz.equals(Double.class) || clz == Double.TYPE) { | |||
return toDouble(attr, arr, idx, obj); | |||
} else if (clz.equals(Float.class) || clz == Float.TYPE) { | |||
return toDouble(attr, arr, idx, obj).floatValue(); | |||
} else if (clz.equals(Long.class) || clz == Long.TYPE) { | |||
return toDouble(attr, arr, idx, obj).longValue(); | |||
} | |||
Object ret = obj != null ? obj.get(attr) : arr.get(idx); | |||
if (ret instanceof JreJsonFunction || clz.equals(Function.class)) { | |||
return ret != null && ret instanceof JreJsonFunction ? ((JreJsonFunction) ret).getFunction() | |||
: null; | |||
} else if (ret instanceof JsonNull) { | |||
return null; | |||
} else if (ret instanceof JsonString) { | |||
return ((JsonString) ret).asString(); | |||
} else if (ret instanceof JsonBoolean) { | |||
return ((JsonBoolean) ret).asBoolean(); | |||
} else if (ret instanceof JsonNumber) { | |||
return toDouble(attr, arr, idx, obj); | |||
} else if (ret instanceof JsonArray || clz.isArray() || clz.equals(List.class)) { | |||
Class<?> ctype = Object.class; | |||
if (clz.isArray()) { | |||
ctype = clz.getComponentType(); | |||
} else { | |||
Type returnType = method.getGenericReturnType(); | |||
if (returnType instanceof ParameterizedType) { | |||
ctype = (Class<?>) ((ParameterizedType) returnType).getActualTypeArguments()[0]; | |||
} | |||
} | |||
return jsonArrayToList(obj.getArray(attr), ctype, clz.isArray()); | |||
} else if (ret instanceof JsonObject) { | |||
if (clz == Object.class) { | |||
return jsonFactory.createBinder((JsonObject) ret); | |||
} else if (IsProperties.class.isAssignableFrom(clz) && !clz.isAssignableFrom(ret.getClass())) { | |||
return jsonFactory.create(clz, (JsonObject) ret); | |||
} | |||
} | |||
return ret; | |||
} | |||
private <T> JsonArray listToJsonArray(Object... l) throws Throwable { | |||
JsonArray ret = Json.createArray(); | |||
for (Object o : l) { | |||
setValue(ret, null, null, o); | |||
} | |||
return ret; | |||
} | |||
private Object setValue(JsonArray jsArr, JsonObject jsObj, String attr, Object val) { | |||
if (val == null) { | |||
return Json.createNull(); | |||
} | |||
try { | |||
Class<?> valClaz = JsonValue.class; | |||
if (val instanceof Number) { | |||
val = ((Number) val).doubleValue(); | |||
valClaz = Double.TYPE; | |||
} else if (val instanceof Boolean) { | |||
valClaz = Boolean.TYPE; | |||
} else if (val instanceof Date) { | |||
val = ((Date) val).getTime(); | |||
valClaz = Double.TYPE; | |||
} else if (val instanceof String) { | |||
valClaz = String.class; | |||
} else if (val instanceof IsProperties) { | |||
val = ((IsProperties) val).getDataImpl(); | |||
} else if (val.getClass().isArray() || val instanceof List) { | |||
val = | |||
listToJsonArray(val.getClass().isArray() ? (Object[]) val : ((List<?>) val).toArray()); | |||
} else if (val instanceof Function) { | |||
val = new JreJsonFunction((Function) val); | |||
} | |||
if (jsObj != null) { | |||
Method mth = jsObj.getClass().getMethod("put", String.class, valClaz); | |||
mth.invoke(jsObj, new Object[] {attr, val}); | |||
return jsObj; | |||
} else { | |||
Method mth = jsArr.getClass().getMethod("set", Integer.TYPE, valClaz); | |||
mth.invoke(jsArr, new Object[] {new Integer(jsArr.length()), val}); | |||
return jsArr; | |||
} | |||
} catch (Throwable e) { | |||
e.printStackTrace(); | |||
} | |||
return null; | |||
} | |||
@Override | |||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |||
String mname = method.getName(); | |||
Class<?>[] classes = method.getParameterTypes(); | |||
int largs = classes.length; | |||
Name name = method.getAnnotation(Name.class); | |||
String attr = name != null ? name.value() : methodName2AttrName(mname); | |||
if ("getFieldNames".equals(mname)) { | |||
return jsonObject.keys(); | |||
} else if ("as".equals(mname)) { | |||
@SuppressWarnings("unchecked") | |||
Class<? extends JsonBuilder> clz = (Class<? extends JsonBuilder>) args[0]; | |||
return jsonFactory.create(clz, jsonObject); | |||
} else if ("getJsonName".equals(mname)) { | |||
return JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass())); | |||
} else if (mname.matches("getProperties|getDataImpl")) { | |||
return jsonObject; | |||
} else if (largs > 0 && ("parse".equals(mname) || "load".equals(mname))) { | |||
String json = String.valueOf(args[0]); | |||
if (largs > 1 && Boolean.TRUE.equals(args[1])) { | |||
json = Properties.wrapPropertiesString(json); | |||
} | |||
jsonObject = Json.parse(json); | |||
} else if ("strip".equals(mname)) { | |||
stripProxy((JsonBuilder) proxy); | |||
} else if (mname.matches("toString")) { | |||
return jsonObject.toString(); | |||
} else if (mname.matches("toJsonWithName")) { | |||
String jsonName = | |||
JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass())); | |||
return "{\"" + jsonName + "\":" + jsonObject.toString() + "}"; | |||
} else if (mname.matches("toJson")) { | |||
return 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); | |||
} else if (largs == 2 && mname.equals("set")) { | |||
setValue(null, jsonObject, String.valueOf(args[0]), args[1]); | |||
return proxy; | |||
} else if (largs == 1 || mname.startsWith("set")) { | |||
setValue(null, jsonObject, attr, args[0]); | |||
return proxy; | |||
} | |||
return null; | |||
} | |||
public String methodName2AttrName(String s) { | |||
return deCapitalize(s.replaceFirst("^[gs]et", "")); | |||
} | |||
private String deCapitalize(String s) { | |||
return s != null && s.length() > 0 ? s.substring(0, 1).toLowerCase() + s.substring(1) : s; | |||
} | |||
/* | |||
* This method removes all the json which is not mapped into a | |||
* method inside the JsonBuilder Object. | |||
* Also if the proxy contains another JsonBuilder in their methods | |||
* the method strip() is called. | |||
*/ | |||
private void stripProxy(JsonBuilder proxy) throws Throwable { | |||
Class<?> type = proxy.getClass().getInterfaces()[0]; | |||
HashSet<String> validAttrs = getAttributeNames(type.getMethods()); | |||
Hashtable<String, Method> ispropertyGetters = getJsonBuilders(type.getMethods()); | |||
for (String key : jsonObject.keys()) { | |||
String name = methodName2AttrName(key); | |||
if (!validAttrs.contains(name)) { | |||
jsonObject.remove(key); | |||
continue; | |||
} | |||
Method ispropertyGetter = ispropertyGetters.get(name); | |||
if (ispropertyGetter != null) { | |||
((IsProperties) invoke(proxy, ispropertyGetter, new Object[] {})).strip(); | |||
} | |||
} | |||
} | |||
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 : o.keys()) { | |||
ret += ret.isEmpty() ? "" : "&"; | |||
JsonValue v = o.get(k); | |||
if (v instanceof JsonArray) { | |||
for (int i = 0, l = ((JsonArray) v).length(); i < l; i++) { | |||
ret += i > 0 ? "&" : ""; | |||
JsonValue e = ((JsonArray) v).get(i); | |||
ret += k + "[]=" + e.toJson(); | |||
} | |||
} else { | |||
if (v != null && !(v instanceof JsonNull)) { | |||
ret += k + "=" + v.toJson(); | |||
} | |||
} | |||
} | |||
return ret; | |||
} | |||
private HashSet<String> getAttributeNames(Method[] methods) { | |||
HashSet<String> valid = new HashSet<String>(); | |||
if (methods == null || methods.length == 0) { | |||
return valid; | |||
} | |||
for (Method m : methods) { | |||
String attr = methodName2AttrName(m.getName()); | |||
Name annotation = m.getAnnotation(Name.class); | |||
if (annotation != null) { | |||
attr = annotation.value(); | |||
} | |||
valid.add(attr); | |||
} | |||
return valid; | |||
} | |||
private Hashtable<String, Method> getJsonBuilders(Method[] methods) { | |||
Hashtable<String, Method> ispropertyGetters = new Hashtable<String, Method>(); | |||
if (methods == null || methods.length == 0) { | |||
return ispropertyGetters; | |||
} | |||
for (Method m : methods) { | |||
Class<?>[] classes = m.getParameterTypes(); | |||
boolean isJsonBuilder = | |||
classes.length == 0 && IsProperties.class.isAssignableFrom(m.getReturnType()); | |||
if (isJsonBuilder) { | |||
String attr = methodName2AttrName(m.getName()); | |||
ispropertyGetters.put(attr, m); | |||
} | |||
} | |||
return ispropertyGetters; | |||
} | |||
} |
@@ -17,30 +17,13 @@ package com.google.gwt.query.vm; | |||
import com.google.gwt.query.client.Function; | |||
import com.google.gwt.query.client.IsProperties; | |||
import com.google.gwt.query.client.Properties; | |||
import com.google.gwt.query.client.builders.JsonBuilder; | |||
import com.google.gwt.query.client.builders.JsonFactory; | |||
import com.google.gwt.query.client.builders.Name; | |||
import com.google.gwt.query.rebind.JsonBuilderGenerator; | |||
import java.lang.reflect.Array; | |||
import java.lang.reflect.InvocationHandler; | |||
import java.lang.reflect.Method; | |||
import java.lang.reflect.ParameterizedType; | |||
import java.lang.reflect.Proxy; | |||
import java.lang.reflect.Type; | |||
import java.util.ArrayList; | |||
import java.util.Date; | |||
import java.util.List; | |||
import elemental.json.Json; | |||
import elemental.json.JsonArray; | |||
import elemental.json.JsonBoolean; | |||
import elemental.json.JsonNull; | |||
import elemental.json.JsonNumber; | |||
import elemental.json.JsonObject; | |||
import elemental.json.JsonString; | |||
import elemental.json.JsonValue; | |||
import elemental.json.impl.JreJsonNull; | |||
/** | |||
@@ -51,7 +34,7 @@ import elemental.json.impl.JreJsonNull; | |||
*/ | |||
public class JsonFactoryJre implements JsonFactory { | |||
static JsonFactoryJre jsonFactory = new JsonFactoryJre(); | |||
/** | |||
* Although functions cannot be serialized to json we use JsonBuilders | |||
@@ -76,236 +59,6 @@ public class JsonFactoryJre implements JsonFactory { | |||
} | |||
} | |||
/** | |||
* | |||
*/ | |||
public static class JsonBuilderHandler implements InvocationHandler { | |||
private JsonObject jsonObject; | |||
public JsonBuilderHandler() { | |||
jsonObject = Json.createObject(); | |||
} | |||
public JsonBuilderHandler(JsonObject j) { | |||
jsonObject = j; | |||
} | |||
public JsonBuilderHandler(String payload) throws Throwable { | |||
jsonObject = Json.parse(payload); | |||
} | |||
@SuppressWarnings("unchecked") | |||
private <T> Object jsonArrayToList(JsonArray j, Class<T> ctype, boolean isArray) { | |||
List<T> l = new ArrayList<T>(); | |||
for (int i = 0; j != null && i < j.length(); i++) { | |||
l.add((T) getValue(j, i, null, null, ctype, null)); | |||
} | |||
return l.isEmpty() ? null : isArray ? l.toArray((T[]) Array.newInstance(ctype, l.size())) : l; | |||
} | |||
private Double toDouble(String attr, JsonArray arr, int idx, JsonObject obj) { | |||
try { | |||
return obj != null ? obj.getNumber(attr) : arr.getNumber(idx); | |||
} catch (Exception e) { | |||
return Double.valueOf(0d); | |||
} | |||
} | |||
private Object getValue(JsonArray arr, int idx, JsonObject obj, String attr, Class<?> clz, | |||
Method method) { | |||
if (clz.equals(Boolean.class) || clz == Boolean.TYPE) { | |||
try { | |||
return obj != null ? obj.getBoolean(attr) : arr.getBoolean(idx); | |||
} catch (Exception e) { | |||
return Boolean.FALSE; | |||
} | |||
} else if (clz.equals(Date.class)) { | |||
return new Date((long) (obj != null ? obj.getNumber(attr) : arr.getNumber(idx))); | |||
} else if (clz.equals(Byte.class) || clz == Byte.TYPE) { | |||
return toDouble(attr, arr, idx, obj).byteValue(); | |||
} else if (clz.equals(Short.class) || clz == Short.TYPE) { | |||
return toDouble(attr, arr, idx, obj).shortValue(); | |||
} else if (clz.equals(Integer.class) || clz == Integer.TYPE) { | |||
return toDouble(attr, arr, idx, obj).intValue(); | |||
} else if (clz.equals(Double.class) || clz == Double.TYPE) { | |||
return toDouble(attr, arr, idx, obj); | |||
} else if (clz.equals(Float.class) || clz == Float.TYPE) { | |||
return toDouble(attr, arr, idx, obj).floatValue(); | |||
} else if (clz.equals(Long.class) || clz == Long.TYPE) { | |||
return toDouble(attr, arr, idx, obj).longValue(); | |||
} | |||
Object ret = obj != null ? obj.get(attr) : arr.get(idx); | |||
if (ret instanceof JreJsonFunction || clz.equals(Function.class)) { | |||
return ret != null && ret instanceof JreJsonFunction ? ((JreJsonFunction) ret) | |||
.getFunction() : null; | |||
} else if (ret instanceof JsonNull) { | |||
return null; | |||
} else if (ret instanceof JsonString) { | |||
return ((JsonString) ret).asString(); | |||
} else if (ret instanceof JsonBoolean) { | |||
return ((JsonBoolean) ret).asBoolean(); | |||
} else if (ret instanceof JsonNumber) { | |||
return toDouble(attr, arr, idx, obj); | |||
} else if (ret instanceof JsonArray || clz.isArray() || clz.equals(List.class)) { | |||
Class<?> ctype = Object.class; | |||
if (clz.isArray()) { | |||
ctype = clz.getComponentType(); | |||
} else { | |||
Type returnType = method.getGenericReturnType(); | |||
if (returnType instanceof ParameterizedType) { | |||
ctype = (Class<?>) ((ParameterizedType) returnType).getActualTypeArguments()[0]; | |||
} | |||
} | |||
return jsonArrayToList(obj.getArray(attr), ctype, clz.isArray()); | |||
} else if (ret instanceof JsonObject) { | |||
if (clz == Object.class) { | |||
return jsonFactory.createBinder((JsonObject) ret); | |||
} else if (IsProperties.class.isAssignableFrom(clz) | |||
&& !clz.isAssignableFrom(ret.getClass())) { | |||
return jsonFactory.create(clz, (JsonObject) ret); | |||
} | |||
} | |||
return ret; | |||
} | |||
private <T> JsonArray listToJsonArray(Object... l) throws Throwable { | |||
JsonArray ret = Json.createArray(); | |||
for (Object o : l) { | |||
setValue(ret, null, null, o); | |||
} | |||
return ret; | |||
} | |||
private Object setValue(JsonArray jsArr, JsonObject jsObj, String attr, Object val) { | |||
if (val == null) { | |||
return Json.createNull(); | |||
} | |||
try { | |||
Class<?> valClaz = JsonValue.class; | |||
if (val instanceof Number) { | |||
val = ((Number) val).doubleValue(); | |||
valClaz = Double.TYPE; | |||
} else if (val instanceof Boolean) { | |||
valClaz = Boolean.TYPE; | |||
} else if (val instanceof Date) { | |||
val = ((Date) val).getTime(); | |||
valClaz = Double.TYPE; | |||
} else if (val instanceof String) { | |||
valClaz = String.class; | |||
} else if (val instanceof IsProperties) { | |||
val = ((IsProperties) val).getDataImpl(); | |||
} else if (val.getClass().isArray() || val instanceof List) { | |||
val = | |||
listToJsonArray(val.getClass().isArray() ? (Object[]) val : ((List<?>) val).toArray()); | |||
} else if (val instanceof Function) { | |||
val = new JreJsonFunction((Function) val); | |||
} | |||
if (jsObj != null) { | |||
Method mth = jsObj.getClass().getMethod("put", String.class, valClaz); | |||
mth.invoke(jsObj, new Object[] {attr, val}); | |||
return jsObj; | |||
} else { | |||
Method mth = jsArr.getClass().getMethod("set", Integer.TYPE, valClaz); | |||
mth.invoke(jsArr, new Object[] {new Integer(jsArr.length()), val}); | |||
return jsArr; | |||
} | |||
} catch (Throwable e) { | |||
e.printStackTrace(); | |||
} | |||
return null; | |||
} | |||
@Override | |||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |||
String mname = method.getName(); | |||
Class<?>[] classes = method.getParameterTypes(); | |||
int largs = classes.length; | |||
Name name = method.getAnnotation(Name.class); | |||
String attr = name != null ? name.value() : deCapitalize(mname.replaceFirst("^[gs]et", "")); | |||
if ("getFieldNames".equals(mname)) { | |||
return jsonObject.keys(); | |||
} else if ("as".equals(mname)) { | |||
@SuppressWarnings("unchecked") | |||
Class<? extends JsonBuilder> clz = (Class<? extends JsonBuilder>) args[0]; | |||
return jsonFactory.create(clz, jsonObject); | |||
} else if ("getJsonName".equals(mname)) { | |||
return JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass())); | |||
} else if (mname.matches("getProperties|getDataImpl")) { | |||
return jsonObject; | |||
} else if (largs > 0 && ("parse".equals(mname) || "load".equals(mname))) { | |||
String json = String.valueOf(args[0]); | |||
if (largs > 1 && Boolean.TRUE.equals(args[1])) { | |||
json = Properties.wrapPropertiesString(json); | |||
} | |||
jsonObject = Json.parse(json); | |||
} else if (mname.matches("toString")) { | |||
return jsonObject.toString(); | |||
} else if (mname.matches("toJsonWithName")) { | |||
String jsonName = | |||
JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass())); | |||
return "{\"" + jsonName + "\":" + jsonObject.toString() + "}"; | |||
} else if (mname.matches("toJson")) { | |||
return 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); | |||
} else if (largs == 2 && mname.equals("set")) { | |||
setValue(null, jsonObject, String.valueOf(args[0]), args[1]); | |||
return proxy; | |||
} else if (largs == 1 || mname.startsWith("set")) { | |||
setValue(null, jsonObject, attr, args[0]); | |||
return proxy; | |||
} | |||
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 : o.keys()) { | |||
ret += ret.isEmpty() ? "" : "&"; | |||
JsonValue v = o.get(k); | |||
if (v instanceof JsonArray) { | |||
for (int i = 0, l = ((JsonArray) v).length(); i < l; i++) { | |||
ret += i > 0 ? "&" : ""; | |||
JsonValue e = ((JsonArray) v).get(i); | |||
ret += k + "[]=" + e.toJson(); | |||
} | |||
} else { | |||
if (v != null && !(v instanceof JsonNull)) { | |||
ret += k + "=" + v.toJson(); | |||
} | |||
} | |||
} | |||
return ret; | |||
} | |||
} | |||
@SuppressWarnings("unchecked") | |||
public <T> T create(Class<T> clz, JsonObject jso) { | |||
InvocationHandler handler = new JsonBuilderHandler(jso); |
@@ -133,5 +133,15 @@ public class GQueryWidgetsTestGwt extends GWTTestCase { | |||
b2.click(); | |||
assertEquals("red", $(b1).css("color", false)); | |||
} | |||
public void testSelectorWidget() { | |||
final Button b1 = new Button("Button click"); | |||
RootPanel.get().add(b1); | |||
GQuery g = $(b1); | |||
assertTrue(g.isVisible()); | |||
g.hide(); | |||
assertFalse(g.isVisible()); | |||
b1.removeFromParent(); | |||
} | |||
} |
@@ -23,12 +23,11 @@ import com.google.gwt.query.client.IsProperties; | |||
import com.google.gwt.query.client.builders.JsonBuilder; | |||
import com.google.gwt.query.client.builders.Name; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.PrintStream; | |||
import java.util.Arrays; | |||
import java.util.Date; | |||
import java.util.List; | |||
/** | |||
* Tests for Deferred which can run either in JVM and GWT | |||
*/ | |||
@@ -152,4 +151,62 @@ public class DataBindingTestJre extends GWTTestCase { | |||
assertEquals(1, c.<Number>get("a").intValue()); | |||
} | |||
public interface GAddress extends JsonBuilder { | |||
String street(); | |||
String city(); | |||
} | |||
public interface GUser extends JsonBuilder { | |||
@Name("_id") | |||
String getId(); | |||
int getAge(); | |||
String getName(); | |||
GAddress address(); | |||
} | |||
public static final String JSON_USER_EXAMPLE = " { " | |||
+ " '_id': 'aaabbbccc', " | |||
+ " 'email': 'foo@bar.com', " | |||
+ " 'age': 27, " | |||
+ " 'name': 'Foo Bar', " | |||
+ " 'address': {" | |||
+ " 'street': 'Street Foo N6', " | |||
+ " 'phone': '670'" | |||
+ " }" | |||
+ "}"; | |||
public void | |||
test_parse_json() { | |||
GUser entity = GQ.create(GUser.class); | |||
entity.parse(JSON_USER_EXAMPLE, true); | |||
assertNotNull(entity.get("email")); | |||
assertEquals("aaabbbccc", entity.getId()); | |||
assertEquals(27, entity.getAge()); | |||
assertEquals("Foo Bar", entity.getName()); | |||
assertNotNull(entity.address()); | |||
assertEquals("Street Foo N6", entity.address().street()); | |||
assertNotNull(entity.address().get("phone")); | |||
} | |||
public void | |||
test_parse_strict_json() { | |||
GUser entity = GQ.create(GUser.class); | |||
entity.parse(JSON_USER_EXAMPLE, true); | |||
entity.strip(); | |||
assertEquals("aaabbbccc", entity.getId()); | |||
assertNull(entity.get("email")); | |||
assertEquals(27, entity.getAge()); | |||
assertEquals("Foo Bar", entity.getName()); | |||
assertNotNull(entity.address()); | |||
assertEquals("Street Foo N6", entity.address().street()); | |||
// Recursion not implemented in client side | |||
if (GWT.isScript()) { | |||
assertNull(entity.address().get("phone")); | |||
} | |||
} | |||
} |