KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > beanutils > BeanPropertyValueChangeClosure


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16  
17 package org.apache.commons.beanutils;
18
19 import org.apache.commons.collections.Closure;
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22
23 import java.lang.reflect.InvocationTargetException JavaDoc;
24
25
26 /**
27  * <p><code>Closure</code> that sets a property.</p>
28  * <p>
29  * An implementation of <code>org.apache.commons.collections.Closure</code> that updates
30  * a specified property on the object provided with a specified value.
31  * The <code>BeanPropertyValueChangeClosure</code> constructor takes two parameters which determine
32  * what property will be updated and with what value.
33  * <dl>
34  * <dt>
35  * <b><code><pre>public BeanPropertyValueChangeClosure( String propertyName, Object propertyValue )</pre></code></b>
36  * </dt>
37  * <dd>
38  * Will create a <code>Closure</code> that will update an object by setting the property
39  * specified by <code>propertyName</code> to the value specified by <code>propertyValue</code>.
40  * </dd>
41  * </dl>
42  *
43  * <p/>
44  * <strong>Note:</strong> Property names can be a simple, nested, indexed, or mapped property as defined by
45  * <code>org.apache.commons.beanutils.PropertyUtils</code>. If any object in the property path
46  * specified by <code>propertyName</code> is <code>null</code> then the outcome is based on the
47  * value of the <code>ignoreNull</code> attribute.
48  *
49  * <p/>
50  * A typical usage might look like:
51  * <code><pre>
52  * // create the closure
53  * BeanPropertyValueChangeClosure closure =
54  * new BeanPropertyValueChangeClosure( "activeEmployee", Boolean.TRUE );
55  *
56  * // update the Collection
57  * CollectionUtils.forAllDo( peopleCollection, closure );
58  * </pre></code>
59  * <p/>
60  *
61  * This would take a <code>Collection</code> of person objects and update the
62  * <code>activeEmployee</code> property of each object in the <code>Collection</code> to
63  * <code>true</code>. Assuming...
64  * <ul>
65  * <li>
66  * The top level object in the <code>peopleCollection</code> is an object which represents a
67  * person.
68  * </li>
69  * <li>
70  * The person object has a <code>setActiveEmployee( boolean )</code> method which updates
71  * the value for the object's <code>activeEmployee</code> property.
72  * </li>
73  * </ul>
74  *
75  * @author Norm Deane
76  * @see org.apache.commons.beanutils.PropertyUtils
77  * @see org.apache.commons.collections.Closure
78  */

