1.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Tue Jan 28 16:18:33 2014 +0100
1.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Wed Jan 29 15:00:53 2014 +0100
1.3 @@ -114,6 +114,30 @@
1.4 }
1.5 }
1.6
1.7 + @KOTest public void showUnionStrings() throws Exception {
1.8 + Object exp = Utils.exposeHTML(KnockoutTest.class,
1.9 + "<ul id='ones' data-bind='foreach: ones'>\n"
1.10 + + " <li data-bind='text: $data'/>"
1.11 + + "</ul>"
1.12 + + "<ul id='twos' data-bind='foreach: twos'>\n"
1.13 + + " <li data-bind='text: $data'/>"
1.14 + + "</ul>"
1.15 + );
1.16 + try {
1.17 + Union u = new Union(new Union.One("Hello", "All!"));
1.18 + Union m = Models.bind(u, newContext());
1.19 + m.applyBindings();
1.20 +
1.21 + int ones = countChildren("ones");
1.22 + int twos = countChildren("twos");
1.23 +
1.24 + assert ones == 2 : "Two from One: " + ones;
1.25 + assert twos == 0 : "None from Two: " + twos;
1.26 + } finally {
1.27 + Utils.exposeHTML(KnockoutTest.class, "");
1.28 + }
1.29 + }
1.30 +
1.31 @KOTest public void modifyValueAssertChangeInModel() throws Exception {
1.32 Object exp = Utils.exposeHTML(KnockoutTest.class,
1.33 "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
2.1 --- a/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Tue Jan 28 16:18:33 2014 +0100
2.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Wed Jan 29 15:00:53 2014 +0100
2.3 @@ -352,8 +352,8 @@
2.4 + (functions.size() / 2) + ");\n");
2.5 {
2.6 for (int i = 0; i < propsGetSet.size(); i++) {
2.7 - w.append(" registerProperty(\"").append(propsGetSet.get(i).p0).append("\", ");
2.8 - w.append(i + ", " + (propsGetSet.get(i).p2 == null) + ");\n");
2.9 + w.append(" registerProperty(\"").append(propsGetSet.get(i).name).append("\", ");
2.10 + w.append(i + ", " + (propsGetSet.get(i).set == null) + ");\n");
2.11 }
2.12 }
2.13 {
2.14 @@ -366,8 +366,8 @@
2.15 w.append(" @Override public void setValue(" + className + " data, int type, Object value) {\n");
2.16 w.append(" switch (type) {\n");
2.17 for (int i = 0; i < propsGetSet.size(); i++) {
2.18 - final String set = propsGetSet.get(i).p2;
2.19 - String tn = propsGetSet.get(i).p4;
2.20 + final String set = propsGetSet.get(i).set;
2.21 + String tn = propsGetSet.get(i).type;
2.22 String btn = findBoxedType(tn);
2.23 if (btn != null) {
2.24 tn = btn;
2.25 @@ -381,7 +381,7 @@
2.26 w.append(" @Override public Object getValue(" + className + " data, int type) {\n");
2.27 w.append(" switch (type) {\n");
2.28 for (int i = 0; i < propsGetSet.size(); i++) {
2.29 - final String get = propsGetSet.get(i).p1;
2.30 + final String get = propsGetSet.get(i).get;
2.31 if (get != null) {
2.32 w.append(" case " + i + ": return data." + strip(get) + "();\n");
2.33 }
2.34 @@ -427,7 +427,7 @@
2.35 w.append(" this(c);\n");
2.36 int values = 0;
2.37 for (int i = 0; i < propsGetSet.size(); i++) {
2.38 - Prprt p = findPrprt(props, propsGetSet.get(i).p0);
2.39 + Prprt p = findPrprt(props, propsGetSet.get(i).name);
2.40 if (p == null) {
2.41 continue;
2.42 }
2.43 @@ -436,15 +436,15 @@
2.44 w.append(" Object[] ret = new Object[" + values + "];\n");
2.45 w.append(" proto.extract(json, new String[] {\n");
2.46 for (int i = 0; i < propsGetSet.size(); i++) {
2.47 - Prprt p = findPrprt(props, propsGetSet.get(i).p0);
2.48 + Prprt p = findPrprt(props, propsGetSet.get(i).name);
2.49 if (p == null) {
2.50 continue;
2.51 }
2.52 - w.append(" \"").append(propsGetSet.get(i).p0).append("\",\n");
2.53 + w.append(" \"").append(propsGetSet.get(i).name).append("\",\n");
2.54 }
2.55 w.append(" }, ret);\n");
2.56 for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i++) {
2.57 - final String pn = propsGetSet.get(i).p0;
2.58 + final String pn = propsGetSet.get(i).name;
2.59 Prprt p = findPrprt(props, pn);
2.60 if (p == null) {
2.61 continue;
2.62 @@ -580,6 +580,46 @@
2.63 if (!generateOperation(e, body, className, e.getEnclosedElements())) {
2.64 ok = false;
2.65 }
2.66 + List<PropInfo> mergedProps = new ArrayList<PropInfo>(propsGetSet);
2.67 + for (Element ec : e.getEnclosedElements()) {
2.68 + if (ec.getKind() != ElementKind.ENUM_CONSTANT) {
2.69 + continue;
2.70 + }
2.71 + Model em = ec.getAnnotation(Model.class);
2.72 + if (em == null) {
2.73 + continue;
2.74 + }
2.75 + Prprt[] subProps = Prprt.wrap(processingEnv, ec, em.properties());
2.76 + for (Prprt prprt : subProps) {
2.77 + PropInfo found = null;
2.78 + for (PropInfo existing : mergedProps) {
2.79 + if (existing.name.equals(prprt.name())) {
2.80 + found = existing;
2.81 + break;
2.82 + }
2.83 + }
2.84 + if (found == null) {
2.85 + final String tn = typeName(ec, prprt);
2.86 + String[] gs = toGetSet(prprt.name(), tn, prprt.array());
2.87 + String castTo;
2.88 +
2.89 + if (prprt.array()) {
2.90 + castTo = "java.util.List";
2.91 + } else {
2.92 + castTo = tn;
2.93 + }
2.94 + found = new PropInfo(
2.95 + prprt.name(),
2.96 + gs[2],
2.97 + gs[3],
2.98 + gs[0],
2.99 + castTo
2.100 + );
2.101 + mergedProps.add(found);
2.102 + }
2.103 + found.addModel(em);
2.104 + }
2.105 + }
2.106 FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
2.107 w = new OutputStreamWriter(java.openOutputStream());
2.108 try {
2.109 @@ -702,12 +742,12 @@
2.110 }
2.111 w.append(" private static class Html4JavaType extends org.apidesign.html.json.spi.Proto.Type<").append(className).append("> {\n");
2.112 w.append(" private Html4JavaType() {\n super(").append(className).append(".class, ").
2.113 - append(inPckName(e)).append(".class, " + (propsGetSet.size()) + ", "
2.114 + append(inPckName(e)).append(".class, " + (mergedProps.size()) + ", "
2.115 + (functions.size() / 2) + ");\n");
2.116 {
2.117 - for (int i = 0; i < propsGetSet.size(); i++) {
2.118 - w.append(" registerProperty(\"").append(propsGetSet.get(i).p0).append("\", ");
2.119 - w.append(i + ", " + (propsGetSet.get(i).p2 == null) + ");\n");
2.120 + for (int i = 0; i < mergedProps.size(); i++) {
2.121 + w.append(" registerProperty(\"").append(mergedProps.get(i).name).append("\", ");
2.122 + w.append(i + ", " + (mergedProps.get(i).set == null) + ");\n");
2.123 }
2.124 }
2.125 {
2.126 @@ -719,25 +759,52 @@
2.127 w.append(" }\n");
2.128 w.append(" @Override public void setValue(" + className + " data, int type, Object value) {\n");
2.129 w.append(" switch (type) {\n");
2.130 - for (int i = 0; i < propsGetSet.size(); i++) {
2.131 - final String set = propsGetSet.get(i).p2;
2.132 - String tn = propsGetSet.get(i).p4;
2.133 + for (int i = 0; i < mergedProps.size(); i++) {
2.134 + final PropInfo mp = mergedProps.get(i);
2.135 + final String set = mp.set;
2.136 + String tn = mp.type;
2.137 String btn = findBoxedType(tn);
2.138 if (btn != null) {
2.139 tn = btn;
2.140 }
2.141 if (set != null) {
2.142 - w.append(" case " + i + ": data." + strip(set) + "(TYPE.extractValue(" + tn + ".class, value)); return;\n");
2.143 + if (mp.models.isEmpty()) {
2.144 + w.append(" case " + i + ": data." + strip(set) + "(TYPE.extractValue(" + tn + ".class, value)); return;\n");
2.145 + } else {
2.146 + w.append(" case " + i + ": {\n");
2.147 + for (Model mdl : mp.models) {
2.148 + w.append(" if (data.get" + mdl.className() +
2.149 + "() != null) data.get" + mdl.className() + "()." +
2.150 + strip(set) + "(TYPE.extractValue(" + tn +
2.151 + ".class, value));\n"
2.152 + );
2.153 + }
2.154 + w.append(" return;\n");
2.155 + w.append(" }\n");
2.156 + }
2.157 }
2.158 }
2.159 w.append(" }\n");
2.160 w.append(" }\n");
2.161 w.append(" @Override public Object getValue(" + className + " data, int type) {\n");
2.162 w.append(" switch (type) {\n");
2.163 - for (int i = 0; i < propsGetSet.size(); i++) {
2.164 - final String get = propsGetSet.get(i).p1;
2.165 + for (int i = 0; i < mergedProps.size(); i++) {
2.166 + final PropInfo mp = mergedProps.get(i);
2.167 + final String get = mp.get;
2.168 if (get != null) {
2.169 - w.append(" case " + i + ": return data." + strip(get) + "();\n");
2.170 + if (mp.models.isEmpty()) {
2.171 + w.append(" case " + i + ": return data." + strip(get) + "();\n");
2.172 + } else {
2.173 + w.append(" case " + i + ": {\n");
2.174 + for (Model mdl : mp.models) {
2.175 + w.append(" if (data.get" + mdl.className() +
2.176 + "() != null) return data.get" + mdl.className() + "()." +
2.177 + strip(get) + "();\n"
2.178 + );
2.179 + }
2.180 + w.append(" return null;\n");
2.181 + w.append(" }\n");
2.182 + }
2.183 }
2.184 }
2.185 w.append(" }\n");
2.186 @@ -782,7 +849,7 @@
2.187 w.append(" private final Object readUnion(Object json) {\n");
2.188 int values = 1;
2.189 for (int i = 0; i < propsGetSet.size(); i++) {
2.190 - Prprt p = findPrprt(props, propsGetSet.get(i).p0);
2.191 + Prprt p = findPrprt(props, propsGetSet.get(i).name);
2.192 if (p == null) {
2.193 continue;
2.194 }
2.195 @@ -792,11 +859,11 @@
2.196 w.append(" proto.extract(json, new String[] {\n");
2.197 w.append(" \"").append(e.getSimpleName()).append("\",\n");
2.198 for (int i = 0; i < propsGetSet.size(); i++) {
2.199 - Prprt p = findPrprt(props, propsGetSet.get(i).p0);
2.200 + Prprt p = findPrprt(props, propsGetSet.get(i).name);
2.201 if (p == null) {
2.202 continue;
2.203 }
2.204 - w.append(" \"").append(propsGetSet.get(i).p0).append("\",\n");
2.205 + w.append(" \"").append(propsGetSet.get(i).name).append("\",\n");
2.206 }
2.207 w.append(" }, ret);\n");
2.208 w.append(" Object union;\n");
2.209 @@ -812,7 +879,7 @@
2.210 w.append(" default: throw new IllegalStateException(ret[0].toString());\n");
2.211 w.append(" }\n" );
2.212 for (int i = 0, cnt = 1, prop = 0; i < propsGetSet.size(); i++) {
2.213 - final String pn = propsGetSet.get(i).p0;
2.214 + final String pn = propsGetSet.get(i).name;
2.215 Prprt p = findPrprt(props, pn);
2.216 if (p == null) {
2.217 continue;
2.218 @@ -924,7 +991,7 @@
2.219 final PropInfo switchProp = new PropInfo(e.getSimpleName().toString(), null, null, null, null);
2.220 if (sharedProps.contains(switchProp)) {
2.221 ok = false;
2.222 - error("Duplicated property " + switchProp.p0 + " due to enum switch", e);
2.223 + error("Duplicated property " + switchProp.name + " due to enum switch", e);
2.224 } else {
2.225 sharedProps.add(switchProp);
2.226 }
2.227 @@ -2351,26 +2418,28 @@
2.228 }
2.229
2.230 private static final class PropInfo {
2.231 - final String p0;
2.232 - final String p1;
2.233 - final String p2;
2.234 + final String name;
2.235 + final String get;
2.236 + final String set;
2.237 final String p3;
2.238 - final String p4;
2.239 + final String type;
2.240 + final List<Model> models;
2.241
2.242 PropInfo(
2.243 String p1, String p2, Object p3, String p4, String p5
2.244 ) {
2.245 - this.p0 = p1;
2.246 - this.p1 = p2;
2.247 - this.p2 = p3 == null ? null : p3.toString();
2.248 + this.name = p1;
2.249 + this.get = p2;
2.250 + this.set = p3 == null ? null : p3.toString();
2.251 this.p3 = p4;
2.252 - this.p4 = p5;
2.253 + this.type = p5;
2.254 + models = new ArrayList<Model>();
2.255 }
2.256
2.257 @Override
2.258 public int hashCode() {
2.259 int hash = 7;
2.260 - hash = 19 * hash + (this.p0 != null ? this.p0.hashCode() : 0);
2.261 + hash = 19 * hash + (this.name != null ? this.name.hashCode() : 0);
2.262 return hash;
2.263 }
2.264
2.265 @@ -2383,10 +2452,14 @@
2.266 return false;
2.267 }
2.268 final PropInfo other = (PropInfo) obj;
2.269 - if ((this.p0 == null) ? (other.p0 != null) : !this.p0.equals(other.p0)) {
2.270 + if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
2.271 return false;
2.272 }
2.273 return true;
2.274 }
2.275 +
2.276 + private void addModel(Model em) {
2.277 + models.add(em);
2.278 + }
2.279 } // end of PropInfo
2.280 }
3.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java Tue Jan 28 16:18:33 2014 +0100
3.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java Wed Jan 29 15:00:53 2014 +0100
3.3 @@ -188,7 +188,7 @@
3.4 }
3.5 }
3.6
3.7 - static final class MapTechnology
3.8 + public static final class MapTechnology
3.9 implements Technology<Map<String,One>>, Transfer {
3.10
3.11 @Override
4.1 --- a/json/src/test/java/org/netbeans/html/json/impl/PlainEnumTest.java Tue Jan 28 16:18:33 2014 +0100
4.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/PlainEnumTest.java Wed Jan 29 15:00:53 2014 +0100
4.3 @@ -42,9 +42,14 @@
4.4 */
4.5 package org.netbeans.html.json.impl;
4.6
4.7 +import java.util.Map;
4.8 +import net.java.html.BrwsrCtx;
4.9 +import net.java.html.json.MapModelTest;
4.10 import net.java.html.json.Model;
4.11 import net.java.html.json.Models;
4.12 import net.java.html.json.Property;
4.13 +import org.apidesign.html.context.spi.Contexts;
4.14 +import org.apidesign.html.json.spi.Technology;
4.15 import static org.testng.Assert.*;
4.16 import org.testng.annotations.Test;
4.17
4.18 @@ -130,4 +135,18 @@
4.19 int next = json.indexOf('{', 1);
4.20 assertEquals(next, -1, "No other {");
4.21 }
4.22 +
4.23 + @Test public void unionOfProperties() {
4.24 + MapModelTest.MapTechnology mt = new MapModelTest.MapTechnology();
4.25 + BrwsrCtx ctx = Contexts.newBuilder().register(Technology.class, mt, 1).build();
4.26 +
4.27 + Union on = new Union(new Union.B("9.9"), 11, 1.1);
4.28 + Union u = Models.bind(on, ctx);
4.29 +
4.30 + Map<?,?> map = (Map<?,?>)Models.toRaw(u);
4.31 + assertNotNull(map.get("x"), "Four properties: " + map);
4.32 + assertNotNull(map.get("y"), "Four properties: " + map);
4.33 + assertNotNull(map.get("ua"), "Four properties: " + map);
4.34 + assertNotNull(map.get("ub"), "Four properties: " + map);
4.35 + }
4.36 }