]> source.dussan.org Git - gwtquery.git/commitdiff
Use native JSON.stringify when available. Fix to store native js numbers in Propertie...
authorManolo Carrasco <manolo@apache.org>
Mon, 10 Sep 2012 15:08:42 +0000 (15:08 +0000)
committerManolo Carrasco <manolo@apache.org>
Mon, 10 Sep 2012 15:08:42 +0000 (15:08 +0000)
gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java
gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java
gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsUtils.java
gwtquery-core/src/main/java/com/google/gwt/query/rebind/JsonBuilderGenerator.java
gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTestGwt.java
gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryCoreTestGwt.java

index 52c257f7a99eeaf8bb7f9c7275badcd41e6567d5..d2ae415e941a54121eb8ec368a5bedb2ce52b2c8 100644 (file)
@@ -15,7 +15,6 @@
  */\r
 package com.google.gwt.query.client;\r
 \r
-import com.google.gwt.core.client.GWT;\r
 import com.google.gwt.core.client.JavaScriptObject;\r
 import com.google.gwt.core.client.JsArrayMixed;\r
 import com.google.gwt.query.client.js.JsCache;\r
@@ -133,7 +132,15 @@ public class Properties extends JavaScriptObject {
     c().delete(String.valueOf(name));\r
   }\r
   \r
