src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/DefaultParticleBinder.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.ArrayList;
    29 import java.util.Collection;
    30 import java.util.Collections;
    31 import java.util.HashMap;
    32 import java.util.Hashtable;
    33 import java.util.List;
    34 import java.util.Map;
    36 import com.sun.tools.internal.xjc.model.CClassInfo;
    37 import com.sun.tools.internal.xjc.model.CPropertyInfo;
    38 import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
    39 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
    40 import com.sun.xml.internal.xsom.XSElementDecl;
    41 import com.sun.xml.internal.xsom.XSModelGroup;
    42 import com.sun.xml.internal.xsom.XSModelGroupDecl;
    43 import com.sun.xml.internal.xsom.XSParticle;
    44 import com.sun.xml.internal.xsom.XSTerm;
    45 import com.sun.xml.internal.xsom.XSWildcard;
    46 import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
    47 import java.math.BigInteger;
    49 /**
    50  * {@link ParticleBinder} that follows the JAXB spec.
    51  *
    52  * @author Kohsuke Kawaguchi
    53  */
    54 final class DefaultParticleBinder extends ParticleBinder {
    56     @Override
    57     public void build( XSParticle p, Collection<XSParticle> forcedProps ) {
    58         Checker checker = checkCollision(p,forcedProps);
    60         if(checker.hasNameCollision()) {
    61             CReferencePropertyInfo prop = new CReferencePropertyInfo(
    62                 getCurrentBean().getBaseClass()==null?"Content":"Rest",
    63                 true, false, false, p,
    64                 builder.getBindInfo(p).toCustomizationList(),
    65                 p.getLocator(), false, false, false);
    66             RawTypeSetBuilder.build(p,false).addTo(prop);
    67             prop.javadoc = Messages.format( Messages.MSG_FALLBACK_JAVADOC,
    68                     checker.getCollisionInfo().toString() );
    70             getCurrentBean().addProperty(prop);
    71         } else {
    72             new Builder(checker.markedParticles).particle(p);
    73         }
    74     }
    76     @Override
    77     public boolean checkFallback( XSParticle p ) {
    78         return checkCollision(p,Collections.<XSParticle>emptyList()).hasNameCollision();
    79     }
    81     private Checker checkCollision( XSParticle p, Collection<XSParticle> forcedProps ) {
    82         // scan the tree by a checker.
    83         Checker checker = new Checker(forcedProps);
    85         CClassInfo superClass = getCurrentBean().getBaseClass();
    87         if(superClass!=null)
    88             checker.readSuperClass(superClass);
    89         checker.particle(p);
    91         return checker;
    92     }
   103     /**
   104      * Marks particles that need to be mapped to properties,
   105      * by reading customization info.
   106      */
   107     private final class Checker implements XSTermVisitor {
   109         Checker(Collection<XSParticle> forcedProps) {
   110             this.forcedProps = forcedProps;
   111         }
   113         boolean hasNameCollision() {
   114             return collisionInfo!=null;
   115         }
   117         CollisionInfo getCollisionInfo() {
   118             return collisionInfo;
   119         }
   121         /**
   122          * If a collision is found, this field will be non-null.
   123          */
   124         private CollisionInfo collisionInfo = null;
   126         /** Used to check name collision. */
   127         private final NameCollisionChecker cchecker = new NameCollisionChecker();
   129         /**
   130          * @see DefaultParticleBinder#build(XSParticle, Collection<com.sun.xml.internal.xsom.XSParticle>)
   131          */
   132         private final Collection<XSParticle> forcedProps;
   134         public void particle( XSParticle p ) {
   136             if(getLocalPropCustomization(p)!=null
   137             || builder.getLocalDomCustomization(p)!=null) {
   138                 // if a property customization is specfied,
   139                 // check that value and turn around.
   140                 check(p);
   141                 mark(p);
   142                 return;
   143             }
   145             XSTerm t = p.getTerm();
   147             if(p.isRepeated() && (t.isModelGroup() || t.isModelGroupDecl())) {
   148                 // a repeated model group gets its own property
   149                 mark(p);
   150                 return;
   151             }
   153             if(forcedProps.contains(p)) {
   154                 // this particle must become a property
   155                 mark(p);
   156                 return;
   157             }
   159             outerParticle = p;
   160             t.visit(this);
   161         }
   163         /**
   164          * This field points to the parent XSParticle.
   165          * The value is only valid when we are processing XSTerm.
   166          */
   167         private XSParticle outerParticle;
   169         public void elementDecl(XSElementDecl decl) {
   170             check(outerParticle);
   171             mark(outerParticle);
   172         }
   174         public void modelGroup(XSModelGroup mg) {
   175             // choice gets mapped to a property
   176             if(mg.getCompositor()== XSModelGroup.Compositor.CHOICE && builder.getGlobalBinding().isChoiceContentPropertyEnabled()) {
   177                 mark(outerParticle);
   178                 return;
   179             }
   181             for( XSParticle child : mg.getChildren() )
   182                 particle(child);
   183         }
   185         public void modelGroupDecl(XSModelGroupDecl decl) {
   186             modelGroup(decl.getModelGroup());
   187         }
   189         public void wildcard(XSWildcard wc) {
   190             mark(outerParticle);
   191         }
   193         void readSuperClass( CClassInfo ci ) {
   194             cchecker.readSuperClass(ci);
   195         }
   200         /**
   201          * Checks the name collision of a newly found particle.
   202          */
   203         private void check( XSParticle p ) {
   204             if( collisionInfo==null )
   205                 collisionInfo = cchecker.check(p);
   206         }
   208         /**
   209          * Marks a particle that it's going to be mapped to a property.
   210          */
   211         private void mark( XSParticle p ) {
   212             markedParticles.put(p,computeLabel(p));
   213         }
   215         /**
   216          * Marked particles.
   217          *
   218          * A map from XSParticle to its label.
   219          */
   220         public final Map<XSParticle,String> markedParticles = new HashMap<XSParticle,String>();
   223         /**
   224          * Checks name collisions among particles that belong to sequences.
   225          */
   226         private final class NameCollisionChecker {
   228             /**
   229              * Checks the label conflict of a particle.
   230              * This method shall be called for each marked particle.
   231              *
   232              * @return
   233              *      a description of a collision if a name collision is
   234              *      found. Otherwise null.
   235              */
   236             CollisionInfo check( XSParticle p ) {
   237                 // this can be used for particles with a property customization,
   238                 // which may not have element declaration as its term.
   239 //                // we only check particles with element declarations.
   240 //                _assert( p.getTerm().isElementDecl() );
   242                 String label = computeLabel(p);
   243                 if( occupiedLabels.containsKey(label) ) {
   244                     // collide with occupied labels
   245                     return new CollisionInfo(label,p.getLocator(),
   246                             occupiedLabels.get(label).locator);
   247                 }
   249                 for( XSParticle jp : particles ) {
   250                     if(!check( p, jp )) {
   251                         // problem was found. no need to check further
   252                         return new CollisionInfo( label, p.getLocator(), jp.getLocator() );
   253                     }
   254                 }
   255                 particles.add(p);
   256                 return null;
   257             }
   259             /** List of particles reported through the check method. */
   260             private final List<XSParticle> particles = new ArrayList<XSParticle>();
   262             /**
   263              * Label names already used in the base type.
   264              */
   265             private final Map<String,CPropertyInfo> occupiedLabels = new HashMap<String,CPropertyInfo>();
   267             /**
   268              * Checks the conflict of two particles.
   269              * @return
   270              *      true if the check was successful.
   271              */
   272             private boolean check( XSParticle p1, XSParticle p2 ) {
   273                 return !computeLabel(p1).equals(computeLabel(p2));
   274             }
   276             /**
   277              * Reads fields of the super class and includes them
   278              * to name collision tests.
   279              */
   280             void readSuperClass( CClassInfo base ) {
   281                 for( ; base!=null; base=base.getBaseClass() ) {
   282                     for( CPropertyInfo p : base.getProperties() )
   283                         occupiedLabels.put(p.getName(true),p);
   284                 }
   285             }
   286         }
   292         /** Keep the computed label names for particles. */
   293         private final Map<XSParticle,String> labelCache = new Hashtable<XSParticle,String>();
   295         /**
   296          * Hides the computeLabel method of the outer class
   297          * and adds caching.
   298          */
   299         private String computeLabel( XSParticle p ) {
   300             String label = labelCache.get(p);
   301             if(label==null)
   302                 labelCache.put( p, label=DefaultParticleBinder.this.computeLabel(p) );
   303             return label;
   304         }
   305     }
   318     /**
   319      * Builds properties by using the result computed by Checker
   320      */
   321     private final class Builder implements XSTermVisitor {
   322         Builder( Map<XSParticle,String> markedParticles ) {
   323             this.markedParticles = markedParticles;
   324         }
   326         /** All marked particles. */
   327         private final Map<XSParticle,String/*label*/> markedParticles;
   329         /**
   330          * When we are visiting inside an optional particle, this flag
   331          * is set to true.
   332          *
   333          * <p>
   334          * This allows us to correctly generate primitive/boxed types.
   335          */
   336         private boolean insideOptionalParticle;
   339         /** Returns true if a particle is marked. */
   340         private boolean marked( XSParticle p ) {
   341             return markedParticles.containsKey(p);
   342         }
   343         /** Gets a label of a particle. */
   344         private String getLabel( XSParticle p ) {
   345             return markedParticles.get(p);
   346         }
   348         public void particle( XSParticle p ) {
   349             XSTerm t = p.getTerm();
   351             if(marked(p)) {
   352                 BIProperty cust = BIProperty.getCustomization(p);
   353                 CPropertyInfo prop = cust.createElementOrReferenceProperty(
   354                     getLabel(p), false, p, RawTypeSetBuilder.build(p,insideOptionalParticle));
   355                 getCurrentBean().addProperty(prop);
   356             } else {
   357                 // repeated model groups should have been marked already
   358                 assert !p.isRepeated();
   360                 boolean oldIOP = insideOptionalParticle;
   361                 insideOptionalParticle |= BigInteger.ZERO.equals(p.getMinOccurs());
   362                 // this is an unmarked particle
   363                 t.visit(this);
   364                 insideOptionalParticle = oldIOP;
   365             }
   366         }
   368         public void elementDecl( XSElementDecl e ) {
   369             // because the corresponding particle must be marked.
   370             assert false;
   371         }
   373         public void wildcard( XSWildcard wc ) {
   374             // because the corresponding particle must be marked.
   375             assert false;
   376         }
   378         public void modelGroupDecl( XSModelGroupDecl decl ) {
   379             modelGroup(decl.getModelGroup());
   380         }
   382         public void modelGroup( XSModelGroup mg ) {
   383             boolean oldIOP = insideOptionalParticle;
   384             insideOptionalParticle |= mg.getCompositor()==XSModelGroup.CHOICE;
   386             for( XSParticle p : mg.getChildren())
   387                 particle(p);
   389             insideOptionalParticle = oldIOP;
   390         }
   391     }
   392 }

mercurial