Clover coverage report - dom4j - 1.6.1
Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00
file stats: LOC: 1.055   Methods: 49
NCLOC: 727   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
DefaultElement.java 59,8% 68,3% 75,5% 65,5%
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   
 14    import org.dom4j.Attribute;
 15    import org.dom4j.Branch;
 16    import org.dom4j.Document;
 17    import org.dom4j.DocumentFactory;
 18    import org.dom4j.Element;
 19    import org.dom4j.IllegalAddException;
 20    import org.dom4j.Namespace;
 21    import org.dom4j.Node;
 22    import org.dom4j.ProcessingInstruction;
 23    import org.dom4j.QName;
 24   
 25    /**
 26    * <p>
 27    * <code>DefaultElement</code> is the default DOM4J default implementation of
 28    * an XML element.
 29    * </p>
 30    *
 31    * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
 32    * @version $Revision: 1.59 $
 33    */
 34    public class DefaultElement extends AbstractElement {
 35    /** The <code>DocumentFactory</code> instance used by default */
 36    private static final transient DocumentFactory DOCUMENT_FACTORY =
 37    DocumentFactory.getInstance();
 38   
 39    /** The <code>QName</code> for this element */
 40    private QName qname;
 41   
 42    /**
 43    * Stores the parent branch of this node which is either a Document if this
 44    * element is the root element in a document, or another Element if it is a
 45    * child of the root document, or null if it has not been added to a
 46    * document yet.
 47    */
 48    private Branch parentBranch;
 49   
 50    /**
 51    * Stores null for no content, a Node for a single content node or a List
 52    * for multiple content nodes. The List will be lazily constructed when
 53    * required.
 54    */
 55    private Object content;
 56   
 57    /** Lazily constructes list of attributes */
 58    private Object attributes;
 59   
 60  1 public DefaultElement(String name) {
 61  1 this.qname = DOCUMENT_FACTORY.createQName(name);
 62    }
 63   
 64  96007 public DefaultElement(QName qname) {
 65  96007 this.qname = qname;
 66    }
 67   
 68  0 public DefaultElement(QName qname, int attributeCount) {
 69  0 this.qname = qname;
 70   
 71  0 if (attributeCount > 1) {
 72  0 this.attributes = new ArrayList(attributeCount);
 73    }
 74    }
 75   
 76  0 public DefaultElement(String name, Namespace namespace) {
 77  0 this.qname = DOCUMENT_FACTORY.createQName(name, namespace);
 78    }
 79   
 80  131539 public Element getParent() {
 81  131539 Element result = null;
 82   
 83  131539 if (parentBranch instanceof Element) {
 84  35288 result = (Element) parentBranch;
 85    }
 86   
 87  131539 return result;
 88    }
 89   
 90  94507 public void setParent(Element parent) {
 91  94507 if (parentBranch instanceof Element || (parent != null)) {
 92  92978 parentBranch = parent;
 93    }
 94    }
 95   
 96  13010 public Document getDocument() {
 97  13010 if (parentBranch instanceof Document) {
 98  6597 return (Document) parentBranch;
 99  6413 } else if (parentBranch instanceof Element) {
 100  117 Element parent = (Element) parentBranch;
 101   
 102  117 return parent.getDocument();
 103    }
 104   
 105  6296 return null;
 106    }
 107   
 108  15752 public void setDocument(Document document) {
 109  15752 if (parentBranch instanceof Document || (document != null)) {
 110  12600 parentBranch = document;
 111    }
 112    }
 113   
 114  10 public boolean supportsParent() {
 115  10 return true;
 116    }
 117   
 118  619575 public QName getQName() {
 119  619575 return qname;
 120    }
 121   
 122  1502 public void setQName(QName name) {
 123  1502 this.qname = name;
 124    }
 125   
 126  183 public String getText() {
 127  183 final Object contentShadow = content;
 128   
 129  183 if (contentShadow instanceof List) {
 130  80 return super.getText();
 131    } else {
 132  103 if (contentShadow != null) {
 133  93 return getContentAsText(contentShadow);
 134    } else {
 135  10 return "";
 136    }
 137    }
 138    }
 139   
 140  8 public String getStringValue() {
 141  8 final Object contentShadow = content;
 142   
 143  8 if (contentShadow instanceof List) {
 144  6 List list = (List) contentShadow;
 145   
 146  6 int size = list.size();
 147   
 148  6 if (size > 0) {
 149  6 if (size == 1) {
 150    // optimised to avoid StringBuffer creation
 151  4 return getContentAsStringValue(list.get(0));
 152    } else {
 153  2 StringBuffer buffer = new StringBuffer();
 154   
 155  2 for (int i = 0; i < size; i++) {
 156  9 Object node = list.get(i);
 157   
 158  9 String string = getContentAsStringValue(node);
 159   
 160  9 if (string.length() > 0) {
 161  7 if (USE_STRINGVALUE_SEPARATOR) {
 162  0 if (buffer.length() > 0) {
 163  0 buffer.append(' ');
 164    }
 165    }
 166   
 167  7 buffer.append(string);
 168    }
 169    }
 170   
 171  2 return buffer.toString();
 172    }
 173    }
 174    } else {
 175  2 if (contentShadow != null) {
 176  0 return getContentAsStringValue(contentShadow);
 177    }
 178    }
 179   
 180  2 return "";
 181    }
 182   
 183  129 public Object clone() {
 184  129 DefaultElement answer = (DefaultElement) super.clone();
 185   
 186  129 if (answer != this) {
 187  129 answer.content = null;
 188   
 189  129 answer.attributes = null;
 190   
 191  129 answer.appendAttributes(this);
 192   
 193  129 answer.appendContent(this);
 194    }
 195   
 196  129 return answer;
 197    }
 198   
 199  8764 public Namespace getNamespaceForPrefix(String prefix) {
 200  8764 if (prefix == null) {
 201  9 prefix = "";
 202    }
 203   
 204  8764 if (prefix.equals(getNamespacePrefix())) {
 205  3721 return getNamespace();
 206  5043 } else if (prefix.equals("xml")) {
 207  0 return Namespace.XML_NAMESPACE;
 208    } else {
 209  5043 final Object contentShadow = content;
 210   
 211  5043 if (contentShadow instanceof List) {
 212  5040 List list = (List) contentShadow;
 213   
 214  5040 int size = list.size();
 215   
 216  5040 for (int i = 0; i < size; i++) {
 217  5100 Object object = list.get(i);
 218   
 219  5100 if (object instanceof Namespace) {
 220  5055 Namespace namespace = (Namespace) object;
 221   
 222  5055 if (prefix.equals(namespace.getPrefix())) {
 223  5023 return namespace;
 224    }
 225    }
 226    }
 227  3 } else if (contentShadow instanceof Namespace) {
 228  0 Namespace namespace = (Namespace) contentShadow;
 229   
 230  0 if (prefix.equals(namespace.getPrefix())) {
 231  0 return namespace;
 232    }
 233    }
 234    }
 235   
 236  20 Element parent = getParent();
 237   
 238  20 if (parent != null) {
 239  19 Namespace answer = parent.getNamespaceForPrefix(prefix);
 240   
 241  19 if (answer != null) {
 242  19 return answer;
 243    }
 244    }
 245   
 246  1 if ((prefix == null) || (prefix.length() <= 0)) {
 247  0 return Namespace.NO_NAMESPACE;
 248    }
 249   
 250  1 return null;
 251    }
 252   
 253  9 public Namespace getNamespaceForURI(String uri) {
 254  9 if ((uri == null) || (uri.length() <= 0)) {
 255  0 return Namespace.NO_NAMESPACE;
 256  9 } else if (uri.equals(getNamespaceURI())) {
 257  0 return getNamespace();
 258    } else {
 259  9 final Object contentShadow = content;
 260   
 261  9 if (contentShadow instanceof List) {
 262  9 List list = (List) contentShadow;
 263   
 264  9 int size = list.size();
 265   
 266  9 for (int i = 0; i < size; i++) {
 267  21 Object object = list.get(i);
 268   
 269  21 if (object instanceof Namespace) {
 270  12 Namespace namespace = (Namespace) object;
 271   
 272  12 if (uri.equals(namespace.getURI())) {
 273  6 return namespace;
 274    }
 275    }
 276    }
 277  0 } else if (contentShadow instanceof Namespace) {
 278  0 Namespace namespace = (Namespace) contentShadow;
 279   
 280  0 if (uri.equals(namespace.getURI())) {
 281  0 return namespace;
 282    }
 283    }
 284   
 285  3 Element parent = getParent();
 286   
 287  3 if (parent != null) {
 288  3 return parent.getNamespaceForURI(uri);
 289    }
 290   
 291  0 return null;
 292    }
 293    }
 294   
 295  9903 public List declaredNamespaces() {
 296  9903 BackedList answer = createResultList();
 297   
 298    // if (getNamespaceURI().length() > 0) {
 299    //
 300    // answer.addLocal(getNamespace());
 301    //
 302    // }
 303  9903 final Object contentShadow = content;
 304   
 305  9903 if (contentShadow instanceof List) {
 306  9903 List list = (List) contentShadow;
 307   
 308  9903 int size = list.size();
 309   
 310  9903 for (int i = 0; i < size; i++) {
 311  31929 Object object = list.get(i);
 312   
 313  31929 if (object instanceof Namespace) {
 314  821 answer.addLocal(object);
 315    }
 316    }
 317    } else {
 318  0 if (contentShadow instanceof Namespace) {
 319  0 answer.addLocal(contentShadow);
 320    }
 321    }
 322   
 323  9903 return answer;
 324    }
 325   
 326  15 public List additionalNamespaces() {
 327  15 final Object contentShadow = content;
 328   
 329  15 if (contentShadow instanceof List) {
 330  13 List list = (List) contentShadow;
 331   
 332  13 int size = list.size();
 333   
 334  13 BackedList answer = createResultList();
 335   
 336  13 for (int i = 0; i < size; i++) {
 337  89 Object object = list.get(i);
 338   
 339  89 if (object instanceof Namespace) {
 340  25 Namespace namespace = (Namespace) object;
 341   
 342  25 if (!namespace.equals(getNamespace())) {
 343  13 answer.addLocal(namespace);
 344    }
 345    }
 346    }
 347   
 348  13 return answer;
 349    } else {
 350  2 if (contentShadow instanceof Namespace) {
 351  1 Namespace namespace = (Namespace) contentShadow;
 352   
 353  1 if (namespace.equals(getNamespace())) {
 354  1 return createEmptyList();
 355    }
 356   
 357  0 return createSingleResultList(namespace);
 358    } else {
 359  1 return createEmptyList();
 360    }
 361    }
 362    }
 363   
 364  0 public List additionalNamespaces(String defaultNamespaceURI) {
 365  0 final Object contentShadow = content;
 366   
 367  0 if (contentShadow instanceof List) {
 368  0 List list = (List) contentShadow;
 369   
 370  0 BackedList answer = createResultList();
 371   
 372  0 int size = list.size();
 373   
 374  0 for (int i = 0; i < size; i++) {
 375  0 Object object = list.get(i);
 376   
 377  0 if (object instanceof Namespace) {
 378  0 Namespace namespace = (Namespace) object;
 379   
 380  0 if (!defaultNamespaceURI.equals(namespace.getURI())) {
 381  0 answer.addLocal(namespace);
 382    }
 383    }
 384    }
 385   
 386  0 return answer;
 387    } else {
 388  0 if (contentShadow instanceof Namespace) {
 389  0 Namespace namespace = (Namespace) contentShadow;
 390   
 391  0 if (!defaultNamespaceURI.equals(namespace.getURI())) {
 392  0 return createSingleResultList(namespace);
 393    }
 394    }
 395    }
 396   
 397  0 return createEmptyList();
 398    }
 399   
 400    // Processing instruction API
 401  0 public List processingInstructions() {
 402  0 final Object contentShadow = content;
 403   
 404  0 if (contentShadow instanceof List) {
 405  0 List list = (List) contentShadow;
 406   
 407  0 BackedList answer = createResultList();
 408   
 409  0 int size = list.size();
 410   
 411  0 for (int i = 0; i < size; i++) {
 412  0 Object object = list.get(i);
 413   
 414  0 if (object instanceof ProcessingInstruction) {
 415  0 answer.addLocal(object);
 416    }
 417    }
 418   
 419  0 return answer;
 420    } else {
 421  0 if (contentShadow instanceof ProcessingInstruction) {
 422  0 return createSingleResultList(contentShadow);
 423    }
 424   
 425  0 return createEmptyList();
 426    }
 427    }
 428   
 429  0 public List processingInstructions(String target) {
 430  0 final Object shadow = content;
 431   
 432  0 if (shadow instanceof List) {
 433  0 List list = (List) shadow;
 434   
 435  0 BackedList answer = createResultList();
 436   
 437  0 int size = list.size();
 438   
 439  0 for (int i = 0; i < size; i++) {
 440  0 Object object = list.get(i);
 441   
 442  0 if (object instanceof ProcessingInstruction) {
 443  0 ProcessingInstruction pi = (ProcessingInstruction) object;
 444   
 445  0 if (target.equals(pi.getName())) {
 446  0 answer.addLocal(pi);
 447    }
 448    }
 449    }
 450   
 451  0 return answer;
 452    } else {
 453  0 if (shadow instanceof ProcessingInstruction) {
 454  0 ProcessingInstruction pi = (ProcessingInstruction) shadow;
 455   
 456  0 if (target.equals(pi.getName())) {
 457  0 return createSingleResultList(pi);
 458    }
 459    }
 460   
 461  0 return createEmptyList();
 462    }
 463    }
 464   
 465  0 public ProcessingInstruction processingInstruction(String target) {
 466  0 final Object shadow = content;
 467   
 468  0 if (shadow instanceof List) {
 469  0 List list = (List) shadow;
 470   
 471  0 int size = list.size();
 472   
 473  0 for (int i = 0; i < size; i++) {
 474  0 Object object = list.get(i);
 475   
 476  0 if (object instanceof ProcessingInstruction) {
 477  0 ProcessingInstruction pi = (ProcessingInstruction) object;
 478   
 479  0 if (target.equals(pi.getName())) {
 480  0 return pi;
 481    }
 482    }
 483    }
 484    } else {
 485  0 if (shadow instanceof ProcessingInstruction) {
 486  0 ProcessingInstruction pi = (ProcessingInstruction) shadow;
 487   
 488  0 if (target.equals(pi.getName())) {
 489  0 return pi;
 490    }
 491    }
 492    }
 493   
 494  0 return null;
 495    }
 496   
 497  0 public boolean removeProcessingInstruction(String target) {
 498  0 final Object shadow = content;
 499   
 500  0 if (shadow instanceof List) {
 501  0 List list = (List) shadow;
 502   
 503  0 for (Iterator iter = list.iterator(); iter.hasNext();) {
 504  0 Object object = iter.next();
 505   
 506  0 if (object instanceof ProcessingInstruction) {
 507  0 ProcessingInstruction pi = (ProcessingInstruction) object;
 508   
 509  0 if (target.equals(pi.getName())) {
 510  0 iter.remove();
 511   
 512  0 return true;
 513    }
 514    }
 515    }
 516    } else {
 517  0 if (shadow instanceof ProcessingInstruction) {
 518  0 ProcessingInstruction pi = (ProcessingInstruction) shadow;
 519   
 520  0 if (target.equals(pi.getName())) {
 521  0 this.content = null;
 522   
 523  0 return true;
 524    }
 525    }
 526    }
 527   
 528  0 return false;
 529    }
 530   
 531  125 public Element element(String name) {
 532  125 final Object contentShadow = content;
 533   
 534  125 if (contentShadow instanceof List) {
 535  30 List list = (List) contentShadow;
 536   
 537  30 int size = list.size();
 538   
 539  82 for (int i = 0; i < size; i++) {
 540  82 Object object = list.get(i);
 541   
 542  82 if (object instanceof Element) {
 543  36 Element element = (Element) object;
 544   
 545  36 if (name.equals(element.getName())) {
 546  30 return element;
 547    }
 548    }
 549    }
 550    } else {
 551  95 if (contentShadow instanceof Element) {
 552  6 Element element = (Element) contentShadow;
 553   
 554  6 if (name.equals(element.getName())) {
 555  6 return element;
 556    }
 557    }
 558    }
 559   
 560  89 return null;
 561    }
 562   
 563  2965 public Element element(QName qName) {
 564  2965 final Object contentShadow = content;
 565   
 566  2965 if (contentShadow instanceof List) {
 567  2705 List list = (List) contentShadow;
 568   
 569  2705 int size = list.size();
 570   
 571  2705 for (int i = 0; i < size; i++) {
 572  21262 Object object = list.get(i);
 573   
 574  21262 if (object instanceof Element) {
 575  11680 Element element = (Element) object;
 576   
 577  11680 if (qName.equals(element.getQName())) {
 578  2290 return element;
 579    }
 580    }
 581    }
 582    } else {
 583  260 if (contentShadow instanceof Element) {
 584  1 Element element = (Element) contentShadow;
 585   
 586  1 if (qName.equals(element.getQName())) {
 587  1 return element;
 588    }
 589    }
 590    }
 591   
 592  674 return null;
 593    }
 594   
 595  0 public Element element(String name, Namespace namespace) {
 596  0 return element(getDocumentFactory().createQName(name, namespace));
 597    }
 598   
 599  2 public void setContent(List content) {
 600  2 contentRemoved();
 601   
 602  2 if (content instanceof ContentListFacade) {
 603  2 content = ((ContentListFacade) content).getBackingList();
 604    }
 605   
 606  2 if (content == null) {
 607  0 this.content = null;
 608    } else {
 609  2 int size = content.size();
 610   
 611  2 List newContent = createContentList(size);
 612   
 613  2 for (int i = 0; i < size; i++) {
 614  7 Object object = content.get(i);
 615   
 616  7 if (object instanceof Node) {
 617  7 Node node = (Node) object;
 618  7 Element parent = node.getParent();
 619   
 620  7 if ((parent != null) && (parent != this)) {
 621  2 node = (Node) node.clone();
 622    }
 623   
 624  7 newContent.add(node);
 625  7 childAdded(node);
 626  0 } else if (object != null) {
 627  0 String text = object.toString();
 628  0 Node node = getDocumentFactory().createText(text);
 629  0 newContent.add(node);
 630  0 childAdded(node);
 631    }
 632    }
 633   
 634  2 this.content = newContent;
 635    }
 636    }
 637   
 638  0 public void clearContent() {
 639  0 if (content != null) {
 640  0 contentRemoved();
 641   
 642  0 content = null;
 643    }
 644    }
 645   
 646  355275 public Node node(int index) {
 647  355275 if (index >= 0) {
 648  355275 final Object contentShadow = content;
 649  355275 Object node;
 650   
 651  355275 if (contentShadow instanceof List) {
 652  333677 List list = (List) contentShadow;
 653   
 654  333677 if (index >= list.size()) {
 655  0 return null;
 656    }
 657   
 658  333677 node = list.get(index);
 659    } else {
 660  21598 node = (index == 0) ? contentShadow : null;
 661    }
 662   
 663  355275 if (node != null) {
 664  355275 if (node instanceof Node) {
 665  355275 return (Node) node;
 666    } else {
 667  0 return new DefaultText(node.toString());
 668    }
 669    }
 670    }
 671   
 672  0 return null;
 673    }
 674   
 675  0 public int indexOf(Node node) {
 676  0 final Object contentShadow = content;
 677   
 678  0 if (contentShadow instanceof List) {
 679  0 List list = (List) contentShadow;
 680   
 681  0 return list.indexOf(node);
 682    } else {
 683  0 if ((contentShadow != null) && contentShadow.equals(node)) {
 684  0 return 0;
 685    } else {
 686  0 return -1;
 687    }
 688    }
 689    }
 690   
 691  125606 public int nodeCount() {
 692  125606 final Object contentShadow = content;
 693   
 694  125606 if (contentShadow instanceof List) {
 695  103856 List list = (List) contentShadow;
 696   
 697  103856 return list.size();
 698    } else {
 699  21750 return (contentShadow != null) ? 1 : 0;
 700    }
 701    }
 702   
 703  94704 public Iterator nodeIterator() {
 704  94704 final Object contentShadow = content;
 705   
 706  94704 if (contentShadow instanceof List) {
 707  33208 List list = (List) contentShadow;
 708   
 709  33208 return list.iterator();
 710    } else {
 711  61496 if (contentShadow != null) {
 712  61120 return createSingleIterator(contentShadow);
 713    } else {
 714  376 return EMPTY_ITERATOR;
 715    }
 716    }
 717    }
 718   
 719  109 public List attributes() {
 720  109 return new ContentListFacade(this, attributeList());
 721    }
 722   
 723  0 public void setAttributes(List attributes) {
 724  0 if (attributes instanceof ContentListFacade) {
 725  0 attributes = ((ContentListFacade) attributes).getBackingList();
 726    }
 727   
 728  0 this.attributes = attributes;
 729    }
 730   
 731  5028 public Iterator attributeIterator() {
 732  5028 final Object attributesShadow = this.attributes;
 733   
 734  5028 if (attributesShadow instanceof List) {
 735  2596 List list = (List) attributesShadow;
 736   
 737  2596 return list.iterator();
 738  2432 } else if (attributesShadow != null) {
 739  998 return createSingleIterator(attributesShadow);
 740    } else {
 741  1434 return EMPTY_ITERATOR;
 742    }
 743    }
 744   
 745  24324 public Attribute attribute(int index) {
 746  24324 final Object attributesShadow = this.attributes;
 747   
 748  24324 if (attributesShadow instanceof List) {
 749  22129 List list = (List) attributesShadow;
 750   
 751  22129 return (Attribute) list.get(index);
 752  2195 } else if ((attributesShadow != null) && (index == 0)) {
 753  2195 return (Attribute) attributesShadow;
 754    } else {
 755  0 return null;
 756    }
 757    }
 758   
 759  110652 public int attributeCount() {
 760  110652 final Object attributesShadow = this.attributes;
 761   
 762  110652 if (attributesShadow instanceof List) {
 763  65626 List list = (List) attributesShadow;
 764   
 765  65626 return list.size();
 766    } else {
 767  45026 return (attributesShadow != null) ? 1 : 0;
 768    }
 769    }
 770   
 771  3958 public Attribute attribute(String name) {
 772  3958 final Object attributesShadow = this.attributes;
 773   
 774  3958 if (attributesShadow instanceof List) {
 775  1292 List list = (List) attributesShadow;
 776   
 777  1292 int size = list.size();
 778   
 779  1292 for (int i = 0; i < size; i++) {
 780  2294 Attribute attribute = (Attribute) list.get(i);
 781   
 782  2294 if (name.equals(attribute.getName())) {
 783  974 return attribute;
 784    }
 785    }
 786  2666 } else if (attributesShadow != null) {
 787  1729 Attribute attribute = (Attribute) attributesShadow;
 788   
 789  1729 if (name.equals(attribute.getName())) {
 790  575 return attribute;
 791    }
 792    }
 793   
 794  2409 return null;
 795    }
 796   
 797  20997 public Attribute attribute(QName qName) {
 798  20997 final Object attributesShadow = this.attributes;
 799   
 800  20997 if (attributesShadow instanceof List) {
 801  17846 List list = (List) attributesShadow;
 802   
 803  17846 int size = list.size();
 804   
 805  17846 for (int i = 0; i < size; i++) {
 806  20862 Attribute attribute = (Attribute) list.get(i);
 807   
 808  20862 if (qName.equals(attribute.getQName())) {
 809  17696 return attribute;
 810    }
 811    }
 812  3151 } else if (attributesShadow != null) {
 813  618 Attribute attribute = (Attribute) attributesShadow;
 814   
 815  618 if (qName.equals(attribute.getQName())) {
 816  231 return attribute;
 817    }
 818    }
 819   
 820  3070 return null;
 821    }
 822   
 823  0 public Attribute attribute(String name, Namespace namespace) {
 824  0 return attribute(getDocumentFactory().createQName(name, namespace));
 825    }
 826   
 827  10743 public void add(Attribute attribute) {
 828  10743 if (attribute.getParent() != null) {
 829  0 String message = "The Attribute already has an existing parent \""
 830    + attribute.getParent().getQualifiedName() + "\"";
 831   
 832  0 throw new IllegalAddException(this, attribute, message);
 833    }
 834   
 835  10743 if (attribute.getValue() == null) {
 836    // try remove a previous attribute with the same
 837    // name since adding an attribute with a null value
 838    // is equivalent to removing it.
 839  2 Attribute oldAttribute = attribute(attribute.getQName());
 840   
 841  2 if (oldAttribute != null) {
 842  1 remove(oldAttribute);
 843    }
 844    } else {
 845  10741 if (attributes == null) {
 846  9433 attributes = attribute;
 847    } else {
 848  1308 attributeList().add(attribute);
 849    }
 850   
 851  10741 childAdded(attribute);
 852    }
 853    }
 854   
 855  6 public boolean remove(Attribute attribute) {
 856  6 boolean answer = false;
 857  6 final Object attributesShadow = this.attributes;
 858   
 859  6 if (attributesShadow instanceof List) {
 860  3 List list = (List) attributesShadow;
 861   
 862  3 answer = list.remove(attribute);
 863   
 864  3 if (!answer) {
 865    // we may have a copy of the attribute
 866  0 Attribute copy = attribute(attribute.getQName());
 867   
 868  0 if (copy != null) {
 869  0 list.remove(copy);
 870   
 871  0 answer = true;
 872    }
 873    }
 874  3 } else if (attributesShadow != null) {
 875  3 if (attribute.equals(attributesShadow)) {
 876  3 this.attributes = null;
 877   
 878  3 answer = true;
 879    } else {
 880    // we may have a copy of the attribute
 881  0 Attribute other = (Attribute) attributesShadow;
 882   
 883  0 if (attribute.getQName().equals(other.getQName())) {
 884  0 attributes = null;
 885   
 886  0 answer = true;
 887    }
 888    }
 889    }
 890   
 891  6 if (answer) {
 892  6 childRemoved(attribute);
 893    }
 894   
 895  6 return answer;
 896    }
 897   
 898    // Implementation methods
 899    // -------------------------------------------------------------------------
 900  219990 protected void addNewNode(Node node) {
 901  219990 final Object contentShadow = content;
 902   
 903  219990 if (contentShadow == null) {
 904  92043 this.content = node;
 905    } else {
 906  127947 if (contentShadow instanceof List) {
 907  103858 List list = (List) contentShadow;
 908   
 909  103858 list.add(node);
 910    } else {
 911  24089 List list = createContentList();
 912   
 913  24089 list.add(contentShadow);
 914   
 915  24089 list.add(node);
 916   
 917  24089 this.content = list;
 918    }
 919    }
 920   
 921  219990 childAdded(node);
 922    }
 923   
 924  13545 protected boolean removeNode(Node node) {
 925  13545 boolean answer = false;
 926  13545 final Object contentShadow = content;
 927   
 928  13545 if (contentShadow != null) {
 929  13545 if (contentShadow == node) {
 930  1 this.content = null;
 931   
 932  1 answer = true;
 933  13544 } else if (contentShadow instanceof List) {
 934  13544 List list = (List) contentShadow;
 935   
 936  13544 answer = list.remove(node);
 937    }
 938    }
 939   
 940  13545 if (answer) {
 941  13545 childRemoved(node);
 942    }
 943   
 944  13545 return answer;
 945    }
 946   
 947  88171 protected List contentList() {
 948  88171 final Object contentShadow = content;
 949   
 950  88171 if (contentShadow instanceof List) {
 951  61297 return (List) contentShadow;
 952    } else {
 953  26874 List list = createContentList();
 954   
 955  26874 if (contentShadow != null) {
 956  23679 list.add(contentShadow);
 957    }
 958   
 959  26874 this.content = list;
 960   
 961  26874 return list;
 962    }
 963    }
 964   
 965  87124 protected List attributeList() {
 966  87124 final Object attributesShadow = this.attributes;
 967   
 968  87124 if (attributesShadow instanceof List) {
 969  58366 return (List) attributesShadow;
 970  28758 } else if (attributesShadow != null) {
 971  9093 List list = createAttributeList();
 972   
 973  9093 list.add(attributesShadow);
 974   
 975  9093 this.attributes = list;
 976   
 977  9093 return list;
 978    } else {
 979  19665 List list = createAttributeList();
 980   
 981  19665 this.attributes = list;
 982   
 983  19665 return list;
 984    }
 985    }
 986   
 987  1618 protected List attributeList(int size) {
 988  1618 final Object attributesShadow = this.attributes;
 989   
 990  1618 if (attributesShadow instanceof List) {
 991  0 return (List) attributesShadow;
 992  1618 } else if (attributesShadow != null) {
 993  0 List list = createAttributeList(size);
 994   
 995  0 list.add(attributesShadow);
 996   
 997  0 this.attributes = list;
 998   
 999  0 return list;
 1000    } else {
 1001  1618 List list = createAttributeList(size);
 1002   
 1003  1618 this.attributes = list;
 1004   
 1005  1618 return list;
 1006    }
 1007    }
 1008   
 1009  2 protected void setAttributeList(List attributeList) {
 1010  2 this.attributes = attributeList;
 1011    }
 1012   
 1013  228999 protected DocumentFactory getDocumentFactory() {
 1014  228999 DocumentFactory factory = qname.getDocumentFactory();
 1015   
 1016  228999 return (factory != null) ? factory : DOCUMENT_FACTORY;
 1017    }
 1018    }
 1019   
 1020    /*
 1021    * Redistribution and use of this software and associated documentation
 1022    * ("Software"), with or without modification, are permitted provided that the
 1023    * following conditions are met:
 1024    *
 1025    * 1. Redistributions of source code must retain copyright statements and
 1026    * notices. Redistributions must also contain a copy of this document.
 1027    *
 1028    * 2. Redistributions in binary form must reproduce the above copyright notice,
 1029    * this list of conditions and the following disclaimer in the documentation
 1030    * and/or other materials provided with the distribution.
 1031    *
 1032    * 3. The name "DOM4J" must not be used to endorse or promote products derived
 1033    * from this Software without prior written permission of MetaStuff, Ltd. For
 1034    * written permission, please contact dom4j-info@metastuff.com.
 1035    *
 1036    * 4. Products derived from this Software may not be called "DOM4J" nor may
 1037    * "DOM4J" appear in their names without prior written permission of MetaStuff,
 1038    * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
 1039    *
 1040    * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
 1041    *
 1042    * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
 1043    * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 1044    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 1045    * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
 1046    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 1047    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 1048    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 1049    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 1050    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 1051    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 1052    * POSSIBILITY OF SUCH DAMAGE.
 1053    *
 1054    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
 1055    */