src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/ct/AbstractExtendedComplexTypeBuilder.java

Tue, 09 Apr 2013 14:51:13 +0100

author
alanb
date
Tue, 09 Apr 2013 14:51:13 +0100
changeset 368
0989ad8c0860
parent 286
f50545b5e2f1
child 408
b0610cd08440
permissions
-rw-r--r--

8010393: Update JAX-WS RI to 2.2.9-b12941
Reviewed-by: alanb, erikj
Contributed-by: miroslav.kos@oracle.com, martin.grebac@oracle.com

     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  */
    26 package com.sun.tools.internal.xjc.reader.xmlschema.ct;
    28 import java.util.HashMap;
    29 import java.util.Iterator;
    30 import java.util.Map;
    32 import com.sun.tools.internal.xjc.reader.xmlschema.WildcardNameClassBuilder;
    33 import com.sun.xml.internal.xsom.XSAttributeUse;
    34 import com.sun.xml.internal.xsom.XSComplexType;
    35 import com.sun.xml.internal.xsom.XSContentType;
    36 import com.sun.xml.internal.xsom.XSDeclaration;
    37 import com.sun.xml.internal.xsom.XSElementDecl;
    38 import com.sun.xml.internal.xsom.XSModelGroup;
    39 import com.sun.xml.internal.xsom.XSModelGroupDecl;
    40 import com.sun.xml.internal.xsom.XSParticle;
    41 import com.sun.xml.internal.xsom.XSType;
    42 import com.sun.xml.internal.xsom.XSWildcard;
    43 import com.sun.xml.internal.xsom.visitor.XSTermFunction;
    45 import com.sun.xml.internal.rngom.nc.ChoiceNameClass;
    46 import com.sun.xml.internal.rngom.nc.NameClass;
    47 import com.sun.xml.internal.rngom.nc.SimpleNameClass;
    49 /**
    50  * Binds a complex type derived from another complex type by extension.
    51  *
    52  * @author
    53  *     Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
    54  */
    55 abstract class AbstractExtendedComplexTypeBuilder extends CTBuilder {
    57     /**
    58      * Map from {@link XSComplexType} to {@link NameClass}[2] that
    59      * represents the names used in its child elements [0] and
    60      * attributes [1].
    61      */
    62     protected final Map<XSComplexType, NameClass[]> characteristicNameClasses = new HashMap<XSComplexType, NameClass[]>();
    64     /**
    65      * Computes a name class that represents everything in a given content model.
    66      */
    67     protected final XSTermFunction<NameClass> contentModelNameClassBuilder = new XSTermFunction<NameClass>() {
    68         public NameClass wildcard(XSWildcard wc) {
    69             return WildcardNameClassBuilder.build(wc);
    70         }
    72         public NameClass modelGroupDecl(XSModelGroupDecl decl) {
    73             return modelGroup(decl.getModelGroup());
    74         }
    76         public NameClass modelGroup(XSModelGroup group) {
    77             NameClass nc = NameClass.NULL;
    78             for( int i=0; i<group.getSize(); i++ )
    79                 nc = new ChoiceNameClass(nc, group.getChild(i).getTerm().apply(this));
    80             return nc;
    81         }
    83         public NameClass elementDecl(XSElementDecl decl) {
    84             return getNameClass(decl);
    85         }
    86     };
    88     /**
    89      * Checks if the particles/attributes defined in the type parameter
    90      * collides with the name classes of anc/enc.
    91      *
    92      * @return true if there's a collision.
    93      */
    94     protected boolean checkCollision(NameClass anc, NameClass enc, XSComplexType type) {
    95         NameClass[] chnc = characteristicNameClasses.get(type);
    96         if (chnc == null) {
    97             chnc = new NameClass[2];
    98             chnc[0] = getNameClass(type.getContentType());
   100             // build attribute name classes
   101             NameClass nc = NameClass.NULL;
   102             Iterator itr = type.iterateAttributeUses();
   103             while( itr.hasNext() )
   104                 anc = new ChoiceNameClass(anc, getNameClass(((XSAttributeUse) itr.next()).getDecl()));
   105             XSWildcard wc = type.getAttributeWildcard();
   106             if(wc!=null)
   107                 nc = new ChoiceNameClass(nc, WildcardNameClassBuilder.build(wc));
   108             chnc[1] = nc;
   110             characteristicNameClasses.put(type, chnc);
   111         }
   113         return chnc[0].hasOverlapWith(enc) || chnc[1].hasOverlapWith(anc);
   114     }
   116     /**
   117      * Looks for the derivation chain t_1 > t_2 > ... > t
   118      * and find t_i such that t_i derives by restriction but
   119      * for every j>i, t_j derives by extension.
   120      *
   121      * @return null
   122      *      If there's no such t_i or if t_i is any type.
   123      */
   124     protected XSComplexType getLastRestrictedType(XSComplexType t) {
   125         if (t.getBaseType() == schemas.getAnyType()) {
   126             return null;   // we don't count the restriction from anyType
   127         }
   128         if (t.getDerivationMethod() == XSType.RESTRICTION) {
   129             return t;
   130         }
   132         XSComplexType baseType = t.getBaseType().asComplexType();
   133         if (baseType != null) {
   134             return getLastRestrictedType(baseType);
   135         } else {
   136             return null;
   137         }
   138     }
   140     /**
   141      * Checks if this new extension is safe.
   142      *
   143      * UGLY.
   144      * <p>
   145      * If you have ctA extending ctB and ctB restricting ctC, our
   146      * Java classes will look like CtAImpl extending CtBImpl
   147      * extending CtCImpl.
   148      *
   149      * <p>
   150      * Since a derived class unmarshaller uses the base class unmarshaller,
   151      * this could potentially result in incorrect unmarshalling.
   152      * We used to just reject such a case, but then we found that
   153      * there are schemas that are using it.
   154      *
   155      * <p>
   156      * One generalized observation that we reached is that if the extension
   157      * is only adding new elements/attributes which has never been used
   158      * in any of its base class (IOW, if none of the particle / attribute use /
   159      * attribute wildcard can match the name of newly added elements/attributes)
   160      * then it is safe to add them.
   161      *
   162      * <p>
   163      * This function checks if the derivation chain to this type is
   164      * not using restriction, and if it is, then checks if it is safe
   165      * according to the above condition.
   166      *
   167      * @return false
   168      *      If this complex type needs to be rejected.
   169      */
   170     protected boolean checkIfExtensionSafe(XSComplexType baseType, XSComplexType thisType) {
   171         XSComplexType lastType = getLastRestrictedType(baseType);
   173         if (lastType == null) {
   174             return true;    // no restriction in derivation chain
   175         }
   176         NameClass anc = NameClass.NULL;
   177         // build name class for attributes in new complex type
   178         Iterator itr = thisType.iterateDeclaredAttributeUses();
   179         while (itr.hasNext()) {
   180             anc = new ChoiceNameClass(anc, getNameClass(((XSAttributeUse) itr.next()).getDecl()));
   181         }
   182         // TODO: attribute wildcard
   184         NameClass enc = getNameClass(thisType.getExplicitContent());
   186         // check against every base type ... except the root anyType
   187         while (lastType != lastType.getBaseType()) {
   188             if (checkCollision(anc, enc, lastType)) {
   189                 return false;
   190             }
   192             if (lastType.getBaseType().isSimpleType()) // if the base type is a simple type, there won't be
   193             // any further name collision.
   194             {
   195                 return true;
   196             }
   198             lastType = lastType.getBaseType().asComplexType();
   199         }
   201         return true;    // OK
   202     }
   204     /**
   205      * Gets a {@link NameClass} that represents all the terms in the given content type.
   206      * If t is not a particle, just return an empty name class.
   207      */
   208     private NameClass getNameClass(XSContentType t) {
   209         if(t==null) return NameClass.NULL;
   210         XSParticle p = t.asParticle();
   211         if(p==null) return NameClass.NULL;
   212         else        return p.getTerm().apply(contentModelNameClassBuilder);
   213     }
   215     /**
   216      * Gets a {@link SimpleNameClass} from the name of a {@link XSDeclaration}.
   217      */
   218     private NameClass getNameClass(XSDeclaration decl) {
   219         return new SimpleNameClass(decl.getTargetNamespace(), decl.getName());
   220     }
   222 }

mercurial