1 23 24 package org.xquark.xquery.typing; 25 26 import java.util.*; 27 28 import org.xml.sax.SAXException ; 29 import org.xquark.schema.*; 30 import org.xquark.schema.datatypes.PrimitiveType; 31 import org.xquark.xpath.*; 32 import org.xquark.xquery.ModuleLocator; 33 import org.xquark.xquery.ModuleManager; 34 import org.xquark.xquery.metadata.StaticContext; 35 import org.xquark.xquery.parser.*; 36 import org.xquark.xquery.parser.primitivefunctions.fnfunctions.*; 37 import org.xquark.xquery.parser.primitivefunctions.xsfunctions.*; 38 import org.xquark.xquery.parser.util.Constants; 39 40 public class TypeVisitor extends DefaultParserVisitor { 41 private static final String RCSRevision = "$Revision: 1.12 $"; 42 private static final String RCSName = "$Name: $"; 43 44 private static final String STAR = "*"; 45 private static final String XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; 46 47 public static final String SC_STRING = "string"; 48 public static final String SC_BOOLEAN = "boolean"; 49 public static final String SC_DOUBLE = "double"; 50 public static final String SC_DECIMAL = "decimal"; 51 public static final String SC_INTEGER = "integer"; 52 public static final String SC_FLOAT = "float"; 53 public static final String SC_DATE = "date"; 54 public static final String SC_TIME = "time"; 55 public static final String SC_DATETIME = "dateTime"; 56 public static final String SC_ANYTYPE = "anyType"; 57 public static final String SC_QNAME = "QName"; 59 private static final String TEMP_NAME = "TEMP_NAME"; 60 61 private StaticContext context = null; 62 63 private ArrayList contextXNodes = null; 65 private QType contextQType = null; 66 private byte contextType = QTypeDocument.ANY_ORIGIN; 67 private LocatedExpression contextLocated = null; 68 private int contextLocatedStepIndex = -1; 69 70 private boolean inPredicate = false; 72 private boolean noForce = true; 73 74 private SchemaManager typingschemamanager = null; 75 private Schema typingschema = null; 76 boolean qaOnly = false; 78 79 81 public TypeVisitor(StaticContext context, boolean qaOnly) throws TypeException { 82 this.context = context; 83 this.qaOnly = qaOnly; 84 if (typingschemamanager == null) { 85 this.typingschemamanager = new SchemaManager(); 86 this.typingschema = new Schema("http://www.xquark.org/EXECUTIONPLAN", null, typingschemamanager); 87 try { 88 typingschemamanager.putSchema(typingschema); 89 } catch (SAXException saxe) { 90 throw new TypeException("Could not add schema to manager"); 91 } 92 } 93 } 94 95 public TypeVisitor(StaticContext context) throws TypeException { 96 this.context = context; 97 if (typingschemamanager == null) { 98 this.typingschemamanager = new SchemaManager(); 99 this.typingschema = new Schema("http://www.xquark.org/EXECUTIONPLAN", null, typingschemamanager); 100 try { 101 typingschemamanager.putSchema(typingschema); 102 } catch (SAXException saxe) { 103 throw new TypeException("Could not add schema to manager"); 104 } 105 } 106 } 107 108 public StaticContext getStaticContext() { 109 return context; 110 } 111 112 public SchemaManager getSchemaManager() { 113 return context.getSchemaManager(); 114 } 115 116 public SchemaLocator getSchemaLocator() { 117 return context.getSchemaManager(); 118 } 119 120 public ModuleManager getModuleManager() { 121 return context.getModuleManager(); 122 } 123 124 public ModuleLocator getModuleLocator() { 125 return context.getModuleManager(); 126 } 127 128 public SchemaManager getTypingSchemaManager() { 129 return typingschemamanager; 130 } 131 132 public void setNoForce(boolean noForce) { 133 this.noForce = noForce; 134 } 135 136 138 private void setTypingContext(ArrayList xnodes, QType qtype, LocatedExpression contextLocated, int contextLocatedStepIndex) throws XQueryException { 139 this.contextXNodes = xnodes; 140 this.contextQType = qtype; 141 this.contextLocated = contextLocated; 142 this.contextLocatedStepIndex = contextLocatedStepIndex; 143 } 144 145 147 178 public void visit(AttributeValuePair arg) throws XQueryException { 179 if (noForce && arg.getQType() != null) 181 return; 182 XQueryExpression attributeName = arg.getAttributeName(); XQueryExpression attributeValue = arg.getAttributeValue(); if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 186 if (attributeValue.getQType() == null) 187 return; 188 } 189 if ( 190 attributeValue.getQType() == null) 191 attributeValue.accept(this); 192 if (attributeValue.getQType() == null) 194 throw new TypeException("Expression " + attributeValue + " could not be typed."); 196 QType nameQType = attributeName.getQType(); 197 if (nameQType != null && (!nameQType.isQName() || nameQType.isMultiple())) { 198 nameQType = nameQType.applyDATAFunction(); 199 if (nameQType == null || !nameQType.isQName() || nameQType.isMultiple()) 200 throw new TypeException("Expression '" + attributeName + "', of attribute value pair has incorrect type."); 201 } 202 QType valueQType = attributeValue.getQType(); 203 if (valueQType != null && !valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString()) { 204 valueQType = valueQType.applyDATAFunction(); 205 if (valueQType == null || (!valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString())) 206 throw new TypeException("Expression '" + attributeValue + "', of attribute value pair has incorrect type."); 207 } 208 QType attQType = attributeValue.getQType(); 209 if (arg.getAttributeName() instanceof QName) 210 arg.setQType(new QTypeAttribute((QName)arg.getAttributeName(), attQType.getSimpleType())); 211 else if (arg.isXmlns()) 212 arg.setQType(new QTypeAttribute(new QName(null, null, "xmlns", arg.getParentModule(), null), attQType.getSimpleType())); 213 else if (arg.getAttributeName() instanceof ValueString) 214 arg.setQType(new QTypeAttribute(new QName(null, null, ((ValueString)arg.getAttributeName()).getValue(), arg.getParentModule(), null), attQType.getSimpleType())); 215 else 216 arg.setQType(new QTypeAttribute(new QName("*", "*", "*", arg.getParentModule(), null), attQType.getSimpleType())); 217 } 218 219 public void visit(BinOpANDExpression arg) throws XQueryException { 220 if (noForce && arg.getQType() != null) 222 return; 223 XQueryExpression expr1 = arg.getExpression1(); 224 XQueryExpression expr2 = arg.getExpression2(); 225 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 227 if (expr1.getQType() == null) 228 return; 229 if (expr2.getQType() == null) 230 return; 231 } 232 if ( 233 expr1.getQType() == null) 234 expr1.accept(this); 235 if ( 236 expr2.getQType() == null) 237 expr2.accept(this); 238 if (expr1.getQType() == null) 240 throw new TypeException("Expression " + expr1 + " could not be typed."); if (expr2.getQType() == null) 242 throw new TypeException("Expression " + expr2 + " could not be typed."); arg.setQType(new QTypeAtom(context.getSchemaManager().getBooleanType())); 245 } 246 247 public void visit(BinOpORExpression arg) throws XQueryException { 248 XQueryExpression expr1 = arg.getExpression1(); 249 XQueryExpression expr2 = arg.getExpression2(); 250 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 252 if (expr1.getQType() == null) 253 return; 254 if (expr2.getQType() == null) 255 return; 256 } 257 if ( 258 expr1.getQType() == null) 259 expr1.accept(this); 260 if ( 261 expr2.getQType() == null) 262 expr2.accept(this); 263 if (expr1.getQType() == null) 265 throw new TypeException("Expression " + expr1 + " could not be typed."); if (expr2.getQType() == null) 267 throw new TypeException("Expression " + expr2 + " could not be typed."); arg.setQType(new QTypeAtom(context.getSchemaManager().getBooleanType())); 270 } 271 272 public void visit(CastTreatExpression arg) throws XQueryException { 273 if (noForce && arg.getQType() != null) 275 return; 276 XQueryExpression expr = arg.getExpression(); 277 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 279 if (expr.getQType() == null) 280 return; 281 if ( 282 expr.getQType() == null) 283 expr.accept(this); 284 if (expr.getQType() == null) 286 throw new TypeException("Expression " + expr + " could not be typed."); QType qtype = arg.getSequenceType().getQType(); 289 arg.setQType(qtype); 290 } 291 292 public void visit(CData arg) throws XQueryException { 293 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 294 } 295 296 315 316 public void visit(ComputedNamespace arg) throws XQueryException { 317 if (noForce && arg.getQType() != null) 318 return; 319 XQueryExpression expr = arg.getExpression(); 320 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 322 if (expr.getQType() == null) 323 return; 324 if ( 325 expr.getQType() == null) 326 expr.accept(this); 327 if (expr.getQType() == null) 329 throw new TypeException("Computed namespace " + arg + " argument could not be typed."); QType valueQType = expr.getQType(); 331 if (!valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString()) { 332 valueQType = valueQType.applyDATAFunction(); 333 if (valueQType == null || (!valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString())) 334 throw new TypeException("Computed namespace " + arg + " argument has incorrect type."); 335 } 336 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 338 } 339 340 353 354 public void visit(ComputedText arg) throws XQueryException { 355 if (noForce && arg.getQType() != null) 356 return; 357 XQueryExpression expr = arg.getExpression(); 358 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 360 if (expr.getQType() == null) 361 return; 362 if ( 363 expr.getQType() == null) 364 expr.accept(this); 365 if (expr.getQType() == null) 367 throw new TypeException("Computed text " + arg + " argument could not be typed."); QType valueQType = expr.getQType(); 369 if (!valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString()) { 370 valueQType = valueQType.applyDATAFunction(); 371 if (valueQType == null || (!valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString())) 372 throw new TypeException("Computed text " + arg + " argument has incorrect type."); 373 } 374 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 376 } 377 378 380 405 406 public void visit(Document arg) throws XQueryException { 407 if (noForce && arg.getQType() != null) 409 return; 410 XQueryExpression expr = arg.getExpression(); 411 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 413 if (expr.getQType() == null) 414 return; 415 if ( 416 expr.getQType() == null) 417 expr.accept(this); 418 if (expr.getQType() == null) 419 throw new TypeException("Computed document '" + arg + "', argument could not be typed"); else { 421 if (!expr.getQType().isElement()) 422 throw new TypeException("Computed document '" + arg + "', argument should be an element"); } 424 arg.setQType(new QTypeDocument(expr.getQType(), QTypeDocument.DOCUMENT_ORIGIN)); 426 } 427 428 450 public void visit(Element arg) throws XQueryException { 451 if (noForce && arg.getQType() != null) 452 return; 453 ArrayList attributes = arg.getAttributes(); 454 ArrayList expressions = arg.getSubExpressions(); 455 XQueryExpression startTag = arg.getStartTag(); 456 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 458 if (attributes != null) 459 for (int i = 0; i < attributes.size(); i++) 460 if (((AttributeValuePair) attributes.get(i)).getQType() == null) 461 return; 462 if (expressions != null) 463 for (int j = 0; j < expressions.size(); j++) 464 if (((XQueryExpression) expressions.get(j)).getQType() == null) 465 return; 466 } 467 if (attributes != null) 468 for (int i = 0; i < attributes.size(); i++) 469 if ( 470 ((AttributeValuePair) attributes.get(i)).getQType() == null) { 471 ((AttributeValuePair) attributes.get(i)).accept(this); 472 if (((AttributeValuePair) attributes.get(i)).getQType() == null) 473 throw new TypeException("Expression " + (AttributeValuePair) attributes.get(i) + " could not be typed."); } 475 if (expressions != null) 476 for (int j = 0; j < expressions.size(); j++) { 477 XQueryExpression exprj = (XQueryExpression) expressions.get(j); 478 if ( 479 exprj.getQType() == null) { 480 exprj.accept(this); 481 if (exprj.getQType() == null) 482 throw new TypeException("Expression " + exprj + " could not be typed."); } 484 if (exprj.getQType().isBoolean()) { 485 if (exprj instanceof XQueryExpressionSequence) 486 exprj = (XQueryExpression) ((XQueryExpressionSequence) exprj).getSubExpressions().get(0); 487 if (!(exprj instanceof LocatedExpression) && !(exprj instanceof Variable)) 488 throw new TypeException("Incorrect boolean typed expression in element " + exprj); } 490 } 491 QType tagQType = startTag.getQType(); 493 if (tagQType != null && (!tagQType.isQName() || tagQType.isMultiple())) { 494 tagQType = tagQType.applyDATAFunction(); 495 if (tagQType == null || !tagQType.isQName() || tagQType.isMultiple()) 496 throw new TypeException("Expression '" + startTag + "', of element constructor has incorrect type."); 497 } 498 Set allElements = new HashSet(); 500 if (arg.getAttributes() != null) 501 allElements.addAll(arg.getAttributes()); 502 if (arg.getSubExpressions() != null) 503 allElements.addAll(arg.getSubExpressions()); 504 arg.setQType(buildQTypeElementFromSubElements(arg.getStartTag(), allElements)); 505 } 506 507 public void visit(ExternalVariable arg) throws XQueryException { 508 Variable var = (Variable) arg.getObjectValue(); 509 var.accept(this); 510 arg.setQType(var.getQType()); 511 } 512 513 public void visit(FLWRExpression arg) throws XQueryException { 514 if (noForce && arg.getQType() != null) 516 return; 517 ArrayList variables = arg.getVariables(); 518 XQueryExpression whereClause = arg.getWhereClause(); 519 XQueryExpression returnClause = arg.getReturnClause(); 520 boolean multiple = false; 522 for (int i = 0; i < variables.size(); i++) { 523 Variable vari = (Variable) variables.get(i); 524 if ( 525 vari.getQType() == null) 526 vari.accept(this); 527 if (!multiple) 528 if (vari.getBindingType() == Constants.FOR_BINDINGTYPE && vari.getExpression().getQType().isMultiple()) 529 multiple = true; 530 531 } 532 if (whereClause != null && ( 533 whereClause.getQType() == null)) 534 whereClause.accept(this); 535 if ( 536 returnClause.getQType() == null) 537 returnClause.accept(this); 538 if (returnClause.getQType() == null) 540 throw new TypeException("Incorrect 'return' clause : [ " + returnClause + " ], it could not be typed."); 541 if (whereClause != null && whereClause.getQType() == null) 542 throw new TypeException("Incorrect 'where' clause : [ " + whereClause + " ], it could not be typed."); 543 if (arg.getOrderBy() != null) { 545 for (int i = 0; i < arg.getOrderBy().size(); i++) { 546 XQueryExpression sortiexpr = (XQueryExpression) arg.getOrderBy().get(i); 547 if (sortiexpr.getOrder(0) != Constants.PLACE_ORDER) { 548 QType qtypei = sortiexpr.getQType(); 549 if (qtypei == null || !qtypei.isAtomic() || qtypei.isMultiple()) 550 throw new TypeException("Invalid order by clause : " + sortiexpr); 551 } 552 } 553 } 554 arg.setQType((QType) arg.getReturnClause().getQType().changeOccurence(multiple ? QType.OCC_0_N : QType.OCC_1_1)); 556 } 557 558 560 public void visit(FunctionDeclaration arg) throws XQueryException { 561 if (noForce && arg.getQType() != null) 563 return; 564 SequenceType returnType = arg.getReturnType(); 566 QType qtype = null; 569 if (returnType == null) { 571 if (arg.getExpressions() != null) { 572 ArrayList types = new ArrayList(arg.getExpressions().size()); 573 for (int i = 0; i < arg.getExpressions().size(); i++) { 574 XQueryExpression expri = (XQueryExpression) arg.getExpressions().get(i); 575 if (expri.getQType() != null) 576 types.add(expri.getQType()); 577 else 578 types = null; 579 } 580 if (types != null) { 581 if (types.size() == 1) 582 qtype = (QType) types.get(0); 583 else 584 qtype = new QTypeSequence(types); 585 } 586 } 587 if (qtype == null) { 588 SimpleType type = context.getSchemaManager().getAnySimpleType(); 589 ArrayList list = new ArrayList(3); 591 list.add(new QTypeAtom(type)); 592 list.add(new QTypeAttribute(new QName("*", "*", "*", arg.getParentModule(), null), type)); 593 list.add(new QTypeElement(new QName("*", "*", "*", arg.getParentModule(), null), getType(SC_ANYTYPE))); 594 qtype = new QTypeUnion(list, QType.OCC_0_N); 595 } 596 } else { 597 qtype = returnType.getQType(); 598 } 599 arg.setQType(qtype); 600 } 601 602 604 public void visit(InternalFunctionCall arg) throws XQueryException { 605 SimpleType type = context.getSchemaManager().getAnySimpleType(); 606 ArrayList list = new ArrayList(3); 607 list.add(new QTypeAtom(type)); 608 list.add(new QTypeAttribute(new QName("*", "*", "*", arg.getParentModule(), null), type)); 609 list.add(new QTypeElement(new QName("*", "*", "*", arg.getParentModule(), null), getType(SC_ANYTYPE))); 610 QType qtype = new QTypeUnion(list, QType.OCC_0_N); 611 arg.setQType(qtype); 612 } 613 614 public void visit(ITEExpression arg) throws XQueryException { 615 if (noForce && arg.getQType() != null) 616 return; 617 XQueryExpression ifExpression = arg.getThenExpression(); 618 XQueryExpression thenExpression = arg.getThenExpression(); 619 XQueryExpression elseExpression = arg.getElseExpression(); 620 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 622 if (ifExpression.getQType() == null) 623 return; 624 if (thenExpression.getQType() == null && !(thenExpression instanceof XQueryVoid)) 625 return; 626 if (elseExpression.getQType() == null && !(elseExpression instanceof XQueryVoid)) 627 return; 628 } 629 if ( 630 ifExpression.getQType() == null) 631 ifExpression.accept(this); 632 if (( 633 thenExpression.getQType() == null) && !(thenExpression instanceof XQueryVoid)) 634 thenExpression.accept(this); 635 if (( 636 elseExpression.getQType() == null) && !(elseExpression instanceof XQueryVoid)) 637 elseExpression.accept(this); 638 if (ifExpression.getQType() == null) 640 throw new TypeException("Expression " + ifExpression + " could not be typed."); if (thenExpression.getQType() == null && !(thenExpression instanceof XQueryVoid)) 642 throw new TypeException("Expression " + thenExpression + " could not be typed."); if (elseExpression.getQType() == null && !(elseExpression instanceof XQueryVoid)) 644 throw new TypeException("Expression " + elseExpression + " could not be typed."); ArrayList tmpList = new ArrayList(2); 647 tmpList.add(thenExpression.getQType()); 648 tmpList.add(elseExpression.getQType()); 649 arg.setQType(makeUnion(tmpList)); 650 } 651 652 657 676 public void visit(ItemType arg) throws XQueryException { 677 XQueryExpression expr = arg.getExpression(); 678 QType qtype = null; 679 if (expr == null) { 680 ArrayList list = new ArrayList(7); 681 list.add(new QTypeAtom(context.getSchemaManager().getAnySimpleType())); 682 list.add(new QTypeDocument(null, QTypeDocument.ANY_ORIGIN)); 683 list.add(new QTypeProcessingInstruction()); 684 list.add(new QTypeComment()); 685 list.add(new QTypeText((SimpleType) getType(SC_STRING))); 686 list.add(new QTypeElement(new QName("*", null), getType(SC_ANYTYPE))); 687 list.add(new QTypeAttribute(new QName("*", null), context.getSchemaManager().getAnySimpleType())); 688 qtype = new QTypeUnion(list); 689 } else if (expr instanceof QName) { 690 QName qname = (QName) expr; 691 Type st = null; 692 if (qname.getPrefixName() != null && qname.getPrefixName().equals("xs") && qname.getLocalName().equals("anySimpleType")) { 693 st = context.getSchemaManager().getAnySimpleType(); 694 } else { 695 st = context.getSchemaManager().getType(((QName) expr).getNameSpace(), ((QName) expr).getLocalName()); 697 } 698 if (st != null && st instanceof SimpleType) 699 qtype = new QTypeAtom((SimpleType) st); 700 else 701 throw new TypeException("Expression " + expr + " is not a valid atomic type."); 702 } else if (expr instanceof NodeTest) { 703 NodeTest nodeType = (NodeTest) expr; 704 XQueryExpression ex = nodeType.getArg(); 705 int kind = nodeType.getKind(); 706 switch (kind) { 707 case NodeKind.DOCUMENT : 708 qtype = new QTypeDocument((ex == null) ? null : ex.getQType(), QTypeDocument.ANY_ORIGIN); 709 break; 710 case NodeKind.PI : 711 qtype = new QTypeProcessingInstruction(); 712 break; 713 case NodeKind.COMMENT : 714 qtype = new QTypeComment(); 715 break; 716 case NodeKind.TEXT : 717 qtype = new QTypeText((SimpleType) getType(SC_STRING)); 718 break; 719 case NodeKind.NODE : 720 ArrayList list = new ArrayList(6); 721 list.add(new QTypeDocument(null, QTypeDocument.ANY_ORIGIN)); 722 list.add(new QTypeProcessingInstruction()); 723 list.add(new QTypeComment()); 724 list.add(new QTypeText((SimpleType) getType(SC_STRING))); 725 list.add(new QTypeElement(new QName("*", null), getType(SC_ANYTYPE))); 726 list.add(new QTypeAttribute(new QName("*", null), context.getSchemaManager().getAnySimpleType())); 727 qtype = new QTypeUnion(list); 728 break; 729 } 730 } else if (expr instanceof ElementTest || expr instanceof AttributeTest) { 731 qtype = expr.getQType(); 732 } 733 arg.setQType(qtype); 734 } 735 736 public void visit(ElementTest arg) throws XQueryException { 737 SchemaContextPath scp = arg.getSchemaContextPath(); 738 if (scp != null) { 739 arg.setQType(getQTypeFromDeclaration(computeDeclFromPath(scp), QType.OCC_1_1)); 740 } else { 741 Type type = null; 742 QName typeQName = arg.getTypeQName(); 743 if (typeQName != null) { 744 type = context.getSchemaManager().getType(typeQName.getNameSpace(), typeQName.getLocalName()); 745 if (type == null) 746 throw new TypeException("Could not type ElementTest '" + arg + "' ."); 747 } 748 if (arg.getDeclQName() == null || arg.getDeclQName().equals("*")) { 749 if (type == null) 750 type = getType(SC_ANYTYPE); 751 arg.setQType(new QTypeElement(new QName("*", null), type)); 752 } else { 753 QName eltQName = arg.getDeclQName(); 754 ElementDeclaration eltDecl = context.getSchemaManager().getElementDeclaration(eltQName.getNameSpace(), eltQName.getLocalName()); 755 if (eltDecl == null) 756 throw new TypeException("Could not type ElementTest '" + arg + "' ."); 757 if (type == null) { 759 type = eltDecl.getType(); 760 } else if (eltDecl.getType() != type && !eltDecl.getType().isDerivedFrom(type)) 761 throw new TypeException("Could not type ElementTest '" + arg + "' ."); 762 arg.setQType(new QTypeElement(eltQName, eltDecl, type)); 763 } 764 } 765 } 766 767 public void visit(AttributeTest arg) throws XQueryException { 768 SchemaContextPath scp = arg.getSchemaContextPath(); 769 if (scp != null) { 770 arg.setQType(getQTypeFromDeclaration(computeDeclFromPath(scp), QType.OCC_1_1)); 771 } else { 772 SimpleType stype = null; 773 QName typeQName = arg.getTypeQName(); 774 if (typeQName != null) { 775 Type type = context.getSchemaManager().getType(typeQName.getNameSpace(), typeQName.getLocalName()); 776 if (type == null || !(type instanceof SimpleType)) 777 throw new TypeException("Could not type AttributeTest '" + arg + "' ."); 778 stype = (SimpleType) type; 779 } 780 if (arg.getDeclQName() == null || arg.getDeclQName().equals("*")) { 781 if (stype == null) 782 stype = context.getSchemaManager().getAnySimpleType(); 783 arg.setQType(new QTypeAttribute(new QName("*", null), stype)); 784 } else { 785 QName qname = arg.getDeclQName(); 786 AttributeDeclaration attDecl = context.getSchemaManager().getAttributeDeclaration(qname.getNameSpace(), qname.getLocalName()); 787 if (attDecl == null) 788 throw new TypeException("Could not type AttributeTest '" + arg + "' ."); 789 if (stype == null) { 791 stype = attDecl.getType().getValueType(); 792 } else if (attDecl.getType() != stype && !attDecl.getType().isDerivedFrom(stype)) 793 throw new TypeException("Could not type AttributeTest '" + arg + "' ."); 794 arg.setQType(new QTypeAttribute(qname, attDecl, stype)); 795 } 796 } 797 } 798 799 public void visit(LibraryFunctionCall arg) throws XQueryException { 800 if (noForce && arg.getQType() != null) 802 return; 803 FunctionDeclaration funcdef = arg.getFunctionDefinition(); if (funcdef.getQType() == null) 806 funcdef.accept(this); 807 arg.setQType(funcdef.getQType()); 809 } 810 811 public void visit(ListOpAFTERExpression arg) throws XQueryException { 812 if (noForce && arg.getQType() != null) 814 return; 815 818 XQueryExpression expr1 = arg.getExpression1(); 819 XQueryExpression expr2 = arg.getExpression2(); 820 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 822 if (expr1.getQType() == null) 823 return; 824 if (expr2.getQType() == null) 825 return; 826 } 827 if ( 828 expr1.getQType() == null) 829 expr1.accept(this); 830 if ( 831 expr2.getQType() == null) 832 expr2.accept(this); 833 if (expr1.getQType() == null) 835 throw new TypeException("Expression " + expr1 + " could not be typed."); if (expr2.getQType() == null) 837 throw new TypeException("Expression " + expr2 + " could not be typed."); if (!expr1.getQType().isNode() || !expr2.getQType().isNode()) 839 throw new TypeException("Expression '" + arg + "', at least one of the operands must be a node or collection of node."); 840 arg.setQType(expr1.getQType()); 842 } 843 844 861 899 900 public void visit(ListOpArithExpression arg) throws XQueryException { 901 if (noForce && arg.getQType() != null) 903 return; 904 XQueryExpression expr1 = arg.getExpression1(); 905 XQueryExpression expr2 = arg.getExpression2(); 906 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 908 if (expr1.getQType() == null) 909 return; 910 if (expr2.getQType() == null) 911 return; 912 } 913 if ( 914 expr1.getQType() == null) 915 expr1.accept(this); 916 if ( 917 expr2.getQType() == null) 918 expr2.accept(this); 919 QType qtype1 = expr1.getQType(); 921 QType qtype2 = expr2.getQType(); 922 if (qtype1 == null) 923 throw new TypeException("Expression " + expr1 + " could not be typed."); if (qtype2 == null) 925 throw new TypeException("Expression " + expr2 + " could not be typed."); if (!qtype1.isAtomic()) 927 qtype1 = qtype1.applyDATAFunction(); 928 if (!qtype2.isAtomic()) 929 qtype2 = qtype2.applyDATAFunction(); 930 if (qtype1 == null || (!qtype1.isAtomic() )) 931 throw new TypeException("Expression '" + arg + "', first operand is not an atomic value."); 932 if (qtype2 == null || (!qtype2.isAtomic() )) 933 throw new TypeException("Expression '" + arg + "', second operand is not an atomic value."); 934 if (!qtype1.isNumeric()) 935 throw new TypeException("Expression '" + arg + "', first operand is not numeric."); 936 if (!qtype2.isNumeric()) 937 throw new TypeException("Expression '" + arg + "', second operand is not numeric."); 938 int primType1 = ((SimpleType) qtype1.getType()).getPrimitive().getType(); 940 int primType2 = ((SimpleType) qtype2.getType()).getPrimitive().getType(); 941 if (primType1 == PrimitiveType.DOUBLE || primType2 == PrimitiveType.DOUBLE) 942 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE), (expr1.getQType().isMultiple() || expr2.getQType().isMultiple()) ? QType.OCC_0_N : QType.OCC_1_1)); 943 else if (primType1 == PrimitiveType.FLOAT || primType2 == PrimitiveType.FLOAT) 944 arg.setQType(new QTypeAtom((SimpleType) getType(SC_FLOAT), (expr1.getQType().isMultiple() || expr2.getQType().isMultiple()) ? QType.OCC_0_N : QType.OCC_1_1)); 945 else if (primType1 == PrimitiveType.DECIMAL || primType2 == PrimitiveType.DECIMAL) 946 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DECIMAL), (expr1.getQType().isMultiple() || expr2.getQType().isMultiple()) ? QType.OCC_0_N : QType.OCC_1_1)); 947 else 948 arg.setQType(new QTypeAtom((SimpleType) getType(SC_INTEGER), (expr1.getQType().isMultiple() || expr2.getQType().isMultiple()) ? QType.OCC_0_N : QType.OCC_1_1)); 949 } 950 951 public void visit(ListOpBEFOREExpression arg) throws XQueryException { 952 if (noForce && arg.getQType() != null) 954 return; 955 XQueryExpression expr1 = arg.getExpression1(); 956 XQueryExpression expr2 = arg.getExpression2(); 957 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 959 if (expr1.getQType() == null) 960 return; 961 if (expr2.getQType() == null) 962 return; 963 } 964 if ( 965 expr1.getQType() == null) 966 expr1.accept(this); 967 if ( 968 expr2.getQType() == null) 969 expr2.accept(this); 970 if (expr1.getQType() == null) 972 throw new TypeException("Expression " + expr1 + " could not be typed."); if (expr2.getQType() == null) 974 throw new TypeException("Expression " + expr2 + " could not be typed."); if (!expr1.getQType().isNode() || !expr2.getQType().isNode()) 976 throw new TypeException("Expression '" + arg + "', at least one of the operands must be a node or collection of node."); 977 arg.setQType(expr1.getQType()); 979 } 980 981 public void visit(ListOpCompExpression arg) throws XQueryException { 982 991 if (noForce && arg.getQType() != null) 992 return; 993 995 XQueryExpression expr1 = arg.getExpression1(); 996 XQueryExpression expr2 = arg.getExpression2(); 997 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 999 if (expr1.getQType() == null) 1000 return; 1001 if (expr2.getQType() == null) 1002 return; 1003 } 1004 if ( 1005 expr1.getQType() == null) 1006 expr1.accept(this); 1007 if ( 1008 expr2.getQType() == null) 1009 expr2.accept(this); 1010 QType qtype1 = expr1.getQType(); 1012 QType qtype2 = expr2.getQType(); 1013 if (qtype1 == null) 1014 throw new TypeException("Expression " + expr1 + " could not be typed."); if (qtype2 == null) 1016 throw new TypeException("Expression " + expr2 + " could not be typed."); if (qtype1 != null && qtype2 != null) { 1018 if (!qtype1.isAtom()) 1019 qtype1 = qtype1.applyDATAFunction(); 1020 if (!qtype2.isAtom()) 1021 qtype2 = qtype2.applyDATAFunction(); 1022 if (arg.getOperator() >= Constants.EQ_VALUECOMP && arg.getOperator() <= Constants.NE_VALUECOMP) { 1024 if (qtype1.getOccurence() != QType.OCC_0_1 && qtype1.getOccurence() != QType.OCC_1_1) 1026 throw new TypeException("Expression " + expr1 + " has wrong occurence."); 1027 if (qtype2.getOccurence() != QType.OCC_0_1 && qtype2.getOccurence() != QType.OCC_1_1) 1028 throw new TypeException("Expression " + expr2 + " has wrong occurence."); 1029 } 1030 if (qtype1 == null || !(qtype1.canBeComparedTo(qtype2))) 1032 throw new TypeException("Could not compare types of expression --> " + arg); 1033 } 1034 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 1036 } 1037 1038 public void visit(ListOpEXCEPTExpression arg) throws XQueryException { 1039 if (noForce && arg.getQType() != null) 1041 return; 1042 XQueryExpression expr1 = arg.getExpression1(); 1043 XQueryExpression expr2 = arg.getExpression2(); 1044 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1046 if (expr1.getQType() == null) 1047 return; 1048 if (expr2.getQType() == null) 1049 return; 1050 } 1051 if ( 1052 expr1.getQType() == null) 1053 expr1.accept(this); 1054 if ( 1055 expr2.getQType() == null) 1056 expr2.accept(this); 1057 if (expr1.getQType() == null) 1059 throw new TypeException("Expression " + expr1 + " could not be typed."); if (expr2.getQType() == null) 1061 throw new TypeException("Expression " + expr2 + " could not be typed."); arg.setQType(expr1.getQType()); 1064 } 1065 1066 public void visit(ListOpINTERSECTExpression arg) throws XQueryException { 1067 if (noForce && arg.getQType() != null) 1069 return; 1070 XQueryExpression expr1 = arg.getExpression1(); 1071 XQueryExpression expr2 = arg.getExpression2(); 1072 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1074 if (expr1.getQType() == null) 1075 return; 1076 if (expr2.getQType() == null) 1077 return; 1078 } 1079 if ( 1080 expr1.getQType() == null) 1081 expr1.accept(this); 1082 if ( 1083 expr2.getQType() == null) 1084 expr2.accept(this); 1085 if (expr1.getQType() == null) 1087 throw new TypeException("Expression " + expr1 + " could not be typed."); if (expr2.getQType() == null) 1089 throw new TypeException("Expression " + expr2 + " could not be typed."); arg.setQType(expr1.getQType()); 1092 } 1093 1094 public void visit(ListOpUNIONExpression arg) throws XQueryException { 1095 if (noForce && arg.getQType() != null) 1097 return; 1098 XQueryExpression expr1 = arg.getExpression1(); 1099 XQueryExpression expr2 = arg.getExpression2(); 1100 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1102 if (expr1.getQType() == null) 1103 return; 1104 if (expr2.getQType() == null) 1105 return; 1106 } 1107 if ( 1108 expr1.getQType() == null) 1109 expr1.accept(this); 1110 if ( 1111 expr2.getQType() == null) 1112 expr2.accept(this); 1113 if (expr1.getQType() == null) 1115 throw new TypeException("Expression " + expr1 + " could not be typed."); if (expr2.getQType() == null) 1117 throw new TypeException("Expression " + expr2 + " could not be typed."); ArrayList list = new ArrayList(); 1120 list.add(expr1.getQType()); 1121 list.add(expr2.getQType()); 1122 arg.setQType(new QTypeUnion(list)); 1123 } 1124 1125 public void visit(LocatedExpression arg) throws XQueryException { 1126 ArrayList steps = arg.getSteps(); 1127 if (noForce) { 1129 boolean alltyped = true; 1130 for (int i = 0; i < steps.size(); i++) { 1131 Step stepi = (Step) steps.get(i); 1132 if (stepi.getQType() == null || stepi.getAxis() == Axis.DESCENDANT || stepi.getAxis() == Axis.DESCENDANT_OR_SELF) { 1133 alltyped = false; 1134 break; 1135 } 1136 } 1137 if (alltyped) { 1139 arg.setQType(arg.getStepNum(steps.size() - 1).getQType()); 1140 arg.setXTrees(arg.getStepNum(steps.size() - 1).getXTrees()); 1141 return; 1142 } 1143 } else { 1144 arg.setQType(null); 1145 arg.setXTrees(null); 1146 } 1147 1148 boolean simplePath = arg.isRelative(); 1150 1151 ArrayList tmpContextXNodes = null; 1153 QType tmpContextQType = null; 1154 LocatedExpression tmpContextLocated = null; 1155 int tmpContextLocatedStepIndex = -1; 1156 if (simplePath) { 1158 if (arg.getStepNum(0).getAxis() == Axis.NONE) 1159 arg.getStepNum(0).setAxis(Axis.CHILD); 1160 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1161 1167 return; 1168 } 1169 tmpContextXNodes = contextXNodes; 1170 tmpContextQType = contextQType; 1171 tmpContextLocated = contextLocated; 1172 tmpContextLocatedStepIndex = contextLocatedStepIndex; 1173 arg.setContext(true); 1174 } 1175 else { 1177 if (contextXNodes != null || contextQType != null) { 1178 tmpContextXNodes = contextXNodes; 1179 tmpContextQType = contextQType; 1180 tmpContextLocated = contextLocated; 1181 tmpContextLocatedStepIndex = contextLocatedStepIndex; 1182 contextXNodes = null; 1183 contextQType = null; 1184 tmpContextLocated = null; 1185 contextLocatedStepIndex = -1; 1186 } 1187 } 1188 1189 1191 byte occurence = QType.OCC_1_1; 1192 1193 boolean done = false; 1194 QType qtype = null; 1195 Step stepi = null; 1196 1197 for (int i = 0; i < steps.size(); i++) { 1198 qtype = null; 1200 done = false; 1201 stepi = (Step) steps.get(i); 1202 XQueryExpression stepiExpr = stepi.getExpression(); 1203 1204 if (i == 0 && contextType == QTypeDocument.ANY_ORIGIN) { 1206 if (stepiExpr.getQType() instanceof QTypeDocument && ((QTypeDocument) stepiExpr.getQType()).isFromDocument()) 1207 contextType = QTypeDocument.DOCUMENT_ORIGIN; 1208 else 1209 contextType = QTypeDocument.COLLECTION_ORIGIN; 1210 } 1211 1212 if (noForce) { 1214 if (i == 0 && stepi.getQType() != null) { 1215 contextXNodes = stepi.getXTrees(); 1216 contextQType = stepi.getQType(); 1217 qtype = stepi.getQType(); 1218 done = true; 1219 } 1220 } else { 1221 stepi.setQType(null); 1222 stepi.setXTrees(null); 1223 } 1224 1225 if (!done) { 1227 if (i == 0 && stepi.getAxis() == Axis.NONE) { 1228 qtype = stepiExpr.getQType(); 1229 if (noForce && qtype != null) { 1230 stepi.setXTrees(stepiExpr.getXTrees()); 1231 done = true; 1232 } 1233 } 1234 } 1235 1236 if (!done && stepiExpr instanceof ListOpUNIONExpression) { 1238 this.setTypingContext(contextXNodes, contextQType, arg, i - 1); 1239 stepiExpr.accept(this); 1240 qtype = stepiExpr.getQType(); 1241 if (qtype != null) { 1242 stepi.setXTrees(stepiExpr.getXTrees()); 1243 done = true; 1244 } 1245 } 1246 1247 boolean doNodes = true; 1249 boolean isTextNode = false; 1250 if (!done && stepiExpr instanceof NodeTest) { 1251 if (((NodeTest) stepiExpr).getKind() == NodeKind.TEXT) { 1252 isTextNode = true; 1253 doNodes = false; 1254 } else if (((NodeTest) stepiExpr).getKind() == NodeKind.NODE) 1255 doNodes = false; 1256 } 1257 1258 if (!done && doNodes && contextXNodes != null) { 1260 ArrayList xnodes = context.resolveXPath(contextXNodes, stepi); 1261 if (xnodes != null) { 1262 qtype = this.buildQTypeFromXNodes(xnodes, occurence); 1263 if (qtype != null) { 1264 stepi.setXTrees(xnodes); 1265 done = true; 1266 } 1267 } 1268 } 1269 if (!done && contextQType != null) { 1271 qtype = context.resolveQType(contextType, contextQType, stepi, inPredicate); 1272 if (qtype != null) { 1273 if (isTextNode) 1274 stepi.setXTrees(contextXNodes); 1275 else 1276 stepi.setXTrees(null); 1277 done = true; 1278 } 1279 1280 } 1281 1282 if (done) { 1284 occurence = qtype.getOccurence(); 1285 } else { 1286 if (stepi.getAxis() == Axis.PARENT) { 1288 if (arg.startsWithVariable() || (arg.getParentExpression() != null && !arg.getParentExpression().isEmpty() && arg.getParentExpression().get(0) instanceof ListOpUNIONExpression)) { 1289 XQueryExpression tmpExpr = arg; 1292 XQueryExpression firstExpr = arg.getStepNum(0).getExpression(); 1293 ArrayList stepList = new ArrayList(); 1294 int stepIndex = -1; 1295 try { 1296 while (true) { 1297 if (tmpExpr instanceof LocatedExpression) { 1298 LocatedExpression tmpLoc = (LocatedExpression) tmpExpr; 1299 1300 if (stepIndex == -1) 1301 stepIndex = tmpLoc.getSteps().size() - 1; 1302 for (int j = stepIndex; j >= 0; j--) { 1303 Step clonedStep = (Step) tmpLoc.getStepNum(j).clone(); 1304 clonedStep.setPredicates(null); 1305 stepList.add(0, clonedStep); 1306 } 1307 if (simplePath && (tmpLoc.getInPredicate() || (tmpLoc.getParentExpression() != null && !tmpLoc.getParentExpression().isEmpty() && tmpLoc.getParentExpression().get(0) instanceof ListOpUNIONExpression))) { 1308 tmpExpr = contextLocated; 1309 stepIndex = contextLocatedStepIndex; 1310 ((Step) stepList.get(0)).setHasSeparator(true); 1311 } else { 1312 stepIndex = -1; 1313 firstExpr = tmpLoc.getStepNum(0).getExpression(); 1314 if (firstExpr instanceof Variable) { 1315 tmpExpr = ((Variable) firstExpr).getExpression(); 1316 stepList.remove(0); 1317 } else { 1318 break; 1319 } 1320 } 1321 } else if (tmpExpr instanceof Variable) { 1322 tmpExpr = ((Variable) tmpExpr).getExpression(); 1323 } else if (tmpExpr instanceof FunctionCall) { 1324 stepList.add(0, tmpExpr); 1325 break; 1326 } 1327 } 1328 1329 } catch (CloneNotSupportedException cnse) { 1330 stepList.clear(); 1331 } 1332 1333 if (!stepList.isEmpty() && stepList.size() != steps.size()) { 1334 LocatedExpression loc = new LocatedExpression(stepList, false, arg.getParentModule(), true); 1335 if (loc.getQType() != null) 1336 qtype = loc.getQType(); 1337 } 1338 } else if (arg.getParentExpression() != null && !arg.getParentExpression().isEmpty() && arg.getParentExpression().get(0) instanceof ListOpUNIONExpression) { 1339 boolean prev = inPredicate; 1340 inPredicate = true; 1341 arg.accept(this); 1342 inPredicate = prev; 1343 } 1344 } 1345 } 1346 if (qtype == null) 1347 throw new TypeException("Could not find path : " + arg.toString(false,false,true)); 1348 1349 stepi.setQType(qtype); 1351 contextXNodes = stepi.getXTrees(); 1352 contextQType = stepi.getQType(); 1353 1354 ArrayList predicates = stepi.getPredicates(); 1356 if (predicates != null && !predicates.isEmpty()) { 1357 QType prevContextQType = null; 1358 if (contextQType != null && contextQType.isMultiple()) 1359 prevContextQType = contextQType.changeOccurence(QType.OCC_1_1); 1360 else 1361 prevContextQType = contextQType; 1362 this.setTypingContext(contextXNodes, prevContextQType, arg, i); 1363 for (int j = 0; j < predicates.size(); j++) { 1364 XQueryExpression predicate = (XQueryExpression) predicates.get(j); 1365 if ( 1366 predicate.getQType() == null) { 1367 boolean prev = inPredicate; 1368 inPredicate = true; 1369 predicate.accept(this); 1370 inPredicate = prev; 1371 } 1372 } 1373 if (prevContextQType != null) 1374 contextQType = prevContextQType; 1375 } 1376 } 1377 if (qtype != null) { 1383 arg.setQType(qtype); 1384 1387 } else { 1388 throw new TypeException("Could not find path : " + arg.toString(false,false,true)); 1389 } 1390 1391 contextType = QTypeDocument.ANY_ORIGIN; 1393 this.setTypingContext(tmpContextXNodes, tmpContextQType, tmpContextLocated, tmpContextLocatedStepIndex); 1395 } 1396 1397 public void visit(NodeTest arg) throws XQueryException { 1398 if (noForce && arg.getQType() != null) 1400 return; 1401 1402 if (contextQType == null) 1403 return; 1404 1405 QType qtype = Utils.getSubType(contextType, contextQType, new Step(true, Axis.CHILD, arg, null, null), context.getSchemaManager(), inPredicate); 1406 arg.setQType(qtype); 1407 } 1411 1412 1414 public void visit(QName arg) throws XQueryException { 1415 if (contextXNodes != null && contextQType != null && arg.getParentExpression() != null && arg.getParentExpression().get(0) instanceof SortedExpression) { 1416 QType qtype = null; 1417 if (contextQType != null) { 1420 qtype = Utils.getSubType(contextType, contextQType, new Step(false, Axis.CHILD, arg, null, null), context.getSchemaManager(), inPredicate); 1421 } 1422 if (qtype == null) 1423 throw new TypeException("Could not type expression : " + arg.toString(false,false,true)); 1424 arg.setQType(qtype); 1425 return; 1426 } 1427 QType qtype = null; 1428 if (contextQType != null) { 1429 qtype = Utils.getSubType(contextType, contextQType, new Step(false, Axis.CHILD, arg, null, null), context.getSchemaManager(), inPredicate); 1430 } 1431 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1432 arg.setQType(new QTypeAtom((SimpleType) getType(SC_QNAME))); 1433 return; 1434 } 1435 if (qtype == null) 1439 throw new TypeException("Could not type expression : " + arg.toString(false,false,true)); 1440 arg.setQType(qtype); 1441 } 1442 1443 public void visit(QuantifiedExpression arg) throws XQueryException { 1444 1449 if (noForce && arg.getQType() != null) 1451 return; 1452 1454 ArrayList variables = arg.getVariables(); 1455 XQueryExpression expr = arg.getExpression(); 1456 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1458 for (int i = 0; i < variables.size(); i++) 1459 if (((Variable) variables.get(i)).getExpression().getQType() == null) 1460 return; 1461 if (expr.getQType() == null) 1462 return; 1463 } 1464 for (int i = 0; i < variables.size(); i++) 1465 if ( 1466 ((Variable) variables.get(i)).getExpression().getQType() == null) { 1467 ((Variable) variables.get(i)).getExpression().accept(this); 1468 if (((Variable) variables.get(i)).getExpression().getQType() == null) 1469 throw new TypeException("Expression " + ((Variable) variables.get(i)).getExpression() + " could not be typed."); } 1471 if ( 1472 expr.getQType() == null) 1473 expr.accept(this); 1474 if (expr.getQType() == null) 1475 throw new TypeException("Expression " + expr + " could not be typed."); if (!expr.getQType().isBoolean()) 1478 throw new TypeException("SATISFIES clause must be a boolean."); 1479 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 1481 } 1482 1483 public void visit(RangeExpression arg) throws XQueryException { 1484 1489 XQueryExpression expr1 = arg.getExpression1(); 1490 XQueryExpression expr2 = arg.getExpression2(); 1491 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1493 if (expr1.getQType() == null) 1494 return; 1495 if (expr2.getQType() == null) 1496 return; 1497 } 1498 if ( 1499 expr1.getQType() == null) 1500 expr1.accept(this); 1501 if ( 1502 expr2.getQType() == null) 1503 expr2.accept(this); 1504 if (expr1.getQType() == null) 1506 throw new TypeException("Expression " + expr1 + " could not be typed."); if (expr2.getQType() == null) 1508 throw new TypeException("Expression " + expr2 + " could not be typed."); if (!expr1.getQType().isInteger()) 1510 throw new TypeException("Expression '" + arg + "', first expression is not an integer."); 1511 if (expr2 != null && !expr2.getQType().isInteger()) 1512 throw new TypeException("Expression '" + arg + "', second expression is not an integer."); 1513 } 1514 1515 1517 private Declaration computeDeclFromPath(SchemaContextPath arg) throws XQueryException { 1519 SchemaContextStep step = arg.getStep(0); 1520 QName expr = (QName) step.getExpression(); 1521 Declaration decl = null; 1522 Type scope = null; 1523 if (step.getAxis() == Constants.WITHTYPE) { 1524 scope = context.getSchemaManager().getType(expr.getNameSpace(), expr.getLocalName()); 1525 } else if (step.getAxis() == Constants.NOAXIS) { 1526 decl = context.getSchemaManager().getElementDeclaration(expr.getNameSpace(), expr.getLocalName()); 1527 if (decl == null) 1528 throw new TypeException("Could not type SchemaContextPath '" + arg + "' ."); 1529 scope = decl.getType(); 1530 } 1531 for (int i = 1; i < arg.getSteps().size(); i++) { 1532 if (scope == null) 1533 throw new TypeException("Could not type SchemaContextPath '" + arg + "' ."); 1534 step = arg.getStep(i); 1535 expr = (QName) step.getExpression(); 1536 if (step.getAxis() == Constants.WITHAXIS) 1537 decl = scope.getElementDeclaration(expr.getNameSpace(), expr.getLocalName()); 1538 else 1539 decl = scope.getAttributeDeclaration(expr.getNameSpace(), expr.getLocalName()); 1540 if (decl == null) 1541 throw new TypeException("Could not type SchemaContextPath '" + arg + "' ."); 1542 scope = decl.getType(); 1543 } 1544 if (decl == null) 1545 throw new TypeException("Could not type SchemaContextPath '" + arg + "' ."); 1546 return decl; 1547 } 1548 1549 1568 public void visit(SequenceType arg) throws XQueryException { 1569 QType qtype = null; 1570 if (arg.getItemType() != null) 1571 qtype = arg.getItemType().getQType(); 1572 else { 1573 qtype = new QTypeSequence(null); 1574 } 1575 switch (arg.getOccurrence()) { 1576 case Constants.OCCURRENCE_PLUS : 1577 qtype = qtype.changeOccurence(QType.OCC_1_N); 1578 break; 1579 case Constants.OCCURRENCE_QUESTION_MARK : 1580 qtype = qtype.changeOccurence(QType.OCC_0_1); 1581 break; 1582 case Constants.OCCURRENCE_STAR : 1583 qtype = qtype.changeOccurence(QType.OCC_0_N); 1584 break; 1585 } 1586 if (qtype == null) 1587 throw new TypeException("Expression " + arg + " could not be typed."); arg.setQType(qtype); 1589 } 1590 1591 public void visit(SortedExpression arg) throws XQueryException { 1592 1602 if (noForce && arg.getQType() != null) 1604 return; 1605 XQueryExpression expr = arg.getExpression(); 1606 ArrayList sortClauses = arg.getSortClauses(); 1607 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1609 if (expr.getQType() == null) 1610 return; 1611 } 1612 if ( 1613 expr.getQType() == null) 1614 expr.accept(this); 1615 if (expr.getQType() == null) 1618 throw new TypeException("Expression " + expr + " could not be typed."); 1620 arg.setQType(expr.getQType()); 1630 } 1631 1632 public void visit(Step arg) throws XQueryException { 1634 } 1635 1636 1638 public void visit(UnOpMinusExpression arg) throws XQueryException { 1639 1643 if (noForce && arg.getQType() != null) 1645 return; 1646 XQueryExpression expr = arg.getExpression(); 1647 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1649 if (expr.getQType() == null) 1650 return; 1651 } 1652 if ( 1653 expr.getQType() == null) 1654 expr.accept(this); 1655 if (expr.getQType() == null) 1657 throw new TypeException("Expression " + expr + " could not be typed."); if (expr.getQType() != null) { 1659 if (!expr.getQType().isAtomic() ) 1660 throw new TypeException("Expression '" + arg + "', operand is not an atomic value."); 1661 if (!expr.getQType().isNumeric()) 1662 throw new TypeException("Expression '" + arg + "', operand is not numeric."); 1663 } 1664 QType qtypedata = expr.getQType().applyDATAFunction(); 1666 if (qtypedata != null) 1667 arg.setQType(qtypedata); 1668 else 1669 arg.setQType(expr.getQType()); 1670 } 1671 1672 public void visit(ValidateExpression arg) throws XQueryException { 1673 if (noForce && arg.getQType() != null) 1674 return; 1675 XQueryExpression expr = arg.getExpression(); 1676 arg.setQType(expr.getQType()); 1677 } 1678 1679 1681 public void visit(ValueBoolean arg) throws XQueryException { 1682 1687 if (noForce && arg.getQType() != null) 1689 return; 1690 arg.setQType(new QTypeAtom(context.getSchemaManager().getBooleanType())); 1692 } 1693 1694 public void visit(ValueDecimal arg) throws XQueryException { 1695 1700 if (noForce && arg.getQType() != null) 1702 return; 1703 arg.setQType(new QTypeAtom(context.getSchemaManager().getDecimalType())); 1705 } 1706 1707 public void visit(ValueDouble arg) throws XQueryException { 1708 1713 if (noForce && arg.getQType() != null) 1715 return; 1716 arg.setQType(new QTypeAtom(context.getSchemaManager().getDoubleType())); 1718 } 1719 1720 public void visit(ValueFloat arg) throws XQueryException { 1721 1726 if (noForce && arg.getQType() != null) 1728 return; 1729 arg.setQType(new QTypeAtom(context.getSchemaManager().getFloatType())); 1731 } 1732 1733 public void visit(ValueInteger arg) throws XQueryException { 1734 1739 if (noForce && arg.getQType() != null) 1741 return; 1742 arg.setQType(new QTypeAtom(context.getSchemaManager().getIntegerType())); 1744 } 1745 1746 public void visit(ValueString arg) throws XQueryException { 1747 1752 if (noForce && arg.getQType() != null) 1754 return; 1755 arg.setQType(new QTypeAtom(context.getSchemaManager().getStringType())); 1757 } 1758 1759 public void visit(ValueText arg) throws XQueryException { 1760 1765 if (noForce && arg.getQType() != null) 1767 return; 1768 arg.setQType(new QTypeText((SimpleType) getType(SC_STRING))); 1770 } 1771 1772 public void visit(Variable arg) throws XQueryException { 1773 1778 if (noForce && arg.getQType() != null) 1779 return; 1780 XQueryExpression expression = arg.getExpression(); 1781 if (expression != null) { 1782 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1784 if (expression.getQType() == null) 1785 return; 1786 } 1787 if ( 1788 expression.getQType() == null) 1789 expression.accept(this); 1790 if (expression.getQType() == null) 1792 throw new TypeException("Expression " + expression + " could not be typed."); if (expression instanceof XQueryVoid) 1794 throw new TypeException("Variable " + arg + " could not be bound to existing path."); 1799 if (arg.getBindingType() == Constants.LET_BINDINGTYPE) 1801 arg.setQType(expression.getQType()); 1802 else if (arg.getBindingType() == Constants.FOR_BINDINGTYPE || arg.getBindingType() == Constants.QUANTIFIER_BINDINGTYPE || arg.getBindingType() == Constants.OUTERFOR_BINDINGTYPE) { 1803 QType exprqtype = expression.getQType(); 1804 if (exprqtype instanceof QTypeSequence) 1805 exprqtype = new QTypeUnion(exprqtype.getList()); 1806 if (exprqtype.isMultiple()) { 1807 exprqtype = exprqtype.changeOccurence(QType.OCC_1_1); 1808 } 1809 arg.setQType(exprqtype); 1810 1811 } 1812 else 1815 arg.setQType(expression.getQType()); 1816 } else if (arg.getTypeDeclaration() != null) { 1817 arg.setQType(arg.getTypeDeclaration().getQType()); 1818 } 1819 } 1821 1822 1836 public void visit(XMLComment arg) throws XQueryException { 1837 if (noForce && arg.getQType() != null) 1838 return; 1839 XQueryExpression comment = arg.getComment(); if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1842 if (comment.getQType() == null) 1843 return; 1844 } 1845 if ( 1846 comment.getQType() == null) 1847 comment.accept(this); 1848 if (comment.getQType() == null) 1850 throw new TypeException("Expression " + comment + " could not be typed."); 1852 QType valueQType = comment.getQType(); 1853 if (!valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString()) { 1854 valueQType = valueQType.applyDATAFunction(); 1855 if (valueQType == null || (!valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString())) 1856 throw new TypeException("Expression '" + comment + "', of attribute value pair has incorrect type."); 1857 } 1858 arg.setQType(new QTypeComment()); 1860 } 1861 1862 1886 1887 public void visit(XMLProcessingInstruction arg) throws XQueryException { 1888 if (noForce && arg.getQType() != null) 1889 return; 1890 XQueryExpression piName = arg.getExpression1(); XQueryExpression piValue = arg.getExpression2(); if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) { 1894 if (piValue.getQType() == null) 1897 return; 1898 } 1899 if ( 1905 piValue.getQType() == null) 1906 piValue.accept(this); 1907 if (piValue.getQType() == null) 1909 throw new TypeException("Expression " + piValue + " could not be typed."); 1911 QType nameQType = piName.getQType(); 1912 if (nameQType != null && (!nameQType.isQName() || nameQType.isMultiple())) { 1913 nameQType = nameQType.applyDATAFunction(); 1914 if (nameQType == null || !nameQType.isQName() || nameQType.isMultiple()) 1915 throw new TypeException("Expression '" + piName + "', of processing instruction value pair has incorrect type."); 1916 } 1917 QType valueQType = piValue.getQType(); 1918 if (valueQType != null && !valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString()) { 1919 valueQType = valueQType.applyDATAFunction(); 1920 if (valueQType == null || (!valueQType.canBeCastedInto(QType.PRIMITIVE_string) && !valueQType.isString())) 1921 throw new TypeException("Expression '" + piValue + "', of processing instruction pair has incorrect type."); 1922 } 1923 QType attQType = piValue.getQType(); 1928 arg.setQType(new QTypeProcessingInstruction()); 1929 } 1930 1931 public void visit(XQueryExpression arg) throws XQueryException { 1934 throw new TypeException("Typing of expression : " + arg + " of class " + arg.getClass().getName() + " is not supported"); 1935 } 1936 1937 public void visit(XQueryExpressionSequence arg) throws XQueryException { 1938 1943 if (noForce && arg.getQType() != null) 1945 return; 1946 ArrayList subExpressions = arg.getSubExpressions(); 1947 for (int i = 0; i < subExpressions.size(); i++) 1949 if ( 1950 ((XQueryExpression) subExpressions.get(i)).getQType() == null) { 1951 ((XQueryExpression) subExpressions.get(i)).accept(this); 1952 if (((XQueryExpression) subExpressions.get(i)).getQType() == null) 1953 throw new TypeException("Expression " + (XQueryExpression) subExpressions.get(i) + " could not be typed."); } 1955 if (subExpressions.size() == 1) 1957 arg.setQType(((XQueryExpression) subExpressions.get(0)).getQType()); 1958 else { 1959 ArrayList list = new ArrayList(subExpressions.size()); 1960 boolean unique = true; 1961 for (int i = 0; i < subExpressions.size(); i++) { 1962 XQueryExpression expr = (XQueryExpression) subExpressions.get(i); 1963 QType qtype = expr.getQType(); 1964 if (i != 0 && unique && !((QType) list.get(i - 1)).equals(qtype)) 1965 unique = false; 1966 list.add(qtype); 1967 } 1968 if (unique) 1969 arg.setQType(((QType) list.get(0)).changeOccurence(QType.OCC_0_N)); 1970 else 1972 arg.setQType(new QTypeSequence(list)); 1973 } 1974 } 1975 1976 public void visit(XQueryVoid arg) throws XQueryException { 1982 arg.setQType(new QTypeSequence(null)); 1983 } 1984 1985 1987 public void visit(FunctionABS arg) throws XQueryException { 1988 1993 if (noForce && arg.getQType() != null) 1995 return; 1996 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 1997 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 1999 if (expr.getQType() == null) 2000 return; 2001 if ( 2002 expr.getQType() == null) 2003 expr.accept(this); 2004 if (expr.getQType() == null) 2005 throw new TypeException("Function call abs '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2008 if (!qtype.isNumeric()) 2009 qtype = qtype.applyDATAFunction(); 2010 if (qtype == null || !qtype.isNumeric()) 2011 throw new TypeException("Function call abs '" + arg + "', argument is not numeric"); 2012 arg.setQType(new QTypeAtom(expr.getQType().getSimpleType())); 2014 } 2015 2016 public void visit(FunctionAVG arg) throws XQueryException { 2017 2027 if (noForce && arg.getQType() != null) 2029 return; 2030 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2032 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2034 if (expr.getQType() == null) 2035 return; 2036 if ( 2037 expr.getQType() == null) 2038 expr.accept(this); 2039 if (expr.getQType() == null) 2040 throw new TypeException("Function call avg '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2043 2049 if (!qtype.isAtom()) 2050 qtype = qtype.applyDATAFunction(); 2051 if (qtype == null || !qtype.isAtom()) 2052 throw new TypeException("Function call avg '" + arg + "', argument has incorrect type"); 2053 if (qtype.getSubClass() == QType.SEQUENCE || qtype.getSubClass() == QType.UNION) 2055 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE))); 2056 else { 2057 PrimitiveType primType = ((SimpleType) qtype.getType()).getPrimitive(); 2058 int prim = primType.getType(); 2059 switch (prim) { 2060 case PrimitiveType.FLOAT : 2061 arg.setQType(new QTypeAtom((SimpleType) getType(SC_FLOAT))); 2062 break; 2063 case PrimitiveType.DECIMAL : 2064 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DECIMAL))); 2065 break; 2066 case PrimitiveType.DOUBLE : 2067 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE))); 2068 break; 2069 default : 2070 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE))); 2071 break; 2072 } 2073 } 2074 } 2076 2077 public void visit(FunctionCEILING arg) throws XQueryException { 2078 2083 if (noForce && arg.getQType() != null) 2085 return; 2086 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2087 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2089 if (expr.getQType() == null) 2090 return; 2091 if ( 2092 expr.getQType() == null) 2093 expr.accept(this); 2094 if (expr.getQType() == null) 2095 throw new TypeException("Function call ceiling '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2098 if (!qtype.isNumeric()) 2099 qtype = qtype.applyDATAFunction(); 2100 if (qtype == null || !qtype.isNumeric()) 2101 throw new TypeException("Function call ceiling '" + arg + "', argument is not numeric"); 2102 arg.setQType(new QTypeAtom((SimpleType) getType(SC_INTEGER))); 2104 } 2105 2106 public void visit(FunctionCOLLECTION arg) throws XQueryException { 2107 2112 if (noForce && arg.getQType() != null) 2114 return; 2115 ArrayList xnodes = context.getCollectionRootNodes(arg.getSourceName(), arg.getCollectionName()); 2117 arg.setXTrees(xnodes); 2118 QType qtype = null; 2119 if (xnodes != null) { 2120 ArrayList tmplist = new ArrayList(); 2121 for (int i = 0; i < xnodes.size(); i++) { 2122 Collection childreni = ((XTreeNode) xnodes.get(i)).getChildren(); 2123 if (childreni != null && !childreni.isEmpty()) { 2124 ArrayList childlist = new ArrayList(1); 2125 childlist.addAll(childreni); 2126 QType qtypei = buildQTypeFromXNodes(childlist, QType.OCC_1_1, arg, true); 2127 if (qtypei != null) 2128 tmplist.add(new QTypeDocument(qtypei, QType.OCC_0_N, QTypeDocument.COLLECTION_ORIGIN)); 2129 } 2130 } 2131 if (!tmplist.isEmpty()) { 2132 if (tmplist.size() == 1) 2133 qtype = (QType) tmplist.get(0); 2134 else 2135 qtype = new QTypeUnion(tmplist, QType.OCC_0_N); 2136 } 2137 } 2138 2139 if (qaOnly && qtype == null) 2144 qtype = new QTypeDocument(new QTypeElement(new QName("*", "*", "*", arg.getParentModule(), null), getType(SC_ANYTYPE)), QType.OCC_0_N, QTypeDocument.DOCUMENT_ORIGIN); 2145 arg.setQType(qtype); 2147 2148 } 2149 2150 public void visit(FunctionCONCAT arg) throws XQueryException { 2151 2156 if (noForce && arg.getQType() != null) 2158 return; 2159 ArrayList arguments = arg.getArguments(); 2160 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2162 for (int i = 0; i < arguments.size(); i++) 2163 if (((XQueryExpression) arguments.get(i)).getQType() == null) 2164 return; 2165 for (int i = 0; i < arguments.size(); i++) { 2166 XQueryExpression expri = (XQueryExpression) arguments.get(i); 2167 if ( 2168 expri.getQType() == null) 2169 expri.accept(this); 2170 QType qtypei = expri.getQType(); 2171 if (qtypei == null) throw new TypeException("Function call concat '" + arg + "', argument " + (i + 1) + " could not be typed"); if (!qtypei.isString()) 2174 throw new TypeException("Function call concat '" + arg + "', argument " + (i + 1) + " is not a string."); 2175 if (!qtypei.isAtomic() ) 2176 throw new TypeException("Function call concat '" + arg + "', argument " + (i + 1) + " is not an atomic value.'"); 2177 } 2178 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 2180 } 2181 2182 public void visit(FunctionCONTAINS arg) throws XQueryException { 2183 2190 2191 if (noForce && arg.getQType() != null) 2193 return; 2194 2195 ArrayList arguments = arg.getArguments(); 2196 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2198 for (int i = 0; i < arguments.size(); i++) 2199 if (((XQueryExpression) arguments.get(i)).getQType() == null) 2200 return; 2201 for (int i = 0; i < arguments.size(); i++) { 2202 XQueryExpression expri = (XQueryExpression) arguments.get(i); 2203 if ( 2204 expri.getQType() == null) 2205 expri.accept(this); 2206 if (expri.getQType() == null) throw new TypeException("Function call contains '" + arg + "', argument " + (i + 1) + " could not be typed"); if (!expri.getQType().isAtomic() ) 2209 throw new TypeException("Function call contains '" + arg + "', argument " + (i + 1) + " is not an atomic value.'"); 2210 if (!expri.getQType().isString()) 2211 throw new TypeException("Function call contains '" + arg + "', argument " + (i + 1) + " is not a string."); 2212 } 2213 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 2215 } 2216 2217 public void visit(FunctionCOUNT arg) throws XQueryException { 2218 2223 if (noForce && arg.getQType() != null) 2225 return; 2226 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2227 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2229 if (expr.getQType() == null) 2230 return; 2231 if ( 2232 expr.getQType() == null) 2233 expr.accept(this); 2234 if (expr.getQType() == null) 2235 throw new TypeException("Function call count '" + arg + "', argument could not be typed"); arg.setQType(new QTypeAtom((SimpleType) getType(SC_INTEGER))); 2238 } 2239 2240 public void visit(FunctionCURRENT_DATE arg) throws XQueryException { 2241 2247 if (noForce && arg.getQType() != null) 2251 return; 2252 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DATE))); 2254 } 2255 2256 public void visit(FunctionCURRENT_DATETIME arg) throws XQueryException { 2257 2263 if (noForce && arg.getQType() != null) 2267 return; 2268 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DATETIME))); 2270 } 2271 2272 public void visit(FunctionCURRENT_TIME arg) throws XQueryException { 2273 2279 if (noForce && arg.getQType() != null) 2283 return; 2284 arg.setQType(new QTypeAtom((SimpleType) getType(SC_TIME))); 2286 } 2287 2288 public void visit(FunctionDATA arg) throws XQueryException { 2289 2298 if (noForce && arg.getQType() != null) 2300 return; 2301 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2302 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2304 if (expr.getQType() == null) 2305 return; 2306 if ( 2307 expr.getQType() == null) 2308 expr.accept(this); 2309 if (expr.getQType() == null) 2310 throw new TypeException("Function call count '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2312 QType argqtype = null; 2315 if (qtype.isAtom()) 2316 argqtype = qtype; 2317 else 2318 argqtype = qtype.applyDATAFunction(); 2319 if (argqtype == null) 2320 throw new TypeException("Function call data '" + arg + "', could not apply data function to type '" + qtype + "'."); 2321 arg.setQType(argqtype); 2323 } 2324 2325 public void visit(FunctionDATE arg) throws XQueryException { 2326 2332 if (noForce && arg.getQType() != null) 2334 return; 2335 XQueryExpression argument = (XQueryExpression) arg.getArguments().get(0); 2336 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2338 if (argument.getQType() == null) 2339 return; 2340 if (!(argument instanceof ValueString)) 2341 throw new TypeException("Function call date '" + arg + "', argument is not a string literal"); 2342 try { 2343 SimpleType simpleType = context.getSchemaManager().getDateType(); 2344 String dateValue = simpleType.normalizedValue(((ValueString) argument).getValue()); 2345 simpleType.validate(dateValue, false, null); 2346 ((ValueString) argument).setValue(dateValue); 2347 } catch (SchemaException se) { 2348 throw new TypeException("Function call date '" + arg + "', argument has invalid date format"); 2349 } 2350 arg.setQType(new QTypeAtom(context.getSchemaManager().getDateType())); 2352 } 2353 2354 public void visit(FunctionDATETIME arg) throws XQueryException { 2355 2361 if (noForce && arg.getQType() != null) 2363 return; 2364 XQueryExpression argument = (XQueryExpression) arg.getArguments().get(0); 2365 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2367 if (argument.getQType() == null) 2368 return; 2369 if (!(argument instanceof ValueString)) 2370 throw new TypeException("Function call datetime '" + arg + "', argument is not a string literal"); 2371 try { 2372 SimpleType simpleType = context.getSchemaManager().getDateTimeType(); 2373 String dateValue = simpleType.normalizedValue(((ValueString) argument).getValue()); 2374 simpleType.validate(dateValue, false, null); 2375 ((ValueString) argument).setValue(dateValue); 2376 } catch (SchemaException se) { 2377 throw new TypeException("Function call datetime '" + arg + "', argument has invalid datetime format"); 2378 } 2379 arg.setQType(new QTypeAtom(context.getSchemaManager().getDateTimeType())); 2381 } 2382 2383 public void visit(FunctionDECIMAL arg) throws XQueryException { 2384 2389 if (noForce && arg.getQType() != null) 2391 return; 2392 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2393 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2395 if (expr.getQType() == null) 2396 return; 2397 if ( 2398 expr.getQType() == null) 2399 expr.accept(this); 2400 if (expr.getQType() == null) 2401 throw new TypeException("Function call decimal '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2404 if (!qtype.isAtom()) { 2405 qtype = qtype.applyDATAFunction(); 2406 if (!qtype.isAtom()) 2407 throw new TypeException("Function call decimal '" + arg + "', argument has invalid type, not an atom"); 2408 } 2409 if (!qtype.canBeCastedInto(QType.PRIMITIVE_decimal)) 2410 throw new TypeException("Function call decimal '" + arg + "', argument has type that can not be casted"); 2411 if (expr instanceof ValueString) { 2412 try { 2413 SimpleType simpleType = context.getSchemaManager().getDecimalType(); 2414 String decimalValue = simpleType.normalizedValue(((ValueString) expr).getValue()); 2415 simpleType.validate(decimalValue, false, null); 2416 ((ValueString) expr).setValue(decimalValue); 2417 } catch (SchemaException se) { 2418 throw new TypeException("Function call decimal '" + arg + "', argument is string with invalid format"); 2419 } 2420 } 2421 arg.setQType(new QTypeAtom(context.getSchemaManager().getDecimalType())); 2423 } 2424 2425 public void visit(FunctionDISTINCT_VALUES arg) throws XQueryException { 2426 2431 if (noForce && arg.getQType() != null) 2433 return; 2434 XQueryExpression expr = (XQueryExpression) arg.getArgument(0); 2435 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2437 if (expr.getQType() == null) 2438 return; 2439 if ( 2440 expr.getQType() == null) 2441 expr.accept(this); 2442 if (expr.getQType() == null) 2443 throw new TypeException("Function call distinct-values '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2447 if (!qtype.isAtom() 2448 ) { 2449 qtype = qtype.applyDATAFunction(); 2450 if (qtype == null || !qtype.isAtom() 2451 ) 2452 throw new TypeException("Function call distinct-values '" + arg + "', argument is not a collection of simple values"); 2453 } 2454 arg.setQType(qtype); 2456 } 2457 2458 public void visit(FunctionDOC arg) throws XQueryException { 2459 2460 2465 2466 if (noForce && arg.getQType() != null) 2468 return; 2469 arg.setQType(new QTypeDocument(new QTypeElement(new QName("*", "*", "*", arg.getParentModule(), null), this.getType(SC_ANYTYPE)), QTypeDocument.DOCUMENT_ORIGIN)); 2472 2473 } 2474 2475 public void visit(FunctionDOUBLE arg) throws XQueryException { 2476 2481 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2483 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2485 if (expr.getQType() == null) 2486 return; 2487 if ( 2488 expr.getQType() == null) 2489 expr.accept(this); 2490 if (expr.getQType() == null) 2491 throw new TypeException("Function call double '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2493 if (!qtype.isAtom()) { 2494 qtype = qtype.applyDATAFunction(); 2495 if (qtype == null || !qtype.isAtom()) 2496 throw new TypeException("Function call double '" + arg + "', argument has invalid type, not an atom"); 2497 } 2498 if (!qtype.canBeCastedInto(QType.PRIMITIVE_double)) 2499 throw new TypeException("Function call double '" + arg + "', argument has type that can not be casted"); 2500 if (expr instanceof ValueString) { 2501 try { 2502 SimpleType simpleType = context.getSchemaManager().getDoubleType(); 2503 String value = simpleType.normalizedValue(((ValueString) expr).getValue()); 2504 simpleType.validate(value, false, null); 2505 ((ValueString) expr).setValue(value); 2506 } catch (SchemaException se) { 2507 throw new TypeException("Function call double '" + arg + "', argument is string with invalid format"); 2508 } 2509 } 2510 arg.setQType(new QTypeAtom(context.getSchemaManager().getDoubleType())); 2512 } 2513 2514 public void visit(FunctionEMPTY arg) throws XQueryException { 2515 2520 2521 2523 if (noForce && arg.getQType() != null) 2525 return; 2526 XQueryExpression expr = arg.getArgument(0); 2527 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2529 if (expr.getQType() == null) 2530 return; 2531 if ( 2532 expr.getQType() == null) 2533 expr.accept(this); 2534 if (expr.getQType() == null) 2535 throw new TypeException("Function call empty '" + arg + "', argument could not be typed"); arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 2540 } 2541 2542 public void visit(FunctionENDS_WITH arg) throws XQueryException { 2543 2548 2550 if (noForce && arg.getQType() != null) 2552 return; 2553 ArrayList arguments = arg.getArguments(); 2554 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2556 for (int i = 0; i < arguments.size(); i++) 2557 if (((XQueryExpression) arguments.get(i)).getQType() == null) 2558 return; 2559 for (int i = 0; i < arguments.size(); i++) { 2560 XQueryExpression expri = (XQueryExpression) arguments.get(i); 2561 if ( 2562 expri.getQType() == null) 2563 expri.accept(this); 2564 if (expri.getQType() == null) throw new TypeException("Function call ends-with '" + arg + "', argument " + (i + 1) + " could not be typed"); if (!expri.getQType().isString()) 2567 throw new TypeException("Function call ends-with '" + arg + "', argument " + (i + 1) + " is not a string"); 2568 } 2569 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 2571 } 2572 2573 public void visit(FunctionEXISTS arg) throws XQueryException { 2574 2579 if (noForce && arg.getQType() != null) 2581 return; 2582 2583 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2584 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2586 if (expr.getQType() == null) 2587 return; 2588 if ( 2589 expr.getQType() == null) 2590 expr.accept(this); 2591 if (expr.getQType() == null) 2592 throw new TypeException("Function call empty '" + arg + "', argument could not be typed"); arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 2595 } 2596 2597 public void visit(FunctionEXPANDED_QNAME arg) throws XQueryException { 2598 if (noForce && arg.getQType() != null) 2599 return; 2600 2601 ArrayList arguments = arg.getArguments(); 2602 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2604 for (int i = 0; i < arguments.size(); i++) 2605 if (((XQueryExpression) arguments.get(i)).getQType() == null) 2606 return; 2607 for (int i = 0; i < arguments.size(); i++) { 2608 XQueryExpression expri = (XQueryExpression) arguments.get(i); 2609 if ( 2610 expri.getQType() == null) 2611 expri.accept(this); 2612 if (expri.getQType() == null) throw new TypeException("Function call expanded-QName '" + arg + "', argument " + (i + 1) + " could not be typed"); if (!expri.getQType().isAtom() || !expri.getQType().isString()) 2615 throw new TypeException("Function call expanded-QName '" + arg + "', argument " + (i + 1) + " is not an atomic string.'"); 2616 } 2617 arg.setQType(new QTypeAtom((SimpleType) getType(SC_QNAME))); 2619 } 2620 2621 public void visit(FunctionFALSE arg) throws XQueryException { 2622 2626 if (noForce && arg.getQType() != null) 2628 return; 2629 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 2631 } 2632 2633 public void visit(FunctionFLOAT arg) throws XQueryException { 2634 2639 if (noForce && arg.getQType() != null) 2641 return; 2642 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2643 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2645 if (expr.getQType() == null) 2646 return; 2647 if ( 2648 expr.getQType() == null) 2649 expr.accept(this); 2650 if (expr.getQType() == null) 2651 throw new TypeException("Function call float '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2653 if (!qtype.isAtom()) { 2654 qtype = qtype.applyDATAFunction(); 2655 if (qtype == null || !qtype.isAtom()) 2656 throw new TypeException("Function call float '" + arg + "', argument has invalid type, not an atom"); 2657 } 2658 if (!qtype.canBeCastedInto(QType.PRIMITIVE_float)) 2659 throw new TypeException("Function call float '" + arg + "', argument has type that can not be casted"); 2660 if (expr instanceof ValueString) { 2661 try { 2662 SimpleType simpleType = context.getSchemaManager().getFloatType(); 2663 String value = simpleType.normalizedValue(((ValueString) expr).getValue()); 2664 simpleType.validate(value, false, null); 2665 ((ValueString) expr).setValue(value); 2666 } catch (SchemaException se) { 2667 throw new TypeException("Function call float '" + arg + "', argument is string with invalid format"); 2668 } 2669 } 2670 arg.setQType(new QTypeAtom(context.getSchemaManager().getFloatType())); 2672 } 2673 2674 public void visit(FunctionFLOOR arg) throws XQueryException { 2675 2680 if (noForce && arg.getQType() != null) 2682 return; 2683 XQueryExpression expr = (XQueryExpression) arg.getArguments().get(0); 2684 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2686 if (expr.getQType() == null) 2687 return; 2688 if ( 2689 expr.getQType() == null) 2690 expr.accept(this); 2691 if (expr.getQType() == null) 2692 throw new TypeException("Function call floor '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2695 if (!qtype.isNumeric()) 2696 qtype = qtype.applyDATAFunction(); 2697 if (qtype == null || !qtype.isNumeric()) 2698 throw new TypeException("Function call floor '" + arg + "', argument is not numeric"); 2699 arg.setQType(new QTypeAtom((SimpleType) getType(SC_INTEGER))); 2701 } 2702 2703 public void visit(FunctionGET_MONTH_FROM_DATE arg) throws XQueryException { 2704 2709 if (noForce && arg.getQType() != null) 2711 return; 2712 ArrayList arguments = arg.getArguments(); 2713 XQueryExpression expr = (XQueryExpression) arguments.get(0); 2714 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2716 if (expr.getQType() == null) 2717 return; 2718 if ( 2719 expr.getQType() == null) 2720 expr.accept(this); 2721 if (expr.getQType() == null) 2722 throw new TypeException("Function call lower-case '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2725 if (!qtype.isAtom()) { 2726 qtype = qtype.applyDATAFunction(); 2727 if (qtype == null || !qtype.isAtom()) 2728 throw new TypeException("Function call get-month-from-date '" + arg + "', argument has invalid type, not an atom"); 2729 } 2730 if (!qtype.canBeCastedInto(QType.PRIMITIVE_date)) 2731 throw new TypeException("Function call get-month-from-date '" + arg + "', argument has type that can not be casted"); 2732 2733 if (expr instanceof ValueString) { 2736 try { 2737 SimpleType simpleType = context.getSchemaManager().getDateType(); 2738 String dateValue = simpleType.normalizedValue(((ValueString) expr).getValue()); 2739 simpleType.validate(dateValue, false, null); 2740 ((ValueString) expr).setValue(dateValue); 2741 } catch (SchemaException se) { 2742 throw new TypeException("Function call get-month-from-date '" + arg + "', argument is string with invalid format"); 2743 } 2744 } 2745 arg.setQType(new QTypeAtom(context.getSchemaManager().getIntegerType())); 2747 } 2748 2749 public void visit(FunctionGET_YEAR_FROM_DATE arg) throws XQueryException { 2750 2755 if (noForce && arg.getQType() != null) 2757 return; 2758 ArrayList arguments = arg.getArguments(); 2759 XQueryExpression expr = (XQueryExpression) arguments.get(0); 2760 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2762 if (expr.getQType() == null) 2763 return; 2764 if ( 2765 expr.getQType() == null) 2766 expr.accept(this); 2767 if (expr.getQType() == null) 2768 throw new TypeException("Function call lower-case '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2771 if (!qtype.isAtom()) { 2772 qtype = qtype.applyDATAFunction(); 2773 if (qtype != null || !qtype.isAtom()) 2774 throw new TypeException("Function call get-month-from-date '" + arg + "', argument has invalid type, not an atom"); 2775 } 2776 if (!qtype.canBeCastedInto(QType.PRIMITIVE_date)) 2777 throw new TypeException("Function call get-month-from-date '" + arg + "', argument has type that can not be casted"); 2778 2779 if (expr instanceof ValueString) { 2782 try { 2783 SimpleType simpleType = context.getSchemaManager().getDateType(); 2784 String dateValue = simpleType.normalizedValue(((ValueString) expr).getValue()); 2785 simpleType.validate(dateValue, false, null); 2786 ((ValueString) expr).setValue(dateValue); 2787 } catch (SchemaException se) { 2788 throw new TypeException("Function call get-month-from-date '" + arg + "', argument is string with invalid format"); 2789 } 2790 } 2791 arg.setQType(new QTypeAtom(context.getSchemaManager().getIntegerType())); 2793 } 2794 2795 public void visit(FunctionINTEGER arg) throws XQueryException { 2796 2801 if (noForce && arg.getQType() != null) 2803 return; 2804 ArrayList arguments = arg.getArguments(); 2805 XQueryExpression expr = (XQueryExpression) arguments.get(0); 2806 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2808 if (expr.getQType() == null) 2809 return; 2810 if ( 2811 expr.getQType() == null) 2812 expr.accept(this); 2813 if (expr.getQType() == null) 2814 throw new TypeException("Function call integer '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2816 if (!qtype.canBeCastedInto(QType.PRIMITIVE_decimal)) 2817 throw new TypeException("Function call integer '" + arg + "', argument has type that can not be casted"); 2818 if (expr instanceof ValueString) { 2819 try { 2820 SimpleType simpleType = context.getSchemaManager().getIntegerType(); 2821 String value = simpleType.normalizedValue(((ValueString) expr).getValue()); 2822 simpleType.validate(value, false, null); 2823 ((ValueString) expr).setValue(value); 2824 } catch (SchemaException se) { 2825 throw new TypeException("Function call float '" + arg + "', argument is string with invalid format"); 2826 } 2827 } 2828 arg.setQType(new QTypeAtom(context.getSchemaManager().getIntegerType())); 2830 } 2831 2832 public void visit(FunctionLOCAL_NAME arg) throws XQueryException { 2833 2838 if (noForce && arg.getQType() != null) 2840 return; 2841 ArrayList arguments = arg.getArguments(); 2842 XQueryExpression expr = (XQueryExpression) arguments.get(0); 2843 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2845 if (expr.getQType() == null) 2846 return; 2847 if ( 2848 expr.getQType() == null) 2849 expr.accept(this); 2850 if (expr.getQType() == null) 2851 throw new TypeException("Function call local-name'" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2854 if (!qtype.isNode()) 2855 throw new TypeException("Function call local-name '" + arg + "', argument is not a node"); 2856 if (!qtype.isAtomic() ) 2857 throw new TypeException("Function call local-name '" + arg + "', argument is not an atomic value.'"); 2858 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 2860 } 2861 2862 public void visit(FunctionLOWER_CASE arg) throws XQueryException { 2863 2868 if (noForce && arg.getQType() != null) 2870 return; 2871 ArrayList arguments = arg.getArguments(); 2872 XQueryExpression expr = (XQueryExpression) arguments.get(0); 2873 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2875 if (expr.getQType() == null) 2876 return; 2877 if ( 2878 expr.getQType() == null) 2879 expr.accept(this); 2880 if (expr.getQType() == null) 2881 throw new TypeException("Function call lower-case '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2884 if (!qtype.isString()) 2885 throw new TypeException("Function call lower-case '" + arg + "', argument is not a string"); 2886 if (!qtype.isAtomic() ) 2887 throw new TypeException("Function call lower-case '" + arg + "', argument is not an atomic value.'"); 2888 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 2890 } 2891 2892 public void visit(FunctionMATCHES arg) throws XQueryException { 2893 2898 if (noForce && arg.getQType() != null) 2900 return; 2901 ArrayList arguments = arg.getArguments(); 2902 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2904 for (int i = 0; i < arguments.size(); i++) 2905 if (((XQueryExpression) arguments.get(i)).getQType() == null) 2906 return; 2907 for (int i = 0; i < arguments.size(); i++) { 2908 XQueryExpression expri = (XQueryExpression) arguments.get(i); 2909 if ( 2910 expri.getQType() == null) 2911 expri.accept(this); 2912 if (expri.getQType() == null) throw new TypeException("Function call match '" + arg + "', argument " + (i + 1) + " could not be typed"); if (!expri.getQType().isString()) 2915 throw new TypeException("Function call match '" + arg + "', argument " + (i + 1) + " is not a string"); 2916 if (!expri.getQType().isAtomic() ) 2917 throw new TypeException("Function call match '" + arg + "', argument " + (i + 1) + " is not an atomic value.'"); 2918 } 2919 arg.setQType(new QTypeAtom((SimpleType) getType(SC_INTEGER), QType.OCC_0_N)); 2921 } 2922 2923 public void visit(FunctionMAX arg) throws XQueryException { 2924 2929 if (noForce && arg.getQType() != null) 2931 return; 2932 ArrayList arguments = arg.getArguments(); 2933 XQueryExpression expr = (XQueryExpression) arguments.get(0); 2934 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2936 if (expr.getQType() == null) 2937 return; 2938 if ( 2939 expr.getQType() == null) 2940 expr.accept(this); 2941 if (expr.getQType() == null) 2942 throw new TypeException("Function call max '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2945 2951 if (!qtype.isAtom()) 2952 qtype = qtype.applyDATAFunction(); 2953 if (qtype == null || !qtype.isAtom()) 2954 throw new TypeException("Function call max '" + arg + "', argument has incorrect type"); 2955 if (qtype.getSubClass() == QType.SEQUENCE || qtype.getSubClass() == QType.UNION) 2958 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE))); 2959 else { 2960 if (qtype.getOccurence() != QType.OCC_1_1) 2961 qtype = qtype.changeOccurence(QType.OCC_1_1); 2962 arg.setQType(qtype); 2963 } 2964 } 2965 2966 public void visit(FunctionMIN arg) throws XQueryException { 2967 2972 if (noForce && arg.getQType() != null) 2974 return; 2975 ArrayList arguments = arg.getArguments(); 2976 XQueryExpression expr = (XQueryExpression) arguments.get(0); 2977 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 2979 if (expr.getQType() == null) 2980 return; 2981 if ( 2982 expr.getQType() == null) 2983 expr.accept(this); 2984 if (expr.getQType() == null) 2985 throw new TypeException("Function call min '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 2988 2994 if (!qtype.isAtom()) 2995 qtype = qtype.applyDATAFunction(); 2996 if (qtype == null || !qtype.isAtom()) 2997 throw new TypeException("Function call min '" + arg + "', argument has incorrect type"); 2998 if (qtype.getSubClass() == QType.SEQUENCE || qtype.getSubClass() == QType.UNION) 3001 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE))); 3002 else { 3003 if (qtype.getOccurence() != QType.OCC_1_1) 3004 qtype = qtype.changeOccurence(QType.OCC_1_1); 3005 arg.setQType(qtype); 3006 } 3007 } 3008 3009 public void visit(FunctionNAMESPACE_URI arg) throws XQueryException { 3010 3015 if (noForce && arg.getQType() != null) 3017 return; 3018 ArrayList arguments = arg.getArguments(); 3019 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3020 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3022 if (expr.getQType() == null) 3023 return; 3024 if ( 3025 expr.getQType() == null) 3026 expr.accept(this); 3027 if (expr.getQType() == null) 3028 throw new TypeException("Function call namespace-uri'" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 3031 if (!qtype.isNode()) 3032 throw new TypeException("Function call namespace-uri '" + arg + "', argument is not a node"); 3033 if (!qtype.isAtomic() ) 3034 throw new TypeException("Function call local-name '" + arg + "', argument is not an atomic value.'"); 3035 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 3037 } 3038 3039 public void visit(FunctionNOT arg) throws XQueryException { 3040 3045 if (noForce && arg.getQType() != null) 3047 return; 3048 ArrayList arguments = arg.getArguments(); 3049 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3050 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3052 if (expr.getQType() == null) 3053 return; 3054 if ( 3055 expr.getQType() == null) 3056 expr.accept(this); 3057 if (expr.getQType() == null) 3058 throw new TypeException("Function call not '" + arg + "', argument could not be typed"); if (!expr.getQType().isBoolean()) 3061 throw new TypeException("Function call not '" + arg + "', argument is not a boolean"); 3062 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 3064 } 3065 3066 public void visit(FunctionNUMBER arg) throws XQueryException { 3067 3072 if (noForce && arg.getQType() != null) 3074 return; 3075 ArrayList arguments = arg.getArguments(); 3076 if (arguments != null) { 3077 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3078 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3080 if (expr.getQType() == null) 3081 return; 3082 if ( 3083 expr.getQType() == null) 3084 expr.accept(this); 3085 if (expr.getQType() == null) 3086 throw new TypeException("Function call number '" + arg + "', argument could not be typed"); if (!expr.getQType().isSimpleTypeNode()) 3089 throw new TypeException("Function call number '" + arg + "', argument is not a simple node or collection of simple nodes"); 3090 } 3091 arg.setQType(new QTypeAtom((SimpleType) getType(SC_FLOAT))); 3093 } 3094 3095 3109 public void visit(FunctionQNAME arg) throws XQueryException { 3110 if (noForce && arg.getQType() != null) 3111 return; 3112 3113 ArrayList arguments = arg.getArguments(); 3114 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3115 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3117 if (expr.getQType() == null) 3118 return; 3119 if ( 3120 expr.getQType() == null) 3121 expr.accept(this); 3122 if (expr.getQType() == null) throw new TypeException("Function call QName '" + arg + "', argument could not be typed"); if (!expr.getQType().isAtom() || !expr.getQType().isString()) 3125 throw new TypeException("Function call QName '" + arg + "', argument is not an atomic string.'"); 3126 arg.setQType(new QTypeAtom((SimpleType) getType(SC_QNAME))); 3128 } 3129 3130 public void visit(FunctionROUND arg) throws XQueryException { 3131 3136 if (noForce && arg.getQType() != null) 3138 return; 3139 ArrayList arguments = arg.getArguments(); 3140 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3141 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3143 if (expr.getQType() == null) 3144 return; 3145 if ( 3146 expr.getQType() == null) 3147 expr.accept(this); 3148 if (expr.getQType() == null) 3149 throw new TypeException("Function call round '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 3152 if (!qtype.isNumeric()) 3153 qtype = qtype.applyDATAFunction(); 3154 if (qtype == null || !qtype.isNumeric()) 3155 throw new TypeException("Function call round '" + arg + "', argument is not numeric"); 3156 arg.setQType(new QTypeAtom((SimpleType) getType(SC_INTEGER))); 3158 } 3159 3160 public void visit(FunctionSTARTS_WITH arg) throws XQueryException { 3161 3166 if (noForce && arg.getQType() != null) 3168 return; 3169 ArrayList arguments = arg.getArguments(); 3170 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3172 for (int i = 0; i < arguments.size(); i++) 3173 if (((XQueryExpression) arguments.get(i)).getQType() == null) 3174 return; 3175 for (int i = 0; i < arguments.size(); i++) { 3176 XQueryExpression expri = (XQueryExpression) arguments.get(i); 3177 if ( 3178 expri.getQType() == null) 3179 expri.accept(this); 3180 if (expri.getQType() == null) throw new TypeException("Function call starts-with '" + arg + "', argument " + (i + 1) + " could not be typed"); if (!expri.getQType().isString()) 3183 throw new TypeException("Function call starts-with '" + arg + "', argument " + (i + 1) + " is not a string"); 3184 if (!expri.getQType().isAtomic() ) 3185 throw new TypeException("Function call starts-with '" + arg + "', argument " + (i + 1) + " is not an atomic value.'"); 3186 } 3187 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 3189 } 3190 3191 public void visit(FunctionSTRING arg) throws XQueryException { 3192 3207 3215 if (noForce && arg.getQType() != null) 3217 return; 3218 ArrayList arguments = arg.getArguments(); 3219 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3220 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3222 if (expr.getQType() == null) 3223 return; 3224 if ( 3225 expr.getQType() == null) 3226 expr.accept(this); 3227 if (expr.getQType() == null) 3228 throw new TypeException("Function call string '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 3231 if (qtype == null || (!qtype.isAtomic() && !inPredicate && !qtype.isSimpleTypeNode())) 3234 throw new TypeException("Function call string '" + arg + "', argument must be an atomic value or simple content element."); 3235 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING), qtype.isMultiple() ? QType.OCC_0_N : QType.OCC_1_1)); 3237 } 3242 3243 public void visit(FunctionSTRING_LENGTH arg) throws XQueryException { 3244 3249 if (noForce && arg.getQType() != null) 3251 return; 3252 ArrayList arguments = arg.getArguments(); 3253 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3254 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3256 if (expr.getQType() == null) 3257 return; 3258 if ( 3260 expr.getQType() == null) 3261 expr.accept(this); 3262 if (expr.getQType() == null) throw new TypeException("Function call string-length '" + arg + "', argument could not be typed"); if (!expr.getQType().isString()) 3265 throw new TypeException("Function call string-length '" + arg + "', argument is not a string"); 3266 if (!expr.getQType().isAtomic() ) 3267 throw new TypeException("Function call string-length '" + arg + "', argument is not an atomic value.'"); 3268 arg.setQType(new QTypeAtom((SimpleType) getType(SC_INTEGER))); 3270 } 3271 3272 public void visit(FunctionSUBSTRING arg) throws XQueryException { 3273 3278 if (noForce && arg.getQType() != null) 3280 return; 3281 ArrayList arguments = arg.getArguments(); 3282 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3284 for (int i = 0; i < arguments.size(); i++) 3285 if (((XQueryExpression) arguments.get(i)).getQType() == null) 3286 return; 3287 for (int i = 0; i < arguments.size(); i++) { 3288 XQueryExpression expri = (XQueryExpression) arguments.get(i); 3289 if ( 3290 expri.getQType() == null) 3291 expri.accept(this); 3292 if (expri.getQType() == null) throw new TypeException("Function call substring '" + arg + "', argument " + (i + 1) + " could not be typed"); if (i == 0 && !expri.getQType().isString()) 3295 throw new TypeException("Function call substring '" + arg + "', argument " + (i + 1) + " is not a string"); 3296 if (i != 0 && !expri.getQType().isNumeric()) 3297 throw new TypeException("Function call substring '" + arg + "', argument " + (i + 1) + " is not numeric"); 3298 } 3299 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 3301 } 3302 3303 public void visit(FunctionSUM arg) throws XQueryException { 3304 3314 if (noForce && arg.getQType() != null) 3316 return; 3317 ArrayList arguments = arg.getArguments(); 3318 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3319 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3321 if (expr.getQType() == null) 3322 return; 3323 if ( 3324 expr.getQType() == null) 3325 expr.accept(this); 3326 if (expr.getQType() == null) 3327 throw new TypeException("Function call sum '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 3330 3336 if (!qtype.isAtom()) 3337 qtype = qtype.applyDATAFunction(); 3338 if (qtype == null || !qtype.isAtom()) 3339 throw new TypeException("Function call sum '" + arg + "', argument has incorrect type"); 3340 if (qtype.getSubClass() == QType.SEQUENCE || qtype.getSubClass() == QType.UNION) 3342 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE))); 3343 else { 3344 PrimitiveType primType = ((SimpleType) qtype.getType()).getPrimitive(); 3345 int prim = primType.getType(); 3346 switch (prim) { 3347 case PrimitiveType.FLOAT : 3348 arg.setQType(new QTypeAtom((SimpleType) getType(SC_FLOAT))); 3349 break; 3350 case PrimitiveType.DECIMAL : 3351 if (primType.getFractionDigits() == 0) 3352 arg.setQType(new QTypeAtom((SimpleType) getType(SC_INTEGER))); 3353 else 3354 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DECIMAL))); 3355 break; 3356 case PrimitiveType.DOUBLE : 3357 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE))); 3358 break; 3359 default : 3360 arg.setQType(new QTypeAtom((SimpleType) getType(SC_DOUBLE))); 3361 break; 3362 } 3363 } 3364 } 3366 3367 public void visit(FunctionTIME arg) throws XQueryException { 3368 3374 if (noForce && arg.getQType() != null) 3376 return; 3377 XQueryExpression argument = (XQueryExpression) arg.getArguments().get(0); 3378 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3380 if (argument.getQType() == null) 3381 return; 3382 if (!(argument instanceof ValueString)) 3383 throw new TypeException("Function call time '" + arg + "', argument is not a string literal"); 3384 try { 3385 SimpleType simpleType = context.getSchemaManager().getTimeType(); 3386 String timeValue = simpleType.normalizedValue(((ValueString) argument).getValue()); 3387 simpleType.validate(timeValue, false, null); 3388 ((ValueString) argument).setValue(timeValue); 3389 } catch (SchemaException se) { 3390 throw new TypeException("Function call time '" + arg + "', argument has invalid datetime format"); 3391 } 3392 arg.setQType(new QTypeAtom(context.getSchemaManager().getTimeType())); 3394 } 3395 3396 public void visit(FunctionTRUE arg) throws XQueryException { 3397 3401 if (noForce && arg.getQType() != null) 3403 return; 3404 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 3406 } 3407 3408 public void visit(FunctionUPPER_CASE arg) throws XQueryException { 3409 3414 if (noForce && arg.getQType() != null) 3416 return; 3417 ArrayList arguments = arg.getArguments(); 3418 XQueryExpression expr = (XQueryExpression) arguments.get(0); 3419 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3421 if (expr.getQType() == null) 3422 return; 3423 if ( 3424 expr.getQType() == null) 3425 expr.accept(this); 3426 if (expr.getQType() == null) 3427 throw new TypeException("Function call upper-case '" + arg + "', argument could not be typed"); QType qtype = expr.getQType(); 3430 if (!qtype.isString()) 3431 throw new TypeException("Function call upper-case '" + arg + "', argument is not a string"); 3432 if (!qtype.isAtomic() ) 3433 throw new TypeException("Function call upper-case '" + arg + "', argument is not an atomic value.'"); 3434 arg.setQType(new QTypeAtom((SimpleType) getType(SC_STRING))); 3436 } 3437 3438 public void visit(FunctionDEEP_EQUALS arg) throws XQueryException { 3439 3444 if (noForce && arg.getQType() != null) 3446 return; 3447 3448 ArrayList arguments = arg.getArguments(); 3449 if ((contextXNodes == null || contextXNodes.isEmpty()) && contextQType == null) 3451 for (int i = 0; i < arguments.size(); i++) 3452 if (((XQueryExpression) arguments.get(i)).getQType() == null) 3453 return; 3454 for (int i = 0; i < arguments.size(); i++) { 3455 XQueryExpression expri = (XQueryExpression) arguments.get(i); 3456 if ( 3457 expri.getQType() == null) 3458 expri.accept(this); 3459 if (expri.getQType() == null) throw new TypeException("Function call deep-equals '" + arg + "', argument " + (i + 1) + " could not be typed"); if (!expri.getQType().isAtomic() ) 3462 throw new TypeException("Function call deep-equals '" + arg + "', argument " + (i + 1) + " is not an atomic value.'"); 3463 } 3464 arg.setQType(new QTypeAtom((SimpleType) getType(SC_BOOLEAN))); 3466 } 3467 3468 private Type getType(String typeStr) { 3472 return context.getSchemaManager().getType(XML_SCHEMA, typeStr); 3473 } 3474 3475 private QType buildQTypeFromXNodes(ArrayList schemaNodes, byte occurence) throws XQueryException { 3476 return buildQTypeFromXNodes(schemaNodes, occurence, null, false); 3477 } 3478 3479 private QType buildQTypeFromXNodes(ArrayList schemaNodes, byte occurence, XQueryExpression expr, boolean verify) throws XQueryException { 3480 if (schemaNodes == null || schemaNodes.isEmpty()) 3481 return null; 3482 3483 QType retQType = null; 3484 ArrayList list = new ArrayList(schemaNodes.size()); 3485 QType tmpQType = null; 3486 for (int i = 0; i < schemaNodes.size(); i++) { 3487 TypedXTreeNode typedXTreeNode = (TypedXTreeNode) schemaNodes.get(i); 3488 Declaration decl = typedXTreeNode.getDeclaration(); 3489 if (decl == null) { 3490 if (typedXTreeNode.getLocalName() != null) { 3491 if (typedXTreeNode.getChildren() == null) { 3493 SimpleType type = context.getSchemaManager().getAnySimpleType(); 3494 tmpQType = new QTypeAttribute(new QName(typedXTreeNode.getNamespace(), null, typedXTreeNode.getLocalName(), null, null), type, QType.computeOccurence(occurence, QType.OCC_0_1)); 3495 } else 3496 tmpQType = new QTypeElement(new QName(typedXTreeNode.getNamespace(), null, typedXTreeNode.getLocalName(), null, null), getType(SC_ANYTYPE), QType.OCC_0_N); 3497 } else { 3498 } 3501 } else 3502 tmpQType = getQTypeFromDeclaration(decl, occurence); 3503 list.add(tmpQType); 3504 } 3505 if (list.isEmpty()) 3506 if (verify) 3507 throw new TypeException("Could not find declaration(s) of expression '" + expr + "'"); 3508 else 3509 return null; 3510 else if (list.size() == 1) 3511 return (QType) list.get(0); 3512 return makeUnion(list); 3513 } 3514 3515 private QType getQTypeFromDeclaration(Declaration decl, byte occurence) throws XQueryException { 3516 if (decl == null) 3517 return null; 3518 QType retQType = null; 3520 QName qname = new QName(decl.getNamespace(), null, decl.getName(), null, null); 3521 if (decl instanceof AttributeDeclaration) 3522 retQType = new QTypeAttribute(qname, (AttributeDeclaration) decl, (SimpleType) decl.getType(), QType.computeOccurence(occurence, (((AttributeDeclaration) decl).getUse() == AttributeDeclaration.REQUIRED) ? QType.OCC_1_1 : QType.OCC_0_1)); 3523 if (decl instanceof ElementDeclaration) { 3524 byte elemOccurence = QType.OCC_1_1; 3525 ElementDeclaration eltDecl = (ElementDeclaration) decl; 3526 SchemaScope scopeType = eltDecl.getScope(); if (scopeType != null && scopeType instanceof ComplexType) { 3528 int size[] = ((ComplexType) scopeType).getDeclarationOccurrence(eltDecl.getNamespace(), eltDecl.getName()); 3529 elemOccurence = QType.getOccurence(size[0], size[1]); 3530 } 3531 retQType = new QTypeElement(qname, decl.getType(), QType.computeOccurence(occurence, elemOccurence)); 3532 } 3537 return retQType; 3538 } 3539 3540 private QType makeUnion(ArrayList list) throws XQueryException { 3541 if (list == null || list.isEmpty()) 3542 return null; 3543 for (int i = 0; i < list.size(); i++) { 3545 QType qtypei = (QType) list.get(i); 3546 Type typei = qtypei.getType(); 3547 if (typei != null) { 3548 } 3549 } 3550 for (int i = 0; i < list.size() - 1; i++) { 3551 QType qtypei = (QType) list.get(i); 3552 for (int j = i + 1; j < list.size(); j++) { 3553 if (qtypei.equals((QType) list.get(j))) { 3554 list.remove(j); 3555 j--; 3556 } 3557 } 3558 } 3559 if (list.size() == 1) 3560 return (QType) list.get(0); 3561 return new QTypeUnion(list); 3562 } 3563 3564 private QTypeElement buildQTypeElementFromSubElements(XQueryExpression name, Set allElements) throws XQueryException { 3565 int size = allElements.size(); 3566 ElementTools eTools = new ElementTools(size, name); 3567 if (size == 0) 3569 return new QTypeElement(name, getType(SC_ANYTYPE)); 3570 ComplexType complexType = new ComplexType(this.typingschema, null, null); 3571 3573 SequenceModelGroup sequenceModel = new SequenceModelGroup(); 3574 QTypeElement qte = null; 3575 for (Iterator it = allElements.iterator();it.hasNext();) { 3577 QType qtype = ((XQueryExpression) it.next()).getQType(); 3578 int subclass = qtype.getSubClass(); 3579 if (subclass == QType.ATOM) { 3580 if (size == 1) 3582 return new QTypeElement(name, qtype.getSimpleType() == null ? getType(SC_ANYTYPE) : qtype.getSimpleType()); 3583 else 3584 buildQTypeAtom(eTools, qtype); 3585 } else if (subclass == QType.TEXT) { 3586 if (size == 1) 3587 return new QTypeElement(name, qtype.getSimpleType() == null ? getType(SC_ANYTYPE) : qtype.getSimpleType()); 3588 else 3589 buildQTypeText(eTools, qtype); 3590 } else if (subclass == QType.ATTRIBUTE) { 3591 buildQTypeAttribute(eTools, (QTypeAttribute)qtype, complexType); 3592 } else if (subclass == QType.ELEMENT) { 3593 buildQTypeElement(eTools, qtype, complexType, sequenceModel, qtype.getMinOccurence() == 1, qtype.isMultiple()); 3594 } else if (subclass == QType.UNION) { 3595 buildQTypeUnion(eTools, qtype, complexType, sequenceModel); 3596 } else if (subclass == QType.SEQUENCE) { 3597 qte = buildQTypeSequence(eTools, qtype, complexType, sequenceModel); 3598 if (qte != null) 3599 return qte; 3600 } 3601 } 3602 if (eTools.getCountAttribute() == 0 && eTools.getSize() == eTools.getCountSimpleType()) 3604 return new QTypeElement(name, (SimpleType) getType(SC_STRING)); 3605 if ((eTools.getCountAttribute() == eTools.getSize() - eTools.getCountSimpleType()) && (eTools.getMixed())) { 3607 complexType.setBaseType((SimpleType) getType(SC_STRING)); 3608 complexType.setExtension(true); 3609 complexType.setContentModel(new ContentModel((SimpleType) getType(SC_STRING))); 3610 } 3611 else if ((eTools.getCountAttribute() == eTools.getSize() - 1) && (eTools.getMixed())) { 3613 complexType.setBaseType(eTools.getSimpleType()); 3614 complexType.setExtension(true); 3615 complexType.setContentModel(new ContentModel(eTools.getSimpleType())); 3616 3617 } 3618 else { 3620 ContentModel contentModel = new ContentModel(); 3621 contentModel.setModel(new Particle(sequenceModel)); 3622 if (eTools.getMixed()) 3623 contentModel.setContentType(SchemaConstants.MIXED); 3624 else 3625 contentModel.setContentType(SchemaConstants.ELEMENT_ONLY); 3626 complexType.setContentModel(contentModel); 3627 } 3628 return new QTypeElement(name, complexType); 3632 } 3633 3634 private void buildQTypeAtom(ElementTools eTools, QType qtype) throws XQueryException { 3635 eTools.setSimpleType(qtype.getSimpleType()); 3636 eTools.setMixed(true); 3637 eTools.incCountSimpleType(); 3638 eTools.incCountSimpleList(); 3639 } 3640 3641 private void buildQTypeText(ElementTools eTools, QType qtype) throws XQueryException { 3642 eTools.setSimpleType(qtype.getSimpleType()); 3643 eTools.setMixed(true); 3644 eTools.incCountSimpleType(); 3645 eTools.incCountSimpleList(); 3646 } 3647 3648 private void buildQTypeAttribute(ElementTools eTools, QTypeAttribute qtype, ComplexType complexType) throws XQueryException { 3649 String name = null; 3650 XQueryExpression qname = qtype.getName(); 3651 if (qname instanceof QName) 3652 name = ((QName) qtype.getName()).getName(); 3653 else 3654 name = getTemporaryName(); 3655 if (name.equals("xmlns")) 3657 return; 3658 eTools.incCountAttribute(); 3659 AttributeDeclaration attribute = new AttributeDeclaration(this.typingschema, name, complexType); 3660 attribute.setType(qtype.getSimpleType()); 3661 try { 3662 complexType.register(attribute); 3663 } catch (SchemaException saxe) { 3664 throw new TypeException("Error in register(ElementDeclaration): " + saxe.getMessage()); 3665 } 3666 } 3667 3668 private byte index = 0; 3669 private String getTemporaryName() { 3670 return TEMP_NAME + index++; 3671 } 3672 3673 private void buildQTypeElement(ElementTools eTools, QType qtype, ComplexType complexType, ModelGroup model, boolean hasOne, boolean unbounded) throws XQueryException { 3674 String name = null; 3675 String uri = null; 3676 Schema tmpschema = this.typingschema; 3677 try { 3678 QName qname = (QName) ((QTypeElement) qtype).getName(); 3679 uri = qname.getNameSpace(); 3680 if (uri != null && !uri.equals(STAR)) { 3681 tmpschema = this.typingschemamanager.getSchema(uri); 3682 if (tmpschema == null) { 3683 tmpschema = new Schema(uri, null, typingschemamanager); 3684 try { 3685 typingschemamanager.putSchema(tmpschema); 3686 } catch (SAXException saxe) { 3687 throw new TypeException("Could not add schema to manager"); 3688 } 3689 } 3690 } 3691 name = qname.getName(); 3692 } catch (ClassCastException cce) { 3693 name = "TagDefineInEvaluation"; 3694 } 3695 Particle particle = null; 3696 if (!name.equals(STAR)) { 3697 ElementDeclaration element = null; 3698 element = complexType.getElementDeclaration(uri, name); 3700 if (element == null) { 3701 SchemaScope scope = null; 3702 if (uri != null && !uri.equals(STAR)) { 3703 scope = tmpschema; 3704 element = new ElementDeclaration(tmpschema, name, scope); 3705 element.setQualified(true); 3706 } else { 3707 scope = complexType; 3708 element = new ElementDeclaration(tmpschema, name, scope); 3709 } 3710 element.setType(qtype.getType()); 3711 try { 3712 if (uri != null && !uri.equals(STAR)) 3713 complexType.register(element); 3714 else 3715 scope.register(element); 3716 } catch (SchemaException se) { 3717 throw new XQueryException(se.getMessage()); 3718 } 3719 } else { 3720 element.setType(tmpschema.getType(SC_ANYTYPE)); 3721 3725 } 3726 particle = new Particle(element); 3727 } else { particle = eTools.getWildCard(); 3730 if (particle == null) { 3731 particle = new Particle(new Wildcard(tmpschema,true)); 3732 eTools.addWildCard(particle); 3733 } 3734 } 3735 if (!hasOne) 3736 particle.setMinOccurs(0); 3737 if (unbounded) 3738 particle.setMaxOccursUnbounded(); 3739 model.add(particle); 3740 } 3741 3742 private QTypeElement buildQTypeSequence(ElementTools eTools, QType qtype, ComplexType complexType, SequenceModelGroup sequenceModel) throws XQueryException { 3743 List list = qtype.getList(); 3744 if (list == null) 3745 return null; 3746 int size = list.size(); 3747 QTypeElement qte = null; 3748 for (int i = 0; i < size; i++) { 3749 QType stype = (QType) list.get(i); 3750 int subclass = stype.getSubClass(); 3751 if (subclass == QType.ATOM) { 3752 if (size == 1 && eTools.getSize() == 1) 3754 return new QTypeElement(eTools.getName(), qtype.getSimpleType() == null ? getType(SC_ANYTYPE) : qtype.getSimpleType()); 3755 else 3756 buildQTypeAtom(eTools, stype); 3757 } else if (subclass == QType.TEXT) { 3758 buildQTypeText(eTools, stype); 3759 } else if (subclass == QType.ATTRIBUTE) { 3760 buildQTypeAttribute(eTools, (QTypeAttribute)stype, complexType); 3761 } else if (subclass == QType.ELEMENT) { 3762 buildQTypeElement(eTools, stype, complexType, sequenceModel, stype.getMinOccurence() == 1, stype.isMultiple()); 3763 } else if (subclass == QType.UNION) { 3764 buildQTypeUnion(eTools, stype, complexType, sequenceModel); 3765 } else if (subclass == QType.SEQUENCE) { 3766 qte = buildQTypeSequence(eTools, stype, complexType, sequenceModel); 3767 if (qte != null) 3768 return qte; 3769 } 3770 3771 } 3772 return null; 3773 } 3774 3775 private void buildQTypeUnion(ElementTools eTools, QType qtype, ComplexType complexType, SequenceModelGroup sequenceModel) throws XQueryException { 3776 List list = qtype.getList(); 3777 ChoiceModelGroup choiceModel = null; 3778 for (int i = 0; i < list.size(); i++) { 3779 if (i != 0) 3780 eTools.incSize(); 3781 QType utype = (QType) list.get(i); 3782 int subclass = utype.getSubClass(); 3783 boolean atom = false; 3784 if (subclass == QType.ATOM) { 3785 if (!atom) { 3786 buildQTypeAtom(eTools, utype); 3787 atom = true; 3788 } 3789 } else if (subclass == QType.TEXT) { 3790 buildQTypeText(eTools, utype); 3791 } else if (subclass == QType.ATTRIBUTE) { 3792 buildQTypeAttribute(eTools, (QTypeAttribute)utype, complexType); 3793 } else if (subclass == QType.ELEMENT) { 3794 if (choiceModel == null) 3795 choiceModel = new ChoiceModelGroup(); 3796 buildQTypeElement(eTools, utype, complexType, choiceModel, utype.getMinOccurence() == 1, utype.isMultiple()); 3797 } else if (subclass == QType.SEQUENCE) { 3798 this.buildQTypeSequence(eTools, utype, complexType, sequenceModel); 3799 } else 3800 throw new TypeException("We have not specification for this case (NYI), definition: union { (atom | element | attribute)+ }."); 3801 3802 } 3803 if (choiceModel != null) 3804 sequenceModel.add(new Particle(choiceModel)); 3805 } 3806 3807 private boolean isAnyTypeKind(QType qType) { 3808 Type type = qType.getType(); 3809 if (type != null && type.getNamespace() != null && type.getNamespace().equals(SchemaConstants.XMLSCHEMA_URI) && type.getName() != null && (type.getName().equals(SchemaConstants.ANY_TYPE) || type.getName().equals(SchemaConstants.SIMPLE_UR_TYPE))) 3810 return true; 3811 return false; 3812 } 3813} 3814 | Popular Tags |