001: /*
002: Copyright (c) 2003-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.binding.def;
030:
031: import org.jibx.binding.classes.*;
032: import org.jibx.runtime.JiBXException;
033:
034: /**
035: * Linkage to generic object with defined marshaller and/or unmarshaller. This
036: * provides methods used to generate code for marshalling and unmarshalling
037: * objects of types unknown at binding time, so long as they have mappings
038: * defined.
039: *
040: * @author Dennis M. Sosnoski
041: * @version 1.0
042: */
043:
044: public class DirectGeneric implements IComponent {
045: //
046: // Constants and such related to code generation.
047:
048: private static final String ISEND_METHOD = "org.jibx.runtime.impl.UnmarshallingContext.isEnd";
049: private static final String ISEND_SIGNATURE = "()Z";
050: private static final String UNMARSHALELEMENT_METHOD = "org.jibx.runtime.impl.UnmarshallingContext.unmarshalElement";
051: private static final String UNMARSHALELEMENT_SIGNATURE = "()Ljava/lang/Object;";
052: private static final String MARSHALLABLE_INTERFACE = "org.jibx.runtime.IMarshallable";
053: private static final String MARSHALLABLE_METHOD = "org.jibx.runtime.IMarshallable.marshal";
054: private static final String MARSHALLABLE_SIGNATURE = "(Lorg/jibx/runtime/IMarshallingContext;)V";
055:
056: //
057: // Actual instance data.
058:
059: /** Type handled by this binding. */
060: private final String m_type;
061:
062: /** Optional property definition. */
063: private final PropertyDefinition m_property;
064:
065: /**
066: * Constructor without implicit property.
067: *
068: * @param parent containing binding definition structure
069: * @param type fully qualified class name of object type handled by this
070: * binding (<code>null</code> if unspecified)
071: */
072:
073: public DirectGeneric(IContainer parent, String type) {
074: m_type = (type == null) ? "java.lang.Object" : type;
075: m_property = null;
076: }
077:
078: /**
079: * Constructor with defined property.
080: *
081: * @param parent containing binding definition structure
082: * @param type fully qualified class name of object type handled by this
083: * binding (<code>null</code> if unspecified)
084: * @param prop associated property information
085: */
086:
087: public DirectGeneric(IContainer parent, String type,
088: PropertyDefinition prop) {
089: m_type = (type == null) ? "java.lang.Object" : type;
090: m_property = prop;
091: }
092:
093: /**
094: * Generate presence test code for this mapping. The generated code just
095: * checks that a start tag is next in the document, rather than an end tag.
096: *
097: * @param mb method builder
098: */
099:
100: public void genTestPresent(ContextMethodBuilder mb) {
101:
102: // append code to call unmarshalling context method to check for end tag
103: // as next in document, then invert the result
104: mb.loadContext();
105: mb.appendCallVirtual(ISEND_METHOD, ISEND_SIGNATURE);
106: mb.appendLoadConstant(1);
107: mb.appendIXOR();
108: }
109:
110: /**
111: * Generate unmarshalling code for this mapping. The generated code just
112: * calls the generic unmarshal element method, leaving the unmarshalled
113: * object on the stack (after casting it, if necessary, to the appropriate
114: * type).
115: * TODO: Instead call unmarshalling method with class passed directly, for
116: * better error reporting.
117: *
118: * @param mb method builder
119: */
120:
121: public void genUnmarshal(ContextMethodBuilder mb)
122: throws JiBXException {
123:
124: // check for optional property
125: BranchWrapper tosave = null;
126: if (m_property != null && m_property.isOptional()) {
127:
128: // generate code to check presence for the case of an optional
129: // item, with branch if so; if not present, set a null value
130: // with branch to be targeted at property store.
131: genTestPresent(mb);
132: BranchWrapper ifpres = mb.appendIFNE(this );
133: mb.appendACONST_NULL();
134: tosave = mb.appendUnconditionalBranch(this );
135: mb.targetNext(ifpres);
136: }
137:
138: // append code to call unmarshalling context method for generic element
139: mb.loadContext();
140: mb.appendCallVirtual(UNMARSHALELEMENT_METHOD,
141: UNMARSHALELEMENT_SIGNATURE);
142: mb.appendCreateCast(m_type);
143: mb.targetNext(tosave);
144: if (m_property != null && !m_property.isImplicit()
145: && !m_property.isThis()) {
146: mb.loadObject();
147: mb.appendSWAP();
148: m_property.genStore(mb);
149: }
150: }
151:
152: /**
153: * Generate marshalling code for this mapping. The generated code loads the
154: * object reference and casts it to the generic marshal interface, then
155: * calls the marshal method of that interface.
156: *
157: * @param mb method builder
158: */
159:
160: public void genMarshal(ContextMethodBuilder mb)
161: throws JiBXException {
162:
163: // append code to cast object and call generic marshal method
164: BranchWrapper toend = null;
165: if (m_property != null && !m_property.isImplicit()) {
166: mb.loadObject();
167: m_property.genLoad(mb);
168: if (m_property.isOptional()) {
169:
170: // generate code to check nonnull for the case of an optional item,
171: // with branch if so; if not present, just pop the copy with branch
172: // to be targeted past end.
173: mb.appendDUP();
174: BranchWrapper ifpres = mb.appendIFNONNULL(this );
175: mb.appendPOP();
176: toend = mb.appendUnconditionalBranch(this );
177: mb.targetNext(ifpres);
178: }
179: }
180: mb.appendCreateCast(MARSHALLABLE_INTERFACE);
181: mb.loadContext();
182: mb.appendCallInterface(MARSHALLABLE_METHOD,
183: MARSHALLABLE_SIGNATURE);
184: mb.targetNext(toend);
185: }
186:
187: //
188: // IComponent interface method definitions
189:
190: public boolean isOptional() {
191: return false;
192: }
193:
194: public boolean hasAttribute() {
195: return false;
196: }
197:
198: public void genAttrPresentTest(ContextMethodBuilder mb) {
199: throw new IllegalStateException(
200: "Internal error - no attributes defined");
201: }
202:
203: public void genAttributeUnmarshal(ContextMethodBuilder mb) {
204: throw new IllegalStateException(
205: "Internal error - no attributes defined");
206: }
207:
208: public void genAttributeMarshal(ContextMethodBuilder mb) {
209: throw new IllegalStateException(
210: "Internal error - no attributes defined");
211: }
212:
213: public boolean hasContent() {
214: return true;
215: }
216:
217: public void genContentPresentTest(ContextMethodBuilder mb)
218: throws JiBXException {
219: genTestPresent(mb);
220: }
221:
222: public void genContentUnmarshal(ContextMethodBuilder mb)
223: throws JiBXException {
224: genUnmarshal(mb);
225: }
226:
227: public void genContentMarshal(ContextMethodBuilder mb)
228: throws JiBXException {
229: genMarshal(mb);
230: }
231:
232: public void genNewInstance(ContextMethodBuilder mb) {
233: throw new IllegalStateException(
234: "Internal error - no instance creation");
235: }
236:
237: public String getType() {
238: return MARSHALLABLE_INTERFACE;
239: }
240:
241: public boolean hasId() {
242: return false;
243: }
244:
245: public void genLoadId(ContextMethodBuilder mb) {
246: throw new IllegalStateException(
247: "Internal error - no ID allowed");
248: }
249:
250: public NameDefinition getWrapperName() {
251: return null;
252: }
253:
254: public void setLinkages() {
255: }
256:
257: // DEBUG
258: public void print(int depth) {
259: BindingDefinition.indent(depth);
260: System.out.println("direct generic reference");
261: }
262: }
|