KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > xb > binding > metadata > unmarshalling > impl > DocumentBindingFactoryImpl


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.xb.binding.metadata.unmarshalling.impl;
8
9 import org.jboss.xb.binding.metadata.unmarshalling.DocumentBindingFactory;
10 import org.jboss.xb.binding.metadata.unmarshalling.NamespaceBinding;
11 import org.jboss.xb.binding.metadata.unmarshalling.DocumentBinding;
12 import org.jboss.xb.binding.metadata.unmarshalling.TopElementBinding;
13 import org.jboss.xb.binding.metadata.unmarshalling.ElementBinding;
14 import org.jboss.xb.binding.metadata.unmarshalling.BasicElementBinding;
15 import org.jboss.xb.binding.metadata.unmarshalling.AttributeBinding;
16 import org.jboss.xb.binding.metadata.unmarshalling.DocumentBindingStack;
17 import org.jboss.xb.binding.metadata.unmarshalling.DocumentBinder;
18 import org.jboss.xb.binding.metadata.unmarshalling.XmlValueBinding;
19 import org.jboss.xb.binding.metadata.unmarshalling.XmlValueContainer;
20 import org.jboss.xb.binding.JBossXBRuntimeException;
21
22 import javax.xml.namespace.QName JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.lang.reflect.Field JavaDoc;
29 import java.lang.reflect.Method JavaDoc;
30 import java.lang.reflect.Modifier JavaDoc;
31 import java.lang.reflect.Constructor JavaDoc;
32
33 /**
34  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
35  * @version <tt>$Revision: 1.1.2.1 $</tt>
36  */

