1 /**
2 * Redistribution and use of this software and associated documentation ("Software"), with or
3 * without modification, are permitted provided that the following conditions are met:
4 *
5 * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6 * must also contain a copy of this document.
7 *
8 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9 * conditions and the following disclaimer in the documentation and/or other materials provided with
10 * the distribution.
11 *
12 * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13 * without prior written permission of Intalio, Inc. For written permission, please contact
14 * info@exolab.org.
15 *
16 * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17 * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18 * Intalio, Inc.
19 *
20 * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21 *
22 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Copyright 1999-2005 (C) Intalio, Inc. All Rights Reserved.
32 *
33 * $Id$
34 */
35
36 package org.exolab.castor.mapping;
37
38 import org.exolab.castor.mapping.loader.CollectionHandlers;
39 import java.util.Enumeration;
40
41 /**
42 * An extended version of the FieldHandler interface which is used for making generic libraries of
43 * FieldHandlers which can be used for more than one field or class, but have similar conversion
44 * algorithms.
45 *
46 * @author <a href="kvisco-at-intalio.com">Keith Visco</a>
47 * @version $Revision$ $Date: 2005-01-18 17:29:45 -0700 (Tue, 18 Jan 2005) $
48 * @see FieldDescriptor
49 * @see FieldHandler
50 */
51 public abstract class GeneralizedFieldHandler extends AbstractFieldHandler {
52
53 /**
54 * Error message when a null FieldHandler is encountered
55 */
56 private static final String NULL_HANDLER_ERR =
57 "A call to #setFieldHandler (with a non-null value) must be "
58 + "made before calling this method.";
59
60 /**
61 * The actual FieldHandler to delegate to
62 */
63 private FieldHandler _handler = null;
64
65 /**
66 * The flag controlling automatic collection iteration during convertUponGet
67 */
68 private boolean _autoCollectionIteration = true;
69
70
71 /**
72 * Creates a new default GeneralizedFieldHandler. This method should be called by all extending
73 * classes so that any important initialization code will be executed.
74 */
75 protected GeneralizedFieldHandler() {
76 super();
77 // -- currently nothing to do, but initialization
78 // -- code may be needed in the future
79 } // -- GeneralizedFieldHandler
80
81
82 /**
83 * This method is used to convert the value when the getValue method is called. The getValue
84 * method will obtain the actual field value from given 'parent' object. This convert method is
85 * then invoked with the field's value. The value returned from this method will be the actual
86 * value returned by getValue method.
87 *
88 * @param value the object value to convert after performing a get operation
89 * @return the converted value.
90 */
91 public abstract Object convertUponGet(Object value);
92
93 /**
94 * This method is used to convert the value when the setValue method is called. The setValue
95 * method will call this method to obtain the converted value. The converted value will then be
96 * used as the value to set for the field.
97 *
98 * @param value the object value to convert before performing a set operation
99 * @return the converted value.
100 */
101 public abstract Object convertUponSet(Object value);
102
103 /**
104 * Returns the class type for the field that this GeneralizedFieldHandler converts to and from.
105 * This should be the type that is used in the object model.
106 *
107 * @return the class type of of the field
108 */
109 public abstract Class getFieldType();
110
111 /**
112 * Sets the FieldHandler that this FieldHander delegates to. A call to this method must be made
113 * with a non-null FieldHandler before this GeneralizedFieldHandler can be used.
114 *
115 * @param handler the FieldHandler to delegate to
116 */
117 public final void setFieldHandler(FieldHandler handler) {
118 _handler = handler;
119 } // -- setFieldHandler
120
121 /**
122 * Sets whether or not this GeneralizedFieldHandler should automatically iterate over the
123 * collection returned by the target object and pass only the items (one by one) to the
124 * convertUponGet method.
125 *
126 * As of Castor 0.9.6 this is true by default.
127 *
128 * @param autoCollectionIteration a boolean that when true indicates that this
129 * GeneralizedFieldHandler should automatically iterate over a collection and pass only
130 * collection items to the convertUponGet method.
131 */
132 public void setCollectionIteration(boolean autoCollectionIteration) {
133 _autoCollectionIteration = autoCollectionIteration;
134 } // -- setCollectionIteration
135
136 // -----------------------------------------------/
137 // - Methods inherited from AbstractFieldHandler -/
138 // -----------------------------------------------/
139
140 /**
141 * Returns the value of the field from the object.
142 *
143 * @param object The object
144 * @return The value of the field
145 * @throws IllegalStateException The Java object has changed and is no longer supported by this
146 * handler, or the handler is not compatiable with the Java object
147 */
148 public final Object getValue(Object object) throws IllegalStateException {
149 if (_handler == null) {
150 throw new IllegalStateException(NULL_HANDLER_ERR);
151 }
152
153 Object value = _handler.getValue(object);
154 if ((_autoCollectionIteration) && (value != null)) {
155
156 if (value instanceof java.util.Enumeration) {
157 return new GFHConverterEnumeration(this, (Enumeration) value);
158 }
159 // -- other collection type?
160 if (CollectionHandlers.hasHandler(value.getClass())) {
161 CollectionHandler colHandler = null;
162 try {
163 colHandler = CollectionHandlers.getHandler(value.getClass());
164 } catch (MappingException mx) {
165 throw new IllegalStateException(mx.getMessage());
166 }
167 return new GFHConverterEnumeration(this, colHandler.elements(value));
168 }
169 }
170
171 return convertUponGet(value);
172 } // -- getValue
173
174
175 /**
176 * Creates a new instance of the object described by this field.
177 *
178 * @param parent The object for which the field is created
179 * @return A new instance of the field's value
180 * @throws IllegalStateException This field is a simple type and cannot be instantiated
181 */
182 public Object newInstance(Object parent) throws IllegalStateException {
183 if (_handler == null) {
184 throw new IllegalStateException(NULL_HANDLER_ERR);
185 }
186 return _handler.newInstance(parent);
187 }
188
189 /**
190 * Creates a new instance of the object described by this field.
191 *
192 * @param parent The object for which the field is created
193 * @param args the set of constructor arguments
194 * @return A new instance of the field's value
195 * @throws IllegalStateException This field is a simple type and cannot be instantiated
196 */
197 public Object newInstance(Object parent, Object[] args) throws IllegalStateException {
198 if (_handler instanceof ExtendedFieldHandler) {
199 return ((ExtendedFieldHandler) _handler).newInstance(parent, args);
200 }
201
202 // -- backward compatibility: ignore arguments
203 return newInstance(parent);
204 }
205
206 /**
207 * Sets the value of the field to a default value.
208 * <p>
209 * Reference fields are set to null, primitive fields are set to their default value, collection
210 * fields are emptied of all elements.
211 *
212 * @param object The object
213 * @throws IllegalStateException The Java object has changed and is no longer supported by this
214 * handler, or the handler is not compatiable with the Java object
215 */
216 public final void resetValue(Object object)
217 throws IllegalStateException, IllegalArgumentException {
218 if (_handler == null) {
219 throw new IllegalStateException(NULL_HANDLER_ERR);
220 }
221 _handler.resetValue(object);
222 }
223
224 /**
225 * Sets the value of the field on the object.
226 *
227 * @param object The object.
228 * @param value The new value.
229 * @throws IllegalStateException The Java object has changed and is no longer supported by this
230 * handler, or the handler is not compatiable with the Java object.
231 * @throws IllegalArgumentException The value passed is not of a supported type.
232 */
233 public final void setValue(Object object, Object value)
234 throws IllegalStateException, IllegalArgumentException {
235 if (_handler == null) {
236 throw new IllegalStateException(NULL_HANDLER_ERR);
237 }
238 _handler.setValue(object, convertUponSet(value));
239 }
240
241 static class GFHConverterEnumeration implements Enumeration {
242
243 Enumeration _enumeration = null;
244 GeneralizedFieldHandler _handler = null;
245
246 GFHConverterEnumeration(GeneralizedFieldHandler handler, Enumeration enumeration) {
247 _enumeration = enumeration;
248 _handler = handler;
249 }
250
251 public boolean hasMoreElements() {
252 return _enumeration.hasMoreElements();
253 }
254
255 public Object nextElement() {
256 Object value = _enumeration.nextElement();
257 return _handler.convertUponGet(value);
258 }
259
260
261 }
262
263 }
264