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 2000 (C) Intalio, Inc. All Rights Reserved.
32 *
33 * $Id$
34 */
35 package org.exolab.castor.xml.handlers;
36
37 import java.lang.reflect.Array;
38 import java.util.StringTokenizer;
39
40 import org.exolab.castor.mapping.FieldHandler;
41 import org.exolab.castor.mapping.ValidityException;
42 import org.exolab.castor.xml.TypeValidator;
43 import org.exolab.castor.xml.ValidationException;
44 import org.exolab.castor.xml.XMLFieldHandler;
45
46 /**
47 * A FieldHandler for the XML Schema Collection type.
48 * <p>
49 * TODO : support all kind of XSList.
50 *
51 * @author <a href="blandin@intalio.com">Arnaud Blandin</a>
52 * @version $Revision$ $Date: 2003-03-03 00:05:44 -0700 (Mon, 03 Mar 2003) $
53 */
54 public class CollectionFieldHandler extends XMLFieldHandler {
55
56 /** The field handler to which we delegate. */
57 private final FieldHandler _handler;
58 /** Type validator to use to validate an instance of this type. */
59 private final TypeValidator _validator;
60
61 // ----------------/
62 // - Constructors -/
63 // ----------------/
64
65 /**
66 * Creates a new CollectionFieldHandler using the given FieldHandler for delegation.
67 *
68 * @param fieldHandler the fieldHandler for delegation.
69 */
70 public CollectionFieldHandler(final FieldHandler fieldHandler) {
71 this(fieldHandler, null);
72 } // -- CollectionFieldHandler
73
74 /**
75 * Creates a new CollectionFieldHandler using the given FieldHandler for delegation and the given
76 * type validator for validation.
77 *
78 * @param fieldHandler the fieldHandler for delegation.
79 * @param validator Type validator to use to validate an instance of this type.
80 */
81 public CollectionFieldHandler(final FieldHandler fieldHandler, final TypeValidator validator) {
82 super();
83 if (fieldHandler == null) {
84 String err = "The FieldHandler argument passed to "
85 + "the constructor of CollectionFieldHandler must not be null.";
86 throw new IllegalArgumentException(err);
87 }
88 this._handler = fieldHandler;
89 this._validator = validator;
90 } // -- CollectionFieldHandler
91
92 // ------------------/
93 // - Public Methods -/
94 // ------------------/
95
96 /**
97 * Sets the value of the field associated with this descriptor. If paased a String, then String is
98 * tokenized and each token is added as an individual instance to the collection.
99 *
100 * @param target the object in which to set the value
101 * @param value the value of the field
102 * @throws IllegalStateException if any value provided fails validation.
103 */
104 public void setValue(final Object target, final Object value)
105 throws java.lang.IllegalStateException {
106 if (value == null) {
107 return;
108 }
109
110 // If not a String, assume we are passed something the field handler understands
111 if (!(value instanceof String)) {
112 _handler.setValue(target, value);
113 return;
114 }
115
116 StringTokenizer temp = new StringTokenizer((java.lang.String) value, " ");
117 final int size = temp.countTokens();
118 for (int i = 0; i < size; i++) {
119 String tempValue = temp.nextToken();
120 try {
121 if (_validator != null) {
122 _validator.validate(tempValue, null);
123 }
124 } catch (ValidationException e) {
125 throw new IllegalStateException(e.getMessage());
126 }
127 _handler.setValue(target, tempValue);
128 }
129 } // -- setValue
130
131 /**
132 * Gets the value of the field associated with this descriptor. If the value is an array, it
133 * returns a string 'representing' this array
134 *
135 * @param target the object from which to get the value
136 * @return the value of the field associated with this descriptor.
137 * @throws IllegalStateException if any value provided fails validation.
138 */
139 public Object getValue(final Object target) throws java.lang.IllegalStateException {
140 // Needs to return the proper object
141 Object temp = _handler.getValue(target);
142
143 if (temp == null) {
144 return temp;
145 }
146
147 if (!temp.getClass().isArray()) {
148 return temp.toString();
149 }
150
151 int size = Array.getLength(temp);
152 if (size == 0) {
153 return null;
154 }
155
156 StringBuilder result = new StringBuilder();
157 for (int i = 0; i < size; i++) {
158 if (i > 0) {
159 result.append(' ');
160 }
161 Object obj = Array.get(temp, i);
162 result.append(obj);
163 }
164 return result.toString();
165 }
166
167 /**
168 * Sets the value of the field to a default value.
169 *
170 * @param target The object to reset
171 * @throws IllegalStateException if the Java object has changed and is no longer supported by this
172 * handler or the handler is not compatible with the Java object
173 */
174 public void resetValue(final Object target) throws java.lang.IllegalStateException {
175 _handler.resetValue(target);
176 }
177
178 /**
179 * Checks the field validity. Returns successfully if the field can be stored, is valid, etc,
180 * throws an exception otherwise.
181 *
182 * @param object The object
183 * @throws ValidityException The field is invalid, is required and null, or any other validity
184 * violation
185 * @throws IllegalStateException The Java object has changed and is no longer supported by this
186 * handler, or the handler is not compatiable with the Java object
187 */
188 public void checkValidity(final Object object) throws ValidityException, IllegalStateException {
189 // -- do nothing for now
190 } // -- checkValidity
191
192 /**
193 * Creates a new instance of the object described by this field.
194 *
195 * @param parent The object for which the field is created
196 * @return A new instance of the field's value
197 * @throws IllegalStateException This field is a simple type and cannot be instantiated
198 */
199 public Object newInstance(final Object parent) throws IllegalStateException {
200 return null;
201 } // -- newInstance
202
203 /**
204 * Returns true if the given object is an XMLFieldHandler that is equivalent to the delegated
205 * handler. An equivalent XMLFieldHandler is an XMLFieldHandler that is an instances of the same
206 * class.
207 *
208 * @param obj The object to compare to <code>this</code>.
209 *
210 * @return true if the given object is an XMLFieldHandler that is equivalent to this one.
211 */
212 public boolean equals(final Object obj) {
213 if (obj == null || !(obj instanceof XMLFieldHandler)) {
214 return false;
215 }
216 return _handler.getClass().isInstance(obj);
217 } // -- equals
218
219 } // -- CollectionFieldHandler