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