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