json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Sat, 02 Aug 2014 12:59:31 +0200
changeset 790 30f20d9c0986
parent 788 f8ac4d547ad3
child 838 bdc3d696dd4a
permissions -rw-r--r--
Fixing Javadoc to succeed on JDK8
jaroslav@9
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@9
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jaroslav@9
     5
 *
jaroslav@358
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@358
     7
 * Other names may be trademarks of their respective owners.
jaroslav@9
     8
 *
jaroslav@358
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@358
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@358
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@358
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@358
    13
 * License. You can obtain a copy of the License at
jaroslav@358
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@358
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@358
    16
 * specific language governing permissions and limitations under the
jaroslav@358
    17
 * License.  When distributing the software, include this License Header
jaroslav@358
    18
 * Notice in each file and include the License file at
jaroslav@358
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@358
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@358
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@358
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@358
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@358
    24
 * your own identifying information:
jaroslav@358
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@358
    26
 *
jaroslav@358
    27
 * Contributor(s):
jaroslav@358
    28
 *
jaroslav@358
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@358
    31
 *
jaroslav@358
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@358
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@358
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@358
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@358
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@358
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@358
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@358
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@358
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@358
    41
 * made subject to such option by the copyright holder.
jaroslav@9
    42
 */
jtulach@787
    43
package org.netbeans.html.json.impl;
jaroslav@9
    44
jtulach@787
    45
import java.io.IOException;
jtulach@787
    46
import java.io.InputStream;
jtulach@787
    47
import java.lang.reflect.InvocationTargetException;
jtulach@787
    48
import java.util.HashMap;
jtulach@777
    49
import java.util.List;
jtulach@773
    50
import java.util.Map;
jaroslav@110
    51
import net.java.html.BrwsrCtx;
jtulach@787
    52
import net.java.html.json.ComputedProperty;
jtulach@787
    53
import net.java.html.json.Model;
jtulach@787
    54
import net.java.html.json.Models;
jtulach@787
    55
import net.java.html.json.Property;
jaroslav@110
    56
import org.apidesign.html.context.spi.Contexts;
jtulach@787
    57
import org.apidesign.html.json.spi.FunctionBinding;
jtulach@787
    58
import org.apidesign.html.json.spi.JSONCall;
jtulach@787
    59
import org.apidesign.html.json.spi.PropertyBinding;
jaroslav@9
    60
import org.apidesign.html.json.spi.Technology;
jaroslav@23
    61
import org.apidesign.html.json.spi.Transfer;
jtulach@773
    62
import static org.testng.Assert.*;
jaroslav@9
    63
import org.testng.annotations.BeforeMethod;
jaroslav@9
    64
import org.testng.annotations.Test;
jaroslav@9
    65
jaroslav@9
    66
/**
jaroslav@9
    67
 *
jtulach@790
    68
 * @author Jaroslav Tulach
jaroslav@9
    69
 */
jtulach@773
    70