-  public final <T> void set(T name, Object val) {\r
+  public final <T> void setNumber(T name, double val) {\r
+    c().putNumber(name, val);\r
+  }\r
+\r
+  public final <T> void setBoolean(T name, boolean val) {\r
+    c().putBoolean(name, val);\r
+  }\r
+  \r
+  public final <T, O> void set(T name, O val) {\r
     c().put(String.valueOf(name), val);\r
   }\r
   \r
@@ -142,63 +149,11 @@ public class Properties extends JavaScriptObject {
   }\r
   \r
   public final String toJsonString() {\r
-    String ret = "";\r
-    for (String k : keys()){\r
-      String ky = k.matches("\\d+") ? k : "\"" + k + "\"";\r
-      JsCache o = getArray(k).cast();\r
-      if (o != null) {\r
-        ret += ky + ":[";\r
-        for (int i = 0, l = o.length(); i < l ; i++) {\r
-          Properties p = o.<JsCache>cast().getJavaScriptObject(i);\r
-          if (p != null) {\r
-            ret += p.toJsonString() + ",";\r
-          } else {\r
-            ret += "\"" + o.getString(i) + "\",";\r
-          }\r
-        }\r
-        ret += "],";\r
-      } else {\r
-        Properties p = getJavaScriptObject(k);\r
-        if (p != null) {\r
-          ret += ky + ":" + p.toJsonString() + ",";\r
-        } else {\r
-          ret += ky + ":\"" + getStr(k) + "\",";\r
-        }\r
-      }\r
-    }\r
-    return "{" + ret.replaceAll(",\\s*([\\]}]|$)","$1")\r
-    .replaceAll("([:,\\[])\"(-?[\\d\\.]+|null|false|true)\"", "$1$2")\r
-    + "}";\r
+    return JsUtils.JSON2String(JsCache.checkNull(this));\r
   }\r
   \r
   public final String toQueryString() {\r
-    String ret = "";\r
-    for (String k : keys()) {\r
-      ret += ret.isEmpty() ? "" : "&";\r
-      JsCache o = getArray(k).cast();\r
-      if (o != null) {\r
-        for (int i = 0, l = o.length(); i < l ; i++) {\r
-          ret += i > 0 ? "&" : "";\r
-          Properties p = o.<JsCache>cast().getJavaScriptObject(i);\r
-          if (p != null) {\r
-            ret += k + "[]=" + p.toJsonString();\r
-          } else {\r
-            ret += k + "[]=" + o.getString(i) ;\r
-          }\r
-        }\r
-      } else {\r
-        Properties p = getJavaScriptObject(k);\r
-        if (p != null) {\r
-          ret += p.toQueryString();\r
-        } else {\r
-          String v = getStr(k);\r
-          if (v != null && !v.isEmpty() && !"null".equalsIgnoreCase(v)) {\r
-            ret += k + "=" + v;\r
-          }          \r
-        }\r
-      }\r
-    }\r
-    return ret;\r
+    return JsUtils.param(JsCache.checkNull(this));\r
   }\r
   \r
   public final boolean isEmpty(){\r
index ba7242a984d83d975b7432bad2d7e706bcfaba50..9de4ebc116bb710059636c7dd5e9632855b284db 100644 (file)
@@ -114,6 +114,14 @@ public class JsCache extends JavaScriptObject {
   public final native int indexOf(Object o) /*-{
     return this.indexOf(o);
   }-*/;
+  
+  public final native <T> void putBoolean(T id, boolean b) /*-{
+    this[id] = b;
+  }-*/;
+  
+  public final native <T> void putNumber(T id, double n) /*-{
+    this[id] = n;
+  }-*/;
 
   public final native <T, O> void put(T id, O obj) /*-{
     this[id] = obj;
@@ -171,11 +179,9 @@ public class JsCache extends JavaScriptObject {
     return ret + "}";
   }
   
-  private void checkNull() {
-    // In dev-mode a null object casted to JavascriptObject does not throw a NPE
-    if (!GWT.isProdMode() && this == null) {
-      throw new NullPointerException();
-    }
+  // In dev-mode a null object casted to JavascriptObject does not throw a NPE
+  public final void checkNull() {
+    checkNull(this);
   }
   
   private final native JsArrayString keysImpl() /*-{
@@ -184,4 +190,14 @@ public class JsCache extends JavaScriptObject {
     for(key in this) if (key != '__gwt_ObjectId') keys.push(String(key));
     return keys;
   }-*/;
+  
+  /**
+   * Throw a NPE when a js is null
+   */
+  public static final <T extends JavaScriptObject> T checkNull(T js) {
+    if (!GWT.isProdMode() && js == null) {
+      throw new NullPointerException();
+    }
+    return js;
+  }
 }
index e3ad15861db6f0499eec479b45e9b82185b3846f..a41d15e5abc60100e472647e048b6ca4cf4cdce4 100644 (file)
@@ -61,6 +61,10 @@ public class JsUtils {
     public native Properties parseJSON(String json) /*-{
                        return $wnd.JSON.parse(json);
     }-*/;
+    
+    public native String JSON2String(JavaScriptObject o) /*-{
+      return $wnd.JSON.stringify(o);
+    }-*/;
 
     public native Element parseXML(String xml) /*-{
                        return new DOMParser().parseFromString(xml, "text/xml").documentElement;
@@ -77,7 +81,7 @@ public class JsUtils {
         Element e = a.get(i);
         int id = e.hashCode();
         if (!cache.exists(id)) {
-          cache.put(id, 1);
+          cache.putNumber(id, 1);
           ret.push(e);
         }
       }
@@ -100,6 +104,41 @@ public class JsUtils {
       // a well-formed json string.
       return evalImpl("(" + json + ")");
     }
+    
+    @Override
+    public String JSON2String(JavaScriptObject js) {
+      // This is a very basic implementation for IE6/IE7 of JSON.stringify
+      // If many people demand a better one we could consider to use json2.js
+      // @see https://github.com/douglascrockford/JSON-js/blob/master/json2.js
+      Properties prop = js.cast();
+      String ret = "";
+      for (String k : prop.keys()){
+        String ky = k.matches("\\d+") ? k : "\"" + k + "\"";
+        JsCache o = prop.getArray(k).cast();
+        if (o != null) {
+          ret += ky + ":[";
+          for (int i = 0, l = o.length(); i < l ; i++) {
+            Properties p = o.<JsCache>cast().getJavaScriptObject(i);
+            if (p != null) {
+              ret += p.toJsonString() + ",";
+            } else {
+              ret += "\"" + o.getString(i) + "\",";
+            }
+          }
+          ret += "],";
+        } else {
+          Properties p = prop.getJavaScriptObject(k);
+          if (p != null) {
+            ret += ky + ":" + p.toJsonString() + ",";
+          } else {
+            ret += ky + ":\"" + prop.getStr(k) + "\",";
+          }
+        }
+      }
+      return "{" + ret.replaceAll(",\\s*([\\]}]|$)","$1")
+      .replaceAll("([:,\\[])\"(-?[\\d\\.]+|null|false|true)\"", "$1$2")
+      + "}";
+    }
 
     @Override
     public native Element parseXML(String xml) /*-{
@@ -275,7 +314,7 @@ public class JsUtils {
         ? false
         : !"HTML".equals(getOwnerDocument(o).getDocumentElement().getNodeName());
   }
-
+  
   /**
    * Load an external javascript library. The inserted script replaces the
    * element with the given id in the document.
@@ -352,7 +391,46 @@ public class JsUtils {
     return utilsImpl.unique(a);
   }
 
-  public static String XML2String(JavaScriptObject o) {
-    return utilsImpl.XML2String(o);
+  public static String XML2String(JavaScriptObject js) {
+    return utilsImpl.XML2String(js);
+  }
+  
+  public static String JSON2String(JavaScriptObject js) {
+    return utilsImpl.JSON2String(js);
+  }
+  
+  /**
+   * Returns a QueryString representation of a JavascriptObject.
+   * TODO: jquery implementation accepts a second parameter (traditional) 
+   */
+  public static String param(JavaScriptObject js) {
+    Properties prop = js.cast();
+    String ret = "";
+    for (String k : prop.keys()) {
+      ret += ret.isEmpty() ? "" : "&";
+      JsCache o = prop.getArray(k).cast();
+      if (o != null) {
+        for (int i = 0, l = o.length(); i < l ; i++) {
+          ret += i > 0 ? "&" : "";
+          Properties p = o.<JsCache>cast().getJavaScriptObject(i);
+          if (p != null) {
+            ret += k + "[]=" + p.toJsonString();
+          } else {
+            ret += k + "[]=" + o.getString(i) ;
+          }
+        }
+      } else {
+        Properties p = prop.getJavaScriptObject(k);
+        if (p != null) {
+          ret += p.toQueryString();
+        } else {
+          String v = prop.getStr(k);
+          if (v != null && !v.isEmpty() && !"null".equalsIgnoreCase(v)) {
+            ret += k + "=" + v;
+          }          
+        }
+      }
+    }
+    return ret;
   }
 }
index bbb7e80ce439f3945b609b5aaf61bd0b6a025119..f61fd4e3a420c52dffde34924bec02f97569eeaa 100644 (file)
@@ -144,6 +144,10 @@ public class JsonBuilderGenerator extends Generator {
         sw.println("return new Date(java.lang.Long.parseLong(p.getStr(\"" + name + "\")));");\r
       } else if (method.getReturnType().isPrimitive() != null) {\r
         sw.println("return (" + retType + ")p.getFloat(\"" + name + "\");");\r
+      } else if (retType.equals("java.lang.Character")) {\r
+        sw.println("return (char) p.getFloat(\"" + name + "\");");\r
+      } else if (retType.equals("java.lang.Byte")) {\r
+        sw.println("return (byte) p.getFloat(\"" + name + "\");");\r
       } else if (retType.equals("java.lang.Integer")) {\r
          sw.println("return (int) p.getFloat(\"" + name + "\");");\r
       } else if (retType.equals("java.lang.Float")) {\r
@@ -154,7 +158,6 @@ public class JsonBuilderGenerator extends Generator {
          sw.println("return (long) p.getFloat(\"" + name + "\");");\r
       } else if (retType.equals("java.lang.Byte")) {\r
          sw.println("return (byte) p.getFloat(\"" + name + "\");");\r
-\r
       } else if (isTypeAssignableTo(method.getReturnType(), stringType)) {\r
         sw.println("return p.getStr(\"" + name + "\");");\r
       } else if (isTypeAssignableTo(method.getReturnType(), jsonBuilderType)) {\r
@@ -219,7 +222,11 @@ public class JsonBuilderGenerator extends Generator {
         }\r
         sw.println("setArrayBase(\"" + name + "\", " + a + ");");\r
       } else if (type.getParameterizedQualifiedSourceName().matches("java.util.Date")) {\r
-        sw.println("p.set(\"" + name + "\", a.getTime());");\r
+        sw.println("p.setNumber(\"" + name + "\", a.getTime());");\r
+      } else if (type.getParameterizedQualifiedSourceName().matches("(java.lang.(Character|Long|Double|Integer|Float|Byte)|(char|long|double|int|float|byte))")) {\r
+        sw.println("p.setNumber(\"" + name + "\", a);");\r
+      } else if (type.getParameterizedQualifiedSourceName().matches("(java.lang.Boolean|boolean)")) {\r
+        sw.println("p.setBoolean(\"" + name + "\", a);");        \r
       } else {\r
         sw.println("p.set(\"" + name + "\", a);");\r
       }\r
index 98a850941fb64009cf56fe6cc1746284cae6c98a..03eddce865f784213990dbdb43e4fe68ea3a49b4 100644 (file)
@@ -147,11 +147,14 @@ public class GQueryAjaxTestGwt extends GWTTestCase {
   
   public void testJsonValidService() {
     delayTestFinish(5000);
-    String testJsonpUrl = "http://services.digg.com/stories/top?appkey=http://mashup.com&type=javascript&callback=?";
+    // Use a public json service
+    String testJsonpUrl = "https://www.googleapis.com/blogger/v2/blogs/user_id/posts/post_id?callback=?&key=NO-KEY";
     Ajax.getJSONP(testJsonpUrl, new Function(){
       public void f() {
         Properties p = getDataProperties();
-        assertTrue(0 < p.getInt("count"));
+        // It should return error since we do not use a valid key
+        // {"error":{"errors":[{"domain":"usageLimits","reason":"keyInvalid","message":"Bad Request"}],"code":400,"message":"Bad Request"}}
+        assertEquals(400, p.getJavaScriptObject("error").<Properties>cast().getInt("code"));
         finishTest();
       }
     }, null, 0);
index c0843612d1e4d4085de056c53582ec05f3caba89..b14533c9f0bcc2c3ef6551a17104e842144a9bd9 100644 (file)
@@ -19,6 +19,14 @@ import static com.google.gwt.query.client.GQuery.$;
 import static com.google.gwt.query.client.GQuery.$$;
 import static com.google.gwt.query.client.GQuery.document;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import junit.framework.Assert;
+
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.dom.client.InputElement;
@@ -44,14 +52,6 @@ import com.google.gwt.user.client.ui.RootPanel;
 import com.google.gwt.user.client.ui.TextArea;
 import com.google.gwt.user.client.ui.Widget;
 
-import junit.framework.Assert;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
 /**
  * Test class for testing gwtquery-core api.
  */
@@ -539,7 +539,7 @@ public class GQueryCoreTestGwt extends GWTTestCase {
     
   }
 
-  public void aatestProperties() {
+  public void testProperties() {
     Properties p = $$("border:'1px solid black'");
     assertEquals(1, p.keys().length);
     assertNotNull(p.getStr("border"));
@@ -549,7 +549,10 @@ public class GQueryCoreTestGwt extends GWTTestCase {
     assertNotNull(p.getStr("border"));
     
     try {
-      // DevMode null casting return an object
+      // DevMode null casting returns an object
+      // @see:
+      //  http://code.google.com/p/gwtquery/issues/detail?id=122
+      //  http://code.google.com/p/google-web-toolkit/issues/detail?id=6625
       ((Properties)null).toJsonString();
       fail("Executing methods of a null object should throw a NullPointerException");
     } catch (NullPointerException e) {