Clover coverage report - dom4j - 1.5
Coverage timestamp: vr sep 3 2004 20:47:03 GMT+01:00
file stats: LOC: 422   Methods: 35
NCLOC: 250   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AbstractBranch.java 65% 66,4% 74,3% 67,5%
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: AbstractBranch.java,v 1.41 2004/06/25 08:03:40 maartenc Exp $
 8    */
 9   
 10    package org.dom4j.tree;
 11   
 12    import java.util.ArrayList;
 13    import java.util.Iterator;
 14    import java.util.List;
 15    import java.util.StringTokenizer;
 16   
 17    import org.dom4j.Branch;
 18    import org.dom4j.Comment;
 19    import org.dom4j.Element;
 20    import org.dom4j.IllegalAddException;
 21    import org.dom4j.Namespace;
 22    import org.dom4j.Node;
 23    import org.dom4j.ProcessingInstruction;
 24    import org.dom4j.QName;
 25    import org.dom4j.io.OutputFormat;
 26   
 27    /** <p><code>AbstractBranch</code> is an abstract base class for
 28    * tree implementors to use for implementation inheritence.</p>
 29    *
 30    * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
 31    * @version $Revision: 1.41 $
 32    */
 33    public abstract class AbstractBranch extends AbstractNode implements Branch {
 34   
 35    /** The output format used by default */
 36    protected static final OutputFormat outputFormat = new OutputFormat();
 37   
 38    protected static final int DEFAULT_CONTENT_LIST_SIZE = 5;
 39   
 40   
 41  196662 public AbstractBranch() {
 42    }
 43   
 44   
 45  266 public boolean isReadOnly() {
 46  266 return false;
 47    }
 48   
 49  0 public boolean hasContent() {
 50  0 return nodeCount() > 0;
 51    }
 52   
 53  9780 public List content() {
 54  9780 List backingList = contentList();
 55  9780 return new ContentListFacade(this, backingList);
 56    }
 57   
 58  156 public String getText() {
 59  156 List content = contentList();
 60  156 if (content != null) {
 61  156 int size = content.size();
 62  156 if (size >= 1) {
 63  156 Object first = content.get(0);
 64  156 String firstText = getContentAsText( first );
 65  156 if (size == 1) {
 66    // optimised to avoid StringBuffer creation
 67  136 return firstText;
 68    }
 69    else {
 70  20 StringBuffer buffer = new StringBuffer( firstText );
 71  20 for ( int i = 1; i < size; i++ ) {
 72  48 Object node = content.get(i);
 73  48 buffer.append( getContentAsText( node ) );
 74    }
 75  20 return buffer.toString();
 76    }
 77    }
 78    }
 79  0 return "";
 80    }
 81   
 82    /** @return the text value of the given content object
 83    * as text which returns the text value of CDATA, Entity or Text nodes
 84    */
 85  400 protected String getContentAsText(Object content) {
 86  400 if ( content instanceof Node) {
 87  400 Node node = (Node) content;
 88  400 switch ( node.getNodeType() ) {
 89  4 case CDATA_SECTION_NODE:
 90    //case ENTITY_NODE:
 91  0 case ENTITY_REFERENCE_NODE:
 92  386 case TEXT_NODE:
 93  390 return node.getText();
 94    }
 95    }
 96  0 else if ( content instanceof String) {
 97  0 return (String) content;
 98    }
 99  10 return "";
 100    }
 101   
 102    /** @return the XPath defined string-value of the given content object
 103    */
 104  2620 protected String getContentAsStringValue(Object content) {
 105  2620 if ( content instanceof Node) {
 106  2620 Node node = (Node) content;
 107  2620 switch ( node.getNodeType() ) {
 108  0 case CDATA_SECTION_NODE:
 109    //case ENTITY_NODE:
 110  0 case ENTITY_REFERENCE_NODE:
 111  2426 case TEXT_NODE:
 112  192 case ELEMENT_NODE:
 113  2618 return node.getStringValue();
 114    }
 115    }
 116  0 else if ( content instanceof String) {
 117  0 return (String) content;
 118    }
 119  2 return "";
 120    }
 121   
 122   
 123  154 public String getTextTrim() {
 124  154 String text = getText();
 125   
 126  154 StringBuffer textContent = new StringBuffer();
 127  154 StringTokenizer tokenizer = new StringTokenizer(text);
 128  154 while (tokenizer.hasMoreTokens()) {
 129  198 String str = tokenizer.nextToken();
 130  198 textContent.append(str);
 131  198 if (tokenizer.hasMoreTokens()) {
 132  46 textContent.append(" "); // separator
 133    }
 134    }
 135   
 136  154 return textContent.toString();
 137    }
 138   
 139  0 public void setProcessingInstructions(List listOfPIs) {
 140  0 for ( Iterator iter = listOfPIs.iterator(); iter.hasNext(); ) {
 141  0 ProcessingInstruction pi = (ProcessingInstruction) iter.next();
 142  0 addNode(pi);
 143    }
 144    }
 145   
 146  0 public Element addElement(String name) {
 147  0 Element node = getDocumentFactory().createElement( name );
 148  0 add( node );
 149  0 return node;
 150    }
 151   
 152  4 public Element addElement(String qualifiedName, String namespaceURI) {
 153  4 Element node = getDocumentFactory().createElement( qualifiedName, namespaceURI );
 154  4 add( node );
 155  4 return node;
 156    }
 157   
 158  167342 public Element addElement(QName qname) {
 159  167342 Element node = getDocumentFactory().createElement( qname );
 160  167342 add( node );
 161  167342 return node;
 162    }
 163   
 164  0 public Element addElement(String name, String prefix, String uri) {
 165  0 Namespace namespace = Namespace.get( prefix, uri );
 166  0 QName qName = getDocumentFactory().createQName( name, namespace );
 167  0 return addElement( qName );
 168    }
 169   
 170    // polymorphic node methods
 171   
 172  26 public void add(Node node) {
 173  26 switch ( node.getNodeType() ) {
 174  26 case ELEMENT_NODE:
 175  26 add((Element) node);
 176  26 break;
 177  0 case COMMENT_NODE:
 178  0 add((Comment) node);
 179  0 break;
 180  0 case PROCESSING_INSTRUCTION_NODE:
 181  0 add((ProcessingInstruction) node);
 182  0 break;
 183  0 default:
 184  0 invalidNodeTypeAddException(node);
 185    }
 186    }
 187   
 188  4 public boolean remove(Node node) {
 189  4 switch ( node.getNodeType() ) {
 190  4 case ELEMENT_NODE:
 191  4 return remove((Element) node);
 192  0 case COMMENT_NODE:
 193  0 return remove((Comment) node);
 194  0 case PROCESSING_INSTRUCTION_NODE:
 195  0 return remove((ProcessingInstruction) node);
 196  0 default:
 197  0 invalidNodeTypeAddException(node);
 198  0 return false;
 199    }
 200    }
 201   
 202    // typesafe versions using node classes
 203   
 204  44 public void add(Comment comment) {
 205  44 addNode(comment);
 206    }
 207   
 208  12016 public void add(Element element) {
 209  12016 addNode(element);
 210    }
 211   
 212  42 public void add(ProcessingInstruction pi) {
 213  42 addNode(pi);
 214    }
 215   
 216  0 public boolean remove(Comment comment) {
 217  0 return removeNode(comment);
 218    }
 219   
 220  4 public boolean remove(Element element) {
 221  4 return removeNode(element);
 222    }
 223   
 224  0 public boolean remove(ProcessingInstruction pi) {
 225  0 return removeNode(pi);
 226    }
 227   
 228   
 229  26 public Element elementByID(String elementID) {
 230  26 for ( int i = 0, size = nodeCount(); i < size; i++ ) {
 231  62 Node node = node(i);
 232  62 if ( node instanceof Element ) {
 233  24 Element element = (Element) node;
 234  24 String id = elementID(element);
 235  24 if ( id != null && id.equals( elementID ) ) {
 236  2 return element;
 237    }
 238    else {
 239  22 element = element.elementByID( elementID );
 240  22 if ( element != null ) {
 241  4 return element;
 242    }
 243    }
 244    }
 245    }
 246  20 return null;
 247    }
 248   
 249  276 public void appendContent(Branch branch) {
 250  276 for ( int i = 0, size = branch.nodeCount(); i < size; i++ ) {
 251  634 Node node = branch.node(i);
 252  634 add( (Node) node.clone() );
 253    }
 254    }
 255   
 256   
 257  774 public Node node(int index) {
 258  774 Object object = contentList().get(index);
 259  774 if (object instanceof Node) {
 260  774 return (Node) object;
 261    }
 262  0 if (object instanceof String) {
 263  0 return getDocumentFactory().createText(object.toString());
 264    }
 265  0 return null;
 266    }
 267   
 268  654 public int nodeCount() {
 269  654 return contentList().size();
 270    }
 271   
 272  0 public int indexOf(Node node) {
 273  0 return contentList().indexOf( node );
 274    }
 275   
 276  622 public Iterator nodeIterator() {
 277  622 return contentList().iterator();
 278    }
 279   
 280   
 281    // Implementation methods
 282   
 283    /** @return the ID of the given <code>Element</code>
 284    */
 285  24 protected String elementID(Element element) {
 286    // XXX: there will be other ways of finding the ID
 287    // XXX: should probably have an IDResolver or something
 288  24 return element.attributeValue( "ID" );
 289    }
 290   
 291    /** @return the internal List used to manage the content */
 292    protected abstract List contentList();
 293   
 294    /** A Factory Method pattern which creates
 295    * a List implementation used to store content
 296    */
 297  108060 protected List createContentList() {
 298  108060 return new ArrayList( DEFAULT_CONTENT_LIST_SIZE );
 299    }
 300   
 301    /** A Factory Method pattern which creates
 302    * a List implementation used to store content
 303    */
 304  4 protected List createContentList(int size) {
 305  4 return new ArrayList( size );
 306    }
 307   
 308   
 309    /** A Factory Method pattern which creates
 310    * a BackedList implementation used to store results of
 311    * a filtered content query. */
 312  48326 protected BackedList createResultList() {
 313  48326 return new BackedList( this, contentList() );
 314    }
 315   
 316    /** A Factory Method pattern which creates
 317    * a BackedList implementation which contains a single result
 318    */
 319  0 protected List createSingleResultList( Object result ) {
 320  0 BackedList list = new BackedList( this, contentList(), 1 );
 321  0 list.addLocal( result );
 322  0 return list;
 323    }
 324   
 325    /** A Factory Method pattern which creates an empty
 326    * a BackedList implementation
 327    */
 328  12 protected List createEmptyList() {
 329  12 return new BackedList( this, contentList(), 0 );
 330    }
 331   
 332   
 333    protected abstract void addNode(Node node);
 334   
 335    protected abstract void addNode(int index, Node node);
 336   
 337    protected abstract boolean removeNode(Node node);
 338   
 339   
 340    /** Called when a new child node has been added to me
 341    * to allow any parent relationships to be created or
 342    * events to be fired.
 343    */
 344    protected abstract void childAdded(Node node);
 345   
 346    /** Called when a child node has been removed
 347    * to allow any parent relationships to be deleted or
 348    * events to be fired.
 349    */
 350    protected abstract void childRemoved(Node node);
 351   
 352    /** Called when the given List content has been removed so
 353    * each node should have its parent and document relationships
 354    * cleared
 355    */
 356  12 protected void contentRemoved() {
 357  12 List content = contentList();
 358  12 for ( int i = 0, size = content.size(); i < size; i++ ) {
 359  6 Object object = content.get(i);
 360  6 if ( object instanceof Node ) {
 361  6 childRemoved( (Node) object );
 362    }
 363    }
 364    }
 365   
 366    /** Called when an invalid node has been added.
 367    * Throws an {@link IllegalAddException}.
 368    */
 369  0 protected void invalidNodeTypeAddException(Node node) {
 370  0 throw new IllegalAddException( "Invalid node type. Cannot add node: " + node + " to this branch: " + this );
 371    }
 372   
 373   
 374    }
 375   
 376   
 377   
 378   
 379    /*
 380    * Redistribution and use of this software and associated documentation
 381    * ("Software"), with or without modification, are permitted provided
 382    * that the following conditions are met:
 383    *
 384    * 1. Redistributions of source code must retain copyright
 385    * statements and notices. Redistributions must also contain a
 386    * copy of this document.
 387    *
 388    * 2. Redistributions in binary form must reproduce the
 389    * above copyright notice, this list of conditions and the
 390    * following disclaimer in the documentation and/or other
 391    * materials provided with the distribution.
 392    *
 393    * 3. The name "DOM4J" must not be used to endorse or promote
 394    * products derived from this Software without prior written
 395    * permission of MetaStuff, Ltd. For written permission,
 396    * please contact dom4j-info@metastuff.com.
 397    *
 398    * 4. Products derived from this Software may not be called "DOM4J"
 399    * nor may "DOM4J" appear in their names without prior written
 400    * permission of MetaStuff, Ltd. DOM4J is a registered
 401    * trademark of MetaStuff, Ltd.
 402    *
 403    * 5. Due credit should be given to the DOM4J Project -
 404    * http://www.dom4j.org
 405    *
 406    * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
 407    * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 408    * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 409    * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 410    * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 411    * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 412    * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 413    * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 414    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 415    * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 416    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 417    * OF THE POSSIBILITY OF SUCH DAMAGE.
 418    *
 419    * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
 420    *
 421    * $Id: AbstractBranch.java,v 1.41 2004/06/25 08:03:40 maartenc Exp $
 422    */