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.apache.bcel.Constants;
032: import org.jibx.binding.classes.BoundClass;
033: import org.jibx.binding.classes.ClassFile;
034: import org.jibx.binding.classes.ContextMethodBuilder;
035: import org.jibx.binding.classes.ExceptionMethodBuilder;
036: import org.jibx.runtime.JiBXException;
037:
038: /**
039: * Base class for mapping definitions. This is used for both normal and custom
040: * mappings. It handles adding the appropriate marshalling and/or unmarshalling
041: * interfaces and methods to the classes.
042: */
043: public abstract class MappingBase extends LinkableBase implements
044: IMapping {
045: //
046: // Constants and such related to code generation.
047:
048: // definitions for IMarshallable interface defined on mapped classes
049: protected static final String IMARSHALLABLE_INTERFACE = "org.jibx.runtime.IMarshallable";
050: protected static final String MARSHALLABLE_METHODNAME = "marshal";
051: protected static final String MARSHALLABLE_SIGNATURE = "(Lorg/jibx/runtime/IMarshallingContext;)V";
052: protected static final String GETINDEX_METHODNAME = "JiBX_getIndex";
053: protected static final String GETINDEX_SIGNATURE = "()I";
054: protected static final String CHECKEXTENDS_METHODNAME = "isExtension";
055: protected static final String CHECKEXTENDS_SIGNATURE = "(I)Z";
056:
057: // definitions for IUnmarshallable interface defined on mapped classes
058: protected static final String IUNMARSHALLABLE_INTERFACE = "org.jibx.runtime.IUnmarshallable";
059: protected static final String UNMARSHALLABLE_METHODNAME = "unmarshal";
060: protected static final String UNMARSHALLABLE_SIGNATURE = "(Lorg/jibx/runtime/IUnmarshallingContext;)V";
061:
062: // interface implemented by unmarshaller class
063: protected static final String UNMARSHALLER_INTERFACE = "org.jibx.runtime.IUnmarshaller";
064: protected static final String UNMARSHALLERUNMARSHAL_METHOD = "org.jibx.runtime.IUnmarshaller.unmarshal";
065: protected static final String UNMARSHALLERUNMARSHAL_SIGNATURE = "(Ljava/lang/Object;Lorg/jibx/runtime/IUnmarshallingContext;)"
066: + "Ljava/lang/Object;";
067:
068: // interface implemented by marshaller class
069: protected static final String MARSHALLER_INTERFACE = "org.jibx.runtime.IMarshaller";
070: protected static final String ABSTRACTMARSHALLER_INTERFACE = "org.jibx.runtime.IAbstractMarshaller";
071: protected static final String MARSHALLERMARSHAL_METHOD = "org.jibx.runtime.IMarshaller.marshal";
072: protected static final String MARSHALLERMARSHAL_SIGNATURE = "(Ljava/lang/Object;Lorg/jibx/runtime/IMarshallingContext;)V";
073:
074: // definitions for context methods used to find marshaller and unmarshaller
075: protected static final String GETMARSHALLER_METHOD = "org.jibx.runtime.IMarshallingContext.getMarshaller";
076: protected static final String GETMARSHALLER_SIGNATURE = "(ILjava/lang/String;)Lorg/jibx/runtime/IMarshaller;";
077: protected static final String GETUNMARSHALLER_METHOD = "org.jibx.runtime.IUnmarshallingContext.getUnmarshaller";
078: protected static final String GETUNMARSHALLER_SIGNATURE = "(I)Lorg/jibx/runtime/IUnmarshaller;";
079:
080: //
081: // Actual instance data.
082:
083: /** Index number for this particular binding definition. */
084: private final int m_indexNumber;
085:
086: /** Qualified type name, in text form. */
087: private final String m_typeName;
088:
089: /**
090: * Constructor. This version requires the component to be set later,
091: * using the {@link
092: * org.jibx.binding.def.PassThroughComponent#setWrappedComponent} method.
093: *
094: * @param contain containing binding definition structure
095: * @param type class name handled by mapping
096: * @param tname qualified type name, in text form
097: */
098: public MappingBase(IContainer contain, String type, String tname) {
099: String name = (tname == null) ? type : tname;
100: m_indexNumber = contain.getBindingRoot().getMappedClassIndex(
101: name);
102: m_typeName = tname;
103: }
104:
105: /**
106: * Constructor with wrapped component supplied.
107: *
108: * @param contain containing binding definition structure
109: * @param type class name handled by mapping
110: * @param tname qualified type name, in text form
111: * @param wrap wrapped binding component
112: */
113: public MappingBase(IContainer contain, String type, String tname,
114: IComponent wrap) {
115: this (contain, type, tname);
116: setWrappedComponent(wrap);
117: }
118:
119: /**
120: * Get the mapped class information. This must be implemented in each
121: * subclass to return the type of the bound class.
122: *
123: * @return information for mapped class
124: */
125: public abstract BoundClass getBoundClass();
126:
127: /**
128: * Generate marshallable interface methods for this mapping. This is not
129: * applicable to abstract mappings, since they cannot be marshalled as
130: * separate items.
131: *
132: * @throws JiBXException if error in generating code
133: */
134: protected void addIMarshallableMethod() throws JiBXException {
135:
136: // set up for constructing actual marshal method
137: BoundClass clas = getBoundClass();
138: ClassFile cf = clas.getMungedFile();
139: ContextMethodBuilder mb = new ContextMethodBuilder(
140: MARSHALLABLE_METHODNAME, MARSHALLABLE_SIGNATURE, cf,
141: Constants.ACC_PUBLIC, 0, clas.getClassFile().getName(),
142: 1, MARSHALLER_INTERFACE);
143:
144: // create call to marshalling context method with class index and
145: // actual class name
146: mb.loadContext();
147: mb.appendLoadConstant(getIndex());
148: mb.appendLoadConstant(cf.getName());
149: mb.appendCallInterface(GETMARSHALLER_METHOD,
150: GETMARSHALLER_SIGNATURE);
151:
152: // call the returned marshaller with this object and the marshalling
153: // context as parameters
154: mb.loadObject();
155: mb.loadContext();
156: mb.appendCallInterface(MARSHALLERMARSHAL_METHOD,
157: MARSHALLERMARSHAL_SIGNATURE);
158: mb.appendReturn();
159:
160: // add method to class
161: clas.getUniqueNamed(mb);
162:
163: // set up for constructing get index method
164: ExceptionMethodBuilder xb = new ExceptionMethodBuilder(
165: GETINDEX_METHODNAME, GETINDEX_SIGNATURE, cf,
166: Constants.ACC_PUBLIC);
167:
168: // generate code to return the constant index number
169: xb.appendLoadConstant(getIndex());
170: xb.appendReturn("int");
171:
172: // add the method and interface to class
173: clas.getUniqueNamed(xb);
174: clas.getClassFile().addInterface(IMARSHALLABLE_INTERFACE);
175: }
176:
177: /**
178: * Generate unmarshallable interface method for this mapping. This is not
179: * applicable to abstract mappings, since they cannot be unmarshalled as
180: * separate items.
181: *
182: * @throws JiBXException if error in generating code
183: */
184: protected void addIUnmarshallableMethod() throws JiBXException {
185:
186: // set up for constructing new method
187: BoundClass clas = getBoundClass();
188: ClassFile cf = clas.getMungedFile();
189: ContextMethodBuilder mb = new ContextMethodBuilder(
190: UNMARSHALLABLE_METHODNAME, UNMARSHALLABLE_SIGNATURE,
191: cf, Constants.ACC_PUBLIC, 0, clas.getClassFile()
192: .getName(), 1, UNMARSHALLER_INTERFACE);
193:
194: // create call to unmarshalling context method with class index
195: mb.loadContext();
196: mb.appendLoadConstant(getIndex());
197: mb.appendCallInterface(GETUNMARSHALLER_METHOD,
198: GETUNMARSHALLER_SIGNATURE);
199:
200: // call the returned unmarshaller with this object and the unmarshalling
201: // context as parameters
202: mb.loadObject();
203: mb.loadContext();
204: mb.appendCallInterface(UNMARSHALLERUNMARSHAL_METHOD,
205: UNMARSHALLERUNMARSHAL_SIGNATURE);
206: mb.appendReturn();
207:
208: // add the method and interface to class
209: clas.getUniqueNamed(mb);
210: clas.getClassFile().addInterface(IUNMARSHALLABLE_INTERFACE);
211: }
212:
213: //
214: // IMapping interface method definitions
215:
216: /* (non-Javadoc)
217: * @see org.jibx.binding.def.IMapping#getIndex()
218: */
219: public int getIndex() {
220: return m_indexNumber;
221: }
222:
223: /* (non-Javadoc)
224: * @see org.jibx.binding.def.IMapping#getTypeName()
225: */
226: public String getTypeName() {
227: return m_typeName;
228: }
229: }
|