1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/json-beans/pom.xml Fri Feb 12 08:40:12 2016 +0100
1.3 @@ -0,0 +1,24 @@
1.4 +<?xml version="1.0" encoding="UTF-8"?>
1.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
1.6 + <modelVersion>4.0.0</modelVersion>
1.7 + <parent>
1.8 + <groupId>org.netbeans.html</groupId>
1.9 + <artifactId>pom</artifactId>
1.10 + <version>1.0-SNAPSHOT</version>
1.11 + </parent>
1.12 + <artifactId>net.java.html.beans</artifactId>
1.13 + <name>JSONBeans</name>
1.14 + <packaging>jar</packaging>
1.15 + <dependencies>
1.16 + <dependency>
1.17 + <groupId>${project.groupId}</groupId>
1.18 + <artifactId>net.java.html.json</artifactId>
1.19 + <version>${project.version}</version>
1.20 + </dependency>
1.21 + <dependency>
1.22 + <groupId>org.testng</groupId>
1.23 + <artifactId>testng</artifactId>
1.24 + <scope>test</scope>
1.25 + </dependency>
1.26 + </dependencies>
1.27 +</project>
1.28 \ No newline at end of file
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/json-beans/src/main/java/net/java/html/beans/JSONBeans.java Fri Feb 12 08:40:12 2016 +0100
2.3 @@ -0,0 +1,341 @@
2.4 +/**
2.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.6 + *
2.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
2.8 + *
2.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
2.10 + * Other names may be trademarks of their respective owners.
2.11 + *
2.12 + * The contents of this file are subject to the terms of either the GNU
2.13 + * General Public License Version 2 only ("GPL") or the Common
2.14 + * Development and Distribution License("CDDL") (collectively, the
2.15 + * "License"). You may not use this file except in compliance with the
2.16 + * License. You can obtain a copy of the License at
2.17 + * http://www.netbeans.org/cddl-gplv2.html
2.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.19 + * specific language governing permissions and limitations under the
2.20 + * License. When distributing the software, include this License Header
2.21 + * Notice in each file and include the License file at
2.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
2.23 + * particular file as subject to the "Classpath" exception as provided
2.24 + * by Oracle in the GPL Version 2 section of the License file that
2.25 + * accompanied this code. If applicable, add the following below the
2.26 + * License Header, with the fields enclosed by brackets [] replaced by
2.27 + * your own identifying information:
2.28 + * "Portions Copyrighted [year] [name of copyright owner]"
2.29 + *
2.30 + * Contributor(s):
2.31 + *
2.32 + * The Original Software is NetBeans. The Initial Developer of the Original
2.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
2.34 + *
2.35 + * If you wish your version of this file to be governed by only the CDDL
2.36 + * or only the GPL Version 2, indicate your decision by adding
2.37 + * "[Contributor] elects to include this software in this distribution
2.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
2.39 + * single choice of license, a recipient has the option to distribute
2.40 + * your version of this file under either the CDDL, the GPL Version 2 or
2.41 + * to extend the choice of license to its licensees as provided above.
2.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
2.43 + * Version 2 license, then the option applies only if the new code is
2.44 + * made subject to such option by the copyright holder.
2.45 + */
2.46 +
2.47 +package net.java.html.beans;
2.48 +
2.49 +import java.beans.BeanInfo;
2.50 +import java.beans.IntrospectionException;
2.51 +import java.beans.Introspector;
2.52 +import java.beans.MethodDescriptor;
2.53 +import java.beans.PropertyChangeEvent;
2.54 +import java.beans.PropertyChangeListener;
2.55 +import java.beans.PropertyDescriptor;
2.56 +import java.lang.ref.Reference;
2.57 +import java.lang.ref.WeakReference;
2.58 +import java.lang.reflect.InvocationTargetException;
2.59 +import java.lang.reflect.Method;
2.60 +import java.util.HashMap;
2.61 +import java.util.Map;
2.62 +import java.util.WeakHashMap;
2.63 +import java.util.logging.Level;
2.64 +import java.util.logging.Logger;
2.65 +import net.java.html.BrwsrCtx;
2.66 +import net.java.html.json.Function;
2.67 +import net.java.html.json.Model;
2.68 +import net.java.html.json.Models;
2.69 +import net.java.html.json.Property;
2.70 +import org.apidesign.html.json.spi.Proto;
2.71 +
2.72 +/** Plain old JavaBean objects and {@link Model JSON models} finally together.
2.73 + * In can you own already written JavaBeans, you can use methods in this
2.74 + * class to register them for use where ever the classes generated by the
2.75 + * {@link Model} annotation can be.
2.76 + * In general it is expected that one can save a lot of boilerplate code
2.77 + * by using {@link Model}, but for purposes of compatibility it may be
2.78 + * suitable to spend time to write JavaBeans and only treat them as
2.79 + * models.
2.80 + *
2.81 + * @author Jaroslav Tulach
2.82 + * @since 0.9
2.83 + */
2.84 +public final class JSONBeans {
2.85 + private static final Logger LOG = Logger.getLogger(JSONBeans.class.getName());
2.86 +
2.87 + final Html4JavaType type;
2.88 + final Object model;
2.89 + final Proto proto;
2.90 + Object raw;
2.91 +
2.92 + JSONBeans(Object model, Html4JavaType type, Proto proto) {
2.93 + this.model = model;
2.94 + this.proto = proto;
2.95 + this.type = type;
2.96 + }
2.97 +
2.98 + final void initialize(Object object, Method addPCL) {
2.99 + this.raw = Models.toRaw(model);
2.100 + if (addPCL != null) try {
2.101 + addPCL.invoke(object, new JBPCL());
2.102 + } catch (Exception ex) {
2.103 + throw toRuntime(ex, RuntimeException.class);
2.104 + }
2.105 + }
2.106 +
2.107 + /** Registers the given class as a full featured {@link Model model}.
2.108 + * It inspects the class via {@link Introspector} and uses its properties
2.109 + * as {@link Property} definitions and its {@link BeanInfo#getMethodDescriptors() methods}
2.110 + * as {@link Function} definitions. This method has to be called
2.111 + * once and then all classes if this type can be treated as
2.112 + * {@link Model instances of models}.
2.113 + *
2.114 + * @param javaBeanClass the JavaBean class
2.115 + * @throws IntrospectionException if the JavaBean introspector fails
2.116 + */
2.117 + public static void register(Class<?> javaBeanClass) throws IntrospectionException {
2.118 + BeanInfo bi = Introspector.getBeanInfo(javaBeanClass);
2.119 + Method addPCL;
2.120 + try {
2.121 + addPCL = javaBeanClass.getMethod("addPropertyChangeListener", PropertyChangeListener.class); // NOI18N
2.122 + } catch (NoSuchMethodException ex) {
2.123 + addPCL = null;
2.124 + }
2.125 + Html4JavaType html4JavaType = new Html4JavaType(javaBeanClass,
2.126 + bi.getPropertyDescriptors(),
2.127 + bi.getMethodDescriptors(),
2.128 + addPCL
2.129 + );
2.130 + }
2.131 +
2.132 + @SuppressWarnings("unchecked")
2.133 + static <E extends Throwable> E toRuntime(Throwable ex, Class<E> type) throws E {
2.134 + throw (E)ex;
2.135 + }
2.136 +
2.137 + static void clearProto() {
2.138 + Html4JavaType.protos.get(null);
2.139 + }
2.140 +
2.141 + private static final class Html4JavaType extends Proto.Type {
2.142 + private static final Map<Object,Reference<JSONBeans>> protos = new WeakHashMap<Object, Reference<JSONBeans>>();
2.143 + private final PropertyDescriptor[] properties;
2.144 + private final MethodDescriptor[] methods;
2.145 + private final Method addPCL;
2.146 + private final Class<?> javaBeanClass;
2.147 +
2.148 + Html4JavaType(
2.149 + Class<?> javaBeanClass,
2.150 + PropertyDescriptor[] pd,
2.151 + MethodDescriptor[] md,
2.152 + Method addPCL
2.153 + ) {
2.154 + super(javaBeanClass, javaBeanClass, pd.length, md.length);
2.155 + this.javaBeanClass = javaBeanClass;
2.156 + this.properties = pd;
2.157 + this.methods = md;
2.158 + for (int i = 0; i < pd.length; i++) {
2.159 + registerProperty(pd[i].getName(), i, pd[i].getWriteMethod() == null);
2.160 + }
2.161 + for (int i = 0; i < md.length; i++) {
2.162 + registerFunction(md[i].getName(), i);
2.163 + }
2.164 + this.addPCL = addPCL;
2.165 + }
2.166 +
2.167 + @Override
2.168 + protected void setValue(Object model, int index, Object value) {
2.169 + try {
2.170 + try {
2.171 + final Method m = properties[index].getWriteMethod();
2.172 + value = extractValue(toBoxed(m.getParameterTypes()[0]), value);
2.173 + m.invoke(model, value);
2.174 + } catch (InvocationTargetException ex) {
2.175 + throw ex.getCause();
2.176 + }
2.177 + } catch (Throwable t) {
2.178 + throw toRuntime(t, RuntimeException.class);
2.179 + }
2.180 + }
2.181 +
2.182 + @Override
2.183 + protected Object getValue(Object model, int index) {
2.184 + try {
2.185 + Object ret = properties[index].getReadMethod().invoke(model);
2.186 + if (ret instanceof Object[]) {
2.187 + Object[] arr = new Object[((Object[])ret).length];
2.188 + for (int i = 0; i < arr.length; i++) {
2.189 + Object ith = ((Object[])ret)[i];
2.190 + if (ith != null) {
2.191 + arr[i] = Models.toRaw(ith);
2.192 + }
2.193 + }
2.194 + return arr;
2.195 + }
2.196 + return ret;
2.197 + } catch (Exception ex) {
2.198 + throw toRuntime(ex, RuntimeException.class);
2.199 + }
2.200 + }
2.201 +
2.202 + @Override
2.203 + protected void call(Object model, int index, Object data, Object event) throws Exception {
2.204 + Method m = methods[index].getMethod();
2.205 + final Class<?>[] types = m.getParameterTypes();
2.206 + Object[] args = new Object[types.length];
2.207 + if (args.length > 0) {
2.208 + args[0] = extractValue(types[0], data);
2.209 + }
2.210 + if (args.length > 1) {
2.211 + args[1] = extractValue(types[1], event);
2.212 + }
2.213 + m.invoke(model, args);
2.214 + }
2.215 +
2.216 + @Override
2.217 + protected Object cloneTo(Object model, BrwsrCtx ctx) {
2.218 + try {
2.219 + Object clone = model.getClass().newInstance();
2.220 + for (int i = 0; i < properties.length; i++) {
2.221 + final Method write = properties[i].getWriteMethod();
2.222 + if (write == null) {
2.223 + continue;
2.224 + }
2.225 + Object value = properties[i].getReadMethod().invoke(model);
2.226 + write.invoke(clone, value);
2.227 + }
2.228 + findProto(clone, this, ctx);
2.229 + return clone;
2.230 + } catch (Exception ex) {
2.231 + throw toRuntime(ex, RuntimeException.class);
2.232 + }
2.233 + }
2.234 +
2.235 + @Override
2.236 + protected Object read(BrwsrCtx c, Object json) {
2.237 + try {
2.238 + Object bean = javaBeanClass.newInstance();
2.239 + Proto proto = findProto(bean, this, c);
2.240 +
2.241 + String[] names = new String[properties.length];
2.242 + for (int i = 0; i < names.length; i++) {
2.243 + if (properties[i].getWriteMethod() != null) {
2.244 + names[i] = properties[i].getName();
2.245 + }
2.246 + }
2.247 + Object[] values = new Object[properties.length];
2.248 + proto.extract(json, names, values);
2.249 + for (int i = 0; i < names.length; i++) {
2.250 + if (names[i] != null && values[i] != null) {
2.251 + try {
2.252 + properties[i].getWriteMethod().invoke(bean, values[i]);
2.253 + } catch (IllegalArgumentException ex) {
2.254 + LOG.log(Level.SEVERE, "Cannot set property " + names[i] + " of " + javaBeanClass.getName(), ex);
2.255 + } catch (InvocationTargetException ex) {
2.256 + LOG.log(Level.SEVERE, "Cannot set property " + names[i] + " of " + javaBeanClass.getName(), ex);
2.257 + }
2.258 + }
2.259 + }
2.260 + return bean;
2.261 + } catch (InstantiationException ex) {
2.262 + throw toRuntime(ex, RuntimeException.class);
2.263 + } catch (IllegalAccessException ex) {
2.264 + throw toRuntime(ex, RuntimeException.class);
2.265 + }
2.266 + }
2.267 +
2.268 + @Override
2.269 + protected void onChange(Object model, int index) {
2.270 + // no automatic dependencies between properties
2.271 + }
2.272 +
2.273 + @Override
2.274 + protected Proto protoFor(Object object) {
2.275 + return findProto(object, this, null);
2.276 + }
2.277 +
2.278 + private static Proto findProto(Object object, Html4JavaType type, BrwsrCtx ctx) {
2.279 + Reference<JSONBeans> ref = protos.get(object);
2.280 + JSONBeans jb = ref == null ? null : ref.get();
2.281 + if (jb != null) {
2.282 + return jb.proto;
2.283 + }
2.284 + if (ctx == null) {
2.285 + ctx = BrwsrCtx.findDefault(object.getClass());
2.286 + }
2.287 + Proto p = type.createProto(object, ctx);
2.288 + jb = new JSONBeans(object, type, p);
2.289 + final Reference<JSONBeans> br = new WeakReference<JSONBeans>(jb);
2.290 + protos.put(object, br);
2.291 + jb.initialize(object, type.addPCL);
2.292 + return p;
2.293 + }
2.294 + private static Class<?> toBoxed(Class<?> c) {
2.295 + if (!c.isPrimitive()) {
2.296 + return c;
2.297 + }
2.298 + if (c == Boolean.TYPE) {
2.299 + return Boolean.class;
2.300 + }
2.301 + if (c == Byte.TYPE) {
2.302 + return Byte.class;
2.303 + }
2.304 + if (c == Short.TYPE) {
2.305 + return Short.class;
2.306 + }
2.307 + if (c == Integer.TYPE) {
2.308 + return Integer.class;
2.309 + }
2.310 + if (c == Long.TYPE) {
2.311 + return Long.class;
2.312 + }
2.313 + if (c == Float.TYPE) {
2.314 + return Float.class;
2.315 + }
2.316 + if (c == Double.TYPE) {
2.317 + return Double.class;
2.318 + }
2.319 + if (c == Character.TYPE) {
2.320 + return Character.class;
2.321 + }
2.322 + return c;
2.323 + }
2.324 + }
2.325 +
2.326 + private final class JBPCL implements PropertyChangeListener {
2.327 + @Override
2.328 + public void propertyChange(PropertyChangeEvent evt) {
2.329 + String n = evt.getPropertyName();
2.330 + JSONBeans jb = JSONBeans.this;
2.331 + if (jb == null) {
2.332 + return;
2.333 + }
2.334 + Proto proto = jb.proto;
2.335 + Html4JavaType type = jb.type;
2.336 + for (int i = 0; i < type.properties.length; i++) {
2.337 + PropertyDescriptor p = type.properties[i];
2.338 + if (n == null || n.equals(p.getName())) {
2.339 + proto.valueHasMutated(n, evt.getOldValue(), evt.getNewValue());
2.340 + }
2.341 + }
2.342 + }
2.343 + }
2.344 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/json-beans/src/test/java/net/java/html/beans/MapModelGCTest.java Fri Feb 12 08:40:12 2016 +0100
3.3 @@ -0,0 +1,418 @@
3.4 +/**
3.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3.6 + *
3.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
3.8 + *
3.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
3.10 + * Other names may be trademarks of their respective owners.
3.11 + *
3.12 + * The contents of this file are subject to the terms of either the GNU
3.13 + * General Public License Version 2 only ("GPL") or the Common
3.14 + * Development and Distribution License("CDDL") (collectively, the
3.15 + * "License"). You may not use this file except in compliance with the
3.16 + * License. You can obtain a copy of the License at
3.17 + * http://www.netbeans.org/cddl-gplv2.html
3.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
3.19 + * specific language governing permissions and limitations under the
3.20 + * License. When distributing the software, include this License Header
3.21 + * Notice in each file and include the License file at
3.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
3.23 + * particular file as subject to the "Classpath" exception as provided
3.24 + * by Oracle in the GPL Version 2 section of the License file that
3.25 + * accompanied this code. If applicable, add the following below the
3.26 + * License Header, with the fields enclosed by brackets [] replaced by
3.27 + * your own identifying information:
3.28 + * "Portions Copyrighted [year] [name of copyright owner]"
3.29 + *
3.30 + * Contributor(s):
3.31 + *
3.32 + * The Original Software is NetBeans. The Initial Developer of the Original
3.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
3.34 + *
3.35 + * If you wish your version of this file to be governed by only the CDDL
3.36 + * or only the GPL Version 2, indicate your decision by adding
3.37 + * "[Contributor] elects to include this software in this distribution
3.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
3.39 + * single choice of license, a recipient has the option to distribute
3.40 + * your version of this file under either the CDDL, the GPL Version 2 or
3.41 + * to extend the choice of license to its licensees as provided above.
3.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
3.43 + * Version 2 license, then the option applies only if the new code is
3.44 + * made subject to such option by the copyright holder.
3.45 + */
3.46 +package net.java.html.json;
3.47 +
3.48 +import net.java.html.BrwsrCtx;
3.49 +import java.io.IOException;
3.50 +import java.io.InputStream;
3.51 +import java.lang.reflect.InvocationTargetException;
3.52 +import java.util.HashMap;
3.53 +import java.util.Iterator;
3.54 +import java.util.ListIterator;
3.55 +import java.util.Map;
3.56 +import org.netbeans.html.context.spi.Contexts;
3.57 +import org.netbeans.html.json.spi.FunctionBinding;
3.58 +import org.netbeans.html.json.spi.JSONCall;
3.59 +import org.netbeans.html.json.spi.PropertyBinding;
3.60 +import org.netbeans.html.json.spi.Technology;
3.61 +import org.netbeans.html.json.spi.Transfer;
3.62 +import org.testng.annotations.BeforeMethod;
3.63 +import org.testng.annotations.Test;
3.64 +import static org.testng.Assert.*;
3.65 +
3.66 +/**
3.67 + *
3.68 + * @author Jaroslav Tulach
3.69 + */
3.70 +public class MapModelTest {
3.71 + private MapTechnology t;
3.72 + private BrwsrCtx c;
3.73 +
3.74 + @BeforeMethod public void initTechnology() {
3.75 + t = new MapTechnology();
3.76 + c = Contexts.newBuilder().register(Technology.class, t, 1).
3.77 + register(Transfer.class, t, 1).build();
3.78 + }
3.79 +
3.80 + @Test public void isThereNoApplyBinding() throws Exception {
3.81 + try {
3.82 + Person.class.getMethod("applyBindings");
3.83 + } catch (NoSuchMethodException ex) {
3.84 + // OK
3.85 + return;
3.86 + }
3.87 + fail("There should be no applyBindings() method");
3.88 + }
3.89 +
3.90 + @Test public void isThereABinding() throws Exception {
3.91 + Person p = Models.bind(new Person(), c);
3.92 + Models.applyBindings(p);
3.93 + assertNull(t.appliedId, "Applied globally");
3.94 + p.setFirstName("Jarda");
3.95 +
3.96 + Map m = (Map)Models.toRaw(p);
3.97 + Object v = m.get("firstName");
3.98 + assertNotNull(v, "Value should be in the map");
3.99 + assertEquals(v.getClass(), One.class, "It is instance of One");
3.100 + One o = (One)v;
3.101 + assertEquals(o.changes, 1, "One change so far");
3.102 + assertFalse(o.pb.isReadOnly(), "Mutable property");
3.103 +
3.104 + assertEquals(o.get(), "Jarda", "Value should be in the map");
3.105 +
3.106 + o.set("Karle");
3.107 +
3.108 + assertEquals(p.getFirstName(), "Karle", "Model value updated");
3.109 + assertEquals(o.changes, 2, "Snd change");
3.110 + }
3.111 +
3.112 + @Test public void applyLocally() throws Exception {
3.113 + Person p = Models.bind(new Person(), c);
3.114 + Models.applyBindings(p, "local");
3.115 + assertEquals(t.appliedId, "local", "Applied locally");
3.116 + }
3.117 +
3.118 + @Test public void dontNotifySameProperty() throws Exception {
3.119 + Person p = Models.bind(new Person(), c);
3.120 + p.setFirstName("Jirka");
3.121 +
3.122 + Map m = (Map)Models.toRaw(p);
3.123 + Object v = m.get("firstName");
3.124 + assertNotNull(v, "Value should be in the map");
3.125 + assertEquals(v.getClass(), One.class, "It is instance of One");
3.126 + One o = (One)v;
3.127 + assertEquals(o.changes, 0, "No change so far the only one change happened before we connected");
3.128 +
3.129 + p.setFirstName(new String("Jirka"));
3.130 + assertEquals(o.changes, 0, "No change so far, the value is the same");
3.131 +
3.132 + p.setFirstName("Jarda");
3.133 + assertFalse(o.pb.isReadOnly(), "Mutable property");
3.134 +
3.135 + assertEquals(o.get(), "Jarda", "Value should be in the map");
3.136 +
3.137 + o.set("Karle");
3.138 +
3.139 + assertEquals(p.getFirstName(), "Karle", "Model value updated");
3.140 + assertEquals(o.changes, 2, "Snd change");
3.141 + }
3.142 +
3.143 + @Test public void canSetEnumAsString() throws Exception {
3.144 + Person p = Models.bind(new Person(), c);
3.145 + p.setFirstName("Jirka");
3.146 + p.setSex(Sex.MALE);
3.147 +
3.148 + Map m = (Map)Models.toRaw(p);
3.149 + Object v = m.get("sex");
3.150 + assertNotNull(v, "Value should be in the map");
3.151 + assertEquals(v.getClass(), One.class, "It is instance of One");
3.152 + One o = (One)v;
3.153 +
3.154 + o.set("FEMALE");
3.155 +
3.156 + assertEquals(p.getSex(), Sex.FEMALE, "Changed to female");
3.157 + }
3.158 +
3.159 + @Test public void derivedProperty() throws Exception {
3.160 + Person p = Models.bind(new Person(), c);
3.161 +
3.162 + Map m = (Map)Models.toRaw(p);
3.163 + Object v = m.get("fullName");
3.164 + assertNotNull(v, "Value should be in the map");
3.165 + assertEquals(v.getClass(), One.class, "It is instance of One");
3.166 + One o = (One)v;
3.167 + assertTrue(o.pb.isReadOnly(), "Mutable property");
3.168 + }
3.169 +
3.170 + @Test public void changeSex() {
3.171 + Person p = Models.bind(new Person(), c);
3.172 + p.setFirstName("Trans");
3.173 + p.setSex(Sex.MALE);
3.174 +
3.175 + Map m = (Map)Models.toRaw(p);
3.176 + Object o = m.get("changeSex");
3.177 + assertNotNull(o, "Function registered in the model");
3.178 + assertEquals(o.getClass(), One.class);
3.179 +
3.180 + One one = (One)o;
3.181 + assertNotNull(one.fb, "Function binding specified");
3.182 +
3.183 + one.fb.call(null, null);
3.184 +
3.185 + assertEquals(p.getSex(), Sex.FEMALE, "Changed");
3.186 + }
3.187 +
3.188 + @Test public void setSex() {
3.189 + Person p = Models.bind(new Person(), c);
3.190 + p.setFirstName("Trans");
3.191 +
3.192 + Map m = (Map)Models.toRaw(p);
3.193 + Object o = m.get("changeSex");
3.194 + assertNotNull(o, "Function registered in the model");
3.195 + assertEquals(o.getClass(), One.class);
3.196 +
3.197 + One one = (One)o;
3.198 + assertNotNull(one.fb, "Function binding specified");
3.199 +
3.200 + one.fb.call("FEMALE", new Object());
3.201 +
3.202 + assertEquals(p.getSex(), Sex.FEMALE, "Changed");
3.203 + }
3.204 +
3.205 + @Test public void changeComputedProperty() {
3.206 + Modelik p = Models.bind(new Modelik(), c);
3.207 + p.setValue(5);
3.208 +
3.209 + Map m = (Map)Models.toRaw(p);
3.210 + Object o = m.get("powerValue");
3.211 + assertNotNull(o, "Value is there");
3.212 + assertEquals(o.getClass(), One.class);
3.213 +
3.214 + One one = (One)o;
3.215 + assertNotNull(one.pb, "Prop binding specified");
3.216 +
3.217 + assertEquals(one.pb.getValue(), 25, "Power of 5");
3.218 +
3.219 + one.pb.setValue(16);
3.220 + assertEquals(p.getValue(), 4, "Square root of 16");
3.221 + }
3.222 +
3.223 + @Test public void removeViaIterator() {
3.224 + People p = Models.bind(new People(), c);
3.225 + p.getNicknames().add("One");
3.226 + p.getNicknames().add("Two");
3.227 + p.getNicknames().add("Three");
3.228 +
3.229 + Map m = (Map)Models.toRaw(p);
3.230 + Object o = m.get("nicknames");
3.231 + assertNotNull(o, "List registered in the model");
3.232 + assertEquals(o.getClass(), One.class);
3.233 + One one = (One)o;
3.234 +
3.235 +
3.236 + assertEquals(one.changes, 0, "No change");
3.237 +
3.238 + Iterator<String> it = p.getNicknames().iterator();
3.239 + assertEquals(it.next(), "One");
3.240 + assertEquals(it.next(), "Two");
3.241 + it.remove();
3.242 + assertEquals(it.next(), "Three");
3.243 + assertFalse(it.hasNext());
3.244 +
3.245 +
3.246 + assertEquals(one.changes, 1, "One change");
3.247 + }
3.248 +
3.249 + @Test public void removeViaListIterator() {
3.250 + People p = Models.bind(new People(), c);
3.251 + p.getNicknames().add("One");
3.252 + p.getNicknames().add("Two");
3.253 + p.getNicknames().add("Three");
3.254 +
3.255 + Map m = (Map)Models.toRaw(p);
3.256 + Object o = m.get("nicknames");
3.257 + assertNotNull(o, "List registered in the model");
3.258 + assertEquals(o.getClass(), One.class);
3.259 + One one = (One)o;
3.260 +
3.261 +
3.262 + assertEquals(one.changes, 0, "No change");
3.263 +
3.264 + ListIterator<String> it = p.getNicknames().listIterator(1);
3.265 + assertEquals(it.next(), "Two");
3.266 + it.remove();
3.267 + assertEquals(it.next(), "Three");
3.268 + assertFalse(it.hasNext());
3.269 +
3.270 +
3.271 + assertEquals(one.changes, 1, "One change");
3.272 +
3.273 + it.set("3");
3.274 + assertEquals(p.getNicknames().get(1), "3");
3.275 +
3.276 + assertEquals(one.changes, 2, "Snd change");
3.277 + }
3.278 +
3.279 + @Test public void functionWithParameters() {
3.280 + People p = Models.bind(new People(), c);
3.281 + p.getNicknames().add("One");
3.282 + p.getNicknames().add("Two");
3.283 + p.getNicknames().add("Three");
3.284 +
3.285 + Map m = (Map)Models.toRaw(p);
3.286 + Object o = m.get("inInnerClass");
3.287 + assertNotNull(o, "functiton is available");
3.288 + assertEquals(o.getClass(), One.class);
3.289 + One one = (One)o;
3.290 +
3.291 + Map<String,Object> obj = new HashMap<String, Object>();
3.292 + obj.put("nick", "newNick");
3.293 + obj.put("x", 42);
3.294 + obj.put("y", 7.7f);
3.295 + final Person data = new Person("a", "b", Sex.MALE);
3.296 +
3.297 + one.fb.call(data, obj);
3.298 +
3.299 + assertEquals(p.getInfo().size(), 1, "a+b is there: " + p.getInfo());
3.300 + assertEquals(p.getInfo().get(0), data, "Expecting data: " + p.getInfo());
3.301 +
3.302 + assertEquals(p.getNicknames().size(), 4, "One more nickname: " + p.getNicknames());
3.303 + assertEquals(p.getNicknames().get(3), "newNick");
3.304 +
3.305 + assertEquals(p.getAge().size(), 2, "Two new values: " + p.getAge());
3.306 + assertEquals(p.getAge().get(0).intValue(), 42);
3.307 + assertEquals(p.getAge().get(1).intValue(), 7);
3.308 + }
3.309 +
3.310 + static final class One {
3.311 + int changes;
3.312 + final PropertyBinding pb;
3.313 + final FunctionBinding fb;
3.314 +
3.315 + One(Object m, PropertyBinding pb) throws NoSuchMethodException {
3.316 + this.pb = pb;
3.317 + this.fb = null;
3.318 + }
3.319 + One(Object m, FunctionBinding fb) throws NoSuchMethodException {
3.320 + this.pb = null;
3.321 + this.fb = fb;
3.322 + }
3.323 +
3.324 + Object get() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
3.325 + return pb.getValue();
3.326 + }
3.327 +
3.328 + void set(Object v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
3.329 + pb.setValue(v);
3.330 + }
3.331 + }
3.332 +
3.333 + static final class MapTechnology
3.334 + implements Technology.ApplyId<Map<String,One>>, Transfer {
3.335 + private Map<String, One> appliedData;
3.336 + private String appliedId;
3.337 +
3.338 + @Override
3.339 + public Map<String, One> wrapModel(Object model) {
3.340 + return new HashMap<String, One>();
3.341 + }
3.342 +
3.343 + @Override
3.344 + public void valueHasMutated(Map<String, One> data, String propertyName) {
3.345 + One p = data.get(propertyName);
3.346 + if (p != null) {
3.347 + p.changes++;
3.348 + }
3.349 + }
3.350 +
3.351 + @Override
3.352 + public void bind(PropertyBinding b, Object model, Map<String, One> data) {
3.353 + try {
3.354 + One o = new One(model, b);
3.355 + data.put(b.getPropertyName(), o);
3.356 + } catch (NoSuchMethodException ex) {
3.357 + throw new IllegalStateException(ex);
3.358 + }
3.359 + }
3.360 +
3.361 + @Override
3.362 + public void expose(FunctionBinding fb, Object model, Map<String, One> data) {
3.363 + try {
3.364 + data.put(fb.getFunctionName(), new One(model, fb));
3.365 + } catch (NoSuchMethodException ex) {
3.366 + throw new IllegalStateException(ex);
3.367 + }
3.368 + }
3.369 +
3.370 + @Override
3.371 + public void applyBindings(Map<String, One> data) {
3.372 + throw new UnsupportedOperationException("Never called!");
3.373 + }
3.374 +
3.375 + @Override
3.376 + public Object wrapArray(Object[] arr) {
3.377 + return arr;
3.378 + }
3.379 +
3.380 + @Override
3.381 + public void extract(Object obj, String[] props, Object[] values) {
3.382 + Map<?,?> map = obj instanceof Map ? (Map<?,?>)obj : null;
3.383 + for (int i = 0; i < Math.min(props.length, values.length); i++) {
3.384 + if (map == null) {
3.385 + values[i] = null;
3.386 + } else {
3.387 + values[i] = map.get(props[i]);
3.388 + if (values[i] instanceof One) {
3.389 + values[i] = ((One)values[i]).pb.getValue();
3.390 + }
3.391 + }
3.392 + }
3.393 + }
3.394 +
3.395 + @Override
3.396 + public void loadJSON(JSONCall call) {
3.397 + call.notifyError(new UnsupportedOperationException());
3.398 + }
3.399 +
3.400 + @Override
3.401 + public <M> M toModel(Class<M> modelClass, Object data) {
3.402 + return modelClass.cast(data);
3.403 + }
3.404 +
3.405 + @Override
3.406 + public Object toJSON(InputStream is) throws IOException {
3.407 + throw new IOException();
3.408 + }
3.409 +
3.410 + @Override
3.411 + public void runSafe(Runnable r) {
3.412 + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
3.413 + }
3.414 +
3.415 + @Override
3.416 + public void applyBindings(String id, Map<String, One> data) {
3.417 + this.appliedId = id;
3.418 + this.appliedData = data;
3.419 + }
3.420 + }
3.421 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/json-beans/src/test/java/net/java/html/beans/MapModelTest.java Fri Feb 12 08:40:12 2016 +0100
4.3 @@ -0,0 +1,418 @@
4.4 +/**
4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4.6 + *
4.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
4.8 + *
4.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
4.10 + * Other names may be trademarks of their respective owners.
4.11 + *
4.12 + * The contents of this file are subject to the terms of either the GNU
4.13 + * General Public License Version 2 only ("GPL") or the Common
4.14 + * Development and Distribution License("CDDL") (collectively, the
4.15 + * "License"). You may not use this file except in compliance with the
4.16 + * License. You can obtain a copy of the License at
4.17 + * http://www.netbeans.org/cddl-gplv2.html
4.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
4.19 + * specific language governing permissions and limitations under the
4.20 + * License. When distributing the software, include this License Header
4.21 + * Notice in each file and include the License file at
4.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
4.23 + * particular file as subject to the "Classpath" exception as provided
4.24 + * by Oracle in the GPL Version 2 section of the License file that
4.25 + * accompanied this code. If applicable, add the following below the
4.26 + * License Header, with the fields enclosed by brackets [] replaced by
4.27 + * your own identifying information:
4.28 + * "Portions Copyrighted [year] [name of copyright owner]"
4.29 + *
4.30 + * Contributor(s):
4.31 + *
4.32 + * The Original Software is NetBeans. The Initial Developer of the Original
4.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
4.34 + *
4.35 + * If you wish your version of this file to be governed by only the CDDL
4.36 + * or only the GPL Version 2, indicate your decision by adding
4.37 + * "[Contributor] elects to include this software in this distribution
4.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
4.39 + * single choice of license, a recipient has the option to distribute
4.40 + * your version of this file under either the CDDL, the GPL Version 2 or
4.41 + * to extend the choice of license to its licensees as provided above.
4.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
4.43 + * Version 2 license, then the option applies only if the new code is
4.44 + * made subject to such option by the copyright holder.
4.45 + */
4.46 +package net.java.html.json;
4.47 +
4.48 +import net.java.html.BrwsrCtx;
4.49 +import java.io.IOException;
4.50 +import java.io.InputStream;
4.51 +import java.lang.reflect.InvocationTargetException;
4.52 +import java.util.HashMap;
4.53 +import java.util.Iterator;
4.54 +import java.util.ListIterator;
4.55 +import java.util.Map;
4.56 +import org.netbeans.html.context.spi.Contexts;
4.57 +import org.netbeans.html.json.spi.FunctionBinding;
4.58 +import org.netbeans.html.json.spi.JSONCall;
4.59 +import org.netbeans.html.json.spi.PropertyBinding;
4.60 +import org.netbeans.html.json.spi.Technology;
4.61 +import org.netbeans.html.json.spi.Transfer;
4.62 +import org.testng.annotations.BeforeMethod;
4.63 +import org.testng.annotations.Test;
4.64 +import static org.testng.Assert.*;
4.65 +
4.66 +/**
4.67 + *
4.68 + * @author Jaroslav Tulach
4.69 + */
4.70 +public class MapModelTest {
4.71 + private MapTechnology t;
4.72 + private BrwsrCtx c;
4.73 +
4.74 + @BeforeMethod public void initTechnology() {
4.75 + t = new MapTechnology();
4.76 + c = Contexts.newBuilder().register(Technology.class, t, 1).
4.77 + register(Transfer.class, t, 1).build();
4.78 + }
4.79 +
4.80 + @Test public void isThereNoApplyBinding() throws Exception {
4.81 + try {
4.82 + Person.class.getMethod("applyBindings");
4.83 + } catch (NoSuchMethodException ex) {
4.84 + // OK
4.85 + return;
4.86 + }
4.87 + fail("There should be no applyBindings() method");
4.88 + }
4.89 +
4.90 + @Test public void isThereABinding() throws Exception {
4.91 + Person p = Models.bind(new Person(), c);
4.92 + Models.applyBindings(p);
4.93 + assertNull(t.appliedId, "Applied globally");
4.94 + p.setFirstName("Jarda");
4.95 +
4.96 + Map m = (Map)Models.toRaw(p);
4.97 + Object v = m.get("firstName");
4.98 + assertNotNull(v, "Value should be in the map");
4.99 + assertEquals(v.getClass(), One.class, "It is instance of One");
4.100 + One o = (One)v;
4.101 + assertEquals(o.changes, 1, "One change so far");
4.102 + assertFalse(o.pb.isReadOnly(), "Mutable property");
4.103 +
4.104 + assertEquals(o.get(), "Jarda", "Value should be in the map");
4.105 +
4.106 + o.set("Karle");
4.107 +
4.108 + assertEquals(p.getFirstName(), "Karle", "Model value updated");
4.109 + assertEquals(o.changes, 2, "Snd change");
4.110 + }
4.111 +
4.112 + @Test public void applyLocally() throws Exception {
4.113 + Person p = Models.bind(new Person(), c);
4.114 + Models.applyBindings(p, "local");
4.115 + assertEquals(t.appliedId, "local", "Applied locally");
4.116 + }
4.117 +
4.118 + @Test public void dontNotifySameProperty() throws Exception {
4.119 + Person p = Models.bind(new Person(), c);
4.120 + p.setFirstName("Jirka");
4.121 +
4.122 + Map m = (Map)Models.toRaw(p);
4.123 + Object v = m.get("firstName");
4.124 + assertNotNull(v, "Value should be in the map");
4.125 + assertEquals(v.getClass(), One.class, "It is instance of One");
4.126 + One o = (One)v;
4.127 + assertEquals(o.changes, 0, "No change so far the only one change happened before we connected");
4.128 +
4.129 + p.setFirstName(new String("Jirka"));
4.130 + assertEquals(o.changes, 0, "No change so far, the value is the same");
4.131 +
4.132 + p.setFirstName("Jarda");
4.133 + assertFalse(o.pb.isReadOnly(), "Mutable property");
4.134 +
4.135 + assertEquals(o.get(), "Jarda", "Value should be in the map");
4.136 +
4.137 + o.set("Karle");
4.138 +
4.139 + assertEquals(p.getFirstName(), "Karle", "Model value updated");
4.140 + assertEquals(o.changes, 2, "Snd change");
4.141 + }
4.142 +
4.143 + @Test public void canSetEnumAsString() throws Exception {
4.144 + Person p = Models.bind(new Person(), c);
4.145 + p.setFirstName("Jirka");
4.146 + p.setSex(Sex.MALE);
4.147 +
4.148 + Map m = (Map)Models.toRaw(p);
4.149 + Object v = m.get("sex");
4.150 + assertNotNull(v, "Value should be in the map");
4.151 + assertEquals(v.getClass(), One.class, "It is instance of One");
4.152 + One o = (One)v;
4.153 +
4.154 + o.set("FEMALE");
4.155 +
4.156 + assertEquals(p.getSex(), Sex.FEMALE, "Changed to female");
4.157 + }
4.158 +
4.159 + @Test public void derivedProperty() throws Exception {
4.160 + Person p = Models.bind(new Person(), c);
4.161 +
4.162 + Map m = (Map)Models.toRaw(p);
4.163 + Object v = m.get("fullName");
4.164 + assertNotNull(v, "Value should be in the map");
4.165 + assertEquals(v.getClass(), One.class, "It is instance of One");
4.166 + One o = (One)v;
4.167 + assertTrue(o.pb.isReadOnly(), "Mutable property");
4.168 + }
4.169 +
4.170 + @Test public void changeSex() {
4.171 + Person p = Models.bind(new Person(), c);
4.172 + p.setFirstName("Trans");
4.173 + p.setSex(Sex.MALE);
4.174 +
4.175 + Map m = (Map)Models.toRaw(p);
4.176 + Object o = m.get("changeSex");
4.177 + assertNotNull(o, "Function registered in the model");
4.178 + assertEquals(o.getClass(), One.class);
4.179 +
4.180 + One one = (One)o;
4.181 + assertNotNull(one.fb, "Function binding specified");
4.182 +
4.183 + one.fb.call(null, null);
4.184 +
4.185 + assertEquals(p.getSex(), Sex.FEMALE, "Changed");
4.186 + }
4.187 +
4.188 + @Test public void setSex() {
4.189 + Person p = Models.bind(new Person(), c);
4.190 + p.setFirstName("Trans");
4.191 +
4.192 + Map m = (Map)Models.toRaw(p);
4.193 + Object o = m.get("changeSex");
4.194 + assertNotNull(o, "Function registered in the model");
4.195 + assertEquals(o.getClass(), One.class);
4.196 +
4.197 + One one = (One)o;
4.198 + assertNotNull(one.fb, "Function binding specified");
4.199 +
4.200 + one.fb.call("FEMALE", new Object());
4.201 +
4.202 + assertEquals(p.getSex(), Sex.FEMALE, "Changed");
4.203 + }
4.204 +
4.205 + @Test public void changeComputedProperty() {
4.206 + Modelik p = Models.bind(new Modelik(), c);
4.207 + p.setValue(5);
4.208 +
4.209 + Map m = (Map)Models.toRaw(p);
4.210 + Object o = m.get("powerValue");
4.211 + assertNotNull(o, "Value is there");
4.212 + assertEquals(o.getClass(), One.class);
4.213 +
4.214 + One one = (One)o;
4.215 + assertNotNull(one.pb, "Prop binding specified");
4.216 +
4.217 + assertEquals(one.pb.getValue(), 25, "Power of 5");
4.218 +
4.219 + one.pb.setValue(16);
4.220 + assertEquals(p.getValue(), 4, "Square root of 16");
4.221 + }
4.222 +
4.223 + @Test public void removeViaIterator() {
4.224 + People p = Models.bind(new People(), c);
4.225 + p.getNicknames().add("One");
4.226 + p.getNicknames().add("Two");
4.227 + p.getNicknames().add("Three");
4.228 +
4.229 + Map m = (Map)Models.toRaw(p);
4.230 + Object o = m.get("nicknames");
4.231 + assertNotNull(o, "List registered in the model");
4.232 + assertEquals(o.getClass(), One.class);
4.233 + One one = (One)o;
4.234 +
4.235 +
4.236 + assertEquals(one.changes, 0, "No change");
4.237 +
4.238 + Iterator<String> it = p.getNicknames().iterator();
4.239 + assertEquals(it.next(), "One");
4.240 + assertEquals(it.next(), "Two");
4.241 + it.remove();
4.242 + assertEquals(it.next(), "Three");
4.243 + assertFalse(it.hasNext());
4.244 +
4.245 +
4.246 + assertEquals(one.changes, 1, "One change");
4.247 + }
4.248 +
4.249 + @Test public void removeViaListIterator() {
4.250 + People p = Models.bind(new People(), c);
4.251 + p.getNicknames().add("One");
4.252 + p.getNicknames().add("Two");
4.253 + p.getNicknames().add("Three");
4.254 +
4.255 + Map m = (Map)Models.toRaw(p);
4.256 + Object o = m.get("nicknames");
4.257 + assertNotNull(o, "List registered in the model");
4.258 + assertEquals(o.getClass(), One.class);
4.259 + One one = (One)o;
4.260 +
4.261 +
4.262 + assertEquals(one.changes, 0, "No change");
4.263 +
4.264 + ListIterator<String> it = p.getNicknames().listIterator(1);
4.265 + assertEquals(it.next(), "Two");
4.266 + it.remove();
4.267 + assertEquals(it.next(), "Three");
4.268 + assertFalse(it.hasNext());
4.269 +
4.270 +
4.271 + assertEquals(one.changes, 1, "One change");
4.272 +
4.273 + it.set("3");
4.274 + assertEquals(p.getNicknames().get(1), "3");
4.275 +
4.276 + assertEquals(one.changes, 2, "Snd change");
4.277 + }
4.278 +
4.279 + @Test public void functionWithParameters() {
4.280 + People p = Models.bind(new People(), c);
4.281 + p.getNicknames().add("One");
4.282 + p.getNicknames().add("Two");
4.283 + p.getNicknames().add("Three");
4.284 +
4.285 + Map m = (Map)Models.toRaw(p);
4.286 + Object o = m.get("inInnerClass");
4.287 + assertNotNull(o, "functiton is available");
4.288 + assertEquals(o.getClass(), One.class);
4.289 + One one = (One)o;
4.290 +
4.291 + Map<String,Object> obj = new HashMap<String, Object>();
4.292 + obj.put("nick", "newNick");
4.293 + obj.put("x", 42);
4.294 + obj.put("y", 7.7f);
4.295 + final Person data = new Person("a", "b", Sex.MALE);
4.296 +
4.297 + one.fb.call(data, obj);
4.298 +
4.299 + assertEquals(p.getInfo().size(), 1, "a+b is there: " + p.getInfo());
4.300 + assertEquals(p.getInfo().get(0), data, "Expecting data: " + p.getInfo());
4.301 +
4.302 + assertEquals(p.getNicknames().size(), 4, "One more nickname: " + p.getNicknames());
4.303 + assertEquals(p.getNicknames().get(3), "newNick");
4.304 +
4.305 + assertEquals(p.getAge().size(), 2, "Two new values: " + p.getAge());
4.306 + assertEquals(p.getAge().get(0).intValue(), 42);
4.307 + assertEquals(p.getAge().get(1).intValue(), 7);
4.308 + }
4.309 +
4.310 + static final class One {
4.311 + int changes;
4.312 + final PropertyBinding pb;
4.313 + final FunctionBinding fb;
4.314 +
4.315 + One(Object m, PropertyBinding pb) throws NoSuchMethodException {
4.316 + this.pb = pb;
4.317 + this.fb = null;
4.318 + }
4.319 + One(Object m, FunctionBinding fb) throws NoSuchMethodException {
4.320 + this.pb = null;
4.321 + this.fb = fb;
4.322 + }
4.323 +
4.324 + Object get() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
4.325 + return pb.getValue();
4.326 + }
4.327 +
4.328 + void set(Object v) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
4.329 + pb.setValue(v);
4.330 + }
4.331 + }
4.332 +
4.333 + static final class MapTechnology
4.334 + implements Technology.ApplyId<Map<String,One>>, Transfer {
4.335 + private Map<String, One> appliedData;
4.336 + private String appliedId;
4.337 +
4.338 + @Override
4.339 + public Map<String, One> wrapModel(Object model) {
4.340 + return new HashMap<String, One>();
4.341 + }
4.342 +
4.343 + @Override
4.344 + public void valueHasMutated(Map<String, One> data, String propertyName) {
4.345 + One p = data.get(propertyName);
4.346 + if (p != null) {
4.347 + p.changes++;
4.348 + }
4.349 + }
4.350 +
4.351 + @Override
4.352 + public void bind(PropertyBinding b, Object model, Map<String, One> data) {
4.353 + try {
4.354 + One o = new One(model, b);
4.355 + data.put(b.getPropertyName(), o);
4.356 + } catch (NoSuchMethodException ex) {
4.357 + throw new IllegalStateException(ex);
4.358 + }
4.359 + }
4.360 +
4.361 + @Override
4.362 + public void expose(FunctionBinding fb, Object model, Map<String, One> data) {
4.363 + try {
4.364 + data.put(fb.getFunctionName(), new One(model, fb));
4.365 + } catch (NoSuchMethodException ex) {
4.366 + throw new IllegalStateException(ex);
4.367 + }
4.368 + }
4.369 +
4.370 + @Override
4.371 + public void applyBindings(Map<String, One> data) {
4.372 + throw new UnsupportedOperationException("Never called!");
4.373 + }
4.374 +
4.375 + @Override
4.376 + public Object wrapArray(Object[] arr) {
4.377 + return arr;
4.378 + }
4.379 +
4.380 + @Override
4.381 + public void extract(Object obj, String[] props, Object[] values) {
4.382 + Map<?,?> map = obj instanceof Map ? (Map<?,?>)obj : null;
4.383 + for (int i = 0; i < Math.min(props.length, values.length); i++) {
4.384 + if (map == null) {
4.385 + values[i] = null;
4.386 + } else {
4.387 + values[i] = map.get(props[i]);
4.388 + if (values[i] instanceof One) {
4.389 + values[i] = ((One)values[i]).pb.getValue();
4.390 + }
4.391 + }
4.392 + }
4.393 + }
4.394 +
4.395 + @Override
4.396 + public void loadJSON(JSONCall call) {
4.397 + call.notifyError(new UnsupportedOperationException());
4.398 + }
4.399 +
4.400 + @Override
4.401 + public <M> M toModel(Class<M> modelClass, Object data) {
4.402 + return modelClass.cast(data);
4.403 + }
4.404 +
4.405 + @Override
4.406 + public Object toJSON(InputStream is) throws IOException {
4.407 + throw new IOException();
4.408 + }
4.409 +
4.410 + @Override
4.411 + public void runSafe(Runnable r) {
4.412 + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
4.413 + }
4.414 +
4.415 + @Override
4.416 + public void applyBindings(String id, Map<String, One> data) {
4.417 + this.appliedId = id;
4.418 + this.appliedData = data;
4.419 + }
4.420 + }
4.421 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/json-beans/src/test/java/net/java/html/beans/People.java Fri Feb 12 08:40:12 2016 +0100
5.3 @@ -0,0 +1,78 @@
5.4 +/**
5.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5.6 + *
5.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
5.8 + *
5.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
5.10 + * Other names may be trademarks of their respective owners.
5.11 + *
5.12 + * The contents of this file are subject to the terms of either the GNU
5.13 + * General Public License Version 2 only ("GPL") or the Common
5.14 + * Development and Distribution License("CDDL") (collectively, the
5.15 + * "License"). You may not use this file except in compliance with the
5.16 + * License. You can obtain a copy of the License at
5.17 + * http://www.netbeans.org/cddl-gplv2.html
5.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
5.19 + * specific language governing permissions and limitations under the
5.20 + * License. When distributing the software, include this License Header
5.21 + * Notice in each file and include the License file at
5.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
5.23 + * particular file as subject to the "Classpath" exception as provided
5.24 + * by Oracle in the GPL Version 2 section of the License file that
5.25 + * accompanied this code. If applicable, add the following below the
5.26 + * License Header, with the fields enclosed by brackets [] replaced by
5.27 + * your own identifying information:
5.28 + * "Portions Copyrighted [year] [name of copyright owner]"
5.29 + *
5.30 + * Contributor(s):
5.31 + *
5.32 + * The Original Software is NetBeans. The Initial Developer of the Original
5.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
5.34 + *
5.35 + * If you wish your version of this file to be governed by only the CDDL
5.36 + * or only the GPL Version 2, indicate your decision by adding
5.37 + * "[Contributor] elects to include this software in this distribution
5.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
5.39 + * single choice of license, a recipient has the option to distribute
5.40 + * your version of this file under either the CDDL, the GPL Version 2 or
5.41 + * to extend the choice of license to its licensees as provided above.
5.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
5.43 + * Version 2 license, then the option applies only if the new code is
5.44 + * made subject to such option by the copyright holder.
5.45 + */
5.46 +package net.java.html.beans;
5.47 +
5.48 +import java.beans.PropertyChangeListener;
5.49 +import java.beans.PropertyChangeSupport;
5.50 +
5.51 +/**
5.52 + *
5.53 + * @author Jaroslav Tulach
5.54 + */
5.55 +public class People {
5.56 +
5.57 + private Person[] people;
5.58 +
5.59 + public static final String PROP_PEOPLE = "people";
5.60 +
5.61 + public Person[] getPeople() {
5.62 + return people;
5.63 + }
5.64 +
5.65 + public void setPeople(Person... people) {
5.66 + Person[] oldPeople = this.people;
5.67 + this.people = people;
5.68 + propertyChangeSupport.firePropertyChange(PROP_PEOPLE, oldPeople, people);
5.69 + }
5.70 +
5.71 + private transient final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
5.72 +
5.73 + public void addPropertyChangeListener(PropertyChangeListener listener) {
5.74 + propertyChangeSupport.addPropertyChangeListener(listener);
5.75 + }
5.76 +
5.77 + public void removePropertyChangeListener(PropertyChangeListener listener) {
5.78 + propertyChangeSupport.removePropertyChangeListener(listener);
5.79 + }
5.80 +
5.81 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/json-beans/src/test/java/net/java/html/beans/Person.java Fri Feb 12 08:40:12 2016 +0100
6.3 @@ -0,0 +1,142 @@
6.4 +/**
6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
6.6 + *
6.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
6.8 + *
6.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
6.10 + * Other names may be trademarks of their respective owners.
6.11 + *
6.12 + * The contents of this file are subject to the terms of either the GNU
6.13 + * General Public License Version 2 only ("GPL") or the Common
6.14 + * Development and Distribution License("CDDL") (collectively, the
6.15 + * "License"). You may not use this file except in compliance with the
6.16 + * License. You can obtain a copy of the License at
6.17 + * http://www.netbeans.org/cddl-gplv2.html
6.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
6.19 + * specific language governing permissions and limitations under the
6.20 + * License. When distributing the software, include this License Header
6.21 + * Notice in each file and include the License file at
6.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
6.23 + * particular file as subject to the "Classpath" exception as provided
6.24 + * by Oracle in the GPL Version 2 section of the License file that
6.25 + * accompanied this code. If applicable, add the following below the
6.26 + * License Header, with the fields enclosed by brackets [] replaced by
6.27 + * your own identifying information:
6.28 + * "Portions Copyrighted [year] [name of copyright owner]"
6.29 + *
6.30 + * Contributor(s):
6.31 + *
6.32 + * The Original Software is NetBeans. The Initial Developer of the Original
6.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
6.34 + *
6.35 + * If you wish your version of this file to be governed by only the CDDL
6.36 + * or only the GPL Version 2, indicate your decision by adding
6.37 + * "[Contributor] elects to include this software in this distribution
6.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
6.39 + * single choice of license, a recipient has the option to distribute
6.40 + * your version of this file under either the CDDL, the GPL Version 2 or
6.41 + * to extend the choice of license to its licensees as provided above.
6.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
6.43 + * Version 2 license, then the option applies only if the new code is
6.44 + * made subject to such option by the copyright holder.
6.45 + */
6.46 +
6.47 +package net.java.html.beans;
6.48 +
6.49 +import java.beans.PropertyChangeListener;
6.50 +import java.beans.PropertyChangeSupport;
6.51 +
6.52 +/**
6.53 + *
6.54 + * @author Jaroslav Tulach
6.55 + */
6.56 +public final class Person {
6.57 + private String firstName;
6.58 + private String lastName;
6.59 + private Sex sex;
6.60 + private boolean good;
6.61 +
6.62 + public static final String PROP_FIRSTNAME = "firstName";
6.63 + public static final String PROP_LASTNAME = "lastName";
6.64 + public static final String PROP_FULLNAME = "fullName";
6.65 + public static final String PROP_SEX = "sex";
6.66 + public static final String PROP_GOOD = "good";
6.67 +
6.68 + public Person() {
6.69 + }
6.70 +
6.71 + public Person(String firstName, String lastName, Sex sex) {
6.72 + this.firstName = firstName;
6.73 + this.lastName = lastName;
6.74 + this.sex = sex;
6.75 + }
6.76 +
6.77 + public Sex getSex() {
6.78 + return sex;
6.79 + }
6.80 +
6.81 + public void setSex(Sex sex) {
6.82 + Sex oldSex = this.sex;
6.83 + this.sex = sex;
6.84 + propertyChangeSupport.firePropertyChange(PROP_SEX, oldSex, sex);
6.85 + }
6.86 +
6.87 + public void changeSex(Sex to) {
6.88 + if (to != null) {
6.89 + setSex(to);
6.90 + return;
6.91 + }
6.92 + if (getSex() == Sex.MALE) {
6.93 + setSex(Sex.FEMALE);
6.94 + } else {
6.95 + setSex(Sex.MALE);
6.96 + }
6.97 + }
6.98 +
6.99 + public boolean isGood() {
6.100 + return good;
6.101 + }
6.102 +
6.103 + public void setGood(boolean good) {
6.104 + boolean oldGood = this.good;
6.105 + this.good = good;
6.106 + propertyChangeSupport.firePropertyChange(PROP_GOOD, oldGood, good);
6.107 + }
6.108 +
6.109 + public String getFirstName() {
6.110 + return firstName;
6.111 + }
6.112 +
6.113 + public void setFirstName(String firstName) {
6.114 + String oldFirstName = this.firstName;
6.115 + this.firstName = firstName;
6.116 + propertyChangeSupport.firePropertyChange(PROP_FIRSTNAME, oldFirstName, firstName);
6.117 + propertyChangeSupport.firePropertyChange(PROP_FULLNAME, null, null);
6.118 + }
6.119 +
6.120 + public String getLastName() {
6.121 + return lastName;
6.122 + }
6.123 +
6.124 + public String getFullName() {
6.125 + return firstName + " " + lastName;
6.126 + }
6.127 +
6.128 + public void setLastName(String lastName) {
6.129 + String oldLastName = this.lastName;
6.130 + this.lastName = lastName;
6.131 + propertyChangeSupport.firePropertyChange(PROP_LASTNAME, oldLastName, lastName);
6.132 + propertyChangeSupport.firePropertyChange(PROP_FULLNAME, null, null);
6.133 + }
6.134 +
6.135 + private transient final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
6.136 +
6.137 + public void addPropertyChangeListener(PropertyChangeListener listener) {
6.138 + propertyChangeSupport.addPropertyChangeListener(listener);
6.139 + }
6.140 +
6.141 + public void removePropertyChangeListener(PropertyChangeListener listener) {
6.142 + propertyChangeSupport.removePropertyChangeListener(listener);
6.143 + }
6.144 +
6.145 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/json-beans/src/test/java/net/java/html/beans/Sex.java Fri Feb 12 08:40:12 2016 +0100
7.3 @@ -0,0 +1,51 @@
7.4 +/**
7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
7.6 + *
7.7 + * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
7.8 + *
7.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7.10 + * Other names may be trademarks of their respective owners.
7.11 + *
7.12 + * The contents of this file are subject to the terms of either the GNU
7.13 + * General Public License Version 2 only ("GPL") or the Common
7.14 + * Development and Distribution License("CDDL") (collectively, the
7.15 + * "License"). You may not use this file except in compliance with the
7.16 + * License. You can obtain a copy of the License at
7.17 + * http://www.netbeans.org/cddl-gplv2.html
7.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
7.19 + * specific language governing permissions and limitations under the
7.20 + * License. When distributing the software, include this License Header
7.21 + * Notice in each file and include the License file at
7.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
7.23 + * particular file as subject to the "Classpath" exception as provided
7.24 + * by Oracle in the GPL Version 2 section of the License file that
7.25 + * accompanied this code. If applicable, add the following below the
7.26 + * License Header, with the fields enclosed by brackets [] replaced by
7.27 + * your own identifying information:
7.28 + * "Portions Copyrighted [year] [name of copyright owner]"
7.29 + *
7.30 + * Contributor(s):
7.31 + *
7.32 + * The Original Software is NetBeans. The Initial Developer of the Original
7.33 + * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
7.34 + *
7.35 + * If you wish your version of this file to be governed by only the CDDL
7.36 + * or only the GPL Version 2, indicate your decision by adding
7.37 + * "[Contributor] elects to include this software in this distribution
7.38 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
7.39 + * single choice of license, a recipient has the option to distribute
7.40 + * your version of this file under either the CDDL, the GPL Version 2 or
7.41 + * to extend the choice of license to its licensees as provided above.
7.42 + * However, if you add GPL Version 2 code and therefore, elected the GPL
7.43 + * Version 2 license, then the option applies only if the new code is
7.44 + * made subject to such option by the copyright holder.
7.45 + */
7.46 +package net.java.html.beans;
7.47 +
7.48 +/**
7.49 + *
7.50 + * @author Jaroslav Tulach
7.51 + */
7.52 +public enum Sex {
7.53 + MALE, FEMALE;
7.54 +}
8.1 --- a/json/src/main/java/org/netbeans/html/json/spi/Proto.java Mon Sep 21 21:19:13 2015 +0200
8.2 +++ b/json/src/main/java/org/netbeans/html/json/spi/Proto.java Fri Feb 12 08:40:12 2016 +0100
8.3 @@ -563,7 +563,7 @@
8.4 ) {
8.5 assert getClass().getName().endsWith("$Html4JavaType");
8.6 try {
8.7 - assert getClass().getDeclaringClass() == clazz;
8.8 + assert clazz == modelFor || getClass().getDeclaringClass() == clazz;
8.9 } catch (SecurityException ex) {
8.10 // OK, no check
8.11 }