325N/A/*
325N/A * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
325N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
325N/A *
325N/A * This code is free software; you can redistribute it and/or modify it
325N/A * under the terms of the GNU General Public License version 2 only, as
325N/A * published by the Free Software Foundation. Oracle designates this
325N/A * particular file as subject to the "Classpath" exception as provided
325N/A * by Oracle in the LICENSE file that accompanied this code.
325N/A *
325N/A * This code is distributed in the hope that it will be useful, but WITHOUT
325N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
325N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
325N/A * version 2 for more details (a copy is included in the LICENSE file that
325N/A * accompanied this code).
325N/A *
325N/A * You should have received a copy of the GNU General Public License version
325N/A * 2 along with this work; if not, write to the Free Software Foundation,
325N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
325N/A *
325N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
325N/A * or visit www.oracle.com if you need additional information or have any
325N/A * questions.
325N/A */
325N/A
325N/Apackage com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
325N/A
325N/Aimport java.util.Collection;
325N/Aimport java.util.Collections;
325N/A
325N/Aimport javax.xml.bind.annotation.XmlAttribute;
325N/Aimport javax.xml.bind.annotation.XmlElement;
325N/Aimport javax.xml.bind.annotation.XmlElementRef;
325N/Aimport javax.xml.bind.annotation.XmlRootElement;
325N/Aimport javax.xml.namespace.QName;
325N/A
325N/Aimport com.sun.codemodel.internal.JJavaName;
325N/Aimport com.sun.codemodel.internal.JType;
325N/Aimport com.sun.tools.internal.xjc.ErrorReceiver;
325N/Aimport com.sun.tools.internal.xjc.generator.bean.field.FieldRenderer;
325N/Aimport com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
325N/Aimport com.sun.tools.internal.xjc.generator.bean.field.IsSetFieldRenderer;
325N/Aimport com.sun.tools.internal.xjc.model.CAttributePropertyInfo;
325N/Aimport com.sun.tools.internal.xjc.model.CCustomizations;
325N/Aimport com.sun.tools.internal.xjc.model.CElementPropertyInfo;
325N/Aimport com.sun.tools.internal.xjc.model.CPropertyInfo;
325N/Aimport com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
325N/Aimport com.sun.tools.internal.xjc.model.CValuePropertyInfo;
325N/Aimport com.sun.tools.internal.xjc.model.TypeUse;
325N/Aimport com.sun.tools.internal.xjc.reader.Const;
325N/Aimport com.sun.tools.internal.xjc.reader.RawTypeSet;
325N/Aimport com.sun.tools.internal.xjc.reader.Ring;
325N/Aimport com.sun.tools.internal.xjc.reader.TypeUtil;
325N/Aimport com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder;
325N/Aimport com.sun.xml.internal.bind.api.impl.NameConverter;
325N/Aimport com.sun.xml.internal.xsom.XSAnnotation;
325N/Aimport com.sun.xml.internal.xsom.XSAttGroupDecl;
325N/Aimport com.sun.xml.internal.xsom.XSAttributeDecl;
325N/Aimport com.sun.xml.internal.xsom.XSAttributeUse;
325N/Aimport com.sun.xml.internal.xsom.XSComplexType;
325N/Aimport com.sun.xml.internal.xsom.XSComponent;
325N/Aimport com.sun.xml.internal.xsom.XSContentType;
325N/Aimport com.sun.xml.internal.xsom.XSElementDecl;
325N/Aimport com.sun.xml.internal.xsom.XSFacet;
325N/Aimport com.sun.xml.internal.xsom.XSIdentityConstraint;
325N/Aimport com.sun.xml.internal.xsom.XSModelGroup;
325N/Aimport com.sun.xml.internal.xsom.XSModelGroupDecl;
325N/Aimport com.sun.xml.internal.xsom.XSNotation;
325N/Aimport com.sun.xml.internal.xsom.XSParticle;
325N/Aimport com.sun.xml.internal.xsom.XSSchema;
325N/Aimport com.sun.xml.internal.xsom.XSSimpleType;
325N/Aimport com.sun.xml.internal.xsom.XSWildcard;
325N/Aimport com.sun.xml.internal.xsom.XSXPath;
325N/Aimport com.sun.xml.internal.xsom.util.XSFinder;
325N/Aimport com.sun.xml.internal.xsom.visitor.XSFunction;
325N/A
325N/Aimport org.xml.sax.Locator;
325N/A
325N/A/**
325N/A * Property customization.
325N/A *
325N/A * This customization turns an arbitrary schema component
325N/A * into a Java property (some restrictions apply.)
325N/A *
325N/A * <p>
325N/A * All the getter methods (such as <code>getBaseType</code> or
325N/A * <code>getBindStyle</code>) honors the delegation chain of
325N/A * property customization specified in the spec. Namely,
325N/A * if two property customizations are attached to an attribute
325N/A * use and an attribute decl, then anything unspecified in the
325N/A * attribute use defaults to attribute decl.
325N/A *
325N/A * <p>
325N/A * Property customizations are acknowledged
325N/A * (1) when they are actually used, and
325N/A * (2) when they are given at the component, which is mapped to a class.
325N/A * (so-called "point of declaration" customization)
325N/A *
325N/A * @author
325N/A * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
325N/A */
325N/A@XmlRootElement(name="property")
325N/Apublic final class BIProperty extends AbstractDeclarationImpl {
325N/A
325N/A // can be null
325N/A @XmlAttribute
325N/A private String name = null;
325N/A
325N/A // can be null
325N/A @XmlElement
325N/A private String javadoc = null;
325N/A
325N/A // can be null
325N/A @XmlElement
325N/A private BaseTypeBean baseType = null;
325N/A
325N/A // TODO: report 'unsupported' error if this is true
325N/A @XmlAttribute
325N/A private boolean generateFailFastSetterMethod = false;
325N/A
325N/A
325N/A
325N/A public BIProperty(Locator loc, String _propName, String _javadoc,
325N/A BaseTypeBean _baseType, CollectionTypeAttribute collectionType, Boolean isConst,
325N/A OptionalPropertyMode optionalProperty, Boolean genElemProp) {
325N/A super(loc);
325N/A
325N/A this.name = _propName;
325N/A this.javadoc = _javadoc;
325N/A this.baseType = _baseType;
325N/A this.collectionType = collectionType;
325N/A this.isConstantProperty = isConst;
325N/A this.optionalProperty = optionalProperty;
325N/A this.generateElementProperty = genElemProp;
325N/A }
325N/A
325N/A protected BIProperty() {}
325N/A
325N/A @Override
325N/A public Collection<BIDeclaration> getChildren() {
325N/A BIConversion conv = getConv();
325N/A if(conv==null)
325N/A return super.getChildren();
325N/A else
325N/A return Collections.<BIDeclaration>singleton(conv);
325N/A }
325N/A
325N/A public void setParent( BindInfo parent ) {
325N/A super.setParent(parent);
325N/A if(baseType!=null && baseType.conv!=null)
325N/A baseType.conv.setParent(parent);
325N/A }
325N/A
325N/A
325N/A
325N/A /**
325N/A * Returns the customized property name.
325N/A *
325N/A * This method honors the "enableJavaNamingConvention" customization
325N/A * and formats the property name accordingly if necessary.
325N/A *
325N/A * Thus the caller should <em>NOT</em> apply the XML-to-Java name
325N/A * conversion algorithm to the value returned from this method.
325N/A *
325N/A * @param forConstant
325N/A * If the property name is intended for a constant property name,
325N/A * set to true. This will change the result
325N/A *
325N/A * @return
325N/A * This method can return null if the customization doesn't
325N/A * specify the name.
325N/A */
325N/A public String getPropertyName( boolean forConstant ) {
325N/A if(name!=null) {
325N/A BIGlobalBinding gb = getBuilder().getGlobalBinding();
325N/A NameConverter nc = getBuilder().model.getNameConverter();
325N/A
325N/A if( gb.isJavaNamingConventionEnabled() && !forConstant )
325N/A // apply XML->Java conversion
325N/A return nc.toPropertyName(name);
325N/A else
325N/A return name; // ... or don't change the value
325N/A }
325N/A BIProperty next = getDefault();
325N/A if(next!=null) return next.getPropertyName(forConstant);
325N/A else return null;
325N/A }
325N/A
325N/A /**
325N/A * Gets the associated javadoc.
325N/A *
325N/A * @return
325N/A * null if none is specfieid.
325N/A */
325N/A public String getJavadoc() {
325N/A return javadoc;
325N/A }
325N/A
325N/A // can be null
325N/A public JType getBaseType() {
325N/A if(baseType!=null && baseType.name!=null) {
325N/A return TypeUtil.getType(getCodeModel(),
325N/A baseType.name,
325N/A Ring.get(ErrorReceiver.class),getLocation());
325N/A }
325N/A BIProperty next = getDefault();
325N/A if(next!=null) return next.getBaseType();
325N/A else return null;
325N/A }
325N/A
325N/A
325N/A // can be null
325N/A @XmlAttribute
325N/A private CollectionTypeAttribute collectionType = null;
325N/A
325N/A /**
325N/A * Gets the realization of this field.
325N/A * @return Always return non-null.
325N/A */
325N/A CollectionTypeAttribute getCollectionType() {
325N/A if(collectionType!=null) return collectionType;
325N/A return getDefault().getCollectionType();
325N/A }
325N/A
325N/A
325N/A @XmlAttribute
325N/A private OptionalPropertyMode optionalProperty = null;
325N/A
325N/A // virtual property for @generateIsSetMethod
325N/A @XmlAttribute
325N/A void setGenerateIsSetMethod(boolean b) {
325N/A optionalProperty = b ? OptionalPropertyMode.ISSET : OptionalPropertyMode.WRAPPER;
325N/A }
325N/A
325N/A public OptionalPropertyMode getOptionalPropertyMode() {
325N/A if(optionalProperty!=null) return optionalProperty;
325N/A return getDefault().getOptionalPropertyMode();
325N/A }
325N/A
325N/A // null if delegated
325N/A @XmlAttribute
325N/A private Boolean generateElementProperty = null;
325N/A /**
325N/A * If true, the property will automatically be a reference property.
325N/A * (Talk about confusing names!)
325N/A */
325N/A private Boolean generateElementProperty() {
325N/A if(generateElementProperty!=null) return generateElementProperty;
325N/A BIProperty next = getDefault();
325N/A if(next!=null) return next.generateElementProperty();
325N/A
325N/A return null;
325N/A }
325N/A
325N/A
325N/A // true, false, or null (which means the value should be inherited.)
325N/A @XmlAttribute(name="fixedAttributeAsConstantProperty")
325N/A private Boolean isConstantProperty;
325N/A /**
325N/A * Gets the inherited value of the "fixedAttrToConstantProperty" customization.
325N/A *
325N/A * <p>
325N/A * Note that returning true from this method doesn't necessarily mean
325N/A * that a property needs to be mapped to a constant property.
325N/A * It just means that it's mapped to a constant property
325N/A * <b>if an attribute use carries a fixed value.</b>
325N/A *
325N/A * <p>
325N/A * I don't like this semantics but that's what the spec implies.
325N/A */
325N/A public boolean isConstantProperty() {
325N/A if(isConstantProperty!=null) return isConstantProperty;
325N/A
325N/A BIProperty next = getDefault();
325N/A if(next!=null) return next.isConstantProperty();
325N/A
325N/A // globalBinding always has true or false in this property,
325N/A // so this can't happen
325N/A throw new AssertionError();
325N/A }
325N/A
325N/A public CValuePropertyInfo createValueProperty(String defaultName,boolean forConstant,
325N/A XSComponent source,TypeUse tu, QName typeName) {
325N/A
325N/A markAsAcknowledged();
325N/A constantPropertyErrorCheck();
325N/A
325N/A String name = getPropertyName(forConstant);
325N/A if(name==null) {
325N/A name = defaultName;
325N/A if(tu.isCollection() && getBuilder().getGlobalBinding().isSimpleMode())
325N/A name = JJavaName.getPluralForm(name);
325N/A }
325N/A
325N/A CValuePropertyInfo prop = wrapUp(new CValuePropertyInfo(name, source, getCustomizations(source), source.getLocator(), tu, typeName), source);
325N/A BIInlineBinaryData.handle(source, prop);
325N/A return prop;
325N/A }
325N/A
325N/A public CAttributePropertyInfo createAttributeProperty( XSAttributeUse use, TypeUse tu ) {
325N/A
325N/A boolean forConstant =
325N/A getCustomization(use).isConstantProperty() &&
325N/A use.getFixedValue()!=null;
325N/A
325N/A String name = getPropertyName(forConstant);
325N/A if(name==null) {
325N/A NameConverter conv = getBuilder().getNameConverter();
325N/A if(forConstant)
325N/A name = conv.toConstantName(use.getDecl().getName());
325N/A else
325N/A name = conv.toPropertyName(use.getDecl().getName());
325N/A if(tu.isCollection() && getBuilder().getGlobalBinding().isSimpleMode())
325N/A name = JJavaName.getPluralForm(name);
325N/A }
325N/A
325N/A markAsAcknowledged();
325N/A constantPropertyErrorCheck();
325N/A
325N/A return wrapUp(new CAttributePropertyInfo(name,use,getCustomizations(use),use.getLocator(),
325N/A BGMBuilder.getName(use.getDecl()), tu,
325N/A BGMBuilder.getName(use.getDecl().getType()), use.isRequired() ),use);
325N/A }
325N/A
325N/A /**
325N/A *
325N/A *
325N/A * @param defaultName
325N/A * If the name is not customized, this name will be used
325N/A * as the default. Note that the name conversion <b>MUST</b>
325N/A * be applied before this method is called if necessary.
325N/A * @param source
325N/A * Source schema component from which a field is built.
325N/A */
325N/A public CElementPropertyInfo createElementProperty(String defaultName, boolean forConstant, XSParticle source,
325N/A RawTypeSet types) {
325N/A
325N/A if(!types.refs.isEmpty())
325N/A // if this property is empty, don't acknowleedge the customization
325N/A // this allows pointless property customization to be reported as an error
325N/A markAsAcknowledged();
325N/A constantPropertyErrorCheck();
325N/A
325N/A String name = getPropertyName(forConstant);
325N/A if(name==null)
325N/A name = defaultName;
325N/A
325N/A CElementPropertyInfo prop = wrapUp(
325N/A new CElementPropertyInfo(
325N/A name, types.getCollectionMode(),
325N/A types.id(),
325N/A types.getExpectedMimeType(),
325N/A source, getCustomizations(source),
325N/A source.getLocator(), types.isRequired()),
325N/A source);
325N/A
325N/A types.addTo(prop);
325N/A
325N/A BIInlineBinaryData.handle(source.getTerm(), prop);
325N/A return prop;
325N/A }
325N/A
325N/A public CReferencePropertyInfo createDummyExtendedMixedReferenceProperty(
325N/A String defaultName, XSComponent source, RawTypeSet types) {
325N/A return createReferenceProperty(
325N/A defaultName,
325N/A false,
325N/A source,
325N/A types,
325N/A true,
325N/A true,
325N/A false,
325N/A true);
325N/A }
325N/A
325N/A public CReferencePropertyInfo createContentExtendedMixedReferenceProperty(
325N/A String defaultName, XSComponent source, RawTypeSet types) {
325N/A return createReferenceProperty(
325N/A defaultName,
325N/A false,
325N/A source,
325N/A types,
325N/A true,
325N/A false,
325N/A true,
325N/A true);
325N/A }
325N/A
325N/A public CReferencePropertyInfo createReferenceProperty(
325N/A String defaultName, boolean forConstant, XSComponent source,
325N/A RawTypeSet types, boolean isMixed, boolean dummy, boolean content, boolean isMixedExtended) {
325N/A
325N/A 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
325N/A content = true;
325N/A } else {
325N/A if(!types.refs.isEmpty())
325N/A // if this property is empty, don't acknowleedge the customization
325N/A // this allows pointless property customization to be reported as an error
325N/A markAsAcknowledged();
325N/A }
325N/A constantPropertyErrorCheck();
325N/A
325N/A String name = getPropertyName(forConstant);
325N/A if(name==null)
325N/A name = defaultName;
325N/A
325N/A CReferencePropertyInfo prop = wrapUp(
325N/A new CReferencePropertyInfo(
325N/A name,
325N/A (types == null) ? true : types.getCollectionMode().isRepeated()||isMixed,
325N/A (types == null) ? false : types.isRequired(),
325N/A isMixed,
325N/A source,
325N/A getCustomizations(source), source.getLocator(), dummy, content, isMixedExtended),
325N/A source);
325N/A if (types != null) {
325N/A types.addTo(prop);
325N/A }
325N/A
325N/A BIInlineBinaryData.handle(source, prop);
325N/A return prop;
325N/A }
325N/A
325N/A public CPropertyInfo createElementOrReferenceProperty(
325N/A String defaultName, boolean forConstant, XSParticle source,
325N/A RawTypeSet types) {
325N/A
325N/A boolean generateRef;
325N/A
325N/A switch(types.canBeTypeRefs) {
325N/A case CAN_BE_TYPEREF:
325N/A case SHOULD_BE_TYPEREF:
325N/A // it's up to the use
325N/A Boolean b = generateElementProperty();
325N/A if(b==null) // follow XJC recommendation
325N/A generateRef = types.canBeTypeRefs== RawTypeSet.Mode.CAN_BE_TYPEREF;
325N/A else // use the value user gave us
325N/A generateRef = b;
325N/A break;
325N/A case MUST_BE_REFERENCE:
325N/A generateRef = true;
325N/A break;
325N/A default:
325N/A throw new AssertionError();
325N/A }
325N/A
325N/A if(generateRef) {
325N/A return createReferenceProperty(defaultName,forConstant,source,types, false, false, false, false);
325N/A } else {
325N/A return createElementProperty(defaultName,forConstant,source,types);
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Common finalization of {@link CPropertyInfo} for the create***Property methods.
325N/A */
325N/A private <T extends CPropertyInfo> T wrapUp(T prop, XSComponent source) {
325N/A prop.javadoc = concat(javadoc,
325N/A getBuilder().getBindInfo(source).getDocumentation());
325N/A if(prop.javadoc==null)
325N/A prop.javadoc="";
325N/A
325N/A // decide the realization.
325N/A FieldRenderer r;
325N/A OptionalPropertyMode opm = getOptionalPropertyMode();
325N/A if(prop.isCollection()) {
325N/A CollectionTypeAttribute ct = getCollectionType();
325N/A r = ct.get(getBuilder().model);
325N/A } else {
325N/A FieldRendererFactory frf = getBuilder().fieldRendererFactory;
325N/A
325N/A if(prop.isOptionalPrimitive()) {
325N/A // the property type can be primitive type if we are to ignore absence
325N/A switch(opm) {
325N/A case PRIMITIVE:
325N/A r = frf.getRequiredUnboxed();
325N/A break;
325N/A case WRAPPER:
325N/A // force the wrapper type
325N/A r = frf.getSingle();
325N/A break;
325N/A case ISSET:
325N/A r = frf.getSinglePrimitiveAccess();
325N/A break;
325N/A default:
325N/A throw new Error();
325N/A }
325N/A } else {
325N/A r = frf.getDefault();
325N/A }
325N/A }
325N/A if(opm==OptionalPropertyMode.ISSET) {
325N/A // only isSet is allowed on a collection. these 3 modes aren't really symmetric.
325N/A
325N/A // if the property is a primitive type, we need an explicit unset because
325N/A // we can't overload the meaning of set(null).
325N/A // if it's a collection, we need to be able to unset it so that we can distinguish
325N/A // null list and empty list.
325N/A r = new IsSetFieldRenderer( r, prop.isOptionalPrimitive()||prop.isCollection(), true );
325N/A }
325N/A
325N/A prop.realization = r;
325N/A
325N/A JType bt = getBaseType();
325N/A if(bt!=null)
325N/A prop.baseType = bt;
325N/A
325N/A return prop;
325N/A }
325N/A
325N/A private CCustomizations getCustomizations( XSComponent src ) {
325N/A return getBuilder().getBindInfo(src).toCustomizationList();
325N/A }
325N/A
325N/A private CCustomizations getCustomizations( XSComponent... src ) {
325N/A CCustomizations c = null;
325N/A for (XSComponent s : src) {
325N/A CCustomizations r = getCustomizations(s);
325N/A if(c==null) c = r;
325N/A else c = CCustomizations.merge(c,r);
325N/A }
325N/A return c;
325N/A }
325N/A
325N/A private CCustomizations getCustomizations( XSAttributeUse src ) {
325N/A // customizations for an attribute use should include those defined in the local attribute.
325N/A // this is so that the schema like:
325N/A //
325N/A // <xs:attribute name="foo" type="xs:int">
325N/A // <xs:annotation><xs:appinfo>
325N/A // <hyperjaxb:... />
325N/A //
325N/A // would be picked up
325N/A if(src.getDecl().isLocal())
325N/A return getCustomizations(src,src.getDecl());
325N/A else
325N/A return getCustomizations((XSComponent)src);
325N/A }
325N/A
325N/A private CCustomizations getCustomizations( XSParticle src ) {
325N/A // customizations for a particle should include those defined in the term unless it's global
325N/A // this is so that the schema like:
325N/A //
325N/A // <xs:sequence>
325N/A // <xs:element name="foo" type="xs:int">
325N/A // <xs:annotation><xs:appinfo>
325N/A // <hyperjaxb:... />
325N/A //
325N/A // would be picked up
325N/A if(src.getTerm().isElementDecl()) {
325N/A XSElementDecl xed = src.getTerm().asElementDecl();
325N/A if(xed.isGlobal())
325N/A return getCustomizations((XSComponent)src);
325N/A }
325N/A
325N/A return getCustomizations(src,src.getTerm());
325N/A }
325N/A
325N/A
325N/A
325N/A public void markAsAcknowledged() {
325N/A if( isAcknowledged() ) return;
325N/A
325N/A // mark the parent as well.
325N/A super.markAsAcknowledged();
325N/A
325N/A BIProperty def = getDefault();
325N/A if(def!=null) def.markAsAcknowledged();
325N/A }
325N/A
325N/A private void constantPropertyErrorCheck() {
325N/A if( isConstantProperty!=null && getOwner()!=null ) {
325N/A // run additional check on the isCOnstantProperty value.
325N/A // this value is not allowed if the schema component doesn't have
325N/A // a fixed value constraint.
325N/A //
325N/A // the setParent method associates a customization with the rest of
325N/A // XSOM object graph, so this is the earliest possible moment where
325N/A // we can test this.
325N/A
325N/A if( !hasFixedValue.find(getOwner()) ) {
325N/A Ring.get(ErrorReceiver.class).error(
325N/A getLocation(),
325N/A Messages.ERR_ILLEGAL_FIXEDATTR.format()
325N/A );
325N/A // set this value to null to avoid the same error to be reported more than once.
325N/A isConstantProperty = null;
325N/A }
325N/A }
325N/A }
325N/A
325N/A /**
325N/A * Function object that returns true if a component has
325N/A * a fixed value constraint.
325N/A */
325N/A private final XSFinder hasFixedValue = new XSFinder() {
325N/A public Boolean attributeDecl(XSAttributeDecl decl) {
325N/A return decl.getFixedValue()!=null;
325N/A }
325N/A
325N/A public Boolean attributeUse(XSAttributeUse use) {
325N/A return use.getFixedValue()!=null;
325N/A }
325N/A
325N/A public Boolean schema(XSSchema s) {
325N/A // we allow globalBindings to have isConstantProperty==true,
325N/A // so this method returns true to allow this.
325N/A return true;
325N/A }
325N/A };
325N/A
325N/A /**
325N/A * Finds a BIProperty which this object should delegate to.
325N/A *
325N/A * @return
325N/A * always return non-null for normal BIProperties.
325N/A * If this object is contained in the BIGlobalBinding, then
325N/A * this method returns null to indicate that there's no more default.
325N/A */
325N/A protected BIProperty getDefault() {
325N/A if(getOwner()==null) return null;
325N/A BIProperty next = getDefault(getBuilder(),getOwner());
325N/A if(next==this) return null; // global.
325N/A else return next;
325N/A }
325N/A
325N/A private static BIProperty getDefault( BGMBuilder builder, XSComponent c ) {
325N/A while(c!=null) {
325N/A c = c.apply(defaultCustomizationFinder);
325N/A if(c!=null) {
325N/A BIProperty prop = builder.getBindInfo(c).get(BIProperty.class);
325N/A if(prop!=null) return prop;
325N/A }
325N/A }
325N/A
325N/A // default to the global one
325N/A return builder.getGlobalBinding().getDefaultProperty();
325N/A }
325N/A
325N/A
325N/A /**
325N/A * Finds a property customization that describes how the given
325N/A * component should be mapped to a property (if it's mapped to
325N/A * a property at all.)
325N/A *
325N/A * <p>
325N/A * Consider an attribute use that does NOT carry a property
325N/A * customization. This schema component is nonetheless considered
325N/A * to carry a (sort of) implicit property customization, whose values
325N/A * are defaulted.
325N/A *
325N/A * <p>
325N/A * This method can be think of the method that returns this implied
325N/A * property customization.
325N/A *
325N/A * <p>
325N/A * Note that this doesn't mean the given component needs to be
325N/A * mapped to a property. But if it does map to a property, it needs
325N/A * to follow this customization.
325N/A *
325N/A * I think this semantics is next to non-sense but I couldn't think
325N/A * of any other way to follow the spec.
325N/A *
325N/A * @param c
325N/A * A customization effective on this component will be returned.
325N/A * Can be null just to get the global customization.
325N/A * @return
325N/A * Always return non-null valid object.
325N/A */
325N/A public static BIProperty getCustomization( XSComponent c ) {
325N/A BGMBuilder builder = Ring.get(BGMBuilder.class);
325N/A
325N/A // look for a customization on this component
325N/A if( c!=null ) {
325N/A BIProperty prop = builder.getBindInfo(c).get(BIProperty.class);
325N/A if(prop!=null) return prop;
325N/A }
325N/A
325N/A // if no such thing exists, defeault.
325N/A return getDefault(builder,c);
325N/A }
325N/A
325N/A private final static XSFunction<XSComponent> defaultCustomizationFinder = new XSFunction<XSComponent>() {
325N/A
325N/A public XSComponent attributeUse(XSAttributeUse use) {
325N/A return use.getDecl(); // inherit from the declaration
325N/A }
325N/A
325N/A public XSComponent particle(XSParticle particle) {
325N/A return particle.getTerm(); // inherit from the term
325N/A }
325N/A
325N/A public XSComponent schema(XSSchema schema) {
325N/A // no more delegation
325N/A return null;
325N/A }
325N/A
325N/A // delegates to the context schema object
325N/A public XSComponent attributeDecl(XSAttributeDecl decl) { return decl.getOwnerSchema(); }
325N/A public XSComponent wildcard(XSWildcard wc) { return wc.getOwnerSchema(); }
325N/A public XSComponent modelGroupDecl(XSModelGroupDecl decl) { return decl.getOwnerSchema(); }
325N/A public XSComponent modelGroup(XSModelGroup group) { return group.getOwnerSchema(); }
325N/A public XSComponent elementDecl(XSElementDecl decl) { return decl.getOwnerSchema(); }
325N/A public XSComponent complexType(XSComplexType type) { return type.getOwnerSchema(); }
325N/A public XSComponent simpleType(XSSimpleType st) { return st.getOwnerSchema(); }
325N/A
325N/A // property customizations are not allowed on these components.
325N/A public XSComponent attGroupDecl(XSAttGroupDecl decl) { throw new IllegalStateException(); }
325N/A public XSComponent empty(XSContentType empty) { throw new IllegalStateException(); }
325N/A public XSComponent annotation(XSAnnotation xsAnnotation) { throw new IllegalStateException(); }
325N/A public XSComponent facet(XSFacet xsFacet) { throw new IllegalStateException(); }
325N/A public XSComponent notation(XSNotation xsNotation) { throw new IllegalStateException(); }
325N/A public XSComponent identityConstraint(XSIdentityConstraint x) { throw new IllegalStateException(); }
325N/A public XSComponent xpath(XSXPath xsxPath) { throw new IllegalStateException(); }
325N/A };
325N/A
325N/A
325N/A private static String concat( String s1, String s2 ) {
325N/A if(s1==null) return s2;
325N/A if(s2==null) return s1;
325N/A return s1+"\n\n"+s2;
325N/A }
325N/A
325N/A public QName getName() { return NAME; }
325N/A
325N/A /** Name of this declaration. */
325N/A public static final QName NAME = new QName(
325N/A Const.JAXB_NSURI, "property" );
325N/A
325N/A public BIConversion getConv() {
325N/A if(baseType!=null)
325N/A return baseType.conv;
325N/A else
325N/A return null;
325N/A }
325N/A
325N/A private static final class BaseTypeBean {
325N/A /**
325N/A * If there's a nested javaType customization, this field
325N/A * will keep that customization. Otherwise null.
325N/A *
325N/A * This customization, if present, is used to customize
325N/A * the simple type mapping at the point of reference.
325N/A */
325N/A @XmlElementRef
325N/A BIConversion conv;
325N/A
325N/A /**
325N/A * Java type name.
325N/A */
325N/A @XmlAttribute
325N/A String name;
325N/A }
325N/A}