KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > extras > IdDefRefMapperBase


1 /*
2 Copyright (c) 2005, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.extras;
30
31 import java.util.HashMap JavaDoc;
32
33 import org.jibx.runtime.IAliasable;
34 import org.jibx.runtime.IMarshallable;
35 import org.jibx.runtime.IMarshaller;
36 import org.jibx.runtime.IMarshallingContext;
37 import org.jibx.runtime.IUnmarshaller;
38 import org.jibx.runtime.IUnmarshallingContext;
39 import org.jibx.runtime.JiBXException;
40 import org.jibx.runtime.impl.MarshallingContext;
41 import org.jibx.runtime.impl.UnmarshallingContext;
42
43 /**
44  * <p>Abstract base custom marshaller/unmarshaller for an object that may have
45  * multiple references. The first time an object is seen when marshalling the
46  * full XML representation is generated; successive uses of the same object then
47  * use XML references to the object ID. To use this class you need to create a
48  * subclass with a constructor using the same signature as the one provided
49  * (calling the base class constructor from your subclass constructor) and
50  * implement the abstract {@link #getIdValue} method in your subclass. You can
51  * also override the provided {@link #getAttributeName} method to change the
52  * name used for the IDREF attribute, which must not match the name of an
53  * attribute used in the normal marshalled form of the object. The name used for
54  * this marshaller/unmarshaller in the mapping definition must match the name
55  * used for the base object type being handled.</p>
56  *
57  * @author Dennis M. Sosnoski
58  * @version 1.0
59  */

60
61 public abstract class IdDefRefMapperBase
62     implements IMarshaller, IUnmarshaller, IAliasable {
63     
64     private String JavaDoc m_uri;
65     private int m_index;
66     private String JavaDoc m_name;
67     
68     /**
69      * Aliased constructor taking a name definition for reference elements. The
70      * subclass version will be used by JiBX to define the element name to be
71      * used with this custom marshaller/unmarshaller.
72      *
73      * @param uri namespace URI for the top-level element
74      * @param index namespace index corresponding to the defined URI within the
75      * marshalling context definitions
76      * @param name local name for the reference element
77      */

78     public IdDefRefMapperBase(String JavaDoc uri, int index, String JavaDoc name) {
79         m_uri = uri;
80         m_index = index;
81         m_name = name;
82     }
83     
84     /**
85      * Get the ID value from object being marshalled.
86      *
87      * @return ID value
88      */

89     protected abstract String JavaDoc getIdValue(Object JavaDoc item);
90     
91     /**
92      * Method which can be overridden to supply a different name for the ID
93      * reference attribute. The attribute name used by default is just "ref".
94      */

95     protected String JavaDoc getAttributeName() {
96         return "ref";
97     }
98     
99     /* (non-Javadoc)
100      * @see org.jibx.runtime.IMarshaller#isExtension(int)
101      */

102     public boolean isExtension(int index) {
103         return false;
104     }
105
106     /* (non-Javadoc)
107      * @see org.jibx.runtime.IMarshaller#marshal(java.lang.Object,
108      * org.jibx.runtime.IMarshallingContext)
109      */

110     public void marshal(Object JavaDoc obj, IMarshallingContext ictx)
111         throws JiBXException {
112         
113         // make sure the parameters are as expected
114
if (obj == null) {
115             return;
116         } else if (!(ictx instanceof MarshallingContext)) {
117             throw new JiBXException("Invalid context type for marshaller");
118         } else {
119             
120             // check if ID already defined
121
MarshallingContext ctx = (MarshallingContext)ictx;
122             HashMap JavaDoc map = ctx.getIdMap();
123             String JavaDoc id = getIdValue(obj);
124             Object JavaDoc value = map.get(id);
125             if (value == null) {
126                 if (obj instanceof IMarshallable) {
127                     
128                     // new id, write full representation and add to map
129
map.put(id, obj);
130                     ((IMarshallable)obj).marshal(ctx);
131                     
132                 } else {
133                     throw new JiBXException("Object of type " +
134                         obj.getClass().getName() + " is not marshallable");
135                 }
136             } else if (value.equals(obj)) {
137                 
138                 // generate reference to previously-defined item
139
ctx.startTagAttributes(m_index, m_name);
140                 ctx.attribute(0, getAttributeName(), id);
141                 ctx.closeStartEmpty();
142                 
143             } else {
144                 throw new JiBXException("Duplicate definition for ID " + id);
145             }
146         }
147     }
148
149     /* (non-Javadoc)
150      * @see org.jibx.runtime.IUnmarshaller#isPresent(org.jibx.runtime.IUnmarshallingContext)
151      */

152     public boolean isPresent(IUnmarshallingContext ictx) throws JiBXException {
153         return ictx.isAt(m_uri, m_name);
154     }
155
156     /* (non-Javadoc)
157      * @see org.jibx.runtime.IUnmarshaller#unmarshal(java.lang.Object,
158      * org.jibx.runtime.IUnmarshallingContext)
159      */

160     public Object JavaDoc unmarshal(Object JavaDoc obj, IUnmarshallingContext ictx)
161         throws JiBXException {
162         
163         // make sure we're at the appropriate start tag
164
UnmarshallingContext ctx = (UnmarshallingContext)ictx;
165         if (!ctx.isAt(m_uri, m_name)) {
166             return null;
167         } else {
168             
169             // check for reference to existing ID
170
String JavaDoc id = ctx.attributeText(null, getAttributeName(), null);
171             if (id == null) {
172                 
173                 // no ID value supplied, unmarshal full definition
174
obj = ctx.unmarshalElement();
175                 
176             } else {
177                 
178                 // find object based on ID
179
obj = ctx.findID(id, 0);
180                 ctx.parsePastEndTag(m_uri, m_name);
181                 if (obj == null) {
182                     ctx.throwStartTagException("Reference to undefined ID " +
183                         id);
184                 }
185             }
186         }
187         return obj;
188     }
189 }
Popular Tags