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

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.tools.internal.xjc.reader.xmlschema;
aoqi@0 27
aoqi@0 28 import java.util.ArrayList;
aoqi@0 29 import java.util.Collection;
aoqi@0 30 import java.util.Collections;
aoqi@0 31 import java.util.HashMap;
aoqi@0 32 import java.util.Hashtable;
aoqi@0 33 import java.util.List;
aoqi@0 34 import java.util.Map;
aoqi@0 35
aoqi@0 36 import com.sun.tools.internal.xjc.model.CClassInfo;
aoqi@0 37 import com.sun.tools.internal.xjc.model.CPropertyInfo;
aoqi@0 38 import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
aoqi@0 39 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
aoqi@0 40 import com.sun.xml.internal.xsom.XSElementDecl;
aoqi@0 41 import com.sun.xml.internal.xsom.XSModelGroup;
aoqi@0 42 import com.sun.xml.internal.xsom.XSModelGroupDecl;
aoqi@0 43 import com.sun.xml.internal.xsom.XSParticle;
aoqi@0 44 import com.sun.xml.internal.xsom.XSTerm;
aoqi@0 45 import com.sun.xml.internal.xsom.XSWildcard;
aoqi@0 46 import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
aoqi@0 47 import java.math.BigInteger;
aoqi@0 48
aoqi@0 49 /**
aoqi@0 50 * {@link ParticleBinder} that follows the JAXB spec.
aoqi@0 51 *
aoqi@0 52 * @author Kohsuke Kawaguchi
aoqi@0 53 */
aoqi@0 54 final class DefaultParticleBinder extends ParticleBinder {
aoqi@0 55
aoqi@0 56 @Override
aoqi@0 57 public void build( XSParticle p, Collection<XSParticle> forcedProps ) {
aoqi@0 58 Checker checker = checkCollision(p,forcedProps);
aoqi@0 59
aoqi@0 60 if(checker.hasNameCollision()) {
aoqi@0 61 CReferencePropertyInfo prop = new CReferencePropertyInfo(
aoqi@0 62 getCurrentBean().getBaseClass()==null?"Content":"Rest",
aoqi@0 63 true, false, false, p,
aoqi@0 64 builder.getBindInfo(p).toCustomizationList(),
aoqi@0 65 p.getLocator(), false, false, false);
aoqi@0 66 RawTypeSetBuilder.build(p,false).addTo(prop);
aoqi@0 67 prop.javadoc = Messages.format( Messages.MSG_FALLBACK_JAVADOC,
aoqi@0 68 checker.getCollisionInfo().toString() );
aoqi@0 69
aoqi@0 70 getCurrentBean().addProperty(prop);
aoqi@0 71 } else {
aoqi@0 72 new Builder(checker.markedParticles).particle(p);
aoqi@0 73 }
aoqi@0 74 }
aoqi@0 75
aoqi@0 76 @Override
aoqi@0 77 public boolean checkFallback( XSParticle p ) {
aoqi@0 78 return checkCollision(p,Collections.<XSParticle>emptyList()).hasNameCollision();
aoqi@0 79 }
aoqi@0 80
aoqi@0 81 private Checker checkCollision( XSParticle p, Collection<XSParticle> forcedProps ) {
aoqi@0 82 // scan the tree by a checker.
aoqi@0 83 Checker checker = new Checker(forcedProps);
aoqi@0 84
aoqi@0 85 CClassInfo superClass = getCurrentBean().getBaseClass();
aoqi@0 86
aoqi@0 87 if(superClass!=null)
aoqi@0 88 checker.readSuperClass(superClass);
aoqi@0 89 checker.particle(p);
aoqi@0 90
aoqi@0 91 return checker;
aoqi@0 92 }
aoqi@0 93
aoqi@0 94
aoqi@0 95
aoqi@0 96
aoqi@0 97
aoqi@0 98
aoqi@0 99
aoqi@0 100
aoqi@0 101
aoqi@0 102
aoqi@0 103 /**
aoqi@0 104 * Marks particles that need to be mapped to properties,
aoqi@0 105 * by reading customization info.
aoqi@0 106 */
aoqi@0 107 private final class Checker implements XSTermVisitor {
aoqi@0 108
aoqi@0 109 Checker(Collection<XSParticle> forcedProps) {
aoqi@0 110 this.forcedProps = forcedProps;
aoqi@0 111 }
aoqi@0 112
aoqi@0 113 boolean hasNameCollision() {
aoqi@0 114 return collisionInfo!=null;
aoqi@0 115 }
aoqi@0 116
aoqi@0 117 CollisionInfo getCollisionInfo() {
aoqi@0 118 return collisionInfo;
aoqi@0 119 }
aoqi@0 120
aoqi@0 121 /**
aoqi@0 122 * If a collision is found, this field will be non-null.
aoqi@0 123 */
aoqi@0 124 private CollisionInfo collisionInfo = null;
aoqi@0 125
aoqi@0 126 /** Used to check name collision. */
aoqi@0 127 private final NameCollisionChecker cchecker = new NameCollisionChecker();
aoqi@0 128
aoqi@0 129 /**
aoqi@0 130 * @see DefaultParticleBinder#build(XSParticle, Collection<com.sun.xml.internal.xsom.XSParticle>)
aoqi@0 131 */
aoqi@0 132 private final Collection<XSParticle> forcedProps;
aoqi@0 133
aoqi@0 134 public void particle( XSParticle p ) {
aoqi@0 135
aoqi@0 136 if(getLocalPropCustomization(p)!=null
aoqi@0 137 || builder.getLocalDomCustomization(p)!=null) {
aoqi@0 138 // if a property customization is specfied,
aoqi@0 139 // check that value and turn around.
aoqi@0 140 check(p);
aoqi@0 141 mark(p);
aoqi@0 142 return;
aoqi@0 143 }
aoqi@0 144
aoqi@0 145 XSTerm t = p.getTerm();
aoqi@0 146
aoqi@0 147 if(p.isRepeated() && (t.isModelGroup() || t.isModelGroupDecl())) {
aoqi@0 148 // a repeated model group gets its own property
aoqi@0 149 mark(p);
aoqi@0 150 return;
aoqi@0 151 }
aoqi@0 152
aoqi@0 153 if(forcedProps.contains(p)) {
aoqi@0 154 // this particle must become a property
aoqi@0 155 mark(p);
aoqi@0 156 return;
aoqi@0 157 }
aoqi@0 158
aoqi@0 159 outerParticle = p;
aoqi@0 160 t.visit(this);
aoqi@0 161 }
aoqi@0 162
aoqi@0 163 /**
aoqi@0 164 * This field points to the parent XSParticle.
aoqi@0 165 * The value is only valid when we are processing XSTerm.
aoqi@0 166 */
aoqi@0 167 private XSParticle outerParticle;
aoqi@0 168
aoqi@0 169 public void elementDecl(XSElementDecl decl) {
aoqi@0 170 check(outerParticle);
aoqi@0 171 mark(outerParticle);
aoqi@0 172 }
aoqi@0 173
aoqi@0 174 public void modelGroup(XSModelGroup mg) {
aoqi@0 175 // choice gets mapped to a property
aoqi@0 176 if(mg.getCompositor()== XSModelGroup.Compositor.CHOICE && builder.getGlobalBinding().isChoiceContentPropertyEnabled()) {
aoqi@0 177 mark(outerParticle);
aoqi@0 178 return;
aoqi@0 179 }
aoqi@0 180
aoqi@0 181 for( XSParticle child : mg.getChildren() )
aoqi@0 182 particle(child);
aoqi@0 183 }
aoqi@0 184
aoqi@0 185 public void modelGroupDecl(XSModelGroupDecl decl) {
aoqi@0 186 modelGroup(decl.getModelGroup());
aoqi@0 187 }
aoqi@0 188
aoqi@0 189 public void wildcard(XSWildcard wc) {
aoqi@0 190 mark(outerParticle);
aoqi@0 191 }
aoqi@0 192
aoqi@0 193 void readSuperClass( CClassInfo ci ) {
aoqi@0 194 cchecker.readSuperClass(ci);
aoqi@0 195 }
aoqi@0 196
aoqi@0 197
aoqi@0 198
aoqi@0 199
aoqi@0 200 /**
aoqi@0 201 * Checks the name collision of a newly found particle.
aoqi@0 202 */
aoqi@0 203 private void check( XSParticle p ) {
aoqi@0 204 if( collisionInfo==null )
aoqi@0 205 collisionInfo = cchecker.check(p);
aoqi@0 206 }
aoqi@0 207
aoqi@0 208 /**
aoqi@0 209 * Marks a particle that it's going to be mapped to a property.
aoqi@0 210 */
aoqi@0 211 private void mark( XSParticle p ) {
aoqi@0 212 markedParticles.put(p,computeLabel(p));
aoqi@0 213 }
aoqi@0 214
aoqi@0 215 /**
aoqi@0 216 * Marked particles.
aoqi@0 217 *
aoqi@0 218 * A map from XSParticle to its label.
aoqi@0 219 */
aoqi@0 220 public final Map<XSParticle,String> markedParticles = new HashMap<XSParticle,String>();
aoqi@0 221
aoqi@0 222
aoqi@0 223 /**
aoqi@0 224 * Checks name collisions among particles that belong to sequences.
aoqi@0 225 */
aoqi@0 226 private final class NameCollisionChecker {
aoqi@0 227
aoqi@0 228 /**
aoqi@0 229 * Checks the label conflict of a particle.
aoqi@0 230 * This method shall be called for each marked particle.
aoqi@0 231 *
aoqi@0 232 * @return
aoqi@0 233 * a description of a collision if a name collision is
aoqi@0 234 * found. Otherwise null.
aoqi@0 235 */
aoqi@0 236 CollisionInfo check( XSParticle p ) {
aoqi@0 237 // this can be used for particles with a property customization,
aoqi@0 238 // which may not have element declaration as its term.
aoqi@0 239 // // we only check particles with element declarations.
aoqi@0 240 // _assert( p.getTerm().isElementDecl() );
aoqi@0 241
aoqi@0 242 String label = computeLabel(p);
aoqi@0 243 if( occupiedLabels.containsKey(label) ) {
aoqi@0 244 // collide with occupied labels
aoqi@0 245 return new CollisionInfo(label,p.getLocator(),
aoqi@0 246 occupiedLabels.get(label).locator);
aoqi@0 247 }
aoqi@0 248
aoqi@0 249 for( XSParticle jp : particles ) {
aoqi@0 250 if(!check( p, jp )) {
aoqi@0 251 // problem was found. no need to check further
aoqi@0 252 return new CollisionInfo( label, p.getLocator(), jp.getLocator() );
aoqi@0 253 }
aoqi@0 254 }
aoqi@0 255 particles.add(p);
aoqi@0 256 return null;
aoqi@0 257 }
aoqi@0 258
aoqi@0 259 /** List of particles reported through the check method. */
aoqi@0 260 private final List<XSParticle> particles = new ArrayList<XSParticle>();
aoqi@0 261
aoqi@0 262 /**
aoqi@0 263 * Label names already used in the base type.
aoqi@0 264 */
aoqi@0 265 private final Map<String,CPropertyInfo> occupiedLabels = new HashMap<String,CPropertyInfo>();
aoqi@0 266
aoqi@0 267 /**
aoqi@0 268 * Checks the conflict of two particles.
aoqi@0 269 * @return
aoqi@0 270 * true if the check was successful.
aoqi@0 271 */
aoqi@0 272 private boolean check( XSParticle p1, XSParticle p2 ) {
aoqi@0 273 return !computeLabel(p1).equals(computeLabel(p2));
aoqi@0 274 }
aoqi@0 275
aoqi@0 276 /**
aoqi@0 277 * Reads fields of the super class and includes them
aoqi@0 278 * to name collision tests.
aoqi@0 279 */
aoqi@0 280 void readSuperClass( CClassInfo base ) {
aoqi@0 281 for( ; base!=null; base=base.getBaseClass() ) {
aoqi@0 282 for( CPropertyInfo p : base.getProperties() )
aoqi@0 283 occupiedLabels.put(p.getName(true),p);
aoqi@0 284 }
aoqi@0 285 }
aoqi@0 286 }
aoqi@0 287
aoqi@0 288
aoqi@0 289
aoqi@0 290
aoqi@0 291
aoqi@0 292 /** Keep the computed label names for particles. */
aoqi@0 293 private final Map<XSParticle,String> labelCache = new Hashtable<XSParticle,String>();
aoqi@0 294
aoqi@0 295 /**
aoqi@0 296 * Hides the computeLabel method of the outer class
aoqi@0 297 * and adds caching.
aoqi@0 298 */
aoqi@0 299 private String computeLabel( XSParticle p ) {
aoqi@0 300 String label = labelCache.get(p);
aoqi@0 301 if(label==null)
aoqi@0 302 labelCache.put( p, label=DefaultParticleBinder.this.computeLabel(p) );
aoqi@0 303 return label;
aoqi@0 304 }
aoqi@0 305 }
aoqi@0 306
aoqi@0 307
aoqi@0 308
aoqi@0 309
aoqi@0 310
aoqi@0 311
aoqi@0 312
aoqi@0 313
aoqi@0 314
aoqi@0 315
aoqi@0 316
aoqi@0 317
aoqi@0 318 /**
aoqi@0 319 * Builds properties by using the result computed by Checker
aoqi@0 320 */
aoqi@0 321 private final class Builder implements XSTermVisitor {
aoqi@0 322 Builder( Map<XSParticle,String> markedParticles ) {
aoqi@0 323 this.markedParticles = markedParticles;
aoqi@0 324 }
aoqi@0 325
aoqi@0 326 /** All marked particles. */
aoqi@0 327 private final Map<XSParticle,String/*label*/> markedParticles;
aoqi@0 328
aoqi@0 329 /**
aoqi@0 330 * When we are visiting inside an optional particle, this flag
aoqi@0 331 * is set to true.
aoqi@0 332 *
aoqi@0 333 * <p>
aoqi@0 334 * This allows us to correctly generate primitive/boxed types.
aoqi@0 335 */
aoqi@0 336 private boolean insideOptionalParticle;
aoqi@0 337
aoqi@0 338
aoqi@0 339 /** Returns true if a particle is marked. */
aoqi@0 340 private boolean marked( XSParticle p ) {
aoqi@0 341 return markedParticles.containsKey(p);
aoqi@0 342 }
aoqi@0 343 /** Gets a label of a particle. */
aoqi@0 344 private String getLabel( XSParticle p ) {
aoqi@0 345 return markedParticles.get(p);
aoqi@0 346 }
aoqi@0 347
aoqi@0 348 public void particle( XSParticle p ) {
aoqi@0 349 XSTerm t = p.getTerm();
aoqi@0 350
aoqi@0 351 if(marked(p)) {
aoqi@0 352 BIProperty cust = BIProperty.getCustomization(p);
aoqi@0 353 CPropertyInfo prop = cust.createElementOrReferenceProperty(
aoqi@0 354 getLabel(p), false, p, RawTypeSetBuilder.build(p,insideOptionalParticle));
aoqi@0 355 getCurrentBean().addProperty(prop);
aoqi@0 356 } else {
aoqi@0 357 // repeated model groups should have been marked already
aoqi@0 358 assert !p.isRepeated();
aoqi@0 359
aoqi@0 360 boolean oldIOP = insideOptionalParticle;
aoqi@0 361 insideOptionalParticle |= BigInteger.ZERO.equals(p.getMinOccurs());
aoqi@0 362 // this is an unmarked particle
aoqi@0 363 t.visit(this);
aoqi@0 364 insideOptionalParticle = oldIOP;
aoqi@0 365 }
aoqi@0 366 }
aoqi@0 367
aoqi@0 368 public void elementDecl( XSElementDecl e ) {
aoqi@0 369 // because the corresponding particle must be marked.
aoqi@0 370 assert false;
aoqi@0 371 }
aoqi@0 372
aoqi@0 373 public void wildcard( XSWildcard wc ) {
aoqi@0 374 // because the corresponding particle must be marked.
aoqi@0 375 assert false;
aoqi@0 376 }
aoqi@0 377
aoqi@0 378 public void modelGroupDecl( XSModelGroupDecl decl ) {
aoqi@0 379 modelGroup(decl.getModelGroup());
aoqi@0 380 }
aoqi@0 381
aoqi@0 382 public void modelGroup( XSModelGroup mg ) {
aoqi@0 383 boolean oldIOP = insideOptionalParticle;
aoqi@0 384 insideOptionalParticle |= mg.getCompositor()==XSModelGroup.CHOICE;
aoqi@0 385
aoqi@0 386 for( XSParticle p : mg.getChildren())
aoqi@0 387 particle(p);
aoqi@0 388
aoqi@0 389 insideOptionalParticle = oldIOP;
aoqi@0 390 }
aoqi@0 391 }
aoqi@0 392 }

mercurial