001: /*
002: Copyright (c) 2005, 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 org.jibx.runtime.IAliasable;
032: import org.jibx.runtime.IMarshaller;
033: import org.jibx.runtime.IMarshallingContext;
034: import org.jibx.runtime.IUnmarshaller;
035: import org.jibx.runtime.IUnmarshallingContext;
036: import org.jibx.runtime.JiBXException;
037: import org.jibx.runtime.impl.MarshallingContext;
038: import org.jibx.runtime.impl.UnmarshallingContext;
039:
040: /**
041: * <p>Abstract base custom marshaller/unmarshaller for an object reference. This
042: * marshals the reference as an empty element with a single IDREF attribute, and
043: * unmarshals an element with the same structure to create a reference to the
044: * object with that ID value. To use this class you need to create a subclass
045: * with a constructor using the same signature as the one provided (calling the
046: * base class constructor from your subclass constructor) and implement the
047: * abstract {@link #getIdValue} method in your subclass. You can also override
048: * the provided {@link #getAttributeName} method to change the name used for the
049: * IDREF attribute. Note that this class can only be used when the definitions
050: * precede the references in the XML document; if a referenced ID is not defined
051: * the unmarshaller throws an exception.</p>
052: *
053: * @author Dennis M. Sosnoski
054: * @version 1.0
055: */
056:
057: public abstract class IdRefMapperBase implements IMarshaller,
058: IUnmarshaller, IAliasable {
059:
060: private String m_uri;
061: private int m_index;
062: private String m_name;
063:
064: /**
065: * Aliased constructor taking a name definition for the element. The
066: * subclass version will be used by JiBX to define the element name to be
067: * used with this custom marshaller/unmarshaller.
068: *
069: * @param uri namespace URI for the top-level element
070: * @param index namespace index corresponding to the defined URI within the
071: * marshalling context definitions
072: * @param name local name for the top-level element
073: */
074: public IdRefMapperBase(String uri, int index, String name) {
075: m_uri = uri;
076: m_index = index;
077: m_name = name;
078: }
079:
080: /**
081: * Get the ID value from object being marshalled.
082: *
083: * @return ID value
084: */
085: protected abstract String getIdValue(Object item);
086:
087: /**
088: * Method which can be overridden to supply a different name for the ID
089: * reference attribute. The attribute name used by default is just "ref".
090: */
091: protected String getAttributeName() {
092: return "ref";
093: }
094:
095: /* (non-Javadoc)
096: * @see org.jibx.runtime.IMarshaller#isExtension(int)
097: */
098: public boolean isExtension(int index) {
099: return false;
100: }
101:
102: /* (non-Javadoc)
103: * @see org.jibx.runtime.IMarshaller#marshal(java.lang.Object,
104: * org.jibx.runtime.IMarshallingContext)
105: */
106: public void marshal(Object obj, IMarshallingContext ictx)
107: throws JiBXException {
108:
109: // make sure the parameters are as expected
110: if (obj == null) {
111: return;
112: } else if (!(ictx instanceof MarshallingContext)) {
113: throw new JiBXException(
114: "Invalid context type for marshaller");
115: } else {
116:
117: // generate the element start tag
118: MarshallingContext ctx = (MarshallingContext) ictx;
119: ctx.startTagAttributes(m_index, m_name);
120:
121: // add attribute reference to object ID
122: ctx.attribute(0, getAttributeName(), getIdValue(obj));
123:
124: // close start tag for empty element
125: ctx.closeStartEmpty();
126: }
127: }
128:
129: /* (non-Javadoc)
130: * @see org.jibx.runtime.IUnmarshaller#isPresent(org.jibx.runtime.IUnmarshallingContext)
131: */
132: public boolean isPresent(IUnmarshallingContext ctx)
133: throws JiBXException {
134: return ctx.isAt(m_uri, m_name);
135: }
136:
137: /* (non-Javadoc)
138: * @see org.jibx.runtime.IUnmarshaller#unmarshal(java.lang.Object,
139: * org.jibx.runtime.IUnmarshallingContext)
140: */
141: public Object unmarshal(Object obj, IUnmarshallingContext ictx)
142: throws JiBXException {
143:
144: // make sure we're at the appropriate start tag
145: UnmarshallingContext ctx = (UnmarshallingContext) ictx;
146: if (!ctx.isAt(m_uri, m_name)) {
147: return null;
148: }
149:
150: // get object reference for ID
151: obj = ctx.attributeExistingIDREF(null, getAttributeName(), 0);
152:
153: // skip past the element
154: ctx.parsePastEndTag(m_uri, m_name);
155: return obj;
156: }
157: }
|