37 public class DocumentBindingFactoryImpl
38    extends DocumentBindingFactory
39 {
40    public DocumentBindingStack newDocumentBindingStack()
41    {
42       return new DocumentBindingStackImpl();
43    }
44
45    public NamespaceBinding bindNamespace(DocumentBinding doc, String JavaDoc namespaceUri, String JavaDoc javaPackage)
46    {
47       DocumentBindingStackImpl docStack = (DocumentBindingStackImpl)doc;
48       return docStack.bindNamespace(new DefaultNamespaceBinding(docStack, namespaceUri, javaPackage));
49    }
50
51    public TopElementBinding bindTopElement(NamespaceBinding ns, String JavaDoc elementName, Class JavaDoc javaClass)
52    {
53       NamespaceBindingStack nsStack = (NamespaceBindingStack)ns;
54       return nsStack.bindTopElement(new DefaultTopElementBinding(nsStack, elementName, javaClass));
55    }
56
57    public ElementBinding bindElement(BasicElementBinding parent,
58                                      String JavaDoc namespaceUri,
59                                      String JavaDoc elementName,
60                                      String JavaDoc fieldName,
61                                      Class JavaDoc javaType)
62    {
63       BasicElementBindingStack basicStack = (BasicElementBindingStack)parent;
64       return basicStack.bindChild(
65          new DefaultElementBinding(parent, new QName JavaDoc(namespaceUri, elementName), fieldName, javaType)
66       );
67    }
68
69    public XmlValueBinding bindValue(BasicElementBinding element, String JavaDoc fieldName, Class JavaDoc javaType)
70    {
71       ElementBindingStack basicStack = (ElementBindingStack)element;
72       return basicStack.bindValue(new DefaultXmlValueBinding(element, fieldName, javaType));
73    }
74
75    public XmlValueBinding bindValue(XmlValueContainer container, String JavaDoc fieldName, Class JavaDoc javaType)
76    {
77       XmlValueContainerStack stack = (XmlValueContainerStack)container;
78       return stack.bindValue(new DefaultXmlValueBinding(container, fieldName, javaType));
79    }
80
81    public AttributeBinding bindAttribute(BasicElementBinding parent,
82                                          String JavaDoc namespaceUri,
83                                          String JavaDoc attributeName,
84                                          String JavaDoc fieldName,
85                                          Class JavaDoc javaType)
86    {
87       BasicElementBindingStack stack = (BasicElementBindingStack)parent;
88       AttributeBinding attr = new AttributeBindingImpl(new QName JavaDoc(namespaceUri, attributeName),
89          javaType,
90          parent.getJavaType(),
91          fieldName
92       );
93       stack.bindAttribute(attr);
94       return attr;
95    }
96
97    public DocumentBinding newDocumentBinding()
98    {
99       return new DocumentBindingStackImpl();
100    }
101
102    //
103
// Inner
104
//
105

106    // Abstract classes for this stack implementation
107

108    public static abstract class AbstractDocumentBinding
109       implements DocumentBinding
110    {
111       protected final DocumentBinding doc;
112
113       protected AbstractDocumentBinding(DocumentBinding doc)
114       {
115          if(doc == null)
116          {
117             // todo
118
doc = DocumentBindingFactory.newInstance().newDocumentBindingStack();
119             ((DocumentBindingStackImpl)doc).push(this);
120          }
121          this.doc = doc;
122       }
123
124       public NamespaceBinding getNamespace(String JavaDoc namespaceUri)
125       {
126          return doc.getNamespace(namespaceUri);
127       }
128
129       protected abstract NamespaceBinding getNamespaceLocal(String JavaDoc namespaceUri);
130    }
131
132    public static abstract class AbstractNamespaceBinding
133       implements NamespaceBinding
134    {
135       protected final String JavaDoc namespaceUri;
136       private final DocumentBinding doc;
137
138       protected AbstractNamespaceBinding(DocumentBinding doc, String JavaDoc namespaceUri)
139       {
140          this.namespaceUri = namespaceUri;
141          this.doc = doc;
142       }
143
144       public DocumentBinding getDocument()
145       {
146          return doc;
147       }
148
149       public String JavaDoc getNamespaceUri()
150       {
151          return namespaceUri;
152       }
153
154       public String JavaDoc getJavaPackage()
155       {
156          return doc.getNamespace(namespaceUri).getJavaPackage();
157       }
158
159       public TopElementBinding getTopElement(String JavaDoc elementName)
160       {
161          return doc.getNamespace(namespaceUri).getTopElement(elementName);
162       }
163
164       protected abstract String JavaDoc getJavaPackageLocal();
165
166       protected abstract TopElementBinding getTopElementLocal(String JavaDoc elementName);
167    }
168
169    public static abstract class AbstractXmlValueContainer
170       implements XmlValueContainer
171    {
172       protected final QName JavaDoc name;
173
174       public AbstractXmlValueContainer(QName JavaDoc name)
175       {
176          this.name = name;
177       }
178
179       public QName JavaDoc getName()
180       {
181          return name;
182       }
183
184       public XmlValueBinding getValue()
185       {
186          return getValueStackReference().getValue();
187       }
188
189       public Class JavaDoc getJavaType()
190       {
191          return getValueStackReference().getJavaType();
192       }
193
194       protected abstract XmlValueContainer getValueStackReference();
195
196       protected abstract XmlValueBinding getValueLocal();
197
198       protected abstract Class JavaDoc getJavaTypeLocal();
199    }
200
201    public static abstract class AbstractBasicElementBinding
202       extends AbstractXmlValueContainer
203       implements BasicElementBinding
204    {
205       protected AbstractBasicElementBinding(QName JavaDoc elementName)
206       {
207          super(elementName);
208       }
209
210       public DocumentBinding getDocument()
211       {
212          return getStackReference().getDocument();
213       }
214
215       public ElementBinding getElement(QName JavaDoc elementName)
216       {
217          return getStackReference().getElement(elementName);
218       }
219
220       public AttributeBinding getAttribute(QName JavaDoc attributeName)
221       {
222          return getStackReference().getAttribute(attributeName);
223       }
224
225       public XmlValueBinding getValue()
226       {
227          return getStackReference().getValue();
228       }
229
230       protected XmlValueContainer getValueStackReference()
231       {
232          return getStackReference();
233       }
234
235       protected abstract Class JavaDoc getJavaTypeLocal();
236
237       protected abstract ElementBinding getElementLocal(QName JavaDoc elementName);
238
239       protected abstract AttributeBinding getAttributeLocal(QName JavaDoc attributeName);
240
241       protected abstract XmlValueBinding getValueLocal();
242
243       protected abstract BasicElementBinding getStackReference();
244    }
245
246    public static abstract class AbstractTopElementBinding
247       extends AbstractBasicElementBinding
248       implements TopElementBinding
249    {
250       protected final NamespaceBinding ns;
251
252       protected AbstractTopElementBinding(NamespaceBinding ns, String JavaDoc elementName)
253       {
254          super(new QName JavaDoc(ns.getNamespaceUri(), elementName));
255          this.ns = ns;
256       }
257
258       protected BasicElementBinding getStackReference()
259       {
260          return ns.getTopElement(name.getLocalPart());
261       }
262    }
263
264    public static abstract class AbstractElementBinding
265       extends AbstractBasicElementBinding
266       implements ElementBinding
267    {
268       protected final BasicElementBinding parent;
269
270       protected AbstractElementBinding(BasicElementBinding parent, QName JavaDoc elementName)
271       {
272          super(elementName);
273          this.parent = parent;
274       }
275
276       public Field JavaDoc getField()
277       {
278          return ((ElementBinding)getStackReference()).getField();
279       }
280
281       public Method JavaDoc getGetter()
282       {
283          return ((ElementBinding)getStackReference()).getGetter();
284       }
285
286       public Method JavaDoc getSetter()
287       {
288          return ((ElementBinding)getStackReference()).getSetter();
289       }
290
291       public Class JavaDoc getFieldType()
292       {
293          return ((ElementBinding)getStackReference()).getFieldType();
294       }
295
296       protected BasicElementBinding getStackReference()
297       {
298          return parent.getElement(name);
299       }
300
301       protected abstract Field JavaDoc getFieldLocal();
302
303       protected abstract Method JavaDoc getGetterLocal();
304
305       protected abstract Method JavaDoc getSetterLocal();
306
307       protected abstract Class JavaDoc getFieldTypeLocal();
308    }
309
310    public static abstract class AbstractXmlValueBinding
311       extends AbstractXmlValueContainer
312       implements XmlValueBinding
313    {
314       private final XmlValueContainer container;
315
316       protected AbstractXmlValueBinding(XmlValueContainer container)
317       {
318          super(container.getName());
319          this.container = container;
320       }
321
322       public Field JavaDoc getField()
323       {
324          return container.getValue().getField();
325       }
326
327       public Method JavaDoc getGetter()
328       {
329          return container.getValue().getGetter();
330       }
331
332       public Method JavaDoc getSetter()
333       {
334          return container.getValue().getSetter();
335       }
336
337       public Class JavaDoc getFieldType()
338       {
339          return container.getValue().getFieldType();
340       }
341
342       public XmlValueBinding getValue()
343       {
344          return container.getValue().getValue();
345       }
346
347       protected XmlValueContainer getValueStackReference()
348       {
349          return container.getValue();
350       }
351
352       protected abstract Field JavaDoc getFieldLocal();
353
354       protected abstract Method JavaDoc getGetterLocal();
355
356       protected abstract Method JavaDoc getSetterLocal();
357
358       protected abstract Class JavaDoc getFieldTypeLocal();
359    }
360
361    // Default impl used internally
362

363    private static class DefaultNamespaceBinding
364       extends AbstractNamespaceBinding
365    {
366       private final String JavaDoc javaPackage;
367
368       public DefaultNamespaceBinding(DocumentBinding doc, String JavaDoc namespaceUri, String JavaDoc javaPackage)
369       {
370          super(doc, namespaceUri);
371          this.javaPackage = javaPackage;
372       }
373
374       protected String JavaDoc getJavaPackageLocal()
375       {
376          return javaPackage;
377       }
378
379       protected TopElementBinding getTopElementLocal(String JavaDoc elementName)
380       {
381          return null;
382       }
383    }
384
385    private static class DefaultTopElementBinding
386       extends AbstractTopElementBinding
387    {
388       private final Class JavaDoc javaType;
389
390       DefaultTopElementBinding(NamespaceBinding ns, String JavaDoc elementName, Class JavaDoc javaType)
391       {
392          super(ns, elementName);
393          this.javaType = javaType;
394       }
395
396       protected Class JavaDoc getJavaTypeLocal()
397       {
398          return javaType;
399       }
400
401       protected ElementBinding getElementLocal(QName JavaDoc elementName)
402       {
403          return null;
404       }
405
406       protected AttributeBinding getAttributeLocal(QName JavaDoc attributeName)
407       {
408          return null;
409       }
410
411       protected XmlValueBinding getValueLocal()
412       {
413          return null;
414       }
415    }
416
417    private static class DefaultElementBinding
418       extends AbstractElementBinding
419    {
420       private final Field JavaDoc field;
421       private final Method JavaDoc getter;
422       private final Method JavaDoc setter;
423       private final Class JavaDoc fieldType;
424       private final Class JavaDoc javaType;
425
426       public DefaultElementBinding(BasicElementBinding parent, QName JavaDoc elementName, String JavaDoc fieldName, Class JavaDoc javaType)
427       {
428          super(parent, elementName);
429
430          Class JavaDoc parentType = parent.getJavaType();
431          if(Collection JavaDoc.class.isAssignableFrom(parentType))
432          {
433             field = null;
434             getter = null;
435             setter = null;
436             fieldType = null;
437          }
438          else
439          {
440             Field JavaDoc tmpField = null;
441             Method JavaDoc tmpGetter = null;
442             Method JavaDoc tmpSetter = null;
443             Class JavaDoc tmpFieldType;
444             try
445             {
446                tmpField = parentType.getField(fieldName);
447                tmpFieldType = tmpField.getType();
448             }
449             catch(NoSuchFieldException JavaDoc e)
450             {
451                String JavaDoc baseMethodName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
452                try
453                {
454                   tmpGetter = parentType.getMethod("get" + baseMethodName, null);
455                   tmpFieldType = tmpGetter.getReturnType();
456                   try
457                   {
458                      tmpSetter = parentType.getMethod("set" + baseMethodName, new Class JavaDoc[]{tmpGetter.getReturnType()});
459                   }
460                   catch(NoSuchMethodException JavaDoc nosetter)
461                   {
462                      // this one is immutable
463
}
464                }
465                catch(NoSuchMethodException JavaDoc e1)
466                {
467                   throw new JBossXBRuntimeException("Failed to bind " +
468                      elementName +
469                      " to field " +
470                      fieldName +
471                      " in " +
472                      parentType +
473                      ": neither field nor getter/setter were found."
474                   );
475                }
476             }
477
478             field = tmpField;
479             getter = tmpGetter;
480             setter = tmpSetter;
481             fieldType = tmpFieldType;
482          }
483
484          if(fieldType == null)
485          {
486             this.javaType = javaType == null ? String JavaDoc.class : javaType;
487          }
488          else
489          {
490             if(javaType == null)
491             {
492                this.javaType = fieldType;
493             }
494             else if(Collection JavaDoc.class == fieldType ||
495                Collection JavaDoc.class.isAssignableFrom(fieldType) ||
496                fieldType.isAssignableFrom(javaType))
497             {
498                this.javaType = javaType;
499             }
500             else
501             {
502                throw new JBossXBRuntimeException("Failed to bind " +
503                   elementName +
504                   " to field " +
505                   fieldName +
506                   " in " +
507                   parentType +
508                   ": field type " + fieldType + " is not assignable from the specified Java type " + javaType
509                );
510             }
511
512             if(this.javaType.isInterface() || Modifier.isAbstract(this.javaType.getModifiers()))
513             {
514                throw new JBossXBRuntimeException("Failed to bind " +
515                   elementName +
516                   " to field " +
517                   fieldName +
518                   " in " +
519                   parentType +
520                   ": Java type is abstract class or interface."
521                );
522             }
523          }
524       }
525
526       protected Field JavaDoc getFieldLocal()
527       {
528          return field;
529       }
530
531       protected Method JavaDoc getGetterLocal()
532       {
533          return getter;
534       }
535
536       protected Method JavaDoc getSetterLocal()
537       {
538          return setter;
539       }
540
541       protected Class JavaDoc getFieldTypeLocal()
542       {
543          return fieldType;
544       }
545
546       protected Class JavaDoc getJavaTypeLocal()
547       {
548          return javaType;
549       }
550
551       protected ElementBinding getElementLocal(QName JavaDoc elementName)
552       {
553          return null;
554       }
555
556       protected AttributeBinding getAttributeLocal(QName JavaDoc attributeName)
557       {
558          return null;
559       }
560
561       protected XmlValueBinding getValueLocal()
562       {
563          return null;
564       }
565    }
566
567    private static class DefaultXmlValueBinding
568       extends AbstractXmlValueBinding
569    {
570       private final Field JavaDoc field;
571       private final Method JavaDoc getter;
572       private final Method JavaDoc setter;
573       private final Class JavaDoc fieldType;
574       private final Class JavaDoc javaType;
575
576       public DefaultXmlValueBinding(XmlValueContainer container, String JavaDoc fieldName, Class JavaDoc javaType)
577       {
578          super(container);
579
580          Class JavaDoc parentType = container.getJavaType();
581          if(Collection JavaDoc.class.isAssignableFrom(parentType))
582          {
583             field = null;
584             getter = null;
585             setter = null;
586             fieldType = null;
587          }
588          else
589          {
590             Field JavaDoc tmpField = null;
591             Method JavaDoc tmpGetter = null;
592             Method JavaDoc tmpSetter = null;
593             Class JavaDoc tmpFieldType = null;
594             try
595             {
596                tmpField = parentType.getField(fieldName);
597                tmpFieldType = tmpField.getType();
598             }
599             catch(NoSuchFieldException JavaDoc e)
600             {
601                String JavaDoc baseMethodName = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
602                try
603                {
604                   tmpGetter = parentType.getMethod("get" + baseMethodName, null);
605                   tmpFieldType = tmpGetter.getReturnType();
606                   try
607                   {
608                      tmpSetter = parentType.getMethod("set" + baseMethodName, new Class JavaDoc[]{tmpGetter.getReturnType()});
609                   }
610                   catch(NoSuchMethodException JavaDoc nosetter)
611                   {
612                      // this one is immutable
613
}
614                }
615                catch(NoSuchMethodException JavaDoc e1)
616                {
617                   throw new JBossXBRuntimeException("Failed to bind value of " +
618                      container.getName() +
619                      " to field " +
620                      fieldName +
621                      " in " +
622                      parentType +
623                      ": neither field nor getter/setter were found."
624                   );
625                }
626             }
627
628             field = tmpField;
629             getter = tmpGetter;
630             setter = tmpSetter;
631             fieldType = tmpFieldType;
632          }
633
634          if(fieldType == null)
635          {
636             this.javaType = javaType == null ? String JavaDoc.class : javaType;
637          }
638          else
639          {
640             if(javaType == null)
641             {
642                this.javaType = fieldType;
643             }
644             else if(Collection JavaDoc.class == fieldType ||
645                Collection JavaDoc.class.isAssignableFrom(fieldType) ||
646                fieldType.isAssignableFrom(javaType))
647             {
648                this.javaType = javaType;
649             }
650             else
651             {
652                throw new JBossXBRuntimeException("Failed to bind value of " +
653                   container.getName() +
654                   " to field " +
655                   fieldName +
656                   " in " +
657                   parentType +
658                   ": field type " + fieldType + " is not assignable from the specified Java type " + javaType
659                );
660             }
661
662             if(this.javaType.isInterface() || Modifier.isAbstract(this.javaType.getModifiers()))
663             {
664                throw new JBossXBRuntimeException("Failed to bind value of " +
665                   container.getName() +
666                   " to field " +
667                   fieldName +
668                   " in " +
669                   parentType +
670                   ": Java type is abstract class or interface."
671                );
672             }
673          }
674       }
675
676       protected Field JavaDoc getFieldLocal()
677       {
678          return field;
679       }
680
681       protected Method JavaDoc getGetterLocal()
682       {
683          return getter;
684       }
685
686       protected Method JavaDoc getSetterLocal()
687       {
688          return setter;
689       }
690
691       protected Class JavaDoc getFieldTypeLocal()
692       {
693          return fieldType;
694       }
695
696       protected XmlValueBinding getValueLocal()
697       {
698          return null;
699       }
700
701       protected Class JavaDoc getJavaTypeLocal()
702       {
703          return javaType;
704       }
705    }
706
707    // Stack impl
708

709    class DocumentBindingStackImpl
710       implements DocumentBindingStack
711    {
712       private final List JavaDoc stack = new ArrayList JavaDoc();
713       private final Map JavaDoc namespaces = new HashMap JavaDoc();
714
715       public DocumentBindingStackImpl()
716       {
717       }
718
719       public DocumentBindingStackImpl(DocumentBinding doc)
720       {
721          if(doc != null)
722          {
723             push(doc);
724          }
725       }
726
727       void push(DocumentBinding doc)
728       {
729          stack.add(doc);
730       }
731
732       NamespaceBindingStack bindNamespace(NamespaceBinding ns)
733       {
734          NamespaceBindingStack stack = (NamespaceBindingStack)getNamespace(ns.getNamespaceUri());
735          if(stack == null)
736          {
737             stack = new NamespaceBindingStack(this, ns.getNamespaceUri());
738             namespaces.put(ns.getNamespaceUri(), stack);
739          }
740          stack.push(ns);
741          return stack;
742       }
743
744       public NamespaceBinding getNamespace(String JavaDoc namespaceUri)
745       {
746          NamespaceBindingStack nsStack = (NamespaceBindingStack)namespaces.get(namespaceUri);
747          if(nsStack == null)
748          {
749             nsStack = new NamespaceBindingStack(this, namespaceUri);
750             for(int i = 0; i < stack.size(); ++i)
751             {
752                AbstractDocumentBinding doc = (AbstractDocumentBinding)stack.get(i);
753                NamespaceBinding local = doc.getNamespaceLocal(namespaceUri);
754                if(local != null)
755                {
756                   nsStack.push(local);
757                }
758             }
759
760             if(nsStack.delegates.size() > 0)
761             {
762                namespaces.put(namespaceUri, nsStack);
763             }
764             else
765             {
766                nsStack = null;
767             }
768          }
769          return nsStack;
770       }
771
772       public DocumentBindingStack push(Class JavaDoc documentBindingClass)
773       {
774          pushNewDocumentBinding(documentBindingClass);
775          return this;
776       }
777
778       public DocumentBindingStack push(Class JavaDoc documentBindingClass, DocumentBinder binder)
779       {
780          DocumentBinding newDoc = pushNewDocumentBinding(documentBindingClass);
781          binder.bind(newDoc);
782          return this;
783       }
784
785       // Private
786

787       private DocumentBinding pushNewDocumentBinding(Class JavaDoc documentBindingClass)
788       {
789          if(!DocumentBinding.class.isAssignableFrom(documentBindingClass))
790          {
791             throw new JBossXBRuntimeException("The class must implement " + DocumentBinding.class);
792          }
793
794          DocumentBinding doc;
795          try
796          {
797             Constructor JavaDoc ctor = documentBindingClass.getConstructor(new Class JavaDoc[]{DocumentBinding.class});
798             doc = (DocumentBinding)ctor.newInstance(new Object JavaDoc[]{this});
799             push(doc);
800          }
801          catch(NoSuchMethodException JavaDoc e)
802          {
803             throw new JBossXBRuntimeException(
804                "The class must have a constructor with one parameter of type " + DocumentBinding.class
805             );
806          }
807          catch(Exception JavaDoc e)
808          {
809             throw new JBossXBRuntimeException("Failed to create an instance of " +
810                documentBindingClass +
811                " using constructor which takes one parameter of type " +
812                DocumentBinding.class +
813                ": " +
814                e.getMessage()
815             );
816          }
817          return doc;
818       }
819    }
820
821    class NamespaceBindingStack
822       implements NamespaceBinding
823    {
824       private final DocumentBinding doc;
825       private final String JavaDoc namespaceUri;
826       private final List JavaDoc delegates = new ArrayList JavaDoc();
827       private final Map JavaDoc tops = new HashMap JavaDoc();
828
829       public NamespaceBindingStack(DocumentBinding doc, String JavaDoc namespaceUri)
830       {
831          this.doc = doc;
832          this.namespaceUri = namespaceUri;
833       }
834
835       TopElementBinding bindTopElement(TopElementBinding top)
836       {
837          TopElementBindingStack stack = (TopElementBindingStack)getTopElement(top.getName().getLocalPart());
838          if(stack == null)
839          {
840             stack = new TopElementBindingStack(doc, top.getName());
841             tops.put(stack.getName().getLocalPart(), stack);
842          }
843          stack.push(top);
844          return stack;
845       }
846
847       void push(NamespaceBinding ns)
848       {
849          delegates.add(ns);
850       }
851
852       public String JavaDoc getNamespaceUri()
853       {
854          return namespaceUri;
855       }
856
857       public String JavaDoc getJavaPackage()
858       {
859          return ((AbstractNamespaceBinding)delegates.get(delegates.size() - 1)).getJavaPackageLocal();
860       }
861
862       public DocumentBinding getDocument()
863       {
864          return doc;
865       }
866
867       public TopElementBinding getTopElement(String JavaDoc elementName)
868       {
869          TopElementBindingStack stack = (TopElementBindingStack)tops.get(elementName);
870          if(stack == null)
871          {
872             stack = new TopElementBindingStack(doc, new QName JavaDoc(namespaceUri, elementName));
873             for(int i = 0; i < delegates.size(); ++i)
874             {
875                AbstractNamespaceBinding ns = (AbstractNamespaceBinding)delegates.get(i);
876                TopElementBinding local = ns.getTopElementLocal(elementName);
877                if(local != null)
878                {
879                   stack.push(local);
880                }
881             }
882
883             if(stack.delegates.size() > 0)
884             {
885                tops.put(elementName, stack);
886             }
887             else
888             {
889                stack = null;
890             }
891          }
892          return stack;
893       }
894    }
895
896    class XmlValueContainerStack
897       implements XmlValueContainer
898    {
899       protected final QName JavaDoc name;
900       final List JavaDoc delegates = new ArrayList JavaDoc();
901       private XmlValueBindingStack value;
902
903       public XmlValueContainerStack(QName JavaDoc name)
904       {
905          this.name = name;
906       }
907
908       void push(XmlValueContainer container)
909       {
910          delegates.add(container);
911       }
912
913       XmlValueBinding bindValue(XmlValueBinding value)
914       {
915          getValue();
916          if(this.value == null)
917          {
918             this.value = new XmlValueBindingStack(this);
919          }
920          this.value.push(value);
921          return this.value;
922       }
923
924       public QName JavaDoc getName()
925       {
926          return name;
927       }
928
929       public XmlValueBinding getValue()
930       {
931          if(value == null)
932          {
933             for(int i = 0; i < delegates.size(); ++i)
934             {
935                AbstractXmlValueContainer basic = (AbstractXmlValueContainer)delegates.get(i);
936                XmlValueBinding localValue = basic.getValueLocal();
937                if(localValue != null)
938                {
939                   if(value == null)
940                   {
941                      value = new XmlValueBindingStack(this);
942                   }
943                   value.push(localValue);
944                }
945             }
946          }
947          return value;
948       }
949
950       public Class JavaDoc getJavaType()
951       {
952          return ((AbstractXmlValueContainer)delegates.get(delegates.size() - 1)).getJavaTypeLocal();
953       }
954    }
955
956    class BasicElementBindingStack
957       extends XmlValueContainerStack
958       implements BasicElementBinding
959    {
960       private final DocumentBinding doc;
961       private final Map JavaDoc children = new HashMap JavaDoc();
962       private final Map JavaDoc attributes = new HashMap JavaDoc();
963
964       public BasicElementBindingStack(DocumentBinding doc, QName JavaDoc elementName)
965       {
966          super(elementName);
967          this.doc = doc;
968       }
969
970       ElementBinding bindChild(ElementBinding element)
971       {
972          ElementBindingStack stack = (ElementBindingStack)getElement(element.getName());
973          if(stack == null)
974          {
975             stack = new ElementBindingStack(doc, element.getName());
976             children.put(stack.getName(), stack);
977          }
978          stack.push(element);
979          return stack;
980       }
981
982       void bindAttribute(AttributeBinding attr)
983       {
984          attributes.put(attr.getAttributeName(), attr);
985       }
986
987       public DocumentBinding getDocument()
988       {
989          return doc;
990       }
991
992       public ElementBinding getElement(QName JavaDoc elementName)
993       {
994          ElementBindingStack stack = (ElementBindingStack)children.get(elementName);
995          if(stack == null)
996          {
997             stack = new ElementBindingStack(doc, elementName);
998             for(int i = 0; i < delegates.size(); ++i)
999             {
1000               AbstractBasicElementBinding el = (AbstractBasicElementBinding)delegates.get(i);
1001               ElementBinding local = el.getElementLocal(elementName);
1002               if(local != null)
1003               {
1004                  stack.push(local);
1005               }
1006            }
1007
1008            if(stack.delegates.size() > 0)
1009            {
1010               children.put(elementName, stack);
1011            }
1012            else
1013            {
1014               stack = null;
1015            }
1016         }
1017         return stack;
1018      }
1019
1020      public AttributeBinding getAttribute(QName JavaDoc attributeName)
1021      {
1022         AttributeBinding attr = (AttributeBinding)attributes.get(attributeName);
1023         if(attr == null)
1024         {
1025            for(int i = delegates.size() - 1; i >= 0; --i)
1026            {
1027               AbstractBasicElementBinding basic = (AbstractBasicElementBinding)delegates.get(i);
1028               attr = basic.getAttributeLocal(attributeName);
1029               if(attr != null)
1030               {
1031                  break;
1032               }
1033            }
1034         }
1035         return attr;
1036      }
1037   }
1038
1039   class TopElementBindingStack
1040      extends BasicElementBindingStack
1041      implements TopElementBinding
1042   {
1043      public TopElementBindingStack(DocumentBinding doc, QName JavaDoc elementName)
1044      {
1045         super(doc, elementName);
1046      }
1047   }
1048
1049   class ElementBindingStack
1050      extends BasicElementBindingStack
1051      implements ElementBinding
1052   {
1053      public ElementBindingStack(DocumentBinding doc, QName JavaDoc elementName)
1054      {
1055         super(doc, elementName);
1056      }
1057
1058      public Field JavaDoc getField()
1059      {
1060         return getLatestBinding().getFieldLocal();
1061      }
1062
1063      public Method JavaDoc getGetter()
1064      {
1065         return getLatestBinding().getGetterLocal();
1066      }
1067
1068      public Method JavaDoc getSetter()
1069      {
1070         return getLatestBinding().getSetterLocal();
1071      }
1072
1073      public Class JavaDoc getFieldType()
1074      {
1075         return getLatestBinding().getFieldTypeLocal();
1076      }
1077
1078      // Private
1079

1080      protected AbstractElementBinding getLatestBinding()
1081      {
1082         return (AbstractElementBinding)delegates.get(delegates.size() - 1);
1083      }
1084   }
1085
1086   class XmlValueBindingStack
1087      extends XmlValueContainerStack
1088      implements XmlValueBinding
1089   {
1090      public XmlValueBindingStack(XmlValueContainer container)
1091      {
1092         super(container.getName());
1093      }
1094
1095      public Field JavaDoc getField()
1096      {
1097         return getLatestBinding().getFieldLocal();
1098      }
1099
1100      public Method JavaDoc getGetter()
1101      {
1102         return getLatestBinding().getGetterLocal();
1103      }
1104
1105      public Method JavaDoc getSetter()
1106      {
1107         return getLatestBinding().getSetterLocal();
1108      }
1109
1110      public Class JavaDoc getFieldType()
1111      {
1112         return getLatestBinding().getFieldTypeLocal();
1113      }
1114
1115      private AbstractXmlValueBinding getLatestBinding()
1116      {
1117         return (AbstractXmlValueBinding)delegates.get(delegates.size() - 1);
1118      }
1119   }
1120}
1121
Popular Tags