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