1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/json-beans/src/test/java/net/java/html/beans/MapModelTest.java Fri Feb 12 08:40:12 2016 +0100
1.3 @@ -0,0 +1,418 @@
1.4 +/**
1.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
1.6 + *
1.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
1.8 + *
1.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
1.10 + * Other names may be trademarks of their respective owners.
1.11 + *
1.12 + * The contents of this file are subject to the terms of either the GNU
1.13 + * General Public License Version 2 only ("GPL") or the Common
1.14 + * Development and Distribution License("CDDL") (collectively, the
1.15 + * "License"). You may not use this file except in compliance with the
1.16 + * License. You can obtain a copy of the License at
1.17 + * http://www.netbeans.org/cddl-gplv2.html
1.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
1.19 + * specific language governing permissions and limitations under the
1.20 + * License. When distributing the software, include this License Header
1.21 + * Notice in each file and include the License file at
1.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
1.23 + * particular file as subject to the "Classpath" exception as provided
1.24 + * by Oracle in the GPL Version 2 section of the License file that
1.25 + * accompanied this code. If applicable, add the following below the
1.26 + * License Header, with the fields enclosed by brackets [] replaced by
1.27 + * your own identifying information:
1.28 + * "Portions Copyrighted [year] [name of copyright owner]"
1.29 + *
1.30 + * Contributor(s):
1.31 + *
1.32 + * The Original Software is NetBeans. The Initial Developer of the Original
1.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
1.34 + *
1.35 + * If you wish your version of this file to be governed by only the CDDL
1.36 + * or only the GPL Version 2, indicate your decision by adding
1.37 + * "[Contributor] elects to include this software in this distribution
1.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
1.39 + * single choice of license, a recipient has the option to distribute
1.40 + * your version of this file under either the CDDL, the GPL Version 2 or
1.41 + * to extend the choice of license to its licensees as provided above.
1.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
1.43 + * Version 2 license, then the option applies only if the new code is
1.44 + * made subject to such option by the copyright holder.
1.45 + */
1.46 +package net.java.html.json;
1.47 +
1.48 +import net.java.html.BrwsrCtx;
1.49 +import java.io.IOException;
1.50 +import java.io.InputStream;
1.51 +import java.lang.reflect.InvocationTargetException;
1.52 +import java.util.HashMap;
1.53 +import java.util.Iterator;
1.54 +import java.util.ListIterator;
1.55 +import java.util.Map;
1.56 +import org.netbeans.html.context.spi.Contexts;
1.57 +import org.netbeans.html.json.spi.FunctionBinding;
1.58 +import org.netbeans.html.json.spi.JSONCall;
1.59 +import org.netbeans.html.json.spi.PropertyBinding;
1.60 +import org.netbeans.html.json.spi.Technology;
1.61 +import org.netbeans.html.json.spi.Transfer;
1.62 +import org.testng.annotations.BeforeMethod;
1.63 +import org.testng.annotations.Test;
1.64 +import static org.testng.Assert.*;
1.65 +
1.66 +/**
1.67 + *
1.68 + * @author Jaroslav Tulach
1.69 + */
1.70 +public class MapModelTest {
1.71 + private MapTechnology t;
1.72 + private BrwsrCtx c;
1.73 +
1.74 + @BeforeMethod public void initTechnology() {
1.75 + t = new MapTechnology();
1.76 + c = Contexts.newBuilder().register(Technology.class, t, 1).
1.77 + register(Transfer.class, t, 1).build();
1.78 + }
1.79 +
1.80 + @Test public void isThereNoApplyBinding() throws Exception {
1.81 + try {
1.82 + Person.class.getMethod("applyBindings");
1.83 + } catch (NoSuchMethodException ex) {
1.84 + // OK
1.85 + return;
1.86 + }
1.87 + fail("There should be no applyBindings() method");
1.88 + }
1.89 +
1.90 + @Test public void isThereABinding() throws Exception {
1.91 + Person p = Models.bind(new Person(), c);
1.92 + Models.applyBindings(p);
1.93 + assertNull(t.appliedId, "Applied globally");
1.94 + p.setFirstName("Jarda");
1.95 +
1.96 + Map m = (Map)Models.toRaw(p);
1.97 + Object v = m.get("firstName");
1.98 + assertNotNull(v, "Value should be in the map");
1.99 + assertEquals(v.getClass(), One.class, "It is instance of One");
1.100 + One o = (One)v;
1.101 + assertEquals(o.changes, 1, "One change so far");
1.102 + assertFalse(o.pb.isReadOnly(), "Mutable property");
1.103 +
1.104 + assertEquals(o.get(), "Jarda", "Value should be in the map");
1.105 +
1.106 + o.set("Karle");
1.107 +
1.108 + assertEquals(p.getFirstName(), "Karle", "Model value updated");
1.109 + assertEquals(o.changes, 2, "Snd change");
1.110 + }
1.111 +
1.112 + @Test public void applyLocally() throws Exception {
1.113 + Person p = Models.bind(new Person(), c);
1.114 + Models.applyBindings(p, "local");
1.115 + assertEquals(t.appliedId, "local", "Applied locally");
1.116 + }
1.117 +
1.118 + @Test public void dontNotifySameProperty() throws Exception {
1.119 + Person p = Models.bind(new Person(), c);
1.120 + p.setFirstName("Jirka");
1.121 +
1.122 + Map m = (Map)Models.toRaw(p);
1.123 + Object v = m.get("firstName");
1.124 + assertNotNull(v, "Value should be in the map");
1.125 + assertEquals(v.getClass(), One.class, "It is instance of One");
1.126 + One o = (One)v;
1.127 + assertEquals(o.changes, 0, "No change so far the only one change happened before we connected");
1.128 +
1.129 + p.setFirstName(new String("Jirka"));
1.130 + assertEquals(o.changes, 0, "No change so far, the value is the same");
1.131 +
1.132 + p.setFirstName("Jarda");
1.133 + assertFalse(o.pb.isReadOnly(), "Mutable property");
1.134 +
1.135 + assertEquals(o.get(), "Jarda", "Value should be in the map");
1.136 +
1.137 + o.set("Karle");
1.138 +
1.139 + assertEquals(p.getFirstName(), "Karle", "Model value updated");
1.140 + assertEquals(o.changes, 2, "Snd change");
1.141 + }
1.142 +
1.143 + @Test public void canSetEnumAsString() throws Exception {
1.144 + Person p = Models.bind(new Person(), c);
1.145 + p.setFirstName("Jirka");
1.146 + p.setSex(Sex.MALE);
1.147 +
1.148 + Map m = (Map)Models.toRaw(p);
1.149 + Object v = m.get("sex");
1.150 + assertNotNull(v, "Value should be in the map");
1.151 + assertEquals(v.getClass(), One.class, "It is instance of One");
1.152 + One o = (One)v;
1.153 +
1.154 + o.set("FEMALE");
1.155 +
1.156 + assertEquals(p.getSex(), Sex.FEMALE, "Changed to female");
1.157 + }
1.158 +
1.159 + @Test public void derivedProperty() throws Exception {
1.160 + Person p = Models.bind(new Person(), c);
1.161 +
1.162 + Map m = (Map)Models.toRaw(p);
1.163 + Object v = m.get("fullName");
1.164 + assertNotNull(v, "Value should be in the map");
1.165 + assertEquals(v.getClass(), One.class, "It is instance of One");
1.166 + One o = (One)v;
1.167 + assertTrue(o.pb.isReadOnly(), "Mutable property");
1.168 + }
1.169 +
1.170 + @Test public void changeSex() {
1.171 + Person p = Models.bind(new Person(), c);
1.172 + p.setFirstName("Trans");
1.173 + p.setSex(Sex.MALE);
1.174 +
1.175 + Map m = (Map)Models.toRaw(p);
1.176 + Object o = m.get("changeSex");
1.177 + assertNotNull(o, "Function registered in the model");
1.178 + assertEquals(o.getClass(), One.class);
1.179 +
1.180 + One one = (One)o;
1.181 + assertNotNull(one.fb, "Function binding specified");
1.182 +
1.183 + one.fb.call(null, null);
1.184 +
1.185 + assertEquals(p.getSex(), Sex.FEMALE, "Changed");
1.186 + }
1.187 +
1.188 + @Test public void setSex() {
1.189 + Person p = Models.bind(new Person(), c);
1.190 + p.setFirstName("Trans");
1.191 +
1.192 + Map m = (Map)Models.toRaw(p);
1.193 + Object o = m.get("changeSex");
1.194 + assertNotNull(o, "Function registered in the model");
1.195 + assertEquals(o.getClass(), One.class);
1.196 +
1.197 + One one = (One)o;
1.198 + assertNotNull(one.fb, "Function binding specified");
1.199 +
1.200 + one.fb.call("FEMALE", new Object());
1.201 +
1.202 + assertEquals(p.getSex(), Sex.FEMALE, "Changed");
1.203 + }
1.204 +
1.205 + @Test public void changeComputedProperty() {
1.206 + Modelik p = Models.bind(new Modelik(), c);
1.207 + p.setValue(5);
1.208 +
1.209 + Map m = (Map)Models.toRaw(p);
1.210 + Object o = m.get("powerValue");
1.211 + assertNotNull(o, "Value is there");
1.212 + assertEquals(o.getClass(), One.class);
1.213 +
1.214 + One one = (One)o;
1.215 + assertNotNull(one.pb, "Prop binding specified");
1.216 +
1.217 + assertEquals(one.pb.getValue(), 25, "Power of 5");
1.218 +
1.219 + one.pb.setValue(16);
1.220 + assertEquals(p.getValue(), 4, "Square root of 16");
1.221 + }
1.222 +
1.223 + @Test public void removeViaIterator() {
1.224 + People p = Models.bind(new People(), c);
1.225 + p.getNicknames().add("One");
1.226 + p.getNicknames().add("Two");
1.227 + p.getNicknames().add("Three");
1.228 +
1.229 + Map m = (Map)Models.toRaw(p);
1.230 + Object o = m.get("nicknames");
1.231 + assertNotNull(o, "List registered in the model");
1.232 + assertEquals(o.getClass(), One.class);
1.233 + One one = (One)o;
1.234 +
1.235 +
1.236 + assertEquals(one.changes, 0, "No change");
1.237 +
1.238 + Iterator<String> it = p.getNicknames().iterator();
1.239 + assertEquals(it.next(), "One");
1.240 + assertEquals(it.next(), "Two");
1.241 + it.remove();
1.242 + assertEquals(it.next(), "Three");
1.243 + assertFalse(it.hasNext());
1.244 +
1.245 +
1.246 + assertEquals(one.changes, 1, "One change");
1.247 + }
1.248 +
1.249 + @Test public void removeViaListIterator() {
1.250 + People p = Models.bind(new People(), c);
1.251 + p.getNicknames().add("One");
1.252 + p.getNicknames().add("Two");
1.253 + p.getNicknames().add("Three");
1.254 +
1.255 + Map m = (Map)Models.toRaw(p);
1.256 + Object o = m.get("nicknames");
1.257 + assertNotNull(o, "List registered in the model");
1.258 + assertEquals(o.getClass(), One.class);
1.259 + One one = (One)o;
1.260 +
1.261 +
1.262 + assertEquals(one.changes, 0, "No change");
1.263 +
1.264 + ListIterator<String> it = p.getNicknames().listIterator(1);
1.265 + assertEquals(it.next(), "Two");
1.266 + it.remove();
1.267 + assertEquals(it.next(), "Three");
1.268 + assertFalse(it.hasNext());
1.269 +
1.270 +
1.271 + assertEquals(one.changes, 1, "One change");
1.272 +
1.273 + it.set("3");
1.274 + assertEquals(p.getNicknames().get(1), "3");
1.275 +
1.276 + assertEquals(one.changes, 2, "Snd change");
1.277 + }
1.278 +
1.279 + @Test public void functionWithParameters() {
1.280 + People p = Models.bind(new People(), c);
1.281 + p.getNicknames().add("One");
1.282 + p.getNicknames().add("Two");
1.283 + p.getNicknames().add("Three");
1.284 +
1.285 + Map m = (Map)Models.toRaw(p);
1.286 + Object o = m.get("inInnerClass");
1.287 + assertNotNull(o, "functiton is available");
1.288 + assertEquals(o.getClass(), One.class);
1.289 + One one = (One)o;
1.290 +
1.291 + Map<String,Object> obj = new HashMap<String, Object>();
1.292 + obj.put("nick", "newNick");
1.293 + obj.put("x", 42);
1.294 + obj.put("y", 7.7f);
1.295 + final Person data = new Person("a", "b", Sex.MALE);
1.296 +
1.297 + one.fb.call(data, obj);
1.298 +
1.299 + assertEquals(p.getInfo().size(), 1, "a+b is there: " + p.getInfo());
1.300 + assertEquals(p.getInfo().get(0), data, "Expecting data: " + p.getInfo());
1.301 +
1.302 + assertEquals(p.getNicknames().size(), 4, "One more nickname: " + p.getNicknames());
1.303 + assertEquals(p.getNicknames().get(3), "newNick");
1.304 +
1.305 + assertEquals(p.getAge().size(), 2, "Two new values: " + p.getAge());
1.306 + assertEquals(p.getAge().get(0).intValue(), 42);
1.307 + assertEquals(p.getAge().get(1).intValue(), 7);
1.308 + }
1.309 +
1.310 + static final class One {
1.311 + int changes;
1.312 + final PropertyBinding pb;
1.313 + final FunctionBinding fb;
1.314 +
1.315 + One(Object m, PropertyBinding pb) throws NoSuchMethodException {
1.316 + this.pb = pb;
1.317 + this.fb = null;
1.318 + }
1.319 + One(Object m, FunctionBinding fb) throws NoSuchMethodException {
1.320 + this.pb = null;
1.321 + this.fb = fb;
1.322 + }
1.323 +
1.324 + Object get() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1.325 + return pb.getValue();
1.326 + }
1.327 +
1.328 + void set(Object v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
1.329 + pb.setValue(v);
1.330 + }
1.331 + }
1.332 +
1.333 + static final class MapTechnology
1.334 + implements Technology.ApplyId<Map<String,One>>, Transfer {
1.335 + private Map<String, One> appliedData;
1.336 + private String appliedId;
1.337 +
1.338 + @Override
1.339 + public Map<String, One> wrapModel(Object model) {
1.340 + return new HashMap<String, One>();
1.341 + }
1.342 +
1.343 + @Override
1.344 + public void valueHasMutated(Map<String, One> data, String propertyName) {
1.345 + One p = data.get(propertyName);
1.346 + if (p != null) {
1.347 + p.changes++;
1.348 + }
1.349 + }
1.350 +
1.351 + @Override
1.352 + public void bind(PropertyBinding b, Object model, Map<String, One> data) {
1.353 + try {
1.354 + One o = new One(model, b);
1.355 + data.put(b.getPropertyName(), o);
1.356 + } catch (NoSuchMethodException ex) {
1.357 + throw new IllegalStateException(ex);
1.358 + }
1.359 + }
1.360 +
1.361 + @Override
1.362 + public void expose(FunctionBinding fb, Object model, Map<String, One> data) {
1.363 + try {
1.364 + data.put(fb.getFunctionName(), new One(model, fb));
1.365 + } catch (NoSuchMethodException ex) {
1.366 + throw new IllegalStateException(ex);
1.367 + }
1.368 + }
1.369 +
1.370 + @Override
1.371 + public void applyBindings(Map<String, One> data) {
1.372 + throw new UnsupportedOperationException("Never called!");
1.373 + }
1.374 +
1.375 + @Override
1.376 + public Object wrapArray(Object[] arr) {
1.377 + return arr;
1.378 + }
1.379 +
1.380 + @Override
1.381 + public void extract(Object obj, String[] props, Object[] values) {
1.382 + Map<?,?> map = obj instanceof Map ? (Map<?,?>)obj : null;
1.383 + for (int i = 0; i < Math.min(props.length, values.length); i++) {
1.384 + if (map == null) {
1.385 + values[i] = null;
1.386 + } else {
1.387 + values[i] = map.get(props[i]);
1.388 + if (values[i] instanceof One) {
1.389 + values[i] = ((One)values[i]).pb.getValue();
1.390 + }
1.391 + }
1.392 + }
1.393 + }
1.394 +
1.395 + @Override
1.396 + public void loadJSON(JSONCall call) {
1.397 + call.notifyError(new UnsupportedOperationException());
1.398 + }
1.399 +
1.400 + @Override
1.401 + public <M> M toModel(Class<M> modelClass, Object data) {
1.402 + return modelClass.cast(data);
1.403 + }
1.404 +
1.405 + @Override
1.406 + public Object toJSON(InputStream is) throws IOException {
1.407 + throw new IOException();
1.408 + }
1.409 +
1.410 + @Override
1.411 + public void runSafe(Runnable r) {
1.412 + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1.413 + }
1.414 +
1.415 + @Override
1.416 + public void applyBindings(String id, Map<String, One> data) {
1.417 + this.appliedId = id;
1.418 + this.appliedData = data;
1.419 + }
1.420 + }
1.421 +}