79 public class BeanPropertyValueChangeClosure implements Closure {
80    
81     /** For logging. */
82     private final Log log = LogFactory.getLog(this.getClass());
83
84     /**
85      * The name of the property which will be updated when this <code>Closure</code> executes.
86      */

87     private String JavaDoc propertyName;
88
89     /**
90      * The value that the property specified by <code>propertyName</code>
91      * will be updated to when this <code>Closure</code> executes.
92      */

93     private Object JavaDoc propertyValue;
94
95     /**
96      * Determines whether <code>null</code> objects in the property path will genenerate an
97      * <code>IllegalArgumentException</code> or not. If set to <code>true</code> then if any objects
98      * in the property path leading up to the target property evaluate to <code>null</code> then the
99      * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged but
100      * not rethrown. If set to <code>false</code> then if any objects in the property path leading
101      * up to the target property evaluate to <code>null</code> then the
102      * <code>IllegalArgumentException</code> throw by <code>PropertyUtils</code> will be logged and
103      * rethrown.
104      */

105     private boolean ignoreNull;
106
107     /**
108      * Constructor which takes the name of the property to be changed, the new value to set
109      * the property to, and assumes <code>ignoreNull</code> to be <code>false</code>.
110      *
111      * @param propertyName The name of the property that will be updated with the value specified by
112      * <code>propertyValue</code>.
113      * @param propertyValue The value that <code>propertyName</code> will be set to on the target
114      * object.
115      * @throws IllegalArgumentException If the propertyName provided is null or empty.
116      */

117     public BeanPropertyValueChangeClosure(String JavaDoc propertyName, Object JavaDoc propertyValue) {
118         this(propertyName, propertyValue, false);
119     }
120
121     /**
122      * Constructor which takes the name of the property to be changed, the new value to set
123      * the property to and a boolean which determines whether <code>null</code> objects in the
124      * property path will genenerate an <code>IllegalArgumentException</code> or not.
125      *
126      * @param propertyName The name of the property that will be updated with the value specified by
127      * <code>propertyValue</code>.
128      * @param propertyValue The value that <code>propertyName</code> will be set to on the target
129      * object.
130      * @param ignoreNull Determines whether <code>null</code> objects in the property path will
131      * genenerate an <code>IllegalArgumentException</code> or not.
132      * @throws IllegalArgumentException If the propertyName provided is null or empty.
133      */

134     public BeanPropertyValueChangeClosure(String JavaDoc propertyName, Object JavaDoc propertyValue, boolean ignoreNull) {
135         super();
136
137         if ((propertyName != null) && (propertyName.length() > 0)) {
138             this.propertyName = propertyName;
139             this.propertyValue = propertyValue;
140             this.ignoreNull = ignoreNull;
141         } else {
142             throw new IllegalArgumentException JavaDoc("propertyName cannot be null or empty");
143         }
144     }
145
146     /**
147      * Updates the target object provided using the property update criteria provided when this
148      * <code>BeanPropertyValueChangeClosure</code> was constructed. If any object in the property
149      * path leading up to the target property is <code>null</code> then the outcome will be based on
150      * the value of the <code>ignoreNull</code> attribute. By default, <code>ignoreNull</code> is
151      * <code>false</code> and would result in an <code>IllegalArgumentException</code> if an object
152      * in the property path leading up to the target property is <code>null</code>.
153      *
154      * @param object The object to be updated.
155      * @throws IllegalArgumentException If an IllegalAccessException, InvocationTargetException, or
156      * NoSuchMethodException is thrown when trying to access the property specified on the object
157      * provided. Or if an object in the property path provided is <code>null</code> and
158      * <code>ignoreNull</code> is set to <code>false</code>.
159      */

160     public void execute(Object JavaDoc object) {
161        
162         try {
163             PropertyUtils.setProperty(object, propertyName, propertyValue);
164         } catch (IllegalArgumentException JavaDoc e) {
165             final String JavaDoc errorMsg = "Unable to execute Closure. Null value encountered in property path...";
166
167             if (ignoreNull) {
168                 log.warn("WARNING: " + errorMsg, e);
169             } else {
170                 log.error("ERROR: " + errorMsg, e);
171                 throw e;
172             }
173         } catch (IllegalAccessException JavaDoc e) {
174             final String JavaDoc errorMsg = "Unable to access the property provided.";
175             log.error(errorMsg, e);
176             throw new IllegalArgumentException JavaDoc(errorMsg);
177         } catch (InvocationTargetException JavaDoc e) {
178             final String JavaDoc errorMsg = "Exception occurred in property's getter";
179             log.error(errorMsg, e);
180             throw new IllegalArgumentException JavaDoc(errorMsg);
181         } catch (NoSuchMethodException JavaDoc e) {
182             final String JavaDoc errorMsg = "Property not found";
183             log.error(errorMsg, e);
184             throw new IllegalArgumentException JavaDoc(errorMsg);
185         }
186     }
187
188     /**
189      * Returns the name of the property which will be updated when this <code>Closure</code> executes.
190      *
191      * @return The name of the property which will be updated when this <code>Closure</code> executes.
192      */

193     public String JavaDoc getPropertyName() {
194         return propertyName;
195     }
196
197     /**
198      * Returns the value that the property specified by <code>propertyName</code>
199      * will be updated to when this <code>Closure</code> executes.
200      *
201      * @return The value that the property specified by <code>propertyName</code>
202      * will be updated to when this <code>Closure</code> executes.
203      */

204     public Object JavaDoc getPropertyValue() {
205         return propertyValue;
206     }
207
208     /**
209      * Returns the flag that determines whether <code>null</code> objects in the property path will
210      * genenerate an <code>IllegalArgumentException</code> or not. If set to <code>true</code> then
211      * if any objects in the property path leading up to the target property evaluate to
212      * <code>null</code> then the <code>IllegalArgumentException</code> throw by
213      * <code>PropertyUtils</code> will be logged but not rethrown. If set to <code>false</code> then
214      * if any objects in the property path leading up to the target property evaluate to
215      * <code>null</code> then the <code>IllegalArgumentException</code> throw by
216      * <code>PropertyUtils</code> will be logged and rethrown.
217      *
218      * @return The flag that determines whether <code>null</code> objects in the property path will
219      * genenerate an <code>IllegalArgumentException</code> or not.
220      */

221     public boolean isIgnoreNull() {
222         return ignoreNull;
223     }
224 }
225
Popular Tags