]> source.dussan.org Git - gwtquery.git/commitdiff
First version of XmlBuilder generator, only getters work right now
authorManolo Carrasco <manolo@apache.org>
Fri, 30 Sep 2011 15:31:00 +0000 (15:31 +0000)
committerManolo Carrasco <manolo@apache.org>
Fri, 30 Sep 2011 15:31:00 +0000 (15:31 +0000)
gwtquery-core/src/main/java/com/google/gwt/query/Query.gwt.xml
gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java
gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonName.java [deleted file]
gwtquery-core/src/main/java/com/google/gwt/query/client/builders/Name.java [new file with mode: 0644]
gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilder.java [new file with mode: 0644]
gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilderBase.java [new file with mode: 0644]
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/main/java/com/google/gwt/query/rebind/XmlBuilderGenerator.java [new file with mode: 0644]
gwtquery-core/src/test/java/com/google/gwt/query/client/GQueryAjaxTest.java

index c8d1a594190fb459a7942cb77286c2974c1a70de..61cdd0df1d5a452d2a0824a3bedbe25dd9561f84 100644 (file)
 <module>\r
     <inherits name='com.google.gwt.user.User'/>\r
 \r
+    <!-- Json and Xml builders -->\r
     <generate-with class="com.google.gwt.query.rebind.JsonBuilderGenerator">\r
         <when-type-assignable class="com.google.gwt.query.client.builders.JsonBuilder"/>\r
     </generate-with>\r
+    <generate-with class="com.google.gwt.query.rebind.XmlBuilderGenerator">\r
+        <when-type-assignable class="com.google.gwt.query.client.builders.XmlBuilder"/>\r
+    </generate-with>    \r
 \r
     <!-- Lazy Generator -->\r
     <generate-with class="com.google.gwt.query.rebind.LazyGenerator">\r
