| 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.BeanInfo; | |
| 36 | import java.beans.IntrospectionException; | |
| 37 | import java.beans.Introspector; | |
| 38 | import java.beans.PropertyDescriptor; | |
| 39 | import java.util.Iterator; | |
| 40 | import java.util.Map; | |
| 41 | ||
| 42 | import org.chwf.config.Config; | |
| 43 | import org.chwf.config.PolymorphicConfig; | |
| 44 | import org.chwf.converter.Converter; | |
| 45 | import org.chwf.plugin.OptionLister; | |
| 46 | import org.chwf.util.MiscUtils; | |
| 47 | ||
| 48 | /** | |
| 49 | * Generic default filter created through introspection. Custom bean | |
| 50 | * filters can subclass this class, instead of <code>BeanFilter</code>, | |
| 51 | * to set most of the filter's functionality through reflection. The | |
| 52 | * custom filter can then customize the filters for individual properties | |
| 53 | * and methods by calling the appropriate <code>putFilter</code> method: | |
| 54 | * | |
| 55 | * <pre> | |
| 56 | * package example; | |
| 57 | * import java.text.*; | |
| 58 | * import org.chwf.filter.*; | |
| 59 | * | |
| 60 | * public class AccountFilter extends GenericBeanFilter { | |
| 61 | * public AccountFilter() { | |
| 62 | * super(Account.class); | |
| 63 | * | |
| 64 | * // startDate property filter as an anonymous inner class: | |
| 65 | * PropertyFilter sdFilter = | |
| 66 | * new PropertyFilter("startDate", java.util.Date.class) { | |
| 67 | * | |
| 68 | * public String get(Object object) { | |
| 69 | * DateFormat df = SimpleDateFormat("mm/dd/yyyy"); | |
| 70 | * java.util.Date date = ((Account) object).getStartDate(); | |
| 71 | * if (date == null) { | |
| 72 | * return null; | |
| 73 | * } else { | |
| 74 | * return df.format(date); | |
| 75 | * } | |
| 76 | * } | |
| 77 | * | |
| 78 | * public void set(Object object, String value) { | |
| 79 | * DateFormat df = SimpleDateFormat("mm/dd/yyyy"); | |
| 80 | * try { | |
| 81 | * ((Account) object).setStartDate(df.parse(value)); | |
| 82 | * } catch (java.text.ParseException ex) { | |
| 83 | * throw new IllegalArgumentException(ex.getMessage()); | |
| 84 | * } | |
| 85 | * } | |
| 86 | * }; | |
| 87 | * | |
| 88 | * putPropertyFilter("startDate", sdFilter); | |
| 89 | * | |
| 90 | * initializePropertyAttributes(); // Using configuration | |
| 91 | * } | |
| 92 | * }</pre> | |
| 93 | * | |
| 94 | * @author <a href="mailto:pfstrack@users.sourceforge.net">Paul Strack</a> | |
| 95 | */ | |
| 96 | 1 | public class GenericBeanFilter extends BeanFilter { |
| 97 | ||
| 98 | /** | |
| 99 | * This constructor initializes the property and method filters for the | |
| 100 | * bean. It does <i>not</i> initialize property attributes.<p> | |
| 101 | * | |
| 102 | * @param beanClass The class being filtered. | |
| 103 | * @throws InitializationException If initialization fails for any reason. | |
| 104 | */ | |
| 105 | public GenericBeanFilter(Class beanClass) throws InitializationException { | |
| 106 | 26 | super(beanClass); |
| 107 | try { | |
| 108 | 26 | BeanInfo info = Introspector.getBeanInfo(beanClass); |
| 109 | 26 | initializeProperties(info); |
| 110 | 26 | Introspector.flushFromCaches(beanClass); // To avoid cluttering memory |
| 111 | 26 | } catch (Exception ex) { |
| 112 | 0 | throw new InitializationException( |
| 113 | InitializationException.MESSAGE_INIT_FAILED, | |
| 114 | new Object[] { ex }); | |
| 115 | } | |
| 116 | 26 | } |
| 117 | ||
| 118 | /** | |
| 119 | * This method initializes property attributes, using the JavaBean config | |
| 120 | * file described in the package documentation.<p> | |
| 121 | * | |
| 122 | * @throws InitializationException If introspection fails. | |
| 123 | */ | |
| 124 | protected void initializePropertyAttributes() | |
| 125 | throws InitializationException { | |
| 126 | // Set defaults: | |
| 127 | 26 | PropertyFilter[] filters = getPropertyFilters(); |
| 128 | 26 | initDefaultAttributeValues(filters); |
| 129 | 26 | initFromConfig(filters); |
| 130 | 26 | } |
| 131 | ||
| 132 | /** | |
| 133 | * Initialize default attribute values for label, datatype and readonly. | |
| 134 | * | |
| 135 | * @param filters The Property Filters | |
| 136 | */ | |
| 137 | private void initDefaultAttributeValues(PropertyFilter[] filters) { | |
| 138 | 129 | for (int i = 0; i < filters.length; i++) { |
| 139 | 103 | PropertyFilter filter = filters[i]; |
| 140 | 103 | String label = deriveLabel(filter); |
| 141 | 103 | filter.setAttribute(ATTRIBUTE_LABEL, label); |
| 142 | 103 | String type = MiscUtils.getWrapper(filter.getType()).getName(); |
| 143 | 103 | filter.setAttribute(ATTRIBUTE_DATATYPE, type); |
| 144 | 103 | if (!filter.isWriteable()) { |
| 145 | 60 | filter.setAttribute(ATTRIBUTE_READONLY, new Boolean(true)); |
| 146 | } | |
| 147 | } | |
| 148 | 26 | } |
| 149 | ||
| 150 | /** | |
| 151 | * Initialize property attributes using config. | |
| 152 | * | |
| 153 | * @param filters The Property Filters | |
| 154 | * @throws InitializationException If something goes wrong. | |
| 155 | */ | |
| 156 | private void initFromConfig(PropertyFilter[] filters) | |
| 157 | throws InitializationException { | |
| 158 | try { | |
| 159 | 26 | Class beanClass = getBeanClass(); |
| 160 | 26 | Config config = PolymorphicConfig.getConfig(beanClass); |
| 161 | 129 | for (int j = 0; j < filters.length; j++) { |
| 162 | 103 | PropertyFilter filter = filters[j]; |
| 163 | 103 | String filterName = filter.getName(); |
| 164 | 103 | Map data = config.getMap(filterName); |
| 165 | 103 | Iterator attributes = data.keySet().iterator(); |
| 166 | 103 | Class type = filter.getType(); |
| 167 | 280 | while (attributes.hasNext()) { |
| 168 | 74 | String attribute = (String) attributes.next(); |
| 169 | 74 | if (!(attribute.indexOf('.') > 0)) { |
| 170 | 27 | String value = (String) data.get(attribute); |
| 171 | 27 | if (attribute.equals(ATTRIBUTE_MAXLENGTH) |
| 172 | || attribute.equals(ATTRIBUTE_MINLENGTH) | |
| 173 | || attribute.equals(ATTRIBUTE_SCALE)) { | |
| 174 | 7 | Converter converter = Converter.getConverter(Integer.TYPE); |
| 175 | 7 | filter.setAttribute(attribute, converter.parse(value)); |
| 176 | 20 | } else if ( |
| 177 | attribute.equals(ATTRIBUTE_MIN) | |
| 178 | || attribute.equals(ATTRIBUTE_MAX)) { | |
| 179 | 15 | Converter converter = Converter.getConverter(type); |
| 180 | 15 | filter.setAttribute(attribute, converter.parse(value)); |
| 181 | 5 | } else if (attribute.equals(ATTRIBUTE_REQUIRED)) { |
| 182 | 1 | Converter converter = Converter.getConverter(Boolean.TYPE); |
| 183 | 1 | filter.setAttribute(attribute, converter.parse(value)); |
| 184 | } else { | |
| 185 | 4 | filter.setAttribute(attribute, value); |
| 186 | } | |
| 187 | } | |
| 188 | } | |
| 189 | ||
| 190 | 103 | Map options = |
| 191 | OptionLister.getInstance().loadOptionList(beanClass, filterName); | |
| 192 | 103 | if (options != null) { |
| 193 | 6 | filter.setAttribute(BeanFilter.ATTRIBUTE_OPTIONS, options); |
| 194 | } | |
| 195 | } | |
| 196 | 26 | } catch (Exception ex) { |
| 197 | 0 | Object[] arguments = { ex }; |
| 198 | 0 | throw new InitializationException( |
| 199 | InitializationException.MESSAGE_PROPERTY_INIT_FAILED, | |
| 200 | new Object[] { ex }); | |
| 201 | } | |
| 202 | 26 | } |
| 203 | ||
| 204 | /** | |
| 205 | * Initialize property filters. | |
| 206 | * | |
| 207 | * @param info The BeanInfo for the class. | |
| 208 | * @throws IntrospectionException For BeanInfo exceptions. | |
| 209 | */ | |
| 210 | private void initializeProperties(BeanInfo info) | |
| 211 | throws IntrospectionException { | |
| 212 | 26 | PropertyDescriptor[] properties = info.getPropertyDescriptors(); |
| 213 | 129 | for (int i = 0; i < properties.length; i++) { |
| 214 | try { | |
| 215 | 103 | putPropertyFilter( |
| 216 | properties[i].getName(), | |
| 217 | new GenericPropertyFilter(getBeanClass(), properties[i])); | |
| 218 | 103 | } catch (InitializationException ex) { |
| 219 | // Suppress properties whose filter cannot be constructed. | |
| 220 | 0 | i = i * 1; // Dummy op so that checkstyle does not complain |
| 221 | } | |
| 222 | } | |
| 223 | 26 | } |
| 224 | ||
| 225 | /** | |
| 226 | * Method that derives the propery label from the property name, | |
| 227 | * by "un-camel-casing" the name. | |
| 228 | * | |
| 229 | * @param filter The property filter. | |
| 230 | * @return The derived label. | |
| 231 | */ | |
| 232 | private String deriveLabel(PropertyFilter filter) { | |
| 233 | 103 | char[] name = filter.getName().toCharArray(); |
| 234 | 103 | StringBuffer label = new StringBuffer(name.length); |
| 235 | 103 | label.append(Character.toUpperCase(name[0])); |
| 236 | 103 | boolean wasUppercase = Character.isUpperCase(name[0]); |
| 237 | 750 | for (int i = 1; i < name.length; i++) { |
| 238 | 647 | char c = name[i]; |
| 239 | 647 | if (Character.isUpperCase(c)) { |
| 240 | 49 | if (!wasUppercase) { |
| 241 | 45 | label.append(' '); |
| 242 | } | |
| 243 | 49 | label.append(c); |
| 244 | 49 | wasUppercase = true; |
| 245 | } else { | |
| 246 | 598 | label.append(c); |
| 247 | 598 | wasUppercase = false; |
| 248 | } | |
| 249 | } | |
| 250 | 103 | return label.toString(); |
| 251 | } | |
| 252 | ||
| 253 | /** Constant for specifying string parameters in reflection. */ | |
| 254 | 1 | private static final Class[] STRING_PARAM = { String.class }; |
| 255 | } |
|
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |