1.1 --- a/.hgtags Mon Mar 25 13:29:42 2013 +0100
1.2 +++ b/.hgtags Thu Apr 11 16:59:42 2013 +0200
1.3 @@ -1,3 +1,7 @@
1.4 0a115f1c6f3c70458fc479ae82b4d7fcdeb7e95a jdk7-b147_base
1.5 7367a296a9ec4a88e0292a41244c96283818e563 bck2brwsr-0.3
1.6 caf1e66268fd4100d57922d973ae09a6bf3be847 release-${releaseVersion}
1.7 +30e9ac29654fba6f67d0921e7e3aa21133442592 release-0.5
1.8 +caf1e66268fd4100d57922d973ae09a6bf3be847 release-0.4
1.9 +caf1e66268fd4100d57922d973ae09a6bf3be847 release-${releaseVersion}
1.10 +0000000000000000000000000000000000000000 release-${releaseVersion}
2.1 --- a/benchmarks/matrix-multiplication/pom.xml Mon Mar 25 13:29:42 2013 +0100
2.2 +++ b/benchmarks/matrix-multiplication/pom.xml Thu Apr 11 16:59:42 2013 +0200
2.3 @@ -4,12 +4,12 @@
2.4
2.5 <groupId>org.apidesign.bck2brwsr</groupId>
2.6 <artifactId>matrix.multiplication</artifactId>
2.7 - <version>0.5-SNAPSHOT</version>
2.8 + <version>0.6-SNAPSHOT</version>
2.9 <packaging>jar</packaging>
2.10 <parent>
2.11 <artifactId>benchmarks</artifactId>
2.12 <groupId>org.apidesign.bck2brwsr</groupId>
2.13 - <version>0.5-SNAPSHOT</version>
2.14 + <version>0.6-SNAPSHOT</version>
2.15 </parent>
2.16
2.17 <name>Matrix multiplication</name>
2.18 @@ -74,7 +74,7 @@
2.19 <dependency>
2.20 <groupId>org.apidesign.bck2brwsr</groupId>
2.21 <artifactId>emul.mini</artifactId>
2.22 - <version>0.5-SNAPSHOT</version>
2.23 + <version>0.6-SNAPSHOT</version>
2.24 </dependency>
2.25 <dependency>
2.26 <groupId>org.testng</groupId>
2.27 @@ -91,7 +91,7 @@
2.28 <dependency>
2.29 <groupId>org.apidesign.bck2brwsr</groupId>
2.30 <artifactId>vmtest</artifactId>
2.31 - <version>0.5-SNAPSHOT</version>
2.32 + <version>0.6-SNAPSHOT</version>
2.33 <scope>test</scope>
2.34 </dependency>
2.35 </dependencies>
3.1 --- a/benchmarks/pom.xml Mon Mar 25 13:29:42 2013 +0100
3.2 +++ b/benchmarks/pom.xml Thu Apr 11 16:59:42 2013 +0200
3.3 @@ -4,11 +4,11 @@
3.4 <parent>
3.5 <artifactId>bck2brwsr</artifactId>
3.6 <groupId>org.apidesign</groupId>
3.7 - <version>0.5-SNAPSHOT</version>
3.8 + <version>0.6-SNAPSHOT</version>
3.9 </parent>
3.10 <groupId>org.apidesign.bck2brwsr</groupId>
3.11 <artifactId>benchmarks</artifactId>
3.12 - <version>0.5-SNAPSHOT</version>
3.13 + <version>0.6-SNAPSHOT</version>
3.14 <packaging>pom</packaging>
3.15 <name>Performance benchmarks</name>
3.16 <modules>
4.1 --- a/dew/pom.xml Mon Mar 25 13:29:42 2013 +0100
4.2 +++ b/dew/pom.xml Thu Apr 11 16:59:42 2013 +0200
4.3 @@ -4,11 +4,11 @@
4.4 <parent>
4.5 <groupId>org.apidesign</groupId>
4.6 <artifactId>bck2brwsr</artifactId>
4.7 - <version>0.5-SNAPSHOT</version>
4.8 + <version>0.6-SNAPSHOT</version>
4.9 </parent>
4.10 <groupId>org.apidesign.bck2brwsr</groupId>
4.11 <artifactId>dew</artifactId>
4.12 - <version>0.5-SNAPSHOT</version>
4.13 + <version>0.6-SNAPSHOT</version>
4.14 <name>Development Environment for Web</name>
4.15 <url>http://maven.apache.org</url>
4.16 <build>
5.1 --- a/ide/editor/pom.xml Mon Mar 25 13:29:42 2013 +0100
5.2 +++ b/ide/editor/pom.xml Thu Apr 11 16:59:42 2013 +0200
5.3 @@ -4,19 +4,18 @@
5.4 <parent>
5.5 <artifactId>ide</artifactId>
5.6 <groupId>org.apidesign.bck2brwsr</groupId>
5.7 - <version>0.5-SNAPSHOT</version>
5.8 + <version>0.6-SNAPSHOT</version>
5.9 </parent>
5.10
5.11 - <groupId>org.apidesign.bck2brwsr.ide.editor</groupId>
5.12 + <groupId>org.apidesign.bck2brwsr.ide</groupId>
5.13 <artifactId>editor</artifactId>
5.14 - <version>0.5-SNAPSHOT</version>
5.15 + <version>0.6-SNAPSHOT</version>
5.16 <packaging>nbm</packaging>
5.17
5.18 <name>Editor Support for Bck2Brwsr</name>
5.19
5.20 <properties>
5.21 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
5.22 - <netbeans.version>RELEASE72</netbeans.version>
5.23 <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
5.24 </properties>
5.25
5.26 @@ -40,71 +39,59 @@
5.27 <dependency>
5.28 <groupId>org.netbeans.api</groupId>
5.29 <artifactId>org-netbeans-api-annotations-common</artifactId>
5.30 - <version>${netbeans.version}</version>
5.31 </dependency>
5.32 <dependency>
5.33 <groupId>org.netbeans.api</groupId>
5.34 <artifactId>org-netbeans-modules-java-source</artifactId>
5.35 - <version>${netbeans.version}</version>
5.36 </dependency>
5.37 <dependency>
5.38 <groupId>org.netbeans.api</groupId>
5.39 <artifactId>org-netbeans-libs-javacapi</artifactId>
5.40 - <version>${netbeans.version}</version>
5.41 </dependency>
5.42 <dependency>
5.43 <groupId>org.netbeans.api</groupId>
5.44 <artifactId>org-netbeans-spi-java-hints</artifactId>
5.45 - <version>${netbeans.version}</version>
5.46 </dependency>
5.47 <dependency>
5.48 <groupId>org.netbeans.api</groupId>
5.49 <artifactId>org-netbeans-modules-parsing-api</artifactId>
5.50 - <version>${netbeans.version}</version>
5.51 </dependency>
5.52 <dependency>
5.53 <groupId>org.netbeans.api</groupId>
5.54 <artifactId>org-netbeans-spi-editor-hints</artifactId>
5.55 - <version>${netbeans.version}</version>
5.56 </dependency>
5.57 <dependency>
5.58 <groupId>org.netbeans.api</groupId>
5.59 <artifactId>org-openide-util</artifactId>
5.60 - <version>${netbeans.version}</version>
5.61 </dependency>
5.62 <dependency>
5.63 <groupId>org.netbeans.api</groupId>
5.64 <artifactId>org-netbeans-modules-java-lexer</artifactId>
5.65 - <version>${netbeans.version}</version>
5.66 </dependency>
5.67 <dependency>
5.68 <groupId>org.netbeans.api</groupId>
5.69 <artifactId>org-netbeans-modules-lexer</artifactId>
5.70 - <version>${netbeans.version}</version>
5.71 </dependency>
5.72 <dependency>
5.73 <groupId>org.apidesign.bck2brwsr</groupId>
5.74 <artifactId>core</artifactId>
5.75 - <version>0.5-SNAPSHOT</version>
5.76 + <version>0.6-SNAPSHOT</version>
5.77 <type>jar</type>
5.78 <scope>test</scope>
5.79 </dependency>
5.80 <dependency>
5.81 <groupId>org.netbeans.api</groupId>
5.82 <artifactId>org-netbeans-modules-java-hints-test</artifactId>
5.83 - <version>${netbeans.version}</version>
5.84 <scope>test</scope>
5.85 </dependency>
5.86 <dependency>
5.87 <groupId>org.netbeans.api</groupId>
5.88 <artifactId>org-netbeans-libs-junit4</artifactId>
5.89 - <version>${netbeans.version}</version>
5.90 <scope>test</scope>
5.91 </dependency>
5.92 <dependency>
5.93 <groupId>org.netbeans.modules</groupId>
5.94 <artifactId>org-netbeans-lib-nbjavac</artifactId>
5.95 - <version>${netbeans.version}</version>
5.96 <scope>test</scope>
5.97 </dependency>
5.98 <dependency>
6.1 --- a/ide/pom.xml Mon Mar 25 13:29:42 2013 +0100
6.2 +++ b/ide/pom.xml Thu Apr 11 16:59:42 2013 +0200
6.3 @@ -4,11 +4,11 @@
6.4 <parent>
6.5 <artifactId>bck2brwsr</artifactId>
6.6 <groupId>org.apidesign</groupId>
6.7 - <version>0.5-SNAPSHOT</version>
6.8 + <version>0.6-SNAPSHOT</version>
6.9 </parent>
6.10 <groupId>org.apidesign.bck2brwsr</groupId>
6.11 <artifactId>ide</artifactId>
6.12 - <version>0.5-SNAPSHOT</version>
6.13 + <version>0.6-SNAPSHOT</version>
6.14 <packaging>pom</packaging>
6.15 <name>IDE Support</name>
6.16 <modules>
7.1 --- a/javaquery/api/pom.xml Mon Mar 25 13:29:42 2013 +0100
7.2 +++ b/javaquery/api/pom.xml Thu Apr 11 16:59:42 2013 +0200
7.3 @@ -4,11 +4,11 @@
7.4 <parent>
7.5 <groupId>org.apidesign.bck2brwsr</groupId>
7.6 <artifactId>javaquery</artifactId>
7.7 - <version>0.5-SNAPSHOT</version>
7.8 + <version>0.6-SNAPSHOT</version>
7.9 </parent>
7.10 <groupId>org.apidesign.bck2brwsr</groupId>
7.11 <artifactId>javaquery.api</artifactId>
7.12 - <version>0.5-SNAPSHOT</version>
7.13 + <version>0.6-SNAPSHOT</version>
7.14 <name>JavaQuery API</name>
7.15 <url>http://maven.apache.org</url>
7.16 <build>
7.17 @@ -18,8 +18,8 @@
7.18 <artifactId>maven-compiler-plugin</artifactId>
7.19 <version>2.3.2</version>
7.20 <configuration>
7.21 - <source>1.6</source>
7.22 - <target>1.6</target>
7.23 + <source>1.7</source>
7.24 + <target>1.7</target>
7.25 </configuration>
7.26 </plugin>
7.27 <plugin>
8.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypes.java Mon Mar 25 13:29:42 2013 +0100
8.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypes.java Thu Apr 11 16:59:42 2013 +0200
8.3 @@ -41,11 +41,112 @@
8.4 Object ret = getProperty(object, property);
8.5 return ret instanceof Number ? ((Number)ret).intValue() : Integer.MIN_VALUE;
8.6 }
8.7 +
8.8 + public static <T> T toModel(Class<T> modelClass, Object object, String property) {
8.9 + Object ret = getProperty(object, property);
8.10 + if (ret == null || modelClass.isInstance(ret)) {
8.11 + return modelClass.cast(ret);
8.12 + }
8.13 + throw new IllegalStateException("Value " + ret + " is not of type " + modelClass);
8.14 + }
8.15 +
8.16 + public static String toJSON(Object value) {
8.17 + if (value == null) {
8.18 + return "null";
8.19 + }
8.20 + if (value instanceof String) {
8.21 + return '"' +
8.22 + ((String)value).
8.23 + replace("\"", "\\\"").
8.24 + replace("\n", "\\n").
8.25 + replace("\r", "\\r").
8.26 + replace("\t", "\\t")
8.27 + + '"';
8.28 + }
8.29 + return value.toString();
8.30 + }
8.31
8.32 @JavaScriptBody(args = { "object", "property" },
8.33 - body = "var p = object[property]; return p ? p : null;"
8.34 + body = "if (property === null) return object;\n"
8.35 + + "var p = object[property]; return p ? p : null;"
8.36 )
8.37 private static Object getProperty(Object object, String property) {
8.38 return null;
8.39 }
8.40 +
8.41 + public static String createJSONP(Object[] jsonResult, Runnable whenDone) {
8.42 + int h = whenDone.hashCode();
8.43 + String name;
8.44 + for (;;) {
8.45 + name = "jsonp" + Integer.toHexString(h);
8.46 + if (defineIfUnused(name, jsonResult, whenDone)) {
8.47 + return name;
8.48 + }
8.49 + h++;
8.50 + }
8.51 + }
8.52 +
8.53 + @JavaScriptBody(args = { "name", "arr", "run" }, body =
8.54 + "if (window[name]) return false;\n "
8.55 + + "window[name] = function(data) {\n "
8.56 + + " delete window[name];\n"
8.57 + + " var el = window.document.getElementById(name);\n"
8.58 + + " el.parentNode.removeChild(el);\n"
8.59 + + " arr[0] = data;\n"
8.60 + + " run.run__V();\n"
8.61 + + "};\n"
8.62 + + "return true;\n"
8.63 + )
8.64 + private static boolean defineIfUnused(String name, Object[] arr, Runnable run) {
8.65 + return true;
8.66 + }
8.67 +
8.68 + @JavaScriptBody(args = { "url", "arr", "callback" }, body = ""
8.69 + + "var request = new XMLHttpRequest();\n"
8.70 + + "request.open('GET', url, true);\n"
8.71 + + "request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n"
8.72 + + "request.onreadystatechange = function() {\n"
8.73 + + " if (this.readyState!==4) return;\n"
8.74 + + " try {\n"
8.75 + + " arr[0] = eval('(' + this.response + ')');\n"
8.76 + + " } catch (error) {;\n"
8.77 + + " throw 'Cannot parse' + error + ':' + this.response;\n"
8.78 + + " };\n"
8.79 + + " callback.run__V();\n"
8.80 + + "};"
8.81 + + "request.send();"
8.82 + )
8.83 + private static void loadJSON(
8.84 + String url, Object[] jsonResult, Runnable whenDone
8.85 + ) {
8.86 + }
8.87 +
8.88 + public static void loadJSON(
8.89 + String url, Object[] jsonResult, Runnable whenDone, String jsonp
8.90 + ) {
8.91 + if (jsonp == null) {
8.92 + loadJSON(url, jsonResult, whenDone);
8.93 + } else {
8.94 + loadJSONP(url, jsonp);
8.95 + }
8.96 + }
8.97 +
8.98 + @JavaScriptBody(args = { "url", "jsonp" }, body =
8.99 + "var scrpt = window.document.createElement('script');\n "
8.100 + + "scrpt.setAttribute('src', url);\n "
8.101 + + "scrpt.setAttribute('id', jsonp);\n "
8.102 + + "scrpt.setAttribute('type', 'text/javascript');\n "
8.103 + + "var body = document.getElementsByTagName('body')[0];\n "
8.104 + + "body.appendChild(scrpt);\n"
8.105 + )
8.106 + private static void loadJSONP(String url, String jsonp) {
8.107 +
8.108 + }
8.109 +
8.110 + public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
8.111 + for (int i = 0; i < props.length; i++) {
8.112 + values[i] = getProperty(jsonObject, props[i]);
8.113 + }
8.114 + }
8.115 +
8.116 }
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/KOList.java Thu Apr 11 16:59:42 2013 +0200
9.3 @@ -0,0 +1,167 @@
9.4 +/**
9.5 + * Back 2 Browser Bytecode Translator
9.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
9.7 + *
9.8 + * This program is free software: you can redistribute it and/or modify
9.9 + * it under the terms of the GNU General Public License as published by
9.10 + * the Free Software Foundation, version 2 of the License.
9.11 + *
9.12 + * This program is distributed in the hope that it will be useful,
9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.15 + * GNU General Public License for more details.
9.16 + *
9.17 + * You should have received a copy of the GNU General Public License
9.18 + * along with this program. Look for COPYING file in the top folder.
9.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
9.20 + */
9.21 +package org.apidesign.bck2brwsr.htmlpage;
9.22 +
9.23 +import java.util.ArrayList;
9.24 +import java.util.Collection;
9.25 +import java.util.Iterator;
9.26 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
9.27 +
9.28 +/**
9.29 + *
9.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
9.31 + */
9.32 +public final class KOList<T> extends ArrayList<T> {
9.33 + private final String name;
9.34 + private final String[] deps;
9.35 + private Knockout model;
9.36 + private Runnable onchange;
9.37 +
9.38 + public KOList(String name, String... deps) {
9.39 + this.name = name;
9.40 + this.deps = deps;
9.41 + }
9.42 +
9.43 + public void assign(Knockout model) {
9.44 + if (this.model != model) {
9.45 + this.model = model;
9.46 + notifyChange();
9.47 + }
9.48 + }
9.49 +
9.50 + public KOList<T> onChange(Runnable r) {
9.51 + if (this.onchange != null) {
9.52 + throw new IllegalStateException();
9.53 + }
9.54 + this.onchange = r;
9.55 + return this;
9.56 + }
9.57 +
9.58 + @Override
9.59 + public boolean add(T e) {
9.60 + boolean ret = super.add(e);
9.61 + notifyChange();
9.62 + return ret;
9.63 + }
9.64 +
9.65 + @Override
9.66 + public boolean addAll(Collection<? extends T> c) {
9.67 + boolean ret = super.addAll(c);
9.68 + notifyChange();
9.69 + return ret;
9.70 + }
9.71 +
9.72 + @Override
9.73 + public boolean addAll(int index, Collection<? extends T> c) {
9.74 + boolean ret = super.addAll(index, c);
9.75 + notifyChange();
9.76 + return ret;
9.77 + }
9.78 +
9.79 + @Override
9.80 + public boolean remove(Object o) {
9.81 + boolean ret = super.remove(o);
9.82 + notifyChange();
9.83 + return ret;
9.84 + }
9.85 +
9.86 + @Override
9.87 + public void clear() {
9.88 + super.clear();
9.89 + notifyChange();
9.90 + }
9.91 +
9.92 + @Override
9.93 + public boolean removeAll(Collection<?> c) {
9.94 + boolean ret = super.removeAll(c);
9.95 + notifyChange();
9.96 + return ret;
9.97 + }
9.98 +
9.99 + @Override
9.100 + public boolean retainAll(Collection<?> c) {
9.101 + boolean ret = super.retainAll(c);
9.102 + notifyChange();
9.103 + return ret;
9.104 + }
9.105 +
9.106 + @Override
9.107 + public T set(int index, T element) {
9.108 + T ret = super.set(index, element);
9.109 + notifyChange();
9.110 + return ret;
9.111 + }
9.112 +
9.113 + @Override
9.114 + public void add(int index, T element) {
9.115 + super.add(index, element);
9.116 + notifyChange();
9.117 + }
9.118 +
9.119 + @Override
9.120 + public T remove(int index) {
9.121 + T ret = super.remove(index);
9.122 + notifyChange();
9.123 + return ret;
9.124 + }
9.125 +
9.126 + @Override
9.127 + public String toString() {
9.128 + Iterator<T> it = iterator();
9.129 + if (!it.hasNext()) {
9.130 + return "[]";
9.131 + }
9.132 + String sep = "";
9.133 + StringBuilder sb = new StringBuilder();
9.134 + sb.append('[');
9.135 + while (it.hasNext()) {
9.136 + T t = it.next();
9.137 + sb.append(sep);
9.138 + sb.append(ConvertTypes.toJSON(t));
9.139 + sep = ",";
9.140 + }
9.141 + sb.append(']');
9.142 + return sb.toString();
9.143 + }
9.144 +
9.145 +
9.146 + @JavaScriptOnly(name = "koArray", value = "function() { return this.toArray___3Ljava_lang_Object_2(); }")
9.147 + private static native int koArray();
9.148 +
9.149 + private void notifyChange() {
9.150 + Knockout m = model;
9.151 + if (m != null) {
9.152 + m.valueHasMutated(name);
9.153 + for (String dependant : deps) {
9.154 + m.valueHasMutated(dependant);
9.155 + }
9.156 + }
9.157 + Runnable r = onchange;
9.158 + if (r != null) {
9.159 + r.run();
9.160 + }
9.161 + }
9.162 +
9.163 + @Override
9.164 + public KOList clone() {
9.165 + KOList ko = (KOList)super.clone();
9.166 + ko.model = null;
9.167 + return ko;
9.168 + }
9.169 +
9.170 +}
10.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java Mon Mar 25 13:29:42 2013 +0100
10.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java Thu Apr 11 16:59:42 2013 +0200
10.3 @@ -18,6 +18,7 @@
10.4 package org.apidesign.bck2brwsr.htmlpage;
10.5
10.6 import java.lang.reflect.Method;
10.7 +import java.util.List;
10.8 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
10.9 import org.apidesign.bck2brwsr.core.JavaScriptBody;
10.10
10.11 @@ -29,38 +30,40 @@
10.12 public class Knockout {
10.13 /** used by tests */
10.14 static Knockout next;
10.15 -
10.16 - Knockout() {
10.17 + private final Object model;
10.18 +
10.19 + Knockout(Object model) {
10.20 + this.model = model == null ? this : model;
10.21 }
10.22
10.23 public static <M> Knockout applyBindings(
10.24 - Class<M> modelClass, M model, String[] propsGettersAndSetters
10.25 + Object model, String[] propsGettersAndSetters,
10.26 + String[] methodsAndSignatures
10.27 + ) {
10.28 + applyImpl(propsGettersAndSetters, model.getClass(), model, model, methodsAndSignatures);
10.29 + return new Knockout(model);
10.30 + }
10.31 + public static <M> Knockout applyBindings(
10.32 + Class<M> modelClass, M model, String[] propsGettersAndSetters,
10.33 + String[] methodsAndSignatures
10.34 ) {
10.35 Knockout bindings = next;
10.36 next = null;
10.37 if (bindings == null) {
10.38 - bindings = new Knockout();
10.39 + bindings = new Knockout(null);
10.40 }
10.41 - for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
10.42 - try {
10.43 - Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
10.44 - bind(bindings, model, propsGettersAndSetters[i],
10.45 - propsGettersAndSetters[i + 1],
10.46 - propsGettersAndSetters[i + 2],
10.47 - getter.getReturnType().isPrimitive()
10.48 - );
10.49 - } catch (NoSuchMethodException ex) {
10.50 - throw new IllegalStateException(ex.getMessage());
10.51 - }
10.52 - }
10.53 + applyImpl(propsGettersAndSetters, modelClass, bindings, model, methodsAndSignatures);
10.54 applyBindings(bindings);
10.55 return bindings;
10.56 }
10.57
10.58 - @JavaScriptBody(args = { "prop" }, body =
10.59 - "this[prop].valueHasMutated();"
10.60 + public void valueHasMutated(String prop) {
10.61 + valueHasMutated(model, prop);
10.62 + }
10.63 + @JavaScriptBody(args = { "self", "prop" }, body =
10.64 + "self[prop].valueHasMutated();"
10.65 )
10.66 - public void valueHasMutated(String prop) {
10.67 + public void valueHasMutated(Object self, String prop) {
10.68 }
10.69
10.70
10.71 @@ -68,10 +71,11 @@
10.72 public static void triggerEvent(String id, String ev) {
10.73 }
10.74
10.75 - @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive" }, body =
10.76 + @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive", "array" }, body =
10.77 "var bnd = {\n"
10.78 + " 'read': function() {\n"
10.79 + " var v = model[getter]();\n"
10.80 + + " if (array) v = v.koArray();\n"
10.81 + " return v;\n"
10.82 + " },\n"
10.83 + " 'owner': bindings\n"
10.84 @@ -84,10 +88,43 @@
10.85 + "bindings[prop] = ko['computed'](bnd);"
10.86 )
10.87 private static void bind(
10.88 - Object bindings, Object model, String prop, String getter, String setter, boolean primitive
10.89 + Object bindings, Object model, String prop, String getter, String setter, boolean primitive, boolean array
10.90 + ) {
10.91 + }
10.92 +
10.93 + @JavaScriptBody(args = { "bindings", "model", "prop", "sig" }, body =
10.94 + "bindings[prop] = function(data, ev) { model[sig](data, ev); };"
10.95 + )
10.96 + private static void expose(
10.97 + Object bindings, Object model, String prop, String sig
10.98 ) {
10.99 }
10.100
10.101 @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
10.102 private static void applyBindings(Object bindings) {}
10.103 +
10.104 + private static void applyImpl(
10.105 + String[] propsGettersAndSetters,
10.106 + Class<?> modelClass,
10.107 + Object bindings,
10.108 + Object model,
10.109 + String[] methodsAndSignatures
10.110 + ) throws IllegalStateException, SecurityException {
10.111 + for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
10.112 + try {
10.113 + Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
10.114 + bind(bindings, model, propsGettersAndSetters[i],
10.115 + propsGettersAndSetters[i + 1],
10.116 + propsGettersAndSetters[i + 2],
10.117 + getter.getReturnType().isPrimitive(),
10.118 + List.class.isAssignableFrom(getter.getReturnType()));
10.119 + } catch (NoSuchMethodException ex) {
10.120 + throw new IllegalStateException(ex.getMessage());
10.121 + }
10.122 + }
10.123 + for (int i = 0; i < methodsAndSignatures.length; i += 2) {
10.124 + expose(
10.125 + bindings, model, methodsAndSignatures[i], methodsAndSignatures[i + 1]);
10.126 + }
10.127 + }
10.128 }
11.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Mon Mar 25 13:29:42 2013 +0100
11.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java Thu Apr 11 16:59:42 2013 +0200
11.3 @@ -20,23 +20,29 @@
11.4 import java.io.IOException;
11.5 import java.io.InputStream;
11.6 import java.io.OutputStreamWriter;
11.7 +import java.io.StringWriter;
11.8 import java.io.Writer;
11.9 +import java.lang.annotation.AnnotationTypeMismatchException;
11.10 +import java.lang.reflect.Method;
11.11 import java.util.ArrayList;
11.12 import java.util.Collection;
11.13 import java.util.Collections;
11.14 import java.util.HashMap;
11.15 +import java.util.HashSet;
11.16 import java.util.LinkedHashSet;
11.17 import java.util.List;
11.18 -import java.util.Locale;
11.19 import java.util.Map;
11.20 import java.util.Set;
11.21 +import java.util.WeakHashMap;
11.22 import javax.annotation.processing.AbstractProcessor;
11.23 import javax.annotation.processing.Completion;
11.24 import javax.annotation.processing.Completions;
11.25 +import javax.annotation.processing.ProcessingEnvironment;
11.26 import javax.annotation.processing.Processor;
11.27 import javax.annotation.processing.RoundEnvironment;
11.28 import javax.annotation.processing.SupportedAnnotationTypes;
11.29 import javax.lang.model.element.AnnotationMirror;
11.30 +import javax.lang.model.element.AnnotationValue;
11.31 import javax.lang.model.element.Element;
11.32 import javax.lang.model.element.ElementKind;
11.33 import javax.lang.model.element.ExecutableElement;
11.34 @@ -44,14 +50,21 @@
11.35 import javax.lang.model.element.PackageElement;
11.36 import javax.lang.model.element.TypeElement;
11.37 import javax.lang.model.element.VariableElement;
11.38 +import javax.lang.model.type.ArrayType;
11.39 import javax.lang.model.type.MirroredTypeException;
11.40 import javax.lang.model.type.TypeKind;
11.41 import javax.lang.model.type.TypeMirror;
11.42 +import javax.lang.model.util.Elements;
11.43 +import javax.lang.model.util.Types;
11.44 import javax.tools.Diagnostic;
11.45 import javax.tools.FileObject;
11.46 import javax.tools.StandardLocation;
11.47 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
11.48 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
11.49 import org.apidesign.bck2brwsr.htmlpage.api.On;
11.50 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
11.51 +import org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange;
11.52 +import org.apidesign.bck2brwsr.htmlpage.api.OnReceive;
11.53 import org.apidesign.bck2brwsr.htmlpage.api.Page;
11.54 import org.apidesign.bck2brwsr.htmlpage.api.Property;
11.55 import org.openide.util.lookup.ServiceProvider;
11.56 @@ -63,89 +76,70 @@
11.57 */
11.58 @ServiceProvider(service=Processor.class)
11.59 @SupportedAnnotationTypes({
11.60 + "org.apidesign.bck2brwsr.htmlpage.api.Model",
11.61 "org.apidesign.bck2brwsr.htmlpage.api.Page",
11.62 + "org.apidesign.bck2brwsr.htmlpage.api.OnFunction",
11.63 + "org.apidesign.bck2brwsr.htmlpage.api.OnReceive",
11.64 + "org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange",
11.65 + "org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty",
11.66 "org.apidesign.bck2brwsr.htmlpage.api.On"
11.67 })
11.68 public final class PageProcessor extends AbstractProcessor {
11.69 + private final Map<Element,String> models = new WeakHashMap<>();
11.70 + private final Map<Element,Prprt[]> verify = new WeakHashMap<>();
11.71 @Override
11.72 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
11.73 - for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) {
11.74 - Page p = e.getAnnotation(Page.class);
11.75 - if (p == null) {
11.76 - continue;
11.77 - }
11.78 - PackageElement pe = (PackageElement)e.getEnclosingElement();
11.79 - String pkg = pe.getQualifiedName().toString();
11.80 -
11.81 - ProcessPage pp;
11.82 - try {
11.83 - InputStream is = openStream(pkg, p.xhtml());
11.84 - pp = ProcessPage.readPage(is);
11.85 - is.close();
11.86 - } catch (IOException iOException) {
11.87 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't read " + p.xhtml(), e);
11.88 - return false;
11.89 - }
11.90 - Writer w;
11.91 - String className = p.className();
11.92 - if (className.isEmpty()) {
11.93 - int indx = p.xhtml().indexOf('.');
11.94 - className = p.xhtml().substring(0, indx);
11.95 - }
11.96 - try {
11.97 - FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
11.98 - w = new OutputStreamWriter(java.openOutputStream());
11.99 - try {
11.100 - w.append("package " + pkg + ";\n");
11.101 - w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
11.102 - w.append("final class ").append(className).append(" {\n");
11.103 - w.append(" private boolean locked;\n");
11.104 - if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
11.105 - return false;
11.106 - }
11.107 - for (String id : pp.ids()) {
11.108 - String tag = pp.tagNameForId(id);
11.109 - String type = type(tag);
11.110 - w.append(" ").append("public final ").
11.111 - append(type).append(' ').append(cnstnt(id)).append(" = new ").
11.112 - append(type).append("(\"").append(id).append("\");\n");
11.113 - }
11.114 - List<String> propsGetSet = new ArrayList<String>();
11.115 - Map<String,Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
11.116 - generateComputedProperties(w, e.getEnclosedElements(), propsGetSet, propsDeps);
11.117 - generateProperties(w, p.properties(), propsGetSet, propsDeps);
11.118 - w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
11.119 - if (!propsGetSet.isEmpty()) {
11.120 - w.write("public " + className + " applyBindings() {\n");
11.121 - w.write(" ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
11.122 - w.write(className + ".class, this, ");
11.123 - w.write("new String[] {\n");
11.124 - String sep = "";
11.125 - for (String n : propsGetSet) {
11.126 - w.write(sep);
11.127 - if (n == null) {
11.128 - w.write(" null");
11.129 - } else {
11.130 - w.write(" \"" + n + "\"");
11.131 - }
11.132 - sep = ",\n";
11.133 - }
11.134 - w.write("\n });\n return this;\n}\n");
11.135 -
11.136 - w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
11.137 - w.write(" org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
11.138 - w.write("}\n");
11.139 - }
11.140 - w.append("}\n");
11.141 - } finally {
11.142 - w.close();
11.143 - }
11.144 - } catch (IOException ex) {
11.145 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e);
11.146 - return false;
11.147 + boolean ok = true;
11.148 + for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
11.149 + if (!processModel(e)) {
11.150 + ok = false;
11.151 }
11.152 }
11.153 - return true;
11.154 + for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) {
11.155 + if (!processPage(e)) {
11.156 + ok = false;
11.157 + }
11.158 + }
11.159 + if (roundEnv.processingOver()) {
11.160 + models.clear();
11.161 + for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
11.162 + TypeElement te = (TypeElement)entry.getKey();
11.163 + String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
11.164 + Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
11.165 + if (finalElem == null) {
11.166 + continue;
11.167 + }
11.168 + Prprt[] props;
11.169 + Model m = finalElem.getAnnotation(Model.class);
11.170 + if (m != null) {
11.171 + props = Prprt.wrap(processingEnv, finalElem, m.properties());
11.172 + } else {
11.173 + Page p = finalElem.getAnnotation(Page.class);
11.174 + props = Prprt.wrap(processingEnv, finalElem, p.properties());
11.175 + }
11.176 + for (Prprt p : props) {
11.177 + boolean[] isModel = { false };
11.178 + boolean[] isEnum = { false };
11.179 + boolean[] isPrimitive = { false };
11.180 + String t = checkType(p, isModel, isEnum, isPrimitive);
11.181 + if (isEnum[0]) {
11.182 + continue;
11.183 + }
11.184 + if (isPrimitive[0]) {
11.185 + continue;
11.186 + }
11.187 + if (isModel[0]) {
11.188 + continue;
11.189 + }
11.190 + if ("java.lang.String".equals(t)) {
11.191 + continue;
11.192 + }
11.193 + error("The type " + t + " should be defined by @Model annotation", entry.getKey());
11.194 + }
11.195 + }
11.196 + verify.clear();
11.197 + }
11.198 + return ok;
11.199 }
11.200
11.201 private InputStream openStream(String pkg, String name) throws IOException {
11.202 @@ -158,6 +152,236 @@
11.203 }
11.204 }
11.205
11.206 + private void error(String msg, Element e) {
11.207 + processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
11.208 + }
11.209 +
11.210 + private boolean processModel(Element e) {
11.211 + boolean ok = true;
11.212 + Model m = e.getAnnotation(Model.class);
11.213 + if (m == null) {
11.214 + return true;
11.215 + }
11.216 + String pkg = findPkgName(e);
11.217 + Writer w;
11.218 + String className = m.className();
11.219 + models.put(e, className);
11.220 + try {
11.221 + StringWriter body = new StringWriter();
11.222 + List<String> propsGetSet = new ArrayList<>();
11.223 + List<String> functions = new ArrayList<>();
11.224 + Map<String, Collection<String>> propsDeps = new HashMap<>();
11.225 + Map<String, Collection<String>> functionDeps = new HashMap<>();
11.226 + Prprt[] props = createProps(e, m.properties());
11.227 +
11.228 + if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
11.229 + ok = false;
11.230 + }
11.231 + if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
11.232 + ok = false;
11.233 + }
11.234 + if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
11.235 + ok = false;
11.236 + }
11.237 + if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
11.238 + ok = false;
11.239 + }
11.240 + FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
11.241 + w = new OutputStreamWriter(java.openOutputStream());
11.242 + try {
11.243 + w.append("package " + pkg + ";\n");
11.244 + w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
11.245 + w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n");
11.246 + w.append("import org.apidesign.bck2brwsr.core.JavaScriptOnly;\n");
11.247 + w.append("final class ").append(className).append(" implements Cloneable {\n");
11.248 + w.append(" private boolean locked;\n");
11.249 + w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
11.250 + w.append(body.toString());
11.251 + w.append(" private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
11.252 + w.append(" public ").append(className).append("() {\n");
11.253 + w.append(" intKnckt();\n");
11.254 + w.append(" };\n");
11.255 + w.append(" private void intKnckt() {\n");
11.256 + w.append(" ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(this, ");
11.257 + writeStringArray(propsGetSet, w);
11.258 + w.append(", ");
11.259 + writeStringArray(functions, w);
11.260 + w.append(" );\n");
11.261 + w.append(" };\n");
11.262 + w.append(" ").append(className).append("(Object json) {\n");
11.263 + int values = 0;
11.264 + for (int i = 0; i < propsGetSet.size(); i += 4) {
11.265 + Prprt p = findPrprt(props, propsGetSet.get(i));
11.266 + if (p == null) {
11.267 + continue;
11.268 + }
11.269 + values++;
11.270 + }
11.271 + w.append(" Object[] ret = new Object[" + values + "];\n");
11.272 + w.append(" org.apidesign.bck2brwsr.htmlpage.ConvertTypes.extractJSON(json, new String[] {\n");
11.273 + for (int i = 0; i < propsGetSet.size(); i += 4) {
11.274 + Prprt p = findPrprt(props, propsGetSet.get(i));
11.275 + if (p == null) {
11.276 + continue;
11.277 + }
11.278 + w.append(" \"").append(propsGetSet.get(i)).append("\",\n");
11.279 + }
11.280 + w.append(" }, ret);\n");
11.281 + for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 4) {
11.282 + final String pn = propsGetSet.get(i);
11.283 + Prprt p = findPrprt(props, pn);
11.284 + if (p == null) {
11.285 + continue;
11.286 + }
11.287 + boolean[] isModel = { false };
11.288 + boolean[] isEnum = { false };
11.289 + boolean isPrimitive[] = { false };
11.290 + String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
11.291 + if (p.array()) {
11.292 + w.append("if (ret[" + cnt + "] instanceof Object[]) {\n");
11.293 + w.append(" for (Object e : ((Object[])ret[" + cnt + "])) {\n");
11.294 + if (isModel[0]) {
11.295 + w.append(" this.prop_").append(pn).append(".add(new ");
11.296 + w.append(type).append("(e));\n");
11.297 + } else if (isEnum[0]) {
11.298 + w.append(" this.prop_").append(pn);
11.299 + w.append(".add(");
11.300 + w.append(type).append(".valueOf((String)e));\n");
11.301 + } else {
11.302 + if (isPrimitive(type)) {
11.303 + w.append(" this.prop_").append(pn).append(".add(((Number)e).");
11.304 + w.append(type).append("Value());\n");
11.305 + } else {
11.306 + w.append(" this.prop_").append(pn).append(".add((");
11.307 + w.append(type).append(")e);\n");
11.308 + }
11.309 + }
11.310 + w.append(" }\n");
11.311 + w.append("}\n");
11.312 + } else {
11.313 + if (isEnum[0]) {
11.314 + w.append(" this.prop_").append(pn);
11.315 + w.append(" = ");
11.316 + w.append(type).append(".valueOf((String)ret[" + cnt + "]);\n");
11.317 + } else if (isPrimitive(type)) {
11.318 + w.append(" this.prop_").append(pn);
11.319 + w.append(" = ((Number)").append("ret[" + cnt + "]).");
11.320 + w.append(type).append("Value();\n");
11.321 + } else {
11.322 + w.append(" this.prop_").append(pn);
11.323 + w.append(" = (").append(type).append(')');
11.324 + w.append("ret[" + cnt + "];\n");
11.325 + }
11.326 + }
11.327 + cnt++;
11.328 + }
11.329 + w.append(" intKnckt();\n");
11.330 + w.append(" };\n");
11.331 + writeToString(props, w);
11.332 + writeClone(className, props, w);
11.333 + w.append("}\n");
11.334 + } finally {
11.335 + w.close();
11.336 + }
11.337 + } catch (IOException ex) {
11.338 + error("Can't create " + className + ".java", e);
11.339 + return false;
11.340 + }
11.341 + return ok;
11.342 + }
11.343 +
11.344 + private boolean processPage(Element e) {
11.345 + boolean ok = true;
11.346 + Page p = e.getAnnotation(Page.class);
11.347 + if (p == null) {
11.348 + return true;
11.349 + }
11.350 + String pkg = findPkgName(e);
11.351 +
11.352 + ProcessPage pp;
11.353 + try (InputStream is = openStream(pkg, p.xhtml())) {
11.354 + pp = ProcessPage.readPage(is);
11.355 + is.close();
11.356 + } catch (IOException iOException) {
11.357 + error("Can't read " + p.xhtml() + " as " + iOException.getMessage(), e);
11.358 + ok = false;
11.359 + pp = null;
11.360 + }
11.361 + Writer w;
11.362 + String className = p.className();
11.363 + if (className.isEmpty()) {
11.364 + int indx = p.xhtml().indexOf('.');
11.365 + className = p.xhtml().substring(0, indx);
11.366 + }
11.367 + try {
11.368 + StringWriter body = new StringWriter();
11.369 + List<String> propsGetSet = new ArrayList<>();
11.370 + List<String> functions = new ArrayList<>();
11.371 + Map<String, Collection<String>> propsDeps = new HashMap<>();
11.372 + Map<String, Collection<String>> functionDeps = new HashMap<>();
11.373 +
11.374 + Prprt[] props = createProps(e, p.properties());
11.375 + if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
11.376 + ok = false;
11.377 + }
11.378 + if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
11.379 + ok = false;
11.380 + }
11.381 + if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
11.382 + ok = false;
11.383 + }
11.384 + if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
11.385 + ok = false;
11.386 + }
11.387 + if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
11.388 + ok = false;
11.389 + }
11.390 +
11.391 + FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
11.392 + w = new OutputStreamWriter(java.openOutputStream());
11.393 + try {
11.394 + w.append("package " + pkg + ";\n");
11.395 + w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
11.396 + w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n");
11.397 + w.append("final class ").append(className).append(" {\n");
11.398 + w.append(" private boolean locked;\n");
11.399 + if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
11.400 + ok = false;
11.401 + } else {
11.402 + if (pp != null) for (String id : pp.ids()) {
11.403 + String tag = pp.tagNameForId(id);
11.404 + String type = type(tag);
11.405 + w.append(" ").append("public final ").
11.406 + append(type).append(' ').append(cnstnt(id)).append(" = new ").
11.407 + append(type).append("(\"").append(id).append("\");\n");
11.408 + }
11.409 + }
11.410 + w.append(" private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
11.411 + w.append(body.toString());
11.412 + if (!propsGetSet.isEmpty()) {
11.413 + w.write("public " + className + " applyBindings() {\n");
11.414 + w.write(" ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
11.415 + w.write(className + ".class, this, ");
11.416 + writeStringArray(propsGetSet, w);
11.417 + w.append(", ");
11.418 + writeStringArray(functions, w);
11.419 + w.write(");\n return this;\n}\n");
11.420 +
11.421 + w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
11.422 + w.write(" org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
11.423 + w.write("}\n");
11.424 + }
11.425 + w.append("}\n");
11.426 + } finally {
11.427 + w.close();
11.428 + }
11.429 + } catch (IOException ex) {
11.430 + error("Can't create " + className + ".java", e);
11.431 + return false;
11.432 + }
11.433 + return ok;
11.434 + }
11.435 +
11.436 private static String type(String tag) {
11.437 if (tag.equals("title")) {
11.438 return "Title";
11.439 @@ -178,12 +402,13 @@
11.440 }
11.441
11.442 private static String cnstnt(String id) {
11.443 - return id.toUpperCase(Locale.ENGLISH).replace('.', '_').replace('-', '_');
11.444 + return id.replace('.', '_').replace('-', '_');
11.445 }
11.446
11.447 private boolean initializeOnClick(
11.448 String className, TypeElement type, Writer w, ProcessPage pp
11.449 ) throws IOException {
11.450 + boolean ok = true;
11.451 TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
11.452 { //for (Element clazz : pe.getEnclosedElements()) {
11.453 // if (clazz.getKind() != ElementKind.CLASS) {
11.454 @@ -196,58 +421,27 @@
11.455 On oc = method.getAnnotation(On.class);
11.456 if (oc != null) {
11.457 for (String id : oc.id()) {
11.458 + if (pp == null) {
11.459 + error("id = " + id + " not found in HTML page.", method);
11.460 + ok = false;
11.461 + continue;
11.462 + }
11.463 if (pp.tagNameForId(id) == null) {
11.464 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
11.465 - return false;
11.466 + error("id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
11.467 + ok = false;
11.468 + continue;
11.469 }
11.470 ExecutableElement ee = (ExecutableElement)method;
11.471 - StringBuilder params = new StringBuilder();
11.472 - {
11.473 - boolean first = true;
11.474 - for (VariableElement ve : ee.getParameters()) {
11.475 - if (!first) {
11.476 - params.append(", ");
11.477 - }
11.478 - first = false;
11.479 - if (ve.asType() == stringType) {
11.480 - if (ve.getSimpleName().contentEquals("id")) {
11.481 - params.append('"').append(id).append('"');
11.482 - continue;
11.483 - }
11.484 - params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString(ev, \"");
11.485 - params.append(ve.getSimpleName().toString());
11.486 - params.append("\")");
11.487 - continue;
11.488 - }
11.489 - if (processingEnv.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE) == ve.asType()) {
11.490 - params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble(ev, \"");
11.491 - params.append(ve.getSimpleName().toString());
11.492 - params.append("\")");
11.493 - continue;
11.494 - }
11.495 - String rn = ve.asType().toString();
11.496 - int last = rn.lastIndexOf('.');
11.497 - if (last >= 0) {
11.498 - rn = rn.substring(last + 1);
11.499 - }
11.500 - if (rn.equals(className)) {
11.501 - params.append(className).append(".this");
11.502 - continue;
11.503 - }
11.504 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
11.505 - "@On method can only accept String named 'id' or " + className + " arguments",
11.506 - ee
11.507 - );
11.508 - return false;
11.509 - }
11.510 - }
11.511 + CharSequence params = wrapParams(ee, id, className, "ev", null);
11.512 if (!ee.getModifiers().contains(Modifier.STATIC)) {
11.513 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method has to be static", ee);
11.514 - return false;
11.515 + error("@On method has to be static", ee);
11.516 + ok = false;
11.517 + continue;
11.518 }
11.519 if (ee.getModifiers().contains(Modifier.PRIVATE)) {
11.520 - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method can't be private", ee);
11.521 - return false;
11.522 + error("@On method can't be private", ee);
11.523 + ok = false;
11.524 + continue;
11.525 }
11.526 w.append(" OnEvent." + oc.event()).append(".of(").append(cnstnt(id)).
11.527 append(").perform(new OnDispatch(" + dispatchCnt + "));\n");
11.528 @@ -278,7 +472,7 @@
11.529
11.530
11.531 }
11.532 - return true;
11.533 + return ok;
11.534 }
11.535
11.536 @Override
11.537 @@ -292,8 +486,7 @@
11.538
11.539 Element cls = findClass(element);
11.540 Page p = cls.getAnnotation(Page.class);
11.541 - PackageElement pe = (PackageElement) cls.getEnclosingElement();
11.542 - String pkg = pe.getQualifiedName().toString();
11.543 + String pkg = findPkgName(cls);
11.544 ProcessPage pp;
11.545 try {
11.546 InputStream is = openStream(pkg, p.xhtml());
11.547 @@ -303,7 +496,7 @@
11.548 return Collections.emptyList();
11.549 }
11.550
11.551 - List<Completion> cc = new ArrayList<Completion>();
11.552 + List<Completion> cc = new ArrayList<>();
11.553 userText = userText.substring(1);
11.554 for (String id : pp.ids()) {
11.555 if (id.startsWith(userText)) {
11.556 @@ -324,44 +517,89 @@
11.557 return e.getEnclosingElement();
11.558 }
11.559
11.560 - private static void generateProperties(
11.561 - Writer w, Property[] properties, Collection<String> props,
11.562 - Map<String,Collection<String>> deps
11.563 + private boolean generateProperties(
11.564 + Element where,
11.565 + Writer w, Prprt[] properties,
11.566 + Collection<String> props,
11.567 + Map<String,Collection<String>> deps,
11.568 + Map<String,Collection<String>> functionDeps
11.569 ) throws IOException {
11.570 - for (Property p : properties) {
11.571 - final String tn = typeName(p);
11.572 - String[] gs = toGetSet(p.name(), tn);
11.573 + boolean ok = true;
11.574 + for (Prprt p : properties) {
11.575 + final String tn;
11.576 + tn = typeName(where, p);
11.577 + String[] gs = toGetSet(p.name(), tn, p.array());
11.578
11.579 - w.write("private " + tn + " prop_" + p.name() + ";\n");
11.580 - w.write("public " + tn + " " + gs[0] + "() {\n");
11.581 - w.write(" if (locked) throw new IllegalStateException();\n");
11.582 - w.write(" return prop_" + p.name() + ";\n");
11.583 - w.write("}\n");
11.584 - w.write("public void " + gs[1] + "(" + tn + " v) {\n");
11.585 - w.write(" if (locked) throw new IllegalStateException();\n");
11.586 - w.write(" prop_" + p.name() + " = v;\n");
11.587 - w.write(" if (ko != null) {\n");
11.588 - w.write(" ko.valueHasMutated(\"" + p.name() + "\");\n");
11.589 - final Collection<String> dependants = deps.get(p.name());
11.590 - if (dependants != null) {
11.591 - for (String depProp : dependants) {
11.592 - w.write(" ko.valueHasMutated(\"" + depProp + "\");\n");
11.593 + if (p.array()) {
11.594 + w.write("private KOList<" + tn + "> prop_" + p.name() + " = new KOList<" + tn + ">(\""
11.595 + + p.name() + "\"");
11.596 + Collection<String> dependants = deps.get(p.name());
11.597 + if (dependants != null) {
11.598 + for (String depProp : dependants) {
11.599 + w.write(", ");
11.600 + w.write('\"');
11.601 + w.write(depProp);
11.602 + w.write('\"');
11.603 + }
11.604 }
11.605 + w.write(")");
11.606 +
11.607 + dependants = functionDeps.get(p.name());
11.608 + if (dependants != null) {
11.609 + w.write(".onChange(new Runnable() { public void run() {\n");
11.610 + for (String call : dependants) {
11.611 + w.append(call);
11.612 + }
11.613 + w.write("}})");
11.614 + }
11.615 + w.write(";\n");
11.616 +
11.617 + w.write("public java.util.List<" + tn + "> " + gs[0] + "() {\n");
11.618 + w.write(" if (locked) throw new IllegalStateException();\n");
11.619 + w.write(" prop_" + p.name() + ".assign(ko);\n");
11.620 + w.write(" return prop_" + p.name() + ";\n");
11.621 + w.write("}\n");
11.622 + } else {
11.623 + w.write("private " + tn + " prop_" + p.name() + ";\n");
11.624 + w.write("public " + tn + " " + gs[0] + "() {\n");
11.625 + w.write(" if (locked) throw new IllegalStateException();\n");
11.626 + w.write(" return prop_" + p.name() + ";\n");
11.627 + w.write("}\n");
11.628 + w.write("public void " + gs[1] + "(" + tn + " v) {\n");
11.629 + w.write(" if (locked) throw new IllegalStateException();\n");
11.630 + w.write(" prop_" + p.name() + " = v;\n");
11.631 + w.write(" if (ko != null) {\n");
11.632 + w.write(" ko.valueHasMutated(\"" + p.name() + "\");\n");
11.633 + Collection<String> dependants = deps.get(p.name());
11.634 + if (dependants != null) {
11.635 + for (String depProp : dependants) {
11.636 + w.write(" ko.valueHasMutated(\"" + depProp + "\");\n");
11.637 + }
11.638 + }
11.639 + w.write(" }\n");
11.640 + dependants = functionDeps.get(p.name());
11.641 + if (dependants != null) {
11.642 + for (String call : dependants) {
11.643 + w.append(call);
11.644 + }
11.645 + }
11.646 + w.write("}\n");
11.647 }
11.648 - w.write(" }\n");
11.649 - w.write("}\n");
11.650
11.651 props.add(p.name());
11.652 props.add(gs[2]);
11.653 props.add(gs[3]);
11.654 props.add(gs[0]);
11.655 }
11.656 + return ok;
11.657 }
11.658
11.659 private boolean generateComputedProperties(
11.660 - Writer w, Collection<? extends Element> arr, Collection<String> props,
11.661 + Writer w, Prprt[] fixedProps,
11.662 + Collection<? extends Element> arr, Collection<String> props,
11.663 Map<String,Collection<String>> deps
11.664 ) throws IOException {
11.665 + boolean ok = true;
11.666 for (Element e : arr) {
11.667 if (e.getKind() != ElementKind.METHOD) {
11.668 continue;
11.669 @@ -370,30 +608,43 @@
11.670 continue;
11.671 }
11.672 ExecutableElement ee = (ExecutableElement)e;
11.673 - final String tn = ee.getReturnType().toString();
11.674 + final TypeMirror rt = ee.getReturnType();
11.675 + final Types tu = processingEnv.getTypeUtils();
11.676 + TypeMirror ert = tu.erasure(rt);
11.677 + String tn = fqn(ert, ee);
11.678 + boolean array = false;
11.679 + if (tn.equals("java.util.List")) {
11.680 + array = true;
11.681 + }
11.682 +
11.683 final String sn = ee.getSimpleName().toString();
11.684 - String[] gs = toGetSet(sn, tn);
11.685 + String[] gs = toGetSet(sn, tn, array);
11.686
11.687 w.write("public " + tn + " " + gs[0] + "() {\n");
11.688 w.write(" if (locked) throw new IllegalStateException();\n");
11.689 int arg = 0;
11.690 for (VariableElement pe : ee.getParameters()) {
11.691 final String dn = pe.getSimpleName().toString();
11.692 - final String dt = pe.asType().toString();
11.693 - String[] call = toGetSet(dn, dt);
11.694 +
11.695 + if (!verifyPropName(pe, dn, fixedProps)) {
11.696 + ok = false;
11.697 + }
11.698 +
11.699 + final String dt = fqn(pe.asType(), ee);
11.700 + String[] call = toGetSet(dn, dt, false);
11.701 w.write(" " + dt + " arg" + (++arg) + " = ");
11.702 w.write(call[0] + "();\n");
11.703
11.704 Collection<String> depends = deps.get(dn);
11.705 if (depends == null) {
11.706 - depends = new LinkedHashSet<String>();
11.707 + depends = new LinkedHashSet<>();
11.708 deps.put(dn, depends);
11.709 }
11.710 depends.add(sn);
11.711 }
11.712 w.write(" try {\n");
11.713 w.write(" locked = true;\n");
11.714 - w.write(" return " + e.getEnclosingElement().getSimpleName() + '.' + e.getSimpleName() + "(");
11.715 + w.write(" return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
11.716 String sep = "";
11.717 for (int i = 1; i <= arg; i++) {
11.718 w.write(sep);
11.719 @@ -405,17 +656,17 @@
11.720 w.write(" locked = false;\n");
11.721 w.write(" }\n");
11.722 w.write("}\n");
11.723 -
11.724 +
11.725 props.add(e.getSimpleName().toString());
11.726 props.add(gs[2]);
11.727 props.add(null);
11.728 props.add(gs[0]);
11.729 }
11.730
11.731 - return true;
11.732 + return ok;
11.733 }
11.734
11.735 - private static String[] toGetSet(String name, String type) {
11.736 + private static String[] toGetSet(String name, String type, boolean array) {
11.737 String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
11.738 String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
11.739 if ("int".equals(type)) {
11.740 @@ -430,6 +681,14 @@
11.741 bck2brwsrType = "Z";
11.742 }
11.743 final String nu = n.replace('.', '_');
11.744 + if (array) {
11.745 + return new String[] {
11.746 + "get" + n,
11.747 + null,
11.748 + "get" + nu + "__Ljava_util_List_2",
11.749 + null
11.750 + };
11.751 + }
11.752 return new String[]{
11.753 pref + n,
11.754 "set" + n,
11.755 @@ -438,11 +697,701 @@
11.756 };
11.757 }
11.758
11.759 - private static String typeName(Property p) {
11.760 - try {
11.761 - return p.type().getName();
11.762 - } catch (MirroredTypeException ex) {
11.763 - return ex.getTypeMirror().toString();
11.764 + private String typeName(Element where, Prprt p) {
11.765 + String ret;
11.766 + boolean[] isModel = { false };
11.767 + boolean[] isEnum = { false };
11.768 + boolean isPrimitive[] = { false };
11.769 + ret = checkType(p, isModel, isEnum, isPrimitive);
11.770 + if (p.array()) {
11.771 + String bt = findBoxedType(ret);
11.772 + if (bt != null) {
11.773 + return bt;
11.774 + }
11.775 + }
11.776 + return ret;
11.777 + }
11.778 +
11.779 + private static String findBoxedType(String ret) {
11.780 + if (ret.equals("boolean")) {
11.781 + return Boolean.class.getName();
11.782 + }
11.783 + if (ret.equals("byte")) {
11.784 + return Byte.class.getName();
11.785 + }
11.786 + if (ret.equals("short")) {
11.787 + return Short.class.getName();
11.788 + }
11.789 + if (ret.equals("char")) {
11.790 + return Character.class.getName();
11.791 + }
11.792 + if (ret.equals("int")) {
11.793 + return Integer.class.getName();
11.794 + }
11.795 + if (ret.equals("long")) {
11.796 + return Long.class.getName();
11.797 + }
11.798 + if (ret.equals("float")) {
11.799 + return Float.class.getName();
11.800 + }
11.801 + if (ret.equals("double")) {
11.802 + return Double.class.getName();
11.803 + }
11.804 + return null;
11.805 + }
11.806 +
11.807 + private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
11.808 + StringBuilder sb = new StringBuilder();
11.809 + String sep = "";
11.810 + for (Prprt Prprt : existingProps) {
11.811 + if (Prprt.name().equals(propName)) {
11.812 + return true;
11.813 + }
11.814 + sb.append(sep);
11.815 + sb.append('"');
11.816 + sb.append(Prprt.name());
11.817 + sb.append('"');
11.818 + sep = ", ";
11.819 + }
11.820 + error(
11.821 + propName + " is not one of known properties: " + sb
11.822 + , e
11.823 + );
11.824 + return false;
11.825 + }
11.826 +
11.827 + private static String findPkgName(Element e) {
11.828 + for (;;) {
11.829 + if (e.getKind() == ElementKind.PACKAGE) {
11.830 + return ((PackageElement)e).getQualifiedName().toString();
11.831 + }
11.832 + e = e.getEnclosingElement();
11.833 }
11.834 }
11.835 +
11.836 + private boolean generateFunctions(
11.837 + Element clazz, StringWriter body, String className,
11.838 + List<? extends Element> enclosedElements, List<String> functions
11.839 + ) {
11.840 + for (Element m : enclosedElements) {
11.841 + if (m.getKind() != ElementKind.METHOD) {
11.842 + continue;
11.843 + }
11.844 + ExecutableElement e = (ExecutableElement)m;
11.845 + OnFunction onF = e.getAnnotation(OnFunction.class);
11.846 + if (onF == null) {
11.847 + continue;
11.848 + }
11.849 + if (!e.getModifiers().contains(Modifier.STATIC)) {
11.850 + error("@OnFunction method needs to be static", e);
11.851 + return false;
11.852 + }
11.853 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
11.854 + error("@OnFunction method cannot be private", e);
11.855 + return false;
11.856 + }
11.857 + if (e.getReturnType().getKind() != TypeKind.VOID) {
11.858 + error("@OnFunction method should return void", e);
11.859 + return false;
11.860 + }
11.861 + String n = e.getSimpleName().toString();
11.862 + body.append("private void ").append(n).append("(Object data, Object ev) {\n");
11.863 + body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
11.864 + body.append(wrapParams(e, null, className, "ev", "data"));
11.865 + body.append(");\n");
11.866 + body.append("}\n");
11.867 +
11.868 + functions.add(n);
11.869 + functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
11.870 + }
11.871 + return true;
11.872 + }
11.873 +
11.874 + private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
11.875 + Prprt[] properties, String className,
11.876 + Map<String, Collection<String>> functionDeps
11.877 + ) {
11.878 + for (Element m : clazz.getEnclosedElements()) {
11.879 + if (m.getKind() != ElementKind.METHOD) {
11.880 + continue;
11.881 + }
11.882 + ExecutableElement e = (ExecutableElement) m;
11.883 + OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
11.884 + if (onPC == null) {
11.885 + continue;
11.886 + }
11.887 + for (String pn : onPC.value()) {
11.888 + if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
11.889 + error("No Prprt named '" + pn + "' in the model", clazz);
11.890 + return false;
11.891 + }
11.892 + }
11.893 + if (!e.getModifiers().contains(Modifier.STATIC)) {
11.894 + error("@OnPrprtChange method needs to be static", e);
11.895 + return false;
11.896 + }
11.897 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
11.898 + error("@OnPrprtChange method cannot be private", e);
11.899 + return false;
11.900 + }
11.901 + if (e.getReturnType().getKind() != TypeKind.VOID) {
11.902 + error("@OnPrprtChange method should return void", e);
11.903 + return false;
11.904 + }
11.905 + String n = e.getSimpleName().toString();
11.906 +
11.907 +
11.908 + for (String pn : onPC.value()) {
11.909 + StringBuilder call = new StringBuilder();
11.910 + call.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
11.911 + call.append(wrapPropName(e, className, "name", pn));
11.912 + call.append(");\n");
11.913 +
11.914 + Collection<String> change = functionDeps.get(pn);
11.915 + if (change == null) {
11.916 + change = new ArrayList<>();
11.917 + functionDeps.put(pn, change);
11.918 + }
11.919 + change.add(call.toString());
11.920 + for (String dpn : findDerivedFrom(propDeps, pn)) {
11.921 + change = functionDeps.get(dpn);
11.922 + if (change == null) {
11.923 + change = new ArrayList<>();
11.924 + functionDeps.put(dpn, change);
11.925 + }
11.926 + change.add(call.toString());
11.927 + }
11.928 + }
11.929 + }
11.930 + return true;
11.931 + }
11.932 +
11.933 + private boolean generateReceive(
11.934 + Element clazz, StringWriter body, String className,
11.935 + List<? extends Element> enclosedElements, List<String> functions
11.936 + ) {
11.937 + for (Element m : enclosedElements) {
11.938 + if (m.getKind() != ElementKind.METHOD) {
11.939 + continue;
11.940 + }
11.941 + ExecutableElement e = (ExecutableElement)m;
11.942 + OnReceive onR = e.getAnnotation(OnReceive.class);
11.943 + if (onR == null) {
11.944 + continue;
11.945 + }
11.946 + if (!e.getModifiers().contains(Modifier.STATIC)) {
11.947 + error("@OnReceive method needs to be static", e);
11.948 + return false;
11.949 + }
11.950 + if (e.getModifiers().contains(Modifier.PRIVATE)) {
11.951 + error("@OnReceive method cannot be private", e);
11.952 + return false;
11.953 + }
11.954 + if (e.getReturnType().getKind() != TypeKind.VOID) {
11.955 + error("@OnReceive method should return void", e);
11.956 + return false;
11.957 + }
11.958 + String modelClass = null;
11.959 + boolean expectsList = false;
11.960 + List<String> args = new ArrayList<>();
11.961 + {
11.962 + for (VariableElement ve : e.getParameters()) {
11.963 + TypeMirror modelType = null;
11.964 + if (ve.asType().toString().equals(className)) {
11.965 + args.add(className + ".this");
11.966 + } else if (isModel(ve.asType())) {
11.967 + modelType = ve.asType();
11.968 + } else if (ve.asType().getKind() == TypeKind.ARRAY) {
11.969 + modelType = ((ArrayType)ve.asType()).getComponentType();
11.970 + expectsList = true;
11.971 + }
11.972 + if (modelType != null) {
11.973 + if (modelClass != null) {
11.974 + error("There can be only one model class among arguments", e);
11.975 + } else {
11.976 + modelClass = modelType.toString();
11.977 + if (expectsList) {
11.978 + args.add("arr");
11.979 + } else {
11.980 + args.add("arr[0]");
11.981 + }
11.982 + }
11.983 + }
11.984 + }
11.985 + }
11.986 + if (modelClass == null) {
11.987 + error("The method needs to have one @Model class as parameter", e);
11.988 + }
11.989 + String n = e.getSimpleName().toString();
11.990 + body.append("public void ").append(n).append("(");
11.991 + StringBuilder assembleURL = new StringBuilder();
11.992 + String jsonpVarName = null;
11.993 + {
11.994 + String sep = "";
11.995 + boolean skipJSONP = onR.jsonp().isEmpty();
11.996 + for (String p : findParamNames(e, onR.url(), assembleURL)) {
11.997 + if (!skipJSONP && p.equals(onR.jsonp())) {
11.998 + skipJSONP = true;
11.999 + jsonpVarName = p;
11.1000 + continue;
11.1001 + }
11.1002 + body.append(sep);
11.1003 + body.append("String ").append(p);
11.1004 + sep = ", ";
11.1005 + }
11.1006 + if (!skipJSONP) {
11.1007 + error(
11.1008 + "Name of jsonp attribute ('" + onR.jsonp() +
11.1009 + "') is not used in url attribute '" + onR.url() + "'", e
11.1010 + );
11.1011 + }
11.1012 + }
11.1013 + body.append(") {\n");
11.1014 + body.append(" final Object[] result = { null };\n");
11.1015 + body.append(
11.1016 + " class ProcessResult implements Runnable {\n" +
11.1017 + " @Override\n" +
11.1018 + " public void run() {\n" +
11.1019 + " Object value = result[0];\n");
11.1020 + body.append(
11.1021 + " " + modelClass + "[] arr;\n");
11.1022 + body.append(
11.1023 + " if (value instanceof Object[]) {\n" +
11.1024 + " Object[] data = ((Object[])value);\n" +
11.1025 + " arr = new " + modelClass + "[data.length];\n" +
11.1026 + " for (int i = 0; i < data.length; i++) {\n" +
11.1027 + " arr[i] = new " + modelClass + "(data[i]);\n" +
11.1028 + " }\n" +
11.1029 + " } else {\n" +
11.1030 + " arr = new " + modelClass + "[1];\n" +
11.1031 + " arr[0] = new " + modelClass + "(value);\n" +
11.1032 + " }\n"
11.1033 + );
11.1034 + {
11.1035 + body.append(clazz.getSimpleName()).append(".").append(n).append("(");
11.1036 + String sep = "";
11.1037 + for (String arg : args) {
11.1038 + body.append(sep);
11.1039 + body.append(arg);
11.1040 + sep = ", ";
11.1041 + }
11.1042 + body.append(");\n");
11.1043 + }
11.1044 + body.append(
11.1045 + " }\n" +
11.1046 + " }\n"
11.1047 + );
11.1048 + body.append(" ProcessResult pr = new ProcessResult();\n");
11.1049 + if (jsonpVarName != null) {
11.1050 + body.append(" String ").append(jsonpVarName).
11.1051 + append(" = org.apidesign.bck2brwsr.htmlpage.ConvertTypes.createJSONP(result, pr);\n");
11.1052 + }
11.1053 + body.append(" org.apidesign.bck2brwsr.htmlpage.ConvertTypes.loadJSON(\n ");
11.1054 + body.append(assembleURL);
11.1055 + body.append(", result, pr, ").append(jsonpVarName).append("\n );\n");
11.1056 +// body.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
11.1057 +// body.append(wrapParams(e, null, className, "ev", "data"));
11.1058 +// body.append(");\n");
11.1059 + body.append("}\n");
11.1060 + }
11.1061 + return true;
11.1062 + }
11.1063 +
11.1064 + private CharSequence wrapParams(
11.1065 + ExecutableElement ee, String id, String className, String evName, String dataName
11.1066 + ) {
11.1067 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
11.1068 + StringBuilder params = new StringBuilder();
11.1069 + boolean first = true;
11.1070 + for (VariableElement ve : ee.getParameters()) {
11.1071 + if (!first) {
11.1072 + params.append(", ");
11.1073 + }
11.1074 + first = false;
11.1075 + String toCall = null;
11.1076 + if (ve.asType() == stringType) {
11.1077 + if (ve.getSimpleName().contentEquals("id")) {
11.1078 + params.append('"').append(id).append('"');
11.1079 + continue;
11.1080 + }
11.1081 + toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString(";
11.1082 + }
11.1083 + if (ve.asType().getKind() == TypeKind.DOUBLE) {
11.1084 + toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble(";
11.1085 + }
11.1086 + if (ve.asType().getKind() == TypeKind.INT) {
11.1087 + toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toInt(";
11.1088 + }
11.1089 + if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
11.1090 + toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toModel(" + ve.asType() + ".class, ";
11.1091 + }
11.1092 +
11.1093 + if (toCall != null) {
11.1094 + params.append(toCall);
11.1095 + if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
11.1096 + params.append(dataName);
11.1097 + params.append(", null");
11.1098 + } else {
11.1099 + if (evName == null) {
11.1100 + final StringBuilder sb = new StringBuilder();
11.1101 + sb.append("Unexpected string parameter name.");
11.1102 + if (dataName != null) {
11.1103 + sb.append(" Try \"").append(dataName).append("\"");
11.1104 + }
11.1105 + error(sb.toString(), ee);
11.1106 + }
11.1107 + params.append(evName);
11.1108 + params.append(", \"");
11.1109 + params.append(ve.getSimpleName().toString());
11.1110 + params.append("\"");
11.1111 + }
11.1112 + params.append(")");
11.1113 + continue;
11.1114 + }
11.1115 + String rn = fqn(ve.asType(), ee);
11.1116 + int last = rn.lastIndexOf('.');
11.1117 + if (last >= 0) {
11.1118 + rn = rn.substring(last + 1);
11.1119 + }
11.1120 + if (rn.equals(className)) {
11.1121 + params.append(className).append(".this");
11.1122 + continue;
11.1123 + }
11.1124 + error(
11.1125 + "@On method can only accept String named 'id' or " + className + " arguments",
11.1126 + ee
11.1127 + );
11.1128 + }
11.1129 + return params;
11.1130 + }
11.1131 +
11.1132 +
11.1133 + private CharSequence wrapPropName(
11.1134 + ExecutableElement ee, String className, String propName, String propValue
11.1135 + ) {
11.1136 + TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
11.1137 + StringBuilder params = new StringBuilder();
11.1138 + boolean first = true;
11.1139 + for (VariableElement ve : ee.getParameters()) {
11.1140 + if (!first) {
11.1141 + params.append(", ");
11.1142 + }
11.1143 + first = false;
11.1144 + if (ve.asType() == stringType) {
11.1145 + if (propName != null && ve.getSimpleName().contentEquals(propName)) {
11.1146 + params.append('"').append(propValue).append('"');
11.1147 + } else {
11.1148 + error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
11.1149 + }
11.1150 + continue;
11.1151 + }
11.1152 + String rn = fqn(ve.asType(), ee);
11.1153 + int last = rn.lastIndexOf('.');
11.1154 + if (last >= 0) {
11.1155 + rn = rn.substring(last + 1);
11.1156 + }
11.1157 + if (rn.equals(className)) {
11.1158 + params.append(className).append(".this");
11.1159 + continue;
11.1160 + }
11.1161 + error(
11.1162 + "@OnPrprtChange method can only accept String or " + className + " arguments",
11.1163 + ee);
11.1164 + }
11.1165 + return params;
11.1166 + }
11.1167 +
11.1168 + private boolean isModel(TypeMirror tm) {
11.1169 + final Element e = processingEnv.getTypeUtils().asElement(tm);
11.1170 + if (e == null) {
11.1171 + return false;
11.1172 + }
11.1173 + for (Element ch : e.getEnclosedElements()) {
11.1174 + if (ch.getKind() == ElementKind.METHOD) {
11.1175 + ExecutableElement ee = (ExecutableElement)ch;
11.1176 + if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
11.1177 + return true;
11.1178 + }
11.1179 + }
11.1180 + }
11.1181 + return models.values().contains(e.getSimpleName().toString());
11.1182 + }
11.1183 +
11.1184 + private void writeStringArray(List<String> strings, Writer w) throws IOException {
11.1185 + w.write("new String[] {\n");
11.1186 + String sep = "";
11.1187 + for (String n : strings) {
11.1188 + w.write(sep);
11.1189 + if (n == null) {
11.1190 + w.write(" null");
11.1191 + } else {
11.1192 + w.write(" \"" + n + "\"");
11.1193 + }
11.1194 + sep = ",\n";
11.1195 + }
11.1196 + w.write("\n }");
11.1197 + }
11.1198 +
11.1199 + private void writeToString(Prprt[] props, Writer w) throws IOException {
11.1200 + w.write(" public String toString() {\n");
11.1201 + w.write(" StringBuilder sb = new StringBuilder();\n");
11.1202 + w.write(" sb.append('{');\n");
11.1203 + String sep = "";
11.1204 + for (Prprt p : props) {
11.1205 + w.write(sep);
11.1206 + w.append(" sb.append(\"" + p.name() + ": \");\n");
11.1207 + w.append(" sb.append(org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toJSON(prop_");
11.1208 + w.append(p.name()).append("));\n");
11.1209 + sep = " sb.append(',');\n";
11.1210 + }
11.1211 + w.write(" sb.append('}');\n");
11.1212 + w.write(" return sb.toString();\n");
11.1213 + w.write(" }\n");
11.1214 + }
11.1215 + private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
11.1216 + w.write(" public " + className + " clone() {\n");
11.1217 + w.write(" " + className + " ret = new " + className + "();\n");
11.1218 + for (Prprt p : props) {
11.1219 + if (!p.array()) {
11.1220 + boolean isModel[] = { false };
11.1221 + boolean isEnum[] = { false };
11.1222 + boolean isPrimitive[] = { false };
11.1223 + checkType(p, isModel, isEnum, isPrimitive);
11.1224 + if (!isModel[0]) {
11.1225 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
11.1226 + continue;
11.1227 + }
11.1228 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ".clone();\n");
11.1229 + } else {
11.1230 + w.write(" ret.prop_" + p.name() + " = prop_" + p.name() + ".clone();\n");
11.1231 + }
11.1232 + }
11.1233 +
11.1234 + w.write(" return ret;\n");
11.1235 + w.write(" }\n");
11.1236 + }
11.1237 +
11.1238 + private String inPckName(Element e) {
11.1239 + StringBuilder sb = new StringBuilder();
11.1240 + while (e.getKind() != ElementKind.PACKAGE) {
11.1241 + if (sb.length() == 0) {
11.1242 + sb.append(e.getSimpleName());
11.1243 + } else {
11.1244 + sb.insert(0, '.');
11.1245 + sb.insert(0, e.getSimpleName());
11.1246 + }
11.1247 + e = e.getEnclosingElement();
11.1248 + }
11.1249 + return sb.toString();
11.1250 + }
11.1251 +
11.1252 + private String fqn(TypeMirror pt, Element relative) {
11.1253 + if (pt.getKind() == TypeKind.ERROR) {
11.1254 + final Elements eu = processingEnv.getElementUtils();
11.1255 + PackageElement pckg = eu.getPackageOf(relative);
11.1256 + return pckg.getQualifiedName() + "." + pt.toString();
11.1257 + }
11.1258 + return pt.toString();
11.1259 + }
11.1260 +
11.1261 + private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
11.1262 + TypeMirror tm;
11.1263 + try {
11.1264 + String ret = p.typeName(processingEnv);
11.1265 + TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
11.1266 + if (e == null) {
11.1267 + isModel[0] = true;
11.1268 + isEnum[0] = false;
11.1269 + isPrimitive[0] = false;
11.1270 + return ret;
11.1271 + }
11.1272 + tm = e.asType();
11.1273 + } catch (MirroredTypeException ex) {
11.1274 + tm = ex.getTypeMirror();
11.1275 + }
11.1276 + tm = processingEnv.getTypeUtils().erasure(tm);
11.1277 + isPrimitive[0] = tm.getKind().isPrimitive();
11.1278 + final Element e = processingEnv.getTypeUtils().asElement(tm);
11.1279 + final Model m = e == null ? null : e.getAnnotation(Model.class);
11.1280 +
11.1281 + String ret;
11.1282 + if (m != null) {
11.1283 + ret = findPkgName(e) + '.' + m.className();
11.1284 + isModel[0] = true;
11.1285 + models.put(e, m.className());
11.1286 + } else if (findModelForMthd(e)) {
11.1287 + ret = ((TypeElement)e).getQualifiedName().toString();
11.1288 + isModel[0] = true;
11.1289 + } else {
11.1290 + ret = tm.toString();
11.1291 + }
11.1292 + TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
11.1293 + enm = processingEnv.getTypeUtils().erasure(enm);
11.1294 + isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
11.1295 + return ret;
11.1296 + }
11.1297 +
11.1298 + private static boolean findModelForMthd(Element clazz) {
11.1299 + if (clazz == null) {
11.1300 + return false;
11.1301 + }
11.1302 + for (Element e : clazz.getEnclosedElements()) {
11.1303 + if (e.getKind() == ElementKind.METHOD) {
11.1304 + ExecutableElement ee = (ExecutableElement)e;
11.1305 + if (
11.1306 + ee.getSimpleName().contentEquals("modelFor") &&
11.1307 + ee.getParameters().isEmpty()
11.1308 + ) {
11.1309 + return true;
11.1310 + }
11.1311 + }
11.1312 + }
11.1313 + return false;
11.1314 + }
11.1315 +
11.1316 + private Iterable<String> findParamNames(Element e, String url, StringBuilder assembleURL) {
11.1317 + List<String> params = new ArrayList<>();
11.1318 +
11.1319 + for (int pos = 0; ;) {
11.1320 + int next = url.indexOf('{', pos);
11.1321 + if (next == -1) {
11.1322 + assembleURL.append('"')
11.1323 + .append(url.substring(pos))
11.1324 + .append('"');
11.1325 + return params;
11.1326 + }
11.1327 + int close = url.indexOf('}', next);
11.1328 + if (close == -1) {
11.1329 + error("Unbalanced '{' and '}' in " + url, e);
11.1330 + return params;
11.1331 + }
11.1332 + final String paramName = url.substring(next + 1, close);
11.1333 + params.add(paramName);
11.1334 + assembleURL.append('"')
11.1335 + .append(url.substring(pos, next))
11.1336 + .append("\" + ").append(paramName).append(" + ");
11.1337 + pos = close + 1;
11.1338 + }
11.1339 + }
11.1340 +
11.1341 + private static Prprt findPrprt(Prprt[] properties, String propName) {
11.1342 + for (Prprt p : properties) {
11.1343 + if (propName.equals(p.name())) {
11.1344 + return p;
11.1345 + }
11.1346 + }
11.1347 + return null;
11.1348 + }
11.1349 +
11.1350 + private boolean isPrimitive(String type) {
11.1351 + return
11.1352 + "int".equals(type) ||
11.1353 + "double".equals(type) ||
11.1354 + "long".equals(type) ||
11.1355 + "short".equals(type) ||
11.1356 + "byte".equals(type) ||
11.1357 + "float".equals(type);
11.1358 + }
11.1359 +
11.1360 + private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
11.1361 + Set<String> names = new HashSet<>();
11.1362 + for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
11.1363 + if (e.getValue().contains(derivedProp)) {
11.1364 + names.add(e.getKey());
11.1365 + }
11.1366 + }
11.1367 + return names;
11.1368 + }
11.1369 +
11.1370 + private Prprt[] createProps(Element e, Property[] arr) {
11.1371 + Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
11.1372 + Prprt[] prev = verify.put(e, ret);
11.1373 + if (prev != null) {
11.1374 + error("Two sets of properties for ", e);
11.1375 + }
11.1376 + return ret;
11.1377 + }
11.1378 +
11.1379 + private static class Prprt {
11.1380 + private final Element e;
11.1381 + private final AnnotationMirror tm;
11.1382 + private final Property p;
11.1383 +
11.1384 + public Prprt(Element e, AnnotationMirror tm, Property p) {
11.1385 + this.e = e;
11.1386 + this.tm = tm;
11.1387 + this.p = p;
11.1388 + }
11.1389 +
11.1390 + String name() {
11.1391 + return p.name();
11.1392 + }
11.1393 +
11.1394 + boolean array() {
11.1395 + return p.array();
11.1396 + }
11.1397 +
11.1398 + String typeName(ProcessingEnvironment env) {
11.1399 + try {
11.1400 + return p.type().getName();
11.1401 + } catch (AnnotationTypeMismatchException ex) {
11.1402 + for (Object v : getAnnoValues(env)) {
11.1403 + String s = v.toString().replace(" ", "");
11.1404 + if (s.startsWith("type=") && s.endsWith(".class")) {
11.1405 + return s.substring(5, s.length() - 6);
11.1406 + }
11.1407 + }
11.1408 + throw ex;
11.1409 + }
11.1410 + }
11.1411 +
11.1412 +
11.1413 + static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
11.1414 + if (arr.length == 0) {
11.1415 + return new Prprt[0];
11.1416 + }
11.1417 +
11.1418 + if (e.getKind() != ElementKind.CLASS) {
11.1419 + throw new IllegalStateException("" + e.getKind());
11.1420 + }
11.1421 + TypeElement te = (TypeElement)e;
11.1422 + List<? extends AnnotationValue> val = null;
11.1423 + for (AnnotationMirror an : te.getAnnotationMirrors()) {
11.1424 + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
11.1425 + if (entry.getKey().getSimpleName().contentEquals("properties")) {
11.1426 + val = (List)entry.getValue().getValue();
11.1427 + break;
11.1428 + }
11.1429 + }
11.1430 + }
11.1431 + if (val == null || val.size() != arr.length) {
11.1432 + pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
11.1433 + return new Prprt[0];
11.1434 + }
11.1435 + Prprt[] ret = new Prprt[arr.length];
11.1436 + BIG: for (int i = 0; i < ret.length; i++) {
11.1437 + AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
11.1438 + ret[i] = new Prprt(e, am, arr[i]);
11.1439 +
11.1440 + }
11.1441 + return ret;
11.1442 + }
11.1443 +
11.1444 + private List<? extends Object> getAnnoValues(ProcessingEnvironment pe) {
11.1445 + try {
11.1446 + Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
11.1447 + Method m = trees.getMethod("instance", ProcessingEnvironment.class);
11.1448 + Object instance = m.invoke(null, pe);
11.1449 + m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
11.1450 + Object path = m.invoke(instance, e, tm);
11.1451 + m = path.getClass().getMethod("getLeaf");
11.1452 + Object leaf = m.invoke(path);
11.1453 + m = leaf.getClass().getMethod("getArguments");
11.1454 + return (List)m.invoke(leaf);
11.1455 + } catch (Exception ex) {
11.1456 + return Collections.emptyList();
11.1457 + }
11.1458 + }
11.1459 + }
11.1460 +
11.1461 }
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Model.java Thu Apr 11 16:59:42 2013 +0200
12.3 @@ -0,0 +1,44 @@
12.4 +/**
12.5 + * Back 2 Browser Bytecode Translator
12.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
12.7 + *
12.8 + * This program is free software: you can redistribute it and/or modify
12.9 + * it under the terms of the GNU General Public License as published by
12.10 + * the Free Software Foundation, version 2 of the License.
12.11 + *
12.12 + * This program is distributed in the hope that it will be useful,
12.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12.15 + * GNU General Public License for more details.
12.16 + *
12.17 + * You should have received a copy of the GNU General Public License
12.18 + * along with this program. Look for COPYING file in the top folder.
12.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
12.20 + */
12.21 +package org.apidesign.bck2brwsr.htmlpage.api;
12.22 +
12.23 +import java.lang.annotation.ElementType;
12.24 +import java.lang.annotation.Retention;
12.25 +import java.lang.annotation.RetentionPolicy;
12.26 +import java.lang.annotation.Target;
12.27 +
12.28 +/** Defines a model class named {@link #className()} which contains
12.29 + * defined {@link #properties()}. This class can have methods
12.30 + * annotated by {@link ComputedProperty} which define derived
12.31 + * properties in the model class.
12.32 + * <p>
12.33 + * The {@link #className() generated class}'s <code>toString</code>
12.34 + * converts the state of the object into
12.35 + * <a href="http://en.wikipedia.org/wiki/JSON">JSON</a> format.
12.36 + *
12.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
12.38 + */
12.39 +@Retention(RetentionPolicy.SOURCE)
12.40 +@Target(ElementType.TYPE)
12.41 +public @interface Model {
12.42 + /** Name of the model class */
12.43 + String className();
12.44 + /** List of properties in the model.
12.45 + */
12.46 + Property[] properties();
12.47 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnFunction.java Thu Apr 11 16:59:42 2013 +0200
13.3 @@ -0,0 +1,34 @@
13.4 +/**
13.5 + * Back 2 Browser Bytecode Translator
13.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
13.7 + *
13.8 + * This program is free software: you can redistribute it and/or modify
13.9 + * it under the terms of the GNU General Public License as published by
13.10 + * the Free Software Foundation, version 2 of the License.
13.11 + *
13.12 + * This program is distributed in the hope that it will be useful,
13.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13.15 + * GNU General Public License for more details.
13.16 + *
13.17 + * You should have received a copy of the GNU General Public License
13.18 + * along with this program. Look for COPYING file in the top folder.
13.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
13.20 + */
13.21 +package org.apidesign.bck2brwsr.htmlpage.api;
13.22 +
13.23 +import java.lang.annotation.ElementType;
13.24 +import java.lang.annotation.Retention;
13.25 +import java.lang.annotation.RetentionPolicy;
13.26 +import java.lang.annotation.Target;
13.27 +
13.28 +/** Methods in class annotated by {@link Model} or {@link Page} can be
13.29 + * annotated by this annotation to signal that they should be available
13.30 + * as functions to users of the model classes.
13.31 + *
13.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
13.33 + */
13.34 +@Target(ElementType.METHOD)
13.35 +@Retention(RetentionPolicy.SOURCE)
13.36 +public @interface OnFunction {
13.37 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnPropertyChange.java Thu Apr 11 16:59:42 2013 +0200
14.3 @@ -0,0 +1,38 @@
14.4 +/**
14.5 + * Back 2 Browser Bytecode Translator
14.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
14.7 + *
14.8 + * This program is free software: you can redistribute it and/or modify
14.9 + * it under the terms of the GNU General Public License as published by
14.10 + * the Free Software Foundation, version 2 of the License.
14.11 + *
14.12 + * This program is distributed in the hope that it will be useful,
14.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.15 + * GNU General Public License for more details.
14.16 + *
14.17 + * You should have received a copy of the GNU General Public License
14.18 + * along with this program. Look for COPYING file in the top folder.
14.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
14.20 + */
14.21 +package org.apidesign.bck2brwsr.htmlpage.api;
14.22 +
14.23 +import java.lang.annotation.ElementType;
14.24 +import java.lang.annotation.Retention;
14.25 +import java.lang.annotation.RetentionPolicy;
14.26 +import java.lang.annotation.Target;
14.27 +
14.28 +/** Represents a property. Either in a generated model of an HTML
14.29 + * {@link Page} or in a class defined by {@link Model}.
14.30 + *
14.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
14.32 + */
14.33 +@Retention(RetentionPolicy.SOURCE)
14.34 +@Target(ElementType.METHOD)
14.35 +public @interface OnPropertyChange {
14.36 + /** Name(s) of the properties. One wishes to observe.
14.37 + *
14.38 + * @return valid java identifier
14.39 + */
14.40 + String[] value();
14.41 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnReceive.java Thu Apr 11 16:59:42 2013 +0200
15.3 @@ -0,0 +1,93 @@
15.4 +/**
15.5 + * Back 2 Browser Bytecode Translator
15.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
15.7 + *
15.8 + * This program is free software: you can redistribute it and/or modify
15.9 + * it under the terms of the GNU General Public License as published by
15.10 + * the Free Software Foundation, version 2 of the License.
15.11 + *
15.12 + * This program is distributed in the hope that it will be useful,
15.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.15 + * GNU General Public License for more details.
15.16 + *
15.17 + * You should have received a copy of the GNU General Public License
15.18 + * along with this program. Look for COPYING file in the top folder.
15.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
15.20 + */
15.21 +package org.apidesign.bck2brwsr.htmlpage.api;
15.22 +
15.23 +import java.lang.annotation.ElementType;
15.24 +import java.lang.annotation.Retention;
15.25 +import java.lang.annotation.RetentionPolicy;
15.26 +import java.lang.annotation.Target;
15.27 +
15.28 +/** Static methods in classes annotated by {@link Page}
15.29 + * can be marked by this annotation to establish a
15.30 + * <a href="http://en.wikipedia.org/wiki/JSON">JSON</a>
15.31 + * communication point.
15.32 + * The associated model page then gets new method to invoke a network
15.33 + * connection. Example follows:
15.34 + *
15.35 + * <pre>
15.36 + * {@link Page @Page}(className="MyModel", xhtml="page.html", properties={
15.37 + * {@link Property @Property}(name = "people", type=Person.class, array=true)
15.38 + * })
15.39 + * class MyModelImpl {
15.40 + * {@link Model @Model}(className="Person", properties={
15.41 + * {@link Property @Property}(name = "firstName", type=String.class),
15.42 + * {@link Property @Property}(name = "lastName", type=String.class)
15.43 + * })
15.44 + * static class PersonImpl {
15.45 + * {@link ComputedProperty @ComputedProperty}
15.46 + * static String fullName(String firstName, String lastName) {
15.47 + * return firstName + " " + lastName;
15.48 + * }
15.49 + * }
15.50 + *
15.51 + * {@link OnReceive @OnReceive}(url = "{protocol}://your.server.com/person/{name}")
15.52 + * static void getANewPerson(MyModel m, Person p) {
15.53 + * {@link Element#alert Element.alert}("Adding " + p.getFullName() + '!');
15.54 + * m.getPeople().add(p);
15.55 + * }
15.56 + *
15.57 + * // the above will generate method <code>getANewPerson</code> in class <code>MyModel</code>.
15.58 + * // with <code>protocol</code> and <code>name</code> arguments
15.59 + * // which asynchronously contacts the server and in case of success calls
15.60 + * // your {@link OnReceive @OnReceive} with parsed in data
15.61 + *
15.62 + * {@link On @On}(event={@link OnEvent#CLICK OnEvent.CLICK}, id="rqst")
15.63 + * static void requestSmith(MyModel m) {
15.64 + * m.getANewPerson("http", "Smith");
15.65 + * }
15.66 + * }
15.67 + * </pre>
15.68 + * When the server returns <code>{ "firstName" : "John", "lastName" : "Smith" }</code>
15.69 + * the browser will show alert message <em>Adding John Smith!</em>.
15.70 + *
15.71 + * @author Jaroslav Tulach <jtulach@netbeans.org>
15.72 + * @since 0.6
15.73 + */
15.74 +@Retention(RetentionPolicy.SOURCE)
15.75 +@Target(ElementType.METHOD)
15.76 +public @interface OnReceive {
15.77 + /** The URL to connect to. Can contain variable names surrounded by '{' and '}'.
15.78 + * Those parameters will then become variables of the associated method.
15.79 + *
15.80 + * @return the (possibly parametrized) url to connect to
15.81 + */
15.82 + String url();
15.83 +
15.84 + /** Support for <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> requires
15.85 + * a callback from the server generated page to a function defined in the
15.86 + * system. The name of such function is usually specified as a property
15.87 + * (of possibly different names). By defining the <code>jsonp</code> attribute
15.88 + * one turns on the <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a>
15.89 + * transmission and specifies the name of the property. The property should
15.90 + * also be used in the {@link #url()} attribute on appropriate place.
15.91 + *
15.92 + * @return name of a property to carry the name of <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a>
15.93 + * callback function.
15.94 + */
15.95 + String jsonp() default "";
15.96 +}
16.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java Mon Mar 25 13:29:42 2013 +0100
16.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java Thu Apr 11 16:59:42 2013 +0200
16.3 @@ -20,15 +20,36 @@
16.4 import java.lang.annotation.Retention;
16.5 import java.lang.annotation.RetentionPolicy;
16.6 import java.lang.annotation.Target;
16.7 +import java.util.List;
16.8
16.9 -/** Represents a property in a generated model of an HTML
16.10 - * {@link Page}.
16.11 +/** Represents a property. Either in a generated model of an HTML
16.12 + * {@link Page} or in a class defined by {@link Model}.
16.13 *
16.14 * @author Jaroslav Tulach <jtulach@netbeans.org>
16.15 */
16.16 @Retention(RetentionPolicy.SOURCE)
16.17 @Target({})
16.18 public @interface Property {
16.19 + /** Name of the property. Will be used to define proper getter and setter
16.20 + * in the associated class.
16.21 + *
16.22 + * @return valid java identifier
16.23 + */
16.24 String name();
16.25 +
16.26 + /** Type of the property. Can either be primitive type (like <code>int.class</code>,
16.27 + * <code>double.class</code>, etc.), {@link String} or complex model
16.28 + * class (defined by {@link Model} property).
16.29 + *
16.30 + * @return the class of the property
16.31 + */
16.32 Class<?> type();
16.33 +
16.34 + /** Is this property an array of the {@link #type()} or a single value?
16.35 + * If the property is an array, only its getter (returning mutable {@link List} of
16.36 + * the boxed {@link #type()}).
16.37 + *
16.38 + * @return true, if this is supposed to be an array of values.
16.39 + */
16.40 + boolean array() default false;
16.41 }
17.1 --- a/javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js Mon Mar 25 13:29:42 2013 +0100
17.2 +++ b/javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js Thu Apr 11 16:59:42 2013 +0200
17.3 @@ -2193,7 +2193,14 @@
17.4 else
17.5 element[attrName] = attrValue;
17.6 } else if (!toRemove) {
17.7 - element.setAttribute(attrName, attrValue.toString());
17.8 + try {
17.9 + element.setAttribute(attrName, attrValue.toString());
17.10 + } catch (err) {
17.11 + // ignore for now
17.12 + if (console) {
17.13 + console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
17.14 + }
17.15 + }
17.16 }
17.17
17.18 // Treat "name" specially - although you can think of it as an attribute, it also needs
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Compile.java Thu Apr 11 16:59:42 2013 +0200
18.3 @@ -0,0 +1,203 @@
18.4 +/**
18.5 + * Back 2 Browser Bytecode Translator
18.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
18.7 + *
18.8 + * This program is free software: you can redistribute it and/or modify
18.9 + * it under the terms of the GNU General Public License as published by
18.10 + * the Free Software Foundation, version 2 of the License.
18.11 + *
18.12 + * This program is distributed in the hope that it will be useful,
18.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18.15 + * GNU General Public License for more details.
18.16 + *
18.17 + * You should have received a copy of the GNU General Public License
18.18 + * along with this program. Look for COPYING file in the top folder.
18.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
18.20 + */
18.21 +package org.apidesign.bck2brwsr.htmlpage;
18.22 +
18.23 +import java.io.ByteArrayInputStream;
18.24 +import java.io.ByteArrayOutputStream;
18.25 +import java.io.IOException;
18.26 +import java.io.InputStream;
18.27 +import java.io.OutputStream;
18.28 +import java.net.URI;
18.29 +import java.net.URISyntaxException;
18.30 +import java.util.ArrayList;
18.31 +import java.util.Arrays;
18.32 +import java.util.HashMap;
18.33 +import java.util.List;
18.34 +import java.util.Map;
18.35 +import java.util.regex.Matcher;
18.36 +import java.util.regex.Pattern;
18.37 +import javax.tools.Diagnostic;
18.38 +import javax.tools.DiagnosticListener;
18.39 +import javax.tools.FileObject;
18.40 +import javax.tools.ForwardingJavaFileManager;
18.41 +import javax.tools.JavaFileManager;
18.42 +import javax.tools.JavaFileObject;
18.43 +import javax.tools.JavaFileObject.Kind;
18.44 +import javax.tools.SimpleJavaFileObject;
18.45 +import javax.tools.StandardJavaFileManager;
18.46 +import javax.tools.StandardLocation;
18.47 +import javax.tools.ToolProvider;
18.48 +
18.49 +/**
18.50 + *
18.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
18.52 + */
18.53 +final class Compile implements DiagnosticListener<JavaFileObject> {
18.54 + private final List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
18.55 + private final Map<String, byte[]> classes;
18.56 + private final String pkg;
18.57 + private final String cls;
18.58 + private final String html;
18.59 +
18.60 + private Compile(String html, String code) throws IOException {
18.61 + this.pkg = findPkg(code);
18.62 + this.cls = findCls(code);
18.63 + this.html = html;
18.64 + classes = compile(html, code);
18.65 + }
18.66 +
18.67 + /** Performs compilation of given HTML page and associated Java code
18.68 + */
18.69 + public static Compile create(String html, String code) throws IOException {
18.70 + return new Compile(html, code);
18.71 + }
18.72 +
18.73 + /** Checks for given class among compiled resources */
18.74 + public byte[] get(String res) {
18.75 + return classes.get(res);
18.76 + }
18.77 +
18.78 + /** Obtains errors created during compilation.
18.79 + */
18.80 + public List<Diagnostic<? extends JavaFileObject>> getErrors() {
18.81 + List<Diagnostic<? extends JavaFileObject>> err = new ArrayList<>();
18.82 + for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
18.83 + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
18.84 + err.add(diagnostic);
18.85 + }
18.86 + }
18.87 + return err;
18.88 + }
18.89 +
18.90 + private Map<String, byte[]> compile(final String html, final String code) throws IOException {
18.91 + StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
18.92 +
18.93 + final Map<String, ByteArrayOutputStream> class2BAOS = new HashMap<>();
18.94 +
18.95 + JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
18.96 + @Override
18.97 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
18.98 + return code;
18.99 + }
18.100 + };
18.101 + final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
18.102 + @Override
18.103 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
18.104 + return html;
18.105 + }
18.106 +
18.107 + @Override
18.108 + public InputStream openInputStream() throws IOException {
18.109 + return new ByteArrayInputStream(html.getBytes());
18.110 + }
18.111 + };
18.112 +
18.113 + final URI scratch;
18.114 + try {
18.115 + scratch = new URI("mem://mem3");
18.116 + } catch (URISyntaxException ex) {
18.117 + throw new IOException(ex);
18.118 + }
18.119 +
18.120 + JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
18.121 + @Override
18.122 + public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
18.123 + if (kind == Kind.CLASS) {
18.124 + final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
18.125 +
18.126 + class2BAOS.put(className.replace('.', '/') + ".class", buffer);
18.127 + return new SimpleJavaFileObject(sibling.toUri(), kind) {
18.128 + @Override
18.129 + public OutputStream openOutputStream() throws IOException {
18.130 + return buffer;
18.131 + }
18.132 + };
18.133 + }
18.134 +
18.135 + if (kind == Kind.SOURCE) {
18.136 + return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) {
18.137 + private final ByteArrayOutputStream data = new ByteArrayOutputStream();
18.138 + @Override
18.139 + public OutputStream openOutputStream() throws IOException {
18.140 + return data;
18.141 + }
18.142 +
18.143 + @Override
18.144 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
18.145 + data.close();
18.146 + return new String(data.toByteArray());
18.147 + }
18.148 + };
18.149 + }
18.150 +
18.151 + throw new IllegalStateException();
18.152 + }
18.153 +
18.154 + @Override
18.155 + public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
18.156 + if (location == StandardLocation.SOURCE_PATH) {
18.157 + if (packageName.equals(pkg)) {
18.158 + return htmlFile;
18.159 + }
18.160 + }
18.161 +
18.162 + return null;
18.163 + }
18.164 +
18.165 + };
18.166 +
18.167 + ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
18.168 +
18.169 + Map<String, byte[]> result = new HashMap<>();
18.170 +
18.171 + for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
18.172 + result.put(e.getKey(), e.getValue().toByteArray());
18.173 + }
18.174 +
18.175 + return result;
18.176 + }
18.177 +
18.178 +
18.179 + @Override
18.180 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
18.181 + errors.add(diagnostic);
18.182 + }
18.183 + private static String findPkg(String java) throws IOException {
18.184 + Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
18.185 + Matcher m = p.matcher(java);
18.186 + if (!m.find()) {
18.187 + throw new IOException("Can't find package declaration in the java file");
18.188 + }
18.189 + String pkg = m.group(1);
18.190 + return pkg;
18.191 + }
18.192 + private static String findCls(String java) throws IOException {
18.193 + Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
18.194 + Matcher m = p.matcher(java);
18.195 + if (!m.find()) {
18.196 + throw new IOException("Can't find package declaration in the java file");
18.197 + }
18.198 + String cls = m.group(1);
18.199 + return cls;
18.200 + }
18.201 +
18.202 + String getHtml() {
18.203 + String fqn = "'" + pkg + '.' + cls + "'";
18.204 + return html.replace("'${fqn}'", fqn);
18.205 + }
18.206 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypesTest.java Thu Apr 11 16:59:42 2013 +0200
19.3 @@ -0,0 +1,52 @@
19.4 +/**
19.5 + * Back 2 Browser Bytecode Translator
19.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
19.7 + *
19.8 + * This program is free software: you can redistribute it and/or modify
19.9 + * it under the terms of the GNU General Public License as published by
19.10 + * the Free Software Foundation, version 2 of the License.
19.11 + *
19.12 + * This program is distributed in the hope that it will be useful,
19.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19.15 + * GNU General Public License for more details.
19.16 + *
19.17 + * You should have received a copy of the GNU General Public License
19.18 + * along with this program. Look for COPYING file in the top folder.
19.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
19.20 + */
19.21 +package org.apidesign.bck2brwsr.htmlpage;
19.22 +
19.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
19.24 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
19.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
19.26 +import org.testng.annotations.Factory;
19.27 +
19.28 +/**
19.29 + *
19.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
19.31 + */
19.32 +public class ConvertTypesTest {
19.33 + @JavaScriptBody(args = { }, body = "var json = new Object();"
19.34 + + "json.firstName = 'son';\n"
19.35 + + "json.lastName = 'dj';\n"
19.36 + + "json.sex = 'MALE';\n"
19.37 + + "return json;"
19.38 + )
19.39 + private static native Object createJSON();
19.40 +
19.41 + @BrwsrTest
19.42 + public void testConvertToPeople() {
19.43 + final Object o = createJSON();
19.44 +
19.45 + Person p = new Person(o);
19.46 +
19.47 + assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
19.48 + assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
19.49 + assert Sex.MALE.equals(p.getSex()) : "Sex: " + p.getSex();
19.50 + }
19.51 +
19.52 + @Factory public static Object[] create() {
19.53 + return VMTest.create(ConvertTypesTest.class);
19.54 + }
19.55 +}
19.56 \ No newline at end of file
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/JSONTest.java Thu Apr 11 16:59:42 2013 +0200
20.3 @@ -0,0 +1,370 @@
20.4 +/**
20.5 + * Back 2 Browser Bytecode Translator
20.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
20.7 + *
20.8 + * This program is free software: you can redistribute it and/or modify
20.9 + * it under the terms of the GNU General Public License as published by
20.10 + * the Free Software Foundation, version 2 of the License.
20.11 + *
20.12 + * This program is distributed in the hope that it will be useful,
20.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20.15 + * GNU General Public License for more details.
20.16 + *
20.17 + * You should have received a copy of the GNU General Public License
20.18 + * along with this program. Look for COPYING file in the top folder.
20.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
20.20 + */
20.21 +package org.apidesign.bck2brwsr.htmlpage;
20.22 +
20.23 +import java.util.Arrays;
20.24 +import java.util.Iterator;
20.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
20.26 +import org.apidesign.bck2brwsr.htmlpage.api.OnReceive;
20.27 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
20.28 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
20.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
20.30 +import org.apidesign.bck2brwsr.vmtest.Http;
20.31 +import org.apidesign.bck2brwsr.vmtest.VMTest;
20.32 +import org.json.JSONException;
20.33 +import org.json.JSONObject;
20.34 +import org.json.JSONTokener;
20.35 +import org.testng.annotations.Test;
20.36 +import static org.testng.Assert.*;
20.37 +import org.testng.annotations.Factory;
20.38 +
20.39 +/** Need to verify that models produce reasonable JSON objects.
20.40 + *
20.41 + * @author Jaroslav Tulach <jtulach@netbeans.org>
20.42 + */
20.43 +@Page(xhtml = "Empty.html", className = "JSONik", properties = {
20.44 + @Property(name = "fetched", type = PersonImpl.class),
20.45 + @Property(name = "fetchedCount", type = int.class),
20.46 + @Property(name = "fetchedSex", type = Sex.class, array = true)
20.47 +})
20.48 +public class JSONTest {
20.49 + private JSONik js;
20.50 + private Integer orig;
20.51 +
20.52 + @Test public void personToString() throws JSONException {
20.53 + Person p = new Person();
20.54 + p.setSex(Sex.MALE);
20.55 + p.setFirstName("Jarda");
20.56 + p.setLastName("Tulach");
20.57 +
20.58 + JSONTokener t = new JSONTokener(p.toString());
20.59 + JSONObject o;
20.60 + try {
20.61 + o = new JSONObject(t);
20.62 + } catch (JSONException ex) {
20.63 + throw new AssertionError("Can't parse " + p.toString(), ex);
20.64 + }
20.65 +
20.66 + Iterator it = o.sortedKeys();
20.67 + assertEquals(it.next(), "firstName");
20.68 + assertEquals(it.next(), "lastName");
20.69 + assertEquals(it.next(), "sex");
20.70 +
20.71 + assertEquals(o.getString("firstName"), "Jarda");
20.72 + assertEquals(o.getString("lastName"), "Tulach");
20.73 + assertEquals(o.getString("sex"), "MALE");
20.74 + }
20.75 +
20.76 + @Test public void personWithWildCharactersAndNulls() throws JSONException {
20.77 + Person p = new Person();
20.78 + p.setFirstName("'\"\n");
20.79 + p.setLastName("\t\r\u0002");
20.80 +
20.81 + JSONTokener t = new JSONTokener(p.toString());
20.82 + JSONObject o;
20.83 + try {
20.84 + o = new JSONObject(t);
20.85 + } catch (JSONException ex) {
20.86 + throw new AssertionError("Can't parse " + p.toString(), ex);
20.87 + }
20.88 +
20.89 + Iterator it = o.sortedKeys();
20.90 + assertEquals(it.next(), "firstName");
20.91 + assertEquals(it.next(), "lastName");
20.92 + assertEquals(it.next(), "sex");
20.93 +
20.94 + assertEquals(o.getString("firstName"), p.getFirstName());
20.95 + assertEquals(o.getString("lastName"), p.getLastName());
20.96 + assertEquals(o.get("sex"), JSONObject.NULL);
20.97 + }
20.98 +
20.99 + @Test public void personsInArray() throws JSONException {
20.100 + Person p1 = new Person();
20.101 + p1.setFirstName("One");
20.102 +
20.103 + Person p2 = new Person();
20.104 + p2.setFirstName("Two");
20.105 +
20.106 + People arr = new People();
20.107 + arr.getInfo().add(p1);
20.108 + arr.getInfo().add(p2);
20.109 + arr.getNicknames().add("Prvn\u00ed k\u016f\u0148");
20.110 + final String n2 = "Druh\u00fd hlem\u00fd\u017e\u010f, star\u0161\u00ed";
20.111 + arr.getNicknames().add(n2);
20.112 + arr.getAge().add(33);
20.113 + arr.getAge().add(73);
20.114 +
20.115 +
20.116 + final String json = arr.toString();
20.117 +
20.118 + JSONTokener t = new JSONTokener(json);
20.119 + JSONObject o;
20.120 + try {
20.121 + o = new JSONObject(t);
20.122 + } catch (JSONException ex) {
20.123 + throw new AssertionError("Can't parse " + json, ex);
20.124 + }
20.125 +
20.126 + assertEquals(o.getJSONArray("info").getJSONObject(0).getString("firstName"), "One");
20.127 + assertEquals(o.getJSONArray("nicknames").getString(1), n2);
20.128 + assertEquals(o.getJSONArray("age").getInt(1), 73);
20.129 + }
20.130 +
20.131 +
20.132 + @OnReceive(url="/{url}")
20.133 + static void fetch(Person p, JSONik model) {
20.134 + model.setFetched(p);
20.135 + }
20.136 +
20.137 + @OnReceive(url="/{url}")
20.138 + static void fetchArray(Person[] p, JSONik model) {
20.139 + model.setFetchedCount(p.length);
20.140 + model.setFetched(p[0]);
20.141 + }
20.142 +
20.143 + @OnReceive(url="/{url}")
20.144 + static void fetchPeople(People p, JSONik model) {
20.145 + model.setFetchedCount(p.getInfo().size());
20.146 + model.setFetched(p.getInfo().get(0));
20.147 + }
20.148 +
20.149 + @OnReceive(url="/{url}")
20.150 + static void fetchPeopleAge(People p, JSONik model) {
20.151 + int sum = 0;
20.152 + for (int a : p.getAge()) {
20.153 + sum += a;
20.154 + }
20.155 + model.setFetchedCount(sum);
20.156 + }
20.157 +
20.158 + @Http(@Http.Resource(
20.159 + content = "{'firstName': 'Sitar', 'sex': 'MALE'}",
20.160 + path="/person.json",
20.161 + mimeType = "application/json"
20.162 + ))
20.163 + @BrwsrTest public void loadAndParseJSON() throws InterruptedException {
20.164 + if (js == null) {
20.165 + js = new JSONik();
20.166 + js.applyBindings();
20.167 +
20.168 + js.fetch("person.json");
20.169 + }
20.170 +
20.171 + Person p = js.getFetched();
20.172 + if (p == null) {
20.173 + throw new InterruptedException();
20.174 + }
20.175 +
20.176 + assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
20.177 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
20.178 + }
20.179 +
20.180 + @OnReceive(url="/{url}?callme={me}", jsonp = "me")
20.181 + static void fetchViaJSONP(Person p, JSONik model) {
20.182 + model.setFetched(p);
20.183 + }
20.184 +
20.185 + @Http(@Http.Resource(
20.186 + content = "$0({'firstName': 'Mitar', 'sex': 'MALE'})",
20.187 + path="/person.json",
20.188 + mimeType = "application/javascript",
20.189 + parameters = { "callme" }
20.190 + ))
20.191 + @BrwsrTest public void loadAndParseJSONP() throws InterruptedException {
20.192 +
20.193 + if (js == null) {
20.194 + orig = scriptElements();
20.195 + assert orig > 0 : "There should be some scripts on the page";
20.196 +
20.197 + js = new JSONik();
20.198 + js.applyBindings();
20.199 +
20.200 + js.fetchViaJSONP("person.json");
20.201 + }
20.202 +
20.203 + Person p = js.getFetched();
20.204 + if (p == null) {
20.205 + throw new InterruptedException();
20.206 + }
20.207 +
20.208 + assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
20.209 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
20.210 +
20.211 + int now = scriptElements();
20.212 +
20.213 + assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
20.214 + }
20.215 +
20.216 + @JavaScriptBody(args = { }, body = "return window.document.getElementsByTagName('script').length;")
20.217 + private static native int scriptElements();
20.218 +
20.219 + @Http(@Http.Resource(
20.220 + content = "{'firstName': 'Sitar', 'sex': 'MALE'}",
20.221 + path="/person.json",
20.222 + mimeType = "application/json"
20.223 + ))
20.224 + @BrwsrTest public void loadAndParseJSONSentToArray() throws InterruptedException {
20.225 + if (js == null) {
20.226 + js = new JSONik();
20.227 + js.applyBindings();
20.228 +
20.229 + js.fetchArray("person.json");
20.230 + }
20.231 +
20.232 + Person p = js.getFetched();
20.233 + if (p == null) {
20.234 + throw new InterruptedException();
20.235 + }
20.236 +
20.237 + assert p != null : "We should get our person back: " + p;
20.238 + assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
20.239 + assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
20.240 + }
20.241 +
20.242 + @Http(@Http.Resource(
20.243 + content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]",
20.244 + path="/person.json",
20.245 + mimeType = "application/json"
20.246 + ))
20.247 + @BrwsrTest public void loadAndParseJSONArraySingle() throws InterruptedException {
20.248 + if (js == null) {
20.249 + js = new JSONik();
20.250 + js.applyBindings();
20.251 +
20.252 + js.fetch("person.json");
20.253 + }
20.254 +
20.255 + Person p = js.getFetched();
20.256 + if (p == null) {
20.257 + throw new InterruptedException();
20.258 + }
20.259 +
20.260 + assert p != null : "We should get our person back: " + p;
20.261 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
20.262 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
20.263 + }
20.264 +
20.265 + @Http(@Http.Resource(
20.266 + content = "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}",
20.267 + path="/people.json",
20.268 + mimeType = "application/json"
20.269 + ))
20.270 + @BrwsrTest public void loadAndParseArrayInPeople() throws InterruptedException {
20.271 + if (js == null) {
20.272 + js = new JSONik();
20.273 + js.applyBindings();
20.274 +
20.275 + js.fetchPeople("people.json");
20.276 + }
20.277 +
20.278 + if (0 == js.getFetchedCount()) {
20.279 + throw new InterruptedException();
20.280 + }
20.281 +
20.282 + assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
20.283 +
20.284 + Person p = js.getFetched();
20.285 +
20.286 + assert p != null : "We should get our person back: " + p;
20.287 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
20.288 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
20.289 + }
20.290 +
20.291 + @Http(@Http.Resource(
20.292 + content = "{'age':[1, 2, 3]}",
20.293 + path="/people.json",
20.294 + mimeType = "application/json"
20.295 + ))
20.296 + @BrwsrTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
20.297 + if (js == null) {
20.298 + js = new JSONik();
20.299 + js.applyBindings();
20.300 +
20.301 + js.fetchPeopleAge("people.json");
20.302 + }
20.303 +
20.304 + if (0 == js.getFetchedCount()) {
20.305 + throw new InterruptedException();
20.306 + }
20.307 +
20.308 + assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
20.309 + }
20.310 +
20.311 + @OnReceive(url="/{url}")
20.312 + static void fetchPeopleSex(People p, JSONik model) {
20.313 + model.setFetchedCount(1);
20.314 + model.getFetchedSex().addAll(p.getSex());
20.315 + }
20.316 +
20.317 +
20.318 + @Http(@Http.Resource(
20.319 + content = "{'sex':['FEMALE', 'MALE', 'MALE']}",
20.320 + path="/people.json",
20.321 + mimeType = "application/json"
20.322 + ))
20.323 + @BrwsrTest public void loadAndParseArrayOfEnums() throws InterruptedException {
20.324 + if (js == null) {
20.325 + js = new JSONik();
20.326 + js.applyBindings();
20.327 +
20.328 + js.fetchPeopleSex("people.json");
20.329 + }
20.330 +
20.331 + if (0 == js.getFetchedCount()) {
20.332 + throw new InterruptedException();
20.333 + }
20.334 +
20.335 + assert js.getFetchedCount() == 1 : "Loaded";
20.336 +
20.337 + assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
20.338 + assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
20.339 + assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
20.340 + assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
20.341 + }
20.342 +
20.343 + @Http(@Http.Resource(
20.344 + content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
20.345 + + "{'firstName': 'Peter', 'sex': 'MALE'}"
20.346 + + "]",
20.347 + path="/person.json",
20.348 + mimeType = "application/json"
20.349 + ))
20.350 + @BrwsrTest public void loadAndParseJSONArray() throws InterruptedException {
20.351 + if (js == null) {
20.352 + js = new JSONik();
20.353 + js.applyBindings();
20.354 + js.fetchArray("person.json");
20.355 + }
20.356 +
20.357 +
20.358 + Person p = js.getFetched();
20.359 + if (p == null) {
20.360 + throw new InterruptedException();
20.361 + }
20.362 +
20.363 + assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
20.364 + assert p != null : "We should get our person back: " + p;
20.365 + assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
20.366 + assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
20.367 + }
20.368 +
20.369 + @Factory public static Object[] create() {
20.370 + return VMTest.create(JSONTest.class);
20.371 + }
20.372 +
20.373 +}
21.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Mon Mar 25 13:29:42 2013 +0100
21.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java Thu Apr 11 16:59:42 2013 +0200
21.3 @@ -17,21 +17,29 @@
21.4 */
21.5 package org.apidesign.bck2brwsr.htmlpage;
21.6
21.7 +import java.util.List;
21.8 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
21.9 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
21.10 import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
21.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
21.12 import org.apidesign.bck2brwsr.htmlpage.api.Page;
21.13 import org.apidesign.bck2brwsr.htmlpage.api.Property;
21.14 import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
21.15 import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
21.16 import org.apidesign.bck2brwsr.vmtest.VMTest;
21.17 +import static org.testng.Assert.assertEquals;
21.18 import org.testng.annotations.Factory;
21.19 +import org.testng.annotations.Test;
21.20
21.21 /**
21.22 *
21.23 * @author Jaroslav Tulach <jtulach@netbeans.org>
21.24 */
21.25 @Page(xhtml="Knockout.xhtml", className="KnockoutModel", properties={
21.26 - @Property(name="name", type=String.class)
21.27 + @Property(name="name", type=String.class),
21.28 + @Property(name="results", type=String.class, array = true),
21.29 + @Property(name="callbackCount", type=int.class),
21.30 + @Property(name="people", type=PersonImpl.class, array = true)
21.31 })
21.32 public class KnockoutTest {
21.33
21.34 @@ -44,19 +52,207 @@
21.35 KnockoutModel m = new KnockoutModel();
21.36 m.setName("Kukuc");
21.37 m.applyBindings();
21.38 - assert "Kukuc".equals(m.INPUT.getValue()) : "Value is really kukuc: " + m.INPUT.getValue();
21.39 - m.INPUT.setValue("Jardo");
21.40 - m.triggerEvent(m.INPUT, OnEvent.CHANGE);
21.41 + assert "Kukuc".equals(m.input.getValue()) : "Value is really kukuc: " + m.input.getValue();
21.42 + m.input.setValue("Jardo");
21.43 + m.triggerEvent(m.input, OnEvent.CHANGE);
21.44 assert "Jardo".equals(m.getName()) : "Name property updated: " + m.getName();
21.45 }
21.46
21.47 + @HtmlFragment(
21.48 + "<ul id='ul' data-bind='foreach: results'>\n"
21.49 + + " <li data-bind='text: $data, click: $root.call'/>\n"
21.50 + + "</ul>\n"
21.51 + )
21.52 + @BrwsrTest public void displayContentOfArray() {
21.53 + KnockoutModel m = new KnockoutModel();
21.54 + m.getResults().add("Ahoj");
21.55 + m.applyBindings();
21.56 +
21.57 + int cnt = countChildren("ul");
21.58 + assert cnt == 1 : "One child, but was " + cnt;
21.59 +
21.60 + m.getResults().add("Hi");
21.61 +
21.62 + cnt = countChildren("ul");
21.63 + assert cnt == 2 : "Two children now, but was " + cnt;
21.64 +
21.65 + triggerChildClick("ul", 1);
21.66 +
21.67 + assert 1 == m.getCallbackCount() : "One callback " + m.getCallbackCount();
21.68 + assert "Hi".equals(m.getName()) : "We got callback from 2nd child " + m.getName();
21.69 + }
21.70 +
21.71 + @HtmlFragment(
21.72 + "<ul id='ul' data-bind='foreach: cmpResults'>\n"
21.73 + + " <li><b data-bind='text: $data'></b></li>\n"
21.74 + + "</ul>\n"
21.75 + )
21.76 + @BrwsrTest public void displayContentOfDerivedArray() {
21.77 + KnockoutModel m = new KnockoutModel();
21.78 + m.getResults().add("Ahoj");
21.79 + m.applyBindings();
21.80 +
21.81 + int cnt = countChildren("ul");
21.82 + assert cnt == 1 : "One child, but was " + cnt;
21.83 +
21.84 + m.getResults().add("hello");
21.85 +
21.86 + cnt = countChildren("ul");
21.87 + assert cnt == 2 : "Two children now, but was " + cnt;
21.88 + }
21.89 +
21.90 + @HtmlFragment(
21.91 + "<ul id='ul' data-bind='foreach: people'>\n"
21.92 + + " <li data-bind='text: $data.firstName, click: $root.removePerson'></li>\n"
21.93 + + "</ul>\n"
21.94 + )
21.95 + @BrwsrTest public void displayContentOfArrayOfPeople() {
21.96 + KnockoutModel m = new KnockoutModel();
21.97 +
21.98 + final Person first = new Person();
21.99 + first.setFirstName("first");
21.100 + m.getPeople().add(first);
21.101 +
21.102 + m.applyBindings();
21.103 +
21.104 + int cnt = countChildren("ul");
21.105 + assert cnt == 1 : "One child, but was " + cnt;
21.106 +
21.107 + final Person second = new Person();
21.108 + second.setFirstName("second");
21.109 + m.getPeople().add(second);
21.110 +
21.111 + cnt = countChildren("ul");
21.112 + assert cnt == 2 : "Two children now, but was " + cnt;
21.113 +
21.114 + triggerChildClick("ul", 1);
21.115 +
21.116 + assert 1 == m.getCallbackCount() : "One callback " + m.getCallbackCount();
21.117 +
21.118 + cnt = countChildren("ul");
21.119 + assert cnt == 1 : "Again one child, but was " + cnt;
21.120 +
21.121 + String txt = childText("ul", 0);
21.122 + assert "first".equals(txt) : "Expecting 'first': " + txt;
21.123 +
21.124 + first.setFirstName("changed");
21.125 +
21.126 + txt = childText("ul", 0);
21.127 + assert "changed".equals(txt) : "Expecting 'changed': " + txt;
21.128 + }
21.129 +
21.130 + @ComputedProperty
21.131 + static Person firstPerson(List<Person> people) {
21.132 + return people.isEmpty() ? null : people.get(0);
21.133 + }
21.134 +
21.135 + @HtmlFragment(
21.136 + "<p id='ul' data-bind='with: firstPerson'>\n"
21.137 + + " <span data-bind='text: firstName, click: changeSex'></span>\n"
21.138 + + "</p>\n"
21.139 + )
21.140 + @BrwsrTest public void accessFirstPersonWithOnFunction() {
21.141 + trasfertToFemale();
21.142 + }
21.143 +
21.144 + @HtmlFragment(
21.145 + "<ul id='ul' data-bind='foreach: people'>\n"
21.146 + + " <li data-bind='text: $data.firstName, click: changeSex'></li>\n"
21.147 + + "</ul>\n"
21.148 + )
21.149 + @BrwsrTest public void onPersonFunction() {
21.150 + trasfertToFemale();
21.151 + }
21.152 +
21.153 + private void trasfertToFemale() {
21.154 + KnockoutModel m = new KnockoutModel();
21.155 +
21.156 + final Person first = new Person();
21.157 + first.setFirstName("first");
21.158 + first.setSex(Sex.MALE);
21.159 + m.getPeople().add(first);
21.160 +
21.161 +
21.162 + m.applyBindings();
21.163 +
21.164 + int cnt = countChildren("ul");
21.165 + assert cnt == 1 : "One child, but was " + cnt;
21.166 +
21.167 +
21.168 + triggerChildClick("ul", 0);
21.169 +
21.170 + assert first.getSex() == Sex.FEMALE : "Transverted to female: " + first.getSex();
21.171 + }
21.172 +
21.173 + @Test public void cloneModel() {
21.174 + Person model = new Person();
21.175 +
21.176 + model.setFirstName("first");
21.177 + Person snd = model.clone();
21.178 + snd.setFirstName("clone");
21.179 + assertEquals("first", model.getFirstName(), "Value has not changed");
21.180 + assertEquals("clone", snd.getFirstName(), "Value has changed in clone");
21.181 + }
21.182 +
21.183 +
21.184 + @Test public void deepCopyOnClone() {
21.185 + People model = new People();
21.186 + model.getNicknames().add("Jarda");
21.187 + assertEquals(model.getNicknames().size(), 1, "One element");
21.188 + People snd = model.clone();
21.189 + snd.getNicknames().clear();
21.190 + assertEquals(snd.getNicknames().size(), 0, "Clone is empty");
21.191 + assertEquals(model.getNicknames().size(), 1, "Still one element");
21.192 + }
21.193 +
21.194 +
21.195 + @OnFunction
21.196 + static void call(KnockoutModel m, String data) {
21.197 + m.setName(data);
21.198 + m.setCallbackCount(m.getCallbackCount() + 1);
21.199 + }
21.200 +
21.201 + @OnFunction
21.202 + static void removePerson(KnockoutModel model, Person data) {
21.203 + model.setCallbackCount(model.getCallbackCount() + 1);
21.204 + model.getPeople().remove(data);
21.205 + }
21.206 +
21.207 +
21.208 @ComputedProperty
21.209 static String helloMessage(String name) {
21.210 return "Hello " + name + "!";
21.211 }
21.212
21.213 + @ComputedProperty
21.214 + static List<String> cmpResults(List<String> results) {
21.215 + return results;
21.216 + }
21.217 +
21.218 @Factory
21.219 public static Object[] create() {
21.220 return VMTest.create(KnockoutTest.class);
21.221 }
21.222 +
21.223 + @JavaScriptBody(args = { "id" }, body =
21.224 + "var e = window.document.getElementById(id);\n "
21.225 + + "if (typeof e === 'undefined') return -2;\n "
21.226 + + "return e.children.length;\n "
21.227 + )
21.228 + private static native int countChildren(String id);
21.229 +
21.230 + @JavaScriptBody(args = { "id", "pos" }, body =
21.231 + "var e = window.document.getElementById(id);\n "
21.232 + + "var ev = window.document.createEvent('MouseEvents');\n "
21.233 + + "ev.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);\n "
21.234 + + "e.children[pos].dispatchEvent(ev);\n "
21.235 + )
21.236 + private static native void triggerChildClick(String id, int pos);
21.237 +
21.238 + @JavaScriptBody(args = { "id", "pos" }, body =
21.239 + "var e = window.document.getElementById(id);\n "
21.240 + + "var t = e.children[pos].innerHTML;\n "
21.241 + + "return t ? t : null;"
21.242 + )
21.243 + private static native String childText(String id, int pos);
21.244 }
22.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java Mon Mar 25 13:29:42 2013 +0100
22.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java Thu Apr 11 16:59:42 2013 +0200
22.3 @@ -18,8 +18,13 @@
22.4 package org.apidesign.bck2brwsr.htmlpage;
22.5
22.6 import java.util.ArrayList;
22.7 +import java.util.Collections;
22.8 +import java.util.Iterator;
22.9 import java.util.List;
22.10 +import java.util.ListIterator;
22.11 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
22.12 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
22.13 +import org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange;
22.14 import org.apidesign.bck2brwsr.htmlpage.api.Page;
22.15 import org.apidesign.bck2brwsr.htmlpage.api.Property;
22.16 import static org.testng.Assert.*;
22.17 @@ -30,17 +35,22 @@
22.18 *
22.19 * @author Jaroslav Tulach <jtulach@netbeans.org>
22.20 */
22.21 -@Page(xhtml = "Empty.html", className = "Model", properties = {
22.22 +@Page(xhtml = "Empty.html", className = "Modelik", properties = {
22.23 @Property(name = "value", type = int.class),
22.24 - @Property(name = "unrelated", type = long.class)
22.25 + @Property(name = "count", type = int.class),
22.26 + @Property(name = "unrelated", type = long.class),
22.27 + @Property(name = "names", type = String.class, array = true),
22.28 + @Property(name = "values", type = int.class, array = true),
22.29 + @Property(name = "people", type = PersonImpl.class, array = true),
22.30 + @Property(name = "changedProperty", type=String.class)
22.31 })
22.32 public class ModelTest {
22.33 - private Model model;
22.34 - private static Model leakedModel;
22.35 + private Modelik model;
22.36 + private static Modelik leakedModel;
22.37
22.38 @BeforeMethod
22.39 public void createModel() {
22.40 - model = new Model();
22.41 + model = new Modelik();
22.42 }
22.43
22.44 @Test public void classGeneratedWithSetterGetter() {
22.45 @@ -53,6 +63,75 @@
22.46 assertEquals(16, model.getPowerValue());
22.47 }
22.48
22.49 + @Test public void arrayIsMutable() {
22.50 + assertEquals(model.getNames().size(), 0, "Is empty");
22.51 + model.getNames().add("Jarda");
22.52 + assertEquals(model.getNames().size(), 1, "One element");
22.53 + }
22.54 +
22.55 + @Test public void arrayChangesNotified() {
22.56 + MockKnockout my = new MockKnockout();
22.57 + MockKnockout.next = my;
22.58 +
22.59 + model.applyBindings();
22.60 +
22.61 + model.getNames().add("Hello");
22.62 +
22.63 + assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
22.64 + assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
22.65 +
22.66 + my.mutated.clear();
22.67 +
22.68 + Iterator<String> it = model.getNames().iterator();
22.69 + assertEquals(it.next(), "Hello");
22.70 + it.remove();
22.71 +
22.72 + assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
22.73 + assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
22.74 +
22.75 + my.mutated.clear();
22.76 +
22.77 + ListIterator<String> lit = model.getNames().listIterator();
22.78 + lit.add("Jarda");
22.79 +
22.80 + assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
22.81 + assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
22.82 + }
22.83 +
22.84 + @Test public void autoboxedArray() {
22.85 + MockKnockout my = new MockKnockout();
22.86 + MockKnockout.next = my;
22.87 +
22.88 + model.applyBindings();
22.89 +
22.90 + model.getValues().add(10);
22.91 +
22.92 + assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten");
22.93 + }
22.94 +
22.95 + @Test public void derivedArrayProp() {
22.96 + MockKnockout my = new MockKnockout();
22.97 + MockKnockout.next = my;
22.98 +
22.99 + model.applyBindings();
22.100 +
22.101 + model.setCount(10);
22.102 +
22.103 + List<String> arr = model.getRepeat();
22.104 + assertEquals(arr.size(), 10, "Ten items: " + arr);
22.105 +
22.106 + my.mutated.clear();
22.107 +
22.108 + model.setCount(5);
22.109 +
22.110 + arr = model.getRepeat();
22.111 + assertEquals(arr.size(), 5, "Five items: " + arr);
22.112 +
22.113 + assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
22.114 + assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated);
22.115 + assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated);
22.116 + }
22.117 +
22.118 @Test public void derivedPropertiesAreNotified() {
22.119 MockKnockout my = new MockKnockout();
22.120 MockKnockout.next = my;
22.121 @@ -61,6 +140,9 @@
22.122
22.123 model.setValue(33);
22.124
22.125 + // not interested in change of this property
22.126 + my.mutated.remove("changedProperty");
22.127 +
22.128 assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
22.129 assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
22.130 assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
22.131 @@ -68,7 +150,11 @@
22.132 my.mutated.clear();
22.133
22.134 model.setUnrelated(44);
22.135 - assertEquals(my.mutated.size(), 1, "One property changed");
22.136 +
22.137 +
22.138 + // not interested in change of this property
22.139 + my.mutated.remove("changedProperty");
22.140 + assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated);
22.141 assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated");
22.142 }
22.143
22.144 @@ -92,11 +178,43 @@
22.145 }
22.146 }
22.147
22.148 + @OnFunction
22.149 + static void doSomething() {
22.150 + }
22.151 +
22.152 @ComputedProperty
22.153 static int powerValue(int value) {
22.154 return value * value;
22.155 }
22.156
22.157 + @OnPropertyChange({ "powerValue", "unrelated" })
22.158 + static void aPropertyChanged(Modelik m, String name) {
22.159 + m.setChangedProperty(name);
22.160 + }
22.161 +
22.162 + @OnPropertyChange({ "values" })
22.163 + static void anArrayPropertyChanged(String name, Modelik m) {
22.164 + m.setChangedProperty(name);
22.165 + }
22.166 +
22.167 + @Test public void changeAnything() {
22.168 + model.setCount(44);
22.169 + assertNull(model.getChangedProperty(), "No observed value change");
22.170 + }
22.171 + @Test public void changeValue() {
22.172 + model.setValue(33);
22.173 + assertEquals(model.getChangedProperty(), "powerValue", "power property changed");
22.174 + }
22.175 + @Test public void changeUnrelated() {
22.176 + model.setUnrelated(333);
22.177 + assertEquals(model.getChangedProperty(), "unrelated", "unrelated changed");
22.178 + }
22.179 +
22.180 + @Test public void changeInArray() {
22.181 + model.getValues().add(10);
22.182 + assertEquals(model.getChangedProperty(), "values", "Something added into the array");
22.183 + }
22.184 +
22.185 @ComputedProperty
22.186 static String notAllowedRead() {
22.187 return "Not allowed callback: " + leakedModel.getUnrelated();
22.188 @@ -108,12 +226,31 @@
22.189 return "Not allowed callback!";
22.190 }
22.191
22.192 + @ComputedProperty
22.193 + static List<String> repeat(int count) {
22.194 + return Collections.nCopies(count, "Hello");
22.195 + }
22.196 +
22.197 static class MockKnockout extends Knockout {
22.198 - List<String> mutated = new ArrayList<String>();
22.199 + List<String> mutated = new ArrayList<>();
22.200 +
22.201 + MockKnockout() {
22.202 + super(null);
22.203 + }
22.204
22.205 @Override
22.206 public void valueHasMutated(String prop) {
22.207 mutated.add(prop);
22.208 }
22.209 }
22.210 +
22.211 + public @Test void hasPersonPropertyAndComputedFullName() {
22.212 + List<Person> arr = model.getPeople();
22.213 + assertEquals(arr.size(), 0, "By default empty");
22.214 + Person p = null;
22.215 + if (p != null) {
22.216 + String fullNameGenerated = p.getFullName();
22.217 + assertNotNull(fullNameGenerated);
22.218 + }
22.219 + }
22.220 }
23.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Mon Mar 25 13:29:42 2013 +0100
23.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java Thu Apr 11 16:59:42 2013 +0200
23.3 @@ -50,7 +50,7 @@
23.4 if (PAGE != ref) {
23.5 throw new IllegalStateException("Both references should be the same. " + ref + " != " + PAGE);
23.6 }
23.7 - ref.PG_TITLE.setText("You want this window to be named " + ref.PG_TEXT.getValue());
23.8 + ref.pg_title.setText("You want this window to be named " + ref.pg_text.getValue());
23.9 }
23.10
23.11 @On(event = CLICK, id={ "pg.title", "pg.text" })
23.12 @@ -58,11 +58,11 @@
23.13 if (!id.equals("pg.title")) {
23.14 throw new IllegalStateException();
23.15 }
23.16 - PAGE.PG_TITLE.setText(id);
23.17 + PAGE.pg_title.setText(id);
23.18 }
23.19
23.20 @On(event = CLICK, id={ "pg.canvas" })
23.21 static void clickCanvas(String id, double layerX) {
23.22 - PAGE.PG_CANVAS.setWidth((int) layerX);
23.23 + PAGE.pg_canvas.setWidth((int) layerX);
23.24 }
23.25 }
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageTest.java Thu Apr 11 16:59:42 2013 +0200
24.3 @@ -0,0 +1,53 @@
24.4 +/**
24.5 + * Back 2 Browser Bytecode Translator
24.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
24.7 + *
24.8 + * This program is free software: you can redistribute it and/or modify
24.9 + * it under the terms of the GNU General Public License as published by
24.10 + * the Free Software Foundation, version 2 of the License.
24.11 + *
24.12 + * This program is distributed in the hope that it will be useful,
24.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24.15 + * GNU General Public License for more details.
24.16 + *
24.17 + * You should have received a copy of the GNU General Public License
24.18 + * along with this program. Look for COPYING file in the top folder.
24.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
24.20 + */
24.21 +package org.apidesign.bck2brwsr.htmlpage;
24.22 +
24.23 +import java.io.IOException;
24.24 +import java.util.Locale;
24.25 +import javax.tools.Diagnostic;
24.26 +import javax.tools.JavaFileObject;
24.27 +import static org.testng.Assert.*;
24.28 +import org.testng.annotations.Test;
24.29 +
24.30 +/** Verify errors emitted by the processor.
24.31 + *
24.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
24.33 + */
24.34 +public class PageTest {
24.35 + @Test public void verifyWrongType() throws IOException {
24.36 + String html = "<html><body>"
24.37 + + "</body></html>";
24.38 + String code = "package x.y.z;\n"
24.39 + + "import org.apidesign.bck2brwsr.htmlpage.api.*;\n"
24.40 + + "@Page(xhtml=\"index.xhtml\", className=\"Model\", properties={\n"
24.41 + + " @Property(name=\"prop\", type=Runnable.class)\n"
24.42 + + "})\n"
24.43 + + "class X {\n"
24.44 + + "}\n";
24.45 +
24.46 + Compile c = Compile.create(html, code);
24.47 + assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
24.48 + for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
24.49 + String msg = e.getMessage(Locale.ENGLISH);
24.50 + if (!msg.contains("Runnable")) {
24.51 + fail("Should contain warning about Runnable: " + msg);
24.52 + }
24.53 + }
24.54 + }
24.55 +
24.56 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PersonImpl.java Thu Apr 11 16:59:42 2013 +0200
25.3 @@ -0,0 +1,62 @@
25.4 +/**
25.5 + * Back 2 Browser Bytecode Translator
25.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
25.7 + *
25.8 + * This program is free software: you can redistribute it and/or modify
25.9 + * it under the terms of the GNU General Public License as published by
25.10 + * the Free Software Foundation, version 2 of the License.
25.11 + *
25.12 + * This program is distributed in the hope that it will be useful,
25.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25.15 + * GNU General Public License for more details.
25.16 + *
25.17 + * You should have received a copy of the GNU General Public License
25.18 + * along with this program. Look for COPYING file in the top folder.
25.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
25.20 + */
25.21 +package org.apidesign.bck2brwsr.htmlpage;
25.22 +
25.23 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
25.24 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
25.25 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
25.26 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
25.27 +
25.28 +/**
25.29 + *
25.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
25.31 + */
25.32 +@Model(className = "Person", properties = {
25.33 + @Property(name = "firstName", type = String.class),
25.34 + @Property(name = "lastName", type = String.class),
25.35 + @Property(name = "sex", type = Sex.class)
25.36 +})
25.37 +final class PersonImpl {
25.38 + @ComputedProperty
25.39 + public static String fullName(String firstName, String lastName) {
25.40 + return firstName + " " + lastName;
25.41 + }
25.42 +
25.43 + @ComputedProperty
25.44 + public static String sexType(Sex sex) {
25.45 + return sex == null ? "unknown" : sex.toString();
25.46 + }
25.47 +
25.48 + @OnFunction
25.49 + static void changeSex(Person p) {
25.50 + if (p.getSex() == Sex.MALE) {
25.51 + p.setSex(Sex.FEMALE);
25.52 + } else {
25.53 + p.setSex(Sex.MALE);
25.54 + }
25.55 + }
25.56 +
25.57 + @Model(className = "People", properties = {
25.58 + @Property(array = true, name = "info", type = Person.class),
25.59 + @Property(array = true, name = "nicknames", type = String.class),
25.60 + @Property(array = true, name = "age", type = int.class),
25.61 + @Property(array = true, name = "sex", type = Sex.class)
25.62 + })
25.63 + public class PeopleImpl {
25.64 + }
25.65 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Sex.java Thu Apr 11 16:59:42 2013 +0200
26.3 @@ -0,0 +1,26 @@
26.4 +/**
26.5 + * Back 2 Browser Bytecode Translator
26.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
26.7 + *
26.8 + * This program is free software: you can redistribute it and/or modify
26.9 + * it under the terms of the GNU General Public License as published by
26.10 + * the Free Software Foundation, version 2 of the License.
26.11 + *
26.12 + * This program is distributed in the hope that it will be useful,
26.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
26.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26.15 + * GNU General Public License for more details.
26.16 + *
26.17 + * You should have received a copy of the GNU General Public License
26.18 + * along with this program. Look for COPYING file in the top folder.
26.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
26.20 + */
26.21 +package org.apidesign.bck2brwsr.htmlpage;
26.22 +
26.23 +/**
26.24 + *
26.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
26.26 + */
26.27 +public enum Sex {
26.28 + MALE, FEMALE;
26.29 +}
27.1 --- a/javaquery/demo-calculator-dynamic/nbactions.xml Mon Mar 25 13:29:42 2013 +0100
27.2 +++ b/javaquery/demo-calculator-dynamic/nbactions.xml Thu Apr 11 16:59:42 2013 +0200
27.3 @@ -23,7 +23,7 @@
27.4 <actionName>run</actionName>
27.5 <goals>
27.6 <goal>process-classes</goal>
27.7 - <goal>org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr</goal>
27.8 + <goal>org.apidesign.bck2brwsr:mojo:0.6-SNAPSHOT:brwsr</goal>
27.9 </goals>
27.10 </action>
27.11 </actions>
28.1 --- a/javaquery/demo-calculator-dynamic/pom.xml Mon Mar 25 13:29:42 2013 +0100
28.2 +++ b/javaquery/demo-calculator-dynamic/pom.xml Thu Apr 11 16:59:42 2013 +0200
28.3 @@ -4,7 +4,7 @@
28.4
28.5 <groupId>org.apidesign.bck2brwsr</groupId>
28.6 <artifactId>demo.calculator</artifactId>
28.7 - <version>0.5-SNAPSHOT</version>
28.8 + <version>0.6-SNAPSHOT</version>
28.9 <packaging>jar</packaging>
28.10
28.11 <name>JavaQuery Demo - Calculator</name>
28.12 @@ -18,7 +18,7 @@
28.13 <plugin>
28.14 <groupId>org.apidesign.bck2brwsr</groupId>
28.15 <artifactId>mojo</artifactId>
28.16 - <version>0.5-SNAPSHOT</version>
28.17 + <version>0.6-SNAPSHOT</version>
28.18 <executions>
28.19 <execution>
28.20 <goals>
28.21 @@ -27,8 +27,7 @@
28.22 </execution>
28.23 </executions>
28.24 <configuration>
28.25 - <directory>${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html</directory>
28.26 - <startpage>index.xhtml</startpage>
28.27 + <startpage>org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml</startpage>
28.28 </configuration>
28.29 </plugin>
28.30 <plugin>
28.31 @@ -94,13 +93,13 @@
28.32 <dependency>
28.33 <groupId>org.apidesign.bck2brwsr</groupId>
28.34 <artifactId>emul</artifactId>
28.35 - <version>0.5-SNAPSHOT</version>
28.36 + <version>0.6-SNAPSHOT</version>
28.37 <classifier>rt</classifier>
28.38 </dependency>
28.39 <dependency>
28.40 <groupId>org.apidesign.bck2brwsr</groupId>
28.41 <artifactId>javaquery.api</artifactId>
28.42 - <version>0.5-SNAPSHOT</version>
28.43 + <version>0.6-SNAPSHOT</version>
28.44 </dependency>
28.45 <dependency>
28.46 <groupId>org.testng</groupId>
28.47 @@ -113,7 +112,7 @@
28.48 <artifactId>vm4brwsr</artifactId>
28.49 <classifier>js</classifier>
28.50 <type>zip</type>
28.51 - <version>0.5-SNAPSHOT</version>
28.52 + <version>0.6-SNAPSHOT</version>
28.53 <scope>provided</scope>
28.54 </dependency>
28.55 </dependencies>
29.1 --- a/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java Mon Mar 25 13:29:42 2013 +0100
29.2 +++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java Thu Apr 11 16:59:42 2013 +0200
29.3 @@ -17,9 +17,11 @@
29.4 */
29.5 package org.apidesign.bck2brwsr.demo.calc;
29.6
29.7 +import java.util.List;
29.8 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
29.9 import org.apidesign.bck2brwsr.htmlpage.api.On;
29.10 import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
29.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
29.12 import org.apidesign.bck2brwsr.htmlpage.api.Page;
29.13 import org.apidesign.bck2brwsr.htmlpage.api.Property;
29.14
29.15 @@ -33,11 +35,12 @@
29.16 @Property(name = "memory", type = double.class),
29.17 @Property(name = "display", type = double.class),
29.18 @Property(name = "operation", type = String.class),
29.19 - @Property(name = "hover", type = boolean.class)
29.20 + @Property(name = "hover", type = boolean.class),
29.21 + @Property(name = "history", type = HistoryImpl.class, array = true)
29.22 })
29.23 public class Calc {
29.24 static {
29.25 - new Calculator().applyBindings();
29.26 + new Calculator().applyBindings().setOperation("plus");
29.27 }
29.28
29.29 @On(event = CLICK, id="clear")
29.30 @@ -65,14 +68,31 @@
29.31
29.32 @On(event = CLICK, id="result")
29.33 static void computeTheValue(Calculator c) {
29.34 - c.setDisplay(compute(
29.35 + final double newValue = compute(
29.36 c.getOperation(),
29.37 c.getMemory(),
29.38 c.getDisplay()
29.39 - ));
29.40 + );
29.41 + c.setDisplay(newValue);
29.42 + if (!containsValue(c.getHistory(), newValue)) {
29.43 + History h = new History();
29.44 + h.setValue(newValue);
29.45 + h.setOperation(c.getOperation());
29.46 + c.getHistory().add(h);
29.47 + }
29.48 c.setMemory(0);
29.49 }
29.50
29.51 + @OnFunction
29.52 + static void recoverMemory(Calculator c, History data) {
29.53 + c.setDisplay(data.getValue());
29.54 + }
29.55 +
29.56 + @OnFunction
29.57 + static void removeMemory(Calculator c, History data) {
29.58 + c.getHistory().remove(data);
29.59 + }
29.60 +
29.61 private static double compute(String op, double memory, double display) {
29.62 switch (op) {
29.63 case "plus": return memory + display;
29.64 @@ -109,4 +129,18 @@
29.65 }
29.66 return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display);
29.67 }
29.68 +
29.69 + @ComputedProperty
29.70 + static boolean emptyHistory(List<?> history) {
29.71 + return history.isEmpty();
29.72 + }
29.73 +
29.74 + private static boolean containsValue(List<History> arr, final double newValue) {
29.75 + for (History history : arr) {
29.76 + if (history.getValue() == newValue) {
29.77 + return true;
29.78 + }
29.79 + }
29.80 + return false;
29.81 + }
29.82 }
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/HistoryImpl.java Thu Apr 11 16:59:42 2013 +0200
30.3 @@ -0,0 +1,43 @@
30.4 +/**
30.5 + * Back 2 Browser Bytecode Translator
30.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
30.7 + *
30.8 + * This program is free software: you can redistribute it and/or modify
30.9 + * it under the terms of the GNU General Public License as published by
30.10 + * the Free Software Foundation, version 2 of the License.
30.11 + *
30.12 + * This program is distributed in the hope that it will be useful,
30.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
30.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30.15 + * GNU General Public License for more details.
30.16 + *
30.17 + * You should have received a copy of the GNU General Public License
30.18 + * along with this program. Look for COPYING file in the top folder.
30.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
30.20 + */
30.21 +package org.apidesign.bck2brwsr.demo.calc;
30.22 +
30.23 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
30.24 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
30.25 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
30.26 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
30.27 +
30.28 +/**
30.29 + *
30.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
30.31 + */
30.32 +@Model(className = "History", properties = {
30.33 + @Property(name = "value", type = double.class),
30.34 + @Property(name = "operation", type = String.class)
30.35 +})
30.36 +public class HistoryImpl {
30.37 + @ComputedProperty
30.38 + static String resultOf(String operation) {
30.39 + return "result of " + operation;
30.40 + }
30.41 +
30.42 + @OnFunction
30.43 + static void twice(History data) {
30.44 + data.setValue(2.0 * data.getValue());
30.45 + }
30.46 +}
31.1 --- a/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Mon Mar 25 13:29:42 2013 +0100
31.2 +++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml Thu Apr 11 16:59:42 2013 +0200
31.3 @@ -78,6 +78,19 @@
31.4 </table>
31.5 <div data-bind="text: displayPreview"></div>
31.6
31.7 + <h4>Previous Results</h4>
31.8 +
31.9 + <div data-bind="if: emptyHistory">No results yet.</div>
31.10 + <ul data-bind="foreach: history">
31.11 + <li>
31.12 + <span data-bind="text: $data.value"></span> -
31.13 + <a href="#" data-bind="click: $root.recoverMemory">Use</a>
31.14 + <a href="#" data-bind="click: $root.removeMemory">Remove</a>
31.15 + <a href="#" data-bind="click: $data.twice">Double</a> -
31.16 + <span data-bind="text: $data.resultOf"></span>
31.17 + </li>
31.18 + </ul>
31.19 +
31.20 <script src="bck2brwsr.js"></script>
31.21 <script type="text/javascript">
31.22 var vm = bck2brwsr('demo.calculator-0.5-SNAPSHOT.jar');
31.23 @@ -85,75 +98,5 @@
31.24 </script>
31.25
31.26 <hr/>
31.27 - <pre>
31.28 - <span class="keyword-directive">package</span> org.apidesign.bck2brwsr.mavenhtml;
31.29 -
31.30 - <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.OnClick;
31.31 - <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.Page;
31.32 -
31.33 - <span class="comment">/**</span> <span class="comment">HTML5</span><span class="comment"> & </span><span class="comment">Java</span> <span class="comment">demo</span> <span class="comment">showing</span> <span class="comment">the</span> <span class="comment">power</span> <span class="comment">of</span> <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation processors</a>
31.34 - <span class="comment"> * </span><span class="comment">as</span> <span class="comment">well</span> <span class="comment">as</span> <span class="comment">other</span> <span class="comment">goodies</span><span class="comment">, including type-safe association between</span>
31.35 - <span class="comment"> * </span><span class="comment">an XHTML page and Java.</span>
31.36 - <span class="comment"> * </span>
31.37 - <span class="comment"> * </span><span class="ST1">@author</span> <span class="comment">Jaroslav</span> <span class="comment">Tulach</span> <span class="ST0"><jaroslav.tulach@apidesign.org></span>
31.38 - <span class="comment">*/</span>
31.39 - @Page(xhtml=<span class="string">"</span><span class="string">Calculator.xhtml</span><span class="string">"</span>)
31.40 - <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> App {
31.41 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> memory;
31.42 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> String operation;
31.43 -
31.44 - @OnClick(id=<span class="string">"</span><span class="string">clear</span><span class="string">"</span>)
31.45 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> clear() {
31.46 - memory = <span class="number">0</span>;
31.47 - operation = <span class="keyword-directive">null</span>;
31.48 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">0</span><span class="string">"</span>);
31.49 - }
31.50 -
31.51 - @OnClick(id= { <span class="string">"</span><span class="string">plus</span><span class="string">"</span>, <span class="string">"</span><span class="string">minus</span><span class="string">"</span>, <span class="string">"</span><span class="string">mul</span><span class="string">"</span>, <span class="string">"</span><span class="string">div</span><span class="string">"</span> })
31.52 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> applyOp(String op) {
31.53 - memory = getValue();
31.54 - operation = op;
31.55 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">0</span><span class="string">"</span>);
31.56 - }
31.57 -
31.58 - @OnClick(id=<span class="string">"</span><span class="string">result</span><span class="string">"</span>)
31.59 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> computeTheValue() {
31.60 - <span class="keyword-directive">switch</span> (operation) {
31.61 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">plus</span><span class="string">"</span>: setValue(memory + getValue()); <span class="keyword-directive">break</span>;
31.62 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">minus</span><span class="string">"</span>: setValue(memory - getValue()); <span class="keyword-directive">break</span>;
31.63 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">mul</span><span class="string">"</span>: setValue(memory * getValue()); <span class="keyword-directive">break</span>;
31.64 - <span class="keyword-directive">case</span> <span class="string">"</span><span class="string">div</span><span class="string">"</span>: setValue(memory / getValue()); <span class="keyword-directive">break</span>;
31.65 - <span class="keyword-directive">default</span>: <span class="keyword-directive">throw</span> <span class="keyword-directive">new</span> IllegalStateException(operation);
31.66 - }
31.67 - }
31.68 -
31.69 - @OnClick(id={<span class="string">"</span><span class="string">n0</span><span class="string">"</span>, <span class="string">"</span><span class="string">n1</span><span class="string">"</span>, <span class="string">"</span><span class="string">n2</span><span class="string">"</span>, <span class="string">"</span><span class="string">n3</span><span class="string">"</span>, <span class="string">"</span><span class="string">n4</span><span class="string">"</span>, <span class="string">"</span><span class="string">n5</span><span class="string">"</span>, <span class="string">"</span><span class="string">n6</span><span class="string">"</span>, <span class="string">"</span><span class="string">n7</span><span class="string">"</span>, <span class="string">"</span><span class="string">n8</span><span class="string">"</span>, <span class="string">"</span><span class="string">n9</span><span class="string">"</span>})
31.70 - <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> addDigit(String digit) {
31.71 - digit = digit.substring(<span class="number">1</span>);
31.72 - String v = Calculator.DISPLAY.getValue();
31.73 - <span class="keyword-directive">if</span> (getValue() == <span class="number">0.0</span>) {
31.74 - Calculator.DISPLAY.setValue(digit);
31.75 - } <span class="keyword-directive">else</span> {
31.76 - Calculator.DISPLAY.setValue(v + digit);
31.77 - }
31.78 - }
31.79 -
31.80 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> setValue(<span class="keyword-directive">double</span> v) {
31.81 - StringBuilder sb = <span class="keyword-directive">new</span> StringBuilder();
31.82 - sb.append(v);
31.83 - Calculator.DISPLAY.setValue(sb.toString());
31.84 - }
31.85 -
31.86 - <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> getValue() {
31.87 - <span class="keyword-directive">try</span> {
31.88 - <span class="keyword-directive">return</span> Double.parseDouble(Calculator.DISPLAY.getValue());
31.89 - } <span class="keyword-directive">catch</span> (NumberFormatException ex) {
31.90 - Calculator.DISPLAY.setValue(<span class="string">"</span><span class="string">err</span><span class="string">"</span>);
31.91 - <span class="keyword-directive">return</span> <span class="number">0.0</span>;
31.92 - }
31.93 - }
31.94 - }
31.95 -
31.96 - </pre>
31.97 </body>
31.98 </html>
32.1 --- a/javaquery/demo-calculator/pom.xml Mon Mar 25 13:29:42 2013 +0100
32.2 +++ b/javaquery/demo-calculator/pom.xml Thu Apr 11 16:59:42 2013 +0200
32.3 @@ -4,7 +4,7 @@
32.4
32.5 <groupId>org.apidesign.bck2brwsr</groupId>
32.6 <artifactId>demo.static.calculator</artifactId>
32.7 - <version>0.5-SNAPSHOT</version>
32.8 + <version>0.6-SNAPSHOT</version>
32.9 <packaging>jar</packaging>
32.10
32.11 <name>JavaQuery Demo - Calculator - Static Compilation</name>
32.12 @@ -12,13 +12,14 @@
32.13
32.14 <properties>
32.15 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
32.16 + <bck2brwsr.obfuscationlevel>FULL</bck2brwsr.obfuscationlevel>
32.17 </properties>
32.18 <build>
32.19 <plugins>
32.20 <plugin>
32.21 <groupId>org.apidesign.bck2brwsr</groupId>
32.22 <artifactId>mojo</artifactId>
32.23 - <version>0.5-SNAPSHOT</version>
32.24 + <version>0.6-SNAPSHOT</version>
32.25 <executions>
32.26 <execution>
32.27 <goals>
32.28 @@ -31,7 +32,7 @@
32.29 <directory>${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html/</directory>
32.30 <startpage>index.xhtml</startpage>
32.31 <javascript>${project.build.directory}/bck2brwsr.js</javascript>
32.32 - <obfuscation>FULL</obfuscation>
32.33 + <obfuscation>${bck2brwsr.obfuscationlevel}</obfuscation>
32.34 </configuration>
32.35 </plugin>
32.36 <plugin>
32.37 @@ -97,13 +98,13 @@
32.38 <dependency>
32.39 <groupId>org.apidesign.bck2brwsr</groupId>
32.40 <artifactId>emul</artifactId>
32.41 - <version>0.5-SNAPSHOT</version>
32.42 + <version>0.6-SNAPSHOT</version>
32.43 <classifier>rt</classifier>
32.44 </dependency>
32.45 <dependency>
32.46 <groupId>org.apidesign.bck2brwsr</groupId>
32.47 <artifactId>javaquery.api</artifactId>
32.48 - <version>0.5-SNAPSHOT</version>
32.49 + <version>0.6-SNAPSHOT</version>
32.50 </dependency>
32.51 </dependencies>
32.52 </project>
33.1 --- a/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java Mon Mar 25 13:29:42 2013 +0100
33.2 +++ b/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java Thu Apr 11 16:59:42 2013 +0200
33.3 @@ -17,9 +17,11 @@
33.4 */
33.5 package org.apidesign.bck2brwsr.demo.calc.staticcompilation;
33.6
33.7 +import java.util.List;
33.8 import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
33.9 import org.apidesign.bck2brwsr.htmlpage.api.On;
33.10 import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
33.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
33.12 import org.apidesign.bck2brwsr.htmlpage.api.Page;
33.13 import org.apidesign.bck2brwsr.htmlpage.api.Property;
33.14
33.15 @@ -33,11 +35,12 @@
33.16 @Property(name = "memory", type = double.class),
33.17 @Property(name = "display", type = double.class),
33.18 @Property(name = "operation", type = String.class),
33.19 - @Property(name = "hover", type = boolean.class)
33.20 + @Property(name = "hover", type = boolean.class),
33.21 + @Property(name = "history", type = double.class, array = true)
33.22 })
33.23 public class Calc {
33.24 static {
33.25 - new Calculator().applyBindings();
33.26 + new Calculator().applyBindings().setOperation("plus");
33.27 }
33.28
33.29 @On(event = CLICK, id="clear")
33.30 @@ -65,14 +68,28 @@
33.31
33.32 @On(event = CLICK, id="result")
33.33 static void computeTheValue(Calculator c) {
33.34 - c.setDisplay(compute(
33.35 + final double newValue = compute(
33.36 c.getOperation(),
33.37 c.getMemory(),
33.38 c.getDisplay()
33.39 - ));
33.40 + );
33.41 + c.setDisplay(newValue);
33.42 + if (!c.getHistory().contains(newValue)) {
33.43 + c.getHistory().add(newValue);
33.44 + }
33.45 c.setMemory(0);
33.46 }
33.47
33.48 + @OnFunction
33.49 + static void recoverMemory(Calculator c, double data) {
33.50 + c.setDisplay(data);
33.51 + }
33.52 +
33.53 + @OnFunction
33.54 + static void removeMemory(Calculator c, double data) {
33.55 + c.getHistory().remove(data);
33.56 + }
33.57 +
33.58 private static double compute(String op, double memory, double display) {
33.59 switch (op) {
33.60 case "plus": return memory + display;
33.61 @@ -109,4 +126,9 @@
33.62 }
33.63 return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display);
33.64 }
33.65 +
33.66 + @ComputedProperty
33.67 + static boolean emptyHistory(List<?> history) {
33.68 + return history.isEmpty();
33.69 + }
33.70 }
34.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Mon Mar 25 13:29:42 2013 +0100
34.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml Thu Apr 11 16:59:42 2013 +0200
34.3 @@ -76,8 +76,20 @@
34.4 </tr>
34.5 </tbody>
34.6 </table>
34.7 +
34.8 + <h4>Previous Results</h4>
34.9 +
34.10 + <div data-bind="if: emptyHistory">No results yet.</div>
34.11 + <ul data-bind="foreach: history">
34.12 + <li>
34.13 + <span data-bind="text: $data"></span> -
34.14 + <a href="#" data-bind="click: $root.recoverMemory">Use</a>
34.15 + <a href="#" data-bind="click: $root.removeMemory">Remove</a>
34.16 + </li>
34.17 + </ul>
34.18 +
34.19 <div data-bind="text: displayPreview"></div>
34.20 - <script src="bck2brwsr.js"/>
34.21 + <script src="bck2brwsr.js"></script>
34.22 <script>
34.23 var vm = bck2brwsr('demo.static.calculator-0.5-SNAPSHOT.jar');
34.24 vm.loadClass('org.apidesign.bck2brwsr.demo.calc.staticcompilation.Calc');
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/javaquery/demo-twitter/bck2brwsr-assembly.xml Thu Apr 11 16:59:42 2013 +0200
35.3 @@ -0,0 +1,62 @@
35.4 +<?xml version="1.0"?>
35.5 +<!--
35.6 +
35.7 + Back 2 Browser Bytecode Translator
35.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
35.9 +
35.10 + This program is free software: you can redistribute it and/or modify
35.11 + it under the terms of the GNU General Public License as published by
35.12 + the Free Software Foundation, version 2 of the License.
35.13 +
35.14 + This program is distributed in the hope that it will be useful,
35.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
35.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35.17 + GNU General Public License for more details.
35.18 +
35.19 + You should have received a copy of the GNU General Public License
35.20 + along with this program. Look for COPYING file in the top folder.
35.21 + If not, see http://opensource.org/licenses/GPL-2.0.
35.22 +
35.23 +-->
35.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
35.25 + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
35.26 +
35.27 + <id>bck2brwsr</id>
35.28 + <formats>
35.29 + <format>zip</format>
35.30 + </formats>
35.31 + <baseDirectory>public_html</baseDirectory>
35.32 + <dependencySets>
35.33 + <dependencySet>
35.34 + <useProjectArtifact>false</useProjectArtifact>
35.35 + <scope>runtime</scope>
35.36 + <outputDirectory>lib</outputDirectory>
35.37 + <includes>
35.38 + <include>*:jar</include>
35.39 + <include>*:rt</include>
35.40 + </includes>
35.41 + </dependencySet>
35.42 + </dependencySets>
35.43 + <fileSets>
35.44 + <fileSet>
35.45 + <directory>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/twitter/</directory>
35.46 + <includes>
35.47 + <include>**/*</include>
35.48 + </includes>
35.49 + <excludes>
35.50 + <exclude>**/*.class</exclude>
35.51 + </excludes>
35.52 + <outputDirectory>/</outputDirectory>
35.53 + </fileSet>
35.54 + </fileSets>
35.55 + <files>
35.56 + <file>
35.57 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
35.58 + <outputDirectory>/</outputDirectory>
35.59 + </file>
35.60 + <file>
35.61 + <source>${project.build.directory}/bck2brwsr.js</source>
35.62 + <outputDirectory>/</outputDirectory>
35.63 + </file>
35.64 + </files>
35.65 +</assembly>
35.66 \ No newline at end of file
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/javaquery/demo-twitter/nb-configuration.xml Thu Apr 11 16:59:42 2013 +0200
36.3 @@ -0,0 +1,37 @@
36.4 +<?xml version="1.0" encoding="UTF-8"?>
36.5 +<!--
36.6 +
36.7 + Back 2 Browser Bytecode Translator
36.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
36.9 +
36.10 + This program is free software: you can redistribute it and/or modify
36.11 + it under the terms of the GNU General Public License as published by
36.12 + the Free Software Foundation, version 2 of the License.
36.13 +
36.14 + This program is distributed in the hope that it will be useful,
36.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
36.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36.17 + GNU General Public License for more details.
36.18 +
36.19 + You should have received a copy of the GNU General Public License
36.20 + along with this program. Look for COPYING file in the top folder.
36.21 + If not, see http://opensource.org/licenses/GPL-2.0.
36.22 +
36.23 +-->
36.24 +<project-shared-configuration>
36.25 + <!--
36.26 +This file contains additional configuration written by modules in the NetBeans IDE.
36.27 +The configuration is intended to be shared among all the users of project and
36.28 +therefore it is assumed to be part of version control checkout.
36.29 +Without this configuration present, some functionality in the IDE may be limited or fail altogether.
36.30 +-->
36.31 + <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
36.32 + <!--
36.33 +Properties that influence various parts of the IDE, especially code formatting and the like.
36.34 +You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
36.35 +That way multiple projects can share the same settings (useful for formatting rules for example).
36.36 +Any value defined here will override the pom.xml file value but is only applicable to the current project.
36.37 +-->
36.38 + <netbeans.compile.on.save>none</netbeans.compile.on.save>
36.39 + </properties>
36.40 +</project-shared-configuration>
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/javaquery/demo-twitter/nbactions.xml Thu Apr 11 16:59:42 2013 +0200
37.3 @@ -0,0 +1,29 @@
37.4 +<?xml version="1.0" encoding="UTF-8"?>
37.5 +<!--
37.6 +
37.7 + Back 2 Browser Bytecode Translator
37.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
37.9 +
37.10 + This program is free software: you can redistribute it and/or modify
37.11 + it under the terms of the GNU General Public License as published by
37.12 + the Free Software Foundation, version 2 of the License.
37.13 +
37.14 + This program is distributed in the hope that it will be useful,
37.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
37.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37.17 + GNU General Public License for more details.
37.18 +
37.19 + You should have received a copy of the GNU General Public License
37.20 + along with this program. Look for COPYING file in the top folder.
37.21 + If not, see http://opensource.org/licenses/GPL-2.0.
37.22 +
37.23 +-->
37.24 +<actions>
37.25 + <action>
37.26 + <actionName>run</actionName>
37.27 + <goals>
37.28 + <goal>process-classes</goal>
37.29 + <goal>org.apidesign.bck2brwsr:mojo:0.6-SNAPSHOT:brwsr</goal>
37.30 + </goals>
37.31 + </action>
37.32 +</actions>
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/javaquery/demo-twitter/pom.xml Thu Apr 11 16:59:42 2013 +0200
38.3 @@ -0,0 +1,137 @@
38.4 +<?xml version="1.0" encoding="UTF-8"?>
38.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
38.6 + <modelVersion>4.0.0</modelVersion>
38.7 + <parent>
38.8 + <artifactId>javaquery</artifactId>
38.9 + <groupId>org.apidesign.bck2brwsr</groupId>
38.10 + <version>0.6-SNAPSHOT</version>
38.11 + </parent>
38.12 +
38.13 + <groupId>org.apidesign.bck2brwsr</groupId>
38.14 + <artifactId>demo-twitter</artifactId>
38.15 + <version>0.6-SNAPSHOT</version>
38.16 + <packaging>jar</packaging>
38.17 +
38.18 + <name>Bck2Brwsr's Twttr</name>
38.19 + <description>
38.20 + Rewrite of knockoutjs example to use model written in Java and
38.21 + execute using Bck2Brwsr virtual machine.
38.22 + </description>
38.23 +
38.24 + <repositories>
38.25 + <repository>
38.26 + <id>java.net</id>
38.27 + <name>Java.net</name>
38.28 + <url>https://maven.java.net/content/repositories/releases/</url>
38.29 + <snapshots>
38.30 + </snapshots>
38.31 + </repository>
38.32 + <repository>
38.33 + <id>netbeans</id>
38.34 + <name>NetBeans</name>
38.35 + <url>http://bits.netbeans.org/maven2/</url>
38.36 + </repository>
38.37 + </repositories>
38.38 + <pluginRepositories>
38.39 + <pluginRepository>
38.40 + <id>java.net</id>
38.41 + <name>Java.net</name>
38.42 + <url>https://maven.java.net/content/repositories/releases/</url>
38.43 + <snapshots>
38.44 + </snapshots>
38.45 + </pluginRepository>
38.46 + </pluginRepositories>
38.47 +
38.48 + <properties>
38.49 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
38.50 + <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
38.51 + </properties>
38.52 + <build>
38.53 + <plugins>
38.54 + <plugin>
38.55 + <groupId>org.apidesign.bck2brwsr</groupId>
38.56 + <artifactId>mojo</artifactId>
38.57 + <version>0.6-SNAPSHOT</version>
38.58 + <executions>
38.59 + <execution>
38.60 + <goals>
38.61 + <goal>brwsr</goal>
38.62 + <goal>j2js</goal>
38.63 + </goals>
38.64 + </execution>
38.65 + </executions>
38.66 + <configuration>
38.67 + <startpage>org/apidesign/bck2brwsr/demo/twitter/index.html</startpage>
38.68 + <javascript>${project.build.directory}/bck2brwsr.js</javascript>
38.69 + <obfuscation>${bck2brwsr.obfuscationlevel}</obfuscation>
38.70 + </configuration>
38.71 + </plugin>
38.72 + <plugin>
38.73 + <groupId>org.apache.maven.plugins</groupId>
38.74 + <artifactId>maven-compiler-plugin</artifactId>
38.75 + <version>2.3.2</version>
38.76 + <configuration>
38.77 + <source>1.7</source>
38.78 + <target>1.7</target>
38.79 + </configuration>
38.80 + </plugin>
38.81 + <plugin>
38.82 + <groupId>org.apache.maven.plugins</groupId>
38.83 + <artifactId>maven-jar-plugin</artifactId>
38.84 + <version>2.4</version>
38.85 + <configuration>
38.86 + <archive>
38.87 + <manifest>
38.88 + <addClasspath>true</addClasspath>
38.89 + <classpathPrefix>lib/</classpathPrefix>
38.90 + </manifest>
38.91 + </archive>
38.92 + </configuration>
38.93 + </plugin>
38.94 + <plugin>
38.95 + <artifactId>maven-assembly-plugin</artifactId>
38.96 + <version>2.4</version>
38.97 + <executions>
38.98 + <execution>
38.99 + <id>distro-assembly</id>
38.100 + <phase>package</phase>
38.101 + <goals>
38.102 + <goal>single</goal>
38.103 + </goals>
38.104 + <configuration>
38.105 + <descriptors>
38.106 + <descriptor>bck2brwsr-assembly.xml</descriptor>
38.107 + </descriptors>
38.108 + </configuration>
38.109 + </execution>
38.110 + </executions>
38.111 + </plugin>
38.112 + </plugins>
38.113 + </build>
38.114 +
38.115 + <dependencies>
38.116 + <dependency>
38.117 + <groupId>org.apidesign.bck2brwsr</groupId>
38.118 + <artifactId>emul</artifactId>
38.119 + <version>0.6-SNAPSHOT</version>
38.120 + <classifier>rt</classifier>
38.121 + </dependency>
38.122 + <dependency>
38.123 + <groupId>org.apidesign.bck2brwsr</groupId>
38.124 + <artifactId>javaquery.api</artifactId>
38.125 + <version>0.6-SNAPSHOT</version>
38.126 + </dependency>
38.127 + <dependency>
38.128 + <groupId>org.testng</groupId>
38.129 + <artifactId>testng</artifactId>
38.130 + <version>6.5.2</version>
38.131 + <scope>test</scope>
38.132 + </dependency>
38.133 + <dependency>
38.134 + <groupId>org.apidesign.bck2brwsr</groupId>
38.135 + <artifactId>vmtest</artifactId>
38.136 + <version>0.6-SNAPSHOT</version>
38.137 + <scope>test</scope>
38.138 + </dependency>
38.139 + </dependencies>
38.140 +</project>
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java Thu Apr 11 16:59:42 2013 +0200
39.3 @@ -0,0 +1,194 @@
39.4 +/**
39.5 + * Back 2 Browser Bytecode Translator
39.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
39.7 + *
39.8 + * This program is free software: you can redistribute it and/or modify
39.9 + * it under the terms of the GNU General Public License as published by
39.10 + * the Free Software Foundation, version 2 of the License.
39.11 + *
39.12 + * This program is distributed in the hope that it will be useful,
39.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
39.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39.15 + * GNU General Public License for more details.
39.16 + *
39.17 + * You should have received a copy of the GNU General Public License
39.18 + * along with this program. Look for COPYING file in the top folder.
39.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
39.20 + */
39.21 +package org.apidesign.bck2brwsr.demo.twitter;
39.22 +
39.23 +import java.util.Arrays;
39.24 +import java.util.List;
39.25 +import org.apidesign.bck2brwsr.htmlpage.api.*;
39.26 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
39.27 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
39.28 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
39.29 +
39.30 +/** Controller class for access to Twitter.
39.31 + *
39.32 + * @author Jaroslav Tulach
39.33 + */
39.34 +@Page(xhtml="index.html", className="TwitterModel", properties={
39.35 + @Property(name="savedLists", type=Tweeters.class, array = true),
39.36 + @Property(name="activeTweetersName", type=String.class),
39.37 + @Property(name="activeTweeters", type=String.class, array = true),
39.38 + @Property(name="userNameToAdd", type=String.class),
39.39 + @Property(name="currentTweets", type=Tweet.class, array = true)
39.40 +})
39.41 +public class TwitterClient {
39.42 + @Model(className = "Tweeters", properties = {
39.43 + @Property(name="name", type = String.class),
39.44 + @Property(name="userNames", type = String.class, array = true)
39.45 + })
39.46 + static class Twttrs {
39.47 + }
39.48 + @Model(className = "Tweet", properties = {
39.49 + @Property(name = "from_user", type = String.class),
39.50 + @Property(name = "from_user_id", type = int.class),
39.51 + @Property(name = "profile_image_url", type = String.class),
39.52 + @Property(name = "text", type = String.class),
39.53 + @Property(name = "created_at", type = String.class),
39.54 + })
39.55 + static final class Twt {
39.56 + @ComputedProperty static String html(String text) {
39.57 + StringBuilder sb = new StringBuilder(320);
39.58 + for (int pos = 0;;) {
39.59 + int http = text.indexOf("http", pos);
39.60 + if (http == -1) {
39.61 + sb.append(text.substring(pos));
39.62 + return sb.toString();
39.63 + }
39.64 + int spc = text.indexOf(' ', http);
39.65 + if (spc == -1) {
39.66 + spc = text.length();
39.67 + }
39.68 + sb.append(text.substring(pos, http));
39.69 + String url = text.substring(http, spc);
39.70 + sb.append("<a href='").append(url).append("'>").append(url).append("</a>");
39.71 + pos = spc;
39.72 + }
39.73 + }
39.74 +
39.75 + @ComputedProperty static String userUrl(String from_user) {
39.76 + return "http://twitter.com/" + from_user;
39.77 + }
39.78 + }
39.79 + @Model(className = "TwitterQuery", properties = {
39.80 + @Property(array = true, name = "results", type = Twt.class)
39.81 + })
39.82 + public static final class TwttrQr {
39.83 + }
39.84 +
39.85 + @OnReceive(url="{root}/search.json?{query}&callback={me}", jsonp="me")
39.86 + static void queryTweets(TwitterModel page, TwitterQuery q) {
39.87 + page.getCurrentTweets().clear();
39.88 + page.getCurrentTweets().addAll(q.getResults());
39.89 + }
39.90 +
39.91 + @OnPropertyChange("activeTweetersName")
39.92 + static void changeTweetersList(TwitterModel model) {
39.93 + Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName());
39.94 + model.getActiveTweeters().clear();
39.95 + model.getActiveTweeters().addAll(people.getUserNames());
39.96 + }
39.97 +
39.98 + @OnPropertyChange({ "activeTweeters", "activeTweetersCount" })
39.99 + static void refreshTweets(TwitterModel model) {
39.100 + StringBuilder sb = new StringBuilder();
39.101 + sb.append("rpp=25&q=");
39.102 + String sep = "";
39.103 + for (String p : model.getActiveTweeters()) {
39.104 + sb.append(sep);
39.105 + sb.append("from:");
39.106 + sb.append(p);
39.107 + sep = " OR ";
39.108 + }
39.109 + model.queryTweets("http://search.twitter.com", sb.toString());
39.110 + }
39.111 +
39.112 + static {
39.113 + final TwitterModel model = new TwitterModel();
39.114 + final List<Tweeters> svdLst = model.getSavedLists();
39.115 + svdLst.add(newTweeters("API Design", "JaroslavTulach"));
39.116 + svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
39.117 + svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
39.118 + svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka"));
39.119 + svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
39.120 +
39.121 + model.setActiveTweetersName("NetBeans");
39.122 +
39.123 + model.applyBindings();
39.124 + }
39.125 +
39.126 + @ComputedProperty
39.127 + static boolean hasUnsavedChanges(List<String> activeTweeters, List<Tweeters> savedLists, String activeTweetersName) {
39.128 + Tweeters tw = findByName(savedLists, activeTweetersName);
39.129 + if (activeTweeters == null) {
39.130 + return false;
39.131 + }
39.132 + return !tw.getUserNames().equals(activeTweeters);
39.133 + }
39.134 +
39.135 + @ComputedProperty
39.136 + static int activeTweetersCount(List<String> activeTweeters) {
39.137 + return activeTweeters.size();
39.138 + }
39.139 +
39.140 + @ComputedProperty
39.141 + static boolean userNameToAddIsValid(
39.142 + String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, List<String> activeTweeters
39.143 + ) {
39.144 + return userNameToAdd != null &&
39.145 + userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") &&
39.146 + !activeTweeters.contains(userNameToAdd);
39.147 + }
39.148 +
39.149 + @OnFunction
39.150 + static void deleteList(TwitterModel model) {
39.151 + final List<Tweeters> sl = model.getSavedLists();
39.152 + sl.remove(findByName(sl, model.getActiveTweetersName()));
39.153 + if (sl.isEmpty()) {
39.154 + final Tweeters t = new Tweeters();
39.155 + t.setName("New");
39.156 + sl.add(t);
39.157 + }
39.158 + model.setActiveTweetersName(sl.get(0).getName());
39.159 + }
39.160 +
39.161 + @OnFunction
39.162 + static void saveChanges(TwitterModel model) {
39.163 + Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName());
39.164 + int indx = model.getSavedLists().indexOf(t);
39.165 + if (indx != -1) {
39.166 + t.setName(model.getActiveTweetersName());
39.167 + t.getUserNames().clear();
39.168 + t.getUserNames().addAll(model.getActiveTweeters());
39.169 + }
39.170 + }
39.171 +
39.172 + @OnFunction
39.173 + static void addUser(TwitterModel model) {
39.174 + String n = model.getUserNameToAdd();
39.175 + model.getActiveTweeters().add(n);
39.176 + }
39.177 + @OnFunction
39.178 + static void removeUser(String data, TwitterModel model) {
39.179 + model.getActiveTweeters().remove(data);
39.180 + }
39.181 +
39.182 + private static Tweeters findByName(List<Tweeters> list, String name) {
39.183 + for (Tweeters l : list) {
39.184 + if (l.getName() != null && l.getName().equals(name)) {
39.185 + return l;
39.186 + }
39.187 + }
39.188 + return list.isEmpty() ? new Tweeters() : list.get(0);
39.189 + }
39.190 +
39.191 + private static Tweeters newTweeters(String listName, String... userNames) {
39.192 + Tweeters t = new Tweeters();
39.193 + t.setName(listName);
39.194 + t.getUserNames().addAll(Arrays.asList(userNames));
39.195 + return t;
39.196 + }
39.197 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html Thu Apr 11 16:59:42 2013 +0200
40.3 @@ -0,0 +1,99 @@
40.4 +<?xml version="1.0" encoding="UTF-8"?>
40.5 +<!--
40.6 +
40.7 + Back 2 Browser Bytecode Translator
40.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
40.9 +
40.10 + This program is free software: you can redistribute it and/or modify
40.11 + it under the terms of the GNU General Public License as published by
40.12 + the Free Software Foundation, version 2 of the License.
40.13 +
40.14 + This program is distributed in the hope that it will be useful,
40.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
40.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40.17 + GNU General Public License for more details.
40.18 +
40.19 + You should have received a copy of the GNU General Public License
40.20 + along with this program. Look for COPYING file in the top folder.
40.21 + If not, see http://opensource.org/licenses/GPL-2.0.
40.22 +
40.23 +-->
40.24 +
40.25 +<!--
40.26 + Copied from knockout.js Twitter example:
40.27 + http://knockoutjs.com/examples/twitter.html
40.28 +-->
40.29 +
40.30 +<!DOCTYPE html>
40.31 +<html xmlns="http://www.w3.org/1999/xhtml">
40.32 + <head>
40.33 + <title>Bck2Brwsr's Twitter</title>
40.34 + </head>
40.35 + <body>
40.36 + <link href='twitterExample.css' rel='Stylesheet' ></link>
40.37 +
40.38 + <style type='text/css'>
40.39 + .liveExample select { height: 1.7em; }
40.40 + .liveExample button { height: 2em; }
40.41 + </style>
40.42 +
40.43 +
40.44 + <h2>Bck2Brwsr's Twitter</h2>
40.45 +
40.46 + <p>
40.47 + This code based on original <a href="http://knockoutjs.com/examples/twitter.html">knockout.js Twitter example</a> and
40.48 + uses almost unmodified HTML code. It just changes the model. It
40.49 + is written in Java language and it is executed using <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
40.50 + virtual machine. The Java source code has about 190 lines and is available
40.51 + <a href="http://source.apidesign.org/hg/bck2brwsr/file/7fc6b7e9c982/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java">here</a>
40.52 + - in fact it may even be more dense than the original JavaScript model.
40.53 + </p>
40.54 +
40.55 + <div class='liveExample'>
40.56 + <div class='configuration'>
40.57 + <div class='listChooser'>
40.58 + <button data-bind='click: deleteList, enable: activeTweetersName'>Delete</button>
40.59 + <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>Save</button>
40.60 + <select data-bind='options: savedLists, optionsValue: "name", value: activeTweetersName'> </select>
40.61 + </div>
40.62 +
40.63 + <p>Currently viewing <span data-bind='text: activeTweetersCount'> </span> user(s):</p>
40.64 + <div class='currentUsers' >
40.65 + <ul data-bind='foreach: activeTweeters'>
40.66 + <li>
40.67 + <button data-bind='click: $root.removeUser'>Remove</button>
40.68 + <div data-bind='text: $data'> </div>
40.69 + </li>
40.70 + </ul>
40.71 + </div>
40.72 +
40.73 + <form data-bind='submit: addUser'>
40.74 + <label>Add user:</label>
40.75 + <input data-bind='value: userNameToAdd, valueUpdate: "keyup", css: { invalid: !userNameToAddIsValid() }' />
40.76 + <button data-bind='enable: userNameToAddIsValid' type='submit'>Add</button>
40.77 + </form>
40.78 + </div>
40.79 + <div class='tweets'>
40.80 + <div class='loadingIndicator'>Loading...</div>
40.81 + <table data-bind='foreach: currentTweets' width='100%'>
40.82 + <tr>
40.83 + <td><img data-bind='attr: { src: profile_image_url }' /></td>
40.84 + <td>
40.85 + <a class='twitterUser' data-bind='attr: { href: userUrl }, text: from_user'> </a>
40.86 + <span data-bind='html: html'> </span>
40.87 + <div class='tweetInfo' data-bind='text: created_at'> </div>
40.88 + </td>
40.89 + </tr>
40.90 + </table>
40.91 + </div>
40.92 + </div>
40.93 +
40.94 + <script src="bck2brwsr.js"></script>
40.95 + <script type="text/javascript">
40.96 + var vm = bck2brwsr('demo-twitter-0.6-SNAPSHOT.jar');
40.97 + vm.loadClass('org.apidesign.bck2brwsr.demo.twitter.TwitterClient');
40.98 + </script>
40.99 +
40.100 +
40.101 + </body>
40.102 +</html>
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/twitterExample.css Thu Apr 11 16:59:42 2013 +0200
41.3 @@ -0,0 +1,50 @@
41.4 +/**
41.5 + * Back 2 Browser Bytecode Translator
41.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
41.7 + *
41.8 + * This program is free software: you can redistribute it and/or modify
41.9 + * it under the terms of the GNU General Public License as published by
41.10 + * the Free Software Foundation, version 2 of the License.
41.11 + *
41.12 + * This program is distributed in the hope that it will be useful,
41.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
41.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41.15 + * GNU General Public License for more details.
41.16 + *
41.17 + * You should have received a copy of the GNU General Public License
41.18 + * along with this program. Look for COPYING file in the top folder.
41.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
41.20 + */
41.21 +
41.22 +/*
41.23 + Copied from knockout.js Twitter example:
41.24 + http://knockoutjs.com/examples/twitter.html
41.25 +*/
41.26 +
41.27 +.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; }
41.28 +.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; }
41.29 +.tweets { width: 55%; border: 2px solid gray; height: 40em; overflow: scroll; overflow-x: hidden; background-color: Black; color: White; padding: 0.5em; position: relative; }
41.30 +.tweets table { border-width: 0;}
41.31 +.tweets tr { vertical-align: top; }
41.32 +.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; }
41.33 +.tweets img { width: 4em; }
41.34 +.tweetInfo { color: Gray; font-size: 0.9em; }
41.35 +.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; }
41.36 +input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; }
41.37 +
41.38 +.listChooser select, .listChooser button { vertical-align:top; }
41.39 +.listChooser select { width: 60%; font-size:1.2em; height:1.4em; }
41.40 +.listChooser button { width: 19%; height:1.68em; float:right; }
41.41 +
41.42 +.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; }
41.43 +.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; }
41.44 +.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 }
41.45 +.currentUsers li { height: 2.4em; font-size: 1.2em; background-color: #A7D0E3; border: 1px solid gray; margin-bottom: 0.3em; -webkit-border-radius: 5px; -moz-border-radius: 5px; -webkit-box-shadow: 0 0.2em 0.5em gray; -moz-box-shadow: 0 0.2em 0.5em gray; }
41.46 +.currentUsers li div { padding: 0.6em; }
41.47 +.currentUsers li:hover { background-color: #EEC; }
41.48 +
41.49 +.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; }
41.50 +.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; }
41.51 +.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; }
41.52 +
41.53 +.loadingIndicator { position: absolute; top: 0.1em; left: 0.1em; font: 0.8em Arial; background-color: #229; color: White; padding: 0.2em 0.5em 0.2em 0.5em; display: none; }
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java Thu Apr 11 16:59:42 2013 +0200
42.3 @@ -0,0 +1,67 @@
42.4 +/**
42.5 + * Back 2 Browser Bytecode Translator
42.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
42.7 + *
42.8 + * This program is free software: you can redistribute it and/or modify
42.9 + * it under the terms of the GNU General Public License as published by
42.10 + * the Free Software Foundation, version 2 of the License.
42.11 + *
42.12 + * This program is distributed in the hope that it will be useful,
42.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
42.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42.15 + * GNU General Public License for more details.
42.16 + *
42.17 + * You should have received a copy of the GNU General Public License
42.18 + * along with this program. Look for COPYING file in the top folder.
42.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
42.20 + */
42.21 +package org.apidesign.bck2brwsr.demo.twitter;
42.22 +
42.23 +import java.util.List;
42.24 +import static org.testng.Assert.*;
42.25 +import org.testng.annotations.BeforeMethod;
42.26 +import org.testng.annotations.Test;
42.27 +
42.28 +/** We can unit test the TwitterModel smoothly.
42.29 + *
42.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
42.31 + */
42.32 +public class TwitterClientTest {
42.33 + private TwitterModel model;
42.34 +
42.35 +
42.36 + @BeforeMethod
42.37 + public void initModel() {
42.38 + model = new TwitterModel().applyBindings();
42.39 + }
42.40 +
42.41 + @Test public void testIsValidToAdd() {
42.42 + model.setUserNameToAdd("Joe");
42.43 + Tweeters t = new Tweeters();
42.44 + t.setName("test");
42.45 + model.getSavedLists().add(t);
42.46 + model.setActiveTweetersName("test");
42.47 +
42.48 + assertTrue(model.isUserNameToAddIsValid(), "Joe is OK");
42.49 + TwitterClient.addUser(model);
42.50 + assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time");
42.51 + assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty");
42.52 +
42.53 + List<String> mod = model.getActiveTweeters();
42.54 + assertTrue(model.isHasUnsavedChanges(), "We have modifications");
42.55 + assertEquals(mod.size(), 1, "One element in the list");
42.56 + assertEquals(mod.get(0), "Joe", "Its name is Joe");
42.57 +
42.58 + assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one");
42.59 +
42.60 + TwitterClient.saveChanges(model);
42.61 + assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save");
42.62 +
42.63 + assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one");
42.64 + }
42.65 +
42.66 + @Test public void httpAtTheEnd() {
42.67 + String res = TwitterClient.Twt.html("Ahoj http://kuk");
42.68 + assertEquals(res, "Ahoj <a href='http://kuk'>http://kuk</a>");
42.69 + }
42.70 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterProtocolTest.java Thu Apr 11 16:59:42 2013 +0200
43.3 @@ -0,0 +1,94 @@
43.4 +/**
43.5 + * Back 2 Browser Bytecode Translator
43.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
43.7 + *
43.8 + * This program is free software: you can redistribute it and/or modify
43.9 + * it under the terms of the GNU General Public License as published by
43.10 + * the Free Software Foundation, version 2 of the License.
43.11 + *
43.12 + * This program is distributed in the hope that it will be useful,
43.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
43.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43.15 + * GNU General Public License for more details.
43.16 + *
43.17 + * You should have received a copy of the GNU General Public License
43.18 + * along with this program. Look for COPYING file in the top folder.
43.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
43.20 + */
43.21 +package org.apidesign.bck2brwsr.demo.twitter;
43.22 +
43.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
43.24 +import org.apidesign.bck2brwsr.vmtest.Http;
43.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
43.26 +import org.testng.annotations.Factory;
43.27 +
43.28 +/**
43.29 + *
43.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
43.31 + */
43.32 +public class TwitterProtocolTest {
43.33 + private TwitterModel page;
43.34 + @Http(@Http.Resource(
43.35 + path = "/search.json",
43.36 + mimeType = "application/json",
43.37 + parameters = {"callback"},
43.38 + content = "$0({\"completed_in\":0.04,\"max_id\":320055706885689344,\"max_id_str\""
43.39 + + ":\"320055706885689344\",\"page\":1,\"query\":\"from%3AJaroslavTulach\",\"refresh_url\":"
43.40 + + "\"?since_id=320055706885689344&q=from%3AJaroslavTulach\","
43.41 + + "\"results\":[{\"created_at\":\"Fri, 05 Apr 2013 06:10:01 +0000\","
43.42 + + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
43.43 + + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":320055706885689344,"
43.44 + + "\"id_str\":\"320055706885689344\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
43.45 + + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
43.46 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
43.47 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
43.48 + + "\"@tom_enebo Amzng! Not that I would like #ruby, but I am really glad you guys stabilized the plugin + "
43.49 + + "made it work in #netbeans 7.3! Gd wrk.\",\"to_user\":\"tom_enebo\",\"to_user_id\":14498747,"
43.50 + + "\"to_user_id_str\":\"14498747\",\"to_user_name\":\"tom_enebo\",\"in_reply_to_status_id\":319832359509839872,"
43.51 + + "\"in_reply_to_status_id_str\":\"319832359509839872\"},{\"created_at\":\"Thu, 04 Apr 2013 07:33:06 +0000\","
43.52 + + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
43.53 + + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":319714227088678913,"
43.54 + + "\"id_str\":\"319714227088678913\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
43.55 + + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
43.56 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
43.57 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
43.58 + + "\"RT @drkrab: At #erlangfactory @joerl: Frameworks grow in complexity until nobody can use them.\"},"
43.59 + + "{\"created_at\":\"Tue, 02 Apr 2013 07:44:34 +0000\",\"from_user\":\"JaroslavTulach\","
43.60 + + "\"from_user_id\":420944648,\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\","
43.61 + + "\"geo\":null,\"id\":318992336145248256,\"id_str\":\"318992336145248256\",\"iso_language_code\":\"en\","
43.62 + + "\"metadata\":{\"result_type\":\"recent\"},\"profile_image_url\":"
43.63 + + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
43.64 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
43.65 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
43.66 + + "\"Twitter renamed to twttr http:\\/\\/t.co\\/tqaN4T1xlZ - good, I don't have to rename #bck2brwsr!\"},"
43.67 + + "{\"created_at\":\"Sun, 31 Mar 2013 03:52:04 +0000\",\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,"
43.68 + + "\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,"
43.69 + + "\"id\":318209051223789568,\"id_str\":\"318209051223789568\",\"iso_language_code\":\"en\",\"metadata\":"
43.70 + + "{\"result_type\":\"recent\"},\"profile_image_url\":"
43.71 + + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
43.72 + + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
43.73 + + "\"source\":\"<a href="http:\\/\\/twitter.com\\/">web<\\/a>\",\"text\":"
43.74 + + "\"Math proofs without words. Ingenious: http:\\/\\/t.co\\/sz7yVbfpGw\"}],\"results_per_page\":100,"
43.75 + + "\"since_id\":0,\"since_id_str\":\"0\"})"
43.76 + ))
43.77 + @BrwsrTest public void readFromTwttr() throws InterruptedException {
43.78 + if (page == null) {
43.79 + page = new TwitterModel();
43.80 + page.applyBindings();
43.81 + page.queryTweets("", "q=xyz");
43.82 + }
43.83 +
43.84 + if (page.getCurrentTweets().isEmpty()) {
43.85 + throw new InterruptedException();
43.86 + }
43.87 +
43.88 + assert 4 == page.getCurrentTweets().size() : "Four tweets: " + page.getCurrentTweets();
43.89 +
43.90 + String firstDate = page.getCurrentTweets().get(0).getCreated_at();
43.91 + assert "Fri, 05 Apr 2013 06:10:01 +0000".equals(firstDate) : "Date is OK: " + firstDate;
43.92 + }
43.93 +
43.94 + @Factory public static Object[] create() {
43.95 + return VMTest.create(TwitterProtocolTest.class);
43.96 + }
43.97 +}
44.1 --- a/javaquery/pom.xml Mon Mar 25 13:29:42 2013 +0100
44.2 +++ b/javaquery/pom.xml Thu Apr 11 16:59:42 2013 +0200
44.3 @@ -4,16 +4,17 @@
44.4 <parent>
44.5 <artifactId>bck2brwsr</artifactId>
44.6 <groupId>org.apidesign</groupId>
44.7 - <version>0.5-SNAPSHOT</version>
44.8 + <version>0.6-SNAPSHOT</version>
44.9 </parent>
44.10 <groupId>org.apidesign.bck2brwsr</groupId>
44.11 <artifactId>javaquery</artifactId>
44.12 - <version>0.5-SNAPSHOT</version>
44.13 + <version>0.6-SNAPSHOT</version>
44.14 <packaging>pom</packaging>
44.15 <name>JavaQuery API and Demo</name>
44.16 <modules>
44.17 <module>api</module>
44.18 <module>demo-calculator</module>
44.19 <module>demo-calculator-dynamic</module>
44.20 - </modules>
44.21 -</project>
44.22 + <module>demo-twitter</module>
44.23 + </modules>
44.24 +</project>
44.25 \ No newline at end of file
45.1 --- a/pom.xml Mon Mar 25 13:29:42 2013 +0100
45.2 +++ b/pom.xml Thu Apr 11 16:59:42 2013 +0200
45.3 @@ -3,7 +3,7 @@
45.4 <modelVersion>4.0.0</modelVersion>
45.5 <groupId>org.apidesign</groupId>
45.6 <artifactId>bck2brwsr</artifactId>
45.7 - <version>0.5-SNAPSHOT</version>
45.8 + <version>0.6-SNAPSHOT</version>
45.9 <packaging>pom</packaging>
45.10 <name>Back 2 Browser</name>
45.11 <parent>
45.12 @@ -11,6 +11,11 @@
45.13 <artifactId>jvnet-parent</artifactId>
45.14 <version>3</version>
45.15 </parent>
45.16 + <properties>
45.17 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
45.18 + <netbeans.version>RELEASE73</netbeans.version>
45.19 + <license>COPYING</license>
45.20 + </properties>
45.21 <modules>
45.22 <module>dew</module>
45.23 <module>javaquery</module>
45.24 @@ -80,21 +85,24 @@
45.25 <exclude>.*/**</exclude>
45.26 <exclude>rt/emul/*/src/main/**</exclude>
45.27 <exclude>rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java</exclude>
45.28 - <exclude>rt/mojo/src/main/resources/archetype-resources/**</exclude>
45.29 + <exclude>rt/archetype/src/main/resources/archetype-resources/**</exclude>
45.30 <exclude>rt/vmtest/src/test/resources/**</exclude>
45.31 <exclude>dew/src/main/resources/org/apidesign/bck2brwsr/dew/**</exclude>
45.32 <exclude>javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout*.js</exclude>
45.33 </excludes>
45.34 </configuration>
45.35 </plugin>
45.36 - <plugin>
45.37 - <groupId>org.apache.maven.plugins</groupId>
45.38 - <artifactId>maven-release-plugin</artifactId>
45.39 - <version>2.4</version>
45.40 - <configuration>
45.41 - <tag>release-${releaseVersion}</tag>
45.42 - </configuration>
45.43 - </plugin> </plugins>
45.44 + <plugin>
45.45 + <artifactId>maven-release-plugin</artifactId>
45.46 + <version>2.4</version>
45.47 + <configuration>
45.48 + <mavenExecutorId>forked-path</mavenExecutorId>
45.49 + <useReleaseProfile>false</useReleaseProfile>
45.50 + <arguments>-Pjvnet-release -Pgpg</arguments>
45.51 + <tag>release-${releaseVersion}</tag>
45.52 + </configuration>
45.53 + </plugin>
45.54 + </plugins>
45.55 <pluginManagement>
45.56 <plugins>
45.57 <plugin>
45.58 @@ -139,19 +147,113 @@
45.59 <dependency>
45.60 <groupId>org.netbeans.api</groupId>
45.61 <artifactId>org-netbeans-modules-classfile</artifactId>
45.62 - <version>RELEASE72</version>
45.63 + <version>${netbeans.version}</version>
45.64 <type>jar</type>
45.65 </dependency>
45.66 <dependency>
45.67 <groupId>org.netbeans.api</groupId>
45.68 <artifactId>org-openide-util-lookup</artifactId>
45.69 - <version>RELEASE72</version>
45.70 + <version>${netbeans.version}</version>
45.71 <scope>compile</scope>
45.72 <type>jar</type>
45.73 </dependency>
45.74 + <dependency>
45.75 + <groupId>org.netbeans.api</groupId>
45.76 + <artifactId>org-netbeans-api-annotations-common</artifactId>
45.77 + <version>${netbeans.version}</version>
45.78 + </dependency>
45.79 + <dependency>
45.80 + <groupId>org.netbeans.api</groupId>
45.81 + <artifactId>org-netbeans-modules-java-source</artifactId>
45.82 + <version>${netbeans.version}</version>
45.83 + </dependency>
45.84 + <dependency>
45.85 + <groupId>org.netbeans.api</groupId>
45.86 + <artifactId>org-netbeans-libs-javacapi</artifactId>
45.87 + <version>${netbeans.version}</version>
45.88 + </dependency>
45.89 + <dependency>
45.90 + <groupId>org.netbeans.api</groupId>
45.91 + <artifactId>org-netbeans-spi-java-hints</artifactId>
45.92 + <version>${netbeans.version}</version>
45.93 + </dependency>
45.94 + <dependency>
45.95 + <groupId>org.netbeans.api</groupId>
45.96 + <artifactId>org-netbeans-modules-parsing-api</artifactId>
45.97 + <version>${netbeans.version}</version>
45.98 + </dependency>
45.99 + <dependency>
45.100 + <groupId>org.netbeans.api</groupId>
45.101 + <artifactId>org-netbeans-spi-editor-hints</artifactId>
45.102 + <version>${netbeans.version}</version>
45.103 + </dependency>
45.104 + <dependency>
45.105 + <groupId>org.netbeans.api</groupId>
45.106 + <artifactId>org-openide-util</artifactId>
45.107 + <version>${netbeans.version}</version>
45.108 + </dependency>
45.109 + <dependency>
45.110 + <groupId>org.netbeans.api</groupId>
45.111 + <artifactId>org-netbeans-modules-java-lexer</artifactId>
45.112 + <version>${netbeans.version}</version>
45.113 + </dependency>
45.114 + <dependency>
45.115 + <groupId>org.netbeans.api</groupId>
45.116 + <artifactId>org-netbeans-modules-lexer</artifactId>
45.117 + <version>${netbeans.version}</version>
45.118 + </dependency>
45.119 + <dependency>
45.120 + <groupId>org.netbeans.api</groupId>
45.121 + <artifactId>org-netbeans-modules-java-hints-test</artifactId>
45.122 + <version>${netbeans.version}</version>
45.123 + </dependency>
45.124 + <dependency>
45.125 + <groupId>org.netbeans.api</groupId>
45.126 + <artifactId>org-netbeans-libs-junit4</artifactId>
45.127 + <version>${netbeans.version}</version>
45.128 + </dependency>
45.129 + <dependency>
45.130 + <groupId>org.netbeans.modules</groupId>
45.131 + <artifactId>org-netbeans-lib-nbjavac</artifactId>
45.132 + <version>${netbeans.version}</version>
45.133 + </dependency>
45.134 + <dependency>
45.135 + <groupId>org.netbeans.modules</groupId>
45.136 + <artifactId>org-netbeans-modules-web-browser-api</artifactId>
45.137 + <version>${netbeans.version}</version>
45.138 + <exclusions>
45.139 + <exclusion>
45.140 + <artifactId>org-netbeans-core</artifactId>
45.141 + <groupId>org.netbeans.modules</groupId>
45.142 + </exclusion>
45.143 + <exclusion>
45.144 + <artifactId>org-netbeans-core-multiview</artifactId>
45.145 + <groupId>org.netbeans.api</groupId>
45.146 + </exclusion>
45.147 + <exclusion>
45.148 + <artifactId>org-netbeans-libs-lucene</artifactId>
45.149 + <groupId>org.netbeans.api</groupId>
45.150 + </exclusion>
45.151 + <exclusion>
45.152 + <artifactId>org-netbeans-modules-diff</artifactId>
45.153 + <groupId>org.netbeans.api</groupId>
45.154 + </exclusion>
45.155 + <exclusion>
45.156 + <artifactId>org-netbeans-modules-editor-fold</artifactId>
45.157 + <groupId>org.netbeans.api</groupId>
45.158 + </exclusion>
45.159 + <exclusion>
45.160 + <artifactId>org-netbeans-modules-editor-guards</artifactId>
45.161 + <groupId>org.netbeans.api</groupId>
45.162 + </exclusion>
45.163 + </exclusions>
45.164 + </dependency>
45.165 + <dependency>
45.166 + <artifactId>org-netbeans-modules-projectapi</artifactId>
45.167 + <groupId>org.netbeans.api</groupId>
45.168 + <type>jar</type>
45.169 + <version>${netbeans.version}</version>
45.170 + </dependency>
45.171 </dependencies>
45.172 </dependencyManagement>
45.173 - <properties>
45.174 - <license>COPYING</license>
45.175 - </properties>
45.176 </project>
45.177 \ No newline at end of file
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/rt/archetype/pom.xml Thu Apr 11 16:59:42 2013 +0200
46.3 @@ -0,0 +1,62 @@
46.4 +<?xml version="1.0" encoding="UTF-8"?>
46.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
46.6 + <modelVersion>4.0.0</modelVersion>
46.7 + <parent>
46.8 + <artifactId>rt</artifactId>
46.9 + <groupId>org.apidesign.bck2brwsr</groupId>
46.10 + <version>0.6-SNAPSHOT</version>
46.11 + </parent>
46.12 + <groupId>org.apidesign.bck2brwsr</groupId>
46.13 + <artifactId>bck2brwsr-archetype-html-sample</artifactId>
46.14 + <version>0.6-SNAPSHOT</version>
46.15 + <packaging>jar</packaging>
46.16 + <name>Bck2Brwsr Maven Archetype</name>
46.17 + <description>
46.18 + Creates a skeletal HTML page and associated Java controller class.
46.19 + Runs in any browser (even without Java plugin) with the help of Bck2Brwsr
46.20 + virtual machine.
46.21 + </description>
46.22 + <build>
46.23 + <plugins>
46.24 + <plugin>
46.25 + <groupId>org.apache.maven.plugins</groupId>
46.26 + <artifactId>maven-compiler-plugin</artifactId>
46.27 + <version>2.3.2</version>
46.28 + <configuration>
46.29 + <source>1.6</source>
46.30 + <target>1.6</target>
46.31 + </configuration>
46.32 + </plugin>
46.33 + <plugin>
46.34 + <groupId>org.apache.maven.plugins</groupId>
46.35 + <artifactId>maven-surefire-plugin</artifactId>
46.36 + <configuration>
46.37 + <skipTests>true</skipTests>
46.38 + </configuration>
46.39 + <executions>
46.40 + <execution>
46.41 + <id>test</id>
46.42 + <goals>
46.43 + <goal>test</goal>
46.44 + </goals>
46.45 + <phase>integration-test</phase>
46.46 + <configuration>
46.47 + <additionalClasspathElements>
46.48 + <additionalClasspathElement>${project.build.directory}/bck2brwsr-archetype-html-sample-${project.version}.jar</additionalClasspathElement>
46.49 + </additionalClasspathElements>
46.50 + <skipTests>false</skipTests>
46.51 + </configuration>
46.52 + </execution>
46.53 +
46.54 + </executions>
46.55 + </plugin>
46.56 + </plugins>
46.57 + </build>
46.58 + <dependencies>
46.59 + <dependency>
46.60 + <groupId>org.testng</groupId>
46.61 + <artifactId>testng</artifactId>
46.62 + <scope>test</scope>
46.63 + </dependency>
46.64 + </dependencies>
46.65 +</project>
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/rt/archetype/src/main/java/org/apidesign/bck2brwsr/archetype/package-info.java Thu Apr 11 16:59:42 2013 +0200
47.3 @@ -0,0 +1,18 @@
47.4 +/**
47.5 + * Back 2 Browser Bytecode Translator
47.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
47.7 + *
47.8 + * This program is free software: you can redistribute it and/or modify
47.9 + * it under the terms of the GNU General Public License as published by
47.10 + * the Free Software Foundation, version 2 of the License.
47.11 + *
47.12 + * This program is distributed in the hope that it will be useful,
47.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
47.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47.15 + * GNU General Public License for more details.
47.16 + *
47.17 + * You should have received a copy of the GNU General Public License
47.18 + * along with this program. Look for COPYING file in the top folder.
47.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
47.20 + */
47.21 +package org.apidesign.bck2brwsr.archetype;
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/rt/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml Thu Apr 11 16:59:42 2013 +0200
48.3 @@ -0,0 +1,55 @@
48.4 +<?xml version="1.0" encoding="UTF-8"?>
48.5 +<!--
48.6 +
48.7 + Back 2 Browser Bytecode Translator
48.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
48.9 +
48.10 + This program is free software: you can redistribute it and/or modify
48.11 + it under the terms of the GNU General Public License as published by
48.12 + the Free Software Foundation, version 2 of the License.
48.13 +
48.14 + This program is distributed in the hope that it will be useful,
48.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
48.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48.17 + GNU General Public License for more details.
48.18 +
48.19 + You should have received a copy of the GNU General Public License
48.20 + along with this program. Look for COPYING file in the top folder.
48.21 + If not, see http://opensource.org/licenses/GPL-2.0.
48.22 +
48.23 +-->
48.24 +<archetype-descriptor name="Get Java Bck2Brwsr!">
48.25 + <fileSets>
48.26 + <fileSet filtered="true" packaged="true">
48.27 + <directory>src/main/java</directory>
48.28 + <includes>
48.29 + <include>**/App.java</include>
48.30 + </includes>
48.31 + </fileSet>
48.32 + <fileSet filtered="true" packaged="true">
48.33 + <directory>src/main/resources</directory>
48.34 + <includes>
48.35 + <include>**/*.xhtml</include>
48.36 + <include>**/*.html</include>
48.37 + </includes>
48.38 + </fileSet>
48.39 + <fileSet filtered="true" packaged="true">
48.40 + <directory>src/test/java</directory>
48.41 + <includes>
48.42 + <include>**/*Test.java</include>
48.43 + </includes>
48.44 + </fileSet>
48.45 + <fileSet filtered="false" packaged="false">
48.46 + <directory></directory>
48.47 + <includes>
48.48 + <include>nbactions.xml</include>
48.49 + </includes>
48.50 + </fileSet>
48.51 + <fileSet filtered="true" packaged="false">
48.52 + <directory></directory>
48.53 + <includes>
48.54 + <include>bck2brwsr-assembly.xml</include>
48.55 + </includes>
48.56 + </fileSet>
48.57 + </fileSets>
48.58 +</archetype-descriptor>
48.59 \ No newline at end of file
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/rt/archetype/src/main/resources/archetype-resources/bck2brwsr-assembly.xml Thu Apr 11 16:59:42 2013 +0200
49.3 @@ -0,0 +1,61 @@
49.4 +<?xml version="1.0"?>
49.5 +<!--
49.6 +
49.7 + Back 2 Browser Bytecode Translator
49.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
49.9 +
49.10 + This program is free software: you can redistribute it and/or modify
49.11 + it under the terms of the GNU General Public License as published by
49.12 + the Free Software Foundation, version 2 of the License.
49.13 +
49.14 + This program is distributed in the hope that it will be useful,
49.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
49.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49.17 + GNU General Public License for more details.
49.18 +
49.19 + You should have received a copy of the GNU General Public License
49.20 + along with this program. Look for COPYING file in the top folder.
49.21 + If not, see http://opensource.org/licenses/GPL-2.0.
49.22 +
49.23 +-->
49.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
49.25 + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
49.26 +
49.27 + <id>bck2brwsr</id>
49.28 + <formats>
49.29 + <format>zip</format>
49.30 + </formats>
49.31 + <baseDirectory>public_html</baseDirectory>
49.32 + <dependencySets>
49.33 + <dependencySet>
49.34 + <useProjectArtifact>false</useProjectArtifact>
49.35 + <scope>runtime</scope>
49.36 + <outputDirectory>lib</outputDirectory>
49.37 + <includes>
49.38 + <include>*:jar</include>
49.39 + <include>*:rt</include>
49.40 + </includes>
49.41 + </dependencySet>
49.42 + <dependencySet>
49.43 + <useProjectArtifact>false</useProjectArtifact>
49.44 + <scope>provided</scope>
49.45 + <includes>
49.46 + <include>*:js</include>
49.47 + </includes>
49.48 + <unpack>true</unpack>
49.49 + <outputDirectory>/</outputDirectory>
49.50 + </dependencySet>
49.51 + </dependencySets>
49.52 + <files>
49.53 + <file>
49.54 + <source>${project.build.directory}/${project.build.finalName}.jar</source>
49.55 + <outputDirectory>/</outputDirectory>
49.56 + </file>
49.57 + <file>
49.58 + <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
49.59 + <outputDirectory>/</outputDirectory>
49.60 + <destName>index.html</destName>
49.61 + </file>
49.62 + </files>
49.63 +
49.64 +</assembly>
49.65 \ No newline at end of file
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/rt/archetype/src/main/resources/archetype-resources/nbactions.xml Thu Apr 11 16:59:42 2013 +0200
50.3 @@ -0,0 +1,10 @@
50.4 +<?xml version="1.0" encoding="UTF-8"?>
50.5 +<actions>
50.6 + <action>
50.7 + <actionName>run</actionName>
50.8 + <goals>
50.9 + <goal>process-classes</goal>
50.10 + <goal>org.apidesign.bck2brwsr:mojo:0.6-SNAPSHOT:brwsr</goal>
50.11 + </goals>
50.12 + </action>
50.13 +</actions>
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/rt/archetype/src/main/resources/archetype-resources/pom.xml Thu Apr 11 16:59:42 2013 +0200
51.3 @@ -0,0 +1,135 @@
51.4 +<?xml version="1.0"?>
51.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
51.6 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
51.7 + <modelVersion>4.0.0</modelVersion>
51.8 +
51.9 + <groupId>${groupId}</groupId>
51.10 + <artifactId>${artifactId}</artifactId>
51.11 + <version>${version}</version>
51.12 + <packaging>jar</packaging>
51.13 +
51.14 + <name>${artifactId}</name>
51.15 +
51.16 + <repositories>
51.17 + <repository>
51.18 + <id>java.net</id>
51.19 + <name>Java.net</name>
51.20 + <url>https://maven.java.net/content/repositories/releases/</url>
51.21 + <snapshots>
51.22 + <enabled>true</enabled>
51.23 + </snapshots>
51.24 + </repository>
51.25 + <repository>
51.26 + <id>netbeans</id>
51.27 + <name>NetBeans</name>
51.28 + <url>http://bits.netbeans.org/maven2/</url>
51.29 + </repository>
51.30 + </repositories>
51.31 + <pluginRepositories>
51.32 + <pluginRepository>
51.33 + <id>java.net</id>
51.34 + <name>Java.net</name>
51.35 + <url>https://maven.java.net/content/repositories/releases/</url>
51.36 + <snapshots>
51.37 + <enabled>true</enabled>
51.38 + </snapshots>
51.39 + </pluginRepository>
51.40 + </pluginRepositories>
51.41 +
51.42 + <properties>
51.43 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
51.44 + </properties>
51.45 + <build>
51.46 + <plugins>
51.47 + <plugin>
51.48 + <groupId>org.apidesign.bck2brwsr</groupId>
51.49 + <artifactId>mojo</artifactId>
51.50 + <version>0.6-SNAPSHOT</version>
51.51 + <executions>
51.52 + <execution>
51.53 + <goals>
51.54 + <goal>brwsr</goal>
51.55 + </goals>
51.56 + </execution>
51.57 + </executions>
51.58 + <configuration>
51.59 + <startpage>${package.replace('.','/')}/index.html</startpage>
51.60 + </configuration>
51.61 + </plugin>
51.62 + <plugin>
51.63 + <groupId>org.apache.maven.plugins</groupId>
51.64 + <artifactId>maven-compiler-plugin</artifactId>
51.65 + <version>2.3.2</version>
51.66 + <configuration>
51.67 + <source>1.7</source>
51.68 + <target>1.7</target>
51.69 + </configuration>
51.70 + </plugin>
51.71 + <plugin>
51.72 + <groupId>org.apache.maven.plugins</groupId>
51.73 + <artifactId>maven-jar-plugin</artifactId>
51.74 + <version>2.4</version>
51.75 + <configuration>
51.76 + <archive>
51.77 + <manifest>
51.78 + <addClasspath>true</addClasspath>
51.79 + <classpathPrefix>lib/</classpathPrefix>
51.80 + </manifest>
51.81 + </archive>
51.82 + </configuration>
51.83 + </plugin>
51.84 + <plugin>
51.85 + <artifactId>maven-assembly-plugin</artifactId>
51.86 + <version>2.4</version>
51.87 + <executions>
51.88 + <execution>
51.89 + <id>distro-assembly</id>
51.90 + <phase>package</phase>
51.91 + <goals>
51.92 + <goal>single</goal>
51.93 + </goals>
51.94 + <configuration>
51.95 + <descriptors>
51.96 + <descriptor>bck2brwsr-assembly.xml</descriptor>
51.97 + </descriptors>
51.98 + </configuration>
51.99 + </execution>
51.100 + </executions>
51.101 + </plugin>
51.102 + </plugins>
51.103 + </build>
51.104 +
51.105 + <dependencies>
51.106 + <dependency>
51.107 + <groupId>org.apidesign.bck2brwsr</groupId>
51.108 + <artifactId>emul</artifactId>
51.109 + <version>0.6-SNAPSHOT</version>
51.110 + <classifier>rt</classifier>
51.111 + </dependency>
51.112 + <dependency>
51.113 + <groupId>org.apidesign.bck2brwsr</groupId>
51.114 + <artifactId>javaquery.api</artifactId>
51.115 + <version>0.6-SNAPSHOT</version>
51.116 + </dependency>
51.117 + <dependency>
51.118 + <groupId>org.testng</groupId>
51.119 + <artifactId>testng</artifactId>
51.120 + <version>6.5.2</version>
51.121 + <scope>test</scope>
51.122 + </dependency>
51.123 + <dependency>
51.124 + <groupId>org.apidesign.bck2brwsr</groupId>
51.125 + <artifactId>vm4brwsr</artifactId>
51.126 + <classifier>js</classifier>
51.127 + <type>zip</type>
51.128 + <version>0.6-SNAPSHOT</version>
51.129 + <scope>provided</scope>
51.130 + </dependency>
51.131 + <dependency>
51.132 + <groupId>org.apidesign.bck2brwsr</groupId>
51.133 + <artifactId>vmtest</artifactId>
51.134 + <version>0.6-SNAPSHOT</version>
51.135 + <scope>test</scope>
51.136 + </dependency>
51.137 + </dependencies>
51.138 +</project>
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/main/java/App.java Thu Apr 11 16:59:42 2013 +0200
52.3 @@ -0,0 +1,88 @@
52.4 +package ${package};
52.5 +
52.6 +import java.util.List;
52.7 +import org.apidesign.bck2brwsr.htmlpage.api.*;
52.8 +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
52.9 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
52.10 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
52.11 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
52.12 +
52.13 +/** This is the controller class for associated index.html page. The <code>Index</code>
52.14 + * is autogenerated by parsing the index.html page. It fields represent individual
52.15 + * elements annotated by "id" in the page.
52.16 + */
52.17 +@Page(xhtml="index.html", className="Index", properties={
52.18 + @Property(name="name", type=String.class),
52.19 + @Property(name="messages", type=String.class, array=true),
52.20 +})
52.21 +public class App {
52.22 + static {
52.23 + Index model = new Index();
52.24 + model.setName("World");
52.25 + model.applyBindings();
52.26 + }
52.27 +
52.28 + /**
52.29 + * @param m the model of the index page creates in static initializer
52.30 + */
52.31 + @On(event = CLICK, id="hello")
52.32 + static void hello(Index m) {
52.33 + display(m.getHelloMessage(), m);
52.34 + m.getMessages().add(m.getHelloMessage());
52.35 + }
52.36 +
52.37 + /** Reacts when mouse moves over the canvas.
52.38 + *
52.39 + * @param m the model of the page
52.40 + * @param x property "x" extracted from the event generated by the browser
52.41 + * @param y property "y" from the mouse event
52.42 + */
52.43 + @On(event = MOUSE_MOVE, id="canvas")
52.44 + static void clearPoint(Index m, int x, int y) {
52.45 + GraphicsContext g = m.canvas.getContext();
52.46 + boolean even = (x + y) % 2 == 0;
52.47 + if (even) {
52.48 + g.setFillStyle("blue");
52.49 + } else {
52.50 + g.setFillStyle("red");
52.51 + }
52.52 + g.clearRect(0, 0, 1000, 1000);
52.53 + g.setFont("italic 40px Calibri");
52.54 + g.fillText(m.getHelloMessage(), 10, 40);
52.55 + }
52.56 +
52.57 + /** Callback function called by the KnockOut/Java binding on elements
52.58 + * representing href's with individual messages being their data.
52.59 + *
52.60 + * @param data the data associated with the element
52.61 + * @param m the model of the page
52.62 + */
52.63 + @OnFunction
52.64 + static void display(String data, Index m) {
52.65 + GraphicsContext g = m.canvas.getContext();
52.66 + g.clearRect(0, 0, 1000, 1000);
52.67 + g.setFillStyle("black");
52.68 + g.setFont("italic 40px Calibri");
52.69 + g.fillText(data, 10, 40);
52.70 + }
52.71 +
52.72 + /** Callback function.
52.73 + *
52.74 + * @param data data associated with the actual element on the page
52.75 + * @param m the model of the page
52.76 + */
52.77 + @OnFunction
52.78 + static void remove(String data, Index m) {
52.79 + m.getMessages().remove(data);
52.80 + }
52.81 +
52.82 + @ComputedProperty
52.83 + static String helloMessage(String name) {
52.84 + return "Hello " + name + "!";
52.85 + }
52.86 +
52.87 + @ComputedProperty
52.88 + static boolean noMessages(List<String> messages) {
52.89 + return messages.isEmpty();
52.90 + }
52.91 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/main/resources/index.html Thu Apr 11 16:59:42 2013 +0200
53.3 @@ -0,0 +1,31 @@
53.4 +<?xml version="1.0" encoding="UTF-8"?>
53.5 +<!DOCTYPE html>
53.6 +<html xmlns="http://www.w3.org/1999/xhtml">
53.7 + <head>
53.8 + <title>Bck2Brwsr's Hello World</title>
53.9 + </head>
53.10 + <body>
53.11 + <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
53.12 + Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
53.13 + <button id="hello">Say Hello!</button>
53.14 + <p>
53.15 + <canvas id="canvas" width="300" height="50">
53.16 + </canvas>
53.17 + </p>
53.18 +
53.19 +
53.20 + <div data-bind="if: noMessages">No message displayed yet.</div>
53.21 + <ul data-bind="foreach: messages">
53.22 + <li>
53.23 + <a href="#" data-bind="text: $data, click: $root.display"></a>
53.24 + (<a href="#" data-bind="click: $root.remove">delete</a>)
53.25 + </li>
53.26 + </ul>
53.27 +
53.28 + <script src="bck2brwsr.js"></script>
53.29 + <script type="text/javascript">
53.30 + var vm = bck2brwsr('${artifactId}-${version}.jar');
53.31 + vm.loadClass('${package}.App');
53.32 + </script>
53.33 + </body>
53.34 +</html>
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/test/java/AppTest.java Thu Apr 11 16:59:42 2013 +0200
54.3 @@ -0,0 +1,26 @@
54.4 +package ${package};
54.5 +
54.6 +import static org.testng.Assert.*;
54.7 +import org.testng.annotations.BeforeMethod;
54.8 +import org.testng.annotations.Test;
54.9 +
54.10 +/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot
54.11 + * as it does not reference any HTML elements or browser functionality. Just
54.12 + * operates on the page model.
54.13 + *
54.14 + * @author Jaroslav Tulach <jtulach@netbeans.org>
54.15 + */
54.16 +public class AppTest {
54.17 + private Index model;
54.18 +
54.19 +
54.20 + @BeforeMethod
54.21 + public void initModel() {
54.22 + model = new Index().applyBindings();
54.23 + }
54.24 +
54.25 + @Test public void testHelloMessage() {
54.26 + model.setName("Joe");
54.27 + assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +");
54.28 + }
54.29 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java Thu Apr 11 16:59:42 2013 +0200
55.3 @@ -0,0 +1,40 @@
55.4 +package ${package};
55.5 +
55.6 +import org.apidesign.bck2brwsr.vmtest.Compare;
55.7 +import org.apidesign.bck2brwsr.vmtest.VMTest;
55.8 +import org.testng.annotations.Factory;
55.9 +
55.10 +/** Bck2brwsr cares about compatibility with real Java. Whatever API is
55.11 + * supported by bck2brwsr, it needs to behave the same way as when running
55.12 + * in HotSpot VM.
55.13 + * <p>
55.14 + * There can be bugs, however. To help us fix them, we kindly ask you to
55.15 + * write an "inconsistency" test. A test that compares behavior of the API
55.16 + * between real VM and bck2brwsr VM. This class is skeleton of such test.
55.17 + *
55.18 + * @author Jaroslav Tulach <jtulach@netbeans.org>
55.19 + */
55.20 +public class InconsistencyTest {
55.21 + /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
55.22 + * Make calls to an API that behaves strangely, return some result at
55.23 + * the end. No need to use any <code>assert</code>.
55.24 + *
55.25 + * @return value to compare between HotSpot and bck2brwsr
55.26 + */
55.27 + @Compare
55.28 + public int checkStringHashCode() throws Exception {
55.29 + return "Is string hashCode the same?".hashCode();
55.30 + }
55.31 +
55.32 + /** Factory method that creates a three tests for each method annotated with
55.33 + * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
55.34 + * HotSpot, one in Rhino and the last one compares the results.
55.35 + *
55.36 + * @see org.apidesign.bck2brwsr.vmtest.VMTest
55.37 + */
55.38 + @Factory
55.39 + public static Object[] create() {
55.40 + return VMTest.create(InconsistencyTest.class);
55.41 + }
55.42 +
55.43 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/rt/archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Thu Apr 11 16:59:42 2013 +0200
56.3 @@ -0,0 +1,46 @@
56.4 +package ${package};
56.5 +
56.6 +import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
56.7 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
56.8 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
56.9 +import org.apidesign.bck2brwsr.vmtest.VMTest;
56.10 +import org.testng.annotations.Factory;
56.11 +
56.12 +/** Sometimes it is useful to run tests inside of the real browser.
56.13 + * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
56.14 + * and that is it. If your code references elements on the HTML page,
56.15 + * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
56.16 + * will be made available on the page before your test starts.
56.17 + *
56.18 + * @author Jaroslav Tulach <jtulach@netbeans.org>
56.19 + */
56.20 +public class IntegrationTest {
56.21 +
56.22 + /** Write to testing code here. Use <code>assert</code> (but not TestNG's
56.23 + * Assert, as TestNG is not compiled with target 1.6 yet).
56.24 + */
56.25 + @HtmlFragment(
56.26 + "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
56.27 + "Your name: <input id='input' data-bind=\"value: name, valueUpdate: 'afterkeydown'\"></input>\n" +
56.28 + "<button id=\"hello\">Say Hello!</button>\n" +
56.29 + "<p>\n" +
56.30 + " <canvas id=\"canvas\" width=\"300\" height=\"50\"></canvas>\n" +
56.31 + "</p>\n"
56.32 + )
56.33 + @BrwsrTest
56.34 + public void modifyValueAssertChangeInModel() {
56.35 + Index m = new Index();
56.36 + m.setName("Joe Hacker");
56.37 + m.applyBindings();
56.38 + assert "Joe Hacker".equals(m.input.getValue()) : "Value is really Joe Hacker: " + m.input.getValue();
56.39 + m.input.setValue("Happy Joe");
56.40 + m.triggerEvent(m.input, OnEvent.CHANGE);
56.41 + assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName();
56.42 + }
56.43 +
56.44 + @Factory
56.45 + public static Object[] create() {
56.46 + return VMTest.create(IntegrationTest.class);
56.47 + }
56.48 +
56.49 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/rt/archetype/src/test/java/org/apidesign/bck2brwsr/archetype/ArchetypeVersionTest.java Thu Apr 11 16:59:42 2013 +0200
57.3 @@ -0,0 +1,104 @@
57.4 +/**
57.5 + * Back 2 Browser Bytecode Translator
57.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
57.7 + *
57.8 + * This program is free software: you can redistribute it and/or modify
57.9 + * it under the terms of the GNU General Public License as published by
57.10 + * the Free Software Foundation, version 2 of the License.
57.11 + *
57.12 + * This program is distributed in the hope that it will be useful,
57.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
57.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57.15 + * GNU General Public License for more details.
57.16 + *
57.17 + * You should have received a copy of the GNU General Public License
57.18 + * along with this program. Look for COPYING file in the top folder.
57.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
57.20 + */
57.21 +package org.apidesign.bck2brwsr.archetype;
57.22 +
57.23 +import java.net.URL;
57.24 +import javax.xml.XMLConstants;
57.25 +import javax.xml.parsers.DocumentBuilderFactory;
57.26 +import javax.xml.xpath.XPathConstants;
57.27 +import javax.xml.xpath.XPathExpression;
57.28 +import javax.xml.xpath.XPathFactory;
57.29 +import org.testng.annotations.Test;
57.30 +import org.xml.sax.InputSource;
57.31 +import static org.testng.Assert.*;
57.32 +import org.testng.annotations.BeforeClass;
57.33 +import org.w3c.dom.Document;
57.34 +import org.w3c.dom.NodeList;
57.35 +
57.36 +/**
57.37 + *
57.38 + * @author Jaroslav Tulach <jtulach@netbeans.org>
57.39 + */
57.40 +public class ArchetypeVersionTest {
57.41 + private String version;
57.42 +
57.43 + public ArchetypeVersionTest() {
57.44 + }
57.45 +
57.46 + @BeforeClass public void readCurrentVersion() throws Exception {
57.47 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
57.48 + URL u = l.getResource("META-INF/maven/org.apidesign.bck2brwsr/bck2brwsr-archetype-html-sample/pom.xml");
57.49 + assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
57.50 +
57.51 + final XPathFactory fact = XPathFactory.newInstance();
57.52 + fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
57.53 +
57.54 + XPathExpression xp = fact.newXPath().compile("project/version/text()");
57.55 +
57.56 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
57.57 + version = xp.evaluate(dom);
57.58 +
57.59 + assertFalse(version.isEmpty(), "There should be some version string");
57.60 + }
57.61 +
57.62 +
57.63 + @Test public void testComparePomDepsVersions() throws Exception {
57.64 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
57.65 + URL r = l.getResource("archetype-resources/pom.xml");
57.66 + assertNotNull(r, "Archetype pom found");
57.67 +
57.68 + final XPathFactory fact = XPathFactory.newInstance();
57.69 + XPathExpression xp2 = fact.newXPath().compile(
57.70 + "//version[../groupId/text() = 'org.apidesign.bck2brwsr']/text()"
57.71 + );
57.72 +
57.73 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
57.74 + NodeList arch = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
57.75 +
57.76 + if (arch.getLength() < 3) {
57.77 + fail("There should be at least three dependencies to bck2brwsr APIs: " + arch.getLength());
57.78 + }
57.79 +
57.80 + for (int i = 0; i < arch.getLength(); i++) {
57.81 + assertEquals(arch.item(i).getTextContent(), version, i + "th dependency needs to be on latest version of bck2brwsr");
57.82 + }
57.83 + }
57.84 +
57.85 + @Test public void testNbActions() throws Exception {
57.86 + final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
57.87 + URL r = l.getResource("archetype-resources/nbactions.xml");
57.88 + assertNotNull(r, "Archetype nb file found");
57.89 +
57.90 + final XPathFactory fact = XPathFactory.newInstance();
57.91 + XPathExpression xp2 = fact.newXPath().compile(
57.92 + "//goal/text()"
57.93 + );
57.94 +
57.95 + Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
57.96 + NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
57.97 +
57.98 + for (int i = 0; i < goals.getLength(); i++) {
57.99 + String s = goals.item(i).getTextContent();
57.100 + if (s.contains("bck2brwsr")) {
57.101 + String[] arr = s.split(":");
57.102 + assertEquals(arr.length, 4, "Three :");
57.103 + assertEquals(arr[2], version, "Proper version is used");
57.104 + }
57.105 + }
57.106 + }
57.107 +}
58.1 --- a/rt/core/pom.xml Mon Mar 25 13:29:42 2013 +0100
58.2 +++ b/rt/core/pom.xml Thu Apr 11 16:59:42 2013 +0200
58.3 @@ -4,11 +4,11 @@
58.4 <parent>
58.5 <groupId>org.apidesign.bck2brwsr</groupId>
58.6 <artifactId>rt</artifactId>
58.7 - <version>0.5-SNAPSHOT</version>
58.8 + <version>0.6-SNAPSHOT</version>
58.9 </parent>
58.10 <groupId>org.apidesign.bck2brwsr</groupId>
58.11 <artifactId>core</artifactId>
58.12 - <version>0.5-SNAPSHOT</version>
58.13 + <version>0.6-SNAPSHOT</version>
58.14 <name>Bck2Brwsr Native Annotations</name>
58.15 <url>http://maven.apache.org</url>
58.16 <build>
59.1 --- a/rt/emul/brwsrtest/pom.xml Mon Mar 25 13:29:42 2013 +0100
59.2 +++ b/rt/emul/brwsrtest/pom.xml Thu Apr 11 16:59:42 2013 +0200
59.3 @@ -1,15 +1,14 @@
59.4 <?xml version="1.0"?>
59.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
59.6 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
59.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
59.8 <modelVersion>4.0.0</modelVersion>
59.9 <parent>
59.10 <groupId>org.apidesign.bck2brwsr</groupId>
59.11 <artifactId>emul.pom</artifactId>
59.12 - <version>0.5-SNAPSHOT</version>
59.13 + <version>0.6-SNAPSHOT</version>
59.14 </parent>
59.15 <groupId>org.apidesign.bck2brwsr</groupId>
59.16 <artifactId>brwsrtest</artifactId>
59.17 - <version>0.5-SNAPSHOT</version>
59.18 + <version>0.6-SNAPSHOT</version>
59.19 <name>Tests Inside Real Browser</name>
59.20 <url>http://maven.apache.org</url>
59.21 <properties>
60.1 --- a/rt/emul/compact/pom.xml Mon Mar 25 13:29:42 2013 +0100
60.2 +++ b/rt/emul/compact/pom.xml Thu Apr 11 16:59:42 2013 +0200
60.3 @@ -4,11 +4,11 @@
60.4 <parent>
60.5 <groupId>org.apidesign.bck2brwsr</groupId>
60.6 <artifactId>emul.pom</artifactId>
60.7 - <version>0.5-SNAPSHOT</version>
60.8 + <version>0.6-SNAPSHOT</version>
60.9 </parent>
60.10 <groupId>org.apidesign.bck2brwsr</groupId>
60.11 <artifactId>emul</artifactId>
60.12 - <version>0.5-SNAPSHOT</version>
60.13 + <version>0.6-SNAPSHOT</version>
60.14 <name>Bck2Brwsr API Profile</name>
60.15 <url>http://maven.apache.org</url>
60.16 <properties>
61.1 --- a/rt/emul/mini/pom.xml Mon Mar 25 13:29:42 2013 +0100
61.2 +++ b/rt/emul/mini/pom.xml Thu Apr 11 16:59:42 2013 +0200
61.3 @@ -4,11 +4,11 @@
61.4 <parent>
61.5 <groupId>org.apidesign.bck2brwsr</groupId>
61.6 <artifactId>emul.pom</artifactId>
61.7 - <version>0.5-SNAPSHOT</version>
61.8 + <version>0.6-SNAPSHOT</version>
61.9 </parent>
61.10 <groupId>org.apidesign.bck2brwsr</groupId>
61.11 <artifactId>emul.mini</artifactId>
61.12 - <version>0.5-SNAPSHOT</version>
61.13 + <version>0.6-SNAPSHOT</version>
61.14 <name>Minimal API Profile</name>
61.15 <url>http://maven.apache.org</url>
61.16 <properties>
61.17 @@ -18,7 +18,7 @@
61.18 <dependency>
61.19 <groupId>org.apidesign.bck2brwsr</groupId>
61.20 <artifactId>core</artifactId>
61.21 - <version>0.5-SNAPSHOT</version>
61.22 + <version>0.6-SNAPSHOT</version>
61.23 <type>jar</type>
61.24 </dependency>
61.25 <dependency>
62.1 --- a/rt/emul/mini/src/main/java/java/lang/Class.java Mon Mar 25 13:29:42 2013 +0100
62.2 +++ b/rt/emul/mini/src/main/java/java/lang/Class.java Thu Apr 11 16:59:42 2013 +0200
62.3 @@ -402,8 +402,15 @@
62.4 }
62.5 return cmpType != null && getComponentType().isAssignableFrom(cmpType);
62.6 }
62.7 - String prop = "$instOf_" + getName().replace('.', '_');
62.8 - return hasCnstrProperty(cls, prop);
62.9 + if (isPrimitive()) {
62.10 + return false;
62.11 + } else {
62.12 + if (cls.isPrimitive()) {
62.13 + return false;
62.14 + }
62.15 + String prop = "$instOf_" + getName().replace('.', '_');
62.16 + return hasCnstrProperty(cls, prop);
62.17 + }
62.18 }
62.19
62.20 @JavaScriptBody(args = { "who", "prop" }, body =
62.21 @@ -1245,6 +1252,7 @@
62.22 }
62.23
62.24 @JavaScriptBody(args = { "sig" }, body =
62.25 + "if (!sig) sig = '[Ljava/lang/Object;';\n" +
62.26 "var c = Array[sig];\n" +
62.27 "if (c) return c;\n" +
62.28 "c = vm.java_lang_Class(true);\n" +
63.1 --- a/rt/emul/mini/src/main/java/java/lang/Enum.java Mon Mar 25 13:29:42 2013 +0100
63.2 +++ b/rt/emul/mini/src/main/java/java/lang/Enum.java Thu Apr 11 16:59:42 2013 +0200
63.3 @@ -27,6 +27,7 @@
63.4
63.5 import java.io.Serializable;
63.6 import java.io.IOException;
63.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
63.8
63.9 /**
63.10 * This is the common base class of all Java language enumeration types.
63.11 @@ -225,15 +226,17 @@
63.12 */
63.13 public static <T extends Enum<T>> T valueOf(Class<T> enumType,
63.14 String name) {
63.15 - throw new UnsupportedOperationException();
63.16 -// T result = enumType.enumConstantDirectory().get(name);
63.17 -// if (result != null)
63.18 -// return result;
63.19 -// if (name == null)
63.20 -// throw new NullPointerException("Name is null");
63.21 -// throw new IllegalArgumentException(
63.22 -// "No enum constant " + enumType.getCanonicalName() + "." + name);
63.23 + for (Object o : values(enumType)) {
63.24 + T t = enumType.cast(o);
63.25 + if (name.equals(((Enum)t).name)) {
63.26 + return t;
63.27 + }
63.28 + }
63.29 + throw new IllegalArgumentException();
63.30 }
63.31 +
63.32 + @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.$VALUES;")
63.33 + private static native Object[] values(Class<?> enumType);
63.34
63.35 /**
63.36 * enum classes cannot have finalize methods.
64.1 --- a/rt/emul/mini/src/main/java/java/lang/String.java Mon Mar 25 13:29:42 2013 +0100
64.2 +++ b/rt/emul/mini/src/main/java/java/lang/String.java Thu Apr 11 16:59:42 2013 +0200
64.3 @@ -2220,9 +2220,19 @@
64.4 * <code>replacement</code> is <code>null</code>.
64.5 * @since 1.5
64.6 */
64.7 - public String replace(CharSequence target, CharSequence replacement) {
64.8 - throw new UnsupportedOperationException("This one should be supported, but without dep on rest of regexp");
64.9 - }
64.10 + @JavaScriptBody(args = { "target", "replacement" }, body =
64.11 + "var s = this.toString();\n"
64.12 + + "target = target.toString();\n"
64.13 + + "replacement = replacement.toString();\n"
64.14 + + "for (;;) {\n"
64.15 + + " var ret = s.replace(target, replacement);\n"
64.16 + + " if (ret === s) {\n"
64.17 + + " return ret;\n"
64.18 + + " }\n"
64.19 + + " s = ret;\n"
64.20 + + "}"
64.21 + )
64.22 + public native String replace(CharSequence target, CharSequence replacement);
64.23
64.24 /**
64.25 * Splits this string around matches of the given
65.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Method.java Mon Mar 25 13:29:42 2013 +0100
65.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Method.java Thu Apr 11 16:59:42 2013 +0200
65.3 @@ -501,8 +501,8 @@
65.4 throws IllegalAccessException, IllegalArgumentException,
65.5 InvocationTargetException
65.6 {
65.7 - final boolean isStatic = (getModifiers() & Modifier.STATIC) == 0;
65.8 - if (isStatic && obj == null) {
65.9 + final boolean nonStatic = (getModifiers() & Modifier.STATIC) == 0;
65.10 + if (nonStatic && obj == null) {
65.11 throw new NullPointerException();
65.12 }
65.13 Class[] types = getParameterTypes();
65.14 @@ -517,7 +517,7 @@
65.15 }
65.16 }
65.17 }
65.18 - Object res = invoke0(isStatic, this, obj, args);
65.19 + Object res = invokeTry(nonStatic, this, obj, args);
65.20 if (getReturnType().isPrimitive()) {
65.21 res = fromPrimitive(getReturnType(), res);
65.22 }
65.23 @@ -536,6 +536,15 @@
65.24 + "return method._data().apply(self, p);\n"
65.25 )
65.26 private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args);
65.27 +
65.28 + private static Object invokeTry(boolean isStatic, Method m, Object self, Object[] args)
65.29 + throws InvocationTargetException {
65.30 + try {
65.31 + return invoke0(isStatic, m, self, args);
65.32 + } catch (Throwable ex) {
65.33 + throw new InvocationTargetException(ex, ex.getMessage());
65.34 + }
65.35 + }
65.36
65.37 static Object fromPrimitive(Class<?> type, Object o) {
65.38 if (type == Integer.TYPE) {
66.1 --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Mon Mar 25 13:29:42 2013 +0100
66.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js Thu Apr 11 16:59:42 2013 +0200
66.3 @@ -1,226 +1,244 @@
66.4 // empty line needed here
66.5 -Number.prototype.add32 = function(x) { return (this + x) | 0; };
66.6 -Number.prototype.sub32 = function(x) { return (this - x) | 0; };
66.7 -Number.prototype.mul32 = function(x) {
66.8 - return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
66.9 -};
66.10 -Number.prototype.neg32 = function() { return (-this) | 0; };
66.11
66.12 -Number.prototype.toInt8 = function() { return (this << 24) >> 24; };
66.13 -Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
66.14 +(function(numberPrototype) {
66.15 + numberPrototype.add32 = function(x) {
66.16 + return (this + x) | 0;
66.17 + };
66.18 + numberPrototype.sub32 = function(x) {
66.19 + return (this - x) | 0;
66.20 + };
66.21 + numberPrototype.mul32 = function(x) {
66.22 + return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
66.23 + };
66.24 + numberPrototype.neg32 = function() {
66.25 + return (-this) | 0;
66.26 + };
66.27
66.28 -var __m32 = 0xFFFFFFFF;
66.29 + numberPrototype.toInt8 = function() {
66.30 + return (this << 24) >> 24;
66.31 + };
66.32 + numberPrototype.toInt16 = function() {
66.33 + return (this << 16) >> 16;
66.34 + };
66.35
66.36 -Number.prototype.next32 = function(low) {
66.37 - if (this === 0) {
66.38 - return low;
66.39 - }
66.40 - var l = new Number(low);
66.41 - l.hi = this | 0;
66.42 - return l;
66.43 -};
66.44 + var __m32 = 0xFFFFFFFF;
66.45
66.46 -Number.prototype.high32 = function() {
66.47 - return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0;
66.48 -};
66.49 -Number.prototype.toInt32 = function() { return this | 0; };
66.50 -Number.prototype.toFP = function() {
66.51 - return this.hi ? this.hi * (__m32+1) + this : this;
66.52 -};
66.53 -Number.prototype.toLong = function() {
66.54 - var hi = (this / (__m32+1)) | 0;
66.55 - var low = (this % (__m32+1)) | 0;
66.56 - if (low < 0) {
66.57 - low += __m32+1;
66.58 - }
66.59 -
66.60 - if (this < 0) {
66.61 - hi -= 1;
66.62 - }
66.63 + numberPrototype.next32 = function(low) {
66.64 + if (this === 0) {
66.65 + return low;
66.66 + }
66.67 + var l = new Number(low);
66.68 + l.hi = this | 0;
66.69 + return l;
66.70 + };
66.71
66.72 - return hi.next32(low);
66.73 -};
66.74 + numberPrototype.high32 = function() {
66.75 + return this.hi ? this.hi : (Math.floor(this / (__m32 + 1))) | 0;
66.76 + };
66.77 + numberPrototype.toInt32 = function() {
66.78 + return this | 0;
66.79 + };
66.80 + numberPrototype.toFP = function() {
66.81 + return this.hi ? this.hi * (__m32 + 1) + this : this;
66.82 + };
66.83 + numberPrototype.toLong = function() {
66.84 + var hi = (this / (__m32 + 1)) | 0;
66.85 + var low = (this % (__m32 + 1)) | 0;
66.86 + if (low < 0) {
66.87 + low += __m32 + 1;
66.88 + }
66.89
66.90 -Number.prototype.toExactString = function() {
66.91 - if (this.hi) {
66.92 - // check for Long.MIN_VALUE
66.93 - if ((this.hi == (0x80000000 | 0)) && (this == 0)) {
66.94 - return '-9223372036854775808';
66.95 + if (this < 0) {
66.96 + hi -= 1;
66.97 }
66.98 - var res = 0;
66.99 - var a = [ 6,9,2,7,6,9,4,9,2,4 ];
66.100 - var s = '';
66.101 - var digit;
66.102 - var neg = this.hi < 0;
66.103 - if (neg) {
66.104 - var x = this.neg64();
66.105 - var hi = x.hi;
66.106 - var low = x;
66.107 - } else {
66.108 - var hi = this.hi;
66.109 - var low = this;
66.110 - }
66.111 - for (var i = 0; i < a.length; i++) {
66.112 - res += hi * a[i];
66.113 - var low_digit = low % 10;
66.114 - digit = (res % 10) + low_digit;
66.115
66.116 - low = Math.floor(low / 10);
66.117 - res = Math.floor(res / 10);
66.118 -
66.119 - if (digit >= 10) {
66.120 - digit -= 10;
66.121 - res++;
66.122 - }
66.123 - s = String(digit).concat(s);
66.124 - }
66.125 - s = String(res).concat(s).replace(/^0+/, '');
66.126 - return (neg ? '-' : '').concat(s);
66.127 - }
66.128 - return String(this);
66.129 -};
66.130 -
66.131 -Number.prototype.add64 = function(x) {
66.132 - var low = this + x;
66.133 - carry = 0;
66.134 - if (low > __m32) {
66.135 - carry = 1;
66.136 - low -= (__m32+1);
66.137 - }
66.138 - var hi = (this.high32() + x.high32() + carry) | 0;
66.139 - return hi.next32(low);
66.140 -};
66.141 -
66.142 -Number.prototype.sub64 = function(x) {
66.143 - var low = this - x;
66.144 - carry = 0;
66.145 - if (low < 0) {
66.146 - carry = 1;
66.147 - low += (__m32+1);
66.148 - }
66.149 - var hi = (this.high32() - x.high32() - carry) | 0;
66.150 - return hi.next32(low);
66.151 -};
66.152 -
66.153 -Number.prototype.mul64 = function(x) {
66.154 - var low = this.mul32(x);
66.155 - low += (low < 0) ? (__m32+1) : 0;
66.156 - // first count upper 32 bits of (this.low * x.low)
66.157 - var hi_hi = 0;
66.158 - var hi_low = 0;
66.159 - var m = 1;
66.160 - for (var i = 0; i < 32; i++) {
66.161 - if (x & m) {
66.162 - hi_hi += this >>> 16;
66.163 - hi_low += this & 0xFFFF
66.164 - }
66.165 - hi_low >>= 1;
66.166 - hi_low += (hi_hi & 1) ? 0x8000 : 0;
66.167 - hi_hi >>= 1;
66.168 - m <<= 1;
66.169 - }
66.170 - var hi = (hi_hi << 16) + hi_low;
66.171 -
66.172 - var m1 = this.high32().mul32(x);
66.173 - var m2 = this.mul32(x.high32());
66.174 - hi = hi.add32(m1).add32(m2);
66.175 -
66.176 - return hi.next32(low);
66.177 -};
66.178 -
66.179 -Number.prototype.and64 = function(x) {
66.180 - var low = this & x;
66.181 - low += (low < 0) ? (__m32+1) : 0;
66.182 - if (this.hi && x.hi) {
66.183 - var hi = this.hi & x.hi;
66.184 return hi.next32(low);
66.185 };
66.186 - return low;
66.187 -};
66.188
66.189 -Number.prototype.or64 = function(x) {
66.190 - var low = this | x;
66.191 - low += (low < 0) ? (__m32+1) : 0;
66.192 - if (this.hi || x.hi) {
66.193 - var hi = this.hi | x.hi;
66.194 + numberPrototype.toExactString = function() {
66.195 + if (this.hi) {
66.196 + // check for Long.MIN_VALUE
66.197 + if ((this.hi == (0x80000000 | 0)) && (this == 0)) {
66.198 + return '-9223372036854775808';
66.199 + }
66.200 + var res = 0;
66.201 + var a = [6, 9, 2, 7, 6, 9, 4, 9, 2, 4];
66.202 + var s = '';
66.203 + var digit;
66.204 + var neg = this.hi < 0;
66.205 + if (neg) {
66.206 + var x = this.neg64();
66.207 + var hi = x.hi;
66.208 + var low = x;
66.209 + } else {
66.210 + var hi = this.hi;
66.211 + var low = this;
66.212 + }
66.213 + for (var i = 0; i < a.length; i++) {
66.214 + res += hi * a[i];
66.215 + var low_digit = low % 10;
66.216 + digit = (res % 10) + low_digit;
66.217 +
66.218 + low = Math.floor(low / 10);
66.219 + res = Math.floor(res / 10);
66.220 +
66.221 + if (digit >= 10) {
66.222 + digit -= 10;
66.223 + res++;
66.224 + }
66.225 + s = String(digit).concat(s);
66.226 + }
66.227 + s = String(res).concat(s).replace(/^0+/, '');
66.228 + return (neg ? '-' : '').concat(s);
66.229 + }
66.230 + return String(this);
66.231 + };
66.232 +
66.233 + numberPrototype.add64 = function(x) {
66.234 + var low = this + x;
66.235 + carry = 0;
66.236 + if (low > __m32) {
66.237 + carry = 1;
66.238 + low -= (__m32 + 1);
66.239 + }
66.240 + var hi = (this.high32() + x.high32() + carry) | 0;
66.241 return hi.next32(low);
66.242 };
66.243 - return low;
66.244 -};
66.245
66.246 -Number.prototype.xor64 = function(x) {
66.247 - var low = this ^ x;
66.248 - low += (low < 0) ? (__m32+1) : 0;
66.249 - if (this.hi || x.hi) {
66.250 - var hi = this.hi ^ x.hi;
66.251 + numberPrototype.sub64 = function(x) {
66.252 + var low = this - x;
66.253 + carry = 0;
66.254 + if (low < 0) {
66.255 + carry = 1;
66.256 + low += (__m32 + 1);
66.257 + }
66.258 + var hi = (this.high32() - x.high32() - carry) | 0;
66.259 return hi.next32(low);
66.260 };
66.261 - return low;
66.262 -};
66.263
66.264 -Number.prototype.shl64 = function(x) {
66.265 - if (x >= 32) {
66.266 - var hi = this << (x - 32);
66.267 - return hi.next32(0);
66.268 - } else {
66.269 - var hi = this.high32() << x;
66.270 - var low_reminder = this >> (32 - x);
66.271 - hi |= low_reminder;
66.272 - var low = this << x;
66.273 - low += (low < 0) ? (__m32+1) : 0;
66.274 + numberPrototype.mul64 = function(x) {
66.275 + var low = this.mul32(x);
66.276 + low += (low < 0) ? (__m32 + 1) : 0;
66.277 + // first count upper 32 bits of (this.low * x.low)
66.278 + var hi_hi = 0;
66.279 + var hi_low = 0;
66.280 + var m = 1;
66.281 + for (var i = 0; i < 32; i++) {
66.282 + if (x & m) {
66.283 + hi_hi += this >>> 16;
66.284 + hi_low += this & 0xFFFF
66.285 + }
66.286 + hi_low >>= 1;
66.287 + hi_low += (hi_hi & 1) ? 0x8000 : 0;
66.288 + hi_hi >>= 1;
66.289 + m <<= 1;
66.290 + }
66.291 + var hi = (hi_hi << 16) + hi_low;
66.292 +
66.293 + var m1 = this.high32().mul32(x);
66.294 + var m2 = this.mul32(x.high32());
66.295 + hi = hi.add32(m1).add32(m2);
66.296 +
66.297 return hi.next32(low);
66.298 - }
66.299 -};
66.300 + };
66.301
66.302 -Number.prototype.shr64 = function(x) {
66.303 - if (x >= 32) {
66.304 - var low = this.high32() >> (x - 32);
66.305 - low += (low < 0) ? (__m32+1) : 0;
66.306 + numberPrototype.and64 = function(x) {
66.307 + var low = this & x;
66.308 + low += (low < 0) ? (__m32 + 1) : 0;
66.309 + if (this.hi && x.hi) {
66.310 + var hi = this.hi & x.hi;
66.311 + return hi.next32(low);
66.312 + }
66.313 + ;
66.314 return low;
66.315 - } else {
66.316 - var low = this >> x;
66.317 - var hi_reminder = this.high32() << (32 - x);
66.318 - low |= hi_reminder;
66.319 - low += (low < 0) ? (__m32+1) : 0;
66.320 - var hi = this.high32() >> x;
66.321 - return hi.next32(low);
66.322 - }
66.323 -};
66.324 + };
66.325
66.326 -Number.prototype.ushr64 = function(x) {
66.327 - if (x >= 32) {
66.328 - var low = this.high32() >>> (x - 32);
66.329 - low += (low < 0) ? (__m32+1) : 0;
66.330 + numberPrototype.or64 = function(x) {
66.331 + var low = this | x;
66.332 + low += (low < 0) ? (__m32 + 1) : 0;
66.333 + if (this.hi || x.hi) {
66.334 + var hi = this.hi | x.hi;
66.335 + return hi.next32(low);
66.336 + }
66.337 + ;
66.338 return low;
66.339 - } else {
66.340 - var low = this >>> x;
66.341 - var hi_reminder = this.high32() << (32 - x);
66.342 - low |= hi_reminder;
66.343 - low += (low < 0) ? (__m32+1) : 0;
66.344 - var hi = this.high32() >>> x;
66.345 - return hi.next32(low);
66.346 - }
66.347 -};
66.348 + };
66.349
66.350 -Number.prototype.compare64 = function(x) {
66.351 - if (this.high32() === x.high32()) {
66.352 - return (this < x) ? -1 : ((this > x) ? 1 : 0);
66.353 - }
66.354 - return (this.high32() < x.high32()) ? -1 : 1;
66.355 -};
66.356 + numberPrototype.xor64 = function(x) {
66.357 + var low = this ^ x;
66.358 + low += (low < 0) ? (__m32 + 1) : 0;
66.359 + if (this.hi || x.hi) {
66.360 + var hi = this.hi ^ x.hi;
66.361 + return hi.next32(low);
66.362 + }
66.363 + ;
66.364 + return low;
66.365 + };
66.366
66.367 -Number.prototype.neg64 = function() {
66.368 - var hi = this.high32();
66.369 - var low = this;
66.370 - if ((hi === 0) && (low < 0)) { return -low; }
66.371 - hi = ~hi;
66.372 - low = ~low;
66.373 - low += (low < 0) ? (__m32+1) : 0;
66.374 - var ret = hi.next32(low);
66.375 - return ret.add64(1);
66.376 -};
66.377 + numberPrototype.shl64 = function(x) {
66.378 + if (x >= 32) {
66.379 + var hi = this << (x - 32);
66.380 + return hi.next32(0);
66.381 + } else {
66.382 + var hi = this.high32() << x;
66.383 + var low_reminder = this >> (32 - x);
66.384 + hi |= low_reminder;
66.385 + var low = this << x;
66.386 + low += (low < 0) ? (__m32 + 1) : 0;
66.387 + return hi.next32(low);
66.388 + }
66.389 + };
66.390
66.391 -(function(numberPrototype) {
66.392 + numberPrototype.shr64 = function(x) {
66.393 + if (x >= 32) {
66.394 + var low = this.high32() >> (x - 32);
66.395 + low += (low < 0) ? (__m32 + 1) : 0;
66.396 + return low;
66.397 + } else {
66.398 + var low = this >> x;
66.399 + var hi_reminder = this.high32() << (32 - x);
66.400 + low |= hi_reminder;
66.401 + low += (low < 0) ? (__m32 + 1) : 0;
66.402 + var hi = this.high32() >> x;
66.403 + return hi.next32(low);
66.404 + }
66.405 + };
66.406 +
66.407 + numberPrototype.ushr64 = function(x) {
66.408 + if (x >= 32) {
66.409 + var low = this.high32() >>> (x - 32);
66.410 + low += (low < 0) ? (__m32 + 1) : 0;
66.411 + return low;
66.412 + } else {
66.413 + var low = this >>> x;
66.414 + var hi_reminder = this.high32() << (32 - x);
66.415 + low |= hi_reminder;
66.416 + low += (low < 0) ? (__m32 + 1) : 0;
66.417 + var hi = this.high32() >>> x;
66.418 + return hi.next32(low);
66.419 + }
66.420 + };
66.421 +
66.422 + numberPrototype.compare64 = function(x) {
66.423 + if (this.high32() === x.high32()) {
66.424 + return (this < x) ? -1 : ((this > x) ? 1 : 0);
66.425 + }
66.426 + return (this.high32() < x.high32()) ? -1 : 1;
66.427 + };
66.428 +
66.429 + numberPrototype.neg64 = function() {
66.430 + var hi = this.high32();
66.431 + var low = this;
66.432 + if ((hi === 0) && (low < 0)) {
66.433 + return -low;
66.434 + }
66.435 + hi = ~hi;
66.436 + low = ~low;
66.437 + low += (low < 0) ? (__m32 + 1) : 0;
66.438 + var ret = hi.next32(low);
66.439 + return ret.add64(1);
66.440 + };
66.441 +
66.442 function __handleDivByZero() {
66.443 var exception = new vm.java_lang_ArithmeticException;
66.444 vm.java_lang_ArithmeticException(false).constructor
67.1 --- a/rt/emul/pom.xml Mon Mar 25 13:29:42 2013 +0100
67.2 +++ b/rt/emul/pom.xml Thu Apr 11 16:59:42 2013 +0200
67.3 @@ -4,11 +4,11 @@
67.4 <parent>
67.5 <groupId>org.apidesign.bck2brwsr</groupId>
67.6 <artifactId>rt</artifactId>
67.7 - <version>0.5-SNAPSHOT</version>
67.8 + <version>0.6-SNAPSHOT</version>
67.9 </parent>
67.10 <groupId>org.apidesign.bck2brwsr</groupId>
67.11 <artifactId>emul.pom</artifactId>
67.12 - <version>0.5-SNAPSHOT</version>
67.13 + <version>0.6-SNAPSHOT</version>
67.14 <packaging>pom</packaging>
67.15 <name>Emulation of Core Libraries</name>
67.16 <modules>
68.1 --- a/rt/launcher/pom.xml Mon Mar 25 13:29:42 2013 +0100
68.2 +++ b/rt/launcher/pom.xml Thu Apr 11 16:59:42 2013 +0200
68.3 @@ -4,11 +4,11 @@
68.4 <parent>
68.5 <groupId>org.apidesign.bck2brwsr</groupId>
68.6 <artifactId>rt</artifactId>
68.7 - <version>0.5-SNAPSHOT</version>
68.8 + <version>0.6-SNAPSHOT</version>
68.9 </parent>
68.10 <groupId>org.apidesign.bck2brwsr</groupId>
68.11 <artifactId>launcher</artifactId>
68.12 - <version>0.5-SNAPSHOT</version>
68.13 + <version>0.6-SNAPSHOT</version>
68.14 <name>Bck2Brwsr Launcher</name>
68.15 <url>http://maven.apache.org</url>
68.16 <build>
69.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Mon Mar 25 13:29:42 2013 +0100
69.2 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java Thu Apr 11 16:59:42 2013 +0200
69.3 @@ -98,9 +98,9 @@
69.4 }
69.5 HttpServer s = initServer(".", true);
69.6 int last = startpage.lastIndexOf('/');
69.7 + String prefix = startpage.substring(0, last);
69.8 String simpleName = startpage.substring(last);
69.9 - s.getServerConfiguration().addHttpHandler(new Page(resources, startpage), simpleName);
69.10 - s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
69.11 + s.getServerConfiguration().addHttpHandler(new SubTree(resources, prefix), "/");
69.12 try {
69.13 launchServerAndBrwsr(s, simpleName);
69.14 } catch (URISyntaxException | InterruptedException ex) {
69.15 @@ -177,7 +177,16 @@
69.16 if (r.httpPath.equals(request.getRequestURI())) {
69.17 LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
69.18 response.setContentType(r.httpType);
69.19 - copyStream(r.httpContent, response.getOutputStream(), null);
69.20 + r.httpContent.reset();
69.21 + String[] params = null;
69.22 + if (r.parameters.length != 0) {
69.23 + params = new String[r.parameters.length];
69.24 + for (int i = 0; i < r.parameters.length; i++) {
69.25 + params[i] = request.getParameter(r.parameters[i]);
69.26 + }
69.27 + }
69.28 +
69.29 + copyStream(r.httpContent, response.getOutputStream(), null, params);
69.30 }
69.31 }
69.32 }
69.33 @@ -315,11 +324,15 @@
69.34 }
69.35 if (ch == '$' && params.length > 0) {
69.36 int cnt = is.read() - '0';
69.37 - if (cnt == 'U' - '0') {
69.38 + if (baseURL != null && cnt == 'U' - '0') {
69.39 os.write(baseURL.getBytes("UTF-8"));
69.40 - }
69.41 - if (cnt >= 0 && cnt < params.length) {
69.42 - os.write(params[cnt].getBytes("UTF-8"));
69.43 + } else {
69.44 + if (cnt >= 0 && cnt < params.length) {
69.45 + os.write(params[cnt].getBytes("UTF-8"));
69.46 + } else {
69.47 + os.write('$');
69.48 + os.write(cnt + '0');
69.49 + }
69.50 }
69.51 } else {
69.52 os.write(ch);
69.53 @@ -450,7 +463,7 @@
69.54 }
69.55
69.56 private static class Page extends HttpHandler {
69.57 - private final String resource;
69.58 + final String resource;
69.59 private final String[] args;
69.60 private final Res res;
69.61
69.62 @@ -462,10 +475,7 @@
69.63
69.64 @Override
69.65 public void service(Request request, Response response) throws Exception {
69.66 - String r = resource;
69.67 - if (r == null) {
69.68 - r = request.getHttpHandlerPath();
69.69 - }
69.70 + String r = computePage(request);
69.71 if (r.startsWith("/")) {
69.72 r = r.substring(1);
69.73 }
69.74 @@ -489,6 +499,28 @@
69.75 response.setStatus(404);
69.76 }
69.77 }
69.78 +
69.79 + protected String computePage(Request request) {
69.80 + String r = resource;
69.81 + if (r == null) {
69.82 + r = request.getHttpHandlerPath();
69.83 + }
69.84 + return r;
69.85 + }
69.86 + }
69.87 +
69.88 + private static class SubTree extends Page {
69.89 +
69.90 + public SubTree(Res res, String resource, String... args) {
69.91 + super(res, resource, args);
69.92 + }
69.93 +
69.94 + @Override
69.95 + protected String computePage(Request request) {
69.96 + return resource + request.getHttpHandlerPath();
69.97 + }
69.98 +
69.99 +
69.100 }
69.101
69.102 private static class VM extends HttpHandler {
70.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Mon Mar 25 13:29:42 2013 +0100
70.2 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java Thu Apr 11 16:59:42 2013 +0200
70.3 @@ -55,11 +55,11 @@
70.4 /** HTTP resource to be available during execution. An invocation may
70.5 * perform an HTTP query and obtain a resource relative to the page.
70.6 */
70.7 - public void addHttpResource(String relativePath, String mimeType, InputStream content) {
70.8 - if (relativePath == null || mimeType == null || content == null) {
70.9 + public void addHttpResource(String relativePath, String mimeType, String[] parameters, InputStream content) {
70.10 + if (relativePath == null || mimeType == null || content == null || parameters == null) {
70.11 throw new NullPointerException();
70.12 }
70.13 - resources.add(new Resource(content, mimeType, relativePath));
70.14 + resources.add(new Resource(content, mimeType, relativePath, parameters));
70.15 }
70.16
70.17 /** Invokes the associated method.
70.18 @@ -100,11 +100,16 @@
70.19 final InputStream httpContent;
70.20 final String httpType;
70.21 final String httpPath;
70.22 + final String[] parameters;
70.23
70.24 - Resource(InputStream httpContent, String httpType, String httpPath) {
70.25 + Resource(InputStream httpContent, String httpType, String httpPath,
70.26 + String[] parameters
70.27 + ) {
70.28 + httpContent.mark(Integer.MAX_VALUE);
70.29 this.httpContent = httpContent;
70.30 this.httpType = httpType;
70.31 this.httpPath = httpPath;
70.32 + this.parameters = parameters;
70.33 }
70.34 }
70.35 }
71.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Mon Mar 25 13:29:42 2013 +0100
71.2 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java Thu Apr 11 16:59:42 2013 +0200
71.3 @@ -20,7 +20,6 @@
71.4 import java.io.Closeable;
71.5 import java.io.File;
71.6 import java.io.IOException;
71.7 -import java.net.URLClassLoader;
71.8 import org.apidesign.vm4brwsr.Bck2Brwsr;
71.9
71.10 /** An abstraction for executing tests in a Bck2Brwsr virtual machine.
71.11 @@ -93,7 +92,7 @@
71.12 * @return interface that allows one to stop the server
71.13 * @throws IOException if something goes wrong
71.14 */
71.15 - public static Closeable showURL(URLClassLoader classes, String startpage) throws IOException {
71.16 + public static Closeable showURL(ClassLoader classes, String startpage) throws IOException {
71.17 Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
71.18 l.addClassLoader(classes);
71.19 l.showURL(startpage);
72.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Mon Mar 25 13:29:42 2013 +0100
72.2 +++ b/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java Thu Apr 11 16:59:42 2013 +0200
72.3 @@ -41,28 +41,78 @@
72.4 @JavaScriptBody(args = {"id", "attr"}, body =
72.5 "return window.document.getElementById(id)[attr].toString();")
72.6 private static native Object getAttr(String id, String attr);
72.7 + @JavaScriptBody(args = {"elem", "attr"}, body =
72.8 + "return elem[attr].toString();")
72.9 + private static native Object getAttr(Object elem, String attr);
72.10
72.11 @JavaScriptBody(args = {"id", "attr", "value"}, body =
72.12 "window.document.getElementById(id)[attr] = value;")
72.13 private static native void setAttr(String id, String attr, Object value);
72.14 + @JavaScriptBody(args = {"elem", "attr", "value"}, body =
72.15 + "elem[attr] = value;")
72.16 + private static native void setAttr(Object id, String attr, Object value);
72.17
72.18 @JavaScriptBody(args = {}, body = "return; window.close();")
72.19 private static native void closeWindow();
72.20
72.21 + private static Object textArea;
72.22 + private static Object statusArea;
72.23 +
72.24 private static void log(String newText) {
72.25 - String id = "bck2brwsr.result";
72.26 + if (textArea == null) {
72.27 + return;
72.28 + }
72.29 String attr = "value";
72.30 - setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
72.31 - setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
72.32 + setAttr(textArea, attr, getAttr(textArea, attr) + "\n" + newText);
72.33 + setAttr(textArea, "scrollTop", getAttr(textArea, "scrollHeight"));
72.34 }
72.35
72.36 - public static void execute() throws Exception {
72.37 - String clazz = (String) getAttr("clazz", "value");
72.38 - String method = (String) getAttr("method", "value");
72.39 - Object res = invokeMethod(clazz, method);
72.40 - setAttr("bck2brwsr.result", "value", res);
72.41 + private static void beginTest(Case c) {
72.42 + Object[] arr = new Object[2];
72.43 + beginTest(c.getClassName() + "." + c.getMethodName(), c, arr);
72.44 + textArea = arr[0];
72.45 + statusArea = arr[1];
72.46 + }
72.47 +
72.48 + private static void finishTest(Case c, Object res) {
72.49 + if ("null".equals(res)) {
72.50 + setAttr(statusArea, "innerHTML", "Success");
72.51 + } else {
72.52 + setAttr(statusArea, "innerHTML", "Result " + res);
72.53 + }
72.54 + statusArea = null;
72.55 + textArea = null;
72.56 }
72.57
72.58 + @JavaScriptBody(args = { "test", "c", "arr" }, body =
72.59 + "var ul = window.document.getElementById('bck2brwsr.result');\n"
72.60 + + "var li = window.document.createElement('li');\n"
72.61 + + "var span = window.document.createElement('span');"
72.62 + + "span.innerHTML = test + ' - ';\n"
72.63 + + "var details = window.document.createElement('a');\n"
72.64 + + "details.innerHTML = 'Details';\n"
72.65 + + "details.href = '#';\n"
72.66 + + "var p = window.document.createElement('p');\n"
72.67 + + "var status = window.document.createElement('a');\n"
72.68 + + "status.innerHTML = 'running';"
72.69 + + "details.onclick = function() { li.appendChild(p); li.removeChild(details); status.innerHTML = 'Run Again'; status.href = '#'; };\n"
72.70 + + "status.onclick = function() { c.again__V_3Ljava_lang_Object_2(arr); }\n"
72.71 + + "var pre = window.document.createElement('textarea');\n"
72.72 + + "pre.cols = 100;"
72.73 + + "pre.rows = 10;"
72.74 + + "li.appendChild(span);\n"
72.75 + + "li.appendChild(status);\n"
72.76 + + "var span = window.document.createElement('span');"
72.77 + + "span.innerHTML = ' ';\n"
72.78 + + "li.appendChild(span);\n"
72.79 + + "li.appendChild(details);\n"
72.80 + + "p.appendChild(pre);\n"
72.81 + + "ul.appendChild(li);\n"
72.82 + + "arr[0] = pre;\n"
72.83 + + "arr[1] = status;\n"
72.84 + )
72.85 + private static native void beginTest(String test, Case c, Object[] arr);
72.86 +
72.87 @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
72.88 + "var request = new XMLHttpRequest();\n"
72.89 + "request.open('GET', url, true);\n"
72.90 @@ -84,49 +134,53 @@
72.91 private static class Request implements Runnable {
72.92 private final String[] arr = { null };
72.93 private final String url;
72.94 + private Case c;
72.95 + private int retries;
72.96
72.97 private Request(String url) throws IOException {
72.98 this.url = url;
72.99 loadText(url, this, arr);
72.100 }
72.101 + private Request(String url, String u) throws IOException {
72.102 + this.url = url;
72.103 + loadText(u, this, arr);
72.104 + }
72.105
72.106 @Override
72.107 public void run() {
72.108 try {
72.109 - String data = arr[0];
72.110 - log("\nGot \"" + data + "\"");
72.111 + if (c == null) {
72.112 + String data = arr[0];
72.113 +
72.114 + if (data == null) {
72.115 + log("Some error exiting");
72.116 + closeWindow();
72.117 + return;
72.118 + }
72.119 +
72.120 + if (data.isEmpty()) {
72.121 + log("No data, exiting");
72.122 + closeWindow();
72.123 + return;
72.124 + }
72.125 +
72.126 + c = Case.parseData(data);
72.127 + beginTest(c);
72.128 + log("Got \"" + data + "\"");
72.129 + } else {
72.130 + log("Processing \"" + arr[0] + "\" for " + retries + " time");
72.131 + }
72.132 + Object result = retries++ >= 10 ? "java.lang.InterruptedException:timeout" : c.runTest();
72.133 + finishTest(c, result);
72.134
72.135 - if (data == null) {
72.136 - log("Some error exiting");
72.137 - closeWindow();
72.138 + String u = url + "?request=" + c.getRequestId() + "&result=" + result;
72.139 + new Request(url, u);
72.140 + } catch (Exception ex) {
72.141 + if (ex instanceof InterruptedException) {
72.142 + log("Re-scheduling in 100ms");
72.143 + schedule(this, 100);
72.144 return;
72.145 }
72.146 -
72.147 - if (data.isEmpty()) {
72.148 - log("No data, exiting");
72.149 - closeWindow();
72.150 - return;
72.151 - }
72.152 -
72.153 - Case c = Case.parseData(data);
72.154 - if (c.getHtmlFragment() != null) {
72.155 - setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
72.156 - }
72.157 - log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
72.158 -
72.159 - Object result = invokeMethod(c.getClassName(), c.getMethodName());
72.160 -
72.161 - setAttr("bck2brwsr.fragment", "innerHTML", "");
72.162 - log("Result: " + result);
72.163 -
72.164 - result = encodeURL("" + result);
72.165 -
72.166 - log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
72.167 - String u = url + "?request=" + c.getRequestId() + "&result=" + result;
72.168 -
72.169 - loadText(u, this, arr);
72.170 -
72.171 - } catch (Exception ex) {
72.172 log(ex.getClass().getName() + ":" + ex.getMessage());
72.173 }
72.174 }
72.175 @@ -152,8 +206,10 @@
72.176 return sb.toString();
72.177 }
72.178
72.179 - static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
72.180 - final Object r = invokeMethod(clazz, method);
72.181 + static String invoke(String clazz, String method) throws
72.182 + ClassNotFoundException, InvocationTargetException, IllegalAccessException,
72.183 + InstantiationException, InterruptedException {
72.184 + final Object r = new Case(null).invokeMethod(clazz, method);
72.185 return r == null ? "null" : r.toString().toString();
72.186 }
72.187
72.188 @@ -188,40 +244,17 @@
72.189 }
72.190 }
72.191
72.192 - private static Object invokeMethod(String clazz, String method)
72.193 - throws ClassNotFoundException, InvocationTargetException,
72.194 - SecurityException, IllegalAccessException, IllegalArgumentException,
72.195 - InstantiationException {
72.196 - Method found = null;
72.197 - Class<?> c = Class.forName(clazz);
72.198 - for (Method m : c.getMethods()) {
72.199 - if (m.getName().equals(method)) {
72.200 - found = m;
72.201 - }
72.202 - }
72.203 - Object res;
72.204 - if (found != null) {
72.205 - try {
72.206 - if ((found.getModifiers() & Modifier.STATIC) != 0) {
72.207 - res = found.invoke(null);
72.208 - } else {
72.209 - res = found.invoke(c.newInstance());
72.210 - }
72.211 - } catch (Throwable ex) {
72.212 - res = ex.getClass().getName() + ":" + ex.getMessage();
72.213 - }
72.214 - } else {
72.215 - res = "Can't find method " + method + " in " + clazz;
72.216 - }
72.217 - return res;
72.218 - }
72.219 -
72.220 @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
72.221 private static void turnAssetionStatusOn() {
72.222 }
72.223 +
72.224 + @JavaScriptBody(args = {"r", "time"}, body =
72.225 + "return window.setTimeout(function() { r.run__V(); }, time);")
72.226 + private static native Object schedule(Runnable r, int time);
72.227
72.228 private static final class Case {
72.229 private final Object data;
72.230 + private Object inst;
72.231
72.232 private Case(Object data) {
72.233 this.data = data;
72.234 @@ -247,6 +280,69 @@
72.235 return value("html", data);
72.236 }
72.237
72.238 + void again(Object[] arr) {
72.239 + try {
72.240 + textArea = arr[0];
72.241 + statusArea = arr[1];
72.242 + setAttr(textArea, "value", "");
72.243 + runTest();
72.244 + } catch (Exception ex) {
72.245 + log(ex.getClass().getName() + ":" + ex.getMessage());
72.246 + }
72.247 + }
72.248 +
72.249 + private Object runTest() throws IllegalAccessException,
72.250 + IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException,
72.251 + InvocationTargetException, InstantiationException, InterruptedException {
72.252 + if (this.getHtmlFragment() != null) {
72.253 + setAttr("bck2brwsr.fragment", "innerHTML", this.getHtmlFragment());
72.254 + }
72.255 + log("Invoking " + this.getClassName() + '.' + this.getMethodName() + " as request: " + this.getRequestId());
72.256 + Object result = invokeMethod(this.getClassName(), this.getMethodName());
72.257 + setAttr("bck2brwsr.fragment", "innerHTML", "");
72.258 + log("Result: " + result);
72.259 + result = encodeURL("" + result);
72.260 + log("Sending back: ...?request=" + this.getRequestId() + "&result=" + result);
72.261 + return result;
72.262 + }
72.263 +
72.264 + private Object invokeMethod(String clazz, String method)
72.265 + throws ClassNotFoundException, InvocationTargetException,
72.266 + InterruptedException, IllegalAccessException, IllegalArgumentException,
72.267 + InstantiationException {
72.268 + Method found = null;
72.269 + Class<?> c = Class.forName(clazz);
72.270 + for (Method m : c.getMethods()) {
72.271 + if (m.getName().equals(method)) {
72.272 + found = m;
72.273 + }
72.274 + }
72.275 + Object res;
72.276 + if (found != null) {
72.277 + try {
72.278 + if ((found.getModifiers() & Modifier.STATIC) != 0) {
72.279 + res = found.invoke(null);
72.280 + } else {
72.281 + if (inst == null) {
72.282 + inst = c.newInstance();
72.283 + }
72.284 + res = found.invoke(inst);
72.285 + }
72.286 + } catch (Throwable ex) {
72.287 + if (ex instanceof InvocationTargetException) {
72.288 + ex = ((InvocationTargetException) ex).getTargetException();
72.289 + }
72.290 + if (ex instanceof InterruptedException) {
72.291 + throw (InterruptedException)ex;
72.292 + }
72.293 + res = ex.getClass().getName() + ":" + ex.getMessage();
72.294 + }
72.295 + } else {
72.296 + res = "Can't find method " + method + " in " + clazz;
72.297 + }
72.298 + return res;
72.299 + }
72.300 +
72.301 @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
72.302 private static native Object toJSON(String s);
72.303
73.1 --- a/rt/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Mon Mar 25 13:29:42 2013 +0100
73.2 +++ b/rt/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml Thu Apr 11 16:59:42 2013 +0200
73.3 @@ -31,8 +31,8 @@
73.4
73.5 <h1>Bck2Brwsr Execution Harness</h1>
73.6
73.7 - <textarea id="bck2brwsr.result" rows="25" style="width: 100%;" disabled="">
73.8 - </textarea>
73.9 + <ul id="bck2brwsr.result" style="width: 100%;" >
73.10 + </ul>
73.11
73.12 <div id="bck2brwsr.fragment"/>
73.13
74.1 --- a/rt/mojo/pom.xml Mon Mar 25 13:29:42 2013 +0100
74.2 +++ b/rt/mojo/pom.xml Thu Apr 11 16:59:42 2013 +0200
74.3 @@ -4,13 +4,13 @@
74.4 <parent>
74.5 <groupId>org.apidesign.bck2brwsr</groupId>
74.6 <artifactId>rt</artifactId>
74.7 - <version>0.5-SNAPSHOT</version>
74.8 + <version>0.6-SNAPSHOT</version>
74.9 </parent>
74.10 <groupId>org.apidesign.bck2brwsr</groupId>
74.11 <artifactId>mojo</artifactId>
74.12 - <version>0.5-SNAPSHOT</version>
74.13 + <version>0.6-SNAPSHOT</version>
74.14 <packaging>maven-plugin</packaging>
74.15 - <name>Bck2Brwsr Maven Project</name>
74.16 + <name>Bck2Brwsr Maven Plugins</name>
74.17 <url>http://maven.apache.org</url>
74.18 <build>
74.19 <plugins>
74.20 @@ -62,7 +62,7 @@
74.21 <dependency>
74.22 <groupId>${project.groupId}</groupId>
74.23 <artifactId>vm4brwsr</artifactId>
74.24 - <version>0.5-SNAPSHOT</version>
74.25 + <version>${project.version}</version>
74.26 <exclusions>
74.27 <exclusion>
74.28 <artifactId>emul.mini</artifactId>
74.29 @@ -81,11 +81,5 @@
74.30 <artifactId>launcher</artifactId>
74.31 <version>${project.version}</version>
74.32 </dependency>
74.33 - <dependency>
74.34 - <groupId>org.testng</groupId>
74.35 - <artifactId>testng</artifactId>
74.36 - <version>6.5.2</version>
74.37 - <scope>test</scope>
74.38 - </dependency>
74.39 </dependencies>
74.40 </project>
75.1 --- a/rt/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml Mon Mar 25 13:29:42 2013 +0100
75.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
75.3 @@ -1,55 +0,0 @@
75.4 -<?xml version="1.0" encoding="UTF-8"?>
75.5 -<!--
75.6 -
75.7 - Back 2 Browser Bytecode Translator
75.8 - Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
75.9 -
75.10 - This program is free software: you can redistribute it and/or modify
75.11 - it under the terms of the GNU General Public License as published by
75.12 - the Free Software Foundation, version 2 of the License.
75.13 -
75.14 - This program is distributed in the hope that it will be useful,
75.15 - but WITHOUT ANY WARRANTY; without even the implied warranty of
75.16 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75.17 - GNU General Public License for more details.
75.18 -
75.19 - You should have received a copy of the GNU General Public License
75.20 - along with this program. Look for COPYING file in the top folder.
75.21 - If not, see http://opensource.org/licenses/GPL-2.0.
75.22 -
75.23 --->
75.24 -<archetype-descriptor name="Get Java Bck2Brwsr!">
75.25 - <fileSets>
75.26 - <fileSet filtered="true" packaged="true">
75.27 - <directory>src/main/java</directory>
75.28 - <includes>
75.29 - <include>**/App.java</include>
75.30 - </includes>
75.31 - </fileSet>
75.32 - <fileSet filtered="true" packaged="true">
75.33 - <directory>src/main/resources</directory>
75.34 - <includes>
75.35 - <include>**/*.xhtml</include>
75.36 - <include>**/*.html</include>
75.37 - </includes>
75.38 - </fileSet>
75.39 - <fileSet filtered="true" packaged="true">
75.40 - <directory>src/test/java</directory>
75.41 - <includes>
75.42 - <include>**/*Test.java</include>
75.43 - </includes>
75.44 - </fileSet>
75.45 - <fileSet filtered="false" packaged="false">
75.46 - <directory></directory>
75.47 - <includes>
75.48 - <include>nbactions.xml</include>
75.49 - </includes>
75.50 - </fileSet>
75.51 - <fileSet filtered="true" packaged="false">
75.52 - <directory></directory>
75.53 - <includes>
75.54 - <include>bck2brwsr-assembly.xml</include>
75.55 - </includes>
75.56 - </fileSet>
75.57 - </fileSets>
75.58 -</archetype-descriptor>
75.59 \ No newline at end of file
76.1 --- a/rt/mojo/src/main/resources/archetype-resources/bck2brwsr-assembly.xml Mon Mar 25 13:29:42 2013 +0100
76.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
76.3 @@ -1,61 +0,0 @@
76.4 -<?xml version="1.0"?>
76.5 -<!--
76.6 -
76.7 - Back 2 Browser Bytecode Translator
76.8 - Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
76.9 -
76.10 - This program is free software: you can redistribute it and/or modify
76.11 - it under the terms of the GNU General Public License as published by
76.12 - the Free Software Foundation, version 2 of the License.
76.13 -
76.14 - This program is distributed in the hope that it will be useful,
76.15 - but WITHOUT ANY WARRANTY; without even the implied warranty of
76.16 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
76.17 - GNU General Public License for more details.
76.18 -
76.19 - You should have received a copy of the GNU General Public License
76.20 - along with this program. Look for COPYING file in the top folder.
76.21 - If not, see http://opensource.org/licenses/GPL-2.0.
76.22 -
76.23 --->
76.24 -<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
76.25 - xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
76.26 -
76.27 - <id>bck2brwsr</id>
76.28 - <formats>
76.29 - <format>zip</format>
76.30 - </formats>
76.31 - <baseDirectory>public_html</baseDirectory>
76.32 - <dependencySets>
76.33 - <dependencySet>
76.34 - <useProjectArtifact>false</useProjectArtifact>
76.35 - <scope>runtime</scope>
76.36 - <outputDirectory>lib</outputDirectory>
76.37 - <includes>
76.38 - <include>*:jar</include>
76.39 - <include>*:rt</include>
76.40 - </includes>
76.41 - </dependencySet>
76.42 - <dependencySet>
76.43 - <useProjectArtifact>false</useProjectArtifact>
76.44 - <scope>provided</scope>
76.45 - <includes>
76.46 - <include>*:js</include>
76.47 - </includes>
76.48 - <unpack>true</unpack>
76.49 - <outputDirectory>/</outputDirectory>
76.50 - </dependencySet>
76.51 - </dependencySets>
76.52 - <files>
76.53 - <file>
76.54 - <source>${project.build.directory}/${project.build.finalName}.jar</source>
76.55 - <outputDirectory>/</outputDirectory>
76.56 - </file>
76.57 - <file>
76.58 - <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
76.59 - <outputDirectory>/</outputDirectory>
76.60 - <destName>index.html</destName>
76.61 - </file>
76.62 - </files>
76.63 -
76.64 -</assembly>
76.65 \ No newline at end of file
77.1 --- a/rt/mojo/src/main/resources/archetype-resources/nbactions.xml Mon Mar 25 13:29:42 2013 +0100
77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
77.3 @@ -1,10 +0,0 @@
77.4 -<?xml version="1.0" encoding="UTF-8"?>
77.5 -<actions>
77.6 - <action>
77.7 - <actionName>run</actionName>
77.8 - <goals>
77.9 - <goal>process-classes</goal>
77.10 - <goal>org.apidesign.bck2brwsr:mojo:0.5-SNAPSHOT:brwsr</goal>
77.11 - </goals>
77.12 - </action>
77.13 -</actions>
78.1 --- a/rt/mojo/src/main/resources/archetype-resources/pom.xml Mon Mar 25 13:29:42 2013 +0100
78.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
78.3 @@ -1,135 +0,0 @@
78.4 -<?xml version="1.0"?>
78.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
78.6 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
78.7 - <modelVersion>4.0.0</modelVersion>
78.8 -
78.9 - <groupId>${groupId}</groupId>
78.10 - <artifactId>${artifactId}</artifactId>
78.11 - <version>${version}</version>
78.12 - <packaging>jar</packaging>
78.13 -
78.14 - <name>${artifactId}</name>
78.15 -
78.16 - <repositories>
78.17 - <repository>
78.18 - <id>java.net</id>
78.19 - <name>Java.net</name>
78.20 - <url>https://maven.java.net/content/repositories/releases/</url>
78.21 - <snapshots>
78.22 - <enabled>true</enabled>
78.23 - </snapshots>
78.24 - </repository>
78.25 - <repository>
78.26 - <id>netbeans</id>
78.27 - <name>NetBeans</name>
78.28 - <url>http://bits.netbeans.org/maven2/</url>
78.29 - </repository>
78.30 - </repositories>
78.31 - <pluginRepositories>
78.32 - <pluginRepository>
78.33 - <id>java.net</id>
78.34 - <name>Java.net</name>
78.35 - <url>https://maven.java.net/content/repositories/releases/</url>
78.36 - <snapshots>
78.37 - <enabled>true</enabled>
78.38 - </snapshots>
78.39 - </pluginRepository>
78.40 - </pluginRepositories>
78.41 -
78.42 - <properties>
78.43 - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
78.44 - </properties>
78.45 - <build>
78.46 - <plugins>
78.47 - <plugin>
78.48 - <groupId>org.apidesign.bck2brwsr</groupId>
78.49 - <artifactId>mojo</artifactId>
78.50 - <version>0.5-SNAPSHOT</version>
78.51 - <executions>
78.52 - <execution>
78.53 - <goals>
78.54 - <goal>brwsr</goal>
78.55 - </goals>
78.56 - </execution>
78.57 - </executions>
78.58 - <configuration>
78.59 - <startpage>${package.replace('.','/')}/index.html</startpage>
78.60 - </configuration>
78.61 - </plugin>
78.62 - <plugin>
78.63 - <groupId>org.apache.maven.plugins</groupId>
78.64 - <artifactId>maven-compiler-plugin</artifactId>
78.65 - <version>2.3.2</version>
78.66 - <configuration>
78.67 - <source>1.7</source>
78.68 - <target>1.7</target>
78.69 - </configuration>
78.70 - </plugin>
78.71 - <plugin>
78.72 - <groupId>org.apache.maven.plugins</groupId>
78.73 - <artifactId>maven-jar-plugin</artifactId>
78.74 - <version>2.4</version>
78.75 - <configuration>
78.76 - <archive>
78.77 - <manifest>
78.78 - <addClasspath>true</addClasspath>
78.79 - <classpathPrefix>lib/</classpathPrefix>
78.80 - </manifest>
78.81 - </archive>
78.82 - </configuration>
78.83 - </plugin>
78.84 - <plugin>
78.85 - <artifactId>maven-assembly-plugin</artifactId>
78.86 - <version>2.4</version>
78.87 - <executions>
78.88 - <execution>
78.89 - <id>distro-assembly</id>
78.90 - <phase>package</phase>
78.91 - <goals>
78.92 - <goal>single</goal>
78.93 - </goals>
78.94 - <configuration>
78.95 - <descriptors>
78.96 - <descriptor>bck2brwsr-assembly.xml</descriptor>
78.97 - </descriptors>
78.98 - </configuration>
78.99 - </execution>
78.100 - </executions>
78.101 - </plugin>
78.102 - </plugins>
78.103 - </build>
78.104 -
78.105 - <dependencies>
78.106 - <dependency>
78.107 - <groupId>org.apidesign.bck2brwsr</groupId>
78.108 - <artifactId>emul</artifactId>
78.109 - <version>0.5-SNAPSHOT</version>
78.110 - <classifier>rt</classifier>
78.111 - </dependency>
78.112 - <dependency>
78.113 - <groupId>org.apidesign.bck2brwsr</groupId>
78.114 - <artifactId>javaquery.api</artifactId>
78.115 - <version>0.5-SNAPSHOT</version>
78.116 - </dependency>
78.117 - <dependency>
78.118 - <groupId>org.testng</groupId>
78.119 - <artifactId>testng</artifactId>
78.120 - <version>6.5.2</version>
78.121 - <scope>test</scope>
78.122 - </dependency>
78.123 - <dependency>
78.124 - <groupId>org.apidesign.bck2brwsr</groupId>
78.125 - <artifactId>vm4brwsr</artifactId>
78.126 - <classifier>js</classifier>
78.127 - <type>zip</type>
78.128 - <version>0.5-SNAPSHOT</version>
78.129 - <scope>provided</scope>
78.130 - </dependency>
78.131 - <dependency>
78.132 - <groupId>org.apidesign.bck2brwsr</groupId>
78.133 - <artifactId>vmtest</artifactId>
78.134 - <version>0.5-SNAPSHOT</version>
78.135 - <scope>test</scope>
78.136 - </dependency>
78.137 - </dependencies>
78.138 -</project>
79.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/main/java/App.java Mon Mar 25 13:29:42 2013 +0100
79.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
79.3 @@ -1,34 +0,0 @@
79.4 -package ${package};
79.5 -
79.6 -import org.apidesign.bck2brwsr.htmlpage.api.*;
79.7 -import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
79.8 -import org.apidesign.bck2brwsr.htmlpage.api.Page;
79.9 -import org.apidesign.bck2brwsr.htmlpage.api.Property;
79.10 -import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
79.11 -
79.12 -/** Edit the index.xhtml file. Use 'id' to name certain HTML elements.
79.13 - * Use this class to define behavior of the elements.
79.14 - */
79.15 -@Page(xhtml="index.html", className="Index", properties={
79.16 - @Property(name="name", type=String.class)
79.17 -})
79.18 -public class App {
79.19 - static {
79.20 - Index model = new Index();
79.21 - model.setName("World");
79.22 - model.applyBindings();
79.23 - }
79.24 -
79.25 - @On(event = CLICK, id="hello")
79.26 - static void hello(Index m) {
79.27 - GraphicsContext g = m.CANVAS.getContext();
79.28 - g.clearRect(0, 0, 1000, 1000);
79.29 - g.setFont("italic 40px Calibri");
79.30 - g.fillText(m.getHelloMessage(), 10, 40);
79.31 - }
79.32 -
79.33 - @ComputedProperty
79.34 - static String helloMessage(String name) {
79.35 - return "Hello " + name + "!";
79.36 - }
79.37 -}
80.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/main/resources/index.html Mon Mar 25 13:29:42 2013 +0100
80.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
80.3 @@ -1,22 +0,0 @@
80.4 -<?xml version="1.0" encoding="UTF-8"?>
80.5 -<!DOCTYPE html>
80.6 -<html xmlns="http://www.w3.org/1999/xhtml">
80.7 - <head>
80.8 - <title>Bck2Brwsr's Hello World</title>
80.9 - </head>
80.10 - <body>
80.11 - <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
80.12 - Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
80.13 - <button id="hello">Say Hello!</button>
80.14 - <p>
80.15 - <canvas id="canvas" width="300" height="50">
80.16 - </canvas>
80.17 - </p>
80.18 -
80.19 - <script src="bck2brwsr.js"></script>
80.20 - <script type="text/javascript">
80.21 - var vm = bck2brwsr('${artifactId}-${version}.jar');
80.22 - vm.loadClass('${package}.App');
80.23 - </script>
80.24 - </body>
80.25 -</html>
81.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java Mon Mar 25 13:29:42 2013 +0100
81.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
81.3 @@ -1,26 +0,0 @@
81.4 -package ${package};
81.5 -
81.6 -import static org.testng.Assert.*;
81.7 -import org.testng.annotations.BeforeMethod;
81.8 -import org.testng.annotations.Test;
81.9 -
81.10 -/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot
81.11 - * as it does not reference any HTML elements or browser functionality. Just
81.12 - * operates on the page model.
81.13 - *
81.14 - * @author Jaroslav Tulach <jtulach@netbeans.org>
81.15 - */
81.16 -public class AppTest {
81.17 - private Index model;
81.18 -
81.19 -
81.20 - @BeforeMethod
81.21 - public void initModel() {
81.22 - model = new Index().applyBindings();
81.23 - }
81.24 -
81.25 - @Test public void testHelloMessage() {
81.26 - model.setName("Joe");
81.27 - assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +");
81.28 - }
81.29 -}
82.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java Mon Mar 25 13:29:42 2013 +0100
82.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
82.3 @@ -1,40 +0,0 @@
82.4 -package ${package};
82.5 -
82.6 -import org.apidesign.bck2brwsr.vmtest.Compare;
82.7 -import org.apidesign.bck2brwsr.vmtest.VMTest;
82.8 -import org.testng.annotations.Factory;
82.9 -
82.10 -/** Bck2brwsr cares about compatibility with real Java. Whatever API is
82.11 - * supported by bck2brwsr, it needs to behave the same way as when running
82.12 - * in HotSpot VM.
82.13 - * <p>
82.14 - * There can be bugs, however. To help us fix them, we kindly ask you to
82.15 - * write an "inconsistency" test. A test that compares behavior of the API
82.16 - * between real VM and bck2brwsr VM. This class is skeleton of such test.
82.17 - *
82.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
82.19 - */
82.20 -public class InconsistencyTest {
82.21 - /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
82.22 - * Make calls to an API that behaves strangely, return some result at
82.23 - * the end. No need to use any <code>assert</code>.
82.24 - *
82.25 - * @return value to compare between HotSpot and bck2brwsr
82.26 - */
82.27 - @Compare
82.28 - public int checkStringHashCode() throws Exception {
82.29 - return "Is string hashCode the same?".hashCode();
82.30 - }
82.31 -
82.32 - /** Factory method that creates a three tests for each method annotated with
82.33 - * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
82.34 - * HotSpot, one in Rhino and the last one compares the results.
82.35 - *
82.36 - * @see org.apidesign.bck2brwsr.vmtest.VMTest
82.37 - */
82.38 - @Factory
82.39 - public static Object[] create() {
82.40 - return VMTest.create(InconsistencyTest.class);
82.41 - }
82.42 -
82.43 -}
83.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java Mon Mar 25 13:29:42 2013 +0100
83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
83.3 @@ -1,46 +0,0 @@
83.4 -package ${package};
83.5 -
83.6 -import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
83.7 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
83.8 -import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
83.9 -import org.apidesign.bck2brwsr.vmtest.VMTest;
83.10 -import org.testng.annotations.Factory;
83.11 -
83.12 -/** Sometimes it is useful to run tests inside of the real browser.
83.13 - * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
83.14 - * and that is it. If your code references elements on the HTML page,
83.15 - * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
83.16 - * will be made available on the page before your test starts.
83.17 - *
83.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
83.19 - */
83.20 -public class IntegrationTest {
83.21 -
83.22 - /** Write to testing code here. Use <code>assert</code> (but not TestNG's
83.23 - * Assert, as TestNG is not compiled with target 1.6 yet).
83.24 - */
83.25 - @HtmlFragment(
83.26 - "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
83.27 - "Your name: <input id='input' data-bind=\"value: name, valueUpdate: 'afterkeydown'\"></input>\n" +
83.28 - "<button id=\"hello\">Say Hello!</button>\n" +
83.29 - "<p>\n" +
83.30 - " <canvas id=\"canvas\" width=\"300\" height=\"50\"></canvas>\n" +
83.31 - "</p>\n"
83.32 - )
83.33 - @BrwsrTest
83.34 - public void modifyValueAssertChangeInModel() {
83.35 - Index m = new Index();
83.36 - m.setName("Joe Hacker");
83.37 - m.applyBindings();
83.38 - assert "Joe Hacker".equals(m.INPUT.getValue()) : "Value is really Joe Hacker: " + m.INPUT.getValue();
83.39 - m.INPUT.setValue("Happy Joe");
83.40 - m.triggerEvent(m.INPUT, OnEvent.CHANGE);
83.41 - assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName();
83.42 - }
83.43 -
83.44 - @Factory
83.45 - public static Object[] create() {
83.46 - return VMTest.create(IntegrationTest.class);
83.47 - }
83.48 -
83.49 -}
84.1 --- a/rt/mojo/src/test/java/org/apidesign/bck2brwsr/mojo/ArchetypeVersionTest.java Mon Mar 25 13:29:42 2013 +0100
84.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
84.3 @@ -1,102 +0,0 @@
84.4 -/**
84.5 - * Back 2 Browser Bytecode Translator
84.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
84.7 - *
84.8 - * This program is free software: you can redistribute it and/or modify
84.9 - * it under the terms of the GNU General Public License as published by
84.10 - * the Free Software Foundation, version 2 of the License.
84.11 - *
84.12 - * This program is distributed in the hope that it will be useful,
84.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
84.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84.15 - * GNU General Public License for more details.
84.16 - *
84.17 - * You should have received a copy of the GNU General Public License
84.18 - * along with this program. Look for COPYING file in the top folder.
84.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
84.20 - */
84.21 -package org.apidesign.bck2brwsr.mojo;
84.22 -
84.23 -import java.net.URL;
84.24 -import javax.xml.XMLConstants;
84.25 -import javax.xml.parsers.DocumentBuilderFactory;
84.26 -import javax.xml.xpath.XPathConstants;
84.27 -import javax.xml.xpath.XPathExpression;
84.28 -import javax.xml.xpath.XPathFactory;
84.29 -import org.testng.annotations.Test;
84.30 -import org.xml.sax.InputSource;
84.31 -import static org.testng.Assert.*;
84.32 -import org.testng.annotations.BeforeClass;
84.33 -import org.w3c.dom.Document;
84.34 -import org.w3c.dom.NodeList;
84.35 -
84.36 -/**
84.37 - *
84.38 - * @author Jaroslav Tulach <jtulach@netbeans.org>
84.39 - */
84.40 -public class ArchetypeVersionTest {
84.41 - private String version;
84.42 -
84.43 - public ArchetypeVersionTest() {
84.44 - }
84.45 -
84.46 - @BeforeClass public void readCurrentVersion() throws Exception {
84.47 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
84.48 - URL u = l.getResource("META-INF/maven/org.apidesign.bck2brwsr/mojo/plugin-help.xml");
84.49 - assertNotNull(u, "Own pom found");
84.50 -
84.51 - final XPathFactory fact = XPathFactory.newInstance();
84.52 - fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
84.53 -
84.54 - XPathExpression xp = fact.newXPath().compile("plugin/version/text()");
84.55 - version = xp.evaluate(new InputSource(u.openStream()));
84.56 -
84.57 - assertFalse(version.isEmpty(), "There should be some version string");
84.58 - }
84.59 -
84.60 -
84.61 - @Test public void testComparePomDepsVersions() throws Exception {
84.62 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
84.63 - URL r = l.getResource("archetype-resources/pom.xml");
84.64 - assertNotNull(r, "Archetype pom found");
84.65 -
84.66 - final XPathFactory fact = XPathFactory.newInstance();
84.67 - XPathExpression xp2 = fact.newXPath().compile(
84.68 - "//version[../groupId/text() = 'org.apidesign.bck2brwsr']/text()"
84.69 - );
84.70 -
84.71 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
84.72 - NodeList arch = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
84.73 -
84.74 - if (arch.getLength() < 3) {
84.75 - fail("There should be at least three dependencies to bck2brwsr APIs: " + arch.getLength());
84.76 - }
84.77 -
84.78 - for (int i = 0; i < arch.getLength(); i++) {
84.79 - assertEquals(arch.item(i).getTextContent(), version, i + "th dependency needs to be on latest version of bck2brwsr");
84.80 - }
84.81 - }
84.82 -
84.83 - @Test public void testNbActions() throws Exception {
84.84 - final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
84.85 - URL r = l.getResource("archetype-resources/nbactions.xml");
84.86 - assertNotNull(r, "Archetype nb file found");
84.87 -
84.88 - final XPathFactory fact = XPathFactory.newInstance();
84.89 - XPathExpression xp2 = fact.newXPath().compile(
84.90 - "//goal/text()"
84.91 - );
84.92 -
84.93 - Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
84.94 - NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
84.95 -
84.96 - for (int i = 0; i < goals.getLength(); i++) {
84.97 - String s = goals.item(i).getTextContent();
84.98 - if (s.contains("bck2brwsr")) {
84.99 - String[] arr = s.split(":");
84.100 - assertEquals(arr.length, 4, "Three :");
84.101 - assertEquals(arr[2], version, "Proper version is used");
84.102 - }
84.103 - }
84.104 - }
84.105 -}
85.1 --- a/rt/pom.xml Mon Mar 25 13:29:42 2013 +0100
85.2 +++ b/rt/pom.xml Thu Apr 11 16:59:42 2013 +0200
85.3 @@ -3,18 +3,19 @@
85.4 <modelVersion>4.0.0</modelVersion>
85.5 <groupId>org.apidesign.bck2brwsr</groupId>
85.6 <artifactId>rt</artifactId>
85.7 - <version>0.5-SNAPSHOT</version>
85.8 + <version>0.6-SNAPSHOT</version>
85.9 <packaging>pom</packaging>
85.10 <name>Bck2Brwsr Runtime</name>
85.11 <parent>
85.12 <groupId>org.apidesign</groupId>
85.13 <artifactId>bck2brwsr</artifactId>
85.14 - <version>0.5-SNAPSHOT</version>
85.15 + <version>0.6-SNAPSHOT</version>
85.16 </parent>
85.17 <modules>
85.18 <module>core</module>
85.19 <module>emul</module>
85.20 <module>launcher</module>
85.21 + <module>archetype</module>
85.22 <module>mojo</module>
85.23 <module>vm</module>
85.24 <module>vmtest</module>
86.1 --- a/rt/vm/pom.xml Mon Mar 25 13:29:42 2013 +0100
86.2 +++ b/rt/vm/pom.xml Thu Apr 11 16:59:42 2013 +0200
86.3 @@ -3,12 +3,12 @@
86.4 <parent>
86.5 <groupId>org.apidesign.bck2brwsr</groupId>
86.6 <artifactId>rt</artifactId>
86.7 - <version>0.5-SNAPSHOT</version>
86.8 + <version>0.6-SNAPSHOT</version>
86.9 </parent>
86.10
86.11 <groupId>org.apidesign.bck2brwsr</groupId>
86.12 <artifactId>vm4brwsr</artifactId>
86.13 - <version>0.5-SNAPSHOT</version>
86.14 + <version>0.6-SNAPSHOT</version>
86.15 <packaging>jar</packaging>
86.16
86.17 <name>Virtual Machine for Browser</name>
86.18 @@ -87,7 +87,7 @@
86.19 <executable>java</executable>
86.20 <arguments>
86.21 <argument>-cp</argument>
86.22 - <classpath/>
86.23 + <classpath />
86.24 <argument>org.apidesign.vm4brwsr.Main</argument>
86.25 <argument>--obfuscatelevel</argument>
86.26 <argument>MINIMAL</argument>
87.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Mar 25 13:29:42 2013 +0100
87.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Apr 11 16:59:42 2013 +0200
87.3 @@ -805,7 +805,7 @@
87.4 }
87.5 case opc_ldc_w:
87.6 case opc_ldc2_w: {
87.7 - int indx = readIntArg(byteCodes, i);
87.8 + int indx = readUShortArg(byteCodes, i);
87.9 i += 2;
87.10 String v = encodeConstant(indx);
87.11 int type = VarType.fromConstantType(jc.getTag(indx));
87.12 @@ -847,56 +847,56 @@
87.13 "==", topMostLabel);
87.14 break;
87.15 case opc_ifeq: {
87.16 - int indx = i + readIntArg(byteCodes, i);
87.17 + int indx = i + readShortArg(byteCodes, i);
87.18 emitIf(out, "if (@1 == 0) ",
87.19 smapper.popI(), i, indx, topMostLabel);
87.20 i += 2;
87.21 break;
87.22 }
87.23 case opc_ifne: {
87.24 - int indx = i + readIntArg(byteCodes, i);
87.25 + int indx = i + readShortArg(byteCodes, i);
87.26 emitIf(out, "if (@1 != 0) ",
87.27 smapper.popI(), i, indx, topMostLabel);
87.28 i += 2;
87.29 break;
87.30 }
87.31 case opc_iflt: {
87.32 - int indx = i + readIntArg(byteCodes, i);
87.33 + int indx = i + readShortArg(byteCodes, i);
87.34 emitIf(out, "if (@1 < 0) ",
87.35 smapper.popI(), i, indx, topMostLabel);
87.36 i += 2;
87.37 break;
87.38 }
87.39 case opc_ifle: {
87.40 - int indx = i + readIntArg(byteCodes, i);
87.41 + int indx = i + readShortArg(byteCodes, i);
87.42 emitIf(out, "if (@1 <= 0) ",
87.43 smapper.popI(), i, indx, topMostLabel);
87.44 i += 2;
87.45 break;
87.46 }
87.47 case opc_ifgt: {
87.48 - int indx = i + readIntArg(byteCodes, i);
87.49 + int indx = i + readShortArg(byteCodes, i);
87.50 emitIf(out, "if (@1 > 0) ",
87.51 smapper.popI(), i, indx, topMostLabel);
87.52 i += 2;
87.53 break;
87.54 }
87.55 case opc_ifge: {
87.56 - int indx = i + readIntArg(byteCodes, i);
87.57 + int indx = i + readShortArg(byteCodes, i);
87.58 emitIf(out, "if (@1 >= 0) ",
87.59 smapper.popI(), i, indx, topMostLabel);
87.60 i += 2;
87.61 break;
87.62 }
87.63 case opc_ifnonnull: {
87.64 - int indx = i + readIntArg(byteCodes, i);
87.65 + int indx = i + readShortArg(byteCodes, i);
87.66 emitIf(out, "if (@1 !== null) ",
87.67 smapper.popA(), i, indx, topMostLabel);
87.68 i += 2;
87.69 break;
87.70 }
87.71 case opc_ifnull: {
87.72 - int indx = i + readIntArg(byteCodes, i);
87.73 + int indx = i + readShortArg(byteCodes, i);
87.74 emitIf(out, "if (@1 === null) ",
87.75 smapper.popA(), i, indx, topMostLabel);
87.76 i += 2;
87.77 @@ -923,7 +923,7 @@
87.78 ">=", topMostLabel);
87.79 break;
87.80 case opc_goto: {
87.81 - int indx = i + readIntArg(byteCodes, i);
87.82 + int indx = i + readShortArg(byteCodes, i);
87.83 goTo(out, i, indx, topMostLabel);
87.84 i += 2;
87.85 break;
87.86 @@ -950,7 +950,7 @@
87.87 i = invokeStaticMethod(byteCodes, i, smapper, true);
87.88 break;
87.89 case opc_new: {
87.90 - int indx = readIntArg(byteCodes, i);
87.91 + int indx = readUShortArg(byteCodes, i);
87.92 String ci = jc.getClassName(indx);
87.93 emit(out, "var @1 = new @2;",
87.94 smapper.pushA(), accessClass(ci.replace('/', '_')));
87.95 @@ -963,13 +963,13 @@
87.96 generateNewArray(atype, smapper);
87.97 break;
87.98 case opc_anewarray: {
87.99 - int type = readIntArg(byteCodes, i);
87.100 + int type = readUShortArg(byteCodes, i);
87.101 i += 2;
87.102 generateANewArray(type, smapper);
87.103 break;
87.104 }
87.105 case opc_multianewarray: {
87.106 - int type = readIntArg(byteCodes, i);
87.107 + int type = readUShortArg(byteCodes, i);
87.108 i += 2;
87.109 i = generateMultiANewArray(type, byteCodes, i, smapper);
87.110 break;
87.111 @@ -1185,11 +1185,11 @@
87.112 case opc_sipush:
87.113 emit(out, "var @1 = @2;",
87.114 smapper.pushI(),
87.115 - Integer.toString(readIntArg(byteCodes, i)));
87.116 + Integer.toString(readShortArg(byteCodes, i)));
87.117 i += 2;
87.118 break;
87.119 case opc_getfield: {
87.120 - int indx = readIntArg(byteCodes, i);
87.121 + int indx = readUShortArg(byteCodes, i);
87.122 String[] fi = jc.getFieldInfoName(indx);
87.123 final int type = VarType.fromFieldType(fi[2].charAt(0));
87.124 final String mangleClass = mangleSig(fi[0]);
87.125 @@ -1202,7 +1202,7 @@
87.126 break;
87.127 }
87.128 case opc_putfield: {
87.129 - int indx = readIntArg(byteCodes, i);
87.130 + int indx = readUShortArg(byteCodes, i);
87.131 String[] fi = jc.getFieldInfoName(indx);
87.132 final int type = VarType.fromFieldType(fi[2].charAt(0));
87.133 final String mangleClass = mangleSig(fi[0]);
87.134 @@ -1216,7 +1216,7 @@
87.135 break;
87.136 }
87.137 case opc_getstatic: {
87.138 - int indx = readIntArg(byteCodes, i);
87.139 + int indx = readUShortArg(byteCodes, i);
87.140 String[] fi = jc.getFieldInfoName(indx);
87.141 final int type = VarType.fromFieldType(fi[2].charAt(0));
87.142 emit(out, "var @1 = @2(false)._@3();",
87.143 @@ -1227,7 +1227,7 @@
87.144 break;
87.145 }
87.146 case opc_putstatic: {
87.147 - int indx = readIntArg(byteCodes, i);
87.148 + int indx = readUShortArg(byteCodes, i);
87.149 String[] fi = jc.getFieldInfoName(indx);
87.150 final int type = VarType.fromFieldType(fi[2].charAt(0));
87.151 emit(out, "@1(false)._@2(@3);",
87.152 @@ -1238,13 +1238,13 @@
87.153 break;
87.154 }
87.155 case opc_checkcast: {
87.156 - int indx = readIntArg(byteCodes, i);
87.157 + int indx = readUShortArg(byteCodes, i);
87.158 generateCheckcast(indx, smapper);
87.159 i += 2;
87.160 break;
87.161 }
87.162 case opc_instanceof: {
87.163 - int indx = readIntArg(byteCodes, i);
87.164 + int indx = readUShortArg(byteCodes, i);
87.165 generateInstanceOf(indx, smapper);
87.166 i += 2;
87.167 break;
87.168 @@ -1296,7 +1296,7 @@
87.169 }
87.170
87.171 private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException {
87.172 - int indx = i + readIntArg(byteCodes, i);
87.173 + int indx = i + readShortArg(byteCodes, i);
87.174 out.append("if (").append(v1)
87.175 .append(' ').append(test).append(' ')
87.176 .append(v2).append(") ");
87.177 @@ -1304,11 +1304,6 @@
87.178 return i + 2;
87.179 }
87.180
87.181 - private int readIntArg(byte[] byteCodes, int offsetInstruction) {
87.182 - final int indxHi = byteCodes[offsetInstruction + 1] << 8;
87.183 - final int indxLo = byteCodes[offsetInstruction + 2];
87.184 - return (indxHi & 0xffffff00) | (indxLo & 0xff);
87.185 - }
87.186 private int readInt4(byte[] byteCodes, int offset) {
87.187 final int d = byteCodes[offset + 0] << 24;
87.188 final int c = byteCodes[offset + 1] << 16;
87.189 @@ -1316,18 +1311,25 @@
87.190 final int a = byteCodes[offset + 3];
87.191 return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
87.192 }
87.193 - private int readUByte(byte[] byteCodes, int offset) {
87.194 + private static int readUByte(byte[] byteCodes, int offset) {
87.195 return byteCodes[offset] & 0xff;
87.196 }
87.197
87.198 - private int readUShort(byte[] byteCodes, int offset) {
87.199 + private static int readUShort(byte[] byteCodes, int offset) {
87.200 return ((byteCodes[offset] & 0xff) << 8)
87.201 | (byteCodes[offset + 1] & 0xff);
87.202 }
87.203 + private static int readUShortArg(byte[] byteCodes, int offsetInstruction) {
87.204 + return readUShort(byteCodes, offsetInstruction + 1);
87.205 + }
87.206
87.207 - private int readShort(byte[] byteCodes, int offset) {
87.208 - return (byteCodes[offset] << 8)
87.209 - | (byteCodes[offset + 1] & 0xff);
87.210 + private static int readShort(byte[] byteCodes, int offset) {
87.211 + int signed = byteCodes[offset];
87.212 + byte b0 = (byte)signed;
87.213 + return (b0 << 8) | (byteCodes[offset + 1] & 0xff);
87.214 + }
87.215 + private static int readShortArg(byte[] byteCodes, int offsetInstruction) {
87.216 + return readShort(byteCodes, offsetInstruction + 1);
87.217 }
87.218
87.219 private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
87.220 @@ -1455,7 +1457,7 @@
87.221
87.222 private int invokeStaticMethod(byte[] byteCodes, int i, final StackMapper mapper, boolean isStatic)
87.223 throws IOException {
87.224 - int methodIndex = readIntArg(byteCodes, i);
87.225 + int methodIndex = readUShortArg(byteCodes, i);
87.226 String[] mi = jc.getFieldInfoName(methodIndex);
87.227 char[] returnType = { 'V' };
87.228 StringBuilder cnt = new StringBuilder();
87.229 @@ -1500,7 +1502,7 @@
87.230 }
87.231 private int invokeVirtualMethod(byte[] byteCodes, int i, final StackMapper mapper)
87.232 throws IOException {
87.233 - int methodIndex = readIntArg(byteCodes, i);
87.234 + int methodIndex = readUShortArg(byteCodes, i);
87.235 String[] mi = jc.getFieldInfoName(methodIndex);
87.236 char[] returnType = { 'V' };
87.237 StringBuilder cnt = new StringBuilder();
87.238 @@ -1938,7 +1940,7 @@
87.239 final String type = jc.getClassName(indx);
87.240 if (!type.startsWith("[")) {
87.241 emit(out,
87.242 - "if (@1 !== null && !@1.$instOf_@2) throw {};",
87.243 + "if (@1 !== null && !@1.$instOf_@2) throw vm.java_lang_ClassCastException(true);",
87.244 smapper.getA(0), type.replace('/', '_'));
87.245 } else {
87.246 emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);",
88.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Mon Mar 25 13:29:42 2013 +0100
88.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Thu Apr 11 16:59:42 2013 +0200
88.3 @@ -207,5 +207,12 @@
88.4 true
88.5 );
88.6 }
88.7 +
88.8 + @Test public void valueOfEnum() throws Exception {
88.9 + assertExec("can get value of enum", Classes.class,
88.10 + "valueEnum__Ljava_lang_String_2Ljava_lang_String_2",
88.11 + "TWO", "TWO"
88.12 + );
88.13 + }
88.14
88.15 }
89.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Mon Mar 25 13:29:42 2013 +0100
89.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Thu Apr 11 16:59:42 2013 +0200
89.3 @@ -230,4 +230,7 @@
89.4 return Application.class.isAssignableFrom(MyApplication.class);
89.5 }
89.6
89.7 + public static String valueEnum(String v) {
89.8 + return ClassesMarker.E.valueOf(v).toString();
89.9 + }
89.10 }
90.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java Mon Mar 25 13:29:42 2013 +0100
90.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java Thu Apr 11 16:59:42 2013 +0200
90.3 @@ -18,6 +18,7 @@
90.4 package org.apidesign.vm4brwsr;
90.5
90.6 import java.io.UnsupportedEncodingException;
90.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
90.8
90.9 /**
90.10 *
90.11 @@ -129,4 +130,20 @@
90.12 public String toString() {
90.13 return HELLO + cnt;
90.14 }
90.15 +
90.16 + @JavaScriptBody(args = {}, body = "return [1, 2];")
90.17 + private static native Object crtarr();
90.18 + @JavaScriptBody(args = { "o" }, body = "return o.toString();")
90.19 + private static native String toStrng(Object o);
90.20 +
90.21 + public static String toStringArray(boolean fakeArr, boolean toString) {
90.22 + final Object arr = fakeArr ? crtarr() : new Object[2];
90.23 + final String whole = toString ? arr.toString() : toStrng(arr);
90.24 + int zav = whole.indexOf('@');
90.25 + if (zav <= 0) {
90.26 + zav = whole.length();
90.27 + }
90.28 + return whole.substring(0, zav).toString().toString();
90.29 + }
90.30 +
90.31 }
91.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Mon Mar 25 13:29:42 2013 +0100
91.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Thu Apr 11 16:59:42 2013 +0200
91.3 @@ -194,6 +194,34 @@
91.4
91.5 }
91.6
91.7 + @Test public void toStringOnJSArray() throws Exception {
91.8 + String exp = StringSample.toStringArray(false, true);
91.9 +
91.10 + assertExec(
91.11 + "Treated as Java Object array",
91.12 + StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
91.13 + exp, true, true
91.14 + );
91.15 + }
91.16 +
91.17 + @Test public void toStringOnRealArray() throws Exception {
91.18 + String exp = StringSample.toStringArray(false, true);
91.19 +
91.20 + assertExec(
91.21 + "Is Java Object array",
91.22 + StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
91.23 + exp, false, true
91.24 + );
91.25 + }
91.26 +
91.27 + @Test public void valueOfOnJSArray() throws Exception {
91.28 + assertExec(
91.29 + "Treated as classical JavaScript array",
91.30 + StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
91.31 + "1,2", true, false
91.32 + );
91.33 + }
91.34 +
91.35 private static TestVM code;
91.36
91.37 @BeforeClass
92.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Mon Mar 25 13:29:42 2013 +0100
92.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Thu Apr 11 16:59:42 2013 +0200
92.3 @@ -40,6 +40,14 @@
92.4 compareCode("org/apidesign/vm4brwsr/Classes.class");
92.5 }
92.6
92.7 + @Test public void compareGeneratedCodeForToolkitClass() throws Exception {
92.8 + String genCode = compareCode("org/apidesign/vm4brwsr/Bck2BrwsrToolkit.class");
92.9 + int indx = genCode.indexOf("gt = 65604");
92.10 + if (indx >= 0) {
92.11 + fail("Goto to an invalid label:\n...." + genCode.substring(indx - 30, indx + 30) + "....");
92.12 + }
92.13 + }
92.14 +
92.15 @BeforeClass
92.16 public static void compileTheCode() throws Exception {
92.17 code = TestVM.compileClass("org/apidesign/vm4brwsr/VMinVM");
92.18 @@ -49,7 +57,7 @@
92.19 code = null;
92.20 }
92.21
92.22 - private void compareCode(final String nm) throws Exception, IOException {
92.23 + private String compareCode(final String nm) throws Exception, IOException {
92.24 byte[] arr = BytesLoader.readClass(nm);
92.25 String ret1 = VMinVM.toJavaScript(arr);
92.26
92.27 @@ -88,5 +96,7 @@
92.28 msg.append(code.toString());
92.29 fail(msg.toString());
92.30 }
92.31 +
92.32 + return ret1;
92.33 }
92.34 }
93.1 Binary file rt/vm/src/test/resources/org/apidesign/vm4brwsr/Bck2BrwsrToolkit.class has changed
94.1 --- a/rt/vmtest/pom.xml Mon Mar 25 13:29:42 2013 +0100
94.2 +++ b/rt/vmtest/pom.xml Thu Apr 11 16:59:42 2013 +0200
94.3 @@ -4,11 +4,11 @@
94.4 <parent>
94.5 <groupId>org.apidesign.bck2brwsr</groupId>
94.6 <artifactId>rt</artifactId>
94.7 - <version>0.5-SNAPSHOT</version>
94.8 + <version>0.6-SNAPSHOT</version>
94.9 </parent>
94.10 <groupId>org.apidesign.bck2brwsr</groupId>
94.11 <artifactId>vmtest</artifactId>
94.12 - <version>0.5-SNAPSHOT</version>
94.13 + <version>0.6-SNAPSHOT</version>
94.14
94.15 <name>VM Testing APIs</name>
94.16 <url>http://bck2brwsr.apidesign.org</url>
95.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/BrwsrTest.java Mon Mar 25 13:29:42 2013 +0100
95.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/BrwsrTest.java Thu Apr 11 16:59:42 2013 +0200
95.3 @@ -29,6 +29,10 @@
95.4 * The browser to is by default executed via {@link java.awt.Desktop#browse(java.net.URI)},
95.5 * but one can change that by specifying <code>-Dvmtest.brwsrs=firefox,google-chrome</code>
95.6 * property.
95.7 + * <p>
95.8 + * If the annotated method throws {@link InterruptedException}, it will return
95.9 + * the processing to the browser and after 100ms, called again. This is useful
95.10 + * for testing asynchronous communication, etc.
95.11 *
95.12 * @author Jaroslav Tulach <jtulach@netbeans.org>
95.13 */
96.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java Mon Mar 25 13:29:42 2013 +0100
96.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java Thu Apr 11 16:59:42 2013 +0200
96.3 @@ -53,5 +53,10 @@
96.4 String resource() default "";
96.5 /** mime type of the resource */
96.6 String mimeType();
96.7 + /** query parameters. Can be referenced from the {@link #content} as
96.8 + * <code>$0</code>, <code>$1</code>, etc. The values will be extracted
96.9 + * from URL parameters of the request.
96.10 + */
96.11 + String[] parameters() default {};
96.12 }
96.13 }
97.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Mon Mar 25 13:29:42 2013 +0100
97.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java Thu Apr 11 16:59:42 2013 +0200
97.3 @@ -65,17 +65,17 @@
97.4 for (Http.Resource r : http) {
97.5 if (!r.content().isEmpty()) {
97.6 InputStream is = new ByteArrayInputStream(r.content().getBytes("UTF-8"));
97.7 - c.addHttpResource(r.path(), r.mimeType(), is);
97.8 + c.addHttpResource(r.path(), r.mimeType(), r.parameters(), is);
97.9 } else {
97.10 InputStream is = m.getDeclaringClass().getResourceAsStream(r.resource());
97.11 - c.addHttpResource(r.path(), r.mimeType(), is);
97.12 + c.addHttpResource(r.path(), r.mimeType(), r.parameters(), is);
97.13 }
97.14 }
97.15 }
97.16 String res = c.invoke();
97.17 value = res;
97.18 if (fail) {
97.19 - int idx = res.indexOf(':');
97.20 + int idx = res == null ? -1 : res.indexOf(':');
97.21 if (idx >= 0) {
97.22 Class<? extends Throwable> thrwbl = null;
97.23 try {
98.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Mon Mar 25 13:29:42 2013 +0100
98.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java Thu Apr 11 16:59:42 2013 +0200
98.3 @@ -17,6 +17,7 @@
98.4 */
98.5 package org.apidesign.bck2brwsr.tck;
98.6
98.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
98.8 import org.apidesign.bck2brwsr.vmtest.Compare;
98.9 import org.apidesign.bck2brwsr.vmtest.VMTest;
98.10 import org.testng.annotations.Factory;
98.11 @@ -94,6 +95,50 @@
98.12 @Compare public byte divisionReminder() {
98.13 return mod((byte)1, (byte)2);
98.14 }
98.15 +
98.16 + private static int readShort(byte[] byteCodes, int offset) {
98.17 + int signed = byteCodes[offset];
98.18 + byte b0 = (byte)signed;
98.19 + return (b0 << 8) | (byteCodes[offset + 1] & 0xff);
98.20 + }
98.21 +
98.22 + private static int readShortArg(byte[] byteCodes, int offsetInstruction) {
98.23 + return readShort(byteCodes, offsetInstruction + 1);
98.24 + }
98.25 +
98.26 + @Compare public int readIntArgs255and156() {
98.27 + final byte[] arr = new byte[] { (byte)0, (byte)255, (byte)156 };
98.28 +
98.29 + assert arr[1] == -1 : "First byte: " + arr[1];
98.30 + assert arr[2] == -100 : "Second byte: " + arr[2];
98.31 + final int ret = readShortArg(arr, 0);
98.32 + assert ret < 65000: "Value: " + ret;
98.33 + return ret;
98.34 + }
98.35 +
98.36 + @JavaScriptBody(args = { "arr" }, body = "arr[1] = 255; arr[2] = 156; return arr;")
98.37 + private static byte[] fill255and156(byte[] arr) {
98.38 + arr[1] = (byte)255;
98.39 + arr[2] = (byte)156;
98.40 + return arr;
98.41 + }
98.42 +
98.43 + @Compare public int readIntArgs255and156JSArray() {
98.44 + final byte[] arr = fill255and156(new byte[] { 0, 0, 0 });
98.45 +
98.46 + final int ret = readShortArg(arr, 0);
98.47 + assert ret < 65000: "Value: " + ret;
98.48 + return ret;
98.49 + }
98.50 +
98.51 + @Compare public int readIntArgsMinus1andMinus100() {
98.52 + final byte[] arr = new byte[] { (byte)0, (byte)-1, (byte)-100 };
98.53 +
98.54 + assert arr[1] == -1 : "First byte: " + arr[1];
98.55 + assert arr[2] == -100 : "Second byte: " + arr[2];
98.56 +
98.57 + return readShortArg(arr, 0);
98.58 + }
98.59
98.60 @Factory
98.61 public static Object[] create() {
99.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Mon Mar 25 13:29:42 2013 +0100
99.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java Thu Apr 11 16:59:42 2013 +0200
99.3 @@ -149,6 +149,18 @@
99.4 public int stringToBytesLenght() throws UnsupportedEncodingException {
99.5 return "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("utf8").length;
99.6 }
99.7 +
99.8 + @Compare public String replaceSeq() {
99.9 + return "Hello World.".replace(".", "!");
99.10 + }
99.11 + @Compare public String replaceSeqAll() {
99.12 + return "Hello World! Hello World.".replace("World", "Jarda");
99.13 + }
99.14 + @Compare public String replaceSeqAA() {
99.15 + String res = "aaa".replace("aa", "b");
99.16 + assert res.equals("ba") : "Expecting ba: " + res;
99.17 + return res;
99.18 + }
99.19
99.20 @Factory
99.21 public static Object[] create() {
100.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java Mon Mar 25 13:29:42 2013 +0100
100.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java Thu Apr 11 16:59:42 2013 +0200
100.3 @@ -18,6 +18,8 @@
100.4 package org.apidesign.bck2brwsr.tck;
100.5
100.6 import java.lang.reflect.Array;
100.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
100.8 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
100.9 import org.apidesign.bck2brwsr.vmtest.Compare;
100.10 import org.apidesign.bck2brwsr.vmtest.VMTest;
100.11 import org.testng.annotations.Factory;
100.12 @@ -127,6 +129,30 @@
100.13 return Array.newInstance(int.class, 3, 3, 3).getClass().getName();
100.14 }
100.15
100.16 + @JavaScriptBody(args = {}, body = "return [1, 2];")
100.17 + private static native Object crtarr();
100.18 +
100.19 + @JavaScriptBody(args = {}, body = "return new Object();")
100.20 + private static native Object newobj();
100.21 +
100.22 + @BrwsrTest
100.23 + public static void toStringArray() {
100.24 + final Object arr = crtarr();
100.25 + final Object real = new Object[2];
100.26 + assert arr instanceof Object[] : "Any array is Java array: " + arr;
100.27 + assert arr.getClass() == real.getClass() : "Same classes " + arr + " and " + real.getClass();
100.28 + final String str = arr.toString();
100.29 + assert str != null;
100.30 + assert str.startsWith("[Ljava.lang.Object;@") : str;
100.31 + }
100.32 +
100.33 + @BrwsrTest
100.34 + public static void objectToString() {
100.35 + String s = newobj().toString();
100.36 + assert s != null : "Some string computed";
100.37 + assert s.startsWith("java.lang.Object@") : "Regular object toString(): " + s;
100.38 + }
100.39 +
100.40
100.41 @Factory
100.42 public static Object[] create() {
101.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Mon Mar 25 13:29:42 2013 +0100
101.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Thu Apr 11 16:59:42 2013 +0200
101.3 @@ -53,6 +53,22 @@
101.4 return Runnable.class.isInterface();
101.5 }
101.6
101.7 + @Compare public boolean isAssignableToPrimitiveType() {
101.8 + return boolean.class.isAssignableFrom(Runnable.class);
101.9 + }
101.10 +
101.11 + @Compare public boolean isAssignableFromPrimitiveType() {
101.12 + return Runnable.class.isAssignableFrom(boolean.class);
101.13 + }
101.14 +
101.15 + @Compare public boolean isAssignableLongFromInt() {
101.16 + return long.class.isAssignableFrom(int.class);
101.17 + }
101.18 +
101.19 + @Compare public boolean isAssignableIntFromLong() {
101.20 + return int.class.isAssignableFrom(long.class);
101.21 + }
101.22 +
101.23 @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
101.24 return Runnable.class.getMethod("run").getName();
101.25 }
101.26 @@ -87,6 +103,20 @@
101.27 StaticUse.class.getMethod("instanceMethod").invoke(null);
101.28 return "should not happen";
101.29 }
101.30 +
101.31 + @Compare public String classCastException() {
101.32 + try {
101.33 + Integer i = (Integer)StaticUseSub.getNonNull();
101.34 + return "" + i.intValue();
101.35 + } catch (ClassCastException ex) {
101.36 + return ex.getClass().getName();
101.37 + }
101.38 + }
101.39 +
101.40 + @Compare public String methodThatThrowsException() throws Exception {
101.41 + StaticUse.class.getMethod("instanceMethod").invoke(new StaticUse());
101.42 + return "should not happen";
101.43 + }
101.44
101.45 @Compare public Object voidReturnType() throws Exception {
101.46 return StaticUse.class.getMethod("instanceMethod").getReturnType();
102.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Mon Mar 25 13:29:42 2013 +0100
102.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Thu Apr 11 16:59:42 2013 +0200
102.3 @@ -30,6 +30,7 @@
102.4 }
102.5
102.6 public void instanceMethod() {
102.7 + throw new IllegalStateException();
102.8 }
102.9
102.10 public static int plus(int a, int b) {
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
103.2 +++ b/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CallMeTwiceTest.java Thu Apr 11 16:59:42 2013 +0200
103.3 @@ -0,0 +1,43 @@
103.4 +/**
103.5 + * Back 2 Browser Bytecode Translator
103.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
103.7 + *
103.8 + * This program is free software: you can redistribute it and/or modify
103.9 + * it under the terms of the GNU General Public License as published by
103.10 + * the Free Software Foundation, version 2 of the License.
103.11 + *
103.12 + * This program is distributed in the hope that it will be useful,
103.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
103.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
103.15 + * GNU General Public License for more details.
103.16 + *
103.17 + * You should have received a copy of the GNU General Public License
103.18 + * along with this program. Look for COPYING file in the top folder.
103.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
103.20 + */
103.21 +package org.apidesign.bck2brwsr.vmtest.impl;
103.22 +
103.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
103.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
103.25 +import org.testng.annotations.Factory;
103.26 +
103.27 +/**
103.28 + *
103.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
103.30 + */
103.31 +public class CallMeTwiceTest {
103.32 + int cnt;
103.33 +
103.34 + @BrwsrTest public void callMeTwice() throws InterruptedException {
103.35 + if (cnt++ == 0) {
103.36 + throw new InterruptedException();
103.37 + }
103.38 + int prevCnt = cnt;
103.39 + cnt = 0;
103.40 + assert prevCnt == 2 : "We need to receive two calls " + prevCnt;
103.41 + }
103.42 +
103.43 + @Factory public static Object[] create() {
103.44 + return VMTest.create(CallMeTwiceTest.class);
103.45 + }
103.46 +}