001/*
002 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
003 * 
004 * This software is open source. 
005 * See the bottom of this file for the licence.
006 * 
007 * $Id: ElementStack.java,v 1.5 2001/05/18 18:37:15 drwhite Exp $
008 */
009
010package org.dom4j.io;
011
012import java.util.ArrayList;
013
014import org.dom4j.Element;
015import org.dom4j.ElementPath;
016import org.dom4j.ElementHandler;
017
018/** <p><code>ElementStack</code> is used internally inside the 
019  * {@link SAXContentHandler} to maintain a stack of {@link Element} 
020  * instances. 
021  * It opens an integration possibility allowing derivations to prune the tree
022  * when a node is complete.</p>
023  *
024  * @author <a href="mailto:james.strachan@metastuff.com">James Strachan</a>
025  * @version $Revision: 1.5 $
026  */
027class ElementStack implements ElementPath {
028
029    /** stack of <code>Element</code> objects */
030    protected Element[] stack;
031    
032    /** index of the item at the top of the stack or -1 if the stack is empty */
033    protected int lastElementIndex = -1;
034    
035    private DispatchHandler handler = null;
036
037    
038    public ElementStack() {
039        this(50);
040    }
041    
042    public ElementStack(int defaultCapacity) {
043        stack = new Element[defaultCapacity];
044    }
045    
046    public void setDispatchHandler(DispatchHandler handler)
047    {
048        this.handler = handler;   
049    }
050    
051    /** Peeks at the top element on the stack without changing the contents
052      * of the stack.
053      * 
054      * @return the current element on the stack 
055      */
056    public void clear() {
057        lastElementIndex = -1;
058    }
059    
060    /** Peeks at the top element on the stack without changing the contents
061      * of the stack.
062      * 
063      * @return the current element on the stack 
064      */
065    public Element peekElement() {
066        if ( lastElementIndex < 0 ) { 
067            return null;
068        }
069        return stack[ lastElementIndex ];
070    }
071    
072    /** Pops the element off the stack
073      *
074      * @return the element that has just been popped off the stack 
075      */
076    public Element popElement() {
077        if ( lastElementIndex < 0 ) { 
078            return null;
079        }
080        return stack[ lastElementIndex-- ];
081    }
082    
083    /** Pushes a new element onto the stack
084      * 
085      * @return pushes the new element onto the stack and add it to its parent
086      * if there is one.
087      */
088    public void pushElement(Element element) {
089        int length = stack.length;
090        if ( ++lastElementIndex >= length ) {
091            reallocate( length * 2 );
092        }
093        stack[lastElementIndex] = element;
094    }
095    
096    /** Reallocates the stack to the given size
097      */
098    protected void reallocate( int size ) {
099        Element[] oldStack = stack;
100        stack = new Element[ size ];
101        System.arraycopy( oldStack, 0, stack, 0, oldStack.length );
102    }
103    
104    // The ElementPath Interface
105    //
106    public int size()
107    {
108        return stack.length;
109    }
110    
111    public Element getElement(int depth)
112    {
113        Element element;
114        try {
115            element = (Element)stack[depth];   
116        }
117        catch (ArrayIndexOutOfBoundsException e)
118        {
119            element = null;   
120        }
121        return element;
122    }
123    
124    public String getPath()
125    {
126        if (handler == null) {
127            setDispatchHandler(new DispatchHandler());
128        }
129        return handler.getPath();
130    }
131    
132    public Element getCurrent()
133    {
134        return peekElement();   
135    }
136    
137    public void addHandler(String path, ElementHandler handler) {
138        this.handler.addHandler(getHandlerPath(path), handler);
139    }
140    
141    public void removeHandler(String path) {
142        this.handler.removeHandler(getHandlerPath(path));
143    }
144    
145    private String getHandlerPath(String path) {
146        String handlerPath;
147        if (this.handler == null) {
148            setDispatchHandler(new DispatchHandler());
149        }
150        if (path.startsWith("/")) {
151            handlerPath = path;   
152        }
153        else if (getPath().equals("/")) {
154            handlerPath = getPath() + path;
155        }
156        else {
157            handlerPath = getPath() + "/" + path;   
158        }
159        return handlerPath;
160    }
161}
162
163
164
165
166/*
167 * Redistribution and use of this software and associated documentation
168 * ("Software"), with or without modification, are permitted provided
169 * that the following conditions are met:
170 *
171 * 1. Redistributions of source code must retain copyright
172 *    statements and notices.  Redistributions must also contain a
173 *    copy of this document.
174 *
175 * 2. Redistributions in binary form must reproduce the
176 *    above copyright notice, this list of conditions and the
177 *    following disclaimer in the documentation and/or other
178 *    materials provided with the distribution.
179 *
180 * 3. The name "DOM4J" must not be used to endorse or promote
181 *    products derived from this Software without prior written
182 *    permission of MetaStuff, Ltd.  For written permission,
183 *    please contact dom4j-info@metastuff.com.
184 *
185 * 4. Products derived from this Software may not be called "DOM4J"
186 *    nor may "DOM4J" appear in their names without prior written
187 *    permission of MetaStuff, Ltd. DOM4J is a registered
188 *    trademark of MetaStuff, Ltd.
189 *
190 * 5. Due credit should be given to the DOM4J Project
191 *    (http://dom4j.org/).
192 *
193 * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
194 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
195 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
196 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
197 * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
198 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
199 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
200 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
201 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
202 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
203 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
204 * OF THE POSSIBILITY OF SUCH DAMAGE.
205 *
206 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
207 *
208 * $Id: ElementStack.java,v 1.5 2001/05/18 18:37:15 drwhite Exp $
209 */