Clover coverage report - dom4j - 1.5
Coverage timestamp: vr sep 3 2004 20:47:03 GMT+01:00
file stats: LOC: 873   Methods: 55
NCLOC: 443   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
SAXContentHandler.java 64,4% 79,6% 74,5% 74,3%
coverage coverage
 1    /*
 2    * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
 3    *
 4    * This software is open source.
 5    * See the bottom of this file for the licence.
 6    *
 7    * $Id: SAXContentHandler.java,v 1.59 2004/08/06 09:51:50 maartenc Exp $
 8    */
 9   
 10    package org.dom4j.io;
 11   
 12    import java.lang.reflect.Method;
 13    import java.util.ArrayList;
 14    import java.util.HashMap;
 15    import java.util.List;
 16    import java.util.Map;
 17   
 18    import org.dom4j.Branch;
 19    import org.dom4j.Document;
 20    import org.dom4j.DocumentFactory;
 21    import org.dom4j.DocumentType;
 22    import org.dom4j.Element;
 23    import org.dom4j.ElementHandler;
 24    import org.dom4j.Namespace;
 25    import org.dom4j.QName;
 26    import org.dom4j.dtd.AttributeDecl;
 27    import org.dom4j.dtd.ElementDecl;
 28    import org.dom4j.dtd.ExternalEntityDecl;
 29    import org.dom4j.dtd.InternalEntityDecl;
 30    import org.dom4j.tree.AbstractElement;
 31    import org.dom4j.tree.NamespaceStack;
 32    import org.xml.sax.Attributes;
 33    import org.xml.sax.DTDHandler;
 34    import org.xml.sax.EntityResolver;
 35    import org.xml.sax.InputSource;
 36    import org.xml.sax.Locator;
 37    import org.xml.sax.SAXException;
 38    import org.xml.sax.SAXParseException;
 39    import org.xml.sax.ext.DeclHandler;
 40    import org.xml.sax.ext.LexicalHandler;
 41    import org.xml.sax.helpers.DefaultHandler;
 42   
 43    /** <p><code>SAXContentHandler</code> builds a dom4j tree via SAX events.</p>
 44    *
 45    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 46    * @version $Revision: 1.59 $
 47    */
 48    public class SAXContentHandler extends DefaultHandler implements LexicalHandler, DeclHandler, DTDHandler {
 49   
 50    /** The factory used to create new <code>Document</code> instances */
 51    private DocumentFactory documentFactory;
 52   
 53    /** The document that is being built */
 54    private Document document;
 55   
 56    /** stack of <code>Element</code> objects */
 57    private ElementStack elementStack;
 58   
 59    /** stack of <code>Namespace</code> and <code>QName</code> objects */
 60    private NamespaceStack namespaceStack;
 61   
 62    /** the <code>ElementHandler</code> called as the elements are complete */
 63    private ElementHandler elementHandler;
 64   
 65    /** the Locator */
 66    private Locator locator;
 67   
 68    /** The name of the current entity */
 69    private String entity;
 70   
 71    /** Flag used to indicate that we are inside a DTD section */
 72    private boolean insideDTDSection;
 73   
 74    /** Flag used to indicate that we are inside a CDATA section */
 75    private boolean insideCDATASection;
 76   
 77    /** buffer to hold contents of cdata section across multiple characters events */
 78    private StringBuffer cdataText;
 79   
 80    /** namespaces that are available for use */
 81    private Map availableNamespaceMap = new HashMap();
 82   
 83    /** declared namespaces that are not yet available for use */
 84    private List declaredNamespaceList = new ArrayList();
 85   
 86    /** internal DTD declarations */
 87    private List internalDTDDeclarations;
 88   
 89    /** external DTD declarations */
 90    private List externalDTDDeclarations;
 91   
 92    /** The number of namespaces that are declared in the current scope */
 93    private int declaredNamespaceIndex;
 94   
 95    /** The entity resolver */
 96    private EntityResolver entityResolver;
 97   
 98    private InputSource inputSource;
 99   
 100    /** The current element we are on */
 101    private Element currentElement;
 102   
 103    /** Should internal DTD declarations be expanded into a List in the DTD */
 104    private boolean includeInternalDTDDeclarations = false;
 105   
 106    /** Should external DTD declarations be expanded into a List in the DTD */
 107    private boolean includeExternalDTDDeclarations = false;
 108   
 109    /** The number of levels deep we are inside a startEntity / endEntity call */
 110    private int entityLevel;
 111   
 112    /** Are we in an internal DTD subset? */
 113    private boolean internalDTDsubset = false;
 114   
 115    /** Whether adjacent text nodes should be merged */
 116    private boolean mergeAdjacentText = false;
 117   
 118    /** Have we added text to the buffer */
 119    private boolean textInTextBuffer = false;
 120   
 121    /** Should we ignore comments */
 122    private boolean ignoreComments = false;
 123   
 124    /** Buffer used to concatenate text together */
 125    private StringBuffer textBuffer;
 126   
 127    /** Holds value of property stripWhitespaceText. */
 128    private boolean stripWhitespaceText = false;
 129   
 130   
 131  38 public SAXContentHandler() {
 132  38 this(DocumentFactory.getInstance());
 133    }
 134   
 135  38 public SAXContentHandler(DocumentFactory documentFactory) {
 136  38 this(documentFactory, null);
 137    }
 138   
 139  11598 public SAXContentHandler(DocumentFactory documentFactory, ElementHandler elementHandler) {
 140  11598 this(documentFactory, elementHandler, null);
 141  11598 this.elementStack = createElementStack();
 142    }
 143   
 144  11598 public SAXContentHandler(DocumentFactory documentFactory, ElementHandler elementHandler, ElementStack elementStack) {
 145  11598 this.documentFactory = documentFactory;
 146  11598 this.elementHandler = elementHandler;
 147  11598 this.elementStack = elementStack;
 148  11598 this.namespaceStack = new NamespaceStack(documentFactory);
 149    }
 150   
 151    /** @return the document that has been or is being built
 152    */
 153  23316 public Document getDocument() {
 154  23316 if ( document == null ) {
 155  11600 document = createDocument();
 156    }
 157  23316 return document;
 158    }
 159   
 160    // ContentHandler interface
 161    //-------------------------------------------------------------------------
 162   
 163  11598 public void setDocumentLocator(Locator locator) {
 164  11598 this.locator = locator;
 165    }
 166   
 167  38 public void processingInstruction(String target, String data) throws SAXException {
 168  38 if ( mergeAdjacentText && textInTextBuffer ) {
 169  0 completeCurrentTextNode();
 170    }
 171  38 if ( currentElement != null ) {
 172  2 currentElement.addProcessingInstruction(target, data);
 173    }
 174    else {
 175  36 getDocument().addProcessingInstruction(target, data);
 176    }
 177    }
 178   
 179  11738 public void startPrefixMapping(String prefix, String uri) throws SAXException {
 180  11738 namespaceStack.push( prefix, uri );
 181    }
 182   
 183  11738 public void endPrefixMapping(String prefix) throws SAXException {
 184  11738 namespaceStack.pop( prefix );
 185  11738 declaredNamespaceIndex = namespaceStack.size();
 186    }
 187   
 188  11600 public void startDocument() throws SAXException {
 189    //document = createDocument();
 190  11600 document = null;
 191  11600 currentElement = null;
 192   
 193  11600 elementStack.clear();
 194   
 195  11600 if ( (elementHandler != null) &&
 196    (elementHandler instanceof DispatchHandler) ) {
 197  36 elementStack.setDispatchHandler((DispatchHandler)elementHandler);
 198    }
 199   
 200  11600 namespaceStack.clear();
 201  11600 declaredNamespaceIndex = 0;
 202   
 203  11600 if ( mergeAdjacentText && textBuffer == null ) {
 204  8 textBuffer = new StringBuffer();
 205    }
 206  11600 textInTextBuffer = false;
 207    }
 208   
 209  11600 public void endDocument() throws SAXException {
 210  11600 namespaceStack.clear();
 211  11600 elementStack.clear();
 212  11600 currentElement = null;
 213  11600 textBuffer = null;
 214    }
 215   
 216  168742 public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes attributes) throws SAXException {
 217  168742 if ( mergeAdjacentText && textInTextBuffer ) {
 218  2 completeCurrentTextNode();
 219    }
 220   
 221  168742 QName qName = namespaceStack.getQName(
 222    namespaceURI, localName, qualifiedName
 223    );
 224   
 225  168742 Branch branch = currentElement;
 226  168742 if ( branch == null ) {
 227  11600 branch = getDocument();
 228    }
 229  168742 Element element = branch.addElement(qName);
 230   
 231    // add all declared namespaces
 232  168742 addDeclaredNamespaces(element);
 233   
 234    // now lets add all attribute values
 235  168742 addAttributes( element, attributes );
 236   
 237  168742 elementStack.pushElement(element);
 238  168742 currentElement = element;
 239   
 240  168742 entity = null; // fixes bug527062
 241   
 242  168742 if ( elementHandler != null ) {
 243  156 elementHandler.onStart(elementStack);
 244    }
 245    }
 246   
 247  168742 public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
 248  168742 if ( mergeAdjacentText && textInTextBuffer ) {
 249  10 completeCurrentTextNode();
 250    }
 251   
 252  168742 if ( elementHandler != null && currentElement != null ) {
 253  156 elementHandler.onEnd(elementStack);
 254    }
 255  168742 elementStack.popElement();
 256  168742 currentElement = elementStack.peekElement();
 257    }
 258   
 259  190194 public void characters(char[] ch, int start, int end) throws SAXException {
 260  190194 if ( end == 0 ) {
 261  0 return;
 262    }
 263   
 264  190194 if ( currentElement != null ) {
 265  190194 if (entity != null) {
 266  8 if ( mergeAdjacentText && textInTextBuffer ) {
 267  0 completeCurrentTextNode();
 268    }
 269  8 currentElement.addEntity(entity, new String(ch, start, end));
 270  8 entity = null;
 271    }
 272  190186 else if (insideCDATASection) {
 273  106 if ( mergeAdjacentText && textInTextBuffer ) {
 274  2 completeCurrentTextNode();
 275    }
 276  106 cdataText.append(new String(ch, start, end));
 277    }
 278    else {
 279  190080 if ( mergeAdjacentText ) {
 280  50 textBuffer.append(ch, start, end);
 281  50 textInTextBuffer = true;
 282    }
 283    else {
 284  190030 currentElement.addText(new String(ch, start, end));
 285    }
 286    }
 287    }
 288    }
 289   
 290    // ErrorHandler interface
 291    //-------------------------------------------------------------------------
 292   
 293    /** This method is called when a warning occurs during the parsing
 294    * of the document.
 295    * This method does nothing.
 296    */
 297  256 public void warning(SAXParseException exception) throws SAXException {
 298    // ignore warnings by default
 299    }
 300   
 301    /** This method is called when an error is detected during parsing
 302    * such as a validation error.
 303    * This method rethrows the exception
 304    */
 305  0 public void error(SAXParseException exception) throws SAXException {
 306  0 throw exception;
 307    }
 308   
 309    /** This method is called when a fatal error occurs during parsing.
 310    * This method rethrows the exception
 311    */
 312  0 public void fatalError(SAXParseException exception) throws SAXException {
 313  0 throw exception;
 314    }
 315   
 316    // LexicalHandler interface
 317    //-------------------------------------------------------------------------
 318   
 319  22 public void startDTD(String name, String publicId, String systemId) throws SAXException {
 320  22 getDocument().addDocType(name, publicId, systemId);
 321  22 insideDTDSection = true;
 322  22 internalDTDsubset = true;
 323    }
 324   
 325  22 public void endDTD() throws SAXException {
 326  22 insideDTDSection = false;
 327   
 328  22 DocumentType docType = getDocument().getDocType();
 329  22 if ( docType != null ) {
 330  22 if ( internalDTDDeclarations != null ) {
 331  8 docType.setInternalDeclarations( internalDTDDeclarations );
 332    }
 333  22 if ( externalDTDDeclarations != null ) {
 334  6 docType.setExternalDeclarations( externalDTDDeclarations );
 335    }
 336    }
 337   
 338  22 internalDTDDeclarations = null;
 339  22 externalDTDDeclarations = null;
 340    }
 341   
 342  32 public void startEntity(String name) throws SAXException {
 343  32 ++entityLevel;
 344   
 345    // Ignore DTD references
 346  32 entity = null;
 347  32 if (! insideDTDSection ) {
 348  24 if ( ! isIgnorableEntity(name) ) {
 349  10 entity = name;
 350    }
 351    }
 352   
 353    // internal DTD subsets can only appear outside of a
 354    // startEntity/endEntity block
 355    // see the startDTD method in
 356    // http://dom4j.org/javadoc/org/xml/sax/ext/LexicalHandler.html
 357    // or here:-
 358    // http://dom4j.org/javadoc/org/xml/sax/ext/LexicalHandler.html#startDTD(java.lang.String, java.lang.String, java.lang.String)
 359  32 internalDTDsubset = false;
 360    }
 361   
 362  32 public void endEntity(String name) throws SAXException {
 363  32 --entityLevel;
 364  32 entity = null;
 365  32 if ( entityLevel == 0 ) {
 366  32 internalDTDsubset = true;
 367    }
 368   
 369    }
 370   
 371  106 public void startCDATA() throws SAXException {
 372  106 insideCDATASection = true;
 373  106 cdataText = new StringBuffer();
 374    }
 375   
 376  106 public void endCDATA() throws SAXException {
 377  106 insideCDATASection = false;
 378  106 currentElement.addCDATA(cdataText.toString());
 379    }
 380   
 381  822 public void comment(char[] ch, int start, int end) throws SAXException {
 382  822 if (!ignoreComments) {
 383  822 if ( mergeAdjacentText && textInTextBuffer ) {
 384  2 completeCurrentTextNode();
 385    }
 386  822 String text = new String(ch, start, end);
 387  822 if (!insideDTDSection && text.length() > 0) {
 388  816 if ( currentElement != null ) {
 389  780 currentElement.addComment(text);
 390    }
 391    else {
 392  36 getDocument().addComment(text);
 393    }
 394    }
 395    }
 396    }
 397   
 398    // DeclHandler interface
 399    //-------------------------------------------------------------------------
 400   
 401    /**
 402    * Report an element type declaration.
 403    *
 404    * <p>The content model will consist of the string "EMPTY", the
 405    * string "ANY", or a parenthesised group, optionally followed
 406    * by an occurrence indicator. The model will be normalized so
 407    * that all parameter entities are fully resolved and all whitespace
 408    * is removed,and will include the enclosing parentheses. Other
 409    * normalization (such as removing redundant parentheses or
 410    * simplifying occurrence indicators) is at the discretion of the
 411    * parser.</p>
 412    *
 413    * @param name The element type name.
 414    * @param model The content model as a normalized string.
 415    * @exception SAXException The application may raise an exception.
 416    */
 417  12 public void elementDecl(String name, String model) throws SAXException {
 418  12 if ( internalDTDsubset ) {
 419  6 if ( includeInternalDTDDeclarations ) {
 420  6 addDTDDeclaration( new ElementDecl( name, model ) );
 421    }
 422    }
 423    else {
 424  6 if ( includeExternalDTDDeclarations ) {
 425  6 addExternalDTDDeclaration( new ElementDecl( name, model ) );
 426    }
 427    }
 428    }
 429   
 430    /**
 431    * Report an attribute type declaration.
 432    *
 433    * <p>Only the effective (first) declaration for an attribute will
 434    * be reported. The type will be one of the strings "CDATA",
 435    * "ID", "IDREF", "IDREFS", "NMTOKEN", "NMTOKENS", "ENTITY",
 436    * "ENTITIES", a parenthesized token group with
 437    * the separator "|" and all whitespace removed, or the word
 438    * "NOTATION" followed by a space followed by a parenthesized
 439    * token group with all whitespace removed.</p>
 440    *
 441    * <p>Any parameter entities in the attribute value will be
 442    * expanded, but general entities will not.</p>
 443    *
 444    * @param eName The name of the associated element.
 445    * @param aName The name of the attribute.
 446    * @param type A string representing the attribute type.
 447    * @param valueDefault A string representing the attribute default
 448    * ("#IMPLIED", "#REQUIRED", or "#FIXED") or null if
 449    * none of these applies.
 450    * @param value A string representing the attribute's default value,
 451    * or null if there is none.
 452    * @exception SAXException The application may raise an exception.
 453    */
 454  6 public void attributeDecl(String eName,String aName,String type,String valueDefault,String value) throws SAXException {
 455  6 if ( internalDTDsubset ) {
 456  6 if ( includeInternalDTDDeclarations ) {
 457  6 addDTDDeclaration( new AttributeDecl( eName, aName, type, valueDefault, value) );
 458    }
 459    }
 460    else {
 461  0 if ( includeExternalDTDDeclarations ) {
 462  0 addExternalDTDDeclaration( new AttributeDecl( eName, aName, type, valueDefault, value) );
 463    }
 464    }
 465    }
 466   
 467    /**
 468    * Report an internal entity declaration.
 469    *
 470    * <p>Only the effective (first) declaration for each entity
 471    * will be reported. All parameter entities in the value
 472    * will be expanded, but general entities will not.</p>
 473    *
 474    * @param name The name of the entity. If it is a parameter
 475    * entity, the name will begin with '%'.
 476    * @param value The replacement text of the entity.
 477    * @exception SAXException The application may raise an exception.
 478    * @see #externalEntityDecl
 479    * @see org.xml.sax.DTDHandler#unparsedEntityDecl
 480    */
 481  26 public void internalEntityDecl(String name, String value) throws SAXException {
 482  26 if ( internalDTDsubset ) {
 483  26 if ( includeInternalDTDDeclarations ) {
 484  26 addDTDDeclaration( new InternalEntityDecl( name, value ) );
 485    }
 486    }
 487    else {
 488  0 if ( includeExternalDTDDeclarations ) {
 489  0 addExternalDTDDeclaration( new InternalEntityDecl( name, value ) );
 490    }
 491    }
 492    }
 493   
 494    /**
 495    * Report a parsed external entity declaration.
 496    *
 497    * <p>Only the effective (first) declaration for each entity
 498    * will be reported.</p>
 499    *
 500    * @param name The name of the entity. If it is a parameter
 501    * entity, the name will begin with '%'.
 502    * @param publicId The declared public identifier of the entity, or
 503    * null if none was declared.
 504    * @param systemId The declared system identifier of the entity.
 505    * @exception SAXException The application may raise an exception.
 506    * @see #internalEntityDecl
 507    * @see org.xml.sax.DTDHandler#unparsedEntityDecl
 508    */
 509  0 public void externalEntityDecl(String name, String publicId, String systemId) throws SAXException {
 510  0 if ( internalDTDsubset ) {
 511  0 if ( includeInternalDTDDeclarations ) {
 512  0 addDTDDeclaration( new ExternalEntityDecl( name, publicId, systemId ) );
 513    }
 514    }
 515    else {
 516  0 if ( includeExternalDTDDeclarations ) {
 517  0 addExternalDTDDeclaration( new ExternalEntityDecl( name, publicId, systemId ) );
 518    }
 519    }
 520    }
 521   
 522   
 523    // DTDHandler interface
 524    //-------------------------------------------------------------------------
 525   
 526    /**
 527    * Receive notification of a notation declaration event.
 528    *
 529    * <p>It is up to the application to record the notation for later
 530    * reference, if necessary.</p>
 531    *
 532    * <p>At least one of publicId and systemId must be non-null.
 533    * If a system identifier is present, and it is a URL, the SAX
 534    * parser must resolve it fully before passing it to the
 535    * application through this event.</p>
 536    *
 537    * <p>There is no guarantee that the notation declaration will be
 538    * reported before any unparsed entities that use it.</p>
 539    *
 540    * @param name The notation name.
 541    * @param publicId The notation's public identifier, or null if
 542    * none was given.
 543    * @param systemId The notation's system identifier, or null if
 544    * none was given.
 545    * @exception org.xml.sax.SAXException Any SAX exception, possibly
 546    * wrapping another exception.
 547    * @see #unparsedEntityDecl
 548    * @see org.xml.sax.AttributeList
 549    */
 550  0 public void notationDecl(String name,String publicId,String systemId) throws SAXException {
 551    // #### not supported yet!
 552    }
 553   
 554    /**
 555    * Receive notification of an unparsed entity declaration event.
 556    *
 557    * <p>Note that the notation name corresponds to a notation
 558    * reported by the {@link #notationDecl notationDecl} event.
 559    * It is up to the application to record the entity for later
 560    * reference, if necessary.</p>
 561    *
 562    * <p>If the system identifier is a URL, the parser must resolve it
 563    * fully before passing it to the application.</p>
 564    *
 565    * @exception org.xml.sax.SAXException Any SAX exception, possibly
 566    * wrapping another exception.
 567    * @param name The unparsed entity's name.
 568    * @param publicId The entity's public identifier, or null if none
 569    * was given.
 570    * @param systemId The entity's system identifier.
 571    * @param notationName The name of the associated notation.
 572    * @see #notationDecl
 573    * @see org.xml.sax.AttributeList
 574    */
 575  0 public void unparsedEntityDecl(String name,String publicId,String systemId,String notationName) throws SAXException {
 576    // #### not supported yet!
 577    }
 578   
 579   
 580    // Properties
 581    //-------------------------------------------------------------------------
 582  0 public ElementStack getElementStack() {
 583  0 return elementStack;
 584    }
 585   
 586  0 public void setElementStack(ElementStack elementStack) {
 587  0 this.elementStack = elementStack;
 588    }
 589   
 590  0 public EntityResolver getEntityResolver() {
 591  0 return entityResolver;
 592    }
 593   
 594  11560 public void setEntityResolver(EntityResolver entityResolver) {
 595  11560 this.entityResolver = entityResolver;
 596    }
 597   
 598  0 public InputSource getInputSource() {
 599  0 return inputSource;
 600    }
 601   
 602  11560 public void setInputSource(InputSource inputSource) {
 603  11560 this.inputSource = inputSource;
 604    }
 605   
 606    /** @return whether internal DTD declarations should be expanded into the DocumentType
 607    * object or not.
 608    */
 609  0 public boolean isIncludeInternalDTDDeclarations() {
 610  0 return includeInternalDTDDeclarations;
 611    }
 612   
 613    /** Sets whether internal DTD declarations should be expanded into the DocumentType
 614    * object or not.
 615    *
 616    * @param includeInternalDTDDeclarations whether or not DTD declarations should be expanded
 617    * and included into the DocumentType object.
 618    */
 619  11560 public void setIncludeInternalDTDDeclarations(boolean includeInternalDTDDeclarations) {
 620  11560 this.includeInternalDTDDeclarations = includeInternalDTDDeclarations;
 621    }
 622   
 623    /** @return whether external DTD declarations should be expanded into the DocumentType
 624    * object or not.
 625    */
 626  0 public boolean isIncludeExternalDTDDeclarations() {
 627  0 return includeExternalDTDDeclarations;
 628    }
 629   
 630    /** Sets whether DTD external declarations should be expanded into the DocumentType
 631    * object or not.
 632    *
 633    * @param includeExternalDTDDeclarations whether or not DTD declarations should be expanded
 634    * and included into the DocumentType object.
 635    */
 636  11560 public void setIncludeExternalDTDDeclarations(boolean includeExternalDTDDeclarations) {
 637  11560 this.includeExternalDTDDeclarations = includeExternalDTDDeclarations;
 638    }
 639   
 640    /** Returns whether adjacent text nodes should be merged together.
 641    * @return Value of property mergeAdjacentText.
 642    */
 643  0 public boolean isMergeAdjacentText() {
 644  0 return mergeAdjacentText;
 645    }
 646   
 647    /** Sets whether or not adjacent text nodes should be merged
 648    * together when parsing.
 649    * @param mergeAdjacentText New value of property mergeAdjacentText.
 650    */
 651  11560 public void setMergeAdjacentText(boolean mergeAdjacentText) {
 652  11560 this.mergeAdjacentText = mergeAdjacentText;
 653    }
 654   
 655   
 656    /** Sets whether whitespace between element start and end tags should be ignored
 657    *
 658    * @return Value of property stripWhitespaceText.
 659    */
 660  0 public boolean isStripWhitespaceText() {
 661  0 return stripWhitespaceText;
 662    }
 663   
 664    /** Sets whether whitespace between element start and end tags should be ignored.
 665    *
 666    * @param stripWhitespaceText New value of property stripWhitespaceText.
 667    */
 668  11560 public void setStripWhitespaceText(boolean stripWhitespaceText) {
 669  11560 this.stripWhitespaceText = stripWhitespaceText;
 670    }
 671   
 672    /**
 673    * Returns whether we should ignore comments or not.
 674    * @return boolean
 675    */
 676  0 public boolean isIgnoreComments() {
 677  0 return ignoreComments;
 678    }
 679   
 680    /**
 681    * Sets whether we should ignore comments or not.
 682    * @param ignoreComments whether we should ignore comments or not.
 683    */
 684  11560 public void setIgnoreComments(boolean ignoreComments) {
 685  11560 this.ignoreComments = ignoreComments;
 686    }
 687   
 688   
 689    // Implementation methods
 690    //-------------------------------------------------------------------------
 691   
 692    /** If the current text buffer contains any text then create a new
 693    * text node with it and add it to the current element
 694    */
 695  16 protected void completeCurrentTextNode() {
 696  16 if ( stripWhitespaceText ) {
 697  0 boolean whitespace = true;
 698  0 for ( int i = 0, size = textBuffer.length(); i < size; i++ ) {
 699  0 if ( ! Character.isWhitespace( textBuffer.charAt(i) ) ) {
 700  0 whitespace = false;
 701  0 break;
 702    }
 703    }
 704  0 if ( ! whitespace ) {
 705  0 currentElement.addText( textBuffer.toString() );
 706    }
 707    }
 708    else {
 709  16 currentElement.addText( textBuffer.toString() );
 710    }
 711  16 textBuffer.setLength(0);
 712  16 textInTextBuffer = false;
 713    }
 714   
 715    /** @return the current document
 716    */
 717  11600 protected Document createDocument() {
 718  11600 String encoding = getEncoding();
 719  11600 Document document = documentFactory.createDocument(encoding);
 720   
 721    // set the EntityResolver
 722  11600 document.setEntityResolver(entityResolver);
 723  11600 if (inputSource != null) {
 724  11558 document.setName(inputSource.getSystemId());
 725    }
 726   
 727  11600 return document;
 728    }
 729   
 730  11600 private String getEncoding() {
 731  11600 if (locator == null) {
 732  2 return null;
 733    }
 734   
 735    // use reflection to avoid dependency on Locator2
 736    // or other locator implemenations.
 737  11598 try {
 738  11598 Method m = locator.getClass().getMethod("getEncoding", new Class[]{});
 739  14 if (m != null) {
 740  14 return (String) m.invoke(locator, null);
 741    }
 742    } catch (Exception e) {
 743    // do nothing
 744    }
 745   
 746    // couldn't determine encoding, returning null...
 747  11584 return null;
 748    }
 749   
 750    /** a Strategy Method to determine if a given entity name is ignorable
 751    */
 752  24 protected boolean isIgnorableEntity(String name) {
 753  24 return "amp".equals( name )
 754    || "apos".equals( name )
 755    || "gt".equals( name )
 756    || "lt".equals( name )
 757    || "quot".equals( name );
 758    }
 759   
 760   
 761    /** Add all namespaces declared before the startElement() SAX event
 762    * to the current element so that they are available to child elements
 763    * and attributes
 764    */
 765  168742 protected void addDeclaredNamespaces(Element element) {
 766  168742 Namespace elementNamespace = element.getNamespace();
 767  168742 for ( int size = namespaceStack.size(); declaredNamespaceIndex < size; declaredNamespaceIndex++ ) {
 768  11738 Namespace namespace = namespaceStack.getNamespace(declaredNamespaceIndex);
 769    // if ( namespace != elementNamespace ) {
 770  11738 element.add( namespace );
 771    // }
 772    }
 773    }
 774   
 775    /** Add all the attributes to the given elements
 776    */
 777  168742 protected void addAttributes( Element element, Attributes attributes ) {
 778    // XXXX: as an optimisation, we could deduce this value from the current
 779    // SAX parser settings, the SAX namespaces-prefixes feature
 780   
 781  168742 boolean noNamespaceAttributes = false;
 782  168742 if ( element instanceof AbstractElement ) {
 783    // optimised method
 784  168742 AbstractElement baseElement = (AbstractElement) element;
 785  168742 baseElement.setAttributes( attributes, namespaceStack, noNamespaceAttributes );
 786    }
 787    else {
 788  0 int size = attributes.getLength();
 789  0 for ( int i = 0; i < size; i++ ) {
 790  0 String attributeQualifiedName = attributes.getQName(i);
 791  0 if ( noNamespaceAttributes || ! attributeQualifiedName.startsWith( "xmlns" ) ) {
 792  0 String attributeURI = attributes.getURI(i);
 793  0 String attributeLocalName = attributes.getLocalName(i);
 794  0 String attributeValue = attributes.getValue(i);
 795   
 796  0 QName attributeQName = namespaceStack.getAttributeQName(
 797    attributeURI, attributeLocalName, attributeQualifiedName
 798    );
 799  0 element.addAttribute(attributeQName, attributeValue);
 800    }
 801    }
 802    }
 803    }
 804   
 805   
 806    /** Adds an internal DTD declaration to the list of declarations */
 807  38 protected void addDTDDeclaration(Object declaration) {
 808  38 if ( internalDTDDeclarations == null ) {
 809  8 internalDTDDeclarations = new ArrayList();
 810    }
 811  38 internalDTDDeclarations.add( declaration );
 812    }
 813   
 814    /** Adds an external DTD declaration to the list of declarations */
 815  6 protected void addExternalDTDDeclaration(Object declaration) {
 816  6 if ( externalDTDDeclarations == null ) {
 817  6 externalDTDDeclarations = new ArrayList();
 818    }
 819  6 externalDTDDeclarations.add( declaration );
 820    }
 821   
 822  11598 protected ElementStack createElementStack() {
 823  11598 return new ElementStack();
 824    }
 825    }
 826   
 827   
 828   
 829   
 830    /*
 831    * Redistribution and use of this software and associated documentation
 832    * ("Software"), with or without modification, are permitted provided
 833    * that the following conditions are met:
 834    *
 835    * 1. Redistributions of source code must retain copyright
 836    * statements and notices. Redistributions must also contain a
 837    * copy of this document.
 838    *
 839    * 2. Redistributions in binary form must reproduce the
 840    * above copyright notice, this list of conditions and the
 841    * following disclaimer in the documentation and/or other
 842    * materials provided with the distribution.
 843    *
 844    * 3. The name "DOM4J" must not be used to endorse or promote
 845    * products derived from this Software without prior written
 846    * permission of MetaStuff, Ltd. For written permission,
 847    * please contact dom4j-info@metastuff.com.
 848    *
 849    * 4. Products derived from this Software may not be called "DOM4J"
 850    * nor may "DOM4J" appear in their names without prior written
 851    * permission of MetaStuff, Ltd. DOM4J is a registered
 852    * trademark of MetaStuff, Ltd.
 853    *
 854    * 5. Due credit should be given to the DOM4J Project -
 855    * http://www.dom4j.org
 856    *
 857    * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
 858    * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 859    * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 860    * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 861    * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 862    * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 863    * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 864    * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 865    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 866    * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 867    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 868    * OF THE POSSIBILITY OF SUCH DAMAGE.
 869    *
 870    * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
 871    *
 872    * $Id: SAXContentHandler.java,v 1.59 2004/08/06 09:51:50 maartenc Exp $
 873    */