1 56 57 package org.jdom.contrib.input.scanner; 58 59 import java.io.IOException ; 60 import java.util.*; 61 62 import org.xml.sax.Attributes ; 63 import org.xml.sax.ContentHandler ; 64 import org.xml.sax.InputSource ; 65 import org.xml.sax.XMLReader ; 66 import org.xml.sax.SAXException ; 67 import org.xml.sax.SAXNotRecognizedException ; 68 import org.xml.sax.SAXNotSupportedException ; 69 import org.xml.sax.helpers.XMLFilterImpl ; 70 71 import org.jdom.*; 72 import org.jdom.DefaultJDOMFactory; 73 import org.jdom.JDOMFactory; 74 import org.jdom.input.SAXBuilder; 75 import org.jdom.input.SAXHandler; 76 77 167 public class ElementScanner extends XMLFilterImpl { 168 169 173 private final Collection listeners = new ArrayList(); 174 175 181 private ParserBuilder parserBuilder = new ParserBuilder(); 182 183 186 private SAXHandler saxHandler = null; 187 188 191 private StringBuffer currentPath = new StringBuffer (); 192 193 198 private Map activeRules = new HashMap(); 199 200 207 public ElementScanner() { 208 super(); 209 } 210 211 214 public ElementScanner(XMLReader parent) { 215 super(parent); 216 } 217 218 222 237 public void addElementListener(ElementListener listener, String pattern) 238 throws JDOMException { 239 if (listener != null) { 240 this.listeners.add(XPathMatcher.newXPathMatcher(pattern, listener)); 241 } 242 else { 243 throw (new JDOMException("Invalid listener object: <null>")); 244 } 245 } 246 247 263 public void removeElementListener(ElementListener listener, String pattern) { 264 if ((listener != null) || (pattern != null)) { 265 for (Iterator i=this.listeners.iterator(); i.hasNext(); ) { 266 XPathMatcher m = (XPathMatcher)(i.next()); 267 268 if (((m.getListener().equals(listener)) || (listener == null)) && 269 ((m.getExpression().equals(pattern)) || (pattern == null))) { 270 i.remove(); 271 } 272 } 273 } 274 } 276 277 287 private Collection getMatchingRules(String path, Attributes attrs) { 288 Collection matchingRules = null; 289 290 for (Iterator i=this.listeners.iterator(); i.hasNext(); ) { 291 XPathMatcher rule = (XPathMatcher)(i.next()); 292 293 if (rule.match(path, attrs)) { 294 if (matchingRules == null) { 295 matchingRules = new ArrayList(); 296 } 297 matchingRules.add(rule); 298 } 299 } 300 return (matchingRules); 301 } 302 303 307 313 public void setFactory(JDOMFactory factory) { 314 this.parserBuilder.setFactory(factory); 315 } 316 317 322 public void setValidation(boolean validate) { 323 this.parserBuilder.setValidation(validate); 324 } 325 326 338 public void setIgnoringElementContentWhitespace(boolean ignoringWhite) { 339 this.parserBuilder.setIgnoringElementContentWhitespace(ignoringWhite); 340 } 341 342 353 public void setExpandEntities(boolean expand) { 354 this.parserBuilder.setExpandEntities(expand); 355 } 356 357 361 365 378 public void setFeature(String name, boolean state) 379 throws SAXNotRecognizedException , SAXNotSupportedException { 380 if (this.getParent() != null) { 381 this.getParent().setFeature(name, state); 382 } 383 this.parserBuilder.setFeature(name, state); 384 } 385 386 399 public void setProperty(String name, Object value) 400 throws SAXNotRecognizedException , SAXNotSupportedException { 401 if (this.getParent() != null) { 402 this.getParent().setProperty(name, value); 403 } 404 this.parserBuilder.setProperty(name, value); 405 } 406 407 431 public void parse(InputSource source) throws IOException , SAXException { 432 this.saxHandler = this.parserBuilder.getContentHandler(); 434 435 this.setParent(this.parserBuilder.getXMLReader( 437 this.getParent(), this.saxHandler)); 438 439 super.parse(source); 443 } 444 445 449 456 public void startDocument() throws SAXException { 457 this.currentPath.setLength(0); 459 this.activeRules.clear(); 460 461 this.saxHandler.startDocument(); 463 super.startDocument(); 464 } 465 466 473 public void endDocument() throws SAXException { 474 this.saxHandler.endDocument(); 476 super.endDocument(); 477 } 478 479 489 public void startPrefixMapping(String prefix, String uri) 490 throws SAXException { 491 this.saxHandler.startPrefixMapping(prefix, uri); 493 super.startPrefixMapping(prefix, uri); 494 } 495 496 505 public void endPrefixMapping(String prefix) throws SAXException { 506 this.saxHandler.endPrefixMapping(prefix); 508 super.endPrefixMapping(prefix); 509 } 510 511 531 public void startElement(String nsUri, String localName, 532 String qName, Attributes attrs) 533 throws SAXException { 534 this.currentPath.append('/').append(localName); 536 537 String eltPath = this.currentPath.substring(0); 539 Collection matchingRules = this.getMatchingRules(eltPath, attrs); 540 if (matchingRules != null) { 541 this.activeRules.put(eltPath, matchingRules); 544 } 545 546 if (this.activeRules.size() != 0) { 548 this.saxHandler.startElement(nsUri, localName, qName, attrs); 549 } 550 super.startElement(nsUri, localName, qName, attrs); 551 } 552 553 570 public void endElement(String nsUri, String localName, String qName) 571 throws SAXException { 572 Element elt = this.saxHandler.getCurrentElement(); 574 575 if (this.activeRules.size() != 0) { 578 this.saxHandler.endElement(nsUri, localName, qName); 579 } 580 581 String eltPath = this.currentPath.substring(0); 583 Collection matchingRules = (Collection)(this.activeRules.remove(eltPath)); 584 if (matchingRules != null) { 585 try { 587 for (Iterator i=matchingRules.iterator(); i.hasNext(); ) { 588 XPathMatcher matcher = (XPathMatcher)(i.next()); 589 590 if (matcher.match(eltPath, elt)) { 591 matcher.getListener().elementMatched(eltPath, elt); 592 } 593 } 594 } 595 catch (JDOMException ex1) { 596 throw (new SAXException (ex1.getMessage(), ex1)); 599 } 600 } 601 this.currentPath.setLength( 603 this.currentPath.length() - (localName.length() + 1)); 604 super.endElement(nsUri, localName, qName); 606 } 607 608 619 public void characters(char[] ch, int start, int length) 620 throws SAXException { 621 if (this.activeRules.size() != 0) { 623 this.saxHandler.characters(ch, start, length); 624 } 625 super.characters(ch, start, length); 626 } 627 628 639 public void ignorableWhitespace(char[] ch, int start, int length) 640 throws SAXException { 641 if (this.activeRules.size() != 0) { 643 this.saxHandler.ignorableWhitespace(ch, start, length); 644 } 645 super.ignorableWhitespace(ch, start, length); 646 } 647 648 659 public void processingInstruction(String target, String data) 660 throws SAXException { 661 if (this.activeRules.size() != 0) { 663 this.saxHandler.processingInstruction(target, data); 664 } 665 super.processingInstruction(target, data); 666 } 667 668 677 public void skippedEntity(String name) throws SAXException { 678 if (this.activeRules.size() != 0) { 680 this.saxHandler.skippedEntity(name); 681 } 682 super.skippedEntity(name); 683 } 684 685 686 690 694 699 private static class ParserBuilder extends SAXBuilder { 700 701 public ParserBuilder() { 702 super(); 703 } 704 705 709 protected SAXHandler createContentHandler() { 710 return (new FragmentHandler(new EmptyDocumentFactory(getFactory()))); 711 } 712 713 717 732 public XMLReader getXMLReader(XMLReader parser, SAXHandler handler) 733 throws SAXException { 734 try { 735 if (parser == null) { 737 parser = this.createParser(); 738 } 739 this.configureParser(parser, handler); 741 742 return (parser); 743 } 744 catch (Exception ex1) { 745 throw (new SAXException (ex1.getMessage(), ex1)); 746 } 747 } 748 749 757 public SAXHandler getContentHandler() throws SAXException { 758 try { 759 SAXHandler handler = this.createContentHandler(); 760 this.configureContentHandler(handler); 761 762 return (handler); 763 } 764 catch (Exception ex1) { 765 throw (new SAXException (ex1.getMessage(), ex1)); 766 } 767 } 768 } 769 770 774 781 private static class FragmentHandler extends SAXHandler { 782 785 public FragmentHandler(JDOMFactory factory) { 786 super(factory); 787 788 this.pushElement(new Element("root", null, null)); 792 } 793 } 794 795 799 805 private static class EmptyDocumentFactory implements JDOMFactory { 806 807 810 private final JDOMFactory wrapped; 811 812 820 public EmptyDocumentFactory(JDOMFactory factory) { 821 this.wrapped = (factory != null)? factory: new DefaultJDOMFactory(); 822 } 823 824 828 public Document document(Element rootElement, DocType docType) { 829 return (new EmptyDocument()); 830 } 831 832 public Document document(Element rootElement, DocType docType, 833 String baseURI) { 834 return (new EmptyDocument()); 835 } 836 837 public Document document(Element rootElement) { 838 return (new EmptyDocument()); 839 } 840 841 845 public Attribute attribute(String name, String value, 846 Namespace namespace) { 847 return(this.wrapped.attribute(name, value, namespace)); 848 } 849 public Attribute attribute(String name, String value, int type, 850 Namespace namespace) { 851 return(this.wrapped.attribute(name, value, type, namespace)); 852 } 853 public Attribute attribute(String name, String value) { 854 return(this.wrapped.attribute(name, value)); 855 } 856 public Attribute attribute(String name, String value, int type) { 857 return(this.wrapped.attribute(name, value, type)); 858 } 859 public CDATA cdata(String text) { 860 return(this.wrapped.cdata(text)); 861 } 862 public Text text(String text) { 863 return(this.wrapped.text(text)); 864 } 865 public Comment comment(String text) { 866 return(this.wrapped.comment(text)); 867 } 868 public DocType docType(String elementName, 869 String publicID, String systemID) { 870 return(this.wrapped.docType(elementName, publicID, systemID)); 871 } 872 public DocType docType(String elementName, String systemID) { 873 return(this.wrapped.docType(elementName, systemID)); 874 } 875 public DocType docType(String elementName) { 876 return(this.wrapped.docType(elementName)); 877 } 878 public Element element(String name, Namespace namespace) { 879 return(this.wrapped.element(name, namespace)); 880 } 881 public Element element(String name) { 882 return(this.wrapped.element(name)); 883 } 884 public Element element(String name, String uri) { 885 return(this.wrapped.element(name, uri)); 886 } 887 public Element element(String name, String prefix, String uri) { 888 return(this.wrapped.element(name, prefix, uri)); 889 } 890 public ProcessingInstruction processingInstruction(String target, 891 Map data) { 892 return(this.wrapped.processingInstruction(target, data)); 893 } 894 public ProcessingInstruction processingInstruction(String target, 895 String data) { 896 return(this.wrapped.processingInstruction(target, data)); 897 } 898 public EntityRef entityRef(String name) { 899 return(this.wrapped.entityRef(name)); 900 } 901 public EntityRef entityRef(String name, 902 String publicID, String systemID) { 903 return(this.wrapped.entityRef(name, publicID, systemID)); 904 } 905 public EntityRef entityRef(String name, String systemID) { 906 return(this.wrapped.entityRef(name, systemID)); 907 } 908 909 public void addContent(Parent parent, Content c) { 910 if (parent instanceof Element) { 911 ((Element) parent).addContent(c); 912 } 913 else { 914 ((Document) parent).addContent(c); 915 } 916 } 917 918 public void setAttribute(Element element, Attribute a) { 919 element.setAttribute(a); 920 } 921 922 public void addNamespaceDeclaration(Element element, Namespace additional) { 923 element.addNamespaceDeclaration(additional); 924 } 925 926 927 } 928 929 933 942 private static class EmptyDocument extends Document { 943 944 947 public EmptyDocument() { 948 super(); 949 } 950 951 955 public Document setRootElement(Element root) { return(this); } 956 public Document addContent(Comment comment) { return(this); } 957 public Document addContent(ProcessingInstruction pi) { return(this); } 958 public Document setContent(List newContent) { return(this); } 959 public Document setDocType(DocType docType) { return(this); } 960 } 961 } 962 963 | Popular Tags |