001: /*
002: Copyright (c) 2003-2007, 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: * Property reference with binding defined by component. This handles loading
036: * and storing the property value, calling the wrapped component methods for
037: * everything else.
038: *
039: * @author Dennis M. Sosnoski
040: */
041: public class ComponentProperty extends PassThroughComponent {
042: /** Property definition. */
043: private final PropertyDefinition m_property;
044:
045: /** Skip marshalling code tests flag. */
046: private boolean m_skipMarshal;
047:
048: /** Fake content to force unmarshal to create an object. */
049: private boolean m_forceUnmarshal;
050:
051: /**
052: * Constructor.
053: *
054: * @param prop actual property definition
055: * @param impl component that defines marshalling and unmarshalling
056: * @param skip flag for marshalling code tests to be skipped
057: */
058:
059: public ComponentProperty(PropertyDefinition prop, IComponent impl,
060: boolean skip) {
061: super (impl);
062: m_property = prop;
063: m_skipMarshal = skip;
064: }
065:
066: /**
067: * Set flag for skipping marshalling presence test code generation.
068: *
069: * @param skip <code>true</code> if skipping, <code>false</code> if not
070: */
071: public void setSkipping(boolean skip) {
072: m_skipMarshal = skip;
073: }
074:
075: /**
076: * Set flag to force unmarshalling to create an object.
077: *
078: * @param force <code>true</code> if skipping, <code>false</code> if not
079: */
080: public void setForceUnmarshal(boolean force) {
081: m_forceUnmarshal = force;
082: }
083:
084: /**
085: * Get the property information. This is a kludge used by the ElementWrapper
086: * code to store a <code>null</code> value directly to the property when
087: * unmarshalling a missing or xsi:nil element.
088: *
089: * @return property information
090: */
091: public PropertyDefinition getProperty() {
092: return m_property;
093: }
094:
095: //
096: // IComponent interface method definitions (overrides of defaults)
097:
098: public boolean isOptional() {
099: return m_property.isOptional();
100: }
101:
102: public boolean hasContent() {
103: return m_forceUnmarshal || super .hasContent();
104: }
105:
106: public void genAttributeUnmarshal(ContextMethodBuilder mb)
107: throws JiBXException {
108:
109: // start by generating code to load owning object so can finish by
110: // storing to property
111: if (!m_property.isImplicit() && !m_property.isThis()) {
112: mb.loadObject();
113: }
114: BranchWrapper ifpres = null;
115: BranchWrapper tosave = null;
116: if (m_property.isOptional()) {
117:
118: // generate code to check presence for the case of an optional item,
119: // with branch if so; if not present, set a null value with branch
120: // to be targeted at property store.
121: m_component.genAttrPresentTest(mb);
122: ifpres = mb.appendIFNE(this );
123: mb.appendACONST_NULL();
124: tosave = mb.appendUnconditionalBranch(this );
125: }
126:
127: // generate unmarshalling code for not optional, or optional and
128: // present; get existing instance or create a new one and handle
129: // attribute unmarshalling
130: mb.targetNext(ifpres);
131: if (m_property.isImplicit()) {
132: m_component.genNewInstance(mb);
133: } else if (!m_property.isThis()) {
134:
135: // load current value, cast, copy, and test for non-null
136: mb.loadObject();
137: m_property.genLoad(mb);
138: mb.appendCreateCast(m_property.getGetValueType(),
139: m_component.getType());
140: mb.appendDUP();
141: BranchWrapper haveinst = mb.appendIFNONNULL(this );
142:
143: // current value null, pop copy and create a new instance
144: mb.appendPOP();
145: m_component.genNewInstance(mb);
146: mb.targetNext(haveinst);
147: }
148: m_component.genAttributeUnmarshal(mb);
149:
150: // convert the type if necessary, then store result to property
151: mb.appendCreateCast(m_component.getType(), m_property
152: .getSetValueType());
153: mb.targetNext(tosave);
154: if (!m_property.isImplicit() && !m_property.isThis()) {
155: m_property.genStore(mb);
156: }
157: }
158:
159: public void genAttributeMarshal(ContextMethodBuilder mb)
160: throws JiBXException {
161: if (m_skipMarshal) {
162:
163: // just generate pass-through marshal code generation
164: m_component.genAttributeMarshal(mb);
165:
166: } else {
167:
168: // start by generating code to load the actual object reference
169: if (!m_property.isImplicit()) {
170: mb.loadObject();
171: m_property.genLoad(mb);
172: }
173: BranchWrapper ifpres = null;
174: BranchWrapper toend = null;
175: if (m_property.isOptional()) {
176:
177: // generate code to check nonnull for the case of an optional item,
178: // with branch if so; if not present, just pop the copy with branch
179: // to be targeted past end.
180: mb.appendDUP();
181: ifpres = mb.appendIFNONNULL(this );
182: mb.appendPOP();
183: toend = mb.appendUnconditionalBranch(this );
184: }
185:
186: // generate code for actual marshalling if not optional, or optional and
187: // nonnull; then finish by setting target for optional with
188: // null value case
189: mb.targetNext(ifpres);
190: m_component.genAttributeMarshal(mb);
191: mb.targetNext(toend);
192: }
193: }
194:
195: public void genContentUnmarshal(ContextMethodBuilder mb)
196: throws JiBXException {
197:
198: // check for both attribute and content components
199: if (m_component.hasAttribute()) {
200:
201: // start with code to load reference from attribute unmarshalling
202: if (!m_property.isImplicit()) {
203: mb.loadObject();
204: m_property.genLoad(mb);
205: } else {
206: mb.appendDUP();
207: }
208: BranchWrapper toend = null;
209: if (m_property.isOptional()) {
210:
211: // generate code to check value defined for the case of an
212: // optional item, with branch if so; if not present, just pop
213: // the copy with branch to be targeted past end.
214: toend = mb.appendIFNULL(this );
215: if (!m_property.isImplicit()) {
216: mb.loadObject();
217: m_property.genLoad(mb);
218: } else {
219: mb.appendDUP();
220: }
221: }
222:
223: // follow up in case where present with unmarshalling content
224: m_component.genContentUnmarshal(mb);
225: mb.appendPOP();
226: mb.targetNext(toend);
227:
228: } else {
229:
230: // start by generating code to load owning object so can finish by
231: // storing to property
232: if (!m_property.isImplicit() && !m_property.isThis()) {
233: mb.loadObject();
234: }
235: BranchWrapper ifpres = null;
236: BranchWrapper tosave = null;
237: if (m_property.isOptional() && !m_forceUnmarshal) {
238:
239: // generate code to check presence for the case of an optional
240: // item, with branch if so; if not present, set a null value
241: // with branch to be targeted at property store.
242: m_component.genContentPresentTest(mb);
243: ifpres = mb.appendIFNE(this );
244: mb.appendACONST_NULL();
245: tosave = mb.appendUnconditionalBranch(this );
246: }
247:
248: // generate unmarshalling code for not optional, or optional and
249: // present; get existing instance or create a new one and handle
250: // content unmarshalling
251: mb.targetNext(ifpres);
252: if (m_property.isImplicit()) {
253: m_component.genNewInstance(mb);
254: } else if (!m_property.isThis()) {
255:
256: // load current value, cast, copy, and test for non-null
257: mb.loadObject();
258: m_property.genLoad(mb);
259: mb.appendCreateCast(m_property.getGetValueType(),
260: m_component.getType());
261: mb.appendDUP();
262: BranchWrapper haveinst = mb.appendIFNONNULL(this );
263:
264: // current value null, pop copy and create a new instance
265: mb.appendPOP();
266: m_component.genNewInstance(mb);
267: mb.targetNext(haveinst);
268: }
269: if (!m_forceUnmarshal) {
270: m_component.genContentUnmarshal(mb);
271: }
272:
273: // convert the type if necessary, then store result to property
274: mb.appendCreateCast(m_component.getType(), m_property
275: .getSetValueType());
276: mb.targetNext(tosave);
277: if (!m_property.isImplicit() && !m_property.isThis()) {
278: m_property.genStore(mb);
279: }
280: }
281: }
282:
283: public void genContentMarshal(ContextMethodBuilder mb)
284: throws JiBXException {
285: if (m_forceUnmarshal) {
286: mb.appendPOP();
287: } else {
288: if (m_skipMarshal) {
289:
290: // just generate pass-through marshal code generation
291: m_component.genContentMarshal(mb);
292:
293: } else {
294:
295: // start by generating code to load the actual object reference
296: if (!m_property.isImplicit()) {
297: mb.loadObject();
298: m_property.genLoad(mb);
299: }
300: BranchWrapper ifpres = null;
301: BranchWrapper tonext = null;
302: if (m_property.isOptional()) {
303:
304: // generate code to check nonull for the case of an optional item,
305: // with branch if so; if not present, just pop the copy with branch
306: // to be targeted past end.
307: mb.appendDUP();
308: ifpres = mb.appendIFNONNULL(this );
309: mb.appendPOP();
310: tonext = mb.appendUnconditionalBranch(this );
311: }
312:
313: // generate code for actual marshalling if not optional, or optional and
314: // nonnull; then finish by setting target for optional with null value
315: // case
316: mb.targetNext(ifpres);
317: m_component.genContentMarshal(mb);
318: mb.targetNext(tonext);
319:
320: }
321: }
322: }
323:
324: // DEBUG
325: public void print(int depth) {
326: BindingDefinition.indent(depth);
327: System.out.print("component " + m_property.toString());
328: if (m_skipMarshal) {
329: System.out.print(" (pass-through marshal)");
330: }
331: System.out.println();
332: m_component.print(depth + 1);
333: }
334: }
|