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