index 25d51e1fdd035086dc387899a8013f4058cdf183..f754f4aca44aad7016fd552f2980cfc807102706 100644 (file)
@@ -3763,12 +3763,12 @@ public class GQuery implements Lazy<GQuery, LazyGQuery> {
   }\r
   \r
   /**\r
-   * Return the text contained in the first matched element.\r
+   * Return the concatened text contained in the matched elements.\r
    */\r
   public String text() {\r
     String result = "";\r
     for (Element e : elements) {\r
-      result += e.getInnerText();\r
+      result += JsUtils.text(e);\r
     }\r
     return result;\r
   }\r
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonName.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonName.java
deleted file mode 100644 (file)
index c385579..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*\r
- * Copyright 2011, The gwtquery team.\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
- * use this file except in compliance with the License. You may obtain a copy of\r
- * the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
- * License for the specific language governing permissions and limitations under\r
- * the License.\r
- */\r
-package com.google.gwt.query.client.builders;\r
-\r
-import static java.lang.annotation.ElementType.METHOD;\r
-import java.lang.annotation.Retention;\r
-import java.lang.annotation.RetentionPolicy;\r
-import java.lang.annotation.Target;\r
-\r
-/**\r
- */\r
-@Target({METHOD})\r
-@Retention(RetentionPolicy.RUNTIME)\r
-public @interface JsonName {\r
-  String value();\r
-}\r
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/Name.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/Name.java
new file mode 100644 (file)
index 0000000..5507677
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+ * Copyright 2011, The gwtquery team.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
+ * use this file except in compliance with the License. You may obtain a copy of\r
+ * the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
+ * License for the specific language governing permissions and limitations under\r
+ * the License.\r
+ */\r
+package com.google.gwt.query.client.builders;\r
+\r
+import static java.lang.annotation.ElementType.METHOD;\r
+import java.lang.annotation.Retention;\r
+import java.lang.annotation.RetentionPolicy;\r
+import java.lang.annotation.Target;\r
+\r
+/**\r
+ * Annotation used to specify the attribute, tag or property name\r
+ * in Json or Xml builders.\r
+ */\r
+@Target({METHOD})\r
+@Retention(RetentionPolicy.RUNTIME)\r
+public @interface Name {\r
+  String value();\r
+}\r
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilder.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilder.java
new file mode 100644 (file)
index 0000000..bf3153e
--- /dev/null
@@ -0,0 +1,38 @@
+/*\r
+ * Copyright 2011, The gwtquery team.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
+ * use this file except in compliance with the License. You may obtain a copy of\r
+ * the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
+ * License for the specific language governing permissions and limitations under\r
+ * the License.\r
+ */\r
+package com.google.gwt.query.client.builders;\r
+\r
+import com.google.gwt.dom.client.Element;\r
+\r
+/**\r
+ * Tagging interface used to generate XmlBuilder classes. \r
+ */\r
+public interface XmlBuilder {\r
+  /**\r
+   * load a string or a documentElement.\r
+   */\r
+  <J> J load(Object o);\r
+  \r
+  /**\r
+   * parses a xml string and loads the resulting documentElement.\r
+   */\r
+  <J> J parse(String xml);\r
+  \r
+  /**\r
+   * Returns the documentElement.\r
+   */\r
+  Element getDocumentElement();\r
+}\r
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilderBase.java b/gwtquery-core/src/main/java/com/google/gwt/query/client/builders/XmlBuilderBase.java
new file mode 100644 (file)
index 0000000..0c7fe01
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2011, The gwtquery team.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.query.client.builders;
+
+import static com.google.gwt.query.client.GQuery.$;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.query.client.GQuery;
+import com.google.gwt.query.client.Properties;
+import com.google.gwt.query.client.js.JsUtils;
+
+public abstract class XmlBuilderBase<J extends XmlBuilderBase<?>> implements XmlBuilder {
+  
+  //TODO empty document
+  protected GQuery g = $(JsUtils.parseXML("<root/>"));
+
+  @SuppressWarnings("unchecked")
+  public J parse(String xml) {
+    return load(JsUtils.parseXML(xml));
+  }
+  
+  @SuppressWarnings("unchecked")
+  public J load(Object o) {
+    assert o == null || o instanceof JavaScriptObject && JsUtils.isElement((JavaScriptObject)o) || o instanceof String;
+    if (o != null && o instanceof String) {
+        return parse((String)o);
+    }
+    if (o != null) {
+      g=$((Element)o);
+    }
+    return (J)this;
+  }
+  
+  public String getText() {
+    return g.text();
+  }
+
+  public void setText(String s) {
+    g.text(s);
+  }
+  
+  public String toString() {
+    return g.toString();
+  }
+  
+  protected Element getElementBase(String n) {
+    return g.children(n).get(0);
+  }
+  
+  protected Element[] getElementsBase(String n) {
+    return g.children(n).elements();
+  }
+  
+  public Element getDocumentElement() {
+    return g.get(0);
+  }
+  
+  protected float getFloatBase(String s) {
+    String n = getStrBase(s).replaceAll("[^\\d\\-\\.]", "");
+    return n.isEmpty() ? 0 : Float.parseFloat(n);
+  }
+  
+  protected Boolean getBooleanBase(String n) {
+    return "true".equalsIgnoreCase(getStrBase(n));
+  }
+  
+  protected String getStrBase(String n) {
+    return g.attr(n);
+  }
+  
+  protected Properties getPropertiesBase(String n) {
+    // TODO:
+    return null;
+  }
+}
index 307b7c5ca563241157bd19529f7727364c59a12d..5d64a4656202c6941c2c6632aa428859400355d1 100644 (file)
@@ -46,6 +46,10 @@ public class JsUtils {
      return (new XMLSerializer()).serializeToString(o);
     }-*/;
     
+    public String text(Element e) {
+      return e.getInnerText();
+    }
+    
     public JsArray<Element> unique(JsArray<Element> a) {
       JsArray<Element> ret = JavaScriptObject.createArray().cast();
       JsCache cache = JsCache.create();
@@ -93,6 +97,15 @@ public class JsUtils {
       }
       return super.unique(a);
     }
