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.io;
9   
10  import org.dom4j.Element;
11  import org.dom4j.ElementHandler;
12  import org.dom4j.ElementPath;
13  
14  /***
15   * <p>
16   * <code>ElementStack</code> is used internally inside the {@link
17   * SAXContentHandler} to maintain a stack of {@link Element}instances. It opens
18   * an integration possibility allowing derivations to prune the tree when a node
19   * is complete.
20   * </p>
21   * 
22   * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
23   * @version $Revision: 1.14 $
24   */
25  class ElementStack implements ElementPath {
26      /*** stack of <code>Element</code> objects */
27      protected Element[] stack;
28  
29      /*** index of the item at the top of the stack or -1 if the stack is empty */
30      protected int lastElementIndex = -1;
31  
32      private DispatchHandler handler = null;
33  
34      public ElementStack() {
35          this(50);
36      }
37  
38      public ElementStack(int defaultCapacity) {
39          stack = new Element[defaultCapacity];
40      }
41  
42      public void setDispatchHandler(DispatchHandler dispatchHandler) {
43          this.handler = dispatchHandler;
44      }
45  
46      public DispatchHandler getDispatchHandler() {
47          return this.handler;
48      }
49  
50      /***
51       * Peeks at the top element on the stack without changing the contents of
52       * the stack.
53       */
54      public void clear() {
55          lastElementIndex = -1;
56      }
57  
58      /***
59       * Peeks at the top element on the stack without changing the contents of
60       * the stack.
61       * 
62       * @return the current element on the stack
63       */
64      public Element peekElement() {
65          if (lastElementIndex < 0) {
66              return null;
67          }
68  
69          return stack[lastElementIndex];
70      }
71  
72      /***
73       * Pops the element off the stack
74       * 
75       * @return the element that has just been popped off the stack
76       */
77      public Element popElement() {
78          if (lastElementIndex < 0) {
79              return null;
80          }
81  
82          return stack[lastElementIndex--];
83      }
84  
85      /***
86       * Pushes a new element onto the stack
87       * 
88       * @param element
89       *            DOCUMENT ME!
90       */
91      public void pushElement(Element element) {
92          int length = stack.length;
93  
94          if (++lastElementIndex >= length) {
95              reallocate(length * 2);
96          }
97  
98          stack[lastElementIndex] = element;
99      }
100 
101     /***
102      * Reallocates the stack to the given size
103      * 
104      * @param size
105      *            DOCUMENT ME!
106      */
107     protected void reallocate(int size) {
108         Element[] oldStack = stack;
109         stack = new Element[size];
110         System.arraycopy(oldStack, 0, stack, 0, oldStack.length);
111     }
112 
113     // The ElementPath Interface
114     //
115     public int size() {
116         return lastElementIndex + 1;
117     }
118 
119     public Element getElement(int depth) {
120         Element element;
121 
122         try {
123             element = (Element) stack[depth];
124         } catch (ArrayIndexOutOfBoundsException e) {
125             element = null;
126         }
127 
128         return element;
129     }
130 
131     public String getPath() {
132         if (handler == null) {
133             setDispatchHandler(new DispatchHandler());
134         }
135 
136         return handler.getPath();
137     }
138 
139     public Element getCurrent() {
140         return peekElement();
141     }
142 
143     public void addHandler(String path, ElementHandler elementHandler) {
144         this.handler.addHandler(getHandlerPath(path), elementHandler);
145     }
146 
147     public void removeHandler(String path) {
148         this.handler.removeHandler(getHandlerPath(path));
149     }
150 
151     /***
152      * DOCUMENT ME!
153      * 
154      * @param path
155      *            DOCUMENT ME!
156      * 
157      * @return true when an <code>ElementHandler</code> is registered for the
158      *         specified path.
159      */
160     public boolean containsHandler(String path) {
161         return this.handler.containsHandler(path);
162     }
163 
164     private String getHandlerPath(String path) {
165         String handlerPath;
166 
167         if (this.handler == null) {
168             setDispatchHandler(new DispatchHandler());
169         }
170 
171         if (path.startsWith("/")) {
172             handlerPath = path;
173         } else if (getPath().equals("/")) {
174             handlerPath = getPath() + path;
175         } else {
176             handlerPath = getPath() + "/" + path;
177         }
178 
179         return handlerPath;
180     }
181 }
182 
183 /*
184  * Redistribution and use of this software and associated documentation
185  * ("Software"), with or without modification, are permitted provided that the
186  * following conditions are met:
187  * 
188  * 1. Redistributions of source code must retain copyright statements and
189  * notices. Redistributions must also contain a copy of this document.
190  * 
191  * 2. Redistributions in binary form must reproduce the above copyright notice,
192  * this list of conditions and the following disclaimer in the documentation
193  * and/or other materials provided with the distribution.
194  * 
195  * 3. The name "DOM4J" must not be used to endorse or promote products derived
196  * from this Software without prior written permission of MetaStuff, Ltd. For
197  * written permission, please contact dom4j-info@metastuff.com.
198  * 
199  * 4. Products derived from this Software may not be called "DOM4J" nor may
200  * "DOM4J" appear in their names without prior written permission of MetaStuff,
201  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
202  * 
203  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
204  * 
205  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
206  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
207  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
208  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
209  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
210  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
211  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
212  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
213  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
214  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
215  * POSSIBILITY OF SUCH DAMAGE.
216  * 
217  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
218  */