public class DeepChangeTest {
jaroslav@9
    71
    private MapTechnology t;
jaroslav@110
    72
    private BrwsrCtx c;
jaroslav@9
    73
jaroslav@9
    74
    @BeforeMethod public void initTechnology() {
jaroslav@9
    75
        t = new MapTechnology();
jaroslav@110
    76
        c = Contexts.newBuilder().register(Technology.class, t, 1).
jaroslav@110
    77
            register(Transfer.class, t, 1).build();
jaroslav@9
    78
    }
jaroslav@9
    79
    
jtulach@773
    80
    @Model(className = "MyX", properties = {
jtulach@773
    81
        @Property(name = "one", type = MyY.class),
jtulach@773
    82
        @Property(name = "all", type = MyY.class, array = true)
jtulach@773
    83
    })
jtulach@773
    84
    static class X {
jtulach@787
    85
        @ComputedProperty @Transitive(deep = true) 
jtulach@773
    86
        static String oneName(MyY one) {
jtulach@773
    87
            return one.getValue();
jtulach@773
    88
        }
jtulach@788
    89
        @ComputedProperty
jtulach@775
    90
        static String sndName(MyY one) {
jtulach@775
    91
            return one.getValue().toUpperCase();
jtulach@775
    92
        }
jtulach@787
    93
        @ComputedProperty @Transitive(deep = false) 
jtulach@776
    94
        static String noName(MyY one) {
jtulach@776
    95
            return one.getValue().toUpperCase();
jtulach@776
    96
        }
jtulach@787
    97
        @ComputedProperty @Transitive(deep = true) 
jtulach@775
    98
        static String thrdName(MyY one) {
jtulach@775
    99
            return "X" + one.getCount();
jtulach@775
   100
        }
jtulach@777
   101
        
jtulach@788
   102
        @ComputedProperty
jtulach@777
   103
        static String allNames(List<MyY> all) {
jtulach@777
   104
            StringBuilder sb = new StringBuilder();
jtulach@777
   105
            for (MyY y : all) {
jtulach@777
   106
                sb.append(y.getValue());
jtulach@777
   107
            }
jtulach@777
   108
            return sb.toString();
jtulach@777
   109
        }
jtulach@777
   110
jtulach@787
   111
        @ComputedProperty @Transitive(deep = true)
jtulach@777
   112
        static String firstFromNames(List<MyY> all) {
jtulach@780
   113
            for (MyY y : all) {
jtulach@780
   114
                if (y != null && y.getValue() != null) {
jtulach@780
   115
                    return y.getValue();
jtulach@780
   116
                }
jtulach@777
   117
            }
jtulach@777
   118
            return null;
jtulach@777
   119
        }
jtulach@773
   120
    }
jtulach@773
   121
    @Model(className = "MyY", properties = {
jtulach@775
   122
        @Property(name = "value", type = String.class),
jtulach@775
   123
        @Property(name = "count", type = int.class)
jtulach@773
   124
    })
jtulach@773
   125
    static class Y {
jtulach@773
   126
    }
jtulach@778
   127
    @Model(className = "MyOverall", properties = {
jtulach@778
   128
        @Property(name = "x", type = MyX.class)
jtulach@778
   129
    })
jtulach@778
   130
    static class Overall {
jtulach@787
   131
        @ComputedProperty @Transitive(deep = true) 
jtulach@778
   132
        static String valueAccross(MyX x) {
jtulach@778
   133
            return x.getFirstFromNames();
jtulach@778
   134
        }
jtulach@778
   135
    }
jtulach@773
   136
    
jtulach@774
   137
    @Test public void isTransitiveChangeNotifiedProperly() throws Exception {
jtulach@773
   138
        MyX p = Models.bind(
jtulach@775
   139
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@773
   140
        ), c).applyBindings();
jaroslav@9
   141
        
jaroslav@450
   142
        Map m = (Map)Models.toRaw(p);
jtulach@773
   143
        Object v = m.get("oneName");
jaroslav@9
   144
        assertNotNull(v, "Value should be in the map");
jaroslav@9
   145
        assertEquals(v.getClass(), One.class, "It is instance of One");
jaroslav@9
   146
        One o = (One)v;
jtulach@773
   147
        assertEquals(o.changes, 0, "No changes so far");
jtulach@773
   148
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@773
   149
        assertEquals(o.get(), "Ahoj");
jtulach@773
   150
jtulach@773
   151
        p.getOne().setValue("Nazdar");
jtulach@773
   152
        
jtulach@773
   153
        assertEquals(o.get(), "Nazdar");
jaroslav@9
   154
        assertEquals(o.changes, 1, "One change so far");
jaroslav@9
   155
    }
jtulach@775
   156
    
jtulach@777
   157
    @Test public void isTransitiveChangeInArrayNotifiedProperly() throws Exception {
jtulach@777
   158
        MyX p = Models.bind(
jtulach@777
   159
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@777
   160
        ), c).applyBindings();
jtulach@777
   161
        
jtulach@777
   162
        Map m = (Map)Models.toRaw(p);
jtulach@777
   163
        Object v = m.get("allNames");
jtulach@777
   164
        assertNotNull(v, "Value should be in the map");
jtulach@777
   165
        assertEquals(v.getClass(), One.class, "It is instance of One");
jtulach@777
   166
        One o = (One)v;
jtulach@777
   167
        assertEquals(o.changes, 0, "No changes so far");
jtulach@777
   168
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@777
   169
        assertEquals(o.get(), "HiHello");
jtulach@777
   170
jtulach@777
   171
        p.getAll().get(0).setValue("Nazdar");
jtulach@777
   172
        
jtulach@777
   173
        assertEquals(o.get(), "NazdarHello");
jtulach@777
   174
        assertEquals(o.changes, 1, "One change so far");
jtulach@777
   175
    }
jtulach@779
   176
