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