Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
BeanToPropertyValueTransformer |
|
| 4.2;4.2 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
3 | * contributor license agreements. See the NOTICE file distributed with | |
4 | * this work for additional information regarding copyright ownership. | |
5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
6 | * (the "License"); you may not use this file except in compliance with | |
7 | * the License. You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
18 | package org.apache.commons.beanutils; | |
19 | ||
20 | import org.apache.commons.collections.Transformer; | |
21 | import org.apache.commons.logging.Log; | |
22 | import org.apache.commons.logging.LogFactory; | |
23 | ||
24 | import java.lang.reflect.InvocationTargetException; | |
25 | ||
26 | ||
27 | /** | |
28 | * <p><code>Transformer</code> that outputs a property value.</p> | |
29 | * | |
30 | * <p>An implementation of <code>org.apache.commons.collections.Transformer</code> that transforms | |
31 | * the object provided by returning the value of a specified property of the object. The | |
32 | * constructor for <code>BeanToPropertyValueTransformer</code> requires the name of the property | |
33 | * that will be used in the transformation. The property can be a simple, nested, indexed, or | |
34 | * mapped property as defined by <code>org.apache.commons.beanutils.PropertyUtils</code>. If any | |
35 | * object in the property path specified by <code>propertyName</code> is <code>null</code> then the | |
36 | * outcome is based on the value of the <code>ignoreNull</code> attribute. | |
37 | * </p> | |
38 | * | |
39 | * <p> | |
40 | * A typical usage might look like: | |
41 | * <code><pre> | |
42 | * // create the transformer | |
43 | * BeanToPropertyValueTransformer transformer = new BeanToPropertyValueTransformer( "person.address.city" ); | |
44 | * | |
45 | * // transform the Collection | |
46 | * Collection peoplesCities = CollectionUtils.collect( peopleCollection, transformer ); | |
47 | * </pre></code> | |
48 | * </p> | |
49 | * | |
50 | * <p> | |
51 | * This would take a <code>Collection</code> of person objects and return a <code>Collection</code> | |
52 | * of objects which represents the cities in which each person lived. Assuming... | |
53 | * <ul> | |
54 | * <li> | |
55 | * The top level object in the <code>peeopleCollection</code> is an object which represents a | |
56 | * person. | |
57 | * </li> | |
58 | * <li> | |
59 | * The person object has a <code>getAddress()</code> method which returns an object which | |
60 | * represents a person's address. | |
61 | * </li> | |
62 | * <li> | |
63 | * The address object has a <code>getCity()</code> method which returns an object which | |
64 | * represents the city in which a person lives. | |
65 | * </li> | |
66 | * </ul> | |
67 | * | |
68 | * @author Norm Deane | |
69 | * @see org.apache.commons.beanutils.PropertyUtils | |
70 | * @see org.apache.commons.collections.Transformer | |
71 | */ | |
72 | public class BeanToPropertyValueTransformer implements Transformer { | |
73 | ||
74 | /** For logging. */ | |
75 | 19 | private final Log log = LogFactory.getLog(this.getClass()); |
76 | ||
77 | /** The name of the property that will be used in the transformation of the object. */ | |
78 | private String propertyName; | |
79 | ||
80 | /** | |
81 | * <p>Should null objects on the property path throw an <code>IllegalArgumentException</code>?</p> | |
82 | * <p> | |
83 | * Determines whether <code>null</code> objects in the property path will genenerate an | |
84 | * <code>IllegalArgumentException</code> or not. If set to <code>true</code> then if any objects | |
85 | * in the property path evaluate to <code>null</code> then the | |
86 | * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged but | |
87 | * not rethrown and <code>null</code> will be returned. If set to <code>false</code> then if any | |
88 | * objects in the property path evaluate to <code>null</code> then the | |
89 | * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged and | |
90 | * rethrown. | |
91 | * </p> | |
92 | */ | |
93 | private boolean ignoreNull; | |
94 | ||
95 | /** | |
96 | * Constructs a Transformer which does not ignore nulls. | |
97 | * Constructor which takes the name of the property that will be used in the transformation and | |
98 | * assumes <code>ignoreNull</code> to be <code>false</code>. | |
99 | * | |
100 | * @param propertyName The name of the property that will be used in the transformation. | |
101 | * @throws IllegalArgumentException If the <code>propertyName</code> is <code>null</code> or | |
102 | * empty. | |
103 | */ | |
104 | public BeanToPropertyValueTransformer(String propertyName) { | |
105 | 18 | this(propertyName, false); |
106 | 18 | } |
107 | ||
108 | /** | |
109 | * Constructs a Transformer and sets ignoreNull. | |
110 | * Constructor which takes the name of the property that will be used in the transformation and | |
111 | * a boolean which determines whether <code>null</code> objects in the property path will | |
112 | * genenerate an <code>IllegalArgumentException</code> or not. | |
113 | * | |
114 | * @param propertyName The name of the property that will be used in the transformation. | |
115 | * @param ignoreNull Determines whether <code>null</code> objects in the property path will | |
116 | * genenerate an <code>IllegalArgumentException</code> or not. | |
117 | * @throws IllegalArgumentException If the <code>propertyName</code> is <code>null</code> or | |
118 | * empty. | |
119 | */ | |
120 | public BeanToPropertyValueTransformer(String propertyName, boolean ignoreNull) { | |
121 | 19 | super(); |
122 | ||
123 | 19 | if ((propertyName != null) && (propertyName.length() > 0)) { |
124 | 19 | this.propertyName = propertyName; |
125 | 19 | this.ignoreNull = ignoreNull; |
126 | } else { | |
127 | 0 | throw new IllegalArgumentException( |
128 | "propertyName cannot be null or empty"); | |
129 | } | |
130 | 19 | } |
131 | ||
132 | /** | |
133 | * Returns the value of the property named in the transformer's constructor for | |
134 | * the object provided. If any object in the property path leading up to the target property is | |
135 | * <code>null</code> then the outcome will be based on the value of the <code>ignoreNull</code> | |
136 | * attribute. By default, <code>ignoreNull</code> is <code>false</code> and would result in an | |
137 | * <code>IllegalArgumentException</code> if an object in the property path leading up to the | |
138 | * target property is <code>null</code>. | |
139 | * | |
140 | * @param object The object to be transformed. | |
141 | * @return The value of the property named in the transformer's constructor for the object | |
142 | * provided. | |
143 | * @throws IllegalArgumentException If an IllegalAccessException, InvocationTargetException, or | |
144 | * NoSuchMethodException is thrown when trying to access the property specified on the object | |
145 | * provided. Or if an object in the property path provided is <code>null</code> and | |
146 | * <code>ignoreNull</code> is set to <code>false</code>. | |
147 | */ | |
148 | public Object transform(Object object) { | |
149 | ||
150 | 19 | Object propertyValue = null; |
151 | ||
152 | try { | |
153 | 19 | propertyValue = PropertyUtils.getProperty(object, propertyName); |
154 | 2 | } catch (IllegalArgumentException e) { |
155 | 2 | final String errorMsg = "Problem during transformation. Null value encountered in property path..."; |
156 | ||
157 | 2 | if (ignoreNull) { |
158 | 1 | log.warn("WARNING: " + errorMsg + e); |
159 | } else { | |
160 | 1 | IllegalArgumentException iae = new IllegalArgumentException(errorMsg); |
161 | 1 | if (!BeanUtils.initCause(iae, e)) { |
162 | 0 | log.error(errorMsg, e); |
163 | } | |
164 | 1 | throw iae; |
165 | } | |
166 | 0 | } catch (IllegalAccessException e) { |
167 | 0 | final String errorMsg = "Unable to access the property provided."; |
168 | 0 | IllegalArgumentException iae = new IllegalArgumentException(errorMsg); |
169 | 0 | if (!BeanUtils.initCause(iae, e)) { |
170 | 0 | log.error(errorMsg, e); |
171 | } | |
172 | 0 | throw iae; |
173 | 0 | } catch (InvocationTargetException e) { |
174 | 0 | final String errorMsg = "Exception occurred in property's getter"; |
175 | 0 | IllegalArgumentException iae = new IllegalArgumentException(errorMsg); |
176 | 0 | if (!BeanUtils.initCause(iae, e)) { |
177 | 0 | log.error(errorMsg, e); |
178 | } | |
179 | 0 | throw iae; |
180 | 2 | } catch (NoSuchMethodException e) { |
181 | 2 | final String errorMsg = "No property found for name [" + |
182 | propertyName + "]"; | |
183 | 2 | IllegalArgumentException iae = new IllegalArgumentException(errorMsg); |
184 | 2 | if (!BeanUtils.initCause(iae, e)) { |
185 | 0 | log.error(errorMsg, e); |
186 | } | |
187 | 2 | throw iae; |
188 | 15 | } |
189 | ||
190 | 15 | return propertyValue; |
191 | } | |
192 | ||
193 | /** | |
194 | * Returns the name of the property that will be used in the transformation of the bean. | |
195 | * | |
196 | * @return The name of the property that will be used in the transformation of the bean. | |
197 | */ | |
198 | public String getPropertyName() { | |
199 | 0 | return propertyName; |
200 | } | |
201 | ||
202 | /** | |
203 | * Returns the flag which determines whether <code>null</code> objects in the property path will | |
204 | * genenerate an <code>IllegalArgumentException</code> or not. If set to <code>true</code> then | |
205 | * if any objects in the property path evaluate to <code>null</code> then the | |
206 | * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged but | |
207 | * not rethrown and <code>null</code> will be returned. If set to <code>false</code> then if any | |
208 | * objects in the property path evaluate to <code>null</code> then the | |
209 | * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged and | |
210 | * rethrown. | |
211 | * | |
212 | * @return The flag which determines whether <code>null</code> objects in the property path will | |
213 | * genenerate an <code>IllegalArgumentException</code> or not. | |
214 | */ | |
215 | public boolean isIgnoreNull() { | |
216 | 0 | return ignoreNull; |
217 | } | |
218 | } |