001: /*
002: Copyright (c) 2003, Dennis M. Sosnoski
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without modification,
006: are permitted provided that the following conditions are met:
007:
008: * Redistributions of source code must retain the above copyright notice, this
009: list of conditions and the following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: * Neither the name of JiBX nor the names of its contributors may be used
014: to endorse or promote products derived from this software without specific
015: prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028:
029: package org.jibx.extras;
030:
031: import java.util.ArrayList;
032:
033: import org.jibx.runtime.IAliasable;
034: import org.jibx.runtime.IMarshallable;
035: import org.jibx.runtime.IMarshaller;
036: import org.jibx.runtime.IMarshallingContext;
037: import org.jibx.runtime.IUnmarshaller;
038: import org.jibx.runtime.IUnmarshallingContext;
039: import org.jibx.runtime.JiBXException;
040: import org.jibx.runtime.impl.MarshallingContext;
041: import org.jibx.runtime.impl.UnmarshallingContext;
042:
043: /**
044: * <p>Custom marshaller/unmarshaller for <code>Object[]</code> instances. This
045: * handles mapping arrays typed as <code>java.lang.Object[]</code>, where each
046: * item in the array must be of a mapped type. If a name is specified by the
047: * mapping definition that name is used as a wrapper around the elements
048: * representing the items in the array; otherwise, the elements are just handled
049: * inline.</p>
050: *
051: * @author Dennis M. Sosnoski
052: * @version 1.0
053: */
054:
055: public class ObjectArrayMapper implements IMarshaller, IUnmarshaller,
056: IAliasable {
057:
058: private static final Object[] DUMMY_ARRAY = {};
059:
060: private String m_uri;
061: private int m_index;
062: private String m_name;
063: private ArrayList m_holder;
064:
065: /**
066: * Default constructor. This just sets up for an XML representation with no
067: * element wrapping the actual item structures. It'll be used by JiBX when
068: * no name information is supplied by the mapping which references this
069: * custom marshaller/unmarshaller.
070: */
071:
072: public ObjectArrayMapper() {
073: m_uri = null;
074: m_index = 0;
075: m_name = null;
076: }
077:
078: /**
079: * Aliased constructor. This takes a name definition for the top-level
080: * wrapper element. It'll be used by JiBX when a name is supplied by the
081: * mapping which references this custom marshaller/unmarshaller.
082: *
083: * @param uri namespace URI for the top-level element
084: * @param index namespace index corresponding to the defined URI within the
085: * marshalling context definitions
086: * @param name local name for the top-level element
087: */
088:
089: public ObjectArrayMapper(String uri, int index, String name) {
090: m_uri = uri;
091: m_index = index;
092: m_name = name;
093: }
094:
095: /* (non-Javadoc)
096: * @see org.jibx.runtime.IMarshaller#isExtension(int)
097: */
098:
099: public boolean isExtension(int index) {
100: return false;
101: }
102:
103: /* (non-Javadoc)
104: * @see org.jibx.runtime.IMarshaller#marshal(java.lang.Object,
105: * org.jibx.runtime.IMarshallingContext)
106: */
107:
108: public void marshal(Object obj, IMarshallingContext ictx)
109: throws JiBXException {
110:
111: // make sure the parameters are as expected
112: if (obj == null) {
113: if (m_name == null) {
114: throw new JiBXException(
115: "null array not allowed without wrapper");
116: }
117: } else if (!(DUMMY_ARRAY.getClass().isInstance(obj))) {
118: throw new JiBXException(
119: "Invalid object type for marshaller");
120: } else if (!(ictx instanceof MarshallingContext)) {
121: throw new JiBXException(
122: "Invalid object type for marshaller");
123: } else {
124:
125: // start by generating start tag for container
126: MarshallingContext ctx = (MarshallingContext) ictx;
127: Object[] array = (Object[]) obj;
128: if (m_name != null) {
129: ctx.startTag(m_index, m_name);
130: }
131:
132: // loop through all entries in array
133: for (int i = 0; i < array.length; i++) {
134: Object item = array[i];
135: if (item instanceof IMarshallable) {
136: ((IMarshallable) item).marshal(ctx);
137: } else if (item == null) {
138: throw new JiBXException("Null value at offset " + i
139: + " not supported");
140: } else {
141: throw new JiBXException("Array value of type "
142: + item.getClass().getName() + " at offset "
143: + i + " is not marshallable");
144: }
145: }
146:
147: // finish with end tag for container element
148: if (m_name != null) {
149: ctx.endTag(m_index, m_name);
150: }
151:
152: }
153: }
154:
155: /* (non-Javadoc)
156: * @see org.jibx.runtime.IUnmarshaller#isPresent(org.jibx.runtime.IUnmarshallingContext)
157: */
158:
159: public boolean isPresent(IUnmarshallingContext ctx)
160: throws JiBXException {
161: return ctx.isAt(m_uri, m_name);
162: }
163:
164: /* (non-Javadoc)
165: * @see org.jibx.runtime.IUnmarshaller#unmarshal(java.lang.Object,
166: * org.jibx.runtime.IUnmarshallingContext)
167: */
168:
169: public Object unmarshal(Object obj, IUnmarshallingContext ictx)
170: throws JiBXException {
171:
172: // make sure we're at the appropriate start tag
173: UnmarshallingContext ctx = (UnmarshallingContext) ictx;
174: if (m_name != null) {
175: if (ctx.isAt(m_uri, m_name)) {
176: ctx.parsePastStartTag(m_uri, m_name);
177: } else {
178: return null;
179: }
180: }
181:
182: // create new array if needed
183: if (m_holder == null) {
184: m_holder = new ArrayList();
185: }
186:
187: // process all items present in document
188: while (!ctx.isEnd()) {
189: Object item = ctx.unmarshalElement();
190: m_holder.add(item);
191: }
192:
193: // discard close tag if used
194: if (m_name != null) {
195: ctx.parsePastEndTag(m_uri, m_name);
196: }
197:
198: // return array containing all items
199: Object[] result = m_holder.toArray();
200: m_holder.clear();
201: return result;
202: }
203: }
|