1.1 --- a/json-beans/src/main/java/net/java/html/beans/JSONBeans.java Sun Aug 03 17:38:24 2014 +0200
1.2 +++ b/json-beans/src/main/java/net/java/html/beans/JSONBeans.java Sun Aug 03 18:04:06 2014 +0200
1.3 @@ -43,6 +43,17 @@
1.4
1.5 package net.java.html.beans;
1.6
1.7 +import java.beans.BeanInfo;
1.8 +import java.beans.IntrospectionException;
1.9 +import java.beans.Introspector;
1.10 +import java.beans.MethodDescriptor;
1.11 +import java.beans.PropertyDescriptor;
1.12 +import java.lang.ref.Reference;
1.13 +import java.lang.ref.WeakReference;
1.14 +import java.lang.reflect.InvocationTargetException;
1.15 +import java.lang.reflect.Method;
1.16 +import java.util.HashMap;
1.17 +import java.util.Map;
1.18 import net.java.html.BrwsrCtx;
1.19 import org.apidesign.html.json.spi.Proto;
1.20
1.21 @@ -54,23 +65,64 @@
1.22 private JSONBeans() {
1.23 }
1.24
1.25 - public static void register(Class<?> javaBeanClass) {
1.26 - Html4JavaType html4JavaType = new Html4JavaType(javaBeanClass, 3, 3);
1.27 + public static void register(Class<?> javaBeanClass) throws IntrospectionException {
1.28 + BeanInfo bi = Introspector.getBeanInfo(javaBeanClass);
1.29 + Html4JavaType html4JavaType = new Html4JavaType(javaBeanClass,
1.30 + bi.getPropertyDescriptors(),
1.31 + bi.getMethodDescriptors()
1.32 + );
1.33 }
1.34
1.35 private static final class Html4JavaType extends Proto.Type {
1.36 - Html4JavaType(Class<?> javaBeanClass, int props, int fncs) {
1.37 - super(javaBeanClass, javaBeanClass, props, fncs);
1.38 + private static Map<Object,Reference<Proto>> protos =
1.39 + new HashMap<Object, Reference<Proto>>();
1.40 + private final PropertyDescriptor[] properties;
1.41 + private final MethodDescriptor[] methods;
1.42 +
1.43 + Html4JavaType(
1.44 + Class<?> javaBeanClass,
1.45 + PropertyDescriptor[] pd,
1.46 + MethodDescriptor[] md
1.47 + ) {
1.48 + super(javaBeanClass, javaBeanClass, pd.length, md.length);
1.49 + this.properties = pd;
1.50 + this.methods = md;
1.51 + for (int i = 0; i < pd.length; i++) {
1.52 + registerProperty(pd[i].getName(), i, pd[i].getWriteMethod() == null);
1.53 + }
1.54 + for (int i = 0; i < md.length; i++) {
1.55 + registerFunction(md[i].getName(), i);
1.56 + }
1.57 }
1.58
1.59 @Override
1.60 protected void setValue(Object model, int index, Object value) {
1.61 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1.62 + try {
1.63 + try {
1.64 + properties[index].getWriteMethod().invoke(model, value);
1.65 + } catch (InvocationTargetException ex) {
1.66 + throw ex.getCause();
1.67 + }
1.68 + } catch (RuntimeException ex) {
1.69 + throw (RuntimeException)ex;
1.70 + } catch (Throwable ex) {
1.71 + throw new IllegalStateException(ex);
1.72 + }
1.73 }
1.74
1.75 @Override
1.76 protected Object getValue(Object model, int index) {
1.77 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1.78 + try {
1.79 + try {
1.80 + return properties[index].getReadMethod().invoke(model);
1.81 + } catch (InvocationTargetException ex) {
1.82 + throw ex.getCause();
1.83 + }
1.84 + } catch (RuntimeException ex) {
1.85 + throw (RuntimeException)ex;
1.86 + } catch (Throwable ex) {
1.87 + throw new IllegalStateException(ex);
1.88 + }
1.89 }
1.90
1.91 @Override
1.92 @@ -80,22 +132,53 @@
1.93
1.94 @Override
1.95 protected Object cloneTo(Object model, BrwsrCtx ctx) {
1.96 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1.97 + try {
1.98 + Object clone = model.getClass().newInstance();
1.99 + for (int i = 0; i < properties.length; i++) {
1.100 + try {
1.101 + final Method write = properties[i].getWriteMethod();
1.102 + if (write == null) {
1.103 + continue;
1.104 + }
1.105 + Object value = properties[i].getReadMethod().invoke(model);
1.106 + write.invoke(model, value);
1.107 + } catch (InvocationTargetException ex) {
1.108 + throw ex.getCause();
1.109 + }
1.110 + }
1.111 + findProto(clone, this, ctx);
1.112 + return clone;
1.113 + } catch (RuntimeException ex) {
1.114 + throw (RuntimeException) ex;
1.115 + } catch (Throwable ex) {
1.116 + throw new IllegalStateException(ex);
1.117 + }
1.118 }
1.119
1.120 @Override
1.121 protected Object read(BrwsrCtx c, Object json) {
1.122 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1.123 + throw new UnsupportedOperationException("Not supported yet.");
1.124 }
1.125
1.126 @Override
1.127 protected void onChange(Object model, int index) {
1.128 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1.129 + throw new UnsupportedOperationException("Not supported yet.");
1.130 }
1.131
1.132 @Override
1.133 protected Proto protoFor(Object object) {
1.134 - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
1.135 + return findProto(object, this, null);
1.136 + }
1.137 +
1.138 + private static Proto findProto(Object object, Html4JavaType type, BrwsrCtx ctx) {
1.139 + Reference<Proto> ref = protos.get(object);
1.140 + Proto p = ref == null ? null : ref.get();
1.141 + if (p != null || ctx == null) {
1.142 + return p;
1.143 + }
1.144 + p = type.createProto(object, ctx);
1.145 + protos.put(object, new WeakReference<Proto>(p));
1.146 + return p;
1.147 }
1.148 }
1.149 }
2.1 --- a/json-beans/src/test/java/net/java/html/beans/MapModelTest.java Sun Aug 03 17:38:24 2014 +0200
2.2 +++ b/json-beans/src/test/java/net/java/html/beans/MapModelTest.java Sun Aug 03 18:04:06 2014 +0200
2.3 @@ -42,6 +42,7 @@
2.4 */
2.5 package net.java.html.beans;
2.6
2.7 +import java.beans.IntrospectionException;
2.8 import java.io.IOException;
2.9 import java.io.InputStream;
2.10 import java.lang.reflect.InvocationTargetException;
2.11 @@ -68,7 +69,7 @@
2.12 private MapTechnology t;
2.13 private BrwsrCtx c;
2.14
2.15 - @BeforeClass public static void registerBeanAsModel() {
2.16 + @BeforeClass public static void registerBeanAsModel() throws IntrospectionException {
2.17 JSONBeans.register(Person.class);
2.18 }
2.19