1   
2   
3   
4   
5   
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     
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 
185 
186 
187 
188 
189 
190 
191 
192 
193 
194 
195 
196 
197 
198 
199 
200 
201 
202 
203 
204 
205 
206 
207 
208 
209 
210 
211 
212 
213 
214 
215 
216 
217 
218