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 */ 25 26 package com.sun.xml.internal.xsom.impl.scd; 27 28 import com.sun.xml.internal.xsom.XSAttContainer; 29 import com.sun.xml.internal.xsom.XSAttGroupDecl; 30 import com.sun.xml.internal.xsom.XSAttributeDecl; 31 import com.sun.xml.internal.xsom.XSAttributeUse; 32 import com.sun.xml.internal.xsom.XSComplexType; 33 import com.sun.xml.internal.xsom.XSComponent; 34 import com.sun.xml.internal.xsom.XSElementDecl; 35 import com.sun.xml.internal.xsom.XSFacet; 36 import com.sun.xml.internal.xsom.XSIdentityConstraint; 37 import com.sun.xml.internal.xsom.XSListSimpleType; 38 import com.sun.xml.internal.xsom.XSModelGroup; 39 import com.sun.xml.internal.xsom.XSModelGroup.Compositor; 40 import com.sun.xml.internal.xsom.XSModelGroupDecl; 41 import com.sun.xml.internal.xsom.XSNotation; 42 import com.sun.xml.internal.xsom.XSParticle; 43 import com.sun.xml.internal.xsom.XSRestrictionSimpleType; 44 import com.sun.xml.internal.xsom.XSSchema; 45 import com.sun.xml.internal.xsom.XSSimpleType; 46 import com.sun.xml.internal.xsom.XSType; 47 import com.sun.xml.internal.xsom.XSUnionSimpleType; 48 import com.sun.xml.internal.xsom.XSWildcard; 49 50 import java.util.ArrayList; 51 import java.util.HashSet; 52 import java.util.Iterator; 53 import java.util.List; 54 import java.util.Set; 55 56 /** 57 * Axis of traversal. 58 * 59 * @param <T> 60 * The kind of components that this axis may return. 61 * 62 * @author Kohsuke Kawaguchi 63 */ 64 public interface Axis<T extends XSComponent> { iterator(XSComponent contextNode)65 Iterator<T> iterator(XSComponent contextNode); 66 iterator(Iterator<? extends XSComponent> contextNodes)67 Iterator<T> iterator(Iterator<? extends XSComponent> contextNodes); 68 69 /** 70 * Returns true if this is one of the model group axis. 71 */ isModelGroup()72 boolean isModelGroup(); 73 74 75 /** 76 * Pseudo-axis that selects all the {@link XSSchema}s in the current set. 77 * Used to implement the absolute path expression 78 */ 79 public static final Axis<XSSchema> ROOT = new Axis<XSSchema>() { 80 public Iterator<XSSchema> iterator(XSComponent contextNode) { 81 return contextNode.getRoot().iterateSchema(); 82 } 83 84 public Iterator<XSSchema> iterator(Iterator<? extends XSComponent> contextNodes) { 85 if(!contextNodes.hasNext()) 86 return Iterators.empty(); 87 else 88 // this assumes that all current nodes belong to the same owner. 89 return iterator(contextNodes.next()); 90 } 91 92 public boolean isModelGroup() { 93 return false; 94 } 95 96 public String toString() { 97 return "root::"; 98 } 99 }; 100 101 /** 102 * Pseudo-axis that visits all skipped intermediate steps. 103 * Those are: 104 * <ol> 105 * <li>complex type reachable from element 106 * <li>model groups 107 * <li>combination of above. 108 * </ol> 109 */ 110 public static final Axis<XSComponent> INTERMEDIATE_SKIP = new AbstractAxisImpl<XSComponent>() { 111 public Iterator<XSComponent> elementDecl(XSElementDecl decl) { 112 XSComplexType ct = decl.getType().asComplexType(); 113 if(ct==null) 114 return empty(); 115 else { 116 // also pick up model groups inside this complex type 117 return new Iterators.Union<XSComponent>(singleton(ct),complexType(ct)); 118 } 119 } 120 121 public Iterator<XSComponent> modelGroupDecl(XSModelGroupDecl decl) { 122 return descendants(decl.getModelGroup()); 123 } 124 125 public Iterator<XSComponent> particle(XSParticle particle) { 126 return descendants(particle.getTerm().asModelGroup()); 127 } 128 129 /** 130 * Iterate all descendant model groups of the given model group, including itself. 131 */ 132 private Iterator<XSComponent> descendants(XSModelGroup mg) { 133 // TODO: write a tree iterator 134 // for now, we do it eagerly because I'm lazy 135 List<XSComponent> r = new ArrayList<XSComponent>(); 136 visit(mg,r); 137 return r.iterator(); 138 } 139 140 private void visit(XSModelGroup mg, List<XSComponent> r) { 141 // since model groups never form a cycle, no cycle check is needed 142 r.add(mg); 143 for (XSParticle p : mg) { 144 XSModelGroup child = p.getTerm().asModelGroup(); 145 if(child!=null) 146 visit(child,r); 147 } 148 } 149 150 public String toString() { 151 return "(intermediateSkip)"; 152 } 153 }; 154 155 /** 156 * All descendants reachable via default axes. Used to implement the "//" semantics. 157 * 158 * So far the default axes together are guaranteed not to cause any cycle, so 159 * no cycle check is needed (if it's needed, the life would be much harder!) 160 */ 161 public static final Axis<XSComponent> DESCENDANTS = new Axis<XSComponent>() { 162 public Iterator<XSComponent> iterator(XSComponent contextNode) { 163 return new Visitor().iterator(contextNode); 164 } 165 public Iterator<XSComponent> iterator(Iterator<? extends XSComponent> contextNodes) { 166 return new Visitor().iterator(contextNodes); 167 } 168 169 public boolean isModelGroup() { 170 return false; 171 } 172 173 /** 174 * Stateful visitor that remembers what's already traversed, to reduce the search space. 175 */ 176 final class Visitor extends AbstractAxisImpl<XSComponent> { 177 private final Set<XSComponent> visited = new HashSet<XSComponent>(); 178 179 /** 180 * Recursively apply the {@link Axis#DESCENDANTS} axis. 181 */ 182 final class Recursion extends Iterators.Map<XSComponent,XSComponent> { 183 public Recursion(Iterator<? extends XSComponent> core) { 184 super(core); 185 } 186 187 protected Iterator<XSComponent> apply(XSComponent u) { 188 return DESCENDANTS.iterator(u); 189 } 190 } 191 public Iterator<XSComponent> schema(XSSchema schema) { 192 if(visited.add(schema)) 193 return ret( schema, new Recursion(schema.iterateElementDecls())); 194 else 195 return empty(); 196 } 197 198 public Iterator<XSComponent> elementDecl(XSElementDecl decl) { 199 if(visited.add(decl)) 200 return ret(decl, iterator(decl.getType()) ); 201 else 202 return empty(); 203 } 204 205 public Iterator<XSComponent> simpleType(XSSimpleType type) { 206 if(visited.add(type)) 207 return ret(type, FACET.iterator(type)); 208 else 209 return empty(); 210 } 211 212 public Iterator<XSComponent> complexType(XSComplexType type) { 213 if(visited.add(type)) 214 return ret(type, iterator(type.getContentType())); 215 else 216 return empty(); 217 } 218 219 public Iterator<XSComponent> particle(XSParticle particle) { 220 if(visited.add(particle)) 221 return ret(particle, iterator(particle.getTerm())); 222 else 223 return empty(); 224 } 225 226 public Iterator<XSComponent> modelGroupDecl(XSModelGroupDecl decl) { 227 if(visited.add(decl)) 228 return ret(decl, iterator(decl.getModelGroup())); 229 else 230 return empty(); 231 } 232 233 public Iterator<XSComponent> modelGroup(XSModelGroup group) { 234 if(visited.add(group)) 235 return ret(group, new Recursion(group.iterator())); 236 else 237 return empty(); 238 } 239 240 public Iterator<XSComponent> attGroupDecl(XSAttGroupDecl decl) { 241 if(visited.add(decl)) 242 return ret(decl, new Recursion(decl.iterateAttributeUses())); 243 else 244 return empty(); 245 } 246 247 public Iterator<XSComponent> attributeUse(XSAttributeUse use) { 248 if(visited.add(use)) 249 return ret(use, iterator(use.getDecl())); 250 else 251 return empty(); 252 } 253 254 public Iterator<XSComponent> attributeDecl(XSAttributeDecl decl) { 255 if(visited.add(decl)) 256 return ret(decl, iterator(decl.getType())); 257 else 258 return empty(); 259 } 260 261 private Iterator<XSComponent> ret( XSComponent one, Iterator<? extends XSComponent> rest ) { 262 return union(singleton(one),rest); 263 } 264 } 265 266 public String toString() { 267 return "/"; 268 } 269 }; 270 271 public static final Axis<XSSchema> X_SCHEMA = new Axis<XSSchema>() { 272 public Iterator<XSSchema> iterator(XSComponent contextNode) { 273 return Iterators.singleton(contextNode.getOwnerSchema()); 274 } 275 276 public Iterator<XSSchema> iterator(Iterator<? extends XSComponent> contextNodes) { 277 return new Iterators.Adapter<XSSchema,XSComponent>(contextNodes) { 278 protected XSSchema filter(XSComponent u) { 279 return u.getOwnerSchema(); 280 } 281 }; 282 } 283 284 public boolean isModelGroup() { 285 return false; 286 } 287 288 public String toString() { 289 return "x-schema::"; 290 } 291 }; 292 293 public static final Axis<XSElementDecl> SUBSTITUTION_GROUP = new AbstractAxisImpl<XSElementDecl>() { 294 public Iterator<XSElementDecl> elementDecl(XSElementDecl decl) { 295 return singleton(decl.getSubstAffiliation()); 296 } 297 298 public String toString() { 299 return "substitutionGroup::"; 300 } 301 }; 302 303 public static final Axis<XSAttributeDecl> ATTRIBUTE = new AbstractAxisImpl<XSAttributeDecl>() { 304 public Iterator<XSAttributeDecl> complexType(XSComplexType type) { 305 return attributeHolder(type); 306 } 307 308 public Iterator<XSAttributeDecl> attGroupDecl(XSAttGroupDecl decl) { 309 return attributeHolder(decl); 310 } 311 312 private Iterator<XSAttributeDecl> attributeHolder(final XSAttContainer atts) { 313 // TODO: check spec. is this correct? 314 return new Iterators.Adapter<XSAttributeDecl,XSAttributeUse>(atts.iterateAttributeUses()) { 315 protected XSAttributeDecl filter(XSAttributeUse u) { 316 return u.getDecl(); 317 } 318 }; 319 } 320 321 public Iterator<XSAttributeDecl> schema(XSSchema schema) { 322 return schema.iterateAttributeDecls(); 323 } 324 325 public String toString() { 326 return "@"; 327 } 328 }; 329 330 public static final Axis<XSElementDecl> ELEMENT = new AbstractAxisImpl<XSElementDecl>() { 331 public Iterator<XSElementDecl> particle(XSParticle particle) { 332 return singleton(particle.getTerm().asElementDecl()); 333 } 334 335 public Iterator<XSElementDecl> schema(XSSchema schema) { 336 return schema.iterateElementDecls(); 337 } 338 339 public Iterator<XSElementDecl> modelGroupDecl(XSModelGroupDecl decl) { 340 return modelGroup(decl.getModelGroup()); 341 } 342 343 //public Iterator<XSElementDecl> modelGroup(XSModelGroup group) { 344 // return new Iterators.Map<XSElementDecl,XSParticle>(group.iterator()) { 345 // protected Iterator<XSElementDecl> apply(XSParticle p) { 346 // return particle(p); 347 // } 348 // }; 349 //} 350 351 @Override 352 public String getName() { 353 return ""; 354 } 355 356 public String toString() { 357 return "element::"; 358 } 359 }; 360 361 362 public static final Axis<XSType> TYPE_DEFINITION = new AbstractAxisImpl<XSType>() { 363 public Iterator<XSType> schema(XSSchema schema) { 364 return schema.iterateTypes(); 365 } 366 367 public Iterator<XSType> attributeDecl(XSAttributeDecl decl) { 368 return singleton(decl.getType()); 369 } 370 371 public Iterator<XSType> elementDecl(XSElementDecl decl) { 372 return singleton(decl.getType()); 373 } 374 375 public String toString() { 376 return "~"; 377 } 378 }; 379 380 public static final Axis<XSType> BASETYPE = new AbstractAxisImpl<XSType>() { 381 public Iterator<XSType> simpleType(XSSimpleType type) { 382 return singleton(type.getBaseType()); 383 } 384 385 public Iterator<XSType> complexType(XSComplexType type) { 386 return singleton(type.getBaseType()); 387 } 388 389 public String toString() { 390 return "baseType::"; 391 } 392 }; 393 394 public static final Axis<XSSimpleType> PRIMITIVE_TYPE = new AbstractAxisImpl<XSSimpleType>() { 395 public Iterator<XSSimpleType> simpleType(XSSimpleType type) { 396 return singleton(type.getPrimitiveType()); 397 } 398 399 public String toString() { 400 return "primitiveType::"; 401 } 402 }; 403 404 public static final Axis<XSSimpleType> ITEM_TYPE = new AbstractAxisImpl<XSSimpleType>() { 405 public Iterator<XSSimpleType> simpleType(XSSimpleType type) { 406 XSListSimpleType baseList = type.getBaseListType(); 407 if(baseList==null) return empty(); 408 return singleton(baseList.getItemType()); 409 } 410 411 public String toString() { 412 return "itemType::"; 413 } 414 }; 415 416 public static final Axis<XSSimpleType> MEMBER_TYPE = new AbstractAxisImpl<XSSimpleType>() { 417 public Iterator<XSSimpleType> simpleType(XSSimpleType type) { 418 XSUnionSimpleType baseUnion = type.getBaseUnionType(); 419 if(baseUnion ==null) return empty(); 420 return baseUnion.iterator(); 421 } 422 423 public String toString() { 424 return "memberType::"; 425 } 426 }; 427 428 public static final Axis<XSComponent> SCOPE = new AbstractAxisImpl<XSComponent>() { 429 public Iterator<XSComponent> complexType(XSComplexType type) { 430 return singleton(type.getScope()); 431 } 432 // TODO: attribute declaration has a scope, too. 433 // TODO: element declaration has a scope 434 435 public String toString() { 436 return "scope::"; 437 } 438 }; 439 440 public static final Axis<XSAttGroupDecl> ATTRIBUTE_GROUP = new AbstractAxisImpl<XSAttGroupDecl>() { 441 public Iterator<XSAttGroupDecl> schema(XSSchema schema) { 442 return schema.iterateAttGroupDecls(); 443 } 444 445 public String toString() { 446 return "attributeGroup::"; 447 } 448 }; 449 450 public static final Axis<XSModelGroupDecl> MODEL_GROUP_DECL = new AbstractAxisImpl<XSModelGroupDecl>() { 451 public Iterator<XSModelGroupDecl> schema(XSSchema schema) { 452 return schema.iterateModelGroupDecls(); 453 } 454 455 public Iterator<XSModelGroupDecl> particle(XSParticle particle) { 456 return singleton(particle.getTerm().asModelGroupDecl()); 457 } 458 459 public String toString() { 460 return "group::"; 461 } 462 }; 463 464 public static final Axis<XSIdentityConstraint> IDENTITY_CONSTRAINT = new AbstractAxisImpl<XSIdentityConstraint>() { 465 public Iterator<XSIdentityConstraint> elementDecl(XSElementDecl decl) { 466 return decl.getIdentityConstraints().iterator(); 467 } 468 469 public Iterator<XSIdentityConstraint> schema(XSSchema schema) { 470 // TODO: iterate all elements in this schema (local or global!) and its identity constraints 471 return super.schema(schema); 472 } 473 474 public String toString() { 475 return "identityConstraint::"; 476 } 477 }; 478 479 public static final Axis<XSIdentityConstraint> REFERENCED_KEY = new AbstractAxisImpl<XSIdentityConstraint>() { 480 public Iterator<XSIdentityConstraint> identityConstraint(XSIdentityConstraint decl) { 481 return singleton(decl.getReferencedKey()); 482 } 483 484 public String toString() { 485 return "key::"; 486 } 487 }; 488 489 public static final Axis<XSNotation> NOTATION = new AbstractAxisImpl<XSNotation>() { 490 public Iterator<XSNotation> schema(XSSchema schema) { 491 return schema.iterateNotations(); 492 } 493 494 public String toString() { 495 return "notation::"; 496 } 497 }; 498 499 public static final Axis<XSWildcard> WILDCARD = new AbstractAxisImpl<XSWildcard>() { 500 public Iterator<XSWildcard> particle(XSParticle particle) { 501 return singleton(particle.getTerm().asWildcard()); 502 } 503 504 public String toString() { 505 return "any::"; 506 } 507 }; 508 509 public static final Axis<XSWildcard> ATTRIBUTE_WILDCARD = new AbstractAxisImpl<XSWildcard>() { 510 public Iterator<XSWildcard> complexType(XSComplexType type) { 511 return singleton(type.getAttributeWildcard()); 512 } 513 514 public Iterator<XSWildcard> attGroupDecl(XSAttGroupDecl decl) { 515 return singleton(decl.getAttributeWildcard()); 516 } 517 518 public String toString() { 519 return "anyAttribute::"; 520 } 521 }; 522 523 public static final Axis<XSFacet> FACET = new AbstractAxisImpl<XSFacet>() { 524 public Iterator<XSFacet> simpleType(XSSimpleType type) { 525 // TODO: it's not clear if "facets" mean all inherited facets or just declared facets 526 XSRestrictionSimpleType r = type.asRestriction(); 527 if(r!=null) 528 return r.iterateDeclaredFacets(); 529 else 530 return empty(); 531 } 532 533 public String toString() { 534 return "facet::"; 535 } 536 }; 537 538 public static final Axis<XSModelGroup> MODELGROUP_ALL = new ModelGroupAxis(Compositor.ALL); 539 public static final Axis<XSModelGroup> MODELGROUP_CHOICE = new ModelGroupAxis(Compositor.CHOICE); 540 public static final Axis<XSModelGroup> MODELGROUP_SEQUENCE = new ModelGroupAxis(Compositor.SEQUENCE); 541 public static final Axis<XSModelGroup> MODELGROUP_ANY = new ModelGroupAxis(null); 542 543 static final class ModelGroupAxis extends AbstractAxisImpl<XSModelGroup> { 544 private final XSModelGroup.Compositor compositor; 545 ModelGroupAxis(Compositor compositor)546 ModelGroupAxis(Compositor compositor) { 547 this.compositor = compositor; 548 } 549 550 @Override isModelGroup()551 public boolean isModelGroup() { 552 return true; 553 } 554 particle(XSParticle particle)555 public Iterator<XSModelGroup> particle(XSParticle particle) { 556 return filter(particle.getTerm().asModelGroup()); 557 } 558 modelGroupDecl(XSModelGroupDecl decl)559 public Iterator<XSModelGroup> modelGroupDecl(XSModelGroupDecl decl) { 560 return filter(decl.getModelGroup()); 561 } 562 filter(XSModelGroup mg)563 private Iterator<XSModelGroup> filter(XSModelGroup mg) { 564 if(mg==null) 565 return empty(); 566 if(mg.getCompositor() == compositor || compositor == null) 567 return singleton(mg); 568 else 569 return empty(); 570 } 571 toString()572 public String toString() { 573 if(compositor==null) 574 return "model::*"; 575 else 576 return "model::"+compositor; 577 } 578 } 579 } 580