+    
+    @Override
+    public String text(Element e) {
+      return isXML(e) ? xmlText(e) : super.text(e);
+    }
+    
+    private native String xmlText(Element e) /*-{
+      return e.text;
+    }-*/;
   }
 
   /**
@@ -260,6 +273,10 @@ public class JsUtils {
     return utilsImpl.XML2String(o);
   }
   
+  public static String text(Element e) {
+    return utilsImpl.text(e);
+  }
+  
   /**
    * Parses a xml string and return the xml document element which
    * can then be passed to GQuery to create a typical GQuery object
index 35c6022f475825556cfdda337671f57acbf7752b..76d5a76c8bc803752396d2e417d88141810e522f 100644 (file)
@@ -31,7 +31,7 @@ import com.google.gwt.core.ext.typeinfo.JType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;\r
 import com.google.gwt.query.client.Properties;\r
 import com.google.gwt.query.client.builders.JsonBuilder;\r
-import com.google.gwt.query.client.builders.JsonName;\r
+import com.google.gwt.query.client.builders.Name;\r
 import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;\r
 import com.google.gwt.user.rebind.SourceWriter;\r
 \r
@@ -81,7 +81,7 @@ public class JsonBuilderGenerator extends Generator {
 \r
   public void generateMethod(SourceWriter sw, JMethod method, TreeLogger logger)\r
       throws UnableToCompleteException {\r
-    JsonName nameAnnotation = method.getAnnotation(JsonName.class);\r
+    Name nameAnnotation = method.getAnnotation(Name.class);\r
     String name = nameAnnotation != null ? nameAnnotation.value()\r
         : method.getName().replaceFirst("^(get|set)", "").toLowerCase();\r
 \r
diff --git a/gwtquery-core/src/main/java/com/google/gwt/query/rebind/XmlBuilderGenerator.java b/gwtquery-core/src/main/java/com/google/gwt/query/rebind/XmlBuilderGenerator.java
new file mode 100644 (file)
index 0000000..b0218d7
--- /dev/null
@@ -0,0 +1,165 @@
+/*\r
+ * Copyright 2011, The gwtquery team.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not\r
+ * use this file except in compliance with the License. You may obtain a copy of\r
+ * the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\r
+ * License for the specific language governing permissions and limitations under\r
+ * the License.\r
+ */\r
+package com.google.gwt.query.rebind;\r
+\r
+import java.io.PrintWriter;\r
+\r
+import com.google.gwt.core.ext.Generator;\r
+import com.google.gwt.core.ext.GeneratorContext;\r
+import com.google.gwt.core.ext.TreeLogger;\r
+import com.google.gwt.core.ext.UnableToCompleteException;\r
+import com.google.gwt.core.ext.typeinfo.JArrayType;\r
+import com.google.gwt.core.ext.typeinfo.JClassType;\r
+import com.google.gwt.core.ext.typeinfo.JMethod;\r
+import com.google.gwt.core.ext.typeinfo.JParameter;\r
+import com.google.gwt.core.ext.typeinfo.JPrimitiveType;\r
+import com.google.gwt.core.ext.typeinfo.JType;\r
+import com.google.gwt.core.ext.typeinfo.TypeOracle;\r
+import com.google.gwt.query.client.Properties;\r
+import com.google.gwt.query.client.builders.XmlBuilder;\r
+import com.google.gwt.query.client.builders.Name;\r
+import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;\r
+import com.google.gwt.user.rebind.SourceWriter;\r
+\r
+/**\r
+ */\r
+public class XmlBuilderGenerator extends Generator {\r
+  TypeOracle oracle;\r
+  static JClassType xmlBuilderType;\r
+  static JClassType stringType;\r
+\r
+  public String generate(TreeLogger treeLogger,\r
+      GeneratorContext generatorContext, String requestedClass)\r
+      throws UnableToCompleteException {\r
+    oracle = generatorContext.getTypeOracle();\r
+    JClassType clazz = oracle.findType(requestedClass);\r
+    xmlBuilderType = oracle.findType(XmlBuilder.class.getName());\r
+    stringType = oracle.findType(String.class.getName());\r
+\r
+    String t[] = generateClassName(clazz);\r
+\r
+    SourceWriter sw = getSourceWriter(treeLogger, generatorContext, t[0],\r
+        t[1], requestedClass);\r
+    if (sw != null) {\r
+      for (JMethod method : clazz.getMethods()) {\r
+        generateMethod(sw, method, treeLogger);\r
+      }\r
+      sw.commit(treeLogger);\r
+    }\r
+    return t[2];\r
+  }\r
+\r
+  public String[] generateClassName(JType t) {\r
+    String[] ret = new String[3];\r
+    JClassType c = t.isClassOrInterface();\r
+    ret[0] = c.getPackage().getName();\r
+    ret[1] = c.getName().replace('.', '_') + "_XmlBuilder";\r
+    ret[2] = ret[0] + "." + ret[1];\r
+    return ret;\r
+  }\r
+\r
+  public boolean isTypeAssignableTo(JType t, JClassType o) {\r
+    JClassType c = t.isClassOrInterface();\r
+    return (c != null && c.isAssignableTo(o));\r
+  }\r
+\r
+  public void generateMethod(SourceWriter sw, JMethod method, TreeLogger logger)\r
+      throws UnableToCompleteException {\r
+    Name nameAnnotation = method.getAnnotation(Name.class);\r
+    String name = nameAnnotation != null ? nameAnnotation.value()\r
+        : method.getName().replaceFirst("^(get|set)", "").toLowerCase();\r
+\r
+    String retType = method.getReturnType().getParameterizedQualifiedSourceName();\r
+\r
+    sw.print("public final " + retType + " " + method.getName());\r
+    JParameter[] params = method.getParameters();\r
+    if (params.length == 0) {\r
+      JArrayType arr = method.getReturnType().isArray();\r
+      sw.println("() {");\r
+      sw.indent();\r
+      if (retType.matches("(java.lang.Boolean|boolean)")) {\r
+        sw.println("return getBooleanBase(\"" + name + "\");");\r
+      } else if (method.getReturnType().isPrimitive() != null) {\r
+        sw.println("return (" + retType + ")getFloatBase(\"" + name + "\");");\r
+      } else if (isTypeAssignableTo(method.getReturnType(), stringType)) {\r
+        sw.println("return getStrBase(\"" + name + "\");");\r
+      } else if (isTypeAssignableTo(method.getReturnType(), xmlBuilderType)) {\r
+        String q = method.getReturnType().getQualifiedSourceName();\r
+        sw.println("Element e = getElementBase(\"" + name + "\");");\r
+        sw.println("return e == null ? null : (" + q + ")((" + q + ")GWT.create(" + q + ".class)).load(e);");\r
+      } else if (retType.equals(Properties.class.getName())){\r
+        sw.println("return getPropertiesBase(\"" + name + "\");");\r
+      } else if (arr != null) {\r
+        String q = arr.getComponentType().getQualifiedSourceName();\r
+        sw.println("ArrayList<" + q + "> l = new ArrayList<" + q+ ">();");\r
+        sw.println("for (Element e: getElementsBase(\"" + name + "\")) {");\r
+        sw.println("  " + q + " c = GWT.create(" + q + ".class);");\r
+        sw.println("  c.load(e);");\r
+        sw.println("  l.add(c);");\r
+        sw.println("}");\r
+        sw.println("return l.toArray(new " + q + "[0]);");\r
+//      } else {\r
+//        sw.println("return p.get(\"" + name + "\");");\r
+      }\r
+      sw.outdent();\r
+      sw.println("}");\r
+    } else if (params.length == 1) {\r
+      JType type = params[0].getType();\r
+      JArrayType arr = type.isArray();\r
+      JPrimitiveType pri = type.isPrimitive();\r
+      sw.print("(" + type.getParameterizedQualifiedSourceName() + " a)");\r
+      sw.println("{");\r
+      sw.indent();\r
+      if (arr != null) {\r
+        sw.println("setArrayBase(\"" + name + "\", a);");\r
+      } else if (pri != null) {\r
+      } else {\r
+        sw.println("p.set(\"" + name + "\", a);");\r
+      }\r
+      if (!"void".equals(retType)){\r
+        if (isTypeAssignableTo(method.getReturnType(), method.getEnclosingType())) {\r
+          sw.println("return this;");\r
+        } else {\r
+          sw.println("return null;");\r
+        }\r
+      }\r
+      sw.outdent();\r
+      sw.println("}");\r
+    }\r
+  }\r
+\r
+  protected SourceWriter getSourceWriter(TreeLogger logger,\r
+      GeneratorContext context, String packageName, String className,\r
+      String... interfaceNames) {\r
+    PrintWriter printWriter = context.tryCreate(logger, packageName, className);\r
+    if (printWriter == null) {\r
+      return null;\r
+    }\r
+    ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(\r
+        packageName, className);\r
+    composerFactory.setSuperclass("com.google.gwt.query.client.builders.XmlBuilderBase<"\r
+        + packageName + "." + className + ">");\r
+    composerFactory.addImport("com.google.gwt.query.client.js.*");\r
+    composerFactory.addImport("com.google.gwt.query.client.*");\r
+    composerFactory.addImport("com.google.gwt.core.client.*");\r
+    composerFactory.addImport("com.google.gwt.dom.client.*");\r
+    composerFactory.addImport("java.util.*");\r
+    for (String interfaceName : interfaceNames) {\r
+      composerFactory.addImplementedInterface(interfaceName);\r
+    }\r
+    return composerFactory.createSourceWriter(context, printWriter);\r
+  }\r
+}\r
index 540e1b41daf9e2391e543e75e965de1529748d92..841015b4be036d634d0f942c0ea43eb68694f8a4 100644 (file)
@@ -20,7 +20,8 @@ import com.google.gwt.core.client.GWT;
 import com.google.gwt.dom.client.Element;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.query.client.builders.JsonBuilder;
