jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIGlobalBinding.java
changeset 12009 4abb694f273a
child 22678 ac1ea46be942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxws/src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/bindinfo/BIGlobalBinding.java	Tue Mar 06 16:09:35 2012 -0800
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 1997, 2011, 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.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlEnumValue;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+import javax.xml.namespace.QName;
+
+import com.sun.codemodel.internal.ClassType;
+import com.sun.codemodel.internal.JClassAlreadyExistsException;
+import com.sun.codemodel.internal.JCodeModel;
+import com.sun.codemodel.internal.JDefinedClass;
+import com.sun.tools.internal.xjc.ErrorReceiver;
+import com.sun.tools.internal.xjc.generator.bean.ImplStructureStrategy;
+import static com.sun.tools.internal.xjc.generator.bean.ImplStructureStrategy.BEAN_ONLY;
+import com.sun.tools.internal.xjc.model.Model;
+import com.sun.tools.internal.xjc.reader.Const;
+import com.sun.tools.internal.xjc.reader.Ring;
+import com.sun.tools.internal.xjc.reader.xmlschema.SimpleTypeBuilder;
+import com.sun.tools.internal.xjc.util.ReadOnlyAdapter;
+import com.sun.xml.internal.bind.api.impl.NameConverter;
+import com.sun.xml.internal.bind.v2.WellKnownNamespace;
+import com.sun.xml.internal.xsom.XSDeclaration;
+import com.sun.xml.internal.xsom.XSSchemaSet;
+import com.sun.xml.internal.xsom.XSSimpleType;
+
+/**
+ * Global binding customization. The code is highly temporary.
+ *
+ * <p>
+ * One of the information contained in a global customization
+ * is the default binding for properties. This object contains a
+ * BIProperty object to keep this information.
+ *
+ * @author
+ *  Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
+ */
+@XmlRootElement(name="globalBindings")
+public final class BIGlobalBinding extends AbstractDeclarationImpl {
+
+
+    /**
+     * Gets the name converter that will govern the XML->Java
+     * name conversion process for this compilation.
+     *
+     * <p>
+     * The "underscoreBinding" customization will determine
+     * the exact object returned from this method. The rest of XJC
+     * should just use the NameConverter interface.
+     *
+     * <p>
+     * Always non-null.
+     */
+    @XmlTransient
+    public NameConverter nameConverter = NameConverter.standard;
+
+    // JAXB will use this property to set nameConverter
+    @XmlAttribute
+    void setUnderscoreBinding( UnderscoreBinding ub ) {
+        nameConverter = ub.nc;
+    }
+
+    UnderscoreBinding getUnderscoreBinding() {
+        throw new IllegalStateException();  // no need for this
+    }
+
+    public JDefinedClass getSuperClass() {
+        if(superClass==null)    return null;
+        return superClass.getClazz(ClassType.CLASS);
+    }
+
+    public JDefinedClass getSuperInterface() {
+        if(superInterface==null)    return null;
+        return superInterface.getClazz(ClassType.INTERFACE);
+    }
+
+    public BIProperty getDefaultProperty() {
+        return defaultProperty;
+    }
+
+    public boolean isJavaNamingConventionEnabled() {
+        return isJavaNamingConventionEnabled;
+    }
+
+    public BISerializable getSerializable() {
+        return serializable;
+    }
+
+    public boolean isGenerateElementClass() {
+        return generateElementClass;
+    }
+
+    public boolean isGenerateMixedExtensions() {
+        return generateMixedExtensions;
+    }
+
+    public boolean isChoiceContentPropertyEnabled() {
+        return choiceContentProperty;
+    }
+
+    public int getDefaultEnumMemberSizeCap() {
+        return defaultEnumMemberSizeCap;
+    }
+
+    public boolean isSimpleMode() {
+        return simpleMode!=null;
+    }
+
+    public boolean isRestrictionFreshType() {
+        return treatRestrictionLikeNewType !=null;
+    }
+
+    public EnumMemberMode getEnumMemberMode() {
+        return generateEnumMemberName;
+    }
+
+    public boolean isSimpleTypeSubstitution() {
+        return simpleTypeSubstitution;
+    }
+
+    public ImplStructureStrategy getCodeGenerationStrategy() {
+        return codeGenerationStrategy;
+    }
+
+    public LocalScoping getFlattenClasses() {
+        return flattenClasses;
+    }
+
+    /**
+     * Performs error check
+     */
+    public void errorCheck() {
+        ErrorReceiver er = Ring.get(ErrorReceiver.class);
+        for (QName n : enumBaseTypes) {
+            XSSchemaSet xs = Ring.get(XSSchemaSet.class);
+            XSSimpleType st = xs.getSimpleType(n.getNamespaceURI(), n.getLocalPart());
+            if(st==null) {
+                er.error(loc,Messages.ERR_UNDEFINED_SIMPLE_TYPE.format(n));
+                continue;
+            }
+
+            if(!SimpleTypeBuilder.canBeMappedToTypeSafeEnum(st)) {
+                er.error(loc,Messages.ERR_CANNOT_BE_BOUND_TO_SIMPLETYPE.format(n));
+                continue;
+            }
+        }
+    }
+
+    private static enum UnderscoreBinding {
+        @XmlEnumValue("asWordSeparator")
+        WORD_SEPARATOR(NameConverter.standard),
+        @XmlEnumValue("asCharInWord")
+        CHAR_IN_WORD(NameConverter.jaxrpcCompatible);
+
+        final NameConverter nc;
+
+        UnderscoreBinding(NameConverter nc) {
+            this.nc = nc;
+        }
+    }
+
+    /**
+     * Returns true if the "isJavaNamingConventionEnabled" option is turned on.
+     *
+     * In this mode, the compiler is expected to apply XML-to-Java name
+     * conversion algorithm even to names given by customizations.
+     *
+     * This method is intended to be called by other BIXXX classes.
+     * The effect of this switch should be hidden inside this package.
+     * IOW, the reader.xmlschema package shouldn't be aware of this switch.
+     */
+    @XmlAttribute(name="enableJavaNamingConventions")
+    /*package*/ boolean isJavaNamingConventionEnabled = true;
+
+    /**
+     * True to generate classes for every simple type.
+     */
+    @XmlAttribute(name="mapSimpleTypeDef")
+    boolean simpleTypeSubstitution = false;
+
+    /**
+     * Gets the default defaultProperty customization.
+     */
+    @XmlTransient
+    private BIProperty defaultProperty;
+
+    /*
+        Three properties used to construct a default property
+    */
+    @XmlAttribute
+    private boolean fixedAttributeAsConstantProperty = false;
+    @XmlAttribute
+    private CollectionTypeAttribute collectionType = new CollectionTypeAttribute();
+    @XmlAttribute
+    void setGenerateIsSetMethod(boolean b) {
+        optionalProperty = b ? OptionalPropertyMode.ISSET : OptionalPropertyMode.WRAPPER;
+    }
+
+
+    /**
+     * Returns true if the compiler needs to generate type-safe enum
+     * member names when enumeration values cannot be used as constant names.
+     */
+    @XmlAttribute(name="typesafeEnumMemberName")
+    EnumMemberMode generateEnumMemberName = EnumMemberMode.SKIP;
+
+    /**
+     * The code generation strategy.
+     */
+    @XmlAttribute(name="generateValueClass")
+    ImplStructureStrategy codeGenerationStrategy = BEAN_ONLY;
+
+    /**
+     * Set of datatype names. For a type-safe enum class
+     * to be generated, the underlying XML datatype must be derived from
+     * one of the types in this set.
+     */
+    // default value is set in the post-init action
+    @XmlAttribute(name="typesafeEnumBase")
+    private Set<QName> enumBaseTypes;
+
+    /**
+     * Returns {@link BISerializable} if the extension is specified,
+     * or null otherwise.
+     */
+    @XmlElement
+    private BISerializable serializable = null;
+
+    /**
+     * If &lt;xjc:superClass> extension is specified,
+     * returns the specified root class. Otherwise null.
+     */
+    @XmlElement(namespace=Const.XJC_EXTENSION_URI)
+    ClassNameBean superClass = null;
+
+    /**
+     * If &lt;xjc:superInterface> extension is specified,
+     * returns the specified root class. Otherwise null.
+     */
+    @XmlElement(namespace=Const.XJC_EXTENSION_URI)
+    ClassNameBean superInterface = null;
+
+    /**
+     * Generate the simpler optimized code, but not necessarily
+     * conforming to the spec.
+     */
+    @XmlElement(name="simple",namespace=Const.XJC_EXTENSION_URI)
+    String simpleMode = null;
+
+    /**
+     * Handles complex type restriction as if it were a new type.
+     */
+    @XmlElement(name="treatRestrictionLikeNewType",namespace=Const.XJC_EXTENSION_URI)
+    String treatRestrictionLikeNewType = null;
+
+    /**
+     * True to generate a class for elements by default.
+     */
+    @XmlAttribute
+    boolean generateElementClass = false;
+
+    @XmlAttribute
+    boolean generateMixedExtensions = false;
+
+    @XmlElement(namespace=Const.XJC_EXTENSION_URI)
+    Boolean generateElementProperty = null;
+
+    @XmlAttribute(name="generateElementProperty")     // for JAXB unmarshaller
+    private void setGenerateElementPropertyStd(boolean value) {
+        generateElementProperty = value;
+    }
+
+    @XmlAttribute
+    boolean choiceContentProperty = false;
+
+    @XmlAttribute
+    OptionalPropertyMode optionalProperty = OptionalPropertyMode.WRAPPER;
+
+    /**
+     * Default cap to the number of constants in the enum.
+     * We won't attempt to produce a type-safe enum by default
+     * if there are more enumeration facets than specified in this field.
+     */
+    @XmlAttribute(name="typesafeEnumMaxMembers")
+    int defaultEnumMemberSizeCap = 256;
+
+    /**
+     * If true, interfaces/classes that are normally generated as a nested interface/class
+     * will be generated into the package, allowing the generated classes to be flat.
+     *
+     * See <a href="http://monaco.sfbay/detail.jsf?cr=4969415">Bug 4969415</a> for the motivation.
+     */
+    @XmlAttribute(name="localScoping")
+    LocalScoping flattenClasses = LocalScoping.NESTED;
+
+    /**
+     * Globally-defined conversion customizations.
+     *
+     * @see #setGlobalConversions
+     */
+    @XmlTransient
+    private final Map<QName,BIConversion> globalConversions = new HashMap<QName, BIConversion>();
+
+    // method for JAXB unmarshaller
+    @XmlElement(name="javaType")
+    private void setGlobalConversions(GlobalStandardConversion[] convs) {
+        for (GlobalStandardConversion u : convs) {
+            globalConversions.put(u.xmlType,u);
+        }
+    }
+
+    @XmlElement(name="javaType",namespace=Const.XJC_EXTENSION_URI)
+    private void setGlobalConversions2(GlobalVendorConversion[] convs) {
+        for (GlobalVendorConversion u : convs) {
+            globalConversions.put(u.xmlType,u);
+        }
+    }
+
+    //
+    // these customizations were valid in 1.0, but in 2.0 we don't
+    // use them. OTOH, we don't want to issue an error for them,
+    // so we just define a mapping and ignore the value.
+    //
+    @XmlElement(namespace=Const.XJC_EXTENSION_URI)
+    String noMarshaller = null;
+    @XmlElement(namespace=Const.XJC_EXTENSION_URI)
+    String noUnmarshaller = null;
+    @XmlElement(namespace=Const.XJC_EXTENSION_URI)
+    String noValidator = null;
+    @XmlElement(namespace=Const.XJC_EXTENSION_URI)
+    String noValidatingUnmarshaller = null;
+    @XmlElement(namespace=Const.XJC_EXTENSION_URI)
+    TypeSubstitutionElement typeSubstitution = null;
+
+    /**
+     * Another 1.0 compatibility customization (but we accept it
+     * and treat it as {@link #serializable})
+     */
+    @XmlElement(name="serializable",namespace=Const.XJC_EXTENSION_URI)
+    void setXjcSerializable(BISerializable s) {
+        this.serializable = s;
+    }
+
+
+
+    private static final class TypeSubstitutionElement {
+        @XmlAttribute
+        String type;
+    }
+
+    public void onSetOwner() {
+        super.onSetOwner();
+        // if one is given by options, use that
+        NameConverter nc = Ring.get(Model.class).options.getNameConverter();
+        if(nc!=null)
+            nameConverter = nc;
+    }
+
+    /**
+     * Creates a bind info object with the default values
+     */
+    public BIGlobalBinding() {
+    }
+
+    public void setParent(BindInfo parent) {
+        super.setParent(parent);
+        // fill in the remaining default values
+        if(enumBaseTypes==null)
+            enumBaseTypes = Collections.singleton(new QName(WellKnownNamespace.XML_SCHEMA,"string"));
+
+        this.defaultProperty = new BIProperty(getLocation(),null,null,null,
+                collectionType, fixedAttributeAsConstantProperty, optionalProperty, generateElementProperty );
+        defaultProperty.setParent(parent); // don't forget to initialize the defaultProperty
+    }
+
+    /**
+     * Moves global BIConversion to the right object.
+     */
+    public void dispatchGlobalConversions( XSSchemaSet schema ) {
+        // also set parent to the global conversions
+        for( Map.Entry<QName,BIConversion> e : globalConversions.entrySet() ) {
+
+            QName name = e.getKey();
+            BIConversion conv = e.getValue();
+
+            XSSimpleType st = schema.getSimpleType(name.getNamespaceURI(),name.getLocalPart());
+            if(st==null) {
+                Ring.get(ErrorReceiver.class).error(
+                    getLocation(),
+                    Messages.ERR_UNDEFINED_SIMPLE_TYPE.format(name)
+                );
+                continue; // abort
+            }
+
+            getBuilder().getOrCreateBindInfo(st).addDecl(conv);
+        }
+    }
+
+
+    /**
+     * Checks if the given XML Schema built-in type can be mapped to
+     * a type-safe enum class.
+     *
+     * @param typeName
+     */
+    public boolean canBeMappedToTypeSafeEnum( QName typeName ) {
+        return enumBaseTypes.contains(typeName);
+    }
+
+    public boolean canBeMappedToTypeSafeEnum( String nsUri, String localName ) {
+        return canBeMappedToTypeSafeEnum(new QName(nsUri,localName));
+    }
+
+    public boolean canBeMappedToTypeSafeEnum( XSDeclaration decl ) {
+        return canBeMappedToTypeSafeEnum( decl.getTargetNamespace(), decl.getName() );
+    }
+
+
+    public QName getName() { return NAME; }
+    public static final QName NAME = new QName(
+        Const.JAXB_NSURI, "globalBindings" );
+
+
+    /**
+     * Used to unmarshal
+     * <xmp>
+     * <[element] name="className" />
+     * </xmp>
+     */
+    static final class ClassNameBean {
+        @XmlAttribute(required=true)
+        String name;
+
+        /**
+         * Computed from {@link #name} on demand.
+         */
+        @XmlTransient
+        JDefinedClass clazz;
+
+        JDefinedClass getClazz(ClassType t) {
+            if (clazz != null) return clazz;
+            try {
+                JCodeModel codeModel = Ring.get(JCodeModel.class);
+                clazz = codeModel._class(name, t);
+                clazz.hide();
+                return clazz;
+            } catch (JClassAlreadyExistsException e) {
+                return e.getExistingClass();
+            }
+        }
+    }
+
+    static final class ClassNameAdapter extends ReadOnlyAdapter<ClassNameBean,String> {
+        public String unmarshal(ClassNameBean bean) throws Exception {
+            return bean.name;
+        }
+    }
+
+    /**
+     * Global &lt;jaxb:javaType>.
+     */
+    static final class GlobalStandardConversion extends BIConversion.User {
+        @XmlAttribute
+        QName xmlType;
+
+        @Override
+        public boolean equals(Object obj) {
+            if(obj instanceof GlobalStandardConversion) {
+                return ((GlobalStandardConversion)obj).xmlType.equals(xmlType);
+    }
+
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 7;
+            hash = 73 * hash + (this.xmlType != null ? this.xmlType.hashCode() : 0);
+            return hash;
+        }
+    }
+
+    /**
+     * Global &lt;xjc:javaType>.
+     */
+    static final class GlobalVendorConversion extends BIConversion.UserAdapter {
+        @XmlAttribute
+        QName xmlType;
+
+        @Override
+        public boolean equals(Object obj) {
+            if(obj instanceof GlobalVendorConversion) {
+                return ((GlobalVendorConversion)obj).xmlType.equals(xmlType);
+    }
+
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 7;
+            hash = 73 * hash + (this.xmlType != null ? this.xmlType.hashCode() : 0);
+            return hash;
+        }
+    }
+
+    /* don't want to override equals to avoid overriding hashcode for this complex object, too */
+    public boolean isEqual(BIGlobalBinding b) {
+        boolean equal =
+            this.isJavaNamingConventionEnabled == b.isJavaNamingConventionEnabled &&
+            this.simpleTypeSubstitution == b.simpleTypeSubstitution &&
+            this.fixedAttributeAsConstantProperty == b.fixedAttributeAsConstantProperty &&
+            this.generateEnumMemberName == b.generateEnumMemberName &&
+            this.codeGenerationStrategy == b.codeGenerationStrategy &&
+            this.serializable == b.serializable &&
+            this.superClass == b.superClass &&
+            this.superInterface == b.superInterface &&
+            this.generateElementClass == b.generateElementClass &&
+            this.generateMixedExtensions == b.generateMixedExtensions &&
+            this.generateElementProperty == b.generateElementProperty &&
+            this.choiceContentProperty == b.choiceContentProperty &&
+            this.optionalProperty == b.optionalProperty &&
+            this.defaultEnumMemberSizeCap == b.defaultEnumMemberSizeCap &&
+            this.flattenClasses == b.flattenClasses;
+
+        if (!equal) return false;
+
+        return isEqual(this.nameConverter, b.nameConverter) &&
+               isEqual(this.noMarshaller, b.noMarshaller) &&
+               isEqual(this.noUnmarshaller, b.noUnmarshaller) &&
+               isEqual(this.noValidator, b.noValidator) &&
+               isEqual(this.noValidatingUnmarshaller, b.noValidatingUnmarshaller) &&
+               isEqual(this.typeSubstitution, b.typeSubstitution) &&
+               isEqual(this.simpleMode, b.simpleMode) &&
+               isEqual(this.enumBaseTypes, b.enumBaseTypes) &&
+               isEqual(this.treatRestrictionLikeNewType, b.treatRestrictionLikeNewType) &&
+               isEqual(this.globalConversions, b.globalConversions);
+    }
+
+    private boolean isEqual(Object a, Object b) {
+        if (a != null) {
+            return a.equals(b);
+        }
+        return (b == null);
+    }
+}