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

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

author
alanb
date
Tue, 09 Apr 2013 14:51:13 +0100
changeset 368
0989ad8c0860
parent 0
373ffda63c9a
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;
    28 import java.util.LinkedHashSet;
    29 import java.util.Set;
    31 import javax.activation.MimeType;
    32 import javax.xml.namespace.QName;
    34 import com.sun.tools.internal.xjc.model.CAdapter;
    35 import com.sun.tools.internal.xjc.model.CClass;
    36 import com.sun.tools.internal.xjc.model.CClassInfo;
    37 import com.sun.tools.internal.xjc.model.CCustomizations;
    38 import com.sun.tools.internal.xjc.model.CElement;
    39 import com.sun.tools.internal.xjc.model.CElementInfo;
    40 import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
    41 import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
    42 import com.sun.tools.internal.xjc.model.CTypeRef;
    43 import com.sun.tools.internal.xjc.model.Model;
    44 import com.sun.tools.internal.xjc.model.Multiplicity;
    45 import com.sun.tools.internal.xjc.model.TypeUse;
    46 import com.sun.tools.internal.xjc.reader.RawTypeSet;
    47 import com.sun.tools.internal.xjc.reader.Ring;
    48 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDom;
    49 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
    50 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIXSubstitutable;
    51 import com.sun.xml.internal.bind.v2.model.core.ID;
    52 import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
    53 import com.sun.xml.internal.xsom.XSElementDecl;
    54 import com.sun.xml.internal.xsom.XSModelGroup;
    55 import com.sun.xml.internal.xsom.XSModelGroupDecl;
    56 import com.sun.xml.internal.xsom.XSParticle;
    57 import com.sun.xml.internal.xsom.XSWildcard;
    58 import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
    60 /**
    61  * Builds {@link RawTypeSet} for XML Schema.
    62  *
    63  * @author Kohsuke Kawaguchi
    64  */
    65 public class RawTypeSetBuilder implements XSTermVisitor {
    66     /**
    67      * @param optional
    68      *      if this whole property is optional due to the
    69      *      occurrence constraints on ancestors, set this to true.
    70      *      this will prevent the primitive types to be generated.
    71      */
    72     public static RawTypeSet build( XSParticle p, boolean optional ) {
    73         RawTypeSetBuilder rtsb = new RawTypeSetBuilder();
    74         rtsb.particle(p);
    75         Multiplicity mul = MultiplicityCounter.theInstance.particle(p);
    77         if(optional)
    78             mul = mul.makeOptional();
    80         return new RawTypeSet(rtsb.refs,mul);
    81     }
    83     /**
    84      * To avoid declaring the same element twice for a content model like
    85      * (A,A), we keep track of element names here while we are building up
    86      * this instance.
    87      */
    88     private final Set<QName> elementNames = new LinkedHashSet<QName>();
    90     private final Set<RawTypeSet.Ref> refs = new LinkedHashSet<RawTypeSet.Ref>();
    92     protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
    94     public RawTypeSetBuilder() {}
    97     /**
    98      * Gets the {@link RawTypeSet.Ref}s that were built.
    99      */
   100     public Set<RawTypeSet.Ref> getRefs() {
   101         return refs;
   102     }
   104     /**
   105      * Build up {@link #refs} and compute the total multiplicity of this {@link RawTypeSet.Ref} set.
   106      */
   107     private void particle( XSParticle p ) {
   108         // if the DOM customization is present, bind it like a wildcard
   109         BIDom dom = builder.getLocalDomCustomization(p);
   110         if(dom!=null) {
   111             dom.markAsAcknowledged();
   112             refs.add(new WildcardRef(WildcardMode.SKIP));
   113         } else {
   114             p.getTerm().visit(this);
   115         }
   116     }
   118     public void wildcard(XSWildcard wc) {
   119         refs.add(new WildcardRef(wc));
   120     }
   122     public void modelGroupDecl(XSModelGroupDecl decl) {
   123         modelGroup(decl.getModelGroup());
   124     }
   126     public void modelGroup(XSModelGroup group) {
   127         for( XSParticle p : group.getChildren())
   128             particle(p);
   129     }
   131     public void elementDecl(XSElementDecl decl) {
   133         QName n = BGMBuilder.getName(decl);
   134         if(elementNames.add(n)) {
   135             CElement elementBean = Ring.get(ClassSelector.class).bindToType(decl,null);
   136             if(elementBean==null)
   137                 refs.add(new XmlTypeRef(decl));
   138             else {
   139                 // yikes!
   140                 if(elementBean instanceof CClass)
   141                     refs.add(new CClassRef(decl,(CClass)elementBean));
   142                 else
   143                     refs.add(new CElementInfoRef(decl,(CElementInfo)elementBean));
   144             }
   145         }
   146     }
   148     /**
   149      * Reference to a wildcard.
   150      */
   151     public static final class WildcardRef extends RawTypeSet.Ref {
   152         private final WildcardMode mode;
   154         WildcardRef(XSWildcard wildcard) {
   155             this.mode = getMode(wildcard);
   156         }
   157         WildcardRef(WildcardMode mode) {
   158             this.mode = mode;
   159         }
   161         private static WildcardMode getMode(XSWildcard wildcard) {
   162             switch(wildcard.getMode()) {
   163             case XSWildcard.LAX:
   164                 return WildcardMode.LAX;
   165             case XSWildcard.STRTICT:
   166                 return WildcardMode.STRICT;
   167             case XSWildcard.SKIP:
   168                 return WildcardMode.SKIP;
   169             default:
   170                 throw new IllegalStateException();
   171             }
   172         }
   174         protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
   175             // we don't allow a mapping to typeRef if the wildcard is present
   176             throw new IllegalStateException();
   177         }
   179         protected void toElementRef(CReferencePropertyInfo prop) {
   180             prop.setWildcard(mode);
   181         }
   183         protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
   184             return RawTypeSet.Mode.MUST_BE_REFERENCE;
   185         }
   187         protected boolean isListOfValues() {
   188             return false;
   189         }
   191         protected ID id() {
   192             return ID.NONE;
   193         }
   194     }
   196     /**
   197      * Reference to a class that maps from an element.
   198      */
   199     public static final class CClassRef extends RawTypeSet.Ref {
   200         public final CClass target;
   201         public final XSElementDecl decl;
   203         CClassRef(XSElementDecl decl, CClass target) {
   204             this.decl = decl;
   205             this.target = target;
   206         }
   208         protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
   209             return new CTypeRef(target,decl);
   210         }
   212         protected void toElementRef(CReferencePropertyInfo prop) {
   213             prop.getElements().add(target);
   214         }
   216         protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
   217             // if element substitution can occur, no way it can be mapped to a list of types
   218             if(decl.getSubstitutables().size()>1)
   219                 return RawTypeSet.Mode.MUST_BE_REFERENCE;
   221             return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
   222         }
   224         protected boolean isListOfValues() {
   225             return false;
   226         }
   228         protected ID id() {
   229             return ID.NONE;
   230         }
   231     }
   233     /**
   234      * Reference to a class that maps from an element.
   235      */
   236     public final class CElementInfoRef extends RawTypeSet.Ref {
   237         public final CElementInfo target;
   238         public final XSElementDecl decl;
   240         CElementInfoRef(XSElementDecl decl, CElementInfo target) {
   241             this.decl = decl;
   242             this.target = target;
   243         }
   245         protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
   246             assert !target.isCollection();
   247             CAdapter a = target.getProperty().getAdapter();
   248             if(a!=null && ep!=null) ep.setAdapter(a);
   250             return new CTypeRef(target.getContentType(),decl);
   251         }
   253         protected void toElementRef(CReferencePropertyInfo prop) {
   254             prop.getElements().add(target);
   255         }
   257         protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
   258             // if element substitution can occur, no way it can be mapped to a list of types
   259             if(decl.getSubstitutables().size()>1)
   260                 return RawTypeSet.Mode.MUST_BE_REFERENCE;
   261             // BIXSubstitutable also simulates this effect. Useful for separate compilation
   262             BIXSubstitutable subst = builder.getBindInfo(decl).get(BIXSubstitutable.class);
   263             if(subst!=null) {
   264                 subst.markAsAcknowledged();
   265                 return RawTypeSet.Mode.MUST_BE_REFERENCE;
   266             }
   268             // we have no place to put an adater if this thing maps to a type
   269             CElementPropertyInfo p = target.getProperty();
   270             // if we have an adapter or IDness, which requires special
   271             // annotation, and there's more than one element,
   272             // we have no place to put the special annotation, so we need JAXBElement.
   273             if((parent.refs.size()>1 || !parent.mul.isAtMostOnce()) && p.id()!=ID.NONE)
   274                 return RawTypeSet.Mode.MUST_BE_REFERENCE;
   275             if(parent.refs.size() > 1 && p.getAdapter() != null)
   276                 return RawTypeSet.Mode.MUST_BE_REFERENCE;
   278             if(target.hasClass())
   279                 // if the CElementInfo was explicitly bound to a class (which happen if and only if
   280                 // the user requested so, then map that to reference property so that the user sees a class
   281                 return RawTypeSet.Mode.CAN_BE_TYPEREF;
   282             else
   283                 return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
   284         }
   286         protected boolean isListOfValues() {
   287             return target.getProperty().isValueList();
   288         }
   290         protected ID id() {
   291             return target.getProperty().id();
   292         }
   294         @Override
   295         protected MimeType getExpectedMimeType() {
   296             return target.getProperty().getExpectedMimeType();
   297         }
   298     }
   300     /**
   301      * References to a type. Could be global or local.
   302      */
   303     public static final class XmlTypeRef extends RawTypeSet.Ref {
   304         private final XSElementDecl decl;
   305         private final TypeUse target;
   307         public XmlTypeRef(XSElementDecl decl) {
   308             this.decl = decl;
   309             SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
   310             stb.refererStack.push(decl);
   311             TypeUse r = Ring.get(ClassSelector.class).bindToType(decl.getType(),decl);
   312             stb.refererStack.pop();
   313             target = r;
   314         }
   316         protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
   317             if(ep!=null && target.getAdapterUse()!=null)
   318                 ep.setAdapter(target.getAdapterUse());
   319             return new CTypeRef(target.getInfo(),decl);
   320         }
   322         /**
   323          * The whole type set can be later bound to a reference property,
   324          * in which case we need to generate additional code to wrap this
   325          * type reference into an element class.
   326          *
   327          * This method generates such an element class and returns it.
   328          */
   329         protected void toElementRef(CReferencePropertyInfo prop) {
   330             CClassInfo scope = Ring.get(ClassSelector.class).getCurrentBean();
   331             Model model = Ring.get(Model.class);
   333             CCustomizations custs = Ring.get(BGMBuilder.class).getBindInfo(decl).toCustomizationList();
   335             if(target instanceof CClassInfo && Ring.get(BIGlobalBinding.class).isSimpleMode()) {
   336                 CClassInfo bean = new CClassInfo(model,scope,
   337                                 model.getNameConverter().toClassName(decl.getName()),
   338                                 decl.getLocator(), null, BGMBuilder.getName(decl), decl,
   339                                 custs);
   340                 bean.setBaseClass((CClassInfo)target);
   341                 prop.getElements().add(bean);
   342             } else {
   343                 CElementInfo e = new CElementInfo(model,BGMBuilder.getName(decl),scope,target,
   344                         decl.getDefaultValue(), decl, custs, decl.getLocator());
   345                 prop.getElements().add(e);
   346             }
   347         }
   349         protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
   350             // if we have an adapter or IDness, which requires special
   351             // annotation, and there's more than one element,
   352             // we have no place to put the special annotation, so we need JAXBElement.
   353             if((parent.refs.size()>1 || !parent.mul.isAtMostOnce()) && target.idUse()!=ID.NONE)
   354                 return RawTypeSet.Mode.MUST_BE_REFERENCE;
   355             if(parent.refs.size() > 1 && target.getAdapterUse() != null)
   356                 return RawTypeSet.Mode.MUST_BE_REFERENCE;
   358             // nillable and optional at the same time. needs an element wrapper to distinguish those
   359             // two states. But this is not a hard requirement.
   360             if(decl.isNillable() && parent.mul.isOptional())
   361                 return RawTypeSet.Mode.CAN_BE_TYPEREF;
   363             return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
   364         }
   366         protected boolean isListOfValues() {
   367             return target.isCollection();
   368         }
   370         protected ID id() {
   371             return target.idUse();
   372         }
   374         @Override
   375         protected MimeType getExpectedMimeType() {
   376             return target.getExpectedMimeType();
   377         }
   378     }
   379 }

mercurial