json/src/test/java/net/java/html/json/MapModelTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 16 Dec 2014 21:03:16 +0100
branchApplyId
changeset 908 ee7a0b3b2d4c
parent 901 4d20596b35bc
permissions -rw-r--r--
Providing an ability to apply model to element with certain id
     1 /**
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     5  *
     6  * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
     7  * Other names may be trademarks of their respective owners.
     8  *
     9  * The contents of this file are subject to the terms of either the GNU
    10  * General Public License Version 2 only ("GPL") or the Common
    11  * Development and Distribution License("CDDL") (collectively, the
    12  * "License"). You may not use this file except in compliance with the
    13  * License. You can obtain a copy of the License at
    14  * http://www.netbeans.org/cddl-gplv2.html
    15  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    16  * specific language governing permissions and limitations under the
    17  * License.  When distributing the software, include this License Header
    18  * Notice in each file and include the License file at
    19  * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    20  * particular file as subject to the "Classpath" exception as provided
    21  * by Oracle in the GPL Version 2 section of the License file that
    22  * accompanied this code. If applicable, add the following below the
    23  * License Header, with the fields enclosed by brackets [] replaced by
    24  * your own identifying information:
    25  * "Portions Copyrighted [year] [name of copyright owner]"
    26  *
    27  * Contributor(s):
    28  *
    29  * The Original Software is NetBeans. The Initial Developer of the Original
    30  * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    31  *
    32  * If you wish your version of this file to be governed by only the CDDL
    33  * or only the GPL Version 2, indicate your decision by adding
    34  * "[Contributor] elects to include this software in this distribution
    35  * under the [CDDL or GPL Version 2] license." If you do not indicate a
    36  * single choice of license, a recipient has the option to distribute
    37  * your version of this file under either the CDDL, the GPL Version 2 or
    38  * to extend the choice of license to its licensees as provided above.
    39  * However, if you add GPL Version 2 code and therefore, elected the GPL
    40  * Version 2 license, then the option applies only if the new code is
    41  * made subject to such option by the copyright holder.
    42  */
    43 package net.java.html.json;
    44 
    45 import net.java.html.BrwsrCtx;
    46 import java.io.IOException;
    47 import java.io.InputStream;
    48 import java.lang.reflect.InvocationTargetException;
    49 import java.util.HashMap;
    50 import java.util.Iterator;
    51 import java.util.ListIterator;
    52 import java.util.Map;
    53 import org.netbeans.html.context.spi.Contexts;
    54 import org.netbeans.html.json.spi.FunctionBinding;
    55 import org.netbeans.html.json.spi.JSONCall;
    56 import org.netbeans.html.json.spi.PropertyBinding;
    57 import org.netbeans.html.json.spi.Technology;
    58 import org.netbeans.html.json.spi.Transfer;
    59 import org.testng.annotations.BeforeMethod;
    60 import org.testng.annotations.Test;
    61 import static org.testng.Assert.*;
    62 
    63 /**
    64  *
    65  * @author Jaroslav Tulach
    66  */
    67 public class MapModelTest {
    68     private MapTechnology t;
    69     private BrwsrCtx c;
    70 
    71     @BeforeMethod public void initTechnology() {
    72         t = new MapTechnology();
    73         c = Contexts.newBuilder().register(Technology.class, t, 1).
    74             register(Transfer.class, t, 1).build();
    75     }
    76     
    77     @Test public void isThereABinding() throws Exception {
    78         Person p = Models.bind(new Person(), c).applyBindings();
    79         assertNull(t.appliedId, "Applied globally");
    80         p.setFirstName("Jarda");
    81         
    82         Map m = (Map)Models.toRaw(p);
    83         Object v = m.get("firstName");
    84         assertNotNull(v, "Value should be in the map");
    85         assertEquals(v.getClass(), One.class, "It is instance of One");
    86         One o = (One)v;
    87         assertEquals(o.changes, 1, "One change so far");
    88         assertFalse(o.pb.isReadOnly(), "Mutable property");
    89         
    90         assertEquals(o.get(), "Jarda", "Value should be in the map");
    91         
    92         o.set("Karle");
    93         
    94         assertEquals(p.getFirstName(), "Karle", "Model value updated");
    95         assertEquals(o.changes, 2, "Snd change");
    96     }
    97     
    98     @Test public void applyLocally() throws Exception {
    99         Person p = Models.bind(new Person(), c).applyBindings("local");
   100         assertEquals(t.appliedId, "local", "Applied locally");
   101     }
   102     
   103     @Test public void dontNotifySameProperty() throws Exception {
   104         Person p = Models.bind(new Person(), c);
   105         p.setFirstName("Jirka");
   106         
   107         Map m = (Map)Models.toRaw(p);
   108         Object v = m.get("firstName");
   109         assertNotNull(v, "Value should be in the map");
   110         assertEquals(v.getClass(), One.class, "It is instance of One");
   111         One o = (One)v;
   112         assertEquals(o.changes, 0, "No change so far the only one change happened before we connected");
   113         
   114         p.setFirstName(new String("Jirka"));
   115         assertEquals(o.changes, 0, "No change so far, the value is the same");
   116         
   117         p.setFirstName("Jarda");
   118         assertFalse(o.pb.isReadOnly(), "Mutable property");
   119         
   120         assertEquals(o.get(), "Jarda", "Value should be in the map");
   121         
   122         o.set("Karle");
   123         
   124         assertEquals(p.getFirstName(), "Karle", "Model value updated");
   125         assertEquals(o.changes, 2, "Snd change");
   126     }
   127     
   128     @Test public void canSetEnumAsString() throws Exception {
   129         Person p = Models.bind(new Person(), c);
   130         p.setFirstName("Jirka");
   131         p.setSex(Sex.MALE);
   132         
   133         Map m = (Map)Models.toRaw(p);
   134         Object v = m.get("sex");
   135         assertNotNull(v, "Value should be in the map");
   136         assertEquals(v.getClass(), One.class, "It is instance of One");
   137         One o = (One)v;
   138         
   139         o.set("FEMALE");
   140 
   141         assertEquals(p.getSex(), Sex.FEMALE, "Changed to female");
   142     }
   143     
   144     @Test public void derivedProperty() throws Exception {
   145         Person p = Models.bind(new Person(), c);
   146         
   147         Map m = (Map)Models.toRaw(p);
   148         Object v = m.get("fullName");
   149         assertNotNull(v, "Value should be in the map");
   150         assertEquals(v.getClass(), One.class, "It is instance of One");
   151         One o = (One)v;
   152         assertTrue(o.pb.isReadOnly(), "Mutable property");
   153     }
   154     
   155     @Test public void changeSex() {
   156         Person p = Models.bind(new Person(), c);
   157         p.setFirstName("Trans");
   158         p.setSex(Sex.MALE);
   159         
   160         Map m = (Map)Models.toRaw(p);
   161         Object o = m.get("changeSex");
   162         assertNotNull(o, "Function registered in the model");
   163         assertEquals(o.getClass(), One.class);
   164         
   165         One one = (One)o;
   166         assertNotNull(one.fb, "Function binding specified");
   167         
   168         one.fb.call(null, null);
   169         
   170         assertEquals(p.getSex(), Sex.FEMALE, "Changed");
   171     }
   172     
   173     @Test public void setSex() {
   174         Person p = Models.bind(new Person(), c);
   175         p.setFirstName("Trans");
   176         
   177         Map m = (Map)Models.toRaw(p);
   178         Object o = m.get("changeSex");
   179         assertNotNull(o, "Function registered in the model");
   180         assertEquals(o.getClass(), One.class);
   181         
   182         One one = (One)o;
   183         assertNotNull(one.fb, "Function binding specified");
   184         
   185         one.fb.call("FEMALE", new Object());
   186         
   187         assertEquals(p.getSex(), Sex.FEMALE, "Changed");
   188     }
   189     
   190     @Test public void removeViaIterator() {
   191         People p = Models.bind(new People(), c);
   192         p.getNicknames().add("One");
   193         p.getNicknames().add("Two");
   194         p.getNicknames().add("Three");
   195 
   196         Map m = (Map)Models.toRaw(p);
   197         Object o = m.get("nicknames");
   198         assertNotNull(o, "List registered in the model");
   199         assertEquals(o.getClass(), One.class);
   200         One one = (One)o;
   201         
   202         
   203         assertEquals(one.changes, 0, "No change");
   204         
   205         Iterator<String> it = p.getNicknames().iterator();
   206         assertEquals(it.next(), "One");
   207         assertEquals(it.next(), "Two");
   208         it.remove();
   209         assertEquals(it.next(), "Three");
   210         assertFalse(it.hasNext());
   211         
   212         
   213         assertEquals(one.changes, 1, "One change");
   214     }
   215     
   216     @Test public void removeViaListIterator() {
   217         People p = Models.bind(new People(), c);
   218         p.getNicknames().add("One");
   219         p.getNicknames().add("Two");
   220         p.getNicknames().add("Three");
   221 
   222         Map m = (Map)Models.toRaw(p);
   223         Object o = m.get("nicknames");
   224         assertNotNull(o, "List registered in the model");
   225         assertEquals(o.getClass(), One.class);
   226         One one = (One)o;
   227         
   228         
   229         assertEquals(one.changes, 0, "No change");
   230         
   231         ListIterator<String> it = p.getNicknames().listIterator(1);
   232         assertEquals(it.next(), "Two");
   233         it.remove();
   234         assertEquals(it.next(), "Three");
   235         assertFalse(it.hasNext());
   236         
   237         
   238         assertEquals(one.changes, 1, "One change");
   239         
   240         it.set("3");
   241         assertEquals(p.getNicknames().get(1), "3");
   242         
   243         assertEquals(one.changes, 2, "Snd change");
   244     }
   245 
   246     @Test public void functionWithParameters() {
   247         People p = Models.bind(new People(), c);
   248         p.getNicknames().add("One");
   249         p.getNicknames().add("Two");
   250         p.getNicknames().add("Three");
   251 
   252         Map m = (Map)Models.toRaw(p);
   253         Object o = m.get("inInnerClass");
   254         assertNotNull(o, "functiton is available");
   255         assertEquals(o.getClass(), One.class);
   256         One one = (One)o;
   257         
   258         Map<String,Object> obj = new HashMap<String, Object>();
   259         obj.put("nick", "newNick");
   260         obj.put("x", 42);
   261         obj.put("y", 7.7f);
   262         final Person data = new Person("a", "b", Sex.MALE);
   263         
   264         one.fb.call(data, obj);
   265 
   266         assertEquals(p.getInfo().size(), 1, "a+b is there: " + p.getInfo());
   267         assertEquals(p.getInfo().get(0), data, "Expecting data: " + p.getInfo());
   268         
   269         assertEquals(p.getNicknames().size(), 4, "One more nickname: " + p.getNicknames());
   270         assertEquals(p.getNicknames().get(3), "newNick");
   271         
   272         assertEquals(p.getAge().size(), 2, "Two new values: " + p.getAge());
   273         assertEquals(p.getAge().get(0).intValue(), 42);
   274         assertEquals(p.getAge().get(1).intValue(), 7);
   275     }
   276     
   277     static final class One {
   278         int changes;
   279         final PropertyBinding pb;
   280         final FunctionBinding fb;
   281     
   282         One(Object m, PropertyBinding pb) throws NoSuchMethodException {
   283             this.pb = pb;
   284             this.fb = null;
   285         }
   286         One(Object m, FunctionBinding fb) throws NoSuchMethodException {
   287             this.pb = null;
   288             this.fb = fb;
   289         }
   290         
   291         Object get() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
   292             return pb.getValue();
   293         }
   294         
   295         void set(Object v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
   296             pb.setValue(v);
   297         }
   298     }
   299     
   300     static final class MapTechnology 
   301     implements Technology.ApplyId<Map<String,One>>, Transfer {
   302         private Map<String, One> appliedData;
   303         private String appliedId;
   304 
   305         @Override
   306         public Map<String, One> wrapModel(Object model) {
   307             return new HashMap<String, One>();
   308         }
   309 
   310         @Override
   311         public void valueHasMutated(Map<String, One> data, String propertyName) {
   312             One p = data.get(propertyName);
   313             if (p != null) {
   314                 p.changes++;
   315             }
   316         }
   317 
   318         @Override
   319         public void bind(PropertyBinding b, Object model, Map<String, One> data) {
   320             try {
   321                 One o = new One(model, b);
   322                 data.put(b.getPropertyName(), o);
   323             } catch (NoSuchMethodException ex) {
   324                 throw new IllegalStateException(ex);
   325             }
   326         }
   327 
   328         @Override
   329         public void expose(FunctionBinding fb, Object model, Map<String, One> data) {
   330             try {
   331                 data.put(fb.getFunctionName(), new One(model, fb));
   332             } catch (NoSuchMethodException ex) {
   333                 throw new IllegalStateException(ex);
   334             }
   335         }
   336 
   337         @Override
   338         public void applyBindings(Map<String, One> data) {
   339             throw new UnsupportedOperationException("Never called!");
   340         }
   341 
   342         @Override
   343         public Object wrapArray(Object[] arr) {
   344             return arr;
   345         }
   346 
   347         @Override
   348         public void extract(Object obj, String[] props, Object[] values) {
   349             Map<?,?> map = obj instanceof Map ? (Map<?,?>)obj : null;
   350             for (int i = 0; i < Math.min(props.length, values.length); i++) {
   351                 if (map == null) {
   352                     values[i] = null;
   353                 } else {
   354                     values[i] = map.get(props[i]);
   355                     if (values[i] instanceof One) {
   356                         values[i] = ((One)values[i]).pb.getValue();
   357                     }
   358                 }
   359             }
   360         }
   361 
   362         @Override
   363         public void loadJSON(JSONCall call) {
   364             call.notifyError(new UnsupportedOperationException());
   365         }
   366 
   367         @Override
   368         public <M> M toModel(Class<M> modelClass, Object data) {
   369             return modelClass.cast(data);
   370         }
   371 
   372         @Override
   373         public Object toJSON(InputStream is) throws IOException {
   374             throw new IOException();
   375         }
   376 
   377         @Override
   378         public void runSafe(Runnable r) {
   379             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   380         }
   381 
   382         @Override
   383         public void applyBindings(String id, Map<String, One> data) {
   384             this.appliedId = id;
   385             this.appliedData = data;
   386         }
   387     }
   388 }