View Javadoc

    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.util;
    9
    10  import java.util.ArrayList;
    11  import java.util.HashMap;
    12  import java.util.Iterator;
    13  import java.util.List;
    14  import java.util.Map;
    15
    16  import org.dom4j.Attribute;
    17  import org.dom4j.Element;
    18  import org.dom4j.Node;
    19  import org.dom4j.QName;
    20  import org.dom4j.tree.BackedList;
    21  import org.dom4j.tree.DefaultElement;
    22
    23  /***
    24   * <p>
    25   * <code>IndexedElement</code> is an implementation of {@link Element}which
    26   * maintains an index of the attributes and elements it contains to optimise
    27   * lookups via name.
    28   * </p>
    29   *
    30   * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
    31   * @version $Revision: 1.10 $
    32   */
    33  public class IndexedElement extends DefaultElement {
    34      /*** Lazily constructed index for elements */
    35      private Map elementIndex;
    36
    37      /*** Lazily constructed index for attributes */
    38      private Map attributeIndex;
    39
    40      public IndexedElement(String name) {
    41          super(name);
    42      }
    43
    44      public IndexedElement(QName qname) {
    45          super(qname);
    46      }
    47
    48      public IndexedElement(QName qname, int attributeCount) {
    49          super(qname, attributeCount);
    50      }
    51
    52      public Attribute attribute(String name) {
    53          return (Attribute) attributeIndex().get(name);
    54      }
    55
    56      public Attribute attribute(QName qName) {
    57          return (Attribute) attributeIndex().get(qName);
    58      }
    59
    60      public Element element(String name) {
    61          return asElement(elementIndex().get(name));
    62      }
    63
    64      public Element element(QName qName) {
    65          return asElement(elementIndex().get(qName));
    66      }
    67
    68      public List elements(String name) {
    69          return asElementList(elementIndex().get(name));
    70      }
    71
    72      public List elements(QName qName) {
    73          return asElementList(elementIndex().get(qName));
    74      }
    75
    76      // Implementation methods
    77      // -------------------------------------------------------------------------
    78      protected Element asElement(Object object) {
    79          if (object instanceof Element) {
    80              return (Element) object;
    81          } else if (object != null) {
    82              List list = (List) object;
    83
    84              if (list.size() >= 1) {
    85                  return (Element) list.get(0);
    86              }
    87          }
    88
    89          return null;
    90      }
    91
    92      protected List asElementList(Object object) {
    93          if (object instanceof Element) {
    94              return createSingleResultList(object);
    95          } else if (object != null) {
    96              List list = (List) object;
    97              BackedList answer = createResultList();
    98
    99              for (int i = 0, size = list.size(); i < size; i++) {
    100                 answer.addLocal(list.get(i));
    101             }
    102
    103             return answer;
    104         }
    105
    106         return createEmptyList();
    107     }
    108
    109     /***
    110      * DOCUMENT ME!
    111      *
    112      * @param object
    113      *            DOCUMENT ME!
    114      *
    115      * @return DOCUMENT ME!
    116      *
    117      * @deprecated WILL BE REMOVED IN dom4j-1.6 !!
    118      */
    119     protected Iterator asElementIterator(Object object) {
    120         return asElementList(object).iterator();
    121     }
    122
    123     // #### could we override the add(Element) remove(Element methods?
    124     protected void addNode(Node node) {
    125         super.addNode(node);
    126
    127         if ((elementIndex != null) && node instanceof Element) {
    128             addToElementIndex((Element) node);
    129         } else if ((attributeIndex != null) && node instanceof Attribute) {
    130             addToAttributeIndex((Attribute) node);
    131         }
    132     }
    133
    134     protected boolean removeNode(Node node) {
    135         if (super.removeNode(node)) {
    136             if ((elementIndex != null) && node instanceof Element) {
    137                 removeFromElementIndex((Element) node);
    138             } else if ((attributeIndex != null) && node instanceof Attribute) {
    139                 removeFromAttributeIndex((Attribute) node);
    140             }
    141
    142             return true;
    143         }
    144
    145         return false;
    146     }
    147
    148     protected Map attributeIndex() {
    149         if (attributeIndex == null) {
    150             attributeIndex = createAttributeIndex();
    151
    152             for (Iterator iter = attributeIterator(); iter.hasNext();) {
    153                 addToAttributeIndex((Attribute) iter.next());
    154             }
    155         }
    156
    157         return attributeIndex;
    158     }
    159
    160     protected Map elementIndex() {
    161         if (elementIndex == null) {
    162             elementIndex = createElementIndex();
    163
    164             for (Iterator iter = elementIterator(); iter.hasNext();) {
    165                 addToElementIndex((Element) iter.next());
    166             }
    167         }
    168
    169         return elementIndex;
    170     }
    171
    172     /***
    173      * A Factory Method to create the index for attributes
    174      *
    175      * @return DOCUMENT ME!
    176      */
    177     protected Map createAttributeIndex() {
    178         Map answer = createIndex();
    179
    180         return answer;
    181     }
    182
    183     /***
    184      * A Factory Method to create the index for elements
    185      *
    186      * @return DOCUMENT ME!
    187      */
    188     protected Map createElementIndex() {
    189         Map answer = createIndex();
    190
    191         return answer;
    192     }
    193
    194     protected void addToElementIndex(Element element) {
    195         QName qName = element.getQName();
    196         String name = qName.getName();
    197         addToElementIndex(qName, element);
    198         addToElementIndex(name, element);
    199     }
    200
    201     protected void addToElementIndex(Object key, Element value) {
    202         Object oldValue = elementIndex.get(key);
    203
    204         if (oldValue == null) {
    205             elementIndex.put(key, value);
    206         } else {
    207             if (oldValue instanceof List) {
    208                 List list = (List) oldValue;
    209                 list.add(value);
    210             } else {
    211                 List list = createList();
    212                 list.add(oldValue);
    213                 list.add(value);
    214                 elementIndex.put(key, list);
    215             }
    216         }
    217     }
    218
    219     protected void removeFromElementIndex(Element element) {
    220         QName qName = element.getQName();
    221         String name = qName.getName();
    222         removeFromElementIndex(qName, element);
    223         removeFromElementIndex(name, element);
    224     }
    225
    226     protected void removeFromElementIndex(Object key, Element value) {
    227         Object oldValue = elementIndex.get(key);
    228
    229         if (oldValue instanceof List) {
    230             List list = (List) oldValue;
    231             list.remove(value);
    232         } else {
    233             elementIndex.remove(key);
    234         }
    235     }
    236
    237     protected void addToAttributeIndex(Attribute attribute) {
    238         QName qName = attribute.getQName();
    239         String name = qName.getName();
    240         addToAttributeIndex(qName, attribute);
    241         addToAttributeIndex(name, attribute);
    242     }
    243
    244     protected void addToAttributeIndex(Object key, Attribute value) {
    245         Object oldValue = attributeIndex.get(key);
    246
    247         if (oldValue != null) {
    248             attributeIndex.put(key, value);
    249         }
    250     }
    251
    252     protected void removeFromAttributeIndex(Attribute attribute) {
    253         QName qName = attribute.getQName();
    254         String name = qName.getName();
    255         removeFromAttributeIndex(qName, attribute);
    256         removeFromAttributeIndex(name, attribute);
    257     }
    258
    259     protected void removeFromAttributeIndex(Object key, Attribute value) {
    260         Object oldValue = attributeIndex.get(key);
    261
    262         if ((oldValue != null) && oldValue.equals(value)) {
    263             attributeIndex.remove(key);
    264         }
    265     }
    266
    267     /***
    268      * Factory method to return a new map implementation for indices
    269      *
    270      * @return DOCUMENT ME!
    271      */
    272     protected Map createIndex() {
    273         return new HashMap();
    274     }
    275
    276     /***
    277      * Factory method to return a list implementation for indices
    278      *
    279      * @return DOCUMENT ME!
    280      */
    281     protected List createList() {
    282         return new ArrayList();
    283     }
    284 }
    285
    286 /*
    287  * Redistribution and use of this software and associated documentation
    288  * ("Software"), with or without modification, are permitted provided that the
    289  * following conditions are met:
    290  *
    291  * 1. Redistributions of source code must retain copyright statements and
    292  * notices. Redistributions must also contain a copy of this document.
    293  *
    294  * 2. Redistributions in binary form must reproduce the above copyright notice,
    295  * this list of conditions and the following disclaimer in the documentation
    296  * and/or other materials provided with the distribution.
    297  *
    298  * 3. The name "DOM4J" must not be used to endorse or promote products derived
    299  * from this Software without prior written permission of MetaStuff, Ltd. For
    300  * written permission, please contact dom4j-info@metastuff.com.
    301  *
    302  * 4. Products derived from this Software may not be called "DOM4J" nor may
    303  * "DOM4J" appear in their names without prior written permission of MetaStuff,
    304  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
    305  *
    306  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
    307  *
    308  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
    309  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    310  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    311  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
    312  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    313  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    314  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    315  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    316  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    317  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    318  * POSSIBILITY OF SUCH DAMAGE.
    319  *
    320  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
    321  */