Removing trailing spaces and ensuring that if a URL parameter is used multiple times, it generates just a single method parameter
1.1 --- a/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Wed May 13 10:21:37 2015 +0300
1.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Wed May 20 06:27:27 2015 +0200
1.3 @@ -91,8 +91,8 @@
1.4 import javax.tools.Diagnostic;
1.5 import javax.tools.FileObject;
1.6 import net.java.html.json.ComputedProperty;
1.7 +import net.java.html.json.Function;
1.8 import net.java.html.json.Model;
1.9 -import net.java.html.json.Function;
1.10 import net.java.html.json.ModelOperation;
1.11 import net.java.html.json.OnPropertyChange;
1.12 import net.java.html.json.OnReceive;
1.13 @@ -170,7 +170,7 @@
1.14 private void error(String msg, Element e) {
1.15 processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
1.16 }
1.17 -
1.18 +
1.19 private boolean processModel(Element e) {
1.20 boolean ok = true;
1.21 Model m = e.getAnnotation(Model.class);
1.22 @@ -189,7 +189,7 @@
1.23 Map<String, Collection<String[]>> propsDeps = new HashMap<String, Collection<String[]>>();
1.24 Map<String, Collection<String>> functionDeps = new HashMap<String, Collection<String>>();
1.25 Prprt[] props = createProps(e, m.properties());
1.26 -
1.27 +
1.28 if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
1.29 ok = false;
1.30 }
1.31 @@ -381,7 +381,7 @@
1.32 w.append(" case " + (i / 2) + ":\n"); // model." + name + "(data, ev); return;\n");
1.33 w.append(" ").append(call).append("\n");
1.34 w.append(" return;\n");
1.35 -
1.36 +
1.37 }
1.38 }
1.39 w.append(" }\n");
1.40 @@ -550,11 +550,11 @@
1.41 }
1.42 return ok;
1.43 }
1.44 -
1.45 +
1.46 private boolean generateProperties(
1.47 Element where,
1.48 Writer w, String className, Prprt[] properties,
1.49 - List<GetSet> props,
1.50 + List<GetSet> props,
1.51 Map<String,Collection<String[]>> deps,
1.52 Map<String,Collection<String>> functionDeps
1.53 ) throws IOException {
1.54 @@ -564,10 +564,10 @@
1.55 tn = typeName(where, p);
1.56 String[] gs = toGetSet(p.name(), tn, p.array());
1.57 String castTo;
1.58 -
1.59 +
1.60 if (p.array()) {
1.61 w.write(" private final java.util.List<" + tn + "> prop_" + p.name() + ";\n");
1.62 -
1.63 +
1.64 castTo = "java.util.List";
1.65 w.write(" public java.util.List<" + tn + "> " + gs[0] + "() {\n");
1.66 w.write(" proto.accessProperty(\"" + p.name() + "\");\n");
1.67 @@ -590,7 +590,7 @@
1.68 Collection<String[]> dependants = deps.get(p.name());
1.69 if (dependants != null) {
1.70 for (String[] pair : dependants) {
1.71 - w.write(" proto.valueHasMutated(\"" + pair[0] + "\", null, " + pair[1] + "());\n");
1.72 + w.write(" proto.valueHasMutated(\"" + pair[0] + "\", null, " + pair[1] + "());\n");
1.73 }
1.74 }
1.75 }
1.76 @@ -605,14 +605,14 @@
1.77 }
1.78 w.write(" }\n");
1.79 }
1.80 -
1.81 +
1.82 for (int i = 0; i < props.size(); i++) {
1.83 if (props.get(i).name.equals(p.name())) {
1.84 error("Cannot have the name " + p.name() + " defined twice", where);
1.85 ok = false;
1.86 }
1.87 }
1.88 -
1.89 +
1.90 props.add(new GetSet(
1.91 p.name(),
1.92 gs[0],
1.93 @@ -657,9 +657,9 @@
1.94 } else {
1.95 toCheck = rt;
1.96 }
1.97 -
1.98 +
1.99 final String sn = ee.getSimpleName().toString();
1.100 -
1.101 +
1.102 if (toCheck.getKind().isPrimitive()) {
1.103 // OK
1.104 } else {
1.105 @@ -682,9 +682,9 @@
1.106 }
1.107 }
1.108 }
1.109 -
1.110 +
1.111 String[] gs = toGetSet(sn, tn, array);
1.112 -
1.113 +
1.114 w.write(" public " + tn);
1.115 if (array) {
1.116 w.write("<" + toCheck + ">");
1.117 @@ -694,7 +694,7 @@
1.118 boolean deep = false;
1.119 for (VariableElement pe : ee.getParameters()) {
1.120 final String dn = pe.getSimpleName().toString();
1.121 -
1.122 +
1.123 if (!verifyPropName(pe, dn, fixedProps)) {
1.124 ok = false;
1.125 }
1.126 @@ -712,7 +712,7 @@
1.127 String[] call = toGetSet(dn, dt, false);
1.128 w.write(" " + dt + " arg" + (++arg) + " = ");
1.129 w.write(call[0] + "();\n");
1.130 -
1.131 +
1.132 Collection<String[]> depends = deps.get(dn);
1.133 if (depends == null) {
1.134 depends = new LinkedHashSet<String[]>();
1.135 @@ -750,7 +750,7 @@
1.136 true
1.137 ));
1.138 }
1.139 -
1.140 +
1.141 return ok;
1.142 }
1.143
1.144 @@ -762,7 +762,7 @@
1.145 pref = "is";
1.146 }
1.147 if (array) {
1.148 - return new String[] {
1.149 + return new String[] {
1.150 pref + n,
1.151 null,
1.152 "a" + n,
1.153 @@ -770,8 +770,8 @@
1.154 };
1.155 }
1.156 return new String[]{
1.157 - pref + n,
1.158 - "set" + n,
1.159 + pref + n,
1.160 + "set" + n,
1.161 "a" + n,
1.162 ""
1.163 };
1.164 @@ -791,7 +791,7 @@
1.165 }
1.166 return ret;
1.167 }
1.168 -
1.169 +
1.170 private static String findBoxedType(String ret) {
1.171 if (ret.equals("boolean")) {
1.172 return Boolean.class.getName();
1.173 @@ -850,7 +850,7 @@
1.174 }
1.175
1.176 private boolean generateFunctions(
1.177 - Element clazz, StringWriter body, String className,
1.178 + Element clazz, StringWriter body, String className,
1.179 List<? extends Element> enclosedElements, List<Object> functions
1.180 ) {
1.181 for (Element m : enclosedElements) {
1.182 @@ -882,7 +882,7 @@
1.183 }
1.184
1.185 private boolean generateOnChange(Element clazz, Map<String,Collection<String[]>> propDeps,
1.186 - Prprt[] properties, String className,
1.187 + Prprt[] properties, String className,
1.188 Map<String, Collection<String>> functionDeps
1.189 ) {
1.190 for (Element m : clazz.getEnclosedElements()) {
1.191 @@ -913,14 +913,14 @@
1.192 return false;
1.193 }
1.194 String n = e.getSimpleName().toString();
1.195 -
1.196 -
1.197 +
1.198 +
1.199 for (String pn : onPC.value()) {
1.200 StringBuilder call = new StringBuilder();
1.201 call.append(" ").append(clazz.getSimpleName()).append(".").append(n).append("(");
1.202 call.append(wrapPropName(e, className, "name", pn));
1.203 call.append(");\n");
1.204 -
1.205 +
1.206 Collection<String> change = functionDeps.get(pn);
1.207 if (change == null) {
1.208 change = new ArrayList<String>();
1.209 @@ -940,8 +940,8 @@
1.210 return true;
1.211 }
1.212
1.213 - private boolean generateOperation(Element clazz,
1.214 - StringWriter body, String className,
1.215 + private boolean generateOperation(Element clazz,
1.216 + StringWriter body, String className,
1.217 List<? extends Element> enclosedElements,
1.218 List<Object> functions
1.219 ) {
1.220 @@ -1022,14 +1022,14 @@
1.221 call.append("); }");
1.222 functions.add(call.toString());
1.223 }
1.224 -
1.225 +
1.226 }
1.227 return true;
1.228 }
1.229 -
1.230 -
1.231 +
1.232 +
1.233 private boolean generateReceive(
1.234 - Element clazz, StringWriter body, String className,
1.235 + Element clazz, StringWriter body, String className,
1.236 List<? extends Element> enclosedElements, StringBuilder inType
1.237 ) {
1.238 inType.append(" @Override public void onMessage(").append(className).append(" model, int index, int type, Object data, Object[] params) {\n");
1.239 @@ -1088,9 +1088,9 @@
1.240 } else {
1.241 error("First parameter needs to be " + className, e);
1.242 return false;
1.243 - }
1.244 + }
1.245 }
1.246 -
1.247 +
1.248 String modelClass;
1.249 {
1.250 final Types tu = processingEnv.getTypeUtils();
1.251 @@ -1152,7 +1152,7 @@
1.252 }
1.253 if (!skipJSONP) {
1.254 error(
1.255 - "Name of jsonp attribute ('" + onR.jsonp() +
1.256 + "Name of jsonp attribute ('" + onR.jsonp() +
1.257 "') is not used in url attribute '" + onR.url() + "'", e
1.258 );
1.259 }
1.260 @@ -1164,7 +1164,7 @@
1.261 error("@OnReceive(method=\"WebSocket\") can only have two arguments", e);
1.262 return false;
1.263 }
1.264 -
1.265 +
1.266 VariableElement ve = e.getParameters().get(i);
1.267 body.append(sep).append(ve.asType().toString()).append(" ").append(ve.getSimpleName());
1.268 final String tp = ve.asType().toString();
1.269 @@ -1270,7 +1270,7 @@
1.270 method.append(");\n");
1.271 return false;
1.272 }
1.273 -
1.274 +
1.275 private boolean generateWSReceiveBody(int index, StringWriter method, StringBuilder body, OnReceive onR, ExecutableElement e, Element clazz, String className, boolean expectsList, String modelClass, String n, List<String> args, List<String> params, StringBuilder urlBefore, String jsonpVarName, StringBuilder urlAfter, String dataMirror) {
1.276 body.append(
1.277 " case " + index + ": {\n" +
1.278 @@ -1469,8 +1469,8 @@
1.279 }
1.280 return params;
1.281 }
1.282 -
1.283 -
1.284 +
1.285 +
1.286 private CharSequence wrapPropName(
1.287 ExecutableElement ee, String className, String propName, String propValue
1.288 ) {
1.289 @@ -1505,7 +1505,7 @@
1.290 }
1.291 return params;
1.292 }
1.293 -
1.294 +
1.295 private boolean isModel(TypeMirror tm) {
1.296 if (tm.getKind() == TypeKind.ERROR) {
1.297 return true;
1.298 @@ -1524,7 +1524,7 @@
1.299 }
1.300 return models.values().contains(e.getSimpleName().toString());
1.301 }
1.302 -
1.303 +
1.304 private void writeToString(Prprt[] props, Writer w) throws IOException {
1.305 w.write(" public String toString() {\n");
1.306 w.write(" StringBuilder sb = new StringBuilder();\n");
1.307 @@ -1563,7 +1563,7 @@
1.308 w.write(" proto.cloneList(ret.prop_" + p.name() + ", ctx, prop_" + p.name() + ");\n");
1.309 }
1.310 }
1.311 -
1.312 +
1.313 w.write(" return ret;\n");
1.314 w.write(" }\n");
1.315 }
1.316 @@ -1618,7 +1618,7 @@
1.317 isEnum[0] = false;
1.318 return e.getSimpleName().toString();
1.319 }
1.320 -
1.321 +
1.322 final Model m = e == null ? null : e.getAnnotation(Model.class);
1.323 String ret;
1.324 if (m != null) {
1.325 @@ -1636,7 +1636,7 @@
1.326 isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
1.327 return ret;
1.328 }
1.329 -
1.330 +
1.331 private static boolean findModelForMthd(Element clazz) {
1.332 if (clazz == null) {
1.333 return false;
1.334 @@ -1658,7 +1658,7 @@
1.335 private Iterable<String> findParamNames(
1.336 Element e, String url, String jsonParam, StringBuilder... both
1.337 ) {
1.338 - List<String> params = new ArrayList<String>();
1.339 + Set<String> params = new LinkedHashSet<String>();
1.340 int wasJSON = 0;
1.341
1.342 for (int pos = 0; ;) {
1.343 @@ -1675,16 +1675,17 @@
1.344 return params;
1.345 }
1.346 final String paramName = url.substring(next + 1, close);
1.347 - params.add(paramName);
1.348 - if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
1.349 - both[wasJSON].append('"')
1.350 - .append(url.substring(pos, next))
1.351 - .append('"');
1.352 - wasJSON = 1;
1.353 - } else {
1.354 - both[wasJSON].append('"')
1.355 - .append(url.substring(pos, next))
1.356 - .append("\" + ").append(paramName).append(" + ");
1.357 + if (params.add(paramName)) {
1.358 + if (paramName.equals(jsonParam) && !jsonParam.isEmpty()) {
1.359 + both[wasJSON].append('"')
1.360 + .append(url.substring(pos, next))
1.361 + .append('"');
1.362 + wasJSON = 1;
1.363 + } else {
1.364 + both[wasJSON].append('"')
1.365 + .append(url.substring(pos, next))
1.366 + .append("\" + ").append(paramName).append(" + ");
1.367 + }
1.368 }
1.369 pos = close + 1;
1.370 }
1.371 @@ -1700,7 +1701,7 @@
1.372 }
1.373
1.374 private boolean isPrimitive(String type) {
1.375 - return
1.376 + return
1.377 "int".equals(type) ||
1.378 "double".equals(type) ||
1.379 "long".equals(type) ||
1.380 @@ -1723,7 +1724,7 @@
1.381 }
1.382 return names;
1.383 }
1.384 -
1.385 +
1.386 private Prprt[] createProps(Element e, Property[] arr) {
1.387 Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
1.388 Prprt[] prev = verify.put(e, ret);
1.389 @@ -1732,7 +1733,7 @@
1.390 }
1.391 return ret;
1.392 }
1.393 -
1.394 +
1.395 private static String strip(String s) {
1.396 int indx = s.indexOf("__");
1.397 if (indx >= 0) {
1.398 @@ -1758,7 +1759,7 @@
1.399 } catch (Exception ex) {
1.400 // fallback
1.401 }
1.402 -
1.403 +
1.404 AnnotationMirror found = null;
1.405 for (AnnotationMirror am : e.getAnnotationMirrors()) {
1.406 if (am.getAnnotationType().toString().equals(OnReceive.class.getName())) {
1.407 @@ -1768,7 +1769,7 @@
1.408 if (found == null) {
1.409 return null;
1.410 }
1.411 -
1.412 +
1.413 for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : found.getElementValues().entrySet()) {
1.414 ExecutableElement ee = entry.getKey();
1.415 AnnotationValue av = entry.getValue();
1.416 @@ -1827,11 +1828,11 @@
1.417 this.tm = tm;
1.418 this.p = p;
1.419 }
1.420 -
1.421 +
1.422 String name() {
1.423 return p.name();
1.424 }
1.425 -
1.426 +
1.427 boolean array() {
1.428 return p.array();
1.429 }
1.430 @@ -1853,13 +1854,13 @@
1.431 }
1.432 throw ex;
1.433 }
1.434 -
1.435 -
1.436 +
1.437 +
1.438 static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
1.439 if (arr.length == 0) {
1.440 return new Prprt[0];
1.441 }
1.442 -
1.443 +
1.444 if (e.getKind() != ElementKind.CLASS) {
1.445 throw new IllegalStateException("" + e.getKind());
1.446 }
1.447 @@ -1881,12 +1882,12 @@
1.448 BIG: for (int i = 0; i < ret.length; i++) {
1.449 AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
1.450 ret[i] = new Prprt(e, am, arr[i]);
1.451 -
1.452 +
1.453 }
1.454 return ret;
1.455 }
1.456 } // end of Prprt
1.457 -
1.458 +
1.459 private static final class GetSet {
1.460 final String name;
1.461 final String getter;
1.462 @@ -1922,15 +1923,15 @@
1.463 );
1.464 }
1.465 }
1.466 -
1.467 +
1.468 return super.getCompletions(element, annotation, member, userText);
1.469 }
1.470 -
1.471 +
1.472 private static final Completion methodOf(String method) {
1.473 ResourceBundle rb = ResourceBundle.getBundle("org.netbeans.html.json.impl.Bundle");
1.474 return Completions.of('"' + method + '"', rb.getString("MSG_Completion_" + method));
1.475 }
1.476 -
1.477 +
1.478 private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, String className) {
1.479 String err = null;
1.480 METHODS:
1.481 @@ -1978,5 +1979,5 @@
1.482 error(err, errElem);
1.483 return false;
1.484 }
1.485 -
1.486 +
1.487 }
2.1 --- a/json/src/test/java/net/java/html/json/ModelTest.java Wed May 13 10:21:37 2015 +0300
2.2 +++ b/json/src/test/java/net/java/html/json/ModelTest.java Wed May 20 06:27:27 2015 +0200
2.3 @@ -42,17 +42,22 @@
2.4 */
2.5 package net.java.html.json;
2.6
2.7 -import net.java.html.BrwsrCtx;
2.8 import java.util.ArrayList;
2.9 import java.util.Collections;
2.10 import java.util.Iterator;
2.11 import java.util.List;
2.12 import java.util.ListIterator;
2.13 +import net.java.html.BrwsrCtx;
2.14 import org.netbeans.html.context.spi.Contexts;
2.15 import org.netbeans.html.json.spi.FunctionBinding;
2.16 import org.netbeans.html.json.spi.PropertyBinding;
2.17 import org.netbeans.html.json.spi.Technology;
2.18 -import static org.testng.Assert.*;
2.19 +import static org.testng.Assert.assertEquals;
2.20 +import static org.testng.Assert.assertFalse;
2.21 +import static org.testng.Assert.assertNotNull;
2.22 +import static org.testng.Assert.assertNull;
2.23 +import static org.testng.Assert.assertTrue;
2.24 +import static org.testng.Assert.fail;
2.25 import org.testng.annotations.BeforeMethod;
2.26 import org.testng.annotations.Test;
2.27
2.28 @@ -73,37 +78,37 @@
2.29 private MockTechnology my;
2.30 private Modelik model;
2.31 private static Modelik leakedModel;
2.32 -
2.33 +
2.34 @BeforeMethod
2.35 public void createModel() {
2.36 my = new MockTechnology();
2.37 final BrwsrCtx c = Contexts.newBuilder().register(Technology.class, my, 1).build();
2.38 model = Models.bind(new Modelik(), c);
2.39 }
2.40 -
2.41 +
2.42 @Test public void classGeneratedWithSetterGetter() {
2.43 model.setValue(10);
2.44 assertEquals(10, model.getValue(), "Value changed");
2.45 }
2.46 -
2.47 +
2.48 @Test public void computedMethod() {
2.49 model.setValue(4);
2.50 assertEquals(16, model.getPowerValue());
2.51 }
2.52 -
2.53 +
2.54 @Test public void equalsAndHashCode() {
2.55 Modelik m1 = new Modelik(10, 20, 30, "changed", "firstName");
2.56 Modelik m2 = new Modelik(10, 20, 30, "changed", "firstName");
2.57 -
2.58 +
2.59 assertTrue(m1.equals(m2), "They are the same");
2.60 assertEquals(m1.hashCode(), m2.hashCode(), "Hashcode is the same");
2.61 -
2.62 +
2.63 m1.setCount(33);
2.64 -
2.65 +
2.66 assertFalse(m1.equals(m2), "No longer the same");
2.67 assertFalse(m1.hashCode() == m2.hashCode(), "No longe is hashcode is the same");
2.68 }
2.69 -
2.70 +
2.71 @Test public void arrayIsMutable() {
2.72 assertEquals(model.getNames().size(), 0, "Is empty");
2.73 model.getNames().add("Jarda");
2.74 @@ -117,49 +122,49 @@
2.75 assertTrue(my.mutated.isEmpty(), "No change still " + my.mutated);
2.76 assertTrue(model.getNames().isEmpty(), "No empty");
2.77 }
2.78 -
2.79 +
2.80 @Test public void arrayChangesNotified() {
2.81 Models.applyBindings(model);
2.82 model.getNames().add("Hello");
2.83 -
2.84 +
2.85 assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
2.86 assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
2.87
2.88 my.mutated.clear();
2.89 -
2.90 +
2.91 Iterator<String> it = model.getNames().iterator();
2.92 assertEquals(it.next(), "Hello");
2.93 it.remove();
2.94 -
2.95 +
2.96 assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
2.97 assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
2.98
2.99 my.mutated.clear();
2.100 -
2.101 +
2.102 ListIterator<String> lit = model.getNames().listIterator();
2.103 lit.add("Jarda");
2.104 -
2.105 +
2.106 assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
2.107 assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
2.108 }
2.109
2.110 @Test public void autoboxedArray() {
2.111 model.getValues().add(10);
2.112 -
2.113 +
2.114 assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten");
2.115 }
2.116
2.117 @Test public void derivedArrayProp() {
2.118 model.applyBindings();
2.119 model.setCount(10);
2.120 -
2.121 +
2.122 List<String> arr = model.getRepeat();
2.123 assertEquals(arr.size(), 10, "Ten items: " + arr);
2.124 -
2.125 +
2.126 my.mutated.clear();
2.127 -
2.128 +
2.129 model.setCount(5);
2.130 -
2.131 +
2.132 arr = model.getRepeat();
2.133 assertEquals(arr.size(), 5, "Five items: " + arr);
2.134
2.135 @@ -167,24 +172,24 @@
2.136 assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated);
2.137 assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated);
2.138 }
2.139 -
2.140 +
2.141 @Test public void derivedPropertiesAreNotified() {
2.142 model.applyBindings();
2.143 -
2.144 +
2.145 model.setValue(33);
2.146 -
2.147 +
2.148 // not interested in change of this property
2.149 my.mutated.remove("changedProperty");
2.150 -
2.151 +
2.152 assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
2.153 assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
2.154 assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
2.155 -
2.156 +
2.157 my.mutated.clear();
2.158 -
2.159 +
2.160 model.setUnrelated(44);
2.161 -
2.162 -
2.163 +
2.164 +
2.165 // not interested in change of this property
2.166 my.mutated.remove("changedProperty");
2.167 assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated);
2.168 @@ -210,16 +215,16 @@
2.169 // OK, we can't read
2.170 }
2.171 }
2.172 -
2.173 +
2.174 @OnReceive(url = "{protocol}://{host}?query={query}", data = Person.class, onError = "errorState")
2.175 static void loadPeople(Modelik thiz, People p) {
2.176 Modelik m = null;
2.177 m.applyBindings();
2.178 m.loadPeople("http", "apidesign.org", "query", new Person());
2.179 }
2.180 -
2.181 +
2.182 static void errorState(Modelik thiz, Exception ex) {
2.183 -
2.184 +
2.185 }
2.186
2.187 @OnReceive(url = "{protocol}://{host}?callback={back}&query={query}", jsonp = "back")
2.188 @@ -228,16 +233,21 @@
2.189 m.applyBindings();
2.190 m.loadPeopleViaJSONP("http", "apidesign.org", "query");
2.191 }
2.192 -
2.193 - @Function
2.194 +
2.195 + @OnReceive(url = "{rep}://{rep}")
2.196 + static void repeatedTest(Modelik thiz, People p) {
2.197 + thiz.repeatedTest("justOneParameterRep");
2.198 + }
2.199 +
2.200 + @Function
2.201 static void doSomething() {
2.202 }
2.203 -
2.204 +
2.205 @ComputedProperty
2.206 static int powerValue(int value) {
2.207 return value * value;
2.208 }
2.209 -
2.210 +
2.211 @OnPropertyChange({ "powerValue", "unrelated" })
2.212 static void aPropertyChanged(Modelik m, String name) {
2.213 m.setChangedProperty(name);
2.214 @@ -247,7 +257,7 @@
2.215 static void anArrayPropertyChanged(String name, Modelik m) {
2.216 m.setChangedProperty(name);
2.217 }
2.218 -
2.219 +
2.220 @Test public void changeAnything() {
2.221 model.setCount(44);
2.222 assertNull(model.getChangedProperty(), "No observed value change");
2.223 @@ -268,7 +278,7 @@
2.224 model.getValues().add(10);
2.225 assertEquals(model.getChangedProperty(), "values", "Something added into the array");
2.226 }
2.227 -
2.228 +
2.229 @ComputedProperty
2.230 static String notAllowedRead() {
2.231 return "Not allowed callback: " + leakedModel.getUnrelated();
2.232 @@ -279,12 +289,12 @@
2.233 leakedModel.setUnrelated(11);
2.234 return "Not allowed callback!";
2.235 }
2.236 -
2.237 +
2.238 @ComputedProperty
2.239 static List<String> repeat(int count) {
2.240 return Collections.nCopies(count, "Hello");
2.241 }
2.242 -
2.243 +
2.244 public @Test void hasPersonPropertyAndComputedFullName() {
2.245 List<Person> arr = model.getPeople();
2.246 assertEquals(arr.size(), 0, "By default empty");
2.247 @@ -294,7 +304,7 @@
2.248 assertNotNull(fullNameGenerated);
2.249 }
2.250 }
2.251 -
2.252 +
2.253 public @Test void computedListIsOfTypeString() {
2.254 Person p = new Person("1st", "2nd", Sex.MALE);
2.255 String first = p.getBothNames().get(0);
2.256 @@ -302,7 +312,7 @@
2.257 assertEquals(first, "1st");
2.258 assertEquals(last, "2nd");
2.259 }
2.260 -
2.261 +
2.262 private static class MockTechnology implements Technology<Object> {
2.263 private final List<String> mutated = new ArrayList<String>();
2.264