jtulach@779
   177
    @Test public void addingIntoArray() throws Exception {
jtulach@779
   178
        MyX p = Models.bind(
jtulach@779
   179
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@779
   180
        ), c).applyBindings();
jtulach@779
   181
        
jtulach@779
   182
        Map m = (Map)Models.toRaw(p);
jtulach@779
   183
        Object v = m.get("allNames");
jtulach@779
   184
        assertNotNull(v, "Value should be in the map");
jtulach@779
   185
        assertEquals(v.getClass(), One.class, "It is instance of One");
jtulach@779
   186
        One o = (One)v;
jtulach@779
   187
        assertEquals(o.changes, 0, "No changes so far");
jtulach@779
   188
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@779
   189
        assertEquals(o.get(), "HiHello");
jtulach@779
   190
jtulach@779
   191
        MyY y = new MyY("Cus", 1);
jtulach@779
   192
        p.getAll().add(y);
jtulach@779
   193
        
jtulach@779
   194
        assertEquals(o.changes, 1, "One change so far");
jtulach@779
   195
        assertEquals(o.get(), "HiHelloCus");
jtulach@779
   196
        
jtulach@779
   197
        y.setValue("Nazdar");
jtulach@779
   198
        
jtulach@779
   199
        assertEquals(o.changes, 2, "2nd change so far");
jtulach@779
   200
        assertEquals(o.get(), "HiHelloNazdar");
jtulach@779
   201
        
jtulach@780
   202
        y.setValue("Zdravim");
jtulach@780
   203
jtulach@780
   204
        assertEquals(o.changes, 3, "3rd change so far");
jtulach@780
   205
        assertEquals(o.get(), "HiHelloZdravim");
jtulach@779
   206
    }
jtulach@777
   207
    
jtulach@777
   208
    @Test public void firstChangeInArrayNotifiedProperly() throws Exception {
jtulach@777
   209
        MyX p = Models.bind(
jtulach@777
   210
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@777
   211
        ), c).applyBindings();
jtulach@777
   212
        
jtulach@777
   213
        Map m = (Map)Models.toRaw(p);
jtulach@777
   214
        Object v = m.get("firstFromNames");
jtulach@777
   215
        assertNotNull(v, "Value should be in the map");
jtulach@777
   216
        assertEquals(v.getClass(), One.class, "It is instance of One");
jtulach@777
   217
        One o = (One)v;
jtulach@777
   218
        assertEquals(o.changes, 0, "No changes so far");
jtulach@777
   219
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@777
   220
        assertEquals(o.get(), "Hi");
jtulach@777
   221
jtulach@777
   222
        p.getAll().get(0).setValue("Nazdar");
jtulach@777
   223
        
jtulach@777
   224
        assertEquals(o.get(), "Nazdar");
jtulach@777
   225
        assertEquals(o.changes, 1, "One change so far");
jtulach@777
   226
    }
jtulach@778
   227
    
jtulach@780
   228
    @Test public void firstChangeInArrayToNull() throws Exception {
jtulach@780
   229
        MyX p = Models.bind(
jtulach@780
   230
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@780
   231
        ), c).applyBindings();
jtulach@780
   232
        
jtulach@780
   233
        Map m = (Map)Models.toRaw(p);
jtulach@780
   234
        Object v = m.get("firstFromNames");
jtulach@780
   235
        assertNotNull(v, "Value should be in the map");
jtulach@780
   236
        assertEquals(v.getClass(), One.class, "It is instance of One");
jtulach@780
   237
        One o = (One)v;
jtulach@780
   238
        assertEquals(o.changes, 0, "No changes so far");
jtulach@780
   239
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@780
   240
        assertEquals(o.get(), "Hi");
jtulach@780
   241
jtulach@780
   242
        p.getAll().get(0).setValue(null);
jtulach@780
   243
        
jtulach@780
   244
        assertEquals(o.get(), "Hello");
jtulach@780
   245
        assertEquals(o.changes, 1, "One change so far");
jtulach@780
   246
        
jtulach@780
   247
        p.getAll().get(0).setValue("Nazdar");
jtulach@780
   248
jtulach@780
   249
        assertEquals(o.get(), "Nazdar");
jtulach@780
   250
        assertEquals(o.changes, 2, "2nd change so far");
jtulach@780
   251
    }
jtulach@780
   252
    
