View Javadoc
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