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 */