001: // Copyright 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.ioc.util;
016:
017: import org.apache.tapestry.ioc.internal.util.CollectionFactory;
018:
019: /**
020: * A simple, streamlined implementation of {@link java.util.Stack}. The implementation is
021: * <em>not</em> threadsafe.
022: *
023: * @param <E>
024: * the type of elements stored in the map
025: * @see CollectionFactory#newStack()
026: */
027: public class Stack<E> {
028: private static final int MINIMUM_SIZE = 3;
029:
030: private static final int DEFAULT_ARRAY_SIZE = 20;
031:
032: private Object[] _items;
033:
034: private int _index = -1;
035:
036: /**
037: * Normal constructor supporting an initial size of 20.
038: */
039: public Stack() {
040: this (DEFAULT_ARRAY_SIZE);
041: }
042:
043: /**
044: * @param initialSize
045: * the initial size of the internal array (which will be expanded as necessary). For
046: * best efficiency, set this to the maximum depth of the stack.
047: */
048: public Stack(int initialSize) {
049: _items = new Object[Math.max(initialSize, MINIMUM_SIZE)];
050: }
051:
052: /** Returns true if the stack is empty. */
053: public boolean isEmpty() {
054: return _index < 0;
055: }
056:
057: /** Pushes a new item onto the stack. */
058: public void push(E item) {
059: _index++;
060:
061: if (_index == _items.length) {
062: int newCapacity = (_items.length * 3) / 2 + 1;
063: Object[] newItems = new Object[newCapacity];
064: System.arraycopy(_items, 0, newItems, 0, _items.length);
065:
066: _items = newItems;
067: }
068:
069: _items[_index] = item;
070: }
071:
072: /**
073: * Pops the top element off the stack and returns it.
074: *
075: * @return the top element of the stack
076: * @throws IllegalStateException
077: * if the stack is empty
078: */
079: @SuppressWarnings("unchecked")
080: public E pop() {
081: checkIfEmpty();
082:
083: Object result = _items[_index];
084:
085: _items[_index] = null;
086:
087: _index--;
088:
089: return (E) result;
090: }
091:
092: private void checkIfEmpty() {
093: if (_index < 0)
094: throw new IllegalStateException(UtilMessages.stackIsEmpty());
095: }
096:
097: /**
098: * Returns the top element of the stack without affecting the stack.
099: *
100: * @return top element on the stack
101: * @throws IllegalStateException
102: * if the stack is empty
103: */
104: @SuppressWarnings("unchecked")
105: public E peek() {
106: checkIfEmpty();
107:
108: return (E) _items[_index];
109: }
110:
111: /**
112: * Describes the stack, listing the element in order of depth (top element first).
113: *
114: * @return string description of the stack
115: */
116: @Override
117: public String toString() {
118: StringBuilder builder = new StringBuilder("Stack[");
119:
120: for (int i = _index; i >= 0; i--) {
121: if (i != _index)
122: builder.append(", ");
123:
124: builder.append(String.valueOf(_items[i]));
125: }
126:
127: builder.append("]");
128:
129: return builder.toString();
130: }
131: }
|