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 2002 (C) Intalio, Inc. All Rights Reserved.
42 *
43 * $Id$
44 */
45 package org.exolab.castor.xml.handlers;
46
47 import org.exolab.castor.mapping.FieldHandler;
48 import org.exolab.castor.mapping.ValidityException;
49 import org.exolab.castor.xml.util.ContainerElement;
50
51 /**
52 * The FieldHandler for ContainerElement.
53 *
54 * @author <a href="kvisco@intalio.com">Keith Visco</a>
55 * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
56 * @see FieldDescriptor org.exolab.castor.mapping.FieldDescriptor
57 * @see FieldHandler org.exolab.castor.mapping.FieldHandler
58 */
59 public final class ContainerFieldHandler implements FieldHandler {
60
61 /** Automatically choose the mode to use. */
62 public static final int MODE_AUTO = 0;
63 /** When the field is not a ContainerElement, this mode is used. */
64 public static final int MODE_PARENT_LINK = 1;
65 /** The mode for a ContainerElement. getValue and setValue operate on the parent. */
66 public static final int MODE_CHILD_LINK = 2;
67
68 /** The actual FieldHandler to delegate to. */
69 private final FieldHandler _handler;
70 /** Mode to use for this ContainerFieldHandler. */
71 private final int _mode = MODE_AUTO;
72
73 /**
74 * Creates a new ContainerFieldHandler with the given FieldHandler.
75 * @param handler The field handler to delegate to.
76 */
77 public ContainerFieldHandler(final FieldHandler handler) {
78 super();
79 _handler = handler;
80 } //-- ContainerFieldHandler
81
82 //-----------------------------/
83 //- Methods from FieldHandler -/
84 //-----------------------------/
85
86 /**
87 * Returns the value of the field from the object. If mode is
88 * MODE_CHILD_LINK or mode is MODE_AUTO and the object is a
89 * ContainerElement, then the value of the parent is returned. Otherwise, a
90 * new ContainerElement is returned. The value of this new ContainerElement
91 * is the value of the provided object and the parent of the new
92 * ContainerElement is the provided object.
93 *
94 * @param object The object to get the value of
95 * @return The value of the field
96 * @throws IllegalStateException The Java object has changed and is no
97 * longer supported by this handler, or the handler is not
98 * compatible with the Java object
99 */
100 public Object getValue(final Object object) throws IllegalStateException {
101 int mode = _mode;
102 if (mode == MODE_AUTO) {
103 if (object instanceof ContainerElement) {
104 mode = MODE_CHILD_LINK;
105 } else {
106 mode = MODE_PARENT_LINK;
107 }
108 }
109
110 if (mode == MODE_CHILD_LINK) {
111 return _handler.getValue(((ContainerElement) object).getParent());
112 }
113
114 // MODE_PARENT_LINK
115 ContainerElement container = new ContainerElement(_handler.getValue(object));
116 container.setParent(object);
117 return container;
118 } //-- getValue
119
120 /**
121 * Creates a new instance of the object described by this field. Of the
122 * object provided is a ContainerElement, then a new isntance of the parent
123 * object is returned. Otherwise a new ContainerElement is created and
124 * returned, with the parent set to the provided object.
125 *
126 * @param parent The object for which the field is created
127 * @return A new instance of the field's value
128 * @throws IllegalStateException This field is a simple type and cannot be
129 * instantiated
130 */
131 public Object newInstance(final Object parent) throws IllegalStateException {
132 //-- MODE_CHILD_LINK and MODE_AUTO
133 if (parent instanceof ContainerElement) {
134 return _handler.newInstance(((ContainerElement) parent).getParent());
135 }
136
137 // MODE_PARENT_LINK
138 ContainerElement container = new ContainerElement();
139 container.setParent(parent);
140 return container;
141 } //-- newInstance
142
143 /**
144 * Sets the value of the field to a default value.
145 * <p>
146 * Reference fields are set to null, primitive fields are set to their
147 * default value, collection fields are emptied of all elements.
148 *
149 * @param object The object
150 * @throws IllegalStateException The Java object has changed and is no
151 * longer supported by this handler, or the handler is not
152 * compatiable with the Java object
153 */
154 public void resetValue(final Object object) throws IllegalStateException {
155 _handler.resetValue(object);
156 }
157
158 /**
159 * Sets the value of the field on the object. That is, sets the value of the
160 * container parent to the provided value.
161 *
162 * @param object The object whose value to set.
163 * @param value The new value
164 * @throws IllegalStateException The Java object has changed and is no
165 * longer supported by this handler, or the handler is not
166 * compatiable with the Java object
167 * @throws IllegalArgumentException The value passed is not of a supported
168 * type
169 */
170 public void setValue(final Object object, final Object value)
171 throws IllegalStateException, IllegalArgumentException {
172 if (_mode == MODE_PARENT_LINK) {
173 // Do nothing for MODE_PARENT_LINK; the container is not part of the object model
174 return;
175 }
176
177 // For MODE_AUTO and MODE_CHILD_LINK:
178 if (object instanceof ContainerElement) {
179 _handler.setValue(((ContainerElement) object).getParent(), value);
180 }
181 } //-- setValue
182
183 /**
184 * Checks the field validity. Returns successfully if the field can be
185 * stored, is valid, etc, throws an exception otherwise.
186 *
187 * @param object The object
188 * @throws ValidityException The field is invalid, is required and null, or
189 * any other validity violation
190 * @throws IllegalStateException The Java object has changed and is no
191 * longer supported by this handler, or the handler is not
192 * compatiable with the Java object
193 */
194 public void checkValidity(final Object object) throws ValidityException, IllegalStateException {
195 //-- deprecated...do nothing
196 } //-- checkValidity
197
198 } //-- ContainerFieldHandler