Line | Hits | Source |
---|---|---|
1 | /* | |
2 | Chrysalis Web Framework [http://chrysalis.sourceforge.net] | |
3 | Copyright (c) 2002, 2003, 2004, Paul Strack | |
4 | ||
5 | All rights reserved. | |
6 | ||
7 | Redistribution and use in source and binary forms, with or without | |
8 | modification, are permitted provided that the following conditions are met: | |
9 | ||
10 | 1. Redistributions of source code must retain the above copyright notice, this | |
11 | list of conditions and the following disclaimer. | |
12 | ||
13 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
14 | this list of conditions and the following disclaimer in the documentation | |
15 | and/or other materials provided with the distribution. | |
16 | ||
17 | 3. Neither the name of the copyright holder nor the names of its contributors | |
18 | may be used to endorse or promote products derived from this software without | |
19 | specific prior written permission. | |
20 | ||
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | |
32 | ||
33 | package org.chwf.filter; | |
34 | ||
35 | import java.beans.PropertyChangeListener; | |
36 | import java.beans.PropertyChangeSupport; | |
37 | import java.util.Map; | |
38 | ||
39 | import org.chwf.converter.ConversionException; | |
40 | ||
41 | /** | |
42 | * The <code>BeanWrapper</code> class is a stateful business object | |
43 | * wrapper that manages string-to-object value conversions and property | |
44 | * change events for a single business object. It simplifies | |
45 | * <code>BeanFilter</code> methods by eliminating the object parameter, | |
46 | * but it is not thread-safe. The <code>BeanWrapper</code> is | |
47 | * appropriate for non-multi-threaded environments like Java GUIs: | |
48 | * | |
49 | * <pre> | |
50 | * BeanWrapper wrapper = new BeanWrapper(account); | |
51 | * wrapper.set("name", "John Smith"); | |
52 | * // account.setName("John Smith"); | |
53 | * wrapper.set("balance", "1234.56"); | |
54 | * // account.setBalance(1234.56); | |
55 | * wrapper.set("startDate", "10/11/2001"); | |
56 | * // account.setStartDate(<<i>10/11/2001</i>>); | |
57 | * wrapper.invoke("save"); | |
58 | * // account.save();</pre> | |
59 | * | |
60 | * The <code>BeanWrapper</code> class also allows registration of | |
61 | * <code>PropertyChangeListener</code> objects to handle | |
62 | * <code>PropertyChangeEvent</code>s. This means that the business | |
63 | * objects themselves do not need to be encumbered with such GUI | |
64 | * specific code. These property change events are only generated | |
65 | * when the property is changed through the <code>BeanWrapper</code>, | |
66 | * using its <code>set()</code> and <code>setAll()</code> methods. | |
67 | * | |
68 | * <pre> | |
69 | * BeanWrapper wrapper = new BeanWrapper(account); | |
70 | * PropertyChangeListener bcl = new BalanceChangeListener(); | |
71 | * wrapper.addPropertyChangeListener("balance", bcl); | |
72 | * // listener is notified when balance is changed via the wrapper</pre> | |
73 | * | |
74 | * @author <a href="mailto:pfstrack@users.sourceforge.net">Paul Strack</a> | |
75 | */ | |
76 | public class BeanWrapper { | |
77 | ||
78 | /** The bean filter. */ | |
79 | private final BeanFilter filter; | |
80 | ||
81 | /** The wrapped object. */ | |
82 | private final Object object; | |
83 | ||
84 | /** For property changed events. */ | |
85 | private final PropertyChangeSupport pcs; | |
86 | ||
87 | /** | |
88 | * Wraps the given object in a <code>BeanWrapper</code>. <p> | |
89 | * | |
90 | * @param object The target object. | |
91 | * @throws InitializationException If the filter cannot be initialized. | |
92 | */ | |
93 | 10 | public BeanWrapper(Object object) throws InitializationException { |
94 | 10 | this.object = object; |
95 | 10 | this.filter = BeanFilter.findFilter(object); |
96 | 10 | this.pcs = new PropertyChangeSupport(object); |
97 | 10 | } |
98 | ||
99 | /** | |
100 | * Retrieves the underlying object.<p> | |
101 | * | |
102 | * @return The original object. | |
103 | */ | |
104 | public Object getObject() { | |
105 | 1 | return this.object; |
106 | } | |
107 | ||
108 | /** | |
109 | * Get the specified property of the wrapped object, as a string.<p> | |
110 | * | |
111 | * @param property The property name. | |
112 | * @return The property value. | |
113 | * @throws FilterException For read failure. | |
114 | */ | |
115 | public String get(String property) throws FilterException { | |
116 | 17 | return filter.get(object, property); |
117 | } | |
118 | ||
119 | /** | |
120 | * Set the specified property of the wrapped object, using a string.<p> | |
121 | * | |
122 | * @param property The property name. | |
123 | * @param value The property value. | |
124 | * @throws ConversionException If the value cannot be converted to | |
125 | * the correct type. | |
126 | * @throws FilterException For write failure. | |
127 | */ | |
128 | public void set(String property, String value) | |
129 | throws ConversionException, FilterException { | |
130 | 13 | String oldValue = null; |
131 | try { | |
132 | 13 | oldValue = get(property); |
133 | 12 | } catch (PropertyNotReadableException ex) { |
134 | // Cannot determine old value | |
135 | 1 | oldValue = null; |
136 | } | |
137 | 13 | filter.set(object, property, value); |
138 | 13 | pcs.firePropertyChange(property, oldValue, value); |
139 | 13 | } |
140 | ||
141 | /** | |
142 | * Set all properties of the wrapped object using a map of name/value pairs. | |
143 | * Note that if an exception is thrown, it is possible that the object has | |
144 | * been partially updated, with some property values updated and others | |
145 | * unchanged. Only writeable properties are updated.<p> | |
146 | * | |
147 | * @param properties A map of property values keyed by property name. | |
148 | * @throws ConversionException If a value cannot be converted to | |
149 | * the correct type. | |
150 | * @throws OperationException One of the underlying set operations | |
151 | * throws an exception. | |
152 | */ | |
153 | public void setAll(Map properties) | |
154 | throws ConversionException, OperationException { | |
155 | 1 | PropertyFilter[] filters = filter.getPropertyFilters(); |
156 | 9 | for (int i = 0; i < filters.length; i++) { |
157 | 8 | String property = filters[i].getName(); |
158 | 8 | Object value = properties.get(property); |
159 | 8 | if ((value != null) && filters[i].isWriteable()) { |
160 | 5 | set(property, value.toString()); |
161 | } | |
162 | } | |
163 | 1 | } |
164 | ||
165 | /** | |
166 | * Add a PropertyChangeListener to the listener list. The listener is | |
167 | * registered for all properties.<p> | |
168 | * | |
169 | * @param listener The PropertyChangeListener to be added. | |
170 | */ | |
171 | public void addPropertyChangeListener(PropertyChangeListener listener) { | |
172 | 2 | pcs.addPropertyChangeListener(listener); |
173 | 2 | } |
174 | ||
175 | /** | |
176 | * Add a PropertyChangeListener for a specific property. The listener will | |
177 | * be invoked only when that property is changed.<p> | |
178 | * | |
179 | * @param propertyName The name of the property to listen for. | |
180 | * @param listener The PropertyChangeListener to be added. | |
181 | */ | |
182 | public void addPropertyChangeListener( | |
183 | String propertyName, | |
184 | PropertyChangeListener listener) { | |
185 | 2 | pcs.addPropertyChangeListener(propertyName, listener); |
186 | 2 | } |
187 | ||
188 | /** | |
189 | * Remove a PropertyChangeListener from the listener list. This removes a | |
190 | * PropertyChangeListener that was registered for all properties.<p> | |
191 | * | |
192 | * @param listener The PropertyChangeListener to be removed. | |
193 | */ | |
194 | public void removePropertyChangeListener(PropertyChangeListener listener) { | |
195 | 1 | pcs.removePropertyChangeListener(listener); |
196 | 1 | } |
197 | ||
198 | /** | |
199 | * Remove a PropertyChangeListener for a specific property.<p> | |
200 | * | |
201 | * @param propertyName The name of the property that was listened for. | |
202 | * @param listener The PropertyChangeListener to be removed. | |
203 | */ | |
204 | public void removePropertyChangeListener( | |
205 | String propertyName, | |
206 | PropertyChangeListener listener) { | |
207 | 1 | pcs.removePropertyChangeListener(propertyName, listener); |
208 | 1 | } |
209 | } |
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |