View Javadoc
1   /*
2    * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
27  
28  import java.util.Collection;
29  import java.util.Collections;
30  
31  import javax.xml.bind.annotation.XmlAttribute;
32  import javax.xml.bind.annotation.XmlElement;
33  import javax.xml.bind.annotation.XmlElementRef;
34  import javax.xml.bind.annotation.XmlRootElement;
35  import javax.xml.namespace.QName;
36  
37  import com.sun.codemodel.internal.JJavaName;
38  import com.sun.codemodel.internal.JType;
39  import com.sun.tools.internal.xjc.ErrorReceiver;
40  import com.sun.tools.internal.xjc.generator.bean.field.FieldRenderer;
41  import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
42  import com.sun.tools.internal.xjc.generator.bean.field.IsSetFieldRenderer;
43  import com.sun.tools.internal.xjc.model.CAttributePropertyInfo;
44  import com.sun.tools.internal.xjc.model.CCustomizations;
45  import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
46  import com.sun.tools.internal.xjc.model.CPropertyInfo;
47  import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
48  import com.sun.tools.internal.xjc.model.CValuePropertyInfo;
49  import com.sun.tools.internal.xjc.model.TypeUse;
50  import com.sun.tools.internal.xjc.reader.Const;
51  import com.sun.tools.internal.xjc.reader.RawTypeSet;
52  import com.sun.tools.internal.xjc.reader.Ring;
53  import com.sun.tools.internal.xjc.reader.TypeUtil;
54  import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder;
55  import com.sun.xml.internal.bind.api.impl.NameConverter;
56  import com.sun.xml.internal.xsom.XSAnnotation;
57  import com.sun.xml.internal.xsom.XSAttGroupDecl;
58  import com.sun.xml.internal.xsom.XSAttributeDecl;
59  import com.sun.xml.internal.xsom.XSAttributeUse;
60  import com.sun.xml.internal.xsom.XSComplexType;
61  import com.sun.xml.internal.xsom.XSComponent;
62  import com.sun.xml.internal.xsom.XSContentType;
63  import com.sun.xml.internal.xsom.XSElementDecl;
64  import com.sun.xml.internal.xsom.XSFacet;
65  import com.sun.xml.internal.xsom.XSIdentityConstraint;
66  import com.sun.xml.internal.xsom.XSModelGroup;
67  import com.sun.xml.internal.xsom.XSModelGroupDecl;
68  import com.sun.xml.internal.xsom.XSNotation;
69  import com.sun.xml.internal.xsom.XSParticle;
70  import com.sun.xml.internal.xsom.XSSchema;
71  import com.sun.xml.internal.xsom.XSSimpleType;
72  import com.sun.xml.internal.xsom.XSWildcard;
73  import com.sun.xml.internal.xsom.XSXPath;
74  import com.sun.xml.internal.xsom.util.XSFinder;
75  import com.sun.xml.internal.xsom.visitor.XSFunction;
76  
77  import org.xml.sax.Locator;
78  
79  /**
80   * Property customization.
81   *
82   * This customization turns an arbitrary schema component
83   * into a Java property (some restrictions apply.)
84   *
85   * <p>
86   * All the getter methods (such as <code>getBaseType</code> or
87   * <code>getBindStyle</code>) honors the delegation chain of
88   * property customization specified in the spec. Namely,
89   * if two property customizations are attached to an attribute
90   * use and an attribute decl, then anything unspecified in the
91   * attribute use defaults to attribute decl.
92   *
93   * <p>
94   * Property customizations are acknowledged
95   * (1) when they are actually used, and
96   * (2) when they are given at the component, which is mapped to a class.
97   *     (so-called "point of declaration" customization)
98   *
99   * @author
100  *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
101  */
102 @XmlRootElement(name="property")
103 public final class BIProperty extends AbstractDeclarationImpl {
104 
105     // can be null
106     @XmlAttribute
107     private String name = null;
108 
109     // can be null
110     @XmlElement
111     private String javadoc = null;
112 
113     // can be null
114     @XmlElement
115     private BaseTypeBean baseType = null;
116 
117     // TODO: report 'unsupported' error if this is true
118     @XmlAttribute
119     private boolean generateFailFastSetterMethod = false;
120 
121 
122 
123     public BIProperty(Locator loc, String _propName, String _javadoc,
124                       BaseTypeBean _baseType, CollectionTypeAttribute collectionType, Boolean isConst,
125                       OptionalPropertyMode optionalProperty, Boolean genElemProp) {
126         super(loc);
127 
128         this.name = _propName;
129         this.javadoc = _javadoc;
130         this.baseType = _baseType;
131         this.collectionType = collectionType;
132         this.isConstantProperty = isConst;
133         this.optionalProperty = optionalProperty;
134         this.generateElementProperty = genElemProp;
135     }
136 
137     protected BIProperty() {}
138 
139     @Override
140     public Collection<BIDeclaration> getChildren() {
141         BIConversion conv = getConv();
142         if(conv==null)
143             return super.getChildren();
144         else
145             return Collections.<BIDeclaration>singleton(conv);
146     }
147 
148     public void setParent( BindInfo parent ) {
149         super.setParent(parent);
150         if(baseType!=null && baseType.conv!=null)
151             baseType.conv.setParent(parent);
152     }
153 
154 
155 
156     /**
157      * Returns the customized property name.
158      *
159      * This method honors the "enableJavaNamingConvention" customization
160      * and formats the property name accordingly if necessary.
161      *
162      * Thus the caller should <em>NOT</em> apply the XML-to-Java name
163      * conversion algorithm to the value returned from this method.
164      *
165      * @param forConstant
166      *      If the property name is intended for a constant property name,
167      *      set to true. This will change the result
168      *
169      * @return
170      *      This method can return null if the customization doesn't
171      *      specify the name.
172      */
173     public String getPropertyName( boolean forConstant ) {
174         if(name!=null) {
175             BIGlobalBinding gb = getBuilder().getGlobalBinding();
176             NameConverter nc = getBuilder().model.getNameConverter();
177 
178             if( gb.isJavaNamingConventionEnabled() && !forConstant )
179                 // apply XML->Java conversion
180                 return nc.toPropertyName(name);
181             else
182                 return name;    // ... or don't change the value
183         }
184         BIProperty next = getDefault();
185         if(next!=null)  return next.getPropertyName(forConstant);
186         else            return null;
187     }
188 
189     /**
190      * Gets the associated javadoc.
191      *
192      * @return
193      *      null if none is specfieid.
194      */
195     public String getJavadoc() {
196         return javadoc;
197     }
198 
199     // can be null
200     public JType getBaseType() {
201         if(baseType!=null && baseType.name!=null) {
202             return TypeUtil.getType(getCodeModel(),
203                     baseType.name,
204                     Ring.get(ErrorReceiver.class),getLocation());
205         }
206         BIProperty next = getDefault();
207         if(next!=null)  return next.getBaseType();
208         else            return null;
209     }
210 
211 
212     // can be null
213     @XmlAttribute
214     private CollectionTypeAttribute collectionType = null;
215 
216     /**
217      * Gets the realization of this field.
218      * @return Always return non-null.
219      */
220     CollectionTypeAttribute getCollectionType() {
221         if(collectionType!=null)   return collectionType;
222         return getDefault().getCollectionType();
223     }
224 
225 
226     @XmlAttribute
227     private OptionalPropertyMode optionalProperty = null;
228 
229     // virtual property for @generateIsSetMethod
230     @XmlAttribute
231     void setGenerateIsSetMethod(boolean b) {
232         optionalProperty = b ? OptionalPropertyMode.ISSET : OptionalPropertyMode.WRAPPER;
233     }
234 
235     public OptionalPropertyMode getOptionalPropertyMode() {
236         if(optionalProperty!=null)   return optionalProperty;
237         return getDefault().getOptionalPropertyMode();
238     }
239 
240     // null if delegated
241     @XmlAttribute
242     private Boolean generateElementProperty = null;
243     /**
244      * If true, the property will automatically be a reference property.
245      * (Talk about confusing names!)
246      */
247     private Boolean generateElementProperty() {
248         if(generateElementProperty!=null)   return generateElementProperty;
249         BIProperty next = getDefault();
250         if(next!=null)      return next.generateElementProperty();
251 
252         return null;
253     }
254 
255 
256     // true, false, or null (which means the value should be inherited.)
257     @XmlAttribute(name="fixedAttributeAsConstantProperty")
258     private Boolean isConstantProperty;
259     /**
260      * Gets the inherited value of the "fixedAttrToConstantProperty" customization.
261      *
262      * <p>
263      * Note that returning true from this method doesn't necessarily mean
264      * that a property needs to be mapped to a constant property.
265      * It just means that it's mapped to a constant property
266      * <b>if an attribute use carries a fixed value.</b>
267      *
268      * <p>
269      * I don't like this semantics but that's what the spec implies.
270      */
271     public boolean isConstantProperty() {
272         if(isConstantProperty!=null)    return isConstantProperty;
273 
274         BIProperty next = getDefault();
275         if(next!=null)      return next.isConstantProperty();
276 
277         // globalBinding always has true or false in this property,
278         // so this can't happen
279         throw new AssertionError();
280     }
281 
282     public CValuePropertyInfo createValueProperty(String defaultName,boolean forConstant,
283         XSComponent source,TypeUse tu, QName typeName) {
284 
285         markAsAcknowledged();
286         constantPropertyErrorCheck();
287 
288         String name = getPropertyName(forConstant);
289         if(name==null) {
290             name = defaultName;
291             if(tu.isCollection() && getBuilder().getGlobalBinding().isSimpleMode())
292                 name = JJavaName.getPluralForm(name);
293         }
294 
295         CValuePropertyInfo prop = wrapUp(new CValuePropertyInfo(name, source, getCustomizations(source), source.getLocator(), tu, typeName), source);
296         BIInlineBinaryData.handle(source, prop);
297         return prop;
298     }
299 
300     public CAttributePropertyInfo createAttributeProperty( XSAttributeUse use, TypeUse tu ) {
301 
302         boolean forConstant =
303             getCustomization(use).isConstantProperty() &&
304             use.getFixedValue()!=null;
305 
306         String name = getPropertyName(forConstant);
307         if(name==null) {
308             NameConverter conv = getBuilder().getNameConverter();
309             if(forConstant)
310                 name = conv.toConstantName(use.getDecl().getName());
311             else
312                 name = conv.toPropertyName(use.getDecl().getName());
313             if(tu.isCollection() && getBuilder().getGlobalBinding().isSimpleMode())
314                 name = JJavaName.getPluralForm(name);
315         }
316 
317         markAsAcknowledged();
318         constantPropertyErrorCheck();
319 
320         return wrapUp(new CAttributePropertyInfo(name,use,getCustomizations(use),use.getLocator(),
321                 BGMBuilder.getName(use.getDecl()), tu,
322                 BGMBuilder.getName(use.getDecl().getType()), use.isRequired() ),use);
323     }
324 
325     /**
326      *
327      *
328      * @param defaultName
329      *      If the name is not customized, this name will be used
330      *      as the default. Note that the name conversion <b>MUST</b>
331      *      be applied before this method is called if necessary.
332      * @param source
333      *      Source schema component from which a field is built.
334      */
335     public CElementPropertyInfo createElementProperty(String defaultName, boolean forConstant, XSParticle source,
336                                                       RawTypeSet types) {
337 
338         if(!types.refs.isEmpty())
339             // if this property is empty, don't acknowleedge the customization
340             // this allows pointless property customization to be reported as an error
341             markAsAcknowledged();
342         constantPropertyErrorCheck();
343 
344         String name = getPropertyName(forConstant);
345         if(name==null)
346             name = defaultName;
347 
348         CElementPropertyInfo prop = wrapUp(
349             new CElementPropertyInfo(
350                 name, types.getCollectionMode(),
351                 types.id(),
352                 types.getExpectedMimeType(),
353                 source, getCustomizations(source),
354                 source.getLocator(), types.isRequired()),
355             source);
356 
357         types.addTo(prop);
358 
359         BIInlineBinaryData.handle(source.getTerm(), prop);
360         return prop;
361     }
362 
363     public CReferencePropertyInfo createDummyExtendedMixedReferenceProperty(
364             String defaultName, XSComponent source, RawTypeSet types) {
365             return createReferenceProperty(
366                     defaultName,
367                     false,
368                     source,
369                     types,
370                     true,
371                     true,
372                     false,
373                     true);
374     }
375 
376     public CReferencePropertyInfo createContentExtendedMixedReferenceProperty(
377             String defaultName, XSComponent source, RawTypeSet types) {
378             return createReferenceProperty(
379                     defaultName,
380                     false,
381                     source,
382                     types,
383                     true,
384                     false,
385                     true,
386                     true);
387     }
388 
389     public CReferencePropertyInfo createReferenceProperty(
390             String defaultName, boolean forConstant, XSComponent source,
391             RawTypeSet types, boolean isMixed, boolean dummy, boolean content, boolean isMixedExtended) {
392 
393         if (types == null) {    // this is a special case where we need to generate content because potential subtypes would need to be able to override what's store inside
394             content = true;
395         } else {
396             if(!types.refs.isEmpty())
397                 // if this property is empty, don't acknowleedge the customization
398                 // this allows pointless property customization to be reported as an error
399                 markAsAcknowledged();
400         }
401         constantPropertyErrorCheck();
402 
403         String name = getPropertyName(forConstant);
404         if(name==null)
405             name = defaultName;
406 
407         CReferencePropertyInfo prop = wrapUp(
408                                             new CReferencePropertyInfo(
409                                                 name,
410                                                 (types == null) ? true : types.getCollectionMode().isRepeated()||isMixed,
411                                                 (types == null) ? false : types.isRequired(),
412                                                 isMixed,
413                                                 source,
414                                                 getCustomizations(source), source.getLocator(), dummy, content, isMixedExtended),
415                                         source);
416         if (types != null) {
417             types.addTo(prop);
418         }
419 
420         BIInlineBinaryData.handle(source, prop);
421         return prop;
422     }
423 
424     public CPropertyInfo createElementOrReferenceProperty(
425             String defaultName, boolean forConstant, XSParticle source,
426             RawTypeSet types) {
427 
428         boolean generateRef;
429 
430         switch(types.canBeTypeRefs) {
431         case CAN_BE_TYPEREF:
432         case SHOULD_BE_TYPEREF:
433             // it's up to the use
434             Boolean b = generateElementProperty();
435             if(b==null) // follow XJC recommendation
436                 generateRef = types.canBeTypeRefs== RawTypeSet.Mode.CAN_BE_TYPEREF;
437             else // use the value user gave us
438                 generateRef = b;
439             break;
440         case MUST_BE_REFERENCE:
441             generateRef = true;
442             break;
443         default:
444             throw new AssertionError();
445         }
446 
447         if(generateRef) {
448             return createReferenceProperty(defaultName,forConstant,source,types, false, false, false, false);
449         } else {
450             return createElementProperty(defaultName,forConstant,source,types);
451         }
452     }
453 
454     /**
455      * Common finalization of {@link CPropertyInfo} for the create***Property methods.
456      */
457     private <T extends CPropertyInfo> T wrapUp(T prop, XSComponent source) {
458         prop.javadoc = concat(javadoc,
459             getBuilder().getBindInfo(source).getDocumentation());
460         if(prop.javadoc==null)
461             prop.javadoc="";
462 
463         // decide the realization.
464         FieldRenderer r;
465         OptionalPropertyMode opm = getOptionalPropertyMode();
466         if(prop.isCollection()) {
467             CollectionTypeAttribute ct = getCollectionType();
468             r = ct.get(getBuilder().model);
469         } else {
470             FieldRendererFactory frf = getBuilder().fieldRendererFactory;
471 
472             if(prop.isOptionalPrimitive()) {
473                 // the property type can be primitive type if we are to ignore absence
474                 switch(opm) {
475                 case PRIMITIVE:
476                     r = frf.getRequiredUnboxed();
477                     break;
478                 case WRAPPER:
479                     // force the wrapper type
480                     r = frf.getSingle();
481                     break;
482                 case ISSET:
483                     r = frf.getSinglePrimitiveAccess();
484                     break;
485                 default:
486                     throw new Error();
487                 }
488             } else {
489                 r = frf.getDefault();
490             }
491         }
492         if(opm==OptionalPropertyMode.ISSET) {
493             // only isSet is allowed on a collection. these 3 modes aren't really symmetric.
494 
495             // if the property is a primitive type, we need an explicit unset because
496             // we can't overload the meaning of set(null).
497             // if it's a collection, we need to be able to unset it so that we can distinguish
498             // null list and empty list.
499             r = new IsSetFieldRenderer( r, prop.isOptionalPrimitive()||prop.isCollection(), true );
500         }
501 
502         prop.realization = r;
503 
504         JType bt = getBaseType();
505         if(bt!=null)
506             prop.baseType = bt;
507 
508         return prop;
509     }
510 
511     private CCustomizations getCustomizations( XSComponent src ) {
512         return getBuilder().getBindInfo(src).toCustomizationList();
513     }
514 
515     private CCustomizations getCustomizations( XSComponent... src ) {
516         CCustomizations c = null;
517         for (XSComponent s : src) {
518             CCustomizations r = getCustomizations(s);
519             if(c==null)     c = r;
520             else            c = CCustomizations.merge(c,r);
521         }
522         return c;
523     }
524 
525     private CCustomizations getCustomizations( XSAttributeUse src ) {
526         // customizations for an attribute use should include those defined in the local attribute.
527         // this is so that the schema like:
528         //
529         // <xs:attribute name="foo" type="xs:int">
530         //   <xs:annotation><xs:appinfo>
531         //     <hyperjaxb:... />
532         //
533         // would be picked up
534         if(src.getDecl().isLocal())
535             return getCustomizations(src,src.getDecl());
536         else
537             return getCustomizations((XSComponent)src);
538     }
539 
540     private CCustomizations getCustomizations( XSParticle src ) {
541         // customizations for a particle  should include those defined in the term unless it's global
542         // this is so that the schema like:
543         //
544         // <xs:sequence>
545         //   <xs:element name="foo" type="xs:int">
546         //     <xs:annotation><xs:appinfo>
547         //       <hyperjaxb:... />
548         //
549         // would be picked up
550         if(src.getTerm().isElementDecl()) {
551             XSElementDecl xed = src.getTerm().asElementDecl();
552             if(xed.isGlobal())
553                 return getCustomizations((XSComponent)src);
554         }
555 
556         return getCustomizations(src,src.getTerm());
557     }
558 
559 
560 
561     public void markAsAcknowledged() {
562         if( isAcknowledged() )  return;
563 
564         // mark the parent as well.
565         super.markAsAcknowledged();
566 
567         BIProperty def = getDefault();
568         if(def!=null)   def.markAsAcknowledged();
569     }
570 
571     private void constantPropertyErrorCheck() {
572         if( isConstantProperty!=null && getOwner()!=null ) {
573             // run additional check on the isCOnstantProperty value.
574             // this value is not allowed if the schema component doesn't have
575             // a fixed value constraint.
576             //
577             // the setParent method associates a customization with the rest of
578             // XSOM object graph, so this is the earliest possible moment where
579             // we can test this.
580 
581             if( !hasFixedValue.find(getOwner()) ) {
582                 Ring.get(ErrorReceiver.class).error(
583                     getLocation(),
584                     Messages.ERR_ILLEGAL_FIXEDATTR.format()
585                 );
586                 // set this value to null to avoid the same error to be reported more than once.
587                 isConstantProperty = null;
588             }
589         }
590     }
591 
592     /**
593      * Function object that returns true if a component has
594      * a fixed value constraint.
595      */
596     private final XSFinder hasFixedValue = new XSFinder() {
597         public Boolean attributeDecl(XSAttributeDecl decl) {
598             return decl.getFixedValue()!=null;
599         }
600 
601         public Boolean attributeUse(XSAttributeUse use) {
602             return use.getFixedValue()!=null;
603         }
604 
605         public Boolean schema(XSSchema s) {
606             // we allow globalBindings to have isConstantProperty==true,
607             // so this method returns true to allow this.
608             return true;
609         }
610     };
611 
612     /**
613      * Finds a BIProperty which this object should delegate to.
614      *
615      * @return
616      *      always return non-null for normal BIProperties.
617      *      If this object is contained in the BIGlobalBinding, then
618      *      this method returns null to indicate that there's no more default.
619      */
620     protected BIProperty getDefault() {
621         if(getOwner()==null)    return null;
622         BIProperty next = getDefault(getBuilder(),getOwner());
623         if(next==this)  return null;    // global.
624         else            return next;
625     }
626 
627     private static BIProperty getDefault( BGMBuilder builder, XSComponent c ) {
628         while(c!=null) {
629             c = c.apply(defaultCustomizationFinder);
630             if(c!=null) {
631                 BIProperty prop = builder.getBindInfo(c).get(BIProperty.class);
632                 if(prop!=null)  return prop;
633             }
634         }
635 
636         // default to the global one
637         return builder.getGlobalBinding().getDefaultProperty();
638     }
639 
640 
641     /**
642      * Finds a property customization that describes how the given
643      * component should be mapped to a property (if it's mapped to
644      * a property at all.)
645      *
646      * <p>
647      * Consider an attribute use that does NOT carry a property
648      * customization. This schema component is nonetheless considered
649      * to carry a (sort of) implicit property customization, whose values
650      * are defaulted.
651      *
652      * <p>
653      * This method can be think of the method that returns this implied
654      * property customization.
655      *
656      * <p>
657      * Note that this doesn't mean the given component needs to be
658      * mapped to a property. But if it does map to a property, it needs
659      * to follow this customization.
660      *
661      * I think this semantics is next to non-sense but I couldn't think
662      * of any other way to follow the spec.
663      *
664      * @param c
665      *      A customization effective on this component will be returned.
666      *      Can be null just to get the global customization.
667      * @return
668      *      Always return non-null valid object.
669      */
670     public static BIProperty getCustomization( XSComponent c ) {
671         BGMBuilder builder = Ring.get(BGMBuilder.class);
672 
673         // look for a customization on this component
674         if( c!=null ) {
675             BIProperty prop = builder.getBindInfo(c).get(BIProperty.class);
676             if(prop!=null)  return prop;
677         }
678 
679         // if no such thing exists, defeault.
680         return getDefault(builder,c);
681     }
682 
683     private final static XSFunction<XSComponent> defaultCustomizationFinder = new XSFunction<XSComponent>() {
684 
685         public XSComponent attributeUse(XSAttributeUse use) {
686             return use.getDecl();   // inherit from the declaration
687         }
688 
689         public XSComponent particle(XSParticle particle) {
690             return particle.getTerm(); // inherit from the term
691         }
692 
693         public XSComponent schema(XSSchema schema) {
694             // no more delegation
695             return null;
696         }
697 
698         // delegates to the context schema object
699         public XSComponent attributeDecl(XSAttributeDecl decl) { return decl.getOwnerSchema(); }
700         public XSComponent wildcard(XSWildcard wc) { return wc.getOwnerSchema(); }
701         public XSComponent modelGroupDecl(XSModelGroupDecl decl) { return decl.getOwnerSchema(); }
702         public XSComponent modelGroup(XSModelGroup group) { return group.getOwnerSchema(); }
703         public XSComponent elementDecl(XSElementDecl decl) { return decl.getOwnerSchema(); }
704         public XSComponent complexType(XSComplexType type) { return type.getOwnerSchema(); }
705         public XSComponent simpleType(XSSimpleType st) { return st.getOwnerSchema(); }
706 
707         // property customizations are not allowed on these components.
708         public XSComponent attGroupDecl(XSAttGroupDecl decl) { throw new IllegalStateException(); }
709         public XSComponent empty(XSContentType empty) { throw new IllegalStateException(); }
710         public XSComponent annotation(XSAnnotation xsAnnotation) { throw new IllegalStateException(); }
711         public XSComponent facet(XSFacet xsFacet) { throw new IllegalStateException(); }
712         public XSComponent notation(XSNotation xsNotation) { throw new IllegalStateException(); }
713         public XSComponent identityConstraint(XSIdentityConstraint x) { throw new IllegalStateException(); }
714         public XSComponent xpath(XSXPath xsxPath) { throw new IllegalStateException(); }
715     };
716 
717 
718     private static String concat( String s1, String s2 ) {
719         if(s1==null)    return s2;
720         if(s2==null)    return s1;
721         return s1+"\n\n"+s2;
722     }
723 
724     public QName getName() { return NAME; }
725 
726     /** Name of this declaration. */
727     public static final QName NAME = new QName(
728         Const.JAXB_NSURI, "property" );
729 
730     public BIConversion getConv() {
731         if(baseType!=null)
732             return baseType.conv;
733         else
734             return null;
735     }
736 
737     private static final class BaseTypeBean {
738         /**
739          * If there's a nested javaType customization, this field
740          * will keep that customization. Otherwise null.
741          *
742          * This customization, if present, is used to customize
743          * the simple type mapping at the point of reference.
744          */
745         @XmlElementRef
746         BIConversion conv;
747 
748         /**
749          * Java type name.
750          */
751         @XmlAttribute
752         String name;
753     }
754 }