KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > binding > def > BindingDefinition


1 /*
2 Copyright (c) 2003-2005, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.binding.def;
30
31 import java.io.File JavaDoc;
32 import java.util.ArrayList JavaDoc;
33
34 import org.apache.bcel.Constants;
35 import org.apache.bcel.generic.ArrayType;
36 import org.apache.bcel.generic.Type;
37 import org.jibx.binding.classes.BoundClass;
38 import org.jibx.binding.classes.BranchWrapper;
39 import org.jibx.binding.classes.ClassCache;
40 import org.jibx.binding.classes.ClassFile;
41 import org.jibx.binding.classes.ClassItem;
42 import org.jibx.binding.classes.ExceptionMethodBuilder;
43 import org.jibx.binding.classes.MethodBuilder;
44 import org.jibx.binding.classes.MungedClass;
45 import org.jibx.binding.util.ArrayMap;
46 import org.jibx.runtime.IBindingFactory;
47 import org.jibx.runtime.JiBXException;
48
49 /**
50  * Binding definition. This is the root of the object graph for a binding.
51  *
52  * @author Dennis M. Sosnoski
53  * @version 1.0
54  */

55
56 public class BindingDefinition extends BindingBuilder.ContainerBase
57 implements IContainer
58 {
59     //
60
// Miscellaneous static data.
61

62     /** Current distribution file name. This is filled in by the Ant build
63      process to match the current distribution. */

64     public static final String JavaDoc CURRENT_VERSION_NAME = "jibx-rc0";
65     
66     /** Prefix used in all code generation for methods and classes. */
67     public static final String JavaDoc GENERATE_PREFIX = "JiBX_";
68     
69     /** Default prefix for automatic ID generation. */
70     /*package*/ static final String JavaDoc DEFAULT_AUTOPREFIX = "id_";
71     
72     /** Table of defined bindings. */
73     private static ArrayList JavaDoc s_bindings;
74     
75     /** Classes included in any binding. */
76     private static ArrayMap s_mappedClasses;
77     
78     //
79
// Static instances of predefined conversions.
80
private static StringConversion s_byteConversion =
81         new PrimitiveStringConversion(Byte.TYPE, new Byte JavaDoc((byte)0), "B",
82         "serializeByte", "parseByte", "attributeByte", "parseElementByte");
83     private static StringConversion s_charConversion =
84         new PrimitiveStringConversion(Character.TYPE, new Character JavaDoc((char)0),
85         "C", "serializeChar", "parseChar", "attributeChar", "parseElementChar");
86     private static StringConversion s_doubleConversion =
87         new PrimitiveStringConversion(Double.TYPE, new Double JavaDoc(0.0d), "D",
88         "serializeDouble", "parseDouble", "attributeDouble",
89         "parseElementDouble");
90     private static StringConversion s_floatConversion =
91         new PrimitiveStringConversion(Float.TYPE, new Float JavaDoc(0.0f), "F",
92         "serializeFloat", "parseFloat", "attributeFloat", "parseElementFloat");
93     private static StringConversion s_intConversion =
94         new PrimitiveStringConversion(Integer.TYPE, new Integer JavaDoc(0), "I",
95         "serializeInt", "parseInt", "attributeInt", "parseElementInt");
96     private static StringConversion s_longConversion =
97         new PrimitiveStringConversion(Long.TYPE, new Long JavaDoc(0L), "J",
98         "serializeLong", "parseLong", "attributeLong", "parseElementLong");
99     private static StringConversion s_shortConversion =
100         new PrimitiveStringConversion(Short.TYPE, new Short JavaDoc((short)0), "S",
101         "serializeShort", "parseShort", "attributeShort", "parseElementShort");
102     private static StringConversion s_booleanConversion =
103         new PrimitiveStringConversion(Boolean.TYPE, Boolean.FALSE, "Z",
104         "serializeBoolean", "parseBoolean", "attributeBoolean",
105         "parseElementBoolean");
106     private static StringConversion s_dateConversion =
107         new ObjectStringConversion(null,
108         "org.jibx.runtime.Utility.serializeDateTime",
109         "org.jibx.runtime.Utility.deserializeDateTime", "java.util.Date");
110     private static StringConversion s_sqlDateConversion =
111         new ObjectStringConversion(null,
112         "org.jibx.runtime.Utility.serializeSqlDate",
113         "org.jibx.runtime.Utility.deserializeSqlDate", "java.sql.Date");
114     private static StringConversion s_sqlTimeConversion =
115         new ObjectStringConversion(null,
116         "org.jibx.runtime.Utility.serializeSqlTime",
117         "org.jibx.runtime.Utility.deserializeSqlTime", "java.sql.Time");
118     private static StringConversion s_timestampConversion =
119         new ObjectStringConversion(null,
120         "org.jibx.runtime.Utility.serializeTimestamp",
121         "org.jibx.runtime.Utility.deserializeTimestamp", "java.sql.Timestamp");
122     public static StringConversion s_base64Conversion =
123         new ObjectStringConversion(null,
124         "org.jibx.runtime.Utility.serializeBase64",
125         "org.jibx.runtime.Utility.deserializeBase64", "byte[]");
126     
127     public static StringConversion s_stringConversion =
128         new ObjectStringConversion(null, null, null, "java.lang.String");
129     public static StringConversion s_objectConversion =
130         new ObjectStringConversion(null, null, null, "java.lang.Object");
131     
132     //
133
// Constants for code generation
134

135     private static final String JavaDoc FACTORY_SUFFIX = "Factory";
136     private static final String JavaDoc FACTORY_INTERFACE =
137         "org.jibx.runtime.IBindingFactory";
138     private static final String JavaDoc[] FACTORY_INTERFACES =
139     {
140         FACTORY_INTERFACE
141     };
142     private static final String JavaDoc FACTORY_INSTNAME = "m_inst";
143     private static final int FACTORY_INSTACCESS =
144         Constants.ACC_PRIVATE | Constants.ACC_STATIC;
145     private static final String JavaDoc MARSHALLER_ARRAYNAME = "m_marshallers";
146     private static final String JavaDoc UNMARSHALLER_ARRAYNAME = "m_unmarshallers";
147     private static final String JavaDoc STRING_ARRAYTYPE = "java.lang.String[]";
148     private static final String JavaDoc CLASSES_ARRAYNAME = "m_classes";
149     private static final String JavaDoc URIS_ARRAYNAME = "m_uris";
150     private static final String JavaDoc GNAMES_ARRAYNAME = "m_globalNames";
151     private static final String JavaDoc GURIS_ARRAYNAME = "m_globalUris";
152     private static final String JavaDoc IDNAMES_ARRAYNAME = "m_idNames";
153     private static final String JavaDoc CREATEMARSHAL_METHODNAME =
154         "createMarshallingContext";
155     private static final String JavaDoc MARSHALCONTEXT_INTERFACE =
156         "org.jibx.runtime.IMarshallingContext";
157     private static final String JavaDoc MARSHALCONTEXT_IMPLEMENTATION =
158         "org.jibx.runtime.impl.MarshallingContext";
159     private static final String JavaDoc MARSHALCONTEXTINIT_SIGNATURE =
160         "([Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V";
161     private static final String JavaDoc CREATEUNMARSHAL_METHODNAME =
162         "createUnmarshallingContext";
163     private static final String JavaDoc UNMARSHALCONTEXT_INTERFACE =
164         "org.jibx.runtime.IUnmarshallingContext";
165     private static final String JavaDoc UNMARSHALCONTEXT_IMPLEMENTATION =
166         "org.jibx.runtime.impl.UnmarshallingContext";
167     private static final String JavaDoc UNMARSHALCONTEXTINIT_SIGNATURE =
168         "(I[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;" +
169         "[Ljava/lang/String;)V";
170     private static final String JavaDoc GETINST_METHODNAME = "getInstance";
171     private static final String JavaDoc UNSUPPORTED_EXCEPTION_CLASS =
172         "java.lang.UnsupportedOperationException";
173     private static final String JavaDoc GETVERSION_METHODNAME = "getCompilerVersion";
174     private static final String JavaDoc GETDISTRIB_METHODNAME =
175         "getCompilerDistribution";
176     private static final String JavaDoc GETDEFINEDNSS_METHODNAME = "getNamespaces";
177     private static final String JavaDoc GETCLASSES_METHODNAME = "getMappedClasses";
178     private static final String JavaDoc GETELEMENTNSS_METHODNAME =
179         "getElementNamespaces";
180     private static final String JavaDoc GETELEMENTNAMES_METHODNAME = "getElementNames";
181
182     //
183
// Actual instance data
184

185     /** Binding name. */
186     private final String JavaDoc m_name;
187     
188     /** Index number of this binding. */
189     private final int m_index;
190
191     /** Input binding flag. */
192     private final boolean m_isInput;
193
194     /** Output binding flag. */
195     private final boolean m_isOutput;
196
197     /** Use global ID values flag. */
198     private final boolean m_isIdGlobal;
199
200     /** Support forward references to IDs flag. */
201     private final boolean m_isForwards;
202
203     /** Generate souce tracking interface flag. */
204     private final boolean m_isTrackSource;
205
206     /** Prefix used for auto-generated ID values. */
207     private final String JavaDoc m_autoPrefix;
208
209     /** Package for generated context factory. */
210     private String JavaDoc m_targetPackage;
211     
212     /** File root for generated context factory. */
213     private File JavaDoc m_targetRoot;
214     
215     /** Classes using unique (per class) identifiers. This is <code>null</code>
216      and unused when using global ID values. */

217     private ArrayMap m_uniqueIds;
218     
219     /** Namespaces URIs included in binding. */
220     private ArrayMap m_namespaceUris;
221     
222     /** Outer definition context with default definitions. */
223     private DefinitionContext m_outerContext;
224     
225     /** Inner definition context constructed for binding. */
226     private DefinitionContext m_activeContext;
227     
228     /** Flag for done assigning indexes to mapped classes. */
229     private boolean m_isMappedDone;
230     
231     /** Next index number for marshaller/unmarshaller slots used in-line. */
232     private int m_mumIndex;
233     
234     /** Classes handled by in-line marshaller/unmarshaller references. */
235     private ArrayList JavaDoc m_extraClasses;
236     
237     /** Marshaller classes used in-line. */
238     private ArrayList JavaDoc m_extraMarshallers;
239     
240     /** Unmarshaller classes used in-line. */
241     private ArrayList JavaDoc m_extraUnmarshallers;
242
243     /**
244      * Constructor. Sets all defaults, including the default name provided, and
245      * initializes the definition context for the outermost level of the
246      * binding.
247      *
248      * @param name binding name
249      * @param ibind input binding flag
250      * @param obind output binding flag
251      * @param auto prefix for auto-generated ID values
252      * @param glob global IDs flag
253      * @param forward support forward referenced IDs flag
254      * @param source add source tracking for unmarshalled objects flag
255      * @throws JiBXException if error in transformation
256      */

257
258     public BindingDefinition(String JavaDoc name, boolean ibind, boolean obind,
259         String JavaDoc auto, boolean glob, boolean forward, boolean source)
260         throws JiBXException {
261         
262         // handle basic initialization
263
super(null);
264         m_name = name;
265         m_isInput = ibind;
266         m_isOutput = obind;
267         m_isIdGlobal = glob;
268         m_isForwards = forward;
269         m_isTrackSource = source;
270         m_autoPrefix = auto;
271         
272         // set base class defaults
273
m_styleDefault = ValueChild.ELEMENT_STYLE;
274         m_autoLink = BindingBuilder.LINK_FIELDS;
275         m_accessLevel = BindingBuilder.ACC_PRIVATE;
276         m_nameStyle = BindingBuilder.NAME_HYPHENS;
277         
278         // initialize the contexts
279
m_outerContext = m_activeContext = new DefinitionContext(this);
280         m_activeContext = new DefinitionContext(this);
281         m_namespaceUris = new ArrayMap();
282         m_namespaceUris.findOrAdd("");
283         m_outerContext.addNamespace(NamespaceDefinition.buildNamespace
284             ("http://www.w3.org/XML/1998/namespace", "xml"));
285         
286         // build the default converters in outer context
287
m_outerContext.setDefaultConversion("byte:default", s_byteConversion);
288         m_outerContext.setDefaultConversion("char:default", s_charConversion);
289         StringConversion schar = s_charConversion.derive("char",
290             "org.jibx.runtime.Utility.serializeCharString",
291             "org.jibx.runtime.Utility.parseCharString", null);
292         m_outerContext.setNamedConversion("char:string", schar);
293         m_outerContext.setDefaultConversion("double:default",
294             s_doubleConversion);
295         m_outerContext.setDefaultConversion("float:default", s_floatConversion);
296         m_outerContext.setDefaultConversion("int:default", s_intConversion);
297         m_outerContext.setDefaultConversion("long:default", s_longConversion);
298         m_outerContext.setDefaultConversion("short:default", s_shortConversion);
299         m_outerContext.setDefaultConversion("boolean:default",
300             s_booleanConversion);
301         m_outerContext.setDefaultConversion("Date:default", s_dateConversion);
302         m_outerContext.setDefaultConversion("SqlDate:default",
303             s_sqlDateConversion);
304         m_outerContext.setDefaultConversion("SqlTime:default",
305             s_sqlTimeConversion);
306         m_outerContext.setDefaultConversion("Timestamp:default",
307             s_timestampConversion);
308         m_outerContext.setDefaultConversion("byte[]:default",
309             s_base64Conversion);
310         m_outerContext.setDefaultConversion("String:default",
311             s_stringConversion);
312         m_outerContext.setDefaultConversion("Object:default",
313             s_objectConversion);
314         
315         // add this binding to list
316
m_index = s_bindings.size();
317         s_bindings.add(this);
318     }
319     
320     /**
321      * Get class linked to binding element. Implementation of
322      * {@link org.jibx.binding.def.IContainer} interface, just returns
323      * <code>null</code> in this case.
324      *
325      * @return information for class linked by binding
326      */

327
328     public BoundClass getBoundClass() {
329         return null;
330     }
331
332     /**
333      * Get default style for value expression. Implementation of
334      * {@link org.jibx.binding.def.IContainer} interface.
335      *
336      * @return default style type for values
337      */

338
339     public int getStyleDefault() {
340         return m_styleDefault;
341     }
342
343     /**
344      * Set ID property. This parent binding component interface method should
345      * never be called for the binding definition, and will throw a runtime
346      * exception if it is called.
347      *
348      * @param child child defining the ID property
349      * @return <code>false</code>
350      */

351
352     public boolean setIdChild(IComponent child) {
353         throw new IllegalStateException JavaDoc("Internal error - setIdChild for root");
354     }
355
356     /**
357      * Get default package used for code generation.
358      *
359      * @return default code generation package
360      */

361
362     public String JavaDoc getDefaultPackage() {
363         return m_targetPackage;
364     }
365
366     /**
367      * Get root directory for default code generation package.
368      *
369      * @return root for default code generation
370      */

371
372     public File JavaDoc getDefaultRoot() {
373         return m_targetRoot;
374     }
375
376     /**
377      * Set location for binding factory class generation.
378      *
379      * @param tpack target package for generated context factory
380      * @param root target root for generated context factory
381      */

382
383     public void setFactoryLocation(String JavaDoc tpack, File JavaDoc root) {
384         m_targetPackage = tpack;
385         m_targetRoot = root;
386     }
387
388     /**
389      * Get index number of binding.
390      *
391      * @return index number for this binding definition
392      */

393
394     public int getIndex() {
395         return m_index;
396     }
397
398     /**
399      * Check if binding is defined for unmarshalling.
400      *
401      * @return <code>true</code> if defined, <code>false</code> if not
402      */

403
404     public boolean isInput() {
405         return m_isInput;
406     }
407
408     /**
409      * Check if binding is defined for marshalling.
410      *
411      * @return <code>true</code> if defined, <code>false</code> if not
412      */

413
414     public boolean isOutput() {
415         return m_isOutput;
416     }
417
418     /**
419      * Check if global ids are used by binding.
420      *
421      * @return <code>true</code> if defined, <code>false</code> if not
422      */

423
424     public boolean isIdGlobal() {
425         return m_isIdGlobal;
426     }
427
428     /**
429      * Check if forward ids are supported by unmarshalling binding.
430      *
431      * @return <code>true</code> if supported, <code>false</code> if not
432      */

433
434     public boolean isForwards() {
435         return m_isForwards;
436     }
437
438     /**
439      * Check if source tracking is supported by unmarshalling binding.
440      *
441      * @return <code>true</code> if defined, <code>false</code> if not
442      */

443
444     public boolean isTrackSource() {
445         return m_isTrackSource;
446     }
447
448     /**
449      * Get prefix for method or class generation.
450      *
451      * @return prefix for names created by this binding
452      */

453
454     public String JavaDoc getPrefix() {
455         return GENERATE_PREFIX + m_name;
456     }
457
458     /**
459      * Get index for mapped class from binding. If the class is not already
460      * included in any binding it is first added to the list of bound classes.
461      * All bindings use the same index numbers to allow easy lookup of the
462      * appropriate marshaller and unmarshaller within a particular binding, but
463      * this does mean that all bindings dealing with a common set of classes
464      * need to be compiled together. This uses the same sequence of values as
465      * the {@link #getMarshallerUnmarshallerIndex} method but differs in that
466      * the values returned by this method are unique per class. This method is
467      * intended for use with &lt;mapping&gt; definitions. It is an error to call
468      * this method after calling the {@link #getMarshallerUnmarshallerIndex}
469      * method.
470      *
471      * @param name fully qualified name of mapped class
472      * @return index number of class
473      */

474
475     public int getMappedClassIndex(String JavaDoc name) {
476         if (m_isMappedDone) {
477             throw new IllegalStateException JavaDoc
478                 ("Internal error: Call out of sequence");
479         } else {
480             return s_mappedClasses.findOrAdd(name);
481         }
482     }
483
484     /**
485      * Get marshaller/unmarshaller slot index in binding. This uses the same
486      * sequence of values as the {@link #getMappedClassIndex} method but differs
487      * in that the same class may have more than one marshaller/unmarshaller
488      * slot defined. It's intended for user-defined marshallers/unmarshallers
489      * where use is specific to a particular context. After the slot has been
490      * assigned by this method, the {@link #setMarshallerUnmarshallerClasses}
491      * method must be used to set the actual class names.
492      *
493      * @param clas fully qualified name of class handled by
494      * marshaller/unmarshaller
495      * @return slot number for marshaller/unmarshaller
496      */

497
498     public int getMarshallerUnmarshallerIndex(String JavaDoc clas) {
499         if (!m_isMappedDone) {
500             m_isMappedDone = true;
501             m_mumIndex = s_mappedClasses.size();
502             m_extraClasses = new ArrayList JavaDoc();
503             m_extraMarshallers = new ArrayList JavaDoc();
504             m_extraUnmarshallers = new ArrayList JavaDoc();
505         }
506         m_extraClasses.add(clas);
507         m_extraMarshallers.add(null);
508         m_extraUnmarshallers.add(null);
509         return m_mumIndex++;
510     }
511
512     /**
513      * Set marshaller and unmarshaller class names for slot.
514      *
515      * @param slot assigned marshaller/unmarshaller slot number
516      * @param mclas fully qualified name of marshaller class
517      * @param mclas fully qualified name of unmarshaller class
518      */

519
520     public void setMarshallerUnmarshallerClasses(int slot, String JavaDoc mclas,
521         String JavaDoc uclas) {
522         int index = slot - s_mappedClasses.size();
523         m_extraMarshallers.set(index, mclas);
524         m_extraUnmarshallers.set(index, uclas);
525     }
526
527     /**
528      * Get index for ID'ed class from binding. If the class is not already
529      * included it is first added to the binding. If globally unique IDs are
530      * used this always returns <code>0</code>.
531      *
532      * @param name fully qualified name of ID'ed class
533      * @return index number of class
534      */

535
536     public int getIdClassIndex(String JavaDoc name) {
537         if (m_isIdGlobal) {
538             return 0;
539         } else {
540             if (m_uniqueIds == null) {
541                 m_uniqueIds = new ArrayMap();
542             }
543             return m_uniqueIds.findOrAdd(name);
544         }
545     }
546
547     /**
548      * Get index for namespace URI in binding. If the URI is not already
549      * included it is first added to the binding. The empty namespace URI
550      * is always given index number <code>0</code>.
551      *
552      * @param uri namespace URI to be included in binding
553      * @return index number of class
554      */

555
556     public int getNamespaceUriIndex(String JavaDoc name) {
557         return m_namespaceUris.findOrAdd(name);
558     }
559
560     /**
561      * Generate code. First sets linkages and executes code generation for
562      * each top-level mapping defined in this binding, which in turn propagates
563      * the code generation all the way down. Then generates the actual binding
564      * factory for this binding.
565      *
566      * TODO: handle unidirectional bindings properly
567      *
568      * @param verbose flag for verbose output
569      * @throws JiBXException if error in code generation
570      */

571
572     public void generateCode(boolean verbose) throws JiBXException {
573         
574         // handle basic linkage and child code generation
575
BoundClass.setModify(m_targetRoot, m_targetPackage);
576         m_activeContext.linkMappings();
577         m_activeContext.setLinkages();
578         m_activeContext.generateCode(verbose);
579         
580         // build the binding factory class
581
String JavaDoc name;
582         if (m_targetPackage.length() == 0) {
583             name = getPrefix() + FACTORY_SUFFIX;
584         } else {
585             name = m_targetPackage + '.' + getPrefix() + FACTORY_SUFFIX;
586         }
587         ClassFile base = ClassCache.getClassFile("java.lang.Object");
588         ClassFile cf = new ClassFile(name, m_targetRoot, base,
589             Constants.ACC_PUBLIC, FACTORY_INTERFACES);
590         
591         // add static field for instance and member fields for data
592
ClassItem inst = cf.addField(FACTORY_INTERFACE,
593             FACTORY_INSTNAME, FACTORY_INSTACCESS);
594         ClassItem marshs = cf.addPrivateField(STRING_ARRAYTYPE,
595             MARSHALLER_ARRAYNAME);
596         ClassItem umarshs = cf.addPrivateField(STRING_ARRAYTYPE,
597             UNMARSHALLER_ARRAYNAME);
598         ClassItem classes = cf.addPrivateField(STRING_ARRAYTYPE,
599             CLASSES_ARRAYNAME);
600         ClassItem uris = cf.addPrivateField(STRING_ARRAYTYPE, URIS_ARRAYNAME);
601         ClassItem gnames = cf.addPrivateField(STRING_ARRAYTYPE,
602             GNAMES_ARRAYNAME);
603         ClassItem guris = cf.addPrivateField(STRING_ARRAYTYPE,
604             GURIS_ARRAYNAME);
605         ClassItem idnames = cf.addPrivateField(STRING_ARRAYTYPE,
606             IDNAMES_ARRAYNAME);
607         
608         // add the private constructor method
609
MethodBuilder mb = new ExceptionMethodBuilder("<init>",
610             Type.VOID, new Type[0], cf, Constants.ACC_PRIVATE);
611         
612         // call the superclass constructor
613
mb.appendLoadLocal(0);
614         mb.appendCallInit("java.lang.Object", "()V");
615         
616         // create and fill array of unmarshaller class names
617
int count = s_mappedClasses.size();
618         int mcnt = m_isMappedDone ? m_mumIndex : count;
619         if (m_isInput) {
620             mb.appendLoadLocal(0);
621             mb.appendLoadConstant(mcnt);
622             mb.appendCreateArray("java.lang.String");
623             for (int i = 0; i < count; i++) {
624                 String JavaDoc cname = (String JavaDoc)s_mappedClasses.get(i);
625                 IMapping map = m_activeContext.getMappingAtLevel(cname);
626                 if (map != null && map.getUnmarshaller() != null) {
627                     mb.appendDUP();
628                     mb.appendLoadConstant(i);
629                     mb.appendLoadConstant(map.getUnmarshaller().getName());
630                     mb.appendAASTORE();
631                 }
632             }
633             for (int i = count; i < mcnt; i++) {
634                 mb.appendDUP();
635                 mb.appendLoadConstant(i);
636                 mb.appendLoadConstant
637                     ((String JavaDoc)m_extraUnmarshallers.get(i-count));
638                 mb.appendAASTORE();
639             }
640             mb.appendPutField(umarshs);
641         }
642         
643         // create and fill array of marshaller class names
644
if (m_isOutput) {
645             mb.appendLoadLocal(0);
646             mb.appendLoadConstant(mcnt);
647             mb.appendCreateArray("java.lang.String");
648             for (int i = 0; i < count; i++) {
649                 String JavaDoc cname = (String JavaDoc)s_mappedClasses.get(i);
650                 IMapping map = m_activeContext.getMappingAtLevel(cname);
651                 if (map != null && map.getMarshaller() != null) {
652                     mb.appendDUP();
653                     mb.appendLoadConstant(i);
654                     mb.appendLoadConstant(map.getMarshaller().getName());
655                     mb.appendAASTORE();
656                 }
657             }
658             for (int i = count; i < mcnt; i++) {
659                 mb.appendDUP();
660                 mb.appendLoadConstant(i);
661                 mb.appendLoadConstant((String JavaDoc)m_extraMarshallers.get(i-count));
662                 mb.appendAASTORE();
663             }
664             mb.appendPutField(marshs);
665         }
666         
667         // create and fill array of mapped class names
668
mb.appendLoadLocal(0);
669         mb.appendLoadConstant(mcnt);
670         mb.appendCreateArray("java.lang.String");
671         for (int i = 0; i < count; i++) {
672             mb.appendDUP();
673             mb.appendLoadConstant(i);
674             mb.appendLoadConstant((String JavaDoc)s_mappedClasses.get(i));
675             mb.appendAASTORE();
676         }
677         for (int i = count; i < mcnt; i++) {
678             mb.appendDUP();
679             mb.appendLoadConstant(i);
680             mb.appendLoadConstant((String JavaDoc)m_extraClasses.get(i-count));
681             mb.appendAASTORE();
682         }
683         mb.appendPutField(classes);
684         
685         // create and fill array of namespace URIs
686
if (m_isOutput) {
687             mb.appendLoadLocal(0);
688             mb.appendLoadConstant(m_namespaceUris.size());
689             mb.appendCreateArray("java.lang.String");
690             for (int i = 0; i < m_namespaceUris.size(); i++) {
691                 mb.appendDUP();
692                 mb.appendLoadConstant(i);
693                 mb.appendLoadConstant((String JavaDoc)m_namespaceUris.get(i));
694                 mb.appendAASTORE();
695             }
696             mb.appendPutField(uris);
697         }
698         
699         // create and fill arrays of globally mapped element names and URIs
700
mb.appendLoadLocal(0);
701         mb.appendLoadConstant(count);
702         mb.appendCreateArray("java.lang.String");
703         for (int i = 0; i < count; i++) {
704             String JavaDoc cname = (String JavaDoc)s_mappedClasses.get(i);
705             IMapping map = m_activeContext.getMappingAtLevel(cname);
706             if (map != null) {
707                 NameDefinition ndef = map.getName();
708                 if (ndef != null) {
709                     mb.appendDUP();
710                     mb.appendLoadConstant(i);
711                     ndef.genPushName(mb);
712                     mb.appendAASTORE();
713                 }
714             }
715         }
716         mb.appendPutField(gnames);
717         mb.appendLoadLocal(0);
718         mb.appendLoadConstant(count);
719         mb.appendCreateArray("java.lang.String");
720         for (int i = 0; i < count; i++) {
721             String JavaDoc cname = (String JavaDoc)s_mappedClasses.get(i);
722             IMapping map = m_activeContext.getMappingAtLevel(cname);
723             if (map != null) {
724                 NameDefinition ndef = map.getName();
725                 if (ndef != null) {
726                     mb.appendDUP();
727                     mb.appendLoadConstant(i);
728                     ndef.genPushUri(mb);
729                     mb.appendAASTORE();
730                 }
731             }
732         }
733         mb.appendPutField(guris);
734         
735         // create and fill array of class names with unique IDs (null if none)
736
mb.appendLoadLocal(0);
737         if (m_uniqueIds != null && m_uniqueIds.size() > 0) {
738             mb.appendLoadConstant(m_uniqueIds.size());
739             mb.appendCreateArray("java.lang.String");
740             for (int i = 0; i < m_uniqueIds.size(); i++) {
741                 mb.appendDUP();
742                 mb.appendLoadConstant(i);
743                 mb.appendLoadConstant((String JavaDoc)m_uniqueIds.get(i));
744                 mb.appendAASTORE();
745             }
746         } else {
747             mb.appendACONST_NULL();
748         }
749         mb.appendPutField(idnames);
750         
751         // finish with return from constructor
752
mb.appendReturn();
753         mb.codeComplete(false);
754         mb.addMethod();
755         
756         // add the public marshalling context construction method
757
mb = new ExceptionMethodBuilder(CREATEMARSHAL_METHODNAME,
758             ClassItem.typeFromName(MARSHALCONTEXT_INTERFACE), new Type[0], cf,
759             Constants.ACC_PUBLIC);
760         if (m_isOutput) {
761             
762             // construct and return marshaller instance
763
mb.appendCreateNew(MARSHALCONTEXT_IMPLEMENTATION);
764             mb.appendDUP();
765             mb.appendLoadLocal(0);
766             mb.appendGetField(classes);
767             mb.appendLoadLocal(0);
768             mb.appendGetField(marshs);
769             mb.appendLoadLocal(0);
770             mb.appendGetField(uris);
771             mb.appendCallInit(MARSHALCONTEXT_IMPLEMENTATION,
772                 MARSHALCONTEXTINIT_SIGNATURE);
773             mb.appendReturn(MARSHALCONTEXT_IMPLEMENTATION);
774                 
775         } else {
776             
777             // throw exception for unsupported operation
778
mb.appendCreateNew(UNSUPPORTED_EXCEPTION_CLASS);
779             mb.appendDUP();
780             mb.appendLoadConstant
781                 ("Binding is input only - cannot create unmarshaller");
782             mb.appendCallInit(UNSUPPORTED_EXCEPTION_CLASS,
783                 MethodBuilder.EXCEPTION_CONSTRUCTOR_SIGNATURE1);
784             mb.appendThrow();
785             
786         }
787         mb.codeComplete(false);
788         mb.addMethod();
789         
790         // add the public unmarshalling context construction method
791
mb = new ExceptionMethodBuilder(CREATEUNMARSHAL_METHODNAME,
792             ClassItem.typeFromName(UNMARSHALCONTEXT_INTERFACE), new Type[0], cf,
793             Constants.ACC_PUBLIC);
794         if (m_isInput) {
795             
796             // construct and return unmarshaller instance
797
mb.appendCreateNew(UNMARSHALCONTEXT_IMPLEMENTATION);
798             mb.appendDUP();
799             mb.appendLoadConstant(mcnt);
800             mb.appendLoadLocal(0);
801             mb.appendGetField(umarshs);
802             mb.appendLoadLocal(0);
803             mb.appendGetField(guris);
804             mb.appendLoadLocal(0);
805             mb.appendGetField(gnames);
806             mb.appendLoadLocal(0);
807             mb.appendGetField(idnames);
808             mb.appendCallInit(UNMARSHALCONTEXT_IMPLEMENTATION,
809                  UNMARSHALCONTEXTINIT_SIGNATURE);
810             mb.appendReturn(UNMARSHALCONTEXT_IMPLEMENTATION);
811             
812         } else {
813             
814             // throw exception for unsupported operation
815
mb.appendCreateNew(UNSUPPORTED_EXCEPTION_CLASS);
816             mb.appendDUP();
817             mb.appendLoadConstant
818                 ("Binding is output only - cannot create marshaller");
819             mb.appendCallInit(UNSUPPORTED_EXCEPTION_CLASS,
820                 MethodBuilder.EXCEPTION_CONSTRUCTOR_SIGNATURE1);
821             mb.appendThrow();
822             
823         }
824         mb.codeComplete(false);
825         mb.addMethod();
826         
827         // add the compiler version access method
828
mb = new ExceptionMethodBuilder(GETVERSION_METHODNAME,
829             Type.INT, new Type[0], cf, Constants.ACC_PUBLIC);
830         mb.appendLoadConstant(IBindingFactory.CURRENT_VERSION_NUMBER);
831         mb.appendReturn("int");
832         mb.codeComplete(false);
833         mb.addMethod();
834         
835         // add the compiler distribution access method
836
mb = new ExceptionMethodBuilder(GETDISTRIB_METHODNAME,
837             Type.STRING, new Type[0], cf, Constants.ACC_PUBLIC);
838         mb.appendLoadConstant(CURRENT_VERSION_NAME);
839         mb.appendReturn(Type.STRING);
840         mb.codeComplete(false);
841         mb.addMethod();
842         
843         // add the defined namespace URI array access method
844
Type satype = new ArrayType(Type.STRING, 1);
845         mb = new ExceptionMethodBuilder(GETDEFINEDNSS_METHODNAME,
846             satype, new Type[0], cf, Constants.ACC_PUBLIC);
847         mb.appendLoadLocal(0);
848         mb.appendGetField(uris);
849         mb.appendReturn(satype);
850         mb.codeComplete(false);
851         mb.addMethod();
852         
853         // add the class name array access method
854
mb = new ExceptionMethodBuilder(GETCLASSES_METHODNAME,
855             satype, new Type[0], cf, Constants.ACC_PUBLIC);
856         mb.appendLoadLocal(0);
857         mb.appendGetField(classes);
858         mb.appendReturn(satype);
859         mb.codeComplete(false);
860         mb.addMethod();
861         
862         // add the element namespace URI array access method
863
mb = new ExceptionMethodBuilder(GETELEMENTNSS_METHODNAME,
864             satype, new Type[0], cf, Constants.ACC_PUBLIC);
865         mb.appendLoadLocal(0);
866         mb.appendGetField(guris);
867         mb.appendReturn(satype);
868         mb.codeComplete(false);
869         mb.addMethod();
870         
871         // add the element name array access method
872
mb = new ExceptionMethodBuilder(GETELEMENTNAMES_METHODNAME,
873             satype, new Type[0], cf, Constants.ACC_PUBLIC);
874         mb.appendLoadLocal(0);
875         mb.appendGetField(gnames);
876         mb.appendReturn(satype);
877         mb.codeComplete(false);
878         mb.addMethod();
879         
880         // finish with instance creation method
881
mb = new ExceptionMethodBuilder(GETINST_METHODNAME,
882             ClassItem.typeFromName(FACTORY_INTERFACE), new Type[0], cf,
883             (short)(Constants.ACC_PUBLIC | Constants.ACC_STATIC));
884         mb.appendGetStatic(inst);
885         BranchWrapper ifdone = mb.appendIFNONNULL(this);
886         mb.appendCreateNew(cf.getName());
887         mb.appendDUP();
888         mb.appendCallInit(cf.getName(), "()V");
889         mb.appendPutStatic(inst);
890         mb.targetNext(ifdone);
891         mb.appendGetStatic(inst);
892         mb.appendReturn(FACTORY_INTERFACE);
893         mb.codeComplete(false);
894         mb.addMethod();
895         
896         // add factory class to generated registry
897
cf = MungedClass.getUniqueSupportClass(cf);
898         String JavaDoc link = name;
899         if (!name.equals(cf.getName())) {
900             link = cf.getName() + '=' + name;
901         }
902         
903         // record the binding factory in each top-level mapped class
904
ArrayList JavaDoc maps = m_activeContext.getMappings();
905         for (int i = 0; i < maps.size(); i++) {
906             IMapping map = (IMapping)maps.get(i);
907             if (map instanceof MappingBase) {
908                 BoundClass bound = ((MappingBase)map).getBoundClass();
909                 if (bound.getClassFile().isModifiable()) {
910                     bound.addFactory(link);
911                 }
912             }
913         }
914     }
915
916     /**
917      * Get indexed binding.
918      *
919      * @param index number of binding to be returned
920      * @return binding at the specified index
921      */

922
923     public static BindingDefinition getBinding(int index) {
924         return (BindingDefinition)s_bindings.get(index);
925     }
926
927     /**
928      * Discard cached information and reset in preparation for a new binding
929      * run.
930      */

931
932     public static void reset() {
933         s_bindings = new ArrayList JavaDoc();
934         s_mappedClasses = new ArrayMap();
935     }
936     
937     //
938
// IContainer interface method definitions
939

940     public boolean isContentOrdered() {
941         return true;
942     }
943
944     public boolean hasNamespaces() {
945         return false;
946     }
947
948     public BindingDefinition getBindingRoot() {
949         return this;
950     }
951
952     public DefinitionContext getDefinitionContext() {
953         return m_activeContext;
954     }
955     
956     // DEBUG
957
private static byte[] s_blanks =
958         " ".getBytes();
959     public static void indent(int depth) {
960         if (depth < s_blanks.length) {
961             System.out.write(s_blanks, 0, depth);
962         } else {
963             System.out.print(s_blanks);
964         }
965     }
966     public void print() {
967         System.out.println("binding " + m_name + ":");
968         m_activeContext.print(1);
969     }
970 }
Popular Tags