1 22 23 package org.xquark.xquery.typing; 24 25 import java.util.*; 26 27 import org.xquark.schema.*; 28 import org.xquark.xpath.Axis; 29 import org.xquark.xpath.NodeKind; 30 import org.xquark.xpath.StepExpr; 31 import org.xquark.xquery.parser.QName; 32 import org.xquark.xquery.parser.XQueryException; 33 34 public class ComputeSubTypeVisitor extends DefaultQTypeVisitor { 35 36 private List historyList = null; 37 private PrimeList resultList = null; 38 private QType resultQType = null; 39 private StepExpr step = null; 40 private SchemaManager schemamanager = null; 41 private byte axis = Axis.NONE; 42 private byte kind = NodeKind.NONE; 43 private QType ANYELT = null; 44 private QType ANYATT = null; 45 private QType TEXT_0_1 = null; 49 private QType TEXT_1_1 = null; 50 private QType TEXT_0_N = null; 51 52 public ComputeSubTypeVisitor() { 53 historyList = new ArrayList(); 54 resultList = new PrimeList(); 55 } 56 57 public void reset(byte contextType, StepExpr step, SchemaManager schemamanager) throws XQueryException { 58 this.step = step; 59 this.schemamanager = schemamanager; 60 historyList.clear(); 61 resultList.clear(); 62 resultQType = null; 63 axis = step.getAxis(); 64 kind = step.getKindTest(); 65 if (ANYELT == null) 66 ANYELT = new QTypeElement(new QName("*", null, "*", null, null), schemamanager.getType(SchemaConstants.XMLSCHEMA_URI, TypeVisitor.SC_ANYTYPE), QType.OCC_0_N); 67 if (ANYATT == null) 68 ANYATT = new QTypeAttribute(new QName("*", null, "*", null, null), (SimpleType) schemamanager.getAnySimpleType()); 69 if (TEXT_0_1 == null) 70 TEXT_0_1 = new QTypeText((SimpleType) schemamanager.getAnySimpleType(), QType.OCC_0_1); 71 if (TEXT_1_1 == null) 72 TEXT_1_1 = new QTypeText((SimpleType) schemamanager.getAnySimpleType(), QType.OCC_0_N); 73 if (TEXT_0_N == null) 74 TEXT_0_N = new QTypeText((SimpleType) schemamanager.getAnySimpleType(), QType.OCC_0_N); 75 } 76 77 public QType getResultQType() { 78 return resultQType; 79 } 80 81 public void visit(QType arg) throws XQueryException { 82 resultQType = null; 83 } 84 85 public void visit(QTypeText arg) throws XQueryException { 86 resultQType = null; 87 Type type = arg.getType(); 88 switch (kind) { 89 case NodeKind.TEXT : 90 switch (axis) { 92 case Axis.SELF : 93 resultQType = arg; 94 break; 95 case Axis.CHILD : 97 case Axis.DESCENDANT : 98 case Axis.DESCENDANT_OR_SELF : 99 case Axis.PARENT : 100 case Axis.ANCESTOR : 101 case Axis.ANCESTOR_OR_SELF : 102 case Axis.ATTRIBUTE : 103 case Axis.FOLLOWING : 104 case Axis.FOLLOWING_SIBLING : 105 case Axis.NAMESPACE : 106 case Axis.PRECEDING : 107 case Axis.PRECEDING_SIBLING : 108 break; 109 } 110 break; 111 case NodeKind.NODE : 112 switch (axis) { 115 case Axis.SELF : 116 case Axis.DESCENDANT_OR_SELF : 117 resultQType = arg; 118 break; 119 case Axis.PARENT : 121 break; 122 case Axis.CHILD : 124 case Axis.DESCENDANT : 125 case Axis.ANCESTOR : 126 case Axis.ANCESTOR_OR_SELF : 127 case Axis.ATTRIBUTE : 128 case Axis.FOLLOWING : 129 case Axis.FOLLOWING_SIBLING : 130 case Axis.NAMESPACE : 131 case Axis.PRECEDING : 132 case Axis.PRECEDING_SIBLING : 133 break; 134 } 135 break; 136 case NodeKind.ELEMENT : 137 switch (axis) { 139 case Axis.PARENT : 141 break; 142 case Axis.SELF : 144 case Axis.CHILD : 145 case Axis.DESCENDANT : 146 case Axis.DESCENDANT_OR_SELF : 147 case Axis.ANCESTOR : 148 case Axis.ANCESTOR_OR_SELF : 149 case Axis.ATTRIBUTE : 150 case Axis.FOLLOWING : 151 case Axis.FOLLOWING_SIBLING : 152 case Axis.NAMESPACE : 153 case Axis.PRECEDING : 154 case Axis.PRECEDING_SIBLING : 155 break; 156 } 157 break; 158 } 159 } 160 161 public void visit(QTypeAttribute arg) throws XQueryException { 162 resultQType = null; 163 Type type = arg.getType(); 164 switch (kind) { 165 case NodeKind.NODE : 166 switch (axis) { 169 case Axis.SELF : 170 case Axis.DESCENDANT_OR_SELF : 171 resultQType = arg; 172 break; 173 case Axis.PARENT : 175 break; 176 case Axis.CHILD : 178 case Axis.DESCENDANT : 179 case Axis.ANCESTOR : 180 case Axis.ANCESTOR_OR_SELF : 181 case Axis.ATTRIBUTE : 182 case Axis.FOLLOWING : 183 case Axis.FOLLOWING_SIBLING : 184 case Axis.NAMESPACE : 185 case Axis.PRECEDING : 186 case Axis.PRECEDING_SIBLING : 187 break; 188 } 189 break; 190 case NodeKind.ELEMENT : 191 switch (axis) { 193 case Axis.PARENT : 195 break; 196 case Axis.SELF : 198 case Axis.CHILD : 199 case Axis.DESCENDANT : 200 case Axis.DESCENDANT_OR_SELF : 201 case Axis.ANCESTOR : 202 case Axis.ANCESTOR_OR_SELF : 203 case Axis.ATTRIBUTE : 204 case Axis.FOLLOWING : 205 case Axis.FOLLOWING_SIBLING : 206 case Axis.NAMESPACE : 207 case Axis.PRECEDING : 208 case Axis.PRECEDING_SIBLING : 209 break; 210 } 211 break; 212 } 213 } 214 215 219 public void visit(QTypeDocument arg) throws XQueryException { 220 resultQType = null; 221 if (arg.getQType() != null) { 222 switch (kind) { 223 case NodeKind.ATTRIBUTE : 224 case NodeKind.TEXT : 225 return; 227 case NodeKind.NODE : 228 switch (axis) { 233 case Axis.SELF : 234 resultQType = arg; 235 break; 236 case Axis.CHILD : 237 case Axis.DESCENDANT : 238 arg.getQType().accept(this); 239 break; 240 case Axis.DESCENDANT_OR_SELF : 241 arg.getQType().accept(this); 242 if (resultQType == null) 243 resultQType = arg; 244 else { 245 if (resultQType instanceof QTypeUnion) { 246 List list = ((QTypeUnion) resultQType).getPrimeList(); 247 list.add(arg); 248 resultQType = new QTypeUnion(list, ((QTypeUnion) resultQType).getOccurence()); 249 } else { 250 List list = new ArrayList(2); 251 list.add(arg); 252 list.add(resultQType); 253 } 254 } 255 break; 256 } 257 break; 258 } 266 } 267 if (resultQType != null) 268 return; 269 if (kind == NodeKind.ELEMENT) { 270 String namespace = step.getNameSpace(); 271 String localname = step.getLocalName(); 272 if (namespace != null && namespace.equals("*")) { 273 274 Collection schemas = schemamanager.getSchemas(); 275 for (Iterator it = schemas.iterator(); it.hasNext();) { 276 Schema schema = (Schema) it.next(); 277 ElementDeclaration eltdecl = schema.getElementDeclaration(localname); 278 if (eltdecl != null) { 279 resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), eltdecl, eltdecl.getType()); 280 break; 281 } 282 } 283 if (resultQType == null && arg.isFromDocument()) 284 resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), schemamanager.getType(SchemaConstants.XMLSCHEMA_URI, TypeVisitor.SC_ANYTYPE)); 285 286 } else { 287 ElementDeclaration eltdecl = schemamanager.getElementDeclaration(namespace, localname); 288 if (eltdecl != null) 289 resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), eltdecl.getType()); 290 else if (arg.isFromDocument()) 291 resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), schemamanager.getType(SchemaConstants.XMLSCHEMA_URI, TypeVisitor.SC_ANYTYPE)); 292 } 294 } else { 296 if (arg.getQType() == null) 297 return; 298 arg.getQType().accept(this); 299 } 300 } 301 304 public void visit(QTypeElement arg) throws XQueryException { 305 resultQType = null; 306 Type type = arg.getType(); 307 switch (kind) { 308 case NodeKind.TEXT : 309 switch (axis) { 313 case Axis.CHILD : 315 case Axis.DESCENDANT_OR_SELF : 316 if (type.getValueType() != null) { 317 resultQType = TEXT_0_1; 318 } else if (type.getContentType() == Type.MIXED) { 319 resultQType = TEXT_0_N; 320 } else { 321 resultQType = null; 322 } 323 if (axis == Axis.CHILD || (resultQType != null && resultQType.isMultiple())) 325 break; 326 case Axis.DESCENDANT : 327 resultList.add(resultQType); 329 axis = Axis.DESCENDANT_OR_SELF; 331 Collection decls = type.getElementDeclarations(); 332 if (decls != null && !decls.isEmpty()) { 333 Iterator it = decls.iterator(); 334 while (it.hasNext()) { 335 Declaration decl = (Declaration) it.next(); 337 StringBuffer buf = new StringBuffer (); 338 if (decl.getNamespace() != null) { 339 buf.append(decl.getNamespace()); 340 buf.append(":"); 341 } 342 buf.append(decl.getName()); 343 if (historyList.contains(buf.toString())) { 345 continue; 346 } 347 historyList.add(buf.toString()); 348 QType tmpQType = null; 349 try { 350 tmpQType = getQTypeFromDeclaration(decl); 351 } catch (XQueryException e) { 352 } 354 if (tmpQType != null) { 355 tmpQType.accept(this); 356 resultList.add(resultQType); 357 } 358 historyList.remove(buf.toString()); 359 if (resultQType.isMultiple()) 361 break; 362 369 } 370 } 371 break; 372 case Axis.ANCESTOR : 375 case Axis.ANCESTOR_OR_SELF : 376 case Axis.ATTRIBUTE : 377 case Axis.FOLLOWING : 378 case Axis.FOLLOWING_SIBLING : 379 case Axis.NAMESPACE : 380 case Axis.PARENT : 381 case Axis.PRECEDING : 382 case Axis.PRECEDING_SIBLING : 383 case Axis.SELF : 384 break; 385 } 386 break; 387 case NodeKind.NODE : 388 switch (axis) { 393 case Axis.SELF : 395 resultQType = arg; 396 break; 397 case Axis.CHILD : 398 ArrayList list = new ArrayList(); 399 if (type.getValueType() != null) { 400 list.add(TEXT_0_1); 401 } else if (((ComplexType) type).getContentType() == Type.MIXED) { 402 list.add(TEXT_0_N); 403 } 404 Collection col = type.getElementDeclarations(); 405 if (col != null && !col.isEmpty()) { 406 Iterator it = col.iterator(); 407 while (it.hasNext()) { 408 ElementDeclaration eltDecl = (ElementDeclaration) it.next(); 409 try { 410 QType tmpQType = getQTypeFromDeclaration(eltDecl); 411 if (tmpQType != null && !list.contains(tmpQType)) 412 list.add(tmpQType); 413 } catch (XQueryException e) { 414 } 416 } 417 } else { 418 if (compareQNames(type.getNamespace(), type.getName(), SchemaConstants.XMLSCHEMA_URI, SchemaConstants.ANY_TYPE)) 419 list.add(new QTypeElement(arg.getName(), type)); 420 } 421 if (!list.isEmpty()) { 422 if (list.size() > 1) 423 resultQType = new QTypeUnion(list); 424 else 425 resultQType = (QType) list.get(0); 426 } 427 break; 428 case Axis.DESCENDANT_OR_SELF : 429 case Axis.DESCENDANT : 430 if (type.getValueType() != null) { 434 resultList.add(TEXT_0_1); 435 } else if (((ComplexType) type).getContentType() == Type.MIXED) { 436 resultList.add(TEXT_0_N); 437 } 438 if (axis == Axis.DESCENDANT_OR_SELF) 440 resultList.add(arg); 441 axis = Axis.DESCENDANT_OR_SELF; 443 if (arg.getType().getName() != null && arg.getType().getName().equals(TypeVisitor.SC_ANYTYPE) && !resultList.contains(ANYELT)) { 445 resultList.add(ANYELT); 446 } 447 Collection decls = type.getElementDeclarations(); 449 if (decls != null && !decls.isEmpty()) { 450 Iterator it = decls.iterator(); 451 while (it.hasNext()) { 452 Declaration decl = (Declaration) it.next(); 453 StringBuffer buf = new StringBuffer (); 454 if (decl.getNamespace() != null) { 455 buf.append(decl.getNamespace()); 456 buf.append(":"); 457 } 458 buf.append(decl.getName()); 459 if (historyList.contains(buf.toString())) { continue; 461 } 462 historyList.add(buf.toString()); 463 QType tmpQType = null; 464 try { 465 tmpQType = getQTypeFromDeclaration(decl); 466 } catch (XQueryException e) { 467 } 469 if (tmpQType != null) { 470 tmpQType.accept(this); 471 resultList.add(resultQType); 472 } 473 historyList.remove(buf.toString()); 474 } 475 } 476 if (historyList.isEmpty()) { 477 if (resultList.size() == 1) 478 resultQType = (QType) resultList.get(0); 479 else if (!resultList.isEmpty()) 480 resultQType = new QTypeUnion(resultList); 481 resultList.clear(); 482 } 483 break; 484 case Axis.ANCESTOR : 486 case Axis.ANCESTOR_OR_SELF : 487 case Axis.ATTRIBUTE : 488 case Axis.FOLLOWING : 489 case Axis.FOLLOWING_SIBLING : 490 case Axis.NAMESPACE : 491 case Axis.PARENT : 492 case Axis.PRECEDING : 493 case Axis.PRECEDING_SIBLING : 494 break; 495 } 497 break; 498 case NodeKind.ATTRIBUTE : 499 break; 500 case NodeKind.ELEMENT : 501 String namespace = step.getNameSpace(); 507 String localname = step.getLocalName(); 508 Type argType = arg.getType(); 509 switch (axis) { 510 case Axis.ATTRIBUTE : 512 if (argType.getName() != null && argType.getName().equals(TypeVisitor.SC_ANYTYPE)) { 513 resultQType = new QTypeAttribute(new QName(namespace, null, localname, null, null),schemamanager.getAnySimpleType()); 515 } else { 517 AttributeDeclaration attDecl = type.getAttributeDeclaration(namespace, localname); 518 if (attDecl == null) { 519 if (localname == null) 521 localname = ""; 522 Collection decls = type.getAttributeDeclarations(); 523 if (decls != null && !decls.isEmpty()) { 524 Iterator it = decls.iterator(); 525 ArrayList list = new ArrayList(); 526 while (it.hasNext()) { 527 AttributeDeclaration decl = (AttributeDeclaration) it.next(); 528 if (compareQNames(namespace, localname, decl.getNamespace(), decl.getName())) { 529 QType tmpQType = null; 530 try { 531 tmpQType = getQTypeFromDeclaration(decl); 532 } catch (XQueryException e) { 533 } 535 if (tmpQType != null && !list.contains(tmpQType)) 536 list.add(tmpQType); 537 } 538 } 539 if (!list.isEmpty()) 540 if (list.size() > 1) 542 resultQType = new QTypeUnion(list); 543 else 544 resultQType = (QType) list.get(0); 545 } 546 } else { try { 548 resultQType = this.getQTypeFromDeclaration((Declaration) attDecl); 549 } catch (XQueryException e) { 550 resultQType = null; 552 } 553 } 554 } 555 break; 556 case Axis.CHILD : 557 if (type.getValueType() != null || type.getContentType() == Type.EMPTY) 558 break; 559 Utils.getSubType((Particle) ((ComplexType) type).getContentModel().getModel(), namespace, localname, schemamanager); 560 resultQType = Utils.getOccurrenceVisitor().getQType(); 561 break; 562 case Axis.DESCENDANT_OR_SELF : 563 case Axis.SELF : 564 QName argqname = (QName) arg.getName(); 565 if (compareQNames(namespace, localname, argqname.getNameSpace(), argqname.getLocalName())) { 566 resultQType = new QTypeElement(new QName(namespace, null, localname, null, null), argType, QType.OCC_0_N); 567 } 568 if (axis == Axis.SELF) 569 break; 570 resultList.add(resultQType); 572 case Axis.DESCENDANT : 573 axis = Axis.DESCENDANT_OR_SELF; 575 Collection decls = type.getElementDeclarations(); 577 if (decls != null && !decls.isEmpty()) { 578 Iterator it = decls.iterator(); 579 while (it.hasNext()) { 580 Declaration decl = (Declaration) it.next(); 581 StringBuffer buf = new StringBuffer (); 582 if (decl.getNamespace() != null) { 583 buf.append(decl.getNamespace()); 584 buf.append(":"); 585 } 586 buf.append(decl.getName()); 587 if (historyList.contains(buf.toString())) { continue; 589 } 590 historyList.add(buf.toString()); 591 QType tmpQType = null; 592 try { 593 tmpQType = getQTypeFromDeclaration(decl); 594 } catch (XQueryException e) { 595 } 597 if (tmpQType != null) { 598 tmpQType.accept(this); 599 resultList.add(resultQType); 600 } 601 historyList.remove(buf.toString()); 602 } 603 } 604 if (historyList.isEmpty()) { 605 if (resultList.size() == 1) 606 resultQType = (QType) resultList.get(0); 607 else if (!resultList.isEmpty()) 608 resultQType = new QTypeUnion(resultList); 609 resultList.clear(); 610 } 611 break; 612 case Axis.ANCESTOR : 614 case Axis.ANCESTOR_OR_SELF : 615 case Axis.FOLLOWING : 616 case Axis.FOLLOWING_SIBLING : 617 case Axis.NAMESPACE : 618 case Axis.PARENT : 619 case Axis.PRECEDING : 620 case Axis.PRECEDING_SIBLING : 621 break; 622 } 623 break; 624 case NodeKind.COMMENT : 625 resultQType = new QTypeComment(QType.OCC_0_N); 630 break; 631 case NodeKind.PI : 632 resultQType = new QTypeProcessingInstruction(); 637 break; 638 case NodeKind.DOCUMENT : 640 case NodeKind.NAMESPACE : 641 break; 642 } 643 } 644 648 public void visit(QTypeSequence arg) throws XQueryException { 649 resultQType = null; 650 ArrayList newList = new ArrayList(); 651 Iterator it = arg.getPrimeList().iterator(); 652 while (it.hasNext()) { 653 QType qtype = (QType) it.next(); 654 qtype.accept(this); 655 if (resultQType != null) { 656 newList.add(resultQType); 657 } 658 } 659 if (!newList.isEmpty()) { 660 if (newList.size() == 1) 661 resultQType = (QType) newList.get(0); 662 else 663 resultQType = new QTypeSequence(newList); 664 } 665 } 666 667 public void visit(QTypeUnion arg) throws XQueryException { 668 resultQType = null; 669 ArrayList newList = new ArrayList(); 670 Iterator it = arg.getPrimeList().iterator(); 671 while (it.hasNext()) { 672 QType qtype = (QType) it.next(); 673 qtype.accept(this); 674 if (resultQType != null && !newList.contains(resultQType)) { 675 newList.add(resultQType); 676 } 677 } 678 if (!newList.isEmpty()) { 679 if (newList.size() == 1) 680 resultQType = (QType) newList.get(0); 681 else 682 resultQType = new QTypeUnion(newList); 683 } 684 } 685 695 private QType getQTypeFromDeclaration(Declaration decl) throws XQueryException { 697 if (decl == null) 698 throw new TypeException("Expression not found in metadata"); 699 QType retQType = null; 700 QName qname = new QName(decl.getNamespace(), null, decl.getName(), null, null); 701 if (decl instanceof AttributeDeclaration) 702 retQType = new QTypeAttribute(qname, (AttributeDeclaration)decl, (SimpleType) decl.getType()); 703 if (decl instanceof ElementDeclaration) { 704 boolean multi = false; 705 ElementDeclaration eltDecl = (ElementDeclaration) decl; 706 SchemaScope scopeType = eltDecl.getScope(); 707 if (scopeType != null && scopeType instanceof ComplexType) { 708 int size[] = { 0, 0 }; 709 size = ((ComplexType) scopeType).getDeclarationOccurrence(eltDecl.getNamespace(), eltDecl.getName()); 710 if (size != null && size[1] > 1) 711 multi = true; 712 } 713 retQType = new QTypeElement(qname, decl.getType(), multi ? QType.OCC_0_N : QType.OCC_1_1); 714 } 715 return retQType; 716 } 717 718 private boolean compareQNames(String nameSpace1, String localName1, String nameSpace2, String localName2) { 719 boolean sameNS = false; 722 if (!sameNS && (nameSpace1 == null || nameSpace1.length() == 0) && (nameSpace2 == null || nameSpace2.length() == 0)) 723 sameNS = true; 724 if (!sameNS && nameSpace1 != null && (nameSpace1.equals("*") || nameSpace1.equals(nameSpace2))) 725 sameNS = true; 726 if (!sameNS && nameSpace2 != null && nameSpace2.equals("*")) 727 sameNS = true; 728 if (sameNS && localName1 != null && localName1 != null && (localName1.equals(localName2) || localName1.equals("*") || localName2.equals("*"))) 729 return true; 730 return false; 731 } 732 } 733 | Popular Tags |