-import com.google.gwt.query.client.builders.JsonName;
+import com.google.gwt.query.client.builders.Name;
+import com.google.gwt.query.client.builders.XmlBuilder;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.RootPanel;
 
@@ -48,21 +49,21 @@ public class GQueryAjaxTest extends GWTTestCase {
     }
   }
   
-  interface MyClass extends JsonBuilder {
+  interface JsonExample extends JsonBuilder {
     int getA();
-    MyClass getB();
-    @JsonName("u")
+    JsonExample getB();
+    @Name("u")
     String getUrl();
     long getD();
     Boolean getZ();
     String[] getT();
-    MyClass setT(String[] strings);
-    MyClass setZ(Boolean b);
+    JsonExample setT(String[] strings);
+    JsonExample setZ(Boolean b);
   }
   
   public void testJsonBuilder() {
     String json = "[{a:1, b:{a:2,b:{a:3}},u:url, d:'2','t':['hola','adios'], 'z': true}]";
-    MyClass c = GWT.create(MyClass.class);
+    JsonExample c = GWT.create(JsonExample.class);
     assertEquals(0, c.getA());
     c.parse(json, true);
     assertEquals(1, c.getA());
@@ -79,4 +80,26 @@ public class GQueryAjaxTest extends GWTTestCase {
     assertEquals("foo", c.getT()[0]);
     assertEquals("bar", c.getT()[1]);
   }
+  
+  interface XmlExample extends XmlBuilder {
+    String getA();
+    Boolean getB();
+    @Name("c")
+    int getNumber();
+    
+    XmlExample[] getX();
+    @Name("x")
+    XmlExample getFirstX();
+  }
+  
+  public void testXmlBuilder() {
+    String xml = "<a a='ra' b='true' c='-1.48'><x a='xa1'/> <x a='xa2'/> text</a>";
+    XmlExample x = GWT.create(XmlExample.class);
+    x.parse(xml);
+    assertTrue(x.getB());
+    assertEquals("ra", x.getA());
+    assertEquals(-1, x.getNumber());
+    assertEquals("xa2", x.getX()[1].getA());
+    assertEquals("xa1", x.getFirstX().getA());
+  }
 }