You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by jt...@apache.org on 2017/09/03 12:48:39 UTC

[06/24] incubator-netbeans-html4j git commit: [INFRA-15006] Initial donation of HTML/Java NetBeans API. Equivalent to the content of html4j-donation-review.zip donated as part of ApacheNetBeansDonation1.zip with SHA256 being 7f2ca0f61953a190613c9a0fbcc1b

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java b/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java
new file mode 100644
index 0000000..9da3ddd
--- /dev/null
+++ b/json/src/test/java/net/java/html/json/PrimitiveArrayTest.java
@@ -0,0 +1,80 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.json;
+
+import java.util.Collections;
+import java.util.List;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Model(className="ByteArray", properties = {
+    @Property(name = "array", type = byte.class, array = true)
+})
+public class PrimitiveArrayTest {
+    @ComputedProperty static int length(List<Byte> array) {
+        return array.size();
+    }
+
+    @ComputedProperty static List<Integer> lengthAsList(List<Byte> array) {
+        return Collections.nCopies(1, array.size());
+    }
+
+    @ComputedProperty static List<String> lengthTextList(List<Byte> array) {
+        return Collections.nCopies(1, "" + array.size());
+    }
+    
+    @Test public void generatedConstructorWithPrimitiveType() {
+        byte[] arr = new byte[10];
+        arr[3] = 10;
+        ByteArray a = new ByteArray(arr);
+        Assert.assertEquals(a.getArray().size(), 10, "Ten elements");
+        Assert.assertEquals(a.getArray().get(3).byteValue(), 10, "Value ten");
+        Assert.assertEquals(a.getLength(), 10, "Derived property is OK too");
+        Assert.assertEquals(a.getLengthTextList().get(0), "10", "Derived string list property is OK");
+        Assert.assertEquals((int)a.getLengthAsList().get(0), 10, "Derived Integer list property is OK");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/net/java/html/json/Sex.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/net/java/html/json/Sex.java b/json/src/test/java/net/java/html/json/Sex.java
new file mode 100644
index 0000000..ef00f00
--- /dev/null
+++ b/json/src/test/java/net/java/html/json/Sex.java
@@ -0,0 +1,51 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.json;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public enum Sex {
+    MALE, FEMALE;
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/net/java/html/json/TypesTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/net/java/html/json/TypesTest.java b/json/src/test/java/net/java/html/json/TypesTest.java
new file mode 100644
index 0000000..693f415
--- /dev/null
+++ b/json/src/test/java/net/java/html/json/TypesTest.java
@@ -0,0 +1,145 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.json;
+
+import net.java.html.BrwsrCtx;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import net.java.html.json.MapModelTest.One;
+import org.netbeans.html.context.spi.Contexts;
+import org.netbeans.html.json.spi.Technology;
+import org.netbeans.html.json.spi.Transfer;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Model(className = "Types", properties = {
+    @Property(name = "intX", type = int.class),
+    @Property(name = "byteX", type = byte.class),
+    @Property(name = "shortX", type = short.class),
+    @Property(name = "longX", type = long.class),
+    @Property(name = "floatX", type = float.class),
+    @Property(name = "doubleX", type = double.class),
+    @Property(name = "charX", type = char.class),
+    @Property(name = "StringX", type = String.class),
+    @Property(name = "boolX", type = boolean.class),
+})
+public class TypesTest {
+    private MapModelTest.MapTechnology t;
+    private BrwsrCtx c;
+
+    @BeforeMethod public void initTechnology() {
+        t = new MapModelTest.MapTechnology();
+        c = Contexts.newBuilder().register(Technology.class, t, 1).
+            register(Transfer.class, t, 1).build();
+    }
+    @Function static void readFromEvent(int intX, 
+        byte byteX, 
+        short shortX, long longX, float floatX, 
+        boolean boolX,
+        char charX,
+        double doubleX,
+        String StringX, Types myModel) {
+        
+        myModel.setIntX(intX);
+        myModel.setDoubleX(doubleX);
+        myModel.setStringX(StringX);
+        
+        myModel.setByteX(byteX);
+        myModel.setShortX(shortX);
+        myModel.setLongX(longX);
+        myModel.setFloatX(floatX);
+        myModel.setBoolX(boolX);
+        myModel.setCharX(charX);
+    }
+    
+    @Test public void canParseEventAttributes() {
+        Types t = Models.bind(new Types(), c);
+        t.setIntX(33);
+        t.setDoubleX(180.5);
+        t.setStringX("Ahoj");
+        t.setCharX('A');
+        t.setByteX((byte)3);
+        t.setShortX((short)10);
+        t.setLongX(66);
+        t.setFloatX(99f);
+        t.setBoolX(true);
+        
+        assertValidJSON(t.toString());
+        
+        Object json = Models.toRaw(t);
+        
+        Types copy = Models.bind(new Types(), c);
+        Map copyMap = (Map) Models.toRaw(copy);
+        One o = (One) copyMap.get("readFromEvent");
+        o.fb.call(null, json);
+        
+        assertEquals(copy.getIntX(), 33);
+        assertEquals(copy.getDoubleX(), 180.5);
+        assertEquals(copy.getStringX(), "Ahoj");
+        assertEquals(copy.getByteX(), (byte)3);
+        assertEquals(copy.getShortX(), (short)10);
+        assertEquals(copy.getLongX(), 66L);
+        assertEquals(copy.getFloatX(), 99f);
+        assertTrue(copy.isBoolX());
+        assertEquals(copy.getCharX(), 'A');
+    }
+    
+    private static void assertValidJSON(String text) {
+        ScriptEngineManager sem = new ScriptEngineManager();
+        ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
+        try {
+            eng.eval("var obj = " + text + ";");
+        } catch (ScriptException ex) {
+            fail("Cannot parse " + text, ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/net/java/html/json/UnderscoreTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/net/java/html/json/UnderscoreTest.java b/json/src/test/java/net/java/html/json/UnderscoreTest.java
new file mode 100644
index 0000000..884c677
--- /dev/null
+++ b/json/src/test/java/net/java/html/json/UnderscoreTest.java
@@ -0,0 +1,67 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.json;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import org.testng.annotations.Test;
+
+
+@Model(className = "UnderscoreModel", targetId="", properties = {
+    @Property(name="__meta", type = MetaModel.class),
+})
+public class UnderscoreTest {
+    @Model(className = "MetaModel", properties = {
+    })
+    static final class MetaCntrl {
+    }
+
+    @Test
+    public void accessMeta() {
+        UnderscoreModel model = new UnderscoreModel();
+        assertNotNull(model);
+        MetaModel meta = new MetaModel();
+        model.set__meta(meta);
+        assertEquals(model.get__meta(), meta);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/net/java/html/json/WebSocketCallTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/net/java/html/json/WebSocketCallTest.java b/json/src/test/java/net/java/html/json/WebSocketCallTest.java
new file mode 100644
index 0000000..01139a7
--- /dev/null
+++ b/json/src/test/java/net/java/html/json/WebSocketCallTest.java
@@ -0,0 +1,56 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.json;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Model(className = "WebSocketCallTestMode", properties = {
+    @Property(name = "nic", type = int.class)
+})
+public class WebSocketCallTest {
+    @OnReceive(method = "WebSocket", data = Person.class, url="{url}")
+    static void wsCall(WebSocketCallTestMode model, Person data) {
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/net/java/html/json/sub/StreetCntrl.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/net/java/html/json/sub/StreetCntrl.java b/json/src/test/java/net/java/html/json/sub/StreetCntrl.java
new file mode 100644
index 0000000..87e13ef
--- /dev/null
+++ b/json/src/test/java/net/java/html/json/sub/StreetCntrl.java
@@ -0,0 +1,53 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package net.java.html.json.sub;
+
+import net.java.html.json.Model;
+import net.java.html.json.Property;
+
+@Model(className = "Street", properties = {
+    @Property(name = "name", type = String.class),
+    @Property(name = "id", type = int.class),
+})
+class StreetCntrl {
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/BuilderTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/BuilderTest.java b/json/src/test/java/org/netbeans/html/json/impl/BuilderTest.java
new file mode 100644
index 0000000..55d1dce
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/BuilderTest.java
@@ -0,0 +1,117 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import java.lang.reflect.Constructor;
+import net.java.html.json.Model;
+import net.java.html.json.Property;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+@Model(className="Builder", builder = "", properties = {
+    @Property(name="bytes", type = byte.class, array = true),
+    @Property(name="chars", type = char.class, array = true),
+    @Property(name="shorts", type = short.class, array = true),
+    @Property(name="ints", type = int.class, array = true),
+    @Property(name="longs", type = long.class, array = true),
+    @Property(name="floats", type = float.class, array = true),
+    @Property(name="doubles", type = double.class, array = true),
+    @Property(name="strings", type = String.class, array = true),
+})
+public class BuilderTest {
+    @Test
+    public void onlyDefaultClassLoader() {
+        Constructor<?>[] arr = Builder.class.getConstructors();
+        assertEquals(arr.length, 1, "One constructor");
+        assertEquals(arr[0].getParameterTypes().length, 0, "No parameters");
+    }
+
+    @Test
+    public void assignBytes() {
+        Builder b = new Builder().bytes((byte)10, (byte)20, (byte)30);
+        assertEquals(b.getBytes().size(), 3);
+        assertEquals(b.getBytes().get(0).byteValue(), (byte)10);
+    }
+    @Test
+    public void assignChars() {
+        Builder b = new Builder().chars((char)10, (char)20, (char)30);
+        assertEquals(b.getChars().size(), 3);
+        assertEquals(b.getChars().get(0).charValue(), 10);
+    }
+    @Test
+    public void assignShort() {
+        Builder b = new Builder().shorts((short)10, (short)20, (short)30);
+        assertEquals(b.getShorts().size(), 3);
+        assertEquals(b.getShorts().get(0).intValue(), 10);
+    }
+    @Test
+    public void assignInts() {
+        Builder b = new Builder().ints(10, 20, 30);
+        assertEquals(b.getInts().size(), 3);
+        assertEquals(b.getInts().get(0).intValue(), 10);
+    }
+    @Test
+    public void assignLongs() {
+        Builder b = new Builder().longs(10, 20, 30);
+        assertEquals(b.getLongs().size(), 3);
+        assertEquals(b.getLongs().get(1).intValue(), 20);
+    }
+    @Test
+    public void assignDouble() {
+        Builder b = new Builder().doubles(10, 20, 30);
+        assertEquals(b.getDoubles().size(), 3);
+        assertEquals(b.getDoubles().get(0), 10.0);
+    }
+    @Test
+    public void assignFloats() {
+        Builder b = new Builder().floats(10, 20, 30);
+        assertEquals(b.getFloats().size(), 3);
+        assertEquals(b.getFloats().get(0), 10.0f);
+    }
+    @Test
+    public void assignStrings() {
+        Builder b = new Builder().strings("A", "AB", "ABC");
+        assertEquals(b.getStrings().size(), 3);
+        assertEquals(b.getStrings().get(1), "AB");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/ConstructorTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/ConstructorTest.java b/json/src/test/java/org/netbeans/html/json/impl/ConstructorTest.java
new file mode 100644
index 0000000..ffa48c0
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/ConstructorTest.java
@@ -0,0 +1,80 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import net.java.html.json.Model;
+import net.java.html.json.Property;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Model(className="Man", properties={
+    @Property(name = "name", type = String.class),
+    @Property(name = "other", type = Address.class, array = true),
+    @Property(name = "primary", type = Address.class),
+    @Property(name = "childrenNames", type = String.class, array = true)
+})
+public class ConstructorTest {
+    @Model(className = "Address", properties = {
+        @Property(name = "place", type = String.class)
+    })
+    static final class AddressModel {
+    }
+    
+    @Test public void initializedByDefault() {
+        Man m = new Man();
+        assertNotNull(m.getPrimary(), "Single subobjects are initialized");
+    }
+    
+    @Test public void hasRichConstructor() {
+        Man m = new Man("Jarda", new Address("home"), new Address("work"), new Address("hotel"));
+        assertEquals(m.getName(), "Jarda");
+        assertNotNull(m.getPrimary(), "Primary address specified");
+        assertNotNull(m.getPrimary().getPlace(), "home");
+        assertEquals(m.getOther().size(), 2, "Two other addresses");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java b/json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java
new file mode 100644
index 0000000..5354da3
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java
@@ -0,0 +1,617 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import net.java.html.BrwsrCtx;
+import net.java.html.json.ComputedProperty;
+import net.java.html.json.Model;
+import net.java.html.json.Models;
+import net.java.html.json.Property;
+import org.netbeans.html.context.spi.Contexts;
+import org.netbeans.html.json.spi.FunctionBinding;
+import org.netbeans.html.json.spi.JSONCall;
+import org.netbeans.html.json.spi.PropertyBinding;
+import org.netbeans.html.json.spi.Technology;
+import org.netbeans.html.json.spi.Transfer;
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class DeepChangeTest {
+    private MapTechnology t;
+    private BrwsrCtx c;
+
+    @BeforeMethod public void initTechnology() {
+        t = new MapTechnology();
+        c = Contexts.newBuilder().register(Technology.class, t, 1).
+            register(Transfer.class, t, 1).build();
+    }
+    
+    @Model(className = "MyX", targetId = "anythingX", properties = {
+        @Property(name = "one", type = MyY.class),
+        @Property(name = "all", type = MyY.class, array = true)
+    })
+    static class X {
+        @ComputedProperty @Transitive(deep = true)
+        static MyY oneCopy(MyY one) {
+            return Models.bind(one, BrwsrCtx.findDefault(X.class));
+        }
+        @ComputedProperty @Transitive(deep = true) 
+        static String oneName(MyY one) {
+            return one.getValue();
+        }
+        @ComputedProperty
+        static String sndName(MyY one) {
+            if (one == null || one.getValue() == null) {
+                return null;
+            } else {
+                return one.getValue().toUpperCase();
+            }
+        }
+        @ComputedProperty @Transitive(deep = false) 
+        static String noName(MyY one) {
+            if (one == null || one.getValue() == null) {
+                return null;
+            } else {
+                return one.getValue().toUpperCase();
+            }
+        }
+        @ComputedProperty @Transitive(deep = true) 
+        static String thrdName(MyY one) {
+            return "X" + one.getCount();
+        }
+        
+        @ComputedProperty
+        static String allNames(List<MyY> all) {
+            StringBuilder sb = new StringBuilder();
+            for (MyY y : all) {
+                sb.append(y.getValue());
+            }
+            return sb.toString();
+        }
+
+        @ComputedProperty @Transitive(deep = true)
+        static String firstFromNames(List<MyY> all) {
+            for (MyY y : all) {
+                if (y != null && y.getValue() != null) {
+                    return y.getValue();
+                }
+            }
+            return null;
+        }
+    }
+    @Model(className = "MyY", properties = {
+        @Property(name = "value", type = String.class),
+        @Property(name = "count", type = int.class)
+    })
+    static class Y {
+    }
+    @Model(className = "MyOverall", properties = {
+        @Property(name = "x", type = MyX.class)
+    })
+    static class Overall {
+        @ComputedProperty @Transitive(deep = true) 
+        static String valueAccross(MyX x) {
+            return x.getFirstFromNames();
+        }
+    }
+    
+    @Test public void isTransitiveChangeNotifiedProperly() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("oneName");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Ahoj");
+
+        p.getOne().setValue("Nazdar");
+        
+        assertEquals(o.get(), "Nazdar");
+        assertEquals(o.changes, 1, "One change so far");
+    }
+    
+    @Test public void isTransitiveChangeInArrayNotifiedProperly() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("allNames");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "HiHello");
+
+        p.getAll().get(0).setValue("Nazdar");
+        
+        assertEquals(o.get(), "NazdarHello");
+        assertEquals(o.changes, 1, "One change so far");
+    }
+
+    @Test public void changingModelClass() throws Exception {
+        final MyY myY = new MyY("Ahoj", 0);
+        MyX p = Models.bind(
+            new MyX(myY, new MyY("Hi", 333), new MyY("Hello", 999)),
+            c)
+        .applyBindings();
+        MyY realY = p.getOne();
+
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("one");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertFalse(o.pb.isReadOnly(), "Normal property");
+        assertEquals(o.get(), myY);
+        assertSame(o.get(), realY);
+
+        final MyY newY = new MyY("Hi", 1);
+        p.setOne(newY);
+
+        assertSame(p.getOne(), newY);
+        assertEquals(o.changes, 1, "One change");
+    }
+
+    @Test public void addingIntoArray() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("allNames");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "HiHello");
+
+        MyY y = new MyY("Cus", 1);
+        p.getAll().add(y);
+        
+        assertEquals(o.changes, 1, "One change so far");
+        assertEquals(o.get(), "HiHelloCus");
+        
+        y.setValue("Nazdar");
+        
+        assertEquals(o.changes, 2, "2nd change so far");
+        assertEquals(o.get(), "HiHelloNazdar");
+        
+        y.setValue("Zdravim");
+
+        assertEquals(o.changes, 3, "3rd change so far");
+        assertEquals(o.get(), "HiHelloZdravim");
+    }
+    
+    @Test public void firstChangeInArrayNotifiedProperly() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("firstFromNames");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Hi");
+
+        p.getAll().get(0).setValue("Nazdar");
+        
+        assertEquals(o.get(), "Nazdar");
+        assertEquals(o.changes, 1, "One change so far");
+    }
+    
+    @Test public void firstChangeInArrayToNull() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("firstFromNames");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Hi");
+
+        p.getAll().get(0).setValue(null);
+        
+        assertEquals(o.get(), "Hello");
+        assertEquals(o.changes, 1, "One change so far");
+        
+        p.getAll().get(0).setValue("Nazdar");
+
+        assertEquals(o.get(), "Nazdar");
+        assertEquals(o.changes, 2, "2nd change so far");
+    }
+    
+    @Test public void firstChangeInArrayNotifiedTransitively() throws Exception {
+        MyOverall p = Models.bind(
+            new MyOverall(new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999))
+        ), c);
+        Models.applyBindings(p);
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("valueAccross");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Hi");
+
+        p.getX().getAll().get(0).setValue("Nazdar");
+        
+        assertEquals(o.get(), "Nazdar");
+        assertEquals(o.changes, 1, "One change so far");
+    }
+    
+    @Test public void secondChangeInArrayIgnored() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("firstFromNames");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Hi");
+
+        p.getAll().get(1).setValue("Nazdar");
+        
+        assertEquals(o.get(), "Hi");
+        assertEquals(o.changes, 0, "No change so far");
+    }
+    
+    @Test public void changeInArraySizeNeedsToBeRecomputed() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("firstFromNames");
+        assertNotNull(v, "Value should be in the map");
+        assertEquals(v.getClass(), One.class, "It is instance of One");
+        One o = (One)v;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Hi");
+
+        p.getAll().remove(1);
+        
+        assertEquals(o.get(), "Hi");
+        assertEquals(o.changes, 1, "This required a change");
+    }
+    
+    @Test public void doublePropertyChangeNotified() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("oneName");
+        assertNotNull(v, "Value should be in the map");
+        Object v2 = m.get("sndName");
+        assertNotNull(v2, "Value2 should be in the map");
+        One o = (One)v;
+        One o2 = (One)v2;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertEquals(o2.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Ahoj");
+        assertEquals(o2.get(), "AHOJ");
+
+        p.getOne().setValue("Nazdar");
+        
+        assertEquals(o.get(), "Nazdar");
+        assertEquals(o.changes, 1, "One change so far");
+        assertEquals(o2.changes, 1, "One change so far");
+        assertEquals(o2.get(), "NAZDAR");
+    }
+    
+    @Test public void onlyAffectedPropertyChangeNotified() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("oneName");
+        assertNotNull(v, "Value should be in the map");
+        Object v2 = m.get("thrdName");
+        assertNotNull(v2, "Value2 should be in the map");
+        One o = (One)v;
+        One o2 = (One)v2;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertEquals(o2.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Ahoj");
+        assertEquals(o2.get(), "X0");
+
+        p.getOne().setCount(10);
+        
+        assertEquals(o.get(), "Ahoj");
+        assertEquals(o.changes, 0, "Still no change");
+        assertEquals(o2.changes, 1, "One change so far");
+        assertEquals(o2.get(), "X10");
+    }
+    
+    @Test public void onlyDeepPropsAreNotified() throws Exception {
+        MyX p = Models.bind(
+            new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+        
+        Map m = (Map)Models.toRaw(p);
+        Object v = m.get("oneName");
+        assertNotNull(v, "Value should be in the map");
+        Object v2 = m.get("noName");
+        assertNotNull(v2, "Value2 should be in the map");
+        One o = (One)v;
+        One o2 = (One)v2;
+        assertEquals(o.changes, 0, "No changes so far");
+        assertEquals(o2.changes, 0, "No changes so far");
+        assertTrue(o.pb.isReadOnly(), "Derived property");
+        assertEquals(o.get(), "Ahoj");
+        assertEquals(o2.get(), "AHOJ");
+
+        p.getOne().setValue("Nazdar");
+        
+        assertEquals(o.get(), "Nazdar");
+        assertEquals(o.changes, 1, "One change so far");
+        assertEquals(o2.changes, 0, "This change is not noticed");
+        assertEquals(o2.get(), "NAZDAR", "but property value changes when computed");
+    }
+
+    @Test
+    public void mixingContextsIsOK() throws Exception {
+        BrwsrCtx ctx = Contexts.newBuilder().build();
+        final MyY one = Models.bind(new MyY("Ahoj", 0), ctx);
+        MyX p = Models.bind(
+            new MyX(one, new MyY("Hi", 333), new MyY("Hello", 999)), c
+        ).applyBindings();
+
+        Map m = (Map) Models.toRaw(p);
+        Object v = m.get("oneName");
+        assertNotNull(v, "Value should be in the map");
+        One o = (One) v;
+        assertEquals(o.get(), "Ahoj");
+
+        p.getOne().setValue("Nazdar");
+
+        assertEquals(o.get(), "Nazdar");
+        assertEquals(o.changes, 1, "One change so far");
+    }
+    
+    @Test
+    public void rebindReplacesTheInstance() throws Exception {
+        BrwsrCtx ctx = Contexts.newBuilder().build();
+        MyX x = new MyX();
+
+        MyY y = Models.bind(new MyY(), ctx);
+        x.setOne(y);
+
+        assertSame(x.getOne(), y);
+    }
+
+    @Test
+    public void rebindReplacesTheInstanceAndNotifies() throws Exception {
+        BrwsrCtx ctx = Contexts.newBuilder().build();
+        final MyY one = Models.bind(new MyY(), ctx);
+        MyX p = Models.bind(
+            new MyX(one, new MyY("Hi", 333), new MyY("Hello", 999)), c
+        ).applyBindings();
+
+        Map m = (Map) Models.toRaw(p);
+        
+        Object v = m.get("one");
+        assertNotNull(v, "Value should be in the map");
+        One o = (One) v;
+        assertEquals(o.changes, 0, "No changes yet");
+
+        MyY y = Models.bind(new MyY(), ctx);
+        p.setOne(y);
+
+        assertSame(p.getOne(), y);
+        assertSame(o.changes, 1, "One change now");
+    }
+
+    @Test
+    public void mixingWithCloneIsOK() throws Exception {
+        BrwsrCtx ctx = Contexts.newBuilder().build();
+        final MyY one = Models.bind(new MyY("Ahoj", 0), ctx);
+        MyX p = Models.bind(new MyX(one, new MyY("Hi", 333), new MyY("Hello", 999)
+        ), c).applyBindings();
+
+        Map m = (Map) Models.toRaw(p);
+        Object v = m.get("oneCopy");
+        assertNotNull(v, "Value should be in the map");
+        One o = (One) v;
+        assertEquals(((MyY)o.get()).getValue(), "Ahoj");
+
+        p.getOne().setValue("Nazdar");
+
+        assertEquals(((MyY)o.get()).getValue(), "Nazdar");
+        assertEquals(o.changes, 1, "One change so far");
+    }
+
+    static final class One {
+
+        int changes;
+        final PropertyBinding pb;
+        final FunctionBinding fb;
+
+        One(Object m, PropertyBinding pb) throws NoSuchMethodException {
+            this.pb = pb;
+            this.fb = null;
+        }
+
+        One(Object m, FunctionBinding fb) throws NoSuchMethodException {
+            this.pb = null;
+            this.fb = fb;
+        }
+
+        Object get() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+            return pb.getValue();
+        }
+
+        void set(Object v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+            pb.setValue(v);
+        }
+
+        void assertNoChange(String msg) {
+            assertEquals(changes, 0, msg);
+        }
+
+        void assertChange(String msg) {
+            if (changes == 0) {
+                fail(msg);
+            }
+            changes = 0;
+        }
+    }
+
+    static final class MapTechnology
+            implements Technology<Map<String, One>>, Transfer {
+
+        @Override
+        public Map<String, One> wrapModel(Object model) {
+            return new HashMap<String, One>();
+        }
+
+        @Override
+        public void valueHasMutated(Map<String, One> data, String propertyName) {
+            One p = data.get(propertyName);
+            if (p != null) {
+                p.changes++;
+            }
+        }
+
+        @Override
+        public void bind(PropertyBinding b, Object model, Map<String, One> data) {
+            try {
+                One o = new One(model, b);
+                data.put(b.getPropertyName(), o);
+            } catch (NoSuchMethodException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+
+        @Override
+        public void expose(FunctionBinding fb, Object model, Map<String, One> data) {
+            try {
+                data.put(fb.getFunctionName(), new One(model, fb));
+            } catch (NoSuchMethodException ex) {
+                throw new IllegalStateException(ex);
+            }
+        }
+
+        @Override
+        public void applyBindings(Map<String, One> data) {
+        }
+
+        @Override
+        public Object wrapArray(Object[] arr) {
+            return arr;
+        }
+
+        @Override
+        public void extract(Object obj, String[] props, Object[] values) {
+            Map<?, ?> map = obj instanceof Map ? (Map<?, ?>) obj : null;
+            for (int i = 0; i < Math.min(props.length, values.length); i++) {
+                if (map == null) {
+                    values[i] = null;
+                } else {
+                    values[i] = map.get(props[i]);
+                    if (values[i] instanceof One) {
+                        values[i] = ((One) values[i]).pb.getValue();
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void loadJSON(JSONCall call) {
+            call.notifyError(new UnsupportedOperationException());
+        }
+
+        @Override
+        public <M> M toModel(Class<M> modelClass, Object data) {
+            return modelClass.cast(data);
+        }
+
+        @Override
+        public Object toJSON(InputStream is) throws IOException {
+            throw new IOException();
+        }
+
+        @Override
+        public void runSafe(Runnable r) {
+            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/EmployeeImpl.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/EmployeeImpl.java b/json/src/test/java/org/netbeans/html/json/impl/EmployeeImpl.java
new file mode 100644
index 0000000..c339cde
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/EmployeeImpl.java
@@ -0,0 +1,119 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import java.util.List;
+import net.java.html.json.Model;
+import net.java.html.json.OnReceive;
+import net.java.html.json.Person;
+import net.java.html.json.Property;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Model(className = "Employee", properties = {
+    @Property(name = "person", type = Person.class),
+    @Property(name = "employer", type = Employer.class),
+    @Property(name = "call", type = Call.class)
+})
+public class EmployeeImpl {
+    @OnReceive(url = "some/url")
+    static void changePersonality(Employee e, Person p) {
+        e.setPerson(p);
+    }
+
+    private static void callChangePers(Employee e) {
+        Person per = new Person();
+        e.changePersonalities(10, 3.14, "Ahoj", per);
+        e.updatePersonalities("kuk", new Person(), 1, 2, "3", new Person());
+        e.socketPersonalities("where", null);
+    }
+
+    @OnReceive(url = "some/other/url")
+    static void changePersonalities(Employee e, List<Person> data, int i, double d, String s, Person o) {
+        e.setCall(new Call(i, d, s, o, data.toArray(new Person[0])));
+    }
+
+    @OnReceive(url = "some/other/url", onError = "errorPersonalitiesWithEx")
+    static void changePersonalitiesWithEx(Employee e, List<Person> data, int i, double d, String s, Person o) {
+        e.setCall(new Call(i, d, s, o, data.toArray(new Person[0])));
+    }
+
+    static void errorPersonalitiesWithEx(Employee e, Exception ex) {
+        e.setCall(new Call(-1, -1, null, null));
+    }
+
+    @OnReceive(url = "some/other/url", onError = "errorPersonalitiesWithParam")
+    static void changePersonalitiesWithParam(Employee e, List<Person> data, int i, double d, String s, Person o) {
+        e.setCall(new Call(i, d, s, o, data.toArray(new Person[0])));
+    }
+
+    static void errorPersonalitiesWithParam(Employee e, Exception ex, int i, double d, String s, Person o) {
+        e.setCall(new Call(i, d, s, o));
+    }
+
+    @OnReceive(url = "{url}", method = "PUT", data = Person.class)
+    static void updatePersonalities(Employee e, List<Person> p, int i, double d, String s, Person o) {
+        e.setPerson(p.get(0));
+    }
+
+    @OnReceive(url = "{url}", method = "WebSocket", data = Person.class)
+    static void socketPersonalities(Employee e, List<Person> p) {
+        e.setPerson(p.get(0));
+    }
+    @OnReceive(url = "{url}", method = "WebSocket", data = Person.class)
+    static void socketArrayPersonalities(Employee e, Person[] p) {
+        e.setPerson(p[0]);
+    }
+    
+    @Model(className="Call", properties = {
+        @Property(name = "i", type=int.class),
+        @Property(name = "d", type=double.class),
+        @Property(name = "s", type=String.class),
+        @Property(name = "p", type=Person.class),
+        @Property(name = "data", type=Person.class, array = true)
+    })
+    static class CallModel {
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java b/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java
new file mode 100644
index 0000000..19b3df9
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java
@@ -0,0 +1,65 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import net.java.html.BrwsrCtx;
+import net.java.html.json.Model;
+import net.java.html.json.Models;
+import net.java.html.json.Property;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Model(className = "Employer", properties = {
+    @Property(name = "name", type = String.class)
+})
+public class EmployerTest {
+    @Test public void preLoadsTheClass() {
+        Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
+        Assert.assertNotNull(em, "Class loaded");
+        Models.applyBindings(em);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/InfinityTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/InfinityTest.java b/json/src/test/java/org/netbeans/html/json/impl/InfinityTest.java
new file mode 100644
index 0000000..035d55d
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/InfinityTest.java
@@ -0,0 +1,151 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import net.java.html.json.Model;
+import net.java.html.json.Property;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import org.testng.annotations.Test;
+
+@Model(className = "Infinity", properties = {
+    @Property(name = "next", type = Infinity.class),
+    @Property(name = "address", type = Address.class)
+})
+public class InfinityTest {
+    @Test
+    public void atLeastThousandStepsDeep() {
+        Infinity infinity = new Infinity();
+        int cnt = 0;
+        while (++cnt < 1000) {
+            infinity = infinity.getNext();
+        }
+        assertNotNull(infinity);
+        assertEquals(cnt, 1000);
+    }
+
+    @Test
+    public void afterInitializationRemainsTheSame() {
+        Infinity infinity = new Infinity();
+        Infinity first = infinity.getNext();
+        Infinity second = infinity.getNext();
+        assertSame(first, second);
+    }
+
+    @Test
+    public void nullRemains() {
+        Infinity infinity = new Infinity();
+        infinity.setNext(null);
+        assertNull(infinity.getNext(), "Remains null");
+        assertNull(infinity.getNext(), "Again");
+    }
+
+    @Test
+    public void ownValueRemains() {
+        Infinity infinity = new Infinity();
+        Infinity n = new Infinity();
+        infinity.setNext(n);
+        assertEquals(infinity.getNext(), n, "Remains n");
+        assertEquals(infinity.getNext(), n, "Again n");
+    }
+
+    @Test
+    public void nullRemainsAfterClone() {
+        Infinity infinity = new Infinity();
+        infinity.setNext(null);
+        Infinity clone = infinity.clone();
+        assertNull(clone.getNext(), "Remains null");
+        assertNull(clone.getNext(), "Again");
+        assertEquals(clone.hashCode(), infinity.hashCode(), "Same hashcode");
+    }
+
+    @Test
+    public void ownValueRemainsAfterClone() {
+        Infinity infinity = new Infinity();
+        Infinity n = new Infinity();
+        infinity.setNext(n);
+        Infinity clone = infinity.clone();
+        assertEquals(clone.getNext(), n, "Remains n");
+        assertEquals(clone.getNext(), n, "Again n");
+    }
+
+    @Test
+    public void hashCodeRemainsAfterClone() {
+        Infinity infinity = new Infinity();
+        Infinity n = new Infinity();
+        infinity.setNext(n);
+        Infinity clone = infinity.clone();
+        assertEquals(clone.getNext(), n, "Remains n");
+        assertEquals(clone.getNext(), n, "Again n");
+        assertEquals(clone.hashCode(), infinity.hashCode(), "Same hashcode");
+    }
+
+    @Test
+    public void simpleToStringWithNull() {
+        Infinity infinity = new Infinity();
+        assertNotNull(infinity.getAddress(), "Initialized will be stored as object");
+        assertEquals("{\"next\":null,\"address\":{\"place\":null}}", infinity.toString());
+        infinity.hashCode();
+
+        Infinity second = new Infinity();
+        assertEquals("{\"next\":null,\"address\":null}", second.toString(), "Uninitialized is turned into null");
+
+        second.hashCode();
+    }
+
+    @Test
+    public void toStringWithNullAndClone() {
+        Infinity infinity = new Infinity();
+        infinity.setNext(null);
+        Infinity clone = infinity.clone();
+        assertNull(infinity.getNext(), "Remains null");
+        assertNotNull(infinity.getAddress(), "Address is initialized");
+        assertNull(clone.getNext(), "Clone Remains null");
+        assertNotNull(clone.getAddress(), "Clone Address is initialized");
+        assertEquals(infinity.toString(), clone.toString());
+        assertEquals(clone.hashCode(), infinity.hashCode(), "Same hashcode");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java b/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java
new file mode 100644
index 0000000..c33df29
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/JSONListTest.java
@@ -0,0 +1,236 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import net.java.html.BrwsrCtx;
+import net.java.html.json.Model;
+import net.java.html.json.Models;
+import net.java.html.json.People;
+import net.java.html.json.Person;
+import net.java.html.json.Property;
+import net.java.html.json.Sex;
+import org.netbeans.html.context.spi.Contexts;
+import org.netbeans.html.json.spi.FunctionBinding;
+import org.netbeans.html.json.spi.PropertyBinding;
+import org.netbeans.html.json.spi.Technology;
+import static org.testng.Assert.*;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+@Model(className = "JSNLst", properties = {
+    @Property(name = "names", type = String.class, array = true)
+})
+public class JSONListTest implements Technology<Object> {
+    private boolean replaceArray;
+    private final Map<String,PropertyBinding> bindings = new HashMap<String,PropertyBinding>();
+    private final List<String> changed = new ArrayList<String>();
+    
+    public JSONListTest() {
+    }
+    
+    @BeforeMethod public void clear() {
+        replaceArray = false;
+        changed.clear();
+    }
+
+    @Test public void testConvertorOnAnObject() {
+        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
+        
+        Person p = Models.bind(new Person(), c);
+        p.setFirstName("1");
+        p.setLastName("2");
+        p.setSex(Sex.MALE);
+
+        Object real = Models.toRaw(p);
+        assertEquals(this, real, "I am the right model");
+    }
+    
+    @Test public void testConvertorOnAnArray() {
+        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
+        
+        Person p = Models.bind(new Person(), c);
+        p.setFirstName("1");
+        p.setLastName("2");
+        p.setSex(Sex.MALE);
+        
+        People people = Models.bind(new People(p), c).applyBindings();
+        assertEquals(people.getInfo().toString(), "[{\"firstName\":\"1\",\"lastName\":\"2\",\"sex\":\"MALE\"}]", "Converted to real JSON");
+        
+        PropertyBinding pb = bindings.get("info");
+        assertNotNull(pb, "Binding for info found");
+        
+        Object real = pb.getValue();
+        assertTrue(real instanceof Object[], "It is an array: " + real);
+        Object[] arr = (Object[])real;
+        assertEquals(arr.length, 1, "Size is one");
+        assertEquals(this, arr[0], "I am the right model");
+    }
+    
+    @Test public void testNicknames() {
+        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
+        
+        People people = Models.bind(new People(), c).applyBindings();
+        people.getNicknames().add("One");
+        people.getNicknames().add("Two");
+        
+        PropertyBinding pb = bindings.get("nicknames");
+        assertNotNull(pb, "Binding for info found");
+        
+        Object real = pb.getValue();
+        assertTrue(real instanceof Object[], "It is an array: " + real);
+        Object[] arr = (Object[])real;
+        assertEquals(arr.length, 2, "Length two");
+        assertEquals(arr[0], "One", "Text should be in the model");
+        assertEquals(arr[1], "Two", "2nd text in the model");
+    }
+    
+    @Test public void testConvertorOnAnArrayWithWrapper() {
+        this.replaceArray = true;
+        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
+        
+        Person p = Models.bind(new Person(), c);
+        p.setFirstName("1");
+        p.setLastName("2");
+        p.setSex(Sex.MALE);
+        
+        People people = Models.bind(new People(), c).applyBindings();
+        people.getInfo().add(p);
+        
+        Object real = JSON.find(people.getInfo());
+        assertEquals(real, this, "I am the model of the array");
+    }
+
+    @Test public void bindingsOnArray() {
+        this.replaceArray = true;
+        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
+        
+        People p = Models.bind(new People(), c).applyBindings();
+        p.getAge().add(30);
+        
+        PropertyBinding pb = bindings.get("age");
+        assertNotNull(pb, "There is a binding for age list");
+        
+        assertEquals(pb.getValue(), this, "I am the model of the array");
+    }
+    
+    @Test public void toStringOnArrayOfStrings() {
+        JSNLst l = new JSNLst("Jarda", "Jirka", "Parda");
+        assertEquals(l.toString(), "{\"names\":[\"Jarda\",\"Jirka\",\"Parda\"]}", "Properly quoted");
+    }
+
+    @Test public void testChangeOnProps() {
+        BrwsrCtx c = Contexts.newBuilder().register(Technology.class, this, 1).build();
+
+        assertTrue(changed.isEmpty());
+        
+        People p = Models.bind(new People(), c).applyBindings();
+        p.getAge().add(42);
+
+        assertEquals(sum(p.getAge()), 42);
+        assertFalse(changed.isEmpty());
+        changed.clear();
+
+        List<Integer> vals = new ArrayList<Integer>();
+        vals.add(12);
+        vals.add(30);
+        ((JSONList)p.getAge()).fastReplace(vals);
+
+        assertEquals(changed.size(), 1, "One change");
+        assertEquals(changed.get(0), "age", "One change");
+        assertEquals(sum(p.getAge()), 42);
+    }
+
+    private static int sum(List<Integer> arr) {
+        int sum = 0;
+        for (Integer i : arr) {
+            sum += i;
+        }
+        return sum;
+    }
+
+    @Override
+    public Object wrapModel(Object model) {
+        return this;
+    }
+
+    @Override
+    public void bind(PropertyBinding b, Object model, Object data) {
+        bindings.put(b.getPropertyName(), b);
+    }
+
+    @Override
+    public void valueHasMutated(Object data, String propertyName) {
+        changed.add(propertyName);
+    }
+
+    @Override
+    public void expose(FunctionBinding fb, Object model, Object d) {
+    }
+
+    @Override
+    public void applyBindings(Object data) {
+    }
+
+    @Override
+    public Object wrapArray(Object[] arr) {
+        return replaceArray ? this : arr;
+    }
+
+    @Override
+    public <M> M toModel(Class<M> modelClass, Object data) {
+        return modelClass.cast(data);
+    }
+
+    @Override
+    public void runSafe(Runnable r) {
+        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java b/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java
new file mode 100644
index 0000000..e4c7281
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/JSONTest.java
@@ -0,0 +1,84 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author Jaroslav Tulach
+ */
+public class JSONTest {
+    
+    public JSONTest() {
+    }
+
+    @Test public void longToStringValue() {
+        assertEquals(JSON.stringValue(Long.valueOf(1)), "1");
+    }
+    
+    @Test public void booleanIsSortOfNumber() {
+        assertEquals(JSON.numberValue(Boolean.TRUE), Integer.valueOf(1));
+        assertEquals(JSON.numberValue(Boolean.FALSE), Integer.valueOf(0));
+    }
+    
+    @Test public void numberToChar() {
+        assertEquals(JSON.charValue(65), Character.valueOf('A'));
+    }
+    @Test public void booleanToChar() {
+        assertEquals(JSON.charValue(false), Character.valueOf((char)0));
+        assertEquals(JSON.charValue(true), Character.valueOf((char)1));
+    }
+    @Test public void stringToChar() {
+        assertEquals(JSON.charValue("Ahoj"), Character.valueOf('A'));
+    }
+    @Test public void stringToBoolean() {
+        assertEquals(JSON.boolValue("false"), Boolean.FALSE);
+        assertEquals(JSON.boolValue("True"), Boolean.TRUE);
+    }
+    @Test public void numberToBoolean() {
+        assertEquals(JSON.boolValue(0), Boolean.FALSE);
+        assertEquals(JSON.boolValue(1), Boolean.TRUE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-netbeans-html4j/blob/226089a5/json/src/test/java/org/netbeans/html/json/impl/NoPropertiesTest.java
----------------------------------------------------------------------
diff --git a/json/src/test/java/org/netbeans/html/json/impl/NoPropertiesTest.java b/json/src/test/java/org/netbeans/html/json/impl/NoPropertiesTest.java
new file mode 100644
index 0000000..ecf975c
--- /dev/null
+++ b/json/src/test/java/org/netbeans/html/json/impl/NoPropertiesTest.java
@@ -0,0 +1,55 @@
+/**
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
+ * Other names may be trademarks of their respective owners.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License.  When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Oracle. Portions Copyright 2013-2016 Oracle. All Rights Reserved.
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ */
+package org.netbeans.html.json.impl;
+
+import net.java.html.json.Model;
+
+/** Originally could not compile.
+ *
+ * @author Jaroslav Tulach
+ */
+@Model(className="NoProperties", properties = {
+})
+public class NoPropertiesTest {
+    
+}