| 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. |