1.1 --- a/json-beans/src/main/java/net/java/html/beans/JSONBeans.java Sun Aug 03 18:04:06 2014 +0200
1.2 +++ b/json-beans/src/main/java/net/java/html/beans/JSONBeans.java Sun Aug 03 18:27:17 2014 +0200
1.3 @@ -47,6 +47,8 @@
1.4 import java.beans.IntrospectionException;
1.5 import java.beans.Introspector;
1.6 import java.beans.MethodDescriptor;
1.7 +import java.beans.PropertyChangeEvent;
1.8 +import java.beans.PropertyChangeListener;
1.9 import java.beans.PropertyDescriptor;
1.10 import java.lang.ref.Reference;
1.11 import java.lang.ref.WeakReference;
1.12 @@ -54,6 +56,8 @@
1.13 import java.lang.reflect.Method;
1.14 import java.util.HashMap;
1.15 import java.util.Map;
1.16 +import java.util.logging.Level;
1.17 +import java.util.logging.Logger;
1.18 import net.java.html.BrwsrCtx;
1.19 import org.apidesign.html.json.spi.Proto;
1.20
1.21 @@ -67,9 +71,23 @@
1.22
1.23 public static void register(Class<?> javaBeanClass) throws IntrospectionException {
1.24 BeanInfo bi = Introspector.getBeanInfo(javaBeanClass);
1.25 - Html4JavaType html4JavaType = new Html4JavaType(javaBeanClass,
1.26 + Method addPCL;
1.27 + try {
1.28 + addPCL = javaBeanClass.getMethod("addPropertyChangeListener", PropertyChangeListener.class);
1.29 + } catch (NoSuchMethodException ex) {
1.30 + addPCL = null;
1.31 + }
1.32 + Method removePCL;
1.33 + try {
1.34 + removePCL = javaBeanClass.getMethod("removePropertyChangeListener", PropertyChangeListener.class);
1.35 + } catch (NoSuchMethodException ex) {
1.36 + removePCL = null;
1.37 + }
1.38 + Html4JavaType html4JavaType = new Html4JavaType(javaBeanClass,
1.39 bi.getPropertyDescriptors(),
1.40 - bi.getMethodDescriptors()
1.41 + bi.getMethodDescriptors(),
1.42 + removePCL != null ? addPCL : null,
1.43 + addPCL != null ? removePCL : null
1.44 );
1.45 }
1.46
1.47 @@ -78,11 +96,14 @@
1.48 new HashMap<Object, Reference<Proto>>();
1.49 private final PropertyDescriptor[] properties;
1.50 private final MethodDescriptor[] methods;
1.51 + private final Method addPCL;
1.52 + private final Method removePCL;
1.53
1.54 Html4JavaType(
1.55 Class<?> javaBeanClass,
1.56 PropertyDescriptor[] pd,
1.57 - MethodDescriptor[] md
1.58 + MethodDescriptor[] md,
1.59 + Method addPCL, Method removePCL
1.60 ) {
1.61 super(javaBeanClass, javaBeanClass, pd.length, md.length);
1.62 this.properties = pd;
1.63 @@ -93,6 +114,8 @@
1.64 for (int i = 0; i < md.length; i++) {
1.65 registerFunction(md[i].getName(), i);
1.66 }
1.67 + this.addPCL = addPCL;
1.68 + this.removePCL = removePCL;
1.69 }
1.70
1.71 @Override
1.72 @@ -177,8 +200,46 @@
1.73 return p;
1.74 }
1.75 p = type.createProto(object, ctx);
1.76 - protos.put(object, new WeakReference<Proto>(p));
1.77 + final BeanRef br = new BeanRef(type, p);
1.78 + protos.put(object, br);
1.79 + if (type.addPCL != null) {
1.80 + br.initialize(object, type.addPCL);
1.81 + }
1.82 return p;
1.83 }
1.84 }
1.85 +
1.86 + private static final class BeanRef
1.87 + extends WeakReference<Proto> implements PropertyChangeListener {
1.88 + private final Html4JavaType type;
1.89 +
1.90 + public BeanRef(Html4JavaType type, Proto referent) {
1.91 + super(referent);
1.92 + this.type = type;
1.93 + }
1.94 +
1.95 + @Override
1.96 + public void propertyChange(PropertyChangeEvent evt) {
1.97 + String n = evt.getPropertyName();
1.98 + Proto proto = get();
1.99 + if (proto == null) {
1.100 + return;
1.101 + }
1.102 + for (int i = 0; i < type.properties.length; i++) {
1.103 + PropertyDescriptor p = type.properties[i];
1.104 + if (n == null || n.equals(p.getName())) {
1.105 + proto.valueHasMutated(n, evt.getOldValue(), evt.getNewValue());
1.106 + }
1.107 + }
1.108 + }
1.109 +
1.110 + final void initialize(Object object, Method addPCL) {
1.111 + try {
1.112 + addPCL.invoke(object, this);
1.113 + } catch (Exception ex) {
1.114 + throw new IllegalStateException(ex);
1.115 + }
1.116 + }
1.117 +
1.118 + }
1.119 }