Coverage details for org.chwf.filter.PropertyFilter

LineHitsSource
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.PropertyDescriptor;
36 import java.lang.reflect.InvocationTargetException;
37 import java.lang.reflect.Method;
38 import java.util.HashMap;
39 import java.util.Iterator;
40 import java.util.Locale;
41 import java.util.Map;
42  
43 import org.chwf.config.Config;
44 import org.chwf.config.ConfigFactory;
45 import org.chwf.config.PolymorphicConfig;
46 import org.chwf.converter.ConversionException;
47 import org.chwf.converter.Converter;
48  
49 /**
50  * An abstract superclass of property filters.
51  *
52  * @author <a href="mailto:pfstrack@users.sourceforge.net">Paul Strack</a>
53  */
54 public abstract class PropertyFilter {
55  
56   /** The property name. */
57   private final String name;
58  
59   /** The property type. */
60   private final Class type;
61  
62   /** The bean class. */
63   private final Class beanClass;
64  
65   /** Property attributes. */
66104  private final Map attributes = new HashMap();
67  
68   /**
69    * The validator that should be used; if <code>null</code>, no validation
70    * should be performed.
71    */
72   private final Validator validator;
73  
74   /**
75    * Constructor.<p>
76    *
77    * @param beanClass The bean class.
78    * @param name The property name.
79    * @param type The property type.
80    * @throws InitializationException If filter initialization fails.
81    */
82   public PropertyFilter(Class beanClass, String name, Class type)
83104    throws InitializationException {
84104    this.name = name;
85104    this.beanClass = beanClass;
86104    this.type = type;
87104    Config config = ConfigFactory.getConfig(beanClass);
88104    if (config.getBoolean("external-validation", false)) {
893      this.validator = Validator.findValidator(beanClass);
90     } else {
91101      this.validator = null;
92     }
93104  }
94  
95   /**
96    * The bean class for the filter.<p>
97    *
98    * @return The bean class for the filter.
99    */
100   public Class getBeanClass() {
101194    return beanClass;
102   }
103  
104   /**
105    * Get the specified property of the target object, as a string.<p>
106    *
107    * @param object The object whose property is being retrieved.
108    * @return The property value.
109    * @throws FilterException For read failure.
110    */
111   public abstract String get(Object object) throws FilterException;
112  
113   /**
114    * Get the specified property of the target object, as an object.<p>
115    *
116    * @param object The object whose property is being retrieved.
117    * @return The property value.
118    * @throws FilterException For read failure.
119    */
120   public abstract Object getPropertyAsObject(Object object)
121     throws FilterException;
122  
123   /**
124    * Set the specified property of the target object, using a string.<p>
125    *
126    * @param object The object whose property is being updated.
127    * @param value The new property value.
128    * @throws ConversionException If the value cannot be converted to
129    * the correct type.
130    * @throws FilterException For write failure.
131    */
132   public abstract void set(Object object, String value)
133     throws ConversionException, FilterException;
134  
135   /**
136    * Get the property name.<p>
137    *
138    * @return The property name.
139    */
140   public String getName() {
141347    return this.name;
142   }
143  
144   /**
145    * Get the property's Java type.<p>
146    *
147    * @return The property's Java type.
148    */
149   public Class getType() {
150335    return this.type;
151   }
152  
153   /**
154    * Get the named attribute value.<p>
155    *
156    * @param name The attribute name.
157    * @return The attribute value.
158    */
159   public Object getAttribute(String name) {
160341    return this.attributes.get(name);
161   }
162  
163   /**
164    * Get the localized value of the named attribute.<p>
165    *
166    * @param name The attribute name.
167    * @param locale The locale.
168    * @return The attribute value.
169    */
170   public String getLocalizedAttribute(String name, Locale locale) {
17130    String defaultValue = Converter.convert(this.attributes.get(name));
17230    String key = this.name + "." + name;
17330    Config config = PolymorphicConfig.getConfig(beanClass, locale);
17430    return config.get(key, defaultValue);
175   }
176  
177   /**
178    * Get all attribute names.<p>
179    *
180    * @return An iterator for all the attribute names.
181    */
182   public Iterator attributeNames() {
1830    return this.attributes.keySet().iterator();
184   }
185  
186   /**
187    * Whether the property is readable. For dynamically generated property
188    * filters, this value is determined by whether the property has a getter
189    * method. For custom filters that extend this class, this value defaults
190    * to <code>true</code>. Custom filters must override this method if they
191    * are not readable<p>
192    *
193    * @return true if readable.
194    */
195   public boolean isReadable() {
1960    return true;
197   }
198  
199   /**
200    * Whether the property is writeable. For dynamically generated property
201    * filters, this value is determined by whether the property has a setter
202    * method and a converter from the <code>org.chwf.converter</code> package.
203    * For custom filters that extend this class, this value defaults to
204    * <code>true</code>. Custom filters must override this method if they
205    * are not writeable.<p>
206    *
207    * @return true if writeable.
208    */
209   public boolean isWriteable() {
2102    return true;
211   }
212  
213   /**
214    * Set the named attribute.<p>
215    *
216    * @param name The attribute name.
217    * @param value The attribute value.
218    */
219   protected void setAttribute(String name, Object value) {
220300    this.attributes.put(name, value);
221300  }
222  
223   /**
224    * Return the validator for this class, or <code>null</code> if the filter
225    * should not perform external validation.<p>
226    *
227    * @return The validator or <code>null</code>
228    */
229   protected Validator getValidator() {
23030    return this.validator;
231   }
232 }
233  
234 /**
235  * Generic default filter created through introspection.
236  *
237  * @author Paul Strack
238  */
239 class GenericPropertyFilter extends PropertyFilter {
240  
241   /** Suffix for datatype properties. */
242   private static final String DATATYPE_PROPERTY_SUFFIX = ".datatype";
243  
244   /** An array for method invocations with no parameters. */
245   private static final Object[] NO_PARAMETER = new Object[0];
246  
247   /** The property's getter. */
248   private final Method getter;
249  
250   /** The property's setter. */
251   private final Method setter;
252  
253   /** The property's converter. */
254   private final Converter converter;
255  
256   /**
257    * Constructor.
258    *
259    * @param beanClass The bean class.
260    * @param descriptor The BeanInfo property descriptor.
261    */
262   public GenericPropertyFilter(
263     Class beanClass,
264     PropertyDescriptor descriptor) {
265     super(beanClass, descriptor.getName(), descriptor.getPropertyType());
266     this.getter = descriptor.getReadMethod();
267     this.converter = Converter.getConverter(this.deriveDatatype());
268     if (this.converter.isSimpleType()) {
269       this.setter = descriptor.getWriteMethod();
270     } else {
271       this.setter = null;
272     }
273   }
274  
275   /**
276    * Get the specified property of the target object, as a string.
277    *
278    * @param object The object whose property is being retrieved.
279    * @return The property value.
280    * @throws FilterException For read failure.
281    */
282   public String get(Object object) throws FilterException {
283     return getConverter().format(getPropertyAsObject(object));
284   }
285  
286   /**
287    * Get the specified property of the target object, as an object.
288    *
289    * @param object The object whose property is being retrieved.
290    * @return The property value.
291    * @throws FilterException For read failure.
292    */
293   public Object getPropertyAsObject(Object object) throws FilterException {
294     checkBeanClass(object);
295     try {
296       return getGetter().invoke(object, NO_PARAMETER);
297     } catch (PropertyNotReadableException ex) {
298       throw ex;
299     } catch (Exception ex) {
300       throw new OperationException(ex);
301     }
302   }
303  
304   /**
305    * Set the specified property of the target object, using a string.
306    *
307    * @param object The object whose property is being updated.
308    * @param value The new property value.
309    * @throws FilterException For write failure.
310    * @throws ConversionException For string conversion failure.
311    */
312   public void set(Object object, String value)
313     throws FilterException, ConversionException {
314  
315     checkBeanClass(object);
316     try {
317       Object valueAsObject = getConverter().parse(value);
318       if (getValidator() != null) {
319         getValidator().validate(object, getName(), valueAsObject);
320       }
321       Object[] arguments = { valueAsObject};
322       getSetter().invoke(object, arguments);
323     } catch (ConversionException ex) {
324       throw ex;
325     } catch (PropertyNotWriteableException ex) {
326       throw ex;
327     } catch (InvocationTargetException ex) {
328       throw new OperationException(ex.getTargetException());
329     } catch (IllegalAccessException ex) {
330       throw new PropertyNotWriteableException(getName());
331     }
332   }
333  
334   /**
335    * Overrides its superclass method to return <code>true</code> if the
336    * property has a getter method.
337    *
338    * @return true if readable.
339    */
340   public boolean isReadable() {
341     return (this.getter != null);
342   }
343  
344   /**
345    * Overrides its superclass method to return <code>true</code> if the
346    * property has a setter method.
347    *
348    * @return true if writeable.
349    */
350   public boolean isWriteable() {
351     return (this.setter != null);
352   }
353  
354   /**
355    * Get the property's converter.
356    *
357    * @return The property's converter.
358    */
359   private Converter getConverter() {
360     return this.converter;
361   }
362  
363   /**
364    * Get the property's getter.
365    *
366    * @return The property's getter.
367    * @throws PropertyNotReadableException If not readable.
368    */
369   private Method getGetter() throws PropertyNotReadableException {
370     if (getter == null) {
371       throw new PropertyNotReadableException(getName());
372     }
373     return getter;
374   }
375  
376   /**
377    * Get the property's setter.
378    *
379    * @return The property's setter.
380    * @throws PropertyNotWriteableException If not writeable.
381    */
382   private Method getSetter() throws PropertyNotWriteableException {
383     if (setter == null) {
384       throw new PropertyNotWriteableException(getName());
385     }
386     return setter;
387   }
388  
389   /**
390    * Check the bean's type.
391    *
392    * @param object The target object.
393    * @throws FilterException If not the correct type.
394    */
395   private void checkBeanClass(Object object) throws FilterException {
396     if (!getBeanClass().isInstance(object)) {
397       throw new FilterException(
398         FilterException.MESSAGE_INCORRECT_OBJECT_TYPE,
399         new Object[] { getBeanClass().getName()});
400     }
401   }
402  
403   /**
404    * Derive the datatype.
405    *
406    * @return Derive the datatype.
407    */
408   private String deriveDatatype() {
409     String typeKey = getName() + DATATYPE_PROPERTY_SUFFIX;
410     String defaultType = getType().getName();
411     Config config = PolymorphicConfig.getConfig(getBeanClass());
412     return config.get(typeKey, defaultType);
413   }
414 }

this report was generated by version 1.0.5 of jcoverage.
visit www.jcoverage.com for updates.

copyright © 2003, jcoverage ltd. all rights reserved.
Java is a trademark of Sun Microsystems, Inc. in the United States and other countries.