jtulach@778
   253
    @Test public void firstChangeInArrayNotifiedTransitively() throws Exception {
jtulach@778
   254
        MyOverall p = Models.bind(
jtulach@778
   255
            new MyOverall(new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999))
jtulach@778
   256
        ), c).applyBindings();
jtulach@778
   257
        
jtulach@778
   258
        Map m = (Map)Models.toRaw(p);
jtulach@778
   259
        Object v = m.get("valueAccross");
jtulach@778
   260
        assertNotNull(v, "Value should be in the map");
jtulach@778
   261
        assertEquals(v.getClass(), One.class, "It is instance of One");
jtulach@778
   262
        One o = (One)v;
jtulach@778
   263
        assertEquals(o.changes, 0, "No changes so far");
jtulach@778
   264
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@778
   265
        assertEquals(o.get(), "Hi");
jtulach@778
   266
jtulach@778
   267
        p.getX().getAll().get(0).setValue("Nazdar");
jtulach@778
   268
        
jtulach@778
   269
        assertEquals(o.get(), "Nazdar");
jtulach@778
   270
        assertEquals(o.changes, 1, "One change so far");
jtulach@778
   271
    }
jtulach@778
   272
    
jtulach@777
   273
    @Test public void secondChangeInArrayIgnored() throws Exception {
jtulach@777
   274
        MyX p = Models.bind(
jtulach@777
   275
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@777
   276
        ), c).applyBindings();
jtulach@777
   277
        
jtulach@777
   278
        Map m = (Map)Models.toRaw(p);
jtulach@777
   279
        Object v = m.get("firstFromNames");
jtulach@777
   280
        assertNotNull(v, "Value should be in the map");
jtulach@777
   281
        assertEquals(v.getClass(), One.class, "It is instance of One");
jtulach@777
   282
        One o = (One)v;
jtulach@777
   283
        assertEquals(o.changes, 0, "No changes so far");
jtulach@777
   284
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@777
   285
        assertEquals(o.get(), "Hi");
jtulach@777
   286
jtulach@777
   287
        p.getAll().get(1).setValue("Nazdar");
jtulach@777
   288
        
jtulach@777
   289
        assertEquals(o.get(), "Hi");
jtulach@777
   290
        assertEquals(o.changes, 0, "No change so far");
jtulach@777
   291
    }
jtulach@777
   292
    
jtulach@777
   293
    @Test public void changeInArraySizeNeedsToBeRecomputed() throws Exception {
jtulach@777
   294
        MyX p = Models.bind(
jtulach@777
   295
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@777
   296
        ), c).applyBindings();
jtulach@777
   297
        
jtulach@777
   298
        Map m = (Map)Models.toRaw(p);
jtulach@777
   299
        Object v = m.get("firstFromNames");
jtulach@777
   300
        assertNotNull(v, "Value should be in the map");
jtulach@777
   301
        assertEquals(v.getClass(), One.class, "It is instance of One");
jtulach@777
   302
        One o = (One)v;
jtulach@777
   303
        assertEquals(o.changes, 0, "No changes so far");
jtulach@777
   304
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@777
   305
        assertEquals(o.get(), "Hi");
jtulach@777
   306
jtulach@777
   307
        p.getAll().remove(1);
jtulach@777
   308
        
jtulach@777
   309
        assertEquals(o.get(), "Hi");
jtulach@777
   310
        assertEquals(o.changes, 1, "This required a change");
jtulach@777
   311
    }
jtulach@777
   312
    
jtulach@775
   313
    @Test public void doublePropertyChangeNotified() throws Exception {
jtulach@775
   314
        MyX p = Models.bind(
jtulach@775
   315
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@775
   316
        ), c).applyBindings();
jtulach@775
   317
        
jtulach@775
   318
        Map m = (Map)Models.toRaw(p);
jtulach@775
   319
        Object v = m.get("oneName");
jtulach@775
   320
        assertNotNull(v, "Value should be in the map");
jtulach@775
   321
        Object v2 = m.get("sndName");
jtulach@775
   322
        assertNotNull(v2, "Value2 should be in the map");
jtulach@775
   323
        One o = (One)v;
jtulach@775
   324
        One o2 = (One)v2;
jtulach@775
   325
        assertEquals(o.changes, 0, "No changes so far");
jtulach@775
   326
        assertEquals(o2.changes, 0, "No changes so far");
jtulach@775
   327
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@775
   328
        assertEquals(o.get(), "Ahoj");
jtulach@775
   329
        assertEquals(o2.get(), "AHOJ");
jtulach@775
   330
