comparison org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableValue.d @ 95:6208d4f6a277

Added trees for databinding.beans and observable
author Frank Benoit <benoit@tionex.de>
date Tue, 21 Apr 2009 10:55:51 +0200
parents
children b74ac5dfcc06
comparison
equal deleted inserted replaced
94:1d37a7813832 95:6208d4f6a277
1 /*******************************************************************************
2 * Copyright (c) 2005, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Brad Reynolds - bug 164653
11 * Brad Reynolds - bug 164134, 171616
12 *******************************************************************************/
13 package org.eclipse.core.internal.databinding.beans;
14
15 import java.beans.PropertyChangeListener;
16 import java.beans.PropertyDescriptor;
17 import java.lang.reflect.InvocationTargetException;
18 import java.lang.reflect.Method;
19
20 import org.eclipse.core.databinding.BindingException;
21 import org.eclipse.core.databinding.beans.BeansObservables;
22 import org.eclipse.core.databinding.beans.IBeanObservable;
23 import org.eclipse.core.databinding.observable.Diffs;
24 import org.eclipse.core.databinding.observable.Realm;
25 import org.eclipse.core.databinding.observable.value.AbstractObservableValue;
26 import org.eclipse.core.databinding.observable.value.ValueDiff;
27 import org.eclipse.core.databinding.util.Policy;
28 import org.eclipse.core.internal.databinding.Util;
29 import org.eclipse.core.runtime.IStatus;
30 import org.eclipse.core.runtime.Status;
31
32 /**
33 * @since 1.0
34 *
35 */
36 public class JavaBeanObservableValue : AbstractObservableValue , IBeanObservable {
37 private final Object object;
38 private bool updating = false;
39
40 private final PropertyDescriptor propertyDescriptor;
41 private ListenerSupport listenerSupport;
42
43 private bool attachListeners;
44
45 /**
46 * @param realm
47 * @param object
48 * @param descriptor
49 */
50 public this(Realm realm, Object object,
51 PropertyDescriptor descriptor) {
52 this(realm, object, descriptor, true);
53 }
54
55 /**
56 * @param realm
57 * @param object
58 * @param descriptor
59 * @param attachListeners
60 */
61 public this(Realm realm, Object object,
62 PropertyDescriptor descriptor, bool attachListeners) {
63 super(realm);
64 this.object = object;
65 this.propertyDescriptor = descriptor;
66 this.attachListeners = attachListeners;
67 }
68
69 protected void firstListenerAdded() {
70 if (!attachListeners) {
71 return;
72 }
73
74 PropertyChangeListener listener = new class() PropertyChangeListener {
75 public void propertyChange(java.beans.PropertyChangeEvent event) {
76 if (!updating) {
77 final ValueDiff diff = Diffs.createValueDiff(event.getOldValue(),
78 event.getNewValue());
79 getRealm().exec(new class() Runnable {
80 public void run() {
81 fireValueChange(diff);
82 }});
83 }
84 }
85 };
86
87 if (listenerSupport is null) {
88 listenerSupport = new ListenerSupport(listener, propertyDescriptor.getName());
89 }
90
91 listenerSupport.hookListener(object);
92 }
93
94 public void doSetValue(Object value) {
95 updating = true;
96 try {
97 Object oldValue = doGetValue();
98
99 if (Util.equals(oldValue, value)) {
100 return;
101 }
102
103 Method writeMethod = propertyDescriptor.getWriteMethod();
104 if (!writeMethod.isAccessible()) {
105 writeMethod.setAccessible(true);
106 }
107 writeMethod.invoke(object, new Object[] { value });
108 fireValueChange(Diffs.createValueDiff(oldValue, doGetValue()));
109 } catch (InvocationTargetException e) {
110 /*
111 * InvocationTargetException wraps any exception thrown by the
112 * invoked method.
113 */
114 throw new RuntimeException(e.getCause());
115 } catch (Exception e) {
116 if cast(BeansObservables.DEBUG) {
117 Policy
118 .getLog()
119 .log(
120 new Status(
121 IStatus.WARNING,
122 Policy.JFACE_DATABINDING,
123 IStatus.OK,
124 "Could not change value of " + object + "." + propertyDescriptor.getName(), e)); //$NON-NLS-1$ //$NON-NLS-2$
125 }
126 } finally {
127 updating = false;
128 }
129 }
130
131 public Object doGetValue() {
132 try {
133 Method readMethod = propertyDescriptor.getReadMethod();
134 if (readMethod is null) {
135 throw new BindingException(propertyDescriptor.getName()
136 + " property does not have a read method."); //$NON-NLS-1$
137 }
138 if (!readMethod.isAccessible()) {
139 readMethod.setAccessible(true);
140 }
141 return readMethod.invoke(object, null);
142 } catch (InvocationTargetException e) {
143 /*
144 * InvocationTargetException wraps any exception thrown by the
145 * invoked method.
146 */
147 throw new RuntimeException(e.getCause());
148 } catch (Exception e) {
149 if cast(BeansObservables.DEBUG) {
150 Policy
151 .getLog()
152 .log(
153 new Status(
154 IStatus.WARNING,
155 Policy.JFACE_DATABINDING,
156 IStatus.OK,
157 "Could not read value of " + object + "." + propertyDescriptor.getName(), e)); //$NON-NLS-1$ //$NON-NLS-2$
158 }
159 return null;
160 }
161 }
162
163 protected void lastListenerRemoved() {
164 unhookListener();
165 }
166
167 private void unhookListener() {
168 if (listenerSupport !is null) {
169 listenerSupport.dispose();
170 listenerSupport = null;
171 }
172 }
173
174 public Object getValueType() {
175 return propertyDescriptor.getPropertyType();
176 }
177
178 public Object getObserved() {
179 return object;
180 }
181
182 public PropertyDescriptor getPropertyDescriptor() {
183 return propertyDescriptor;
184 }
185
186 public synchronized void dispose() {
187 unhookListener();
188 super.dispose();
189 }
190 }