KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > xb > binding > sunday > unmarshalling > XsdBinder


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.xb.binding.sunday.unmarshalling;
23
24 import java.io.InputStream JavaDoc;
25 import java.io.Reader JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.LinkedHashSet JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.ListIterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.ArrayList JavaDoc;
33 import java.util.Set JavaDoc;
34
35 import javax.xml.namespace.QName JavaDoc;
36
37 import org.apache.xerces.xs.StringList;
38 import org.apache.xerces.xs.XSAnnotation;
39 import org.apache.xerces.xs.XSAttributeDeclaration;
40 import org.apache.xerces.xs.XSAttributeUse;
41 import org.apache.xerces.xs.XSComplexTypeDefinition;
42 import org.apache.xerces.xs.XSConstants;
43 import org.apache.xerces.xs.XSElementDeclaration;
44 import org.apache.xerces.xs.XSModel;
45 import org.apache.xerces.xs.XSModelGroup;
46 import org.apache.xerces.xs.XSModelGroupDefinition;
47 import org.apache.xerces.xs.XSNamedMap;
48 import org.apache.xerces.xs.XSObjectList;
49 import org.apache.xerces.xs.XSParticle;
50 import org.apache.xerces.xs.XSSimpleTypeDefinition;
51 import org.apache.xerces.xs.XSTerm;
52 import org.apache.xerces.xs.XSTypeDefinition;
53 import org.apache.xerces.xs.XSWildcard;
54 import org.jboss.logging.Logger;
55 import org.jboss.xb.binding.Constants;
56 import org.jboss.xb.binding.JBossXBRuntimeException;
57 import org.jboss.xb.binding.Util;
58 import org.jboss.xb.binding.sunday.xop.XOPIncludeHandler;
59 import org.jboss.xb.binding.metadata.AddMethodMetaData;
60 import org.jboss.xb.binding.metadata.CharactersMetaData;
61 import org.jboss.xb.binding.metadata.ClassMetaData;
62 import org.jboss.xb.binding.metadata.MapEntryMetaData;
63 import org.jboss.xb.binding.metadata.PackageMetaData;
64 import org.jboss.xb.binding.metadata.PropertyMetaData;
65 import org.jboss.xb.binding.metadata.PutMethodMetaData;
66 import org.jboss.xb.binding.metadata.SchemaMetaData;
67 import org.jboss.xb.binding.metadata.ValueMetaData;
68 import org.jboss.xb.binding.metadata.XsdAnnotation;
69 import org.jboss.xb.binding.metadata.XsdAppInfo;
70
71 /**
72  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
73  * @version <tt>$Revision: 2109 $</tt>
74  */