jtulach@775
   331
        p.getOne().setValue("Nazdar");
jtulach@775
   332
        
jtulach@775
   333
        assertEquals(o.get(), "Nazdar");
jtulach@775
   334
        assertEquals(o.changes, 1, "One change so far");
jtulach@775
   335
        assertEquals(o2.changes, 1, "One change so far");
jtulach@775
   336
        assertEquals(o2.get(), "NAZDAR");
jtulach@775
   337
    }
jtulach@775
   338
    
jtulach@775
   339
    @Test public void onlyAffectedPropertyChangeNotified() throws Exception {
jtulach@775
   340
        MyX p = Models.bind(
jtulach@775
   341
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@775
   342
        ), c).applyBindings();
jtulach@775
   343
        
jtulach@775
   344
        Map m = (Map)Models.toRaw(p);
jtulach@775
   345
        Object v = m.get("oneName");
jtulach@775
   346
        assertNotNull(v, "Value should be in the map");
jtulach@775
   347
        Object v2 = m.get("thrdName");
jtulach@775
   348
        assertNotNull(v2, "Value2 should be in the map");
jtulach@775
   349
        One o = (One)v;
jtulach@775
   350
        One o2 = (One)v2;
jtulach@775
   351
        assertEquals(o.changes, 0, "No changes so far");
jtulach@775
   352
        assertEquals(o2.changes, 0, "No changes so far");
jtulach@775
   353
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@775
   354
        assertEquals(o.get(), "Ahoj");
jtulach@775
   355
        assertEquals(o2.get(), "X0");
jtulach@775
   356
jtulach@775
   357
        p.getOne().setCount(10);
jtulach@775
   358
        
jtulach@775
   359
        assertEquals(o.get(), "Ahoj");
jtulach@775
   360
        assertEquals(o.changes, 0, "Still no change");
jtulach@775
   361
        assertEquals(o2.changes, 1, "One change so far");
jtulach@775
   362
        assertEquals(o2.get(), "X10");
jtulach@775
   363
    }
jtulach@776
   364
    
jtulach@776
   365
    @Test public void onlyDeepPropsAreNotified() throws Exception {
jtulach@776
   366
        MyX p = Models.bind(
jtulach@776
   367
            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
jtulach@776
   368
        ), c).applyBindings();
jtulach@776
   369
        
jtulach@776
   370
        Map m = (Map)Models.toRaw(p);
jtulach@776
   371
        Object v = m.get("oneName");
jtulach@776
   372
        assertNotNull(v, "Value should be in the map");
jtulach@776
   373
        Object v2 = m.get("noName");
jtulach@776
   374
        assertNotNull(v2, "Value2 should be in the map");
jtulach@776
   375
        One o = (One)v;
jtulach@776
   376
        One o2 = (One)v2;
jtulach@776
   377
        assertEquals(o.changes, 0, "No changes so far");
jtulach@776
   378
        assertEquals(o2.changes, 0, "No changes so far");
jtulach@776
   379
        assertTrue(o.pb.isReadOnly(), "Derived property");
jtulach@776
   380
        assertEquals(o.get(), "Ahoj");
jtulach@778
   381
        assertEquals(o2.get(), "AHOJ");
jtulach@776
   382
jtulach@776
   383
        p.getOne().setValue("Nazdar");
jtulach@776
   384
        
jtulach@776
   385
        assertEquals(o.get(), "Nazdar");
jtulach@776
   386
        assertEquals(o.changes, 1, "One change so far");
jtulach@776
   387
        assertEquals(o2.changes, 0, "This change is not noticed");
jtulach@776
   388
        assertEquals(o2.get(), "NAZDAR", "but property value changes when computed");
jtulach@776
   389
    }
jtulach@787
   390
jtulach@787
   391
    static final class One {
jtulach@787
   392
jtulach@787
   393
        int changes;
jtulach@787
   394
        final PropertyBinding pb;
jtulach@787
   395
        final FunctionBinding fb;
jtulach@787
   396
jtulach@787
   397
        One(Object m, PropertyBinding pb) throws NoSuchMethodException {
jtulach@787
   398
            this.pb = pb;
jtulach@787
   399
            this.fb = null;
jtulach@787
   400
        }
jtulach@787
   401
jtulach@787
   402
        One(Object m, FunctionBinding fb) throws NoSuchMethodException {
jtulach@787
   403
            this.pb = null;
jtulach@787
   404
            this.fb = fb;
jtulach@787
   405
        }
jtulach@787
   406
jtulach@787
   407
        Object get() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
jtulach@787
   408
            return pb.getValue();
jtulach@787
   409
        }
