1 22 23 package org.xquark.schema.validation; 24 25 import java.net.URL ; 26 import java.util.*; 27 28 import org.xml.sax.InputSource ; 29 import org.xml.sax.SAXException ; 30 import org.xml.sax.XMLReader ; 31 import org.xquark.schema.*; 32 import org.xquark.util.NamespaceContext; 33 34 public class SchemaValidationContext 35 extends DefaultSchemaLocator 36 implements NamespaceContext, PSVInfoSetProvider { 37 private static final String RCSRevision = "$Revision: 1.5 $"; 38 private static final String RCSName = "$Name: $"; 39 40 private SchemaManager manager; 41 private NamespaceContext nsContext = null; 42 private ArrayList infoset = new ArrayList(32); 43 private int level = 0; 44 private int validationContext = -1; 45 private HashSet IDSet = new HashSet(); 46 private HashSet pendingRefs = new HashSet(); 47 48 private boolean bLoadSchemaFromNamespace = false; 50 51 54 55 public SchemaValidationContext() { 56 this(new SchemaManager()); 57 } 58 59 public SchemaValidationContext(SchemaManager manager) { 60 this.manager = manager; 61 reset(null); 62 } 63 64 public void setLoadSchemaFromNamespace(boolean flag) { 65 bLoadSchemaFromNamespace = flag; 66 } 67 68 public boolean isLoadSchemaFromNamespace() { 69 return bLoadSchemaFromNamespace; 70 } 71 72 public InputSource resolveLocation(String namespace, URL location) { 73 if (!bLoadSchemaFromNamespace && location.toString().equals(namespace)) 74 return null; 75 else 76 return super.resolveLocation(namespace, location); 77 } 78 79 public XMLReader getSchemaReader() throws SAXException { 80 SchemaValidationContext context = new SchemaValidationContext(); 83 ValidatingSchemaFilter filter = 84 new ValidatingSchemaFilter(super.getSchemaReader(), context, true); 85 return filter; 86 } 88 89 public ElementPSVInfoset getCurrentInfoset() { 90 return getInfoset(level); 91 } 92 93 public ElementPSVInfoset getParentInfoset() { 94 return getInfoset(level - 1); 95 } 96 97 public ElementPSVInfoset getInfoset(ElementDeclaration decl) { 98 for (int i = level; i >= 0; i--) { 99 ElementPSVInfoset result = (ElementPSVInfoset) infoset.get(i); 100 if (result.getDeclaration() == decl) 101 return result; 102 } 103 return null; 104 } 105 106 public ElementPSVInfoset getInfoset(int index) { 107 if (index < 0 || index > level) 108 return null; 109 return (ElementPSVInfoset) infoset.get(index); 110 } 111 112 public SchemaManager getSchemaManager() { 113 return manager; 114 } 115 116 119 public String getNamespaceURI(String prefix) { 120 return nsContext != null ? nsContext.getNamespaceURI(prefix) : null; 121 } 122 123 126 public Collection getNamespaceURIs() { 127 return nsContext != null ? nsContext.getNamespaceURIs() : null; 128 } 129 130 133 public String getPrefix(String uri) { 134 return nsContext != null ? nsContext.getPrefix(uri) : null; 135 } 136 137 140 public Collection getPrefixes() { 141 return nsContext != null ? nsContext.getPrefixes() : null; 142 } 143 144 147 public Collection getPrefixes(String uri) { 148 return nsContext != null ? nsContext.getPrefixes(uri) : null; 149 } 150 151 154 public List getDeclaredPrefixes() { 155 return nsContext != null ? nsContext.getDeclaredPrefixes() : null; 156 } 157 158 160 void reset(NamespaceContext nc) { 161 nsContext = nc; 162 level = 0; 163 validationContext = 1; 165 IDSet.clear(); 166 pendingRefs.clear(); 167 infoset.clear(); 168 infoset.add(new ElementPSVInfosetImpl()); 169 } 170 171 public void pushElementInfoset(String namespace, String localName) { 172 level++; 173 if (level == infoset.size()) 174 infoset.add(new ElementPSVInfosetImpl()); 175 ((ElementPSVInfosetImpl) getCurrentInfoset()).initialize( 176 namespace, 177 localName); 178 } 179 180 public void popElementInfoset() { 181 ((ElementPSVInfosetImpl) getCurrentInfoset()).cleanup(); 182 level--; 183 188 } 189 190 ElementDeclaration getElementDeclaration() { 191 return (ElementDeclaration) getCurrentInfoset().getDeclaration(); 192 } 193 194 Type getElementType() { 195 return getCurrentInfoset().getType(); 196 } 197 198 public void initElementValidationInfo( 199 ElementDeclaration matchedDecl, 200 Type type, 201 boolean isNil, 202 int process) { 203 ElementPSVInfosetImpl psvi = 204 (ElementPSVInfosetImpl) getCurrentInfoset(); 205 psvi.setField(-1, PSVInfosetImpl.DECLARATION, matchedDecl); 206 psvi.setType(type); 207 psvi.setNil(isNil); 208 if (matchedDecl == null && type == null) { 211 psvi.setField( 212 -1, 213 PSVInfosetImpl.VALIDATION_ATTEMPTED, 214 PSVInfoset.NONE); 215 psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.NOTKNOWN); 216 } else { 217 psvi.setField( 218 -1, 219 PSVInfosetImpl.VALIDATION_ATTEMPTED, 220 PSVInfoset.FULL); 221 psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.VALID); 222 } 223 psvi.setProcess(process); 224 225 233 if (matchedDecl != null 234 && matchedDecl.getIdentityConstraints() != null) { 235 psvi.addIdentityConstraints(matchedDecl.getIdentityConstraints()); 236 } 237 } 238 239 void computeValidationInfo() { 240 ElementPSVInfosetImpl psvi = 241 (ElementPSVInfosetImpl) getCurrentInfoset(); 242 ElementPSVInfosetImpl parentPsvi = 243 (ElementPSVInfosetImpl) getParentInfoset(); 244 if (psvi.getErrorCodes() != null) { 245 psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.INVALID); 246 } 247 if (psvi.getValidity() == PSVInfoset.INVALID 248 || (psvi.getValidity() == PSVInfoset.NOTKNOWN 249 && psvi.getProcess() == SchemaConstants.STRICT)) 250 parentPsvi.setField( 251 -1, 252 PSVInfosetImpl.VALIDITY, 253 PSVInfoset.INVALID); 254 if (psvi.getValidationAttempted() 255 != parentPsvi.getValidationAttempted()) 256 parentPsvi.setField( 257 -1, 258 PSVInfosetImpl.VALIDATION_ATTEMPTED, 259 PSVInfoset.PARTIAL); 260 } 261 262 public int addAttributePSVI( 263 String namespace, 264 String localName, 265 AttributeDeclaration attrDecl, 266 boolean strict) { 267 ElementPSVInfosetImpl psvi = 268 (ElementPSVInfosetImpl) getCurrentInfoset(); 269 int index = psvi.addAttribute(namespace, localName, attrDecl); 270 if (attrDecl == null) { 271 psvi.setField( 272 index, 273 PSVInfosetImpl.VALIDATION_ATTEMPTED, 274 PSVInfoset.NONE); 275 psvi.setField(index, PSVInfosetImpl.VALIDITY, PSVInfoset.NOTKNOWN); 276 if (psvi.getValidationAttempted() != PSVInfoset.NONE) 277 psvi.setField( 278 -1, 279 PSVInfosetImpl.VALIDATION_ATTEMPTED, 280 PSVInfoset.PARTIAL); 281 if (strict) 282 psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.INVALID); 283 } else { 284 psvi.setField( 285 index, 286 PSVInfosetImpl.VALIDATION_ATTEMPTED, 287 PSVInfoset.FULL); 288 psvi.setField(index, PSVInfosetImpl.VALIDITY, PSVInfoset.VALID); 289 if (psvi.getValidationAttempted() != PSVInfoset.FULL) 290 psvi.setField( 291 -1, 292 PSVInfosetImpl.VALIDATION_ATTEMPTED, 293 PSVInfoset.PARTIAL); 294 } 295 return index; 296 } 297 298 void computeAttributeValidationInfo(int index) { 299 ElementPSVInfosetImpl psvi = 300 (ElementPSVInfosetImpl) getCurrentInfoset(); 301 if (psvi.getField(index, PSVInfosetImpl.SCHEMA_ERROR_CODES) != null) { 302 psvi.setField(index, PSVInfosetImpl.VALIDITY, PSVInfoset.INVALID); 303 psvi.setField(-1, PSVInfosetImpl.VALIDITY, PSVInfoset.INVALID); 304 } 305 } 306 307 void addErrorCodes(int attrIndex, SchemaException ex) { 308 ElementPSVInfosetImpl psvi = 309 (ElementPSVInfosetImpl) getCurrentInfoset(); 310 psvi.addErrorCodes(attrIndex, ex); 311 } 312 313 public void setMemberType(int attrIndex, Type memberType) { 314 ((ElementPSVInfosetImpl) getCurrentInfoset()).setField( 315 attrIndex, 316 PSVInfosetImpl.MEMBER_TYPE, 317 memberType); 318 } 319 320 public void setNormalizedValue(int attrIndex, String normalizedValue) { 321 ((ElementPSVInfosetImpl) getCurrentInfoset()).setField( 322 attrIndex, 323 PSVInfosetImpl.SCHEMA_NORMALIZED_VALUE, 324 normalizedValue); 325 } 326 327 public void setActualValue(int attrIndex, Object actualValue) { 328 ((ElementPSVInfosetImpl) getCurrentInfoset()).setField( 329 attrIndex, 330 PSVInfosetImpl.SCHEMA_ACTUAL_VALUE, 331 actualValue); 332 } 333 334 void setNotation(NotationDeclaration notation) { 335 ((ElementPSVInfosetImpl) getCurrentInfoset()).setNotation(notation); 336 } 337 338 void setSchemaSpecified(int attrIndex, boolean schema) { 339 if (schema) 340 ((ElementPSVInfosetImpl) getCurrentInfoset()).setField( 341 attrIndex, 342 PSVInfosetImpl.SCHEMA_SPECIFIED, 343 PSVInfoset.SCHEMA); 344 else 345 ((ElementPSVInfosetImpl) getCurrentInfoset()).setField( 346 attrIndex, 347 PSVInfosetImpl.SCHEMA_SPECIFIED, 348 PSVInfoset.INFOSET); 349 } 350 351 void checkKeyValue(Object actualValue) throws SchemaException { 352 ElementPSVInfosetImpl psvi = 353 (ElementPSVInfosetImpl) getCurrentInfoset(); 354 psvi.checkKeyValue(actualValue); 355 checkIDValue(psvi.getType(), actualValue); 356 } 357 358 void checkKeyValue(AttributeDeclaration decl, Object actualValue) 359 throws SchemaException { 360 ((ElementPSVInfosetImpl) getCurrentInfoset()).checkKeyValue( 361 decl, 362 actualValue); 363 checkIDValue(decl.getType(), actualValue); 364 } 365 366 void checkIdentityConstraints() throws SchemaException { 368 ((ElementPSVInfosetImpl) getCurrentInfoset()) 369 .checkIdentityConstraints(); 370 checkPendingIDRefs(); 371 } 372 373 private void checkIDValue(Type type, Object value) throws SchemaException { 374 if (type != null) { 375 if (type.isDerivedFrom(manager.getIDType())) { 376 pendingRefs.remove(value); 377 if (!IDSet.add(value)) { 378 throw idException( 379 new SchemaException("cvc-id.2", (Object ) value)); 380 } 381 } else if (type.isDerivedFrom(manager.getIDREFType())) { 382 if (!IDSet.contains(value)) 383 pendingRefs.add(value); 384 } else if (type.isDerivedFrom(manager.getIDREFSType())) { 385 List refList = (List)value; 386 for (int i = 0; i < refList.size(); i++) { 387 Object ref = refList.get(i); 388 if (!IDSet.contains(ref)) 389 pendingRefs.add(ref); 390 } 391 } 392 } 393 } 394 395 private void checkPendingIDRefs() throws SchemaException { 396 if (level == validationContext && pendingRefs.size() > 0) 397 throw idException(new SchemaException("cvc-id.1", pendingRefs)); 398 } 399 400 private SchemaException idException(SchemaException se) { 401 SchemaException result = 402 new SchemaException("cvc-elt.7", getValidationRoot(), se); 403 ElementPSVInfosetImpl rootPsvi = 404 (ElementPSVInfosetImpl) getInfoset(validationContext); 405 rootPsvi.addErrorCodes(-1, result); 406 return result; 407 } 408 409 private SchemaException idException(List exceptions) { 410 SchemaException result = 411 new SchemaException("cvc-elt.7", getValidationRoot(), exceptions); 412 ElementPSVInfosetImpl rootPsvi = 413 (ElementPSVInfosetImpl) getInfoset(validationContext); 414 rootPsvi.addErrorCodes(-1, result); 415 return result; 416 } 417 418 private ElementDeclaration getValidationRoot() { 419 if (validationContext == -1) 420 return null; 421 return (ElementDeclaration) 422 ((ElementPSVInfosetImpl) getInfoset(validationContext)) 423 .getDeclaration(); 424 } 425 426 public static abstract class PSVInfosetImpl implements PSVInfoset { 427 protected static final int NAMESPACE = 0; 428 protected static final int LOCAL_NAME = 1; 429 public static final int DECLARATION = 2; 430 protected static final int SCHEMA_ERROR_CODES = 3; 431 protected static final int SCHEMA_SPECIFIED = 4; 432 public static final int SCHEMA_NORMALIZED_VALUE = 5; 433 protected static final int MEMBER_TYPE = 6; 434 protected static final int VALIDITY = 7; 435 protected static final int VALIDATION_ATTEMPTED = 8; 436 public static final int SCHEMA_ACTUAL_VALUE = 9; 437 protected static final int NFIELDS = 10; 438 protected static final ArrayList EMPTY; 439 static { 440 EMPTY = new ArrayList(NFIELDS); 441 for (int i = 0; i < NFIELDS; i++) 442 EMPTY.add(null); 443 } 444 445 public String getNamespaceURI() { 446 return (String ) getField(NAMESPACE); 447 } 448 449 public String getLocalName() { 450 return (String ) getField(LOCAL_NAME); 451 } 452 453 public Declaration getDeclaration() { 454 return (Declaration) getField(DECLARATION); 455 } 456 457 public Type getType() { 458 Declaration decl = getDeclaration(); 459 if (decl == null) 460 return null; 461 return decl.getType(); 462 } 463 464 public String getNormalizedValue() { 465 return (String ) getField(SCHEMA_NORMALIZED_VALUE); 466 } 467 468 public Object getActualValue() { 469 return getField(SCHEMA_ACTUAL_VALUE); 470 } 471 472 public List getErrorCodes() { 473 return (List) getField(SCHEMA_ERROR_CODES); 474 } 475 476 public String getSpecified() { 477 return (String ) getField(SCHEMA_SPECIFIED); 478 } 479 480 public String getSchemaDefault() { 481 Declaration decl = getDeclaration(); 482 if (decl == null) 483 return null; 484 return decl.getDefaultValue(); 485 } 486 487 public SimpleType getValidatingMemberType() { 488 return (SimpleType) getField(MEMBER_TYPE); 489 } 490 491 public String getValidity() { 492 return (String ) getField(VALIDITY); 493 } 494 495 public String getValidationAttempted() { 496 return (String ) getField(VALIDATION_ATTEMPTED); 497 } 498 499 public abstract ElementPSVInfoset getValidationContext(); 500 501 abstract Object getField(int field); 502 } 503 504 public class ElementPSVInfosetImpl 505 extends PSVInfosetImpl 506 implements ElementPSVInfoset { 507 private static final String RCSRevision = "$Revision: 1.5 $"; 508 private static final String RCSName = "$Name: $"; 509 private Type elementType = null; 510 private boolean nilElement = false; 511 private NotationDeclaration notation = null; 512 private ArrayList fields; 513 private int process = SchemaConstants.STRICT; 514 private HashMap bindingsTable = null; 515 private List references = null; 516 private List filters = null; 517 private List selectors = null; 518 519 public ElementPSVInfosetImpl() { 520 fields = new ArrayList(5 * NFIELDS); 521 fields.addAll(EMPTY); 522 } 523 524 public Type getType() { 525 return elementType; 526 } 527 528 public boolean isNil() { 529 return nilElement; 530 } 531 532 public int getAttributeCount() { 533 return (fields.size() / NFIELDS) - 1; 534 } 535 536 public int getAttributeIndex(String namespace, String localName) { 537 if (namespace != null && namespace.length() == 0) 538 namespace = null; 539 for (int i = 0; i < getAttributeCount(); i++) { 540 String ns = (String ) getField(i, NAMESPACE); 541 String name = (String ) getField(i, LOCAL_NAME); 542 if (localName.equals(name) 543 && ((namespace == null && ns == null) 544 || (namespace != null && namespace.equals(ns)))) 545 return i; 546 } 547 return -1; 548 } 549 550 public ElementPSVInfoset getValidationContext() { 551 return getInfoset(validationContext); 552 } 553 554 public PSVInfoset getAttributePSVInfoset(int index) { 555 if (index < 0) 556 return null; 557 return new ElementPSVInfosetImpl.AttributePSVInfosetImpl(index); 558 } 559 560 public Collection getIdentityConstraintBindings() { 561 return bindingsTable.values(); 562 } 563 564 public NotationDeclaration getNotation() { 565 return notation; 566 } 567 568 public Collection getSchemas() { 569 ElementPSVInfoset root = getValidationContext(); 570 if (this != root) 571 return null; 572 return manager.getSchemas(); 573 } 574 575 578 public String getNamespaceURI(String prefix) { 579 return nsContext != null ? nsContext.getNamespaceURI(prefix) : null; 580 } 581 582 585 public Collection getNamespaceURIs() { 586 return nsContext != null ? nsContext.getNamespaceURIs() : null; 587 } 588 589 592 public String getPrefix(String uri) { 593 return nsContext != null ? nsContext.getPrefix(uri) : null; 594 } 595 596 599 public Collection getPrefixes() { 600 return nsContext != null ? nsContext.getPrefixes() : null; 601 } 602 603 606 public Collection getPrefixes(String uri) { 607 return nsContext != null ? nsContext.getPrefixes(uri) : null; 608 } 609 610 613 public List getDeclaredPrefixes() { 614 return nsContext != null ? nsContext.getDeclaredPrefixes() : null; 615 } 616 617 Object getField(int field) { 618 return getField(-1, field); 619 } 620 621 public void initialize(String namespace, String localName) { 622 elementType = null; 623 nilElement = false; 624 fields.clear(); 625 fields.addAll(EMPTY); 626 setField(-1, NAMESPACE, namespace); 627 setField(-1, LOCAL_NAME, localName); 628 HashMap prevBindings = 629 ((ElementPSVInfosetImpl) getParentInfoset()).getBindingsTable(); 630 if (prevBindings != null) 631 bindingsTable = (HashMap) prevBindings.clone(); 632 List prevFilters = 633 ((ElementPSVInfosetImpl) getParentInfoset()).getFilters(); 634 if (prevFilters != null) { 635 Iterator it = prevFilters.iterator(); 636 while (it.hasNext()) { 637 XPathFilter xf = (XPathFilter) it.next(); 638 if (xf.nextElement(namespace, localName)) { 639 addFilter(xf); 640 if (xf.isDone() && xf instanceof SelectorFilter) { 641 IdentityConstraintBinding binding = 642 ((SelectorFilter) xf).getBinding(); 643 addSelector( 644 new ElementPSVInfosetImpl.Selector(binding)); 645 } 646 } 647 } 648 } 649 } 650 651 public void cleanup() { 652 if (filters != null) { 653 Iterator it = filters.iterator(); 654 while (it.hasNext()) { 655 XPathFilter xf = (XPathFilter) it.next(); 656 xf.decrementIndex(); 657 } 658 } 659 HashMap prevBindings = 660 ((ElementPSVInfosetImpl) getParentInfoset()).getBindingsTable(); 661 if (prevBindings != null) { 662 Iterator it = bindingsTable.entrySet().iterator(); 663 while (it.hasNext()) { 664 Map.Entry entry = (Map.Entry) it.next(); 665 IdentityConstraintBinding prev = 666 (IdentityConstraintBinding) prevBindings.get( 667 entry.getKey()); 668 if (prev != null && entry.getValue() != prev) { 669 prev.propagateEntries( 670 (IdentityConstraintBinding) entry.getValue()); 671 } 672 } 673 } 674 filters = null; 675 selectors = null; 676 bindingsTable = null; 677 references = null; 678 fields.clear(); 679 } 680 681 int addAttribute( 682 String namespace, 683 String localName, 684 AttributeDeclaration attrDecl) { 685 int index = getAttributeCount(); 686 fields.addAll(EMPTY); 687 setField(index, NAMESPACE, namespace); 688 setField(index, LOCAL_NAME, localName); 689 setField(index, DECLARATION, attrDecl); 690 return index; 691 } 692 693 public void setType(Type type) { 694 elementType = type; 695 } 696 697 void setNil(boolean isNil) { 698 nilElement = isNil; 699 } 700 701 void setNotation(NotationDeclaration notation) { 702 this.notation = notation; 703 } 704 705 public void setField(int index, int field, Object value) { 706 int i = (index + 1) * NFIELDS + field; 707 try { 708 fields.set(i, value); 709 } catch (IndexOutOfBoundsException e) { 710 throw new IndexOutOfBoundsException ("index = " + index); 711 } 712 } 713 714 Object getField(int index, int field) { 715 int i = (index + 1) * NFIELDS + field; 716 try { 717 return fields.get(i); 718 } catch (IndexOutOfBoundsException e) { 719 throw new IndexOutOfBoundsException ("index = " + index); 720 } 721 } 722 723 int getProcess() { 724 return process; 725 } 726 727 void setProcess(int process) { 728 this.process = process; 729 } 730 731 List getSelectors() { 732 return selectors; 733 } 734 735 void addSelector(ElementPSVInfosetImpl.Selector selector) { 736 if (selectors == null) 737 selectors = new ArrayList(); 738 selectors.add(selector); 739 Iterator it = selector.getFields().iterator(); 740 int index = 0; 741 while (it.hasNext()) { 742 Iterator it2 = ((List) it.next()).iterator(); 743 while (it2.hasNext()) { 744 XPathExpr xpath = (XPathExpr) it2.next(); 745 addFilter(new FieldFilter(xpath, selector, index)); 746 } 747 index++; 748 } 749 } 750 751 List getFilters() { 752 return filters; 753 } 754 755 void addFilter(XPathFilter xi) { 756 if (filters == null) 757 filters = new ArrayList(); 758 filters.add(xi); 759 } 760 761 HashMap getBindingsTable() { 762 return bindingsTable; 763 } 764 765 void addIdentityConstraints(Collection constraints) { 766 Iterator it = constraints.iterator(); 767 while (it.hasNext()) { 768 IdentityConstraint constraint = (IdentityConstraint) it.next(); 769 if (constraint.getReferencedKey() == null) { 770 IdentityConstraintBinding binding = 771 addIdentityConstraintBinding(constraint); 772 addBindingFilters(binding); 773 } 774 } 775 it = constraints.iterator(); 776 while (it.hasNext()) { 777 IdentityConstraint constraint = (IdentityConstraint) it.next(); 778 IdentityConstraint ref = constraint.getReferencedKey(); 779 if (ref != null) { 780 IdentityConstraintBinding binding = 781 addReferenceBinding(constraint); 782 addBindingFilters(binding); 783 IdentityConstraintBinding refBinding = 784 getIdentityConstraintBinding(ref); 785 if (refBinding == null) { 786 refBinding = addIdentityConstraintBinding(ref); 787 } 788 binding.setReference(refBinding); 789 } 790 } 791 } 792 793 IdentityConstraintBinding addIdentityConstraintBinding(IdentityConstraint constraint) { 794 if (bindingsTable == null) 795 bindingsTable = new HashMap(); 796 IdentityConstraintBinding binding = 797 new IdentityConstraintBinding(constraint); 798 bindingsTable.put(constraint, binding); 799 return binding; 800 } 801 802 IdentityConstraintBinding addReferenceBinding(IdentityConstraint constraint) { 803 if (references == null) 804 references = new ArrayList(); 805 IdentityConstraintBinding binding = 806 new IdentityConstraintBinding(constraint); 807 references.add(binding); 808 return binding; 809 } 810 811 void addBindingFilters(IdentityConstraintBinding binding) { 812 IdentityConstraint constraint = binding.getDefinition(); 813 List xpaths = constraint.getSelector(); 814 Iterator it = xpaths.iterator(); 815 while (it.hasNext()) { 816 SelectorFilter xf = 817 new SelectorFilter((XPathExpr) it.next(), binding); 818 addFilter(xf); 819 if (xf.isDone()) 820 addSelector(new ElementPSVInfosetImpl.Selector(binding)); 821 } 822 } 823 824 IdentityConstraintBinding getIdentityConstraintBinding(IdentityConstraint constraint) { 825 if (bindingsTable == null) 826 return null; 827 return (IdentityConstraintBinding) bindingsTable.get(constraint); 828 } 829 830 void checkKeyValue(Object value) throws SchemaException { 831 if (filters != null) { 832 Iterator it = filters.iterator(); 833 ArrayList exceptions = null; 834 while (it.hasNext()) { 835 try { 836 XPathFilter xf = (XPathFilter) it.next(); 837 if (xf.isDone()) 838 xf.setKeyValue(value); 839 } catch (SchemaException ex) { 840 if (exceptions == null) 841 exceptions = new ArrayList(); 842 exceptions.add(ex); 843 } 844 } 845 if (exceptions != null) 846 throw new SchemaException(exceptions); 847 } 848 } 849 850 void checkKeyValue(AttributeDeclaration decl, Object value) 851 throws SchemaException { 852 if (filters != null) { 853 Iterator it = filters.iterator(); 854 ArrayList exceptions = null; 855 String ns = decl.getNamespace(); 856 String localName = decl.getName(); 857 while (it.hasNext()) { 858 try { 859 XPathFilter xf = (XPathFilter) it.next(); 860 if (xf.nextAttribute(ns, localName)) 861 xf.setKeyValue(value); 862 } catch (SchemaException ex) { 863 if (exceptions == null) 864 exceptions = new ArrayList(); 865 exceptions.add(ex); 866 } 867 } 868 if (exceptions != null) 869 throw new SchemaException(exceptions); 870 } 871 } 872 873 void checkIdentityConstraints() throws SchemaException { 874 ArrayList exceptions = null; 875 boolean nillable = 877 getDeclaration() != null 878 && ((ElementDeclaration) getDeclaration()).isNillable(); 879 boolean complex = 880 getType() != null && getType().getValueType() == null; 881 if (filters != null && (nillable || complex)) { 882 Iterator it = filters.iterator(); 883 while (it.hasNext()) { 884 XPathFilter xf = (XPathFilter) it.next(); 885 if (xf.isDone() && xf instanceof FieldFilter) { 886 IdentityConstraint constraint = 887 ((FieldFilter) xf) 888 .getSelector() 889 .getIdentityConstraint(); 890 if (complex) { 891 if (exceptions == null) 892 exceptions = new ArrayList(); 893 SchemaException se = 894 new SchemaException( 895 "cvc-identity-constraint.3", 896 constraint); 897 exceptions.add( 898 identityConstraintException(constraint, se)); 899 } 900 if (nillable 901 && constraint.getCategory() 902 == IdentityConstraint.CATEGORY_KEY) { 903 if (exceptions == null) 904 exceptions = new ArrayList(); 905 SchemaException se = 906 new SchemaException( 907 "cvc-identity-constraint.4.2.3", 908 constraint); 909 exceptions.add( 910 identityConstraintException(constraint, se)); 911 } 912 } 913 } 914 } 915 if (selectors != null) { 917 Iterator it = selectors.iterator(); 918 while (it.hasNext()) { 919 ElementPSVInfosetImpl.Selector s = 920 (ElementPSVInfosetImpl.Selector) it.next(); 921 IdentityConstraint constraint = s.getIdentityConstraint(); 922 if (s.isSequenceComplete()) { 923 try { 925 s.getBinding().registerEntry(s.getSequence()); 926 } catch (SchemaException se) { 927 if (exceptions == null) 928 exceptions = new ArrayList(); 929 exceptions.add( 930 identityConstraintException(constraint, se)); 931 } 932 } else if ( 933 constraint.getCategory() 934 == IdentityConstraint.CATEGORY_KEY) { 935 if (exceptions == null) 937 exceptions = new ArrayList(); 938 SchemaException ke = null; 939 if (s.isValid()) 940 ke = 941 new SchemaException( 942 null, 943 "key sequence: " + s.getSequence()); 944 SchemaException se = 945 new SchemaException( 946 "cvc-identity-constraint.4.2.1", 947 constraint, 948 ke); 949 exceptions.add( 950 identityConstraintException(constraint, se)); 951 } 952 } 953 } 954 if (references != null) { 955 Iterator it = references.iterator(); 956 while (it.hasNext()) { 957 IdentityConstraintBinding binding = 958 (IdentityConstraintBinding) it.next(); 959 try { 960 binding.checkPendingRefs(); 961 } catch (SchemaException se) { 962 if (exceptions == null) 963 exceptions = new ArrayList(); 964 exceptions.add( 965 identityConstraintException( 966 binding.getDefinition(), 967 se)); 968 } 969 } 970 } 971 if (exceptions != null) 972 throw new SchemaException(exceptions); 973 } 974 975 void addErrorCodes(int attrIndex, SchemaException ex) { 976 ArrayList list = 977 (ArrayList) getField(attrIndex, SCHEMA_ERROR_CODES); 978 if (list == null) { 979 list = new ArrayList(); 980 setField(attrIndex, SCHEMA_ERROR_CODES, list); 981 } 982 addErrorCodes(list, ex); 983 } 984 985 private void addErrorCodes(ArrayList list, SchemaException ex) { 986 list.add(ex.getErrorCode()); 987 List exceptions = ex.getExceptions(); 988 if (exceptions != null) { 989 Iterator it = exceptions.iterator(); 990 while (it.hasNext()) { 991 Exception e = (Exception ) it.next(); 992 if (e instanceof SchemaException) 993 addErrorCodes(list, (SchemaException) e); 994 } 995 } 996 } 997 998 SchemaException identityConstraintException( 999 IdentityConstraint constraint, 1000 SchemaException se) { 1001 ElementDeclaration context = constraint.getContextDeclaration(); 1002 SchemaException result = 1003 new SchemaException("cvc-elt.6", context, se); 1004 ElementPSVInfosetImpl contextPsvi = 1005 (ElementPSVInfosetImpl) getInfoset(context); 1006 contextPsvi.addErrorCodes(-1, result); 1007 return result; 1008 } 1009 1010 SchemaException identityConstraintException( 1011 IdentityConstraint constraint, 1012 List exceptions) { 1013 ElementDeclaration context = constraint.getContextDeclaration(); 1014 SchemaException result = 1015 new SchemaException("cvc-elt.6", context, exceptions); 1016 ElementPSVInfosetImpl contextPsvi = 1017 (ElementPSVInfosetImpl) getInfoset(context); 1018 contextPsvi.addErrorCodes(-1, result); 1019 return result; 1020 } 1021 1022 public PSVInfoset getAttributePSVInfoset( 1023 String namespace, 1024 String localName) { 1025 return getAttributePSVInfoset( 1026 getAttributeIndex(namespace, localName)); 1027 } 1028 1029 class AttributePSVInfosetImpl extends PSVInfosetImpl { 1030 private static final String RCSRevision = "$Revision: 1.5 $"; 1031 private static final String RCSName = "$Name: $"; 1032 1033 private int index; 1034 1035 AttributePSVInfosetImpl(int index) { 1036 this.index = index; 1037 } 1038 1039 public ElementPSVInfoset getValidationContext() { 1040 return getInfoset(validationContext); 1041 } 1042 1043 Object getField(int field) { 1044 return ElementPSVInfosetImpl.this.getField(index, field); 1045 } 1046 } 1047 1048 class Selector { 1049 private static final String RCSRevision = "$Revision: 1.5 $"; 1050 private static final String RCSName = "$Name: $"; 1051 IdentityConstraintBinding binding; 1052 ArrayList keySequence = null; 1053 boolean valid = true; 1054 1055 Selector(IdentityConstraintBinding binding) { 1056 this.binding = binding; 1057 } 1058 1059 IdentityConstraintBinding getBinding() { 1060 return binding; 1061 } 1062 1063 IdentityConstraint getIdentityConstraint() { 1064 return binding.getDefinition(); 1065 } 1066 1067 void setKeyValue(Object value, int index) throws SchemaException { 1068 if (keySequence == null) { 1069 int size = getFields().size(); 1070 keySequence = new ArrayList(size); 1071 for (int i = 0; i < size; i++) 1072 keySequence.add(null); 1073 } 1074 if (keySequence.get(index) != null) { 1075 valid = false; 1076 SchemaException se = 1077 new SchemaException( 1078 "cvc-identity-constraint.3", 1079 getIdentityConstraint(), 1080 new SchemaException( 1081 null, 1082 "key sequence: " + keySequence)); 1083 throw identityConstraintException( 1084 getIdentityConstraint(), 1085 se); 1086 } 1087 keySequence.set(index, value); 1088 } 1089 1090 boolean isValid() { 1091 return valid; 1092 } 1093 1094 List getFields() { 1095 return getIdentityConstraint().getFields(); 1096 } 1097 1098 boolean isSequenceComplete() { 1099 if (!valid) 1100 return false; 1101 if (keySequence == null) 1102 return false; 1103 return !keySequence.contains(null); 1104 } 1105 1106 List getSequence() { 1107 return keySequence; 1108 } 1109 } 1110 } 1111 1112 static class XPathFilter { 1113 private static final String RCSRevision = "$Revision: 1.5 $"; 1114 private static final String RCSName = "$Name: $"; 1115 int index = 0; 1116 XPathExpr xpath; 1117 1118 XPathFilter(XPathExpr xpath) { 1119 this.xpath = xpath; 1120 } 1121 1122 boolean isDone() { 1123 return index == xpath.getStepCount(); 1124 } 1125 1126 boolean nextElement(String namespaceURI, String localName) { 1127 if (isDone()) 1128 return false; 1129 if (xpath.matches(namespaceURI, localName, index, false)) { 1130 index++; 1131 return true; 1132 } 1133 if (index == 0 && xpath.isAnyLevel()) 1134 return true; 1135 return false; 1136 } 1137 1138 boolean nextAttribute(String namespaceURI, String localName) { 1139 if (isDone()) 1140 return false; 1141 if (xpath.matches(namespaceURI, localName, index, true)) { 1142 return true; 1143 } 1144 return false; 1145 } 1146 1147 void decrementIndex() { 1148 if (index > 0) 1149 index--; 1150 } 1151 1152 void setKeyValue(Object value) throws SchemaException { 1153 } 1154 } 1155 1156 static class SelectorFilter extends XPathFilter { 1157 private static final String RCSRevision = "$Revision: 1.5 $"; 1158 private static final String RCSName = "$Name: $"; 1159 IdentityConstraintBinding binding; 1160 1161 SelectorFilter(XPathExpr xpath, IdentityConstraintBinding binding) { 1162 super(xpath); 1163 this.binding = binding; 1164 } 1165 1166 IdentityConstraintBinding getBinding() { 1167 return binding; 1168 } 1169 } 1170 1171 static class FieldFilter extends XPathFilter { 1172 private static final String RCSRevision = "$Revision: 1.5 $"; 1173 private static final String RCSName = "$Name: $"; 1174 ElementPSVInfosetImpl.Selector selector; 1175 int index; 1176 1177 FieldFilter( 1178 XPathExpr xpath, 1179 ElementPSVInfosetImpl.Selector selector, 1180 int index) { 1181 super(xpath); 1182 this.selector = selector; 1183 this.index = index; 1184 } 1185 1186 ElementPSVInfosetImpl.Selector getSelector() { 1187 return selector; 1188 } 1189 1190 void setKeyValue(Object value) throws SchemaException { 1191 selector.setKeyValue(value, index); 1192 } 1193 } 1194 1195} 1196 | Popular Tags |