75 public class XsdBinder
76 {
77    static final Logger log = Logger.getLogger(XsdBinder.class);
78
79    private XsdBinder()
80    {
81    }
82
83    /**
84     * Create a SchemaBinding from and xsd url/uri.
85     *
86     * @param xsdUrl
87     * @return SchemaBinding mapping
88     */

89    public static SchemaBinding bind(String JavaDoc xsdUrl)
90    {
91       DefaultSchemaResolver resolver = new DefaultSchemaResolver();
92       resolver.setBaseURI(xsdUrl);
93       return bind(xsdUrl, resolver);
94    }
95
96    /**
97     * Create a SchemaBinding from and xsd url/uri.
98     *
99     * @param xsdUrl
100     * @param resolver the resolver will be used to resolve imported schemas in the schema being loaded
101     * and also will be set on the returned instance of SchemaBinding
102     * @return SchemaBinding mapping
103     */

104    public static SchemaBinding bind(String JavaDoc xsdUrl, SchemaBindingResolver resolver)
105    {
106       XSModel model = Util.loadSchema(xsdUrl, resolver);
107       return bind(model, resolver);
108    }
109
110    public static SchemaBinding bind(InputStream JavaDoc xsdStream, String JavaDoc encoding)
111    {
112       return bind(xsdStream, encoding, new DefaultSchemaResolver());
113    }
114
115    /**
116     * Create a SchemaBinding from and xsd stream.
117     *
118     * @param xsdStream - the xsd InputStream
119     * @param encoding - optional stream encoding
120     * @return SchemaBinding mapping
121     */

122    public static SchemaBinding bind(InputStream JavaDoc xsdStream, String JavaDoc encoding, String JavaDoc baseURI)
123    {
124       return bind(xsdStream, encoding, baseURI, true);
125    }
126
127    /**
128     * Create a SchemaBinding from and xsd stream.
129     *
130     * @param xsdStream - the xsd InputStream
131     * @param encoding - optional stream encoding
132     * @param processAnnotations - process annotations
133     * @return SchemaBinding mapping
134     */

135    public static SchemaBinding bind(InputStream JavaDoc xsdStream, String JavaDoc encoding, String JavaDoc baseURI, boolean processAnnotations)
136    {
137       DefaultSchemaResolver resolver = new DefaultSchemaResolver();
138       resolver.setBaseURI(baseURI);
139       return bind(xsdStream, encoding, resolver, processAnnotations);
140    }
141
142    /**
143     * Create a SchemaBinding from and xsd stream.
144     *
145     * @param xsdStream - the xsd InputStream
146     * @param encoding - optional stream encoding
147     * @param resolver the resolver will be used to resolve imported schemas in the schema being loaded
148     * and also will be set on the returned instance of SchemaBinding
149     * @return SchemaBinding mapping
150     */

151    public static SchemaBinding bind(InputStream JavaDoc xsdStream, String JavaDoc encoding, SchemaBindingResolver resolver)
152    {
153       return bind(xsdStream, encoding, resolver, true);
154    }
155
156    /**
157     * Create a SchemaBinding from and xsd stream.
158     *
159     * @param xsdStream - the xsd InputStream
160     * @param encoding - optional stream encoding
161     * @param resolver the resolver will be used to resolve imported schemas in the schema being loaded
162     * and also will be set on the returned instance of SchemaBinding
163     * @param processAnnotations whether to process annotations
164     * @return SchemaBinding mapping
165     */

166    public static SchemaBinding bind(InputStream JavaDoc xsdStream, String JavaDoc encoding, SchemaBindingResolver resolver, boolean processAnnotations)
167    {
168       XSModel model = Util.loadSchema(xsdStream, encoding, resolver);
169       return bind(model, resolver, processAnnotations);
170    }
171
172    public static SchemaBinding bind(Reader JavaDoc xsdReader, String JavaDoc encoding)
173    {
174       return bind(xsdReader, encoding, new DefaultSchemaResolver());
175    }
176
177    /**
178     * Create a SchemaBinding from and xsd reader.
179     *
180     * @param xsdReader - xsd reader
181     * @param encoding - optional reader encoding
182     * @return SchemaBinding mapping
183     */

184    public static SchemaBinding bind(Reader JavaDoc xsdReader, String JavaDoc encoding, String JavaDoc baseURI)
185    {
186       DefaultSchemaResolver resolver = new DefaultSchemaResolver();
187       resolver.setBaseURI(baseURI);
188       return bind(xsdReader, encoding, resolver);
189    }
190
191    /**
192     * Create a SchemaBinding from and xsd reader.
193     *
194     * @param xsdReader - xsd reader
195     * @param encoding - optional reader encoding
196     * @param resolver the resolver will be used to resolve imported schemas in the schema being loaded
197     * and also will be set on the returned instance of SchemaBinding
198     * @return SchemaBinding mapping
199     */

200    public static SchemaBinding bind(Reader JavaDoc xsdReader, String JavaDoc encoding, SchemaBindingResolver resolver)
201    {
202       XSModel model = Util.loadSchema(xsdReader, encoding, resolver);
203       return bind(model, resolver);
204    }
205
206    /**
207     * Create a SchemaBinding from and xsd string.
208     *
209     * @param xsd - xsd string
210     * @param encoding - optional string encoding
211     * @return SchemaBinding mapping
212     */

213    public static SchemaBinding bind(String JavaDoc xsd, String JavaDoc encoding)
214    {
215       return bind(xsd, encoding, new DefaultSchemaResolver());
216    }
217
218    /**
219     * Create a SchemaBinding from and xsd string.
220     *
221     * @param xsd - xsd string
222     * @param encoding - optional string encoding
223     * @param resolver the resolver will be used to resolve imported schemas in the schema being loaded
224     * and also will be set on the returned instance of SchemaBinding
225     * @return SchemaBinding mapping
226     */

227    public static SchemaBinding bind(String JavaDoc xsd, String JavaDoc encoding, SchemaBindingResolver resolver)
228    {
229       XSModel model = Util.loadSchema(xsd, encoding);
230       return bind(model, resolver);
231    }
232
233    public static SchemaBinding bind(XSModel model, SchemaBindingResolver resolver)
234    {
235       return bind(model,resolver, true);
236    }
237
238    public static SchemaBinding bind(XSModel model, SchemaBindingResolver resolver, boolean processAnnotations)
239    {
240       Context ctx = new Context();
241       ctx.processAnnotations = processAnnotations;
242       SchemaBinding schema = ctx.schema;
243       schema.setSchemaResolver(resolver);
244
245       // read annotations. for now just log the ones that are going to be used
246
if (ctx.processAnnotations)
247       {
248          XSObjectList annotations = model.getAnnotations();
249          if (ctx.trace)
250          {
251             log.trace("started binding schema " + schema);
252             log.trace("Schema annotations: " + annotations.getLength());
253          }
254
255          for(int i = 0; i < annotations.getLength(); ++i)
256          {
257             XSAnnotation annotation = (XSAnnotation)annotations.item(i);
258             XsdAnnotation an = XsdAnnotation.unmarshal(annotation.getAnnotationString());
259             XsdAppInfo appinfo = an.getAppInfo();
260             if(appinfo != null)
261             {
262                SchemaMetaData schemaBindings = appinfo.getSchemaMetaData();
263                if(schemaBindings != null)
264                {
265                   // Get the ignoreUnresolvedFieldOrClass
266
schema.setIgnoreUnresolvedFieldOrClass(schemaBindings.isIgnoreUnresolvedFieldOrClass());
267                   // Get the ignoreUnresolvedFieldOrClass
268
schema.setReplacePropertyRefs(schemaBindings.isReplacePropertyRefs());
269                   // Get the default package
270
PackageMetaData packageMetaData = schemaBindings.getPackage();
271                   if(packageMetaData != null)
272                   {
273                      if (ctx.trace)
274                         log.trace("schema default package: " + packageMetaData.getName());
275                      schema.setPackageMetaData(packageMetaData);
276                   }
277                }
278             }
279          }
280       }
281
282       StringList namespaceList = model.getNamespaces();
283       Set JavaDoc namespaces = new LinkedHashSet JavaDoc(namespaceList.getLength());
284       for (int i = 0; i < namespaceList.getLength(); ++i)
285          namespaces.add(namespaceList.item(i));
286       schema.setNamespaces(namespaces);
287       
288       XSNamedMap groups = model.getComponents(XSConstants.MODEL_GROUP_DEFINITION);
289       if (ctx.trace)
290          log.trace("Model groups: " + groups.getLength());
291       for(int i = 0; i < groups.getLength(); ++i)
292       {
293          XSModelGroupDefinition groupDef = (XSModelGroupDefinition)groups.item(i);
294          bindGlobalGroup(groupDef.getModelGroup(), ctx.sharedElements);
295       }
296
297       XSNamedMap types = model.getComponents(XSConstants.TYPE_DEFINITION);
298       if (ctx.trace)
299          log.trace("Model types: " + types.getLength());
300       for(int i = 0; i < types.getLength(); ++i)
301       {
302          XSTypeDefinition type = (XSTypeDefinition)types.item(i);
303          if(!Constants.NS_XML_SCHEMA.equals(type.getNamespace()))
304          {
305             bindType(ctx, type);
306          }
307       }
308
309       XSNamedMap elements = model.getComponents(XSConstants.ELEMENT_DECLARATION);
310       if (ctx.trace)
311          log.trace("Model elements: " + types.getLength());
312       for(int i = 0; i < elements.getLength(); ++i)
313       {
314          XSElementDeclaration element = (XSElementDeclaration)elements.item(i);
315          bindElement(ctx, element, 1, 0, false);
316       }
317
318       if (ctx.trace)
319       {
320          log.trace("finished binding schema " + schema);
321       }
322
323       return schema;
324    }
325
326    /**
327     * @param schema schema binding the type should be added to
328     * @param type type definition to be bound
329     * @deprecated <i>This method is added temporary to get anonymous type binding working in JBossWS.
330     * It will be removed when anonymous type binding in JBossWS is implemented properly.
331     * No one else should use this method.</i>
332     *
333     * <p>This method binds a type definition and adds it as a global type to the passed in schema binding.
334     */

335    public static void bindType(SchemaBinding schema, XSTypeDefinition type)
336    {
337       TypeBinding typeBinding = bindType(new Context(schema), type);
338       schema.addType(typeBinding);
339    }
340
341    /**
342     * @param schema schema binding the type should be added to
343     * @param element element declaration to be bound
344     * @param minOccurs
345     * @param maxOccurs
346     * @param maxOccursUnbounded
347     * @deprecated <i>This method is added temporary to get anonymous type binding working in JBossWS.
348     * It will be removed when anonymous type binding in JBossWS is implemented properly.
349     * No one else should use this method.</i>
350     *
351     * <p>This method binds an element declaration and adds it as a global element to the passed in schema binding.
352     */

353    public static void bindElement(SchemaBinding schema,
354                                   XSElementDeclaration element,
355                                   int minOccurs,
356                                   int maxOccurs,
357                                   boolean maxOccursUnbounded)
358    {
359       ParticleBinding particle = bindElement(new Context(schema),
360          element,
361          minOccurs,
362          maxOccurs,
363          maxOccursUnbounded
364       );
365       schema.addElementParticle(particle);
366    }
367
368    // Private
369

370    private static TypeBinding bindType(Context ctx, XSTypeDefinition type)
371    {
372       TypeBinding binding;
373       switch(type.getTypeCategory())
374       {
375          case XSTypeDefinition.SIMPLE_TYPE:
376             binding = bindSimpleType(ctx, (XSSimpleTypeDefinition)type);
377             break;
378          case XSTypeDefinition.COMPLEX_TYPE:
379             binding = bindComplexType(ctx, (XSComplexTypeDefinition)type);
380             break;
381          default:
382             throw new JBossXBRuntimeException("Unexpected type category: " + type.getTypeCategory());
383       }
384       return binding;
385    }
386
387    private static TypeBinding bindSimpleType(Context ctx, XSSimpleTypeDefinition type)
388    {
389       QName JavaDoc typeName = type.getName() == null ? null : new QName JavaDoc(type.getNamespace(), type.getName());
390       TypeBinding binding = typeName == null ? null : ctx.schema.getType(typeName);
391       if(binding != null)
392       {
393          return binding;
394       }
395
396       if(ctx.trace)
397       {
398          log.trace("binding simple type " + typeName);
399       }
400
401       XSTypeDefinition baseTypeDef = type.getBaseType();
402       TypeBinding baseType = baseTypeDef == null ? null : bindType(ctx, baseTypeDef);
403
404       binding = baseType == null ? new TypeBinding(typeName) : new TypeBinding(typeName, baseType);
405
406       StringList strList = type.getLexicalPattern();
407       if(strList != null && strList.getLength() > 0)
408       {
409          for(int i = 0; i < strList.getLength(); ++i)
410          {
411             binding.addLexicalPattern(strList.item(i));
412          }
413       }
414
415       strList = type.getLexicalEnumeration();
416       if(strList != null && strList.getLength() > 0)
417       {
418          for(int i = 0; i < strList.getLength(); ++i)
419          {
420             binding.addEnumValue(strList.item(i));
421          }
422       }
423
424       if(type.getItemType() != null)
425       {
426          TypeBinding itemType = bindSimpleType(ctx, type.getItemType());
427          binding.setItemType(itemType);
428       }
429
430       if(typeName != null)
431       {
432          ctx.schema.addType(binding);
433       }
434
435       if(ctx.trace)
436       {
437          String JavaDoc msg = typeName == null ? "bound simple anonymous type" : "bound simple type " + typeName;
438          if(baseType != null)
439          {
440             msg += " inherited binding metadata from " + baseType.getQName();
441          }
442          log.trace(msg);
443       }
444
445       // customize binding with annotations
446
if(ctx.processAnnotations)
447       {
448          XSObjectList annotations = type.getAnnotations();
449          if(annotations != null)
450          {
451             if(ctx.trace)
452             {
453                log.trace(typeName + " annotations " + annotations.getLength());
454             }
455             for(int i = 0; i < annotations.getLength(); ++i)
456             {
457                XSAnnotation an = (XSAnnotation)annotations.item(i);
458                XsdAnnotation xsdAn = XsdAnnotation.unmarshal(an.getAnnotationString());
459                XsdAppInfo appInfo = xsdAn.getAppInfo();
460                if(appInfo != null)
461                {
462                   ClassMetaData classMetaData = appInfo.getClassMetaData();
463                   if(classMetaData != null)
464                   {
465                      if(ctx.trace)
466                      {
467                         log.trace("simple type " +
468                            type.getName() +
469                            ": impl=" +
470                            classMetaData.getImpl());
471                      }
472                      binding.setClassMetaData(classMetaData);
473                   }
474
475                   ValueMetaData valueMetaData = appInfo.getValueMetaData();
476                   if(valueMetaData != null)
477                   {
478                      if(ctx.trace)
479                      {
480                         log.trace("simple type " +
481                            type.getName() +
482                            ": unmarshalMethod=" +
483                            valueMetaData.getUnmarshalMethod() +
484                            ", marshalMethod=" +
485                            valueMetaData.getMarshalMethod());
486                      }
487                      binding.setValueMetaData(valueMetaData);
488                   }
489                }
490             }
491          }
492       }
493
494       binding.setSchemaBinding(ctx.schema);
495
496       return binding;
497    }
498
499    private static TypeBinding bindComplexType(Context ctx, XSComplexTypeDefinition type)
500    {
501       QName JavaDoc typeName = type.getName() == null ? null : new QName JavaDoc(type.getNamespace(), type.getName());
502       TypeBinding binding = typeName == null ? null : ctx.schema.getType(typeName);
503       if(binding != null)
504       {
505          return binding;
506       }
507
508       XSTypeDefinition baseTypeDef = type.getBaseType();
509       // anyType is the parent of all the types, even the parent of itself according to xerces :)
510
TypeBinding baseType = null;
511       if(baseTypeDef != null && !Constants.QNAME_ANYTYPE.equals(typeName))
512       {
513          baseType = bindType(ctx, baseTypeDef);
514          // sometimes binding the base type can lead to another request
515
// to bind the type being bound here
516
if(typeName != null)
517          {
518             binding = ctx.schema.getType(typeName);
519             if(binding != null)
520             {
521                return binding;
522             }
523          }
524       }
525
526       if (ctx.trace)
527          log.trace("binding complex " + (typeName == null ? "anonymous type" : "type " + typeName));
528
529       binding = new TypeBinding(typeName);
530       binding.setBaseType(baseType);
531       binding.setStartElementCreatesObject(true);
532       binding.setSimple(false);
533
534       if(type.getSimpleType() != null)
535       {
536          TypeBinding simpleType = bindSimpleType(ctx, type.getSimpleType());
537          binding.setSimpleType(simpleType);
538       }
539       else if(type.getContentType() == XSComplexTypeDefinition.CONTENTTYPE_MIXED)
540       {
541          TypeBinding stringType = ctx.schema.getType(Constants.QNAME_STRING);
542          if(stringType == null)
543          {
544             throw new JBossXBRuntimeException("xsd:string has not been bound yet!");
545          }
546          binding.setSimpleType(stringType);
547       }
548
549       if(typeName != null)
550       {
551          ctx.schema.addType(binding);
552       }
553
554       binding.setSchemaBinding(ctx.schema);
555
556       XSObjectList attrs = type.getAttributeUses();
557       if (ctx.trace)
558          log.trace(typeName + " attributes " + attrs.getLength());
559       for(int i = 0; i < attrs.getLength(); ++i)
560       {
561          XSAttributeUse attr = (XSAttributeUse)attrs.item(i);
562          bindAttributes(ctx, binding, attr);
563       }
564
565       // customize binding with xsd annotations
566
if (ctx.processAnnotations)
567       {
568          XSObjectList annotations = type.getAnnotations();
569          if(annotations != null)
570          {
571             if (ctx.trace)
572                log.trace(typeName + " annotations " + annotations.getLength());
573             for(int i = 0; i < annotations.getLength(); ++i)
574             {
575                XSAnnotation an = (XSAnnotation)annotations.item(i);
576                XsdAnnotation xsdAn = XsdAnnotation.unmarshal(an.getAnnotationString());
577                XsdAppInfo appInfo = xsdAn.getAppInfo();
578                if(appInfo != null)
579                {
580                   ClassMetaData classMetaData = appInfo.getClassMetaData();
581                   if(classMetaData != null)
582                   {
583                      if (ctx.trace)
584                      {
585                         log.trace("complex type " +
586                            type.getName() +
587                            ": impl=" +
588                            classMetaData.getImpl()
589                         );
590                      }
591                      binding.setClassMetaData(classMetaData);
592                   }
593
594                   CharactersMetaData charactersMetaData = appInfo.getCharactersMetaData();
595                   if(charactersMetaData != null)
596                   {
597                      if (ctx.trace)
598                      {
599                         PropertyMetaData propertyMetaData = charactersMetaData.getProperty();
600                         if(propertyMetaData != null)
601                         {
602                            log.trace("complex type " +
603                               type.getName() +
604                               ": characters bound to " + propertyMetaData.getName()
605                            );
606                         }
607
608                         ValueMetaData valueMetaData = charactersMetaData.getValue();
609                         if(valueMetaData != null)
610                         {
611                            log.trace("complex type " +
612                               type.getName() +
613                               ": characters unmarshalMethod=" +
614                               valueMetaData.getUnmarshalMethod() +
615                               ", marshalMethod=" + valueMetaData.getMarshalMethod()
616                            );
617                         }
618
619                         boolean mapEntryKey = appInfo.isMapEntryKey();
620                         if(mapEntryKey)
621                         {
622                            log.trace("complex type " +
623                               type.getName() +
624                               ": characters are bound as a key in a map entry"
625                            );
626                         }
627
628                         boolean mapEntryValue = appInfo.isMapEntryValue();
629                         if(mapEntryValue)
630                         {
631                            log.trace("complex type " +
632                               type.getName() +
633                               ": characters are bound as a value in a map entry"
634                            );
635                         }
636                      }
637                      binding.setCharactersMetaData(charactersMetaData);
638                   }
639
640                   MapEntryMetaData mapEntryMetaData = appInfo.getMapEntryMetaData();
641                   if(mapEntryMetaData != null)
642                   {
643                      if (ctx.trace)
644                      {
645                         log.trace("complex type " +
646                            type.getName() +
647                            " is bound to a map entry: impl=" +
648                            mapEntryMetaData.getImpl() +
649                            ", getKeyMethod=" +
650                            mapEntryMetaData.getGetKeyMethod() +
651                            ", setKeyMethod=" +
652                            mapEntryMetaData.getSetKeyMethod() +
653                            ", getValueMethod=" +
654                            mapEntryMetaData.getGetValueMethod() +
655                            ", setValueMethod=" +
656                            mapEntryMetaData.getSetValueMethod() +
657                            ", valueType=" +
658                            mapEntryMetaData.getValueType() +
659                            ", nonNullValue=" + mapEntryMetaData.isNonNullValue()
660                         );
661                      }
662
663                      if(classMetaData != null)
664                      {
665                         throw new JBossXBRuntimeException("Illegal binding: both jbxb:class and jbxb:mapEntry are specified for complex type " +
666                            type.getName()
667                         );
668                      }
669                      binding.setMapEntryMetaData(mapEntryMetaData);
670                   }
671
672                   boolean skip = appInfo.isSkip();
673                   if(skip)
674                   {
675                      if (ctx.trace)
676                      {
677                         log.trace("complex type " +
678                            type.getName() +
679                            ": elements of this type will be skipped; their attrs, character content " +
680                            "and elements will be set the parent."
681                         );
682                      }
683                      binding.setSkip(skip);
684                   }
685
686                   PropertyMetaData propertyMetaData = appInfo.getPropertyMetaData();
687                   if(propertyMetaData != null)
688                   {
689                      if (ctx.trace)
690                      {
691                         log.trace("complex type " +
692                            type.getName() +
693                            ": the content of elements of this type is bound to property " + propertyMetaData.getName()
694                         );
695                      }
696                      binding.setPropertyMetaData(propertyMetaData);
697                   }
698
699                   AddMethodMetaData addMethodMetaData = appInfo.getAddMethodMetaData();
700                   if(addMethodMetaData != null)
701                   {
702                      if (ctx.trace)
703                      {
704                         log.trace("complex type " +
705                            type.getName() +
706                            ": elements of this type will be added to parent objects with addMethod=" +
707                            addMethodMetaData.getMethodName() + ", valueType=" + addMethodMetaData.getValueType()
708                         );
709                      }
710                      binding.setAddMethodMetaData(addMethodMetaData);
711                   }
712                }
713             }
714          }
715       }
716
717       XSParticle particle = type.getParticle();
718       if(particle != null)
719       {
720          ctx.pushType(binding);
721          bindParticle(ctx, particle);
722          ctx.popType();
723       }
724
725       if(binding.hasOnlyXmlMimeAttributes())
726       {
727          addXOPInclude(binding, ctx.schema);
728       }
729
730       if(ctx.trace)
731       {
732          log.trace(typeName == null ? "bound complex anonymous type" : "bound complex type " + typeName);
733       }
734
735       return binding;
736    }
737
738    private static void bindAttributes(Context ctx, TypeBinding type, XSAttributeUse attrUse)
739    {
740       XSAttributeDeclaration attr = attrUse.getAttrDeclaration();
741       QName JavaDoc attrName = new QName JavaDoc(attr.getNamespace(), attr.getName());
742
743       if (ctx.trace)
744       {
745          log.trace("binding attribute " + attrName + " for " + type.getQName() + ", required=" + attrUse.getRequired());
746       }
747
748       XSSimpleTypeDefinition attrType = attr.getTypeDefinition();
749       TypeBinding typeBinding = bindSimpleType(ctx, attrType);
750       AttributeBinding binding = type.addAttribute(attrName, typeBinding, DefaultHandlers.ATTRIBUTE_HANDLER);
751       binding.setRequired(attrUse.getRequired());
752       if(attrUse.getConstraintType() == XSConstants.VC_DEFAULT)
753       {
754          // Associate the default value with the binding
755
binding.setDefaultConstraint(attrUse.getConstraintValue());
756       }
757
758       if (ctx.processAnnotations)
759       {
760          XSAnnotation an = attr.getAnnotation();
761          if(an != null)
762          {
763             if (ctx.trace)
764             {
765                log.trace(attrName + " attribute annotation");
766             }
767
768             XsdAnnotation xsdAn = XsdAnnotation.unmarshal(an.getAnnotationString());
769             XsdAppInfo appInfo = xsdAn.getAppInfo();
770             if(appInfo != null)
771             {
772                PropertyMetaData propertyMetaData = appInfo.getPropertyMetaData();
773                if(propertyMetaData != null)
774                {
775                   binding.setPropertyMetaData(propertyMetaData);
776                }
777
778                boolean mapEntryKey = appInfo.isMapEntryKey();
779                if(mapEntryKey)
780                {
781                   binding.setMapEntryKey(mapEntryKey);
782                }
783
784                boolean mapEntryValue = appInfo.isMapEntryValue();
785                if(mapEntryValue)
786                {
787                   binding.setMapEntryValue(mapEntryValue);
788                }
789             }
790          }
791       }
792
793
794       if (ctx.trace)
795       {
796          String JavaDoc msg = "bound attribute " + attrName;
797
798          if(binding.getPropertyMetaData() != null)
799          {
800             msg += " property=" +
801                binding.getPropertyMetaData().getName() +
802                ", collectionType=" + binding.getPropertyMetaData().getCollectionType();
803          }
804          else if(binding.isMapEntryKey())
805          {
806             msg += "bound as a key in a map entry";
807          }
808          else if(binding.isMapEntryValue())
809          {
810             msg += "bound as a value in a map entry";
811          }
812          else
813          {
814             msg += " type=" + attrType.getName() + ", owner type=" + type.getQName();
815          }
816
817          if(binding.getDefaultConstraint() != null)
818          {
819             msg += ", default=" + binding.getDefaultConstraint();
820          }
821
822          log.trace(msg);
823       }
824    }
825
826    private static void bindParticle(Context ctx, XSParticle particle)
827    {
828       XSTerm term = particle.getTerm();
829       switch(term.getType())
830       {
831          case XSConstants.MODEL_GROUP:
832             XSModelGroup modelGroup = (XSModelGroup)term;
833             // todo: investigate this
834
if(modelGroup.getParticles().getLength() > 0)
835             {
836                ModelGroupBinding groupBinding;
837                switch(modelGroup.getCompositor())
838                {
839                   case XSModelGroup.COMPOSITOR_ALL:
840                      groupBinding = new AllBinding(ctx.schema);
841                      break;
842                   case XSModelGroup.COMPOSITOR_CHOICE:
843                      groupBinding = new ChoiceBinding(ctx.schema);
844                      break;
845                   case XSModelGroup.COMPOSITOR_SEQUENCE:
846                      groupBinding = new SequenceBinding(ctx.schema);
847                      break;
848                   default:
849                      throw new JBossXBRuntimeException("Unexpected model group: " + modelGroup.getCompositor());
850                }
851
852                ParticleBinding particleBinding = new ParticleBinding(groupBinding);
853                particleBinding.setMaxOccursUnbounded(particle.getMaxOccursUnbounded());
854                particleBinding.setMinOccurs(particle.getMinOccurs());
855                particleBinding.setMaxOccurs(particle.getMaxOccurs());
856
857                if (ctx.trace)
858                {
859                   log.trace("created model group " + groupBinding);
860                }
861
862                if (ctx.processAnnotations)
863                {
864                   XSAnnotation annotation = modelGroup.getAnnotation();
865                   if(annotation != null)
866                   {
867                      customizeTerm(annotation, groupBinding, ctx.trace);
868                   }
869                }
870
871                Object JavaDoc o = ctx.peekTypeOrGroup();
872                if(o instanceof ModelGroupBinding)
873                {
874                   ModelGroupBinding parentGroup = (ModelGroupBinding)o;
875                   parentGroup.addParticle(particleBinding);
876                   if (ctx.trace)
877                   {
878                      log.trace("added " + groupBinding + " to " + parentGroup);
879                   }
880                }
881                else if(o instanceof TypeBinding)
882                {
883                   TypeBinding typeBinding = (TypeBinding)o;
884                   typeBinding.setParticle(particleBinding);
885                   if (ctx.trace)
886                   {
887                      log.trace("added " + groupBinding + " to type " + typeBinding.getQName());
888                   }
889                }
890
891                ctx.pushModelGroup(groupBinding);
892                bindModelGroup(ctx, modelGroup);
893                ctx.popModelGroup();
894             }
895             break;
896          case XSConstants.WILDCARD:
897             bindWildcard(ctx, particle);
898             break;
899          case XSConstants.ELEMENT_DECLARATION:
900             bindElement(ctx,
901                (XSElementDeclaration)term,
902                particle.getMinOccurs(),
903                particle.getMaxOccurs(),
904                particle.getMaxOccursUnbounded()
905             );
906             break;
907          default:
908             throw new IllegalStateException JavaDoc("Unexpected term type: " + term.getType());
909       }
910    }
911
912    private static void bindWildcard(Context ctx, XSParticle particle)
913    {
914       WildcardBinding binding = new WildcardBinding(ctx.schema);
915
916       ModelGroupBinding group = (ModelGroupBinding)ctx.peekTypeOrGroup();
917       ParticleBinding particleBinding = new ParticleBinding(binding);
918       particleBinding.setMaxOccurs(particle.getMaxOccurs());
919       particleBinding.setMaxOccursUnbounded(particle.getMaxOccursUnbounded());
920       particleBinding.setMinOccurs(particle.getMinOccurs());
921       group.addParticle(particleBinding);
922
923       TypeBinding type = ctx.peekType();
924       type.setWildcard(binding);
925
926       if (ctx.trace)
927       {
928          log.trace("added wildcard to " + group);
929          log.trace("added wildcard to type " + type.getQName());
930       }
931
932       XSWildcard wildcard = (XSWildcard)particle.getTerm();
933       if(wildcard.getName() != null)
934       {
935          binding.setQName(new QName JavaDoc(wildcard.getNamespace(), wildcard.getName()));
936       }
937
938       binding.setProcessContents(wildcard.getProcessContents());
939
940       if (ctx.processAnnotations)
941       {
942          XSAnnotation annotation = wildcard.getAnnotation();
943          if(annotation != null)
944          {
945             customizeTerm(annotation, binding, ctx.trace);
946          }
947       }
948    }
949
950    private static ParticleBinding bindElement(Context ctx,
951                                               XSElementDeclaration elementDec,
952                                               int minOccurs,
953                                               int maxOccurs,
954                                               boolean maxOccursUnbounded)
955    {
956       QName JavaDoc qName = new QName JavaDoc(elementDec.getNamespace(), elementDec.getName());
957
958       ModelGroupBinding parentGroup = (ModelGroupBinding)ctx.peekTypeOrGroup();
959
960       boolean global = elementDec.getScope() == XSConstants.SCOPE_GLOBAL;
961       ElementBinding element = ctx.schema.getElement(qName);
962       ParticleBinding particle;
963       if(global && element != null)
964       {
965          particle = new ParticleBinding(element);
966          if(parentGroup != null)
967          {
968             parentGroup.addParticle(particle);
969          }
970
971          particle.setMinOccurs(minOccurs);
972          if(maxOccursUnbounded)
973          {
974             particle.setMaxOccursUnbounded(maxOccursUnbounded);
975          }
976          else
977          {
978             particle.setMaxOccurs(maxOccurs);
979          }
980
981          return particle;
982       }
983
984       TypeBinding type = null;
985
986       boolean shared = ctx.sharedElements.isShared(elementDec);
987       if(shared)
988       {
989          type = ctx.sharedElements.getTypeBinding(elementDec);
990       }
991
992       if(type == null)
993       {
994          type = bindType(ctx, elementDec.getTypeDefinition());
995          if(shared)
996          {
997             ctx.sharedElements.setTypeBinding(elementDec, type);
998          }
999       }
1000
1001      element = new ElementBinding(ctx.schema, qName, type);
1002      element.setNillable(elementDec.getNillable());
1003      particle = new ParticleBinding(element);
1004      particle.setMinOccurs(minOccurs);
1005      particle.setMaxOccurs(maxOccurs);
1006      particle.setMaxOccursUnbounded(maxOccursUnbounded);
1007      if(global)
1008      {
1009         ctx.schema.addElementParticle(particle);
1010      }
1011
1012      if(parentGroup != null)
1013      {
1014         parentGroup.addParticle(particle);
1015         if (ctx.trace)
1016         {
1017            log.trace("Element " + element.getQName() + " added to " + parentGroup);
1018         }
1019      }
1020
1021      if (ctx.trace)
1022      {
1023         TypeBinding parentType = ctx.peekType();
1024         log.trace("element: name=" +
1025            qName +
1026            ", type=" +
1027            type.getQName() +
1028            ", repeatable=" +
1029            particle.isRepeatable() +
1030            ", nillable=" +
1031            element.isNillable() +
1032            ", minOccurs=" + minOccurs +
1033            ", maxOccurs=" + (maxOccursUnbounded ? "unbounded" : "" + maxOccurs) +
1034            ", " + (global ? "global scope" : " owner type=" + parentType.getQName())
1035         );
1036      }
1037
1038      // customize element with annotations
1039
if (ctx.processAnnotations)
1040      {
1041         XSAnnotation an = elementDec.getAnnotation();
1042         if(an != null)
1043         {
1044            customizeTerm(an, element, ctx.trace);
1045         }
1046      }
1047      return particle;
1048   }
1049
1050   private static void bindModelGroup(Context ctx, XSModelGroup modelGroup)
1051   {
1052      XSObjectList particles = modelGroup.getParticles();
1053      for(int i = 0; i < particles.getLength(); ++i)
1054      {
1055         XSParticle particle = (XSParticle)particles.item(i);
1056         bindParticle(ctx, particle);
1057      }
1058   }
1059
1060   // Private
1061

1062   private static void addXOPInclude(TypeBinding binding, SchemaBinding schema)
1063   {
1064      binding.setHandler(DefaultHandlers.XOP_HANDLER);
1065      if(binding.getParticle() != null)
1066      {
1067         throw new JBossXBRuntimeException(
1068            "XOP optimizable type has a particle which is unexpected, please, open a JIRA issue!"
1069         );
1070      }
1071
1072      TypeBinding anyUriType = schema.getType(Constants.QNAME_ANYURI);
1073      if(anyUriType == null)
1074      {
1075         log.warn("Type " + Constants.QNAME_ANYURI + " not bound.");
1076      }
1077
1078      TypeBinding xopIncludeType = new TypeBinding(new QName JavaDoc(Constants.NS_XOP_INCLUDE, "Include"));
1079      xopIncludeType.setSchemaBinding(schema);
1080      xopIncludeType.addAttribute(new QName JavaDoc("href"), anyUriType, DefaultHandlers.ATTRIBUTE_HANDLER);
1081      xopIncludeType.setHandler(new XOPIncludeHandler(binding));
1082
1083      ElementBinding xopInclude = new ElementBinding(schema, new QName JavaDoc(Constants.NS_XOP_INCLUDE, "Include"), xopIncludeType);
1084
1085      ParticleBinding particleBinding = new ParticleBinding(xopInclude);
1086      particleBinding.setMinOccurs(0);
1087
1088      binding.addParticle(particleBinding);
1089   }
1090
1091   private static void customizeTerm(XSAnnotation an, TermBinding term, boolean trace)
1092   {
1093      XsdAnnotation xsdAn = XsdAnnotation.unmarshal(an.getAnnotationString());
1094      XsdAppInfo appInfo = xsdAn.getAppInfo();
1095      if(appInfo != null)
1096      {
1097         Boolean JavaDoc skip = null;
1098
1099         ClassMetaData classMetaData = appInfo.getClassMetaData();
1100         if(classMetaData != null)
1101         {
1102            if (trace)
1103            {
1104               String JavaDoc msg;
1105               if(term.isModelGroup())
1106               {
1107                  msg = term + " bound to ";
1108               }
1109               else if(term.isWildcard())
1110               {
1111                  msg = " wildcard bound to ";
1112               }
1113               else
1114               {
1115                  msg = "element: name=" + ((ElementBinding)term).getQName() + ", class=";
1116               }
1117
1118               msg += classMetaData.getImpl();
1119               log.trace(msg);
1120            }
1121            term.setClassMetaData(classMetaData);
1122            skip = Boolean.FALSE;
1123         }
1124
1125         PropertyMetaData propertyMetaData = appInfo.getPropertyMetaData();
1126         if(propertyMetaData != null)
1127         {
1128            if (trace)
1129            {
1130               String JavaDoc msg = term.isWildcard() || term.isModelGroup() ? term + " " : "element: name=" +
1131                  ((ElementBinding)term).getQName() + ", ";
1132               msg += " property=" +
1133                  propertyMetaData.getName() +
1134                  ", collectionType=" + propertyMetaData.getCollectionType();
1135               log.trace(msg);
1136            }
1137            term.setPropertyMetaData(propertyMetaData);
1138         }
1139
1140         MapEntryMetaData mapEntryMetaData = appInfo.getMapEntryMetaData();
1141         if(mapEntryMetaData != null)
1142         {
1143            if(propertyMetaData != null)
1144            {
1145               String JavaDoc msg = "A term can be bound either as a property or as a map" +
1146                  " entry but not both: " +
1147                  (term.isModelGroup() ? term.toString() : ((ElementBinding)term).getQName().toString());
1148               throw new JBossXBRuntimeException(msg);
1149            }
1150
1151            if (trace)
1152            {
1153               String JavaDoc msg = term.isWildcard() || term.isModelGroup() ? term.toString() : "element name=" +
1154                  ((ElementBinding)term).getQName();
1155
1156               msg += " is bound to a map entry: impl=" +
1157                  mapEntryMetaData.getImpl() +
1158                  ", getKeyMethod=" +
1159                  mapEntryMetaData.getGetKeyMethod() +
1160                  ", setKeyMethod=" +
1161                  mapEntryMetaData.getSetKeyMethod() +
1162                  ", getValueMethod=" +
1163                  mapEntryMetaData.getGetValueMethod() +
1164                  ", setValueMethod=" +
1165                  mapEntryMetaData.getSetValueMethod() +
1166                  ", valueType=" +
1167                  mapEntryMetaData.getValueType() +
1168                  ", nonNullValue=" + mapEntryMetaData.isNonNullValue();
1169               log.trace(msg);
1170            }
1171
1172            if(classMetaData != null)
1173            {
1174               String JavaDoc msg = "Invalid customization: both jbxb:class and jbxb:mapEntry are specified for term " +
1175                  (term.isWildcard() || term.isModelGroup() ? term.toString() : ((ElementBinding)term).getQName().toString());
1176               throw new JBossXBRuntimeException(msg);
1177            }
1178            term.setMapEntryMetaData(mapEntryMetaData);
1179            skip = Boolean.FALSE;
1180         }
1181
1182         PutMethodMetaData putMethodMetaData = appInfo.getPutMethodMetaData();
1183         if(putMethodMetaData != null)
1184         {
1185            if (trace)
1186            {
1187               String JavaDoc msg = term.isWildcard() || term.isModelGroup() ? term.toString() : "element: name=" +
1188                  ((ElementBinding)term).getQName() + ",";
1189
1190               msg += " putMethod=" +
1191                  putMethodMetaData.getName() +
1192                  ", keyType=" +
1193                  putMethodMetaData.getKeyType() +
1194                  ", valueType=" + putMethodMetaData.getValueType();
1195               log.trace(msg);
1196            }
1197            term.setPutMethodMetaData(putMethodMetaData);
1198         }
1199
1200         AddMethodMetaData addMethodMetaData = appInfo.getAddMethodMetaData();
1201         if(addMethodMetaData != null)
1202         {
1203            if (trace)
1204            {
1205               String JavaDoc msg = term.isWildcard() || term.isModelGroup() ? term.toString() : "element: name=" +
1206                  ((ElementBinding)term).getQName() + ",";
1207               msg += " addMethod=" +
1208                  addMethodMetaData.getMethodName() +
1209                  ", valueType=" +
1210                  addMethodMetaData.getValueType() +
1211                  ", isChildType=" + addMethodMetaData.isChildType();
1212               log.trace(msg);
1213            }
1214            term.setAddMethodMetaData(addMethodMetaData);
1215         }
1216
1217         ValueMetaData valueMetaData = appInfo.getValueMetaData();
1218         if(valueMetaData != null)
1219         {
1220            if (trace)
1221            {
1222               String JavaDoc msg = term.isWildcard() || term.isModelGroup() ? term.toString() : "element " +
1223                  ((ElementBinding)term).getQName();
1224               msg += ": unmarshalMethod=" + valueMetaData.getUnmarshalMethod();
1225               log.trace(msg);
1226            }
1227            term.setValueMetaData(valueMetaData);
1228         }
1229
1230         boolean mapEntryKey = appInfo.isMapEntryKey();
1231         if(mapEntryKey)
1232         {
1233            if (trace)
1234            {
1235               String JavaDoc msg = term.isWildcard() || term.isModelGroup() ? term.toString() : "element name=" +
1236                  ((ElementBinding)term).getQName();
1237               msg += ": is bound to a key in a map entry";
1238               log.trace(msg);
1239            }
1240            term.setMapEntryKey(mapEntryKey);
1241            skip = Boolean.FALSE;
1242         }
1243
1244         boolean mapEntryValue = appInfo.isMapEntryValue();
1245         if(mapEntryValue)
1246         {
1247            if (trace)
1248            {
1249               String JavaDoc msg = term.isWildcard() || term.isModelGroup() ? term.toString() : "element name=" +
1250                  ((ElementBinding)term).getQName();
1251               msg += ": is bound to a value in a map entry";
1252               log.trace(msg);
1253            }
1254            term.setMapEntryValue(mapEntryValue);
1255            skip = Boolean.FALSE;
1256         }
1257
1258         boolean skipAnnotation = appInfo.isSkip();
1259         if(skip != null)
1260         {
1261            term.setSkip(skip);
1262         }
1263         else if(skipAnnotation)
1264         {
1265            if (trace)
1266            {
1267               String JavaDoc msg = term.isWildcard() || term.isModelGroup() ? term.toString() : "element name=" +
1268                  ((ElementBinding)term).getQName();
1269               msg += ": will be skipped, it's attributes, character content and children will be set on the parent";
1270               log.trace(msg);
1271            }
1272            term.setSkip(skipAnnotation ? Boolean.TRUE : Boolean.FALSE);
1273         }
1274      }
1275   }
1276
1277   private static void bindGlobalGroup(XSModelGroup group, SharedElements sharedElements)
1278   {
1279      XSObjectList particles = group.getParticles();
1280      for(int j = 0; j < particles.getLength(); ++j)
1281      {
1282         XSParticle particle = (XSParticle)particles.item(j);
1283         XSTerm term = particle.getTerm();
1284         switch(term.getType())
1285         {
1286            case XSConstants.ELEMENT_DECLARATION:
1287               XSElementDeclaration element = ((XSElementDeclaration)term);
1288               sharedElements.add(element);
1289               break;
1290            case XSConstants.WILDCARD:
1291               // todo is it actually possible?
1292
break;
1293            case XSConstants.MODEL_GROUP:
1294               bindGlobalGroup((XSModelGroup)term, sharedElements);
1295         }
1296      }
1297   }
1298
1299
1300   // Inner
1301

1302   private static final class SharedElements
1303   {
1304      private Map JavaDoc elements = Collections.EMPTY_MAP;
1305
1306      public void add(XSElementDeclaration element)
1307      {
1308         switch(elements.size())
1309         {
1310            case 0:
1311               elements = Collections.singletonMap(element, null);
1312               break;
1313            case 1:
1314               elements = new HashMap JavaDoc(elements);
1315            default:
1316               elements.put(element, null);
1317         }
1318      }
1319
1320      public boolean isShared(XSElementDeclaration element)
1321      {
1322         return elements.containsKey(element);
1323      }
1324
1325      public TypeBinding getTypeBinding(XSElementDeclaration element)
1326      {
1327         return (TypeBinding)elements.get(element);
1328      }
1329
1330      public void setTypeBinding(XSElementDeclaration element, TypeBinding type)
1331      {
1332         switch(elements.size())
1333         {
1334            case 0:
1335               elements = Collections.singletonMap(element, type);
1336               break;
1337            case 1:
1338               elements = new HashMap JavaDoc(elements);
1339            default:
1340               elements.put(element, type);
1341         }
1342      }
1343   }
1344
1345   private static final class Context
1346   {
1347      public final SchemaBinding schema;
1348      public SharedElements sharedElements = new SharedElements();
1349      public boolean processAnnotations = true;
1350      public boolean trace = log.isTraceEnabled();
1351      private final List JavaDoc typeGroupStack = new ArrayList JavaDoc();
1352
1353      public Context()
1354      {
1355         this(new SchemaBinding());
1356      }
1357
1358      public Context(SchemaBinding schema)
1359      {
1360         this.schema = schema;
1361      }
1362
1363      public void popType()
1364      {
1365         Object JavaDoc o = typeGroupStack.remove(typeGroupStack.size() - 1);
1366         if(!(o instanceof TypeBinding))
1367         {
1368            throw new JBossXBRuntimeException("Should have poped type binding but got " + o);
1369         }
1370      }
1371
1372      public void pushType(TypeBinding binding)
1373      {
1374         typeGroupStack.add(binding);
1375      }
1376
1377      public void popModelGroup()
1378      {
1379         Object JavaDoc o = typeGroupStack.remove(typeGroupStack.size() - 1);
1380         if(!(o instanceof ModelGroupBinding))
1381   {
1382            throw new JBossXBRuntimeException("Should have poped model group binding but got " + o);
1383         }
1384      }
1385
1386      public void pushModelGroup(ModelGroupBinding binding)
1387      {
1388         typeGroupStack.add(binding);
1389      }
1390
1391      public Object JavaDoc peekTypeOrGroup()
1392      {
1393         return typeGroupStack.isEmpty() ? null : typeGroupStack.get(typeGroupStack.size() - 1);
1394      }
1395
1396      public TypeBinding peekType()
1397      {
1398         TypeBinding binding = null;
1399         for(ListIterator JavaDoc i = typeGroupStack.listIterator(typeGroupStack.size()); i.hasPrevious();)
1400         {
1401            Object JavaDoc o = i.previous();
1402            if(o instanceof TypeBinding)
1403            {
1404               binding = (TypeBinding)o;
1405               break;
1406            }
1407         }
1408         return binding;
1409      }
1410   }
1411}
1412
Popular Tags