jtulach@787
   410
jtulach@787
   411
        void set(Object v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
jtulach@787
   412
            pb.setValue(v);
jtulach@787
   413
        }
jtulach@787
   414
    }
jtulach@787
   415
jtulach@787
   416
    static final class MapTechnology
jtulach@787
   417
            implements Technology<Map<String, One>>, Transfer {
jtulach@787
   418
jtulach@787
   419
        @Override
jtulach@787
   420
        public Map<String, One> wrapModel(Object model) {
jtulach@787
   421
            return new HashMap<String, One>();
jtulach@787
   422
        }
jtulach@787
   423
jtulach@787
   424
        @Override
jtulach@787
   425
        public void valueHasMutated(Map<String, One> data, String propertyName) {
jtulach@787
   426
            One p = data.get(propertyName);
jtulach@787
   427
            if (p != null) {
jtulach@787
   428
                p.changes++;
jtulach@787
   429
            }
jtulach@787
   430
        }
jtulach@787
   431
jtulach@787
   432
        @Override
jtulach@787
   433
        public void bind(PropertyBinding b, Object model, Map<String, One> data) {
jtulach@787
   434
            try {
jtulach@787
   435
                One o = new One(model, b);
jtulach@787
   436
                data.put(b.getPropertyName(), o);
jtulach@787
   437
            } catch (NoSuchMethodException ex) {
jtulach@787
   438
                throw new IllegalStateException(ex);
jtulach@787
   439
            }
jtulach@787
   440
        }
jtulach@787
   441
jtulach@787
   442
        @Override
jtulach@787
   443
        public void expose(FunctionBinding fb, Object model, Map<String, One> data) {
jtulach@787
   444
            try {
jtulach@787
   445
                data.put(fb.getFunctionName(), new One(model, fb));
jtulach@787
   446
            } catch (NoSuchMethodException ex) {
jtulach@787
   447
                throw new IllegalStateException(ex);
jtulach@787
   448
            }
jtulach@787
   449
        }
jtulach@787
   450
jtulach@787
   451
        @Override
jtulach@787
   452
        public void applyBindings(Map<String, One> data) {
jtulach@787
   453
        }
jtulach@787
   454
jtulach@787
   455
        @Override
jtulach@787
   456
        public Object wrapArray(Object[] arr) {
jtulach@787
   457
            return arr;
jtulach@787
   458
        }
jtulach@787
   459
jtulach@787
   460
        @Override
jtulach@787
   461
        public void extract(Object obj, String[] props, Object[] values) {
jtulach@787
   462
            Map<?, ?> map = obj instanceof Map ? (Map<?, ?>) obj : null;
jtulach@787
   463
            for (int i = 0; i < Math.min(props.length, values.length); i++) {
jtulach@787
   464
                if (map == null) {
jtulach@787
   465
                    values[i] = null;
jtulach@787
   466
                } else {
jtulach@787
   467
                    values[i] = map.get(props[i]);
jtulach@787
   468
                    if (values[i] instanceof One) {
jtulach@787
   469
                        values[i] = ((One) values[i]).pb.getValue();
jtulach@787
   470
                    }
jtulach@787
   471
                }
jtulach@787
   472
            }
jtulach@787
   473
        }
jtulach@787
   474
jtulach@787
   475
        @Override
jtulach@787
   476
        public void loadJSON(JSONCall call) {
jtulach@787
   477
            call.notifyError(new UnsupportedOperationException());
jtulach@787
   478
        }
jtulach@787
   479
jtulach@787
   480
        @Override
jtulach@787
   481
        public <M> M toModel(Class<M> modelClass, Object data) {
jtulach@787
   482
            return modelClass.cast(data);
jtulach@787
   483
        }
jtulach@787
   484
jtulach@787
   485
        @Override
jtulach@787
   486
        public Object toJSON(InputStream is) throws IOException {
jtulach@787
   487
            throw new IOException();
jtulach@787
   488
        }
jtulach@787
   489
jtulach@787
   490
        @Override
jtulach@787
   491
        public void runSafe(Runnable r) {
jtulach@787
   492
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jtulach@787
   493
        }
jtulach@787
   494
    }
jtulach@776
   495
    
jaroslav@9
   496
}