/* * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo; import java.util.Collection; import java.util.Collections; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.namespace.QName; import com.sun.codemodel.internal.JJavaName; import com.sun.codemodel.internal.JType; import com.sun.tools.internal.xjc.ErrorReceiver; import com.sun.tools.internal.xjc.generator.bean.field.FieldRenderer; import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory; import com.sun.tools.internal.xjc.generator.bean.field.IsSetFieldRenderer; import com.sun.tools.internal.xjc.model.CAttributePropertyInfo; import com.sun.tools.internal.xjc.model.CCustomizations; import com.sun.tools.internal.xjc.model.CElementPropertyInfo; import com.sun.tools.internal.xjc.model.CPropertyInfo; import com.sun.tools.internal.xjc.model.CReferencePropertyInfo; import com.sun.tools.internal.xjc.model.CValuePropertyInfo; import com.sun.tools.internal.xjc.model.TypeUse; import com.sun.tools.internal.xjc.reader.Const; import com.sun.tools.internal.xjc.reader.RawTypeSet; import com.sun.tools.internal.xjc.reader.Ring; import com.sun.tools.internal.xjc.reader.TypeUtil; import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder; import com.sun.xml.internal.bind.api.impl.NameConverter; import com.sun.xml.internal.xsom.XSAnnotation; import com.sun.xml.internal.xsom.XSAttGroupDecl; import com.sun.xml.internal.xsom.XSAttributeDecl; import com.sun.xml.internal.xsom.XSAttributeUse; import com.sun.xml.internal.xsom.XSComplexType; import com.sun.xml.internal.xsom.XSComponent; import com.sun.xml.internal.xsom.XSContentType; import com.sun.xml.internal.xsom.XSElementDecl; import com.sun.xml.internal.xsom.XSFacet; import com.sun.xml.internal.xsom.XSIdentityConstraint; import com.sun.xml.internal.xsom.XSModelGroup; import com.sun.xml.internal.xsom.XSModelGroupDecl; import com.sun.xml.internal.xsom.XSNotation; import com.sun.xml.internal.xsom.XSParticle; import com.sun.xml.internal.xsom.XSSchema; import com.sun.xml.internal.xsom.XSSimpleType; import com.sun.xml.internal.xsom.XSWildcard; import com.sun.xml.internal.xsom.XSXPath; import com.sun.xml.internal.xsom.util.XSFinder; import com.sun.xml.internal.xsom.visitor.XSFunction; import org.xml.sax.Locator; /** * Property customization. * * This customization turns an arbitrary schema component * into a Java property (some restrictions apply.) * *
* All the getter methods (such as getBaseType
or
* getBindStyle
) honors the delegation chain of
* property customization specified in the spec. Namely,
* if two property customizations are attached to an attribute
* use and an attribute decl, then anything unspecified in the
* attribute use defaults to attribute decl.
*
*
* Property customizations are acknowledged
* (1) when they are actually used, and
* (2) when they are given at the component, which is mapped to a class.
* (so-called "point of declaration" customization)
*
* @author
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
@XmlRootElement(name="property")
public final class BIProperty extends AbstractDeclarationImpl {
// can be null
@XmlAttribute
private String name = null;
// can be null
@XmlElement
private String javadoc = null;
// can be null
@XmlElement
private BaseTypeBean baseType = null;
// TODO: report 'unsupported' error if this is true
@XmlAttribute
private boolean generateFailFastSetterMethod = false;
public BIProperty(Locator loc, String _propName, String _javadoc,
BaseTypeBean _baseType, CollectionTypeAttribute collectionType, Boolean isConst,
OptionalPropertyMode optionalProperty, Boolean genElemProp) {
super(loc);
this.name = _propName;
this.javadoc = _javadoc;
this.baseType = _baseType;
this.collectionType = collectionType;
this.isConstantProperty = isConst;
this.optionalProperty = optionalProperty;
this.generateElementProperty = genElemProp;
}
protected BIProperty() {}
@Override
public Collection
* Note that returning true from this method doesn't necessarily mean
* that a property needs to be mapped to a constant property.
* It just means that it's mapped to a constant property
* if an attribute use carries a fixed value.
*
*
* I don't like this semantics but that's what the spec implies.
*/
public boolean isConstantProperty() {
if(isConstantProperty!=null) return isConstantProperty;
BIProperty next = getDefault();
if(next!=null) return next.isConstantProperty();
// globalBinding always has true or false in this property,
// so this can't happen
throw new AssertionError();
}
public CValuePropertyInfo createValueProperty(String defaultName,boolean forConstant,
XSComponent source,TypeUse tu, QName typeName) {
markAsAcknowledged();
constantPropertyErrorCheck();
String name = getPropertyName(forConstant);
if(name==null) {
name = defaultName;
if(tu.isCollection() && getBuilder().getGlobalBinding().isSimpleMode())
name = JJavaName.getPluralForm(name);
}
CValuePropertyInfo prop = wrapUp(new CValuePropertyInfo(name, source, getCustomizations(source), source.getLocator(), tu, typeName), source);
BIInlineBinaryData.handle(source, prop);
return prop;
}
public CAttributePropertyInfo createAttributeProperty( XSAttributeUse use, TypeUse tu ) {
boolean forConstant =
getCustomization(use).isConstantProperty() &&
use.getFixedValue()!=null;
String name = getPropertyName(forConstant);
if(name==null) {
NameConverter conv = getBuilder().getNameConverter();
if(forConstant)
name = conv.toConstantName(use.getDecl().getName());
else
name = conv.toPropertyName(use.getDecl().getName());
if(tu.isCollection() && getBuilder().getGlobalBinding().isSimpleMode())
name = JJavaName.getPluralForm(name);
}
markAsAcknowledged();
constantPropertyErrorCheck();
return wrapUp(new CAttributePropertyInfo(name,use,getCustomizations(use),use.getLocator(),
BGMBuilder.getName(use.getDecl()), tu,
BGMBuilder.getName(use.getDecl().getType()), use.isRequired() ),use);
}
/**
*
*
* @param defaultName
* If the name is not customized, this name will be used
* as the default. Note that the name conversion MUST
* be applied before this method is called if necessary.
* @param source
* Source schema component from which a field is built.
*/
public CElementPropertyInfo createElementProperty(String defaultName, boolean forConstant, XSParticle source,
RawTypeSet types) {
if(!types.refs.isEmpty())
// if this property is empty, don't acknowleedge the customization
// this allows pointless property customization to be reported as an error
markAsAcknowledged();
constantPropertyErrorCheck();
String name = getPropertyName(forConstant);
if(name==null)
name = defaultName;
CElementPropertyInfo prop = wrapUp(
new CElementPropertyInfo(
name, types.getCollectionMode(),
types.id(),
types.getExpectedMimeType(),
source, getCustomizations(source),
source.getLocator(), types.isRequired()),
source);
types.addTo(prop);
BIInlineBinaryData.handle(source.getTerm(), prop);
return prop;
}
public CReferencePropertyInfo createDummyExtendedMixedReferenceProperty(
String defaultName, XSComponent source, RawTypeSet types) {
return createReferenceProperty(
defaultName,
false,
source,
types,
true,
true,
false,
true);
}
public CReferencePropertyInfo createContentExtendedMixedReferenceProperty(
String defaultName, XSComponent source, RawTypeSet types) {
return createReferenceProperty(
defaultName,
false,
source,
types,
true,
false,
true,
true);
}
public CReferencePropertyInfo createReferenceProperty(
String defaultName, boolean forConstant, XSComponent source,
RawTypeSet types, boolean isMixed, boolean dummy, boolean content, boolean isMixedExtended) {
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
content = true;
} else {
if(!types.refs.isEmpty())
// if this property is empty, don't acknowleedge the customization
// this allows pointless property customization to be reported as an error
markAsAcknowledged();
}
constantPropertyErrorCheck();
String name = getPropertyName(forConstant);
if(name==null)
name = defaultName;
CReferencePropertyInfo prop = wrapUp(
new CReferencePropertyInfo(
name,
(types == null) ? true : types.getCollectionMode().isRepeated()||isMixed,
(types == null) ? false : types.isRequired(),
isMixed,
source,
getCustomizations(source), source.getLocator(), dummy, content, isMixedExtended),
source);
if (types != null) {
types.addTo(prop);
}
BIInlineBinaryData.handle(source, prop);
return prop;
}
public CPropertyInfo createElementOrReferenceProperty(
String defaultName, boolean forConstant, XSParticle source,
RawTypeSet types) {
boolean generateRef;
switch(types.canBeTypeRefs) {
case CAN_BE_TYPEREF:
case SHOULD_BE_TYPEREF:
// it's up to the use
Boolean b = generateElementProperty();
if(b==null) // follow XJC recommendation
generateRef = types.canBeTypeRefs== RawTypeSet.Mode.CAN_BE_TYPEREF;
else // use the value user gave us
generateRef = b;
break;
case MUST_BE_REFERENCE:
generateRef = true;
break;
default:
throw new AssertionError();
}
if(generateRef) {
return createReferenceProperty(defaultName,forConstant,source,types, false, false, false, false);
} else {
return createElementProperty(defaultName,forConstant,source,types);
}
}
/**
* Common finalization of {@link CPropertyInfo} for the create***Property methods.
*/
private
* Consider an attribute use that does NOT carry a property
* customization. This schema component is nonetheless considered
* to carry a (sort of) implicit property customization, whose values
* are defaulted.
*
*
* This method can be think of the method that returns this implied
* property customization.
*
*
* Note that this doesn't mean the given component needs to be
* mapped to a property. But if it does map to a property, it needs
* to follow this customization.
*
* I think this semantics is next to non-sense but I couldn't think
* of any other way to follow the spec.
*
* @param c
* A customization effective on this component will be returned.
* Can be null just to get the global customization.
* @return
* Always return non-null valid object.
*/
public static BIProperty getCustomization( XSComponent c ) {
BGMBuilder builder = Ring.get(BGMBuilder.class);
// look for a customization on this component
if( c!=null ) {
BIProperty prop = builder.getBindInfo(c).get(BIProperty.class);
if(prop!=null) return prop;
}
// if no such thing exists, defeault.
return getDefault(builder,c);
}
private final static XSFunction