001: package org.tigris.scarab.util;
002:
003: /* ================================================================
004: * Copyright (c) 2000-2002 CollabNet. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are
008: * met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowlegement: "This product includes
019: * software developed by Collab.Net <http://www.Collab.Net/>."
020: * Alternately, this acknowlegement may appear in the software itself, if
021: * and wherever such third-party acknowlegements normally appear.
022: *
023: * 4. The hosted project names must not be used to endorse or promote
024: * products derived from this software without prior written
025: * permission. For written permission, please contact info@collab.net.
026: *
027: * 5. Products derived from this software may not use the "Tigris" or
028: * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
029: * prior written permission of Collab.Net.
030: *
031: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
032: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
033: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
034: * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
035: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
036: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
037: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
038: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
039: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
040: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
041: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042: *
043: * ====================================================================
044: *
045: * This software consists of voluntary contributions made by many
046: * individuals on behalf of Collab.Net.
047: */
048:
049: import java.util.Collections;
050: import java.util.Iterator;
051: import java.util.NoSuchElementException;
052:
053: public class WindowIterator implements Iterator {
054: public static final WindowIterator EMPTY = new EmptyWindowIterator();
055: private static final Object NOT_INITIALIZED = new Object();
056:
057: private final Iterator i;
058: private final Object[] window;
059: private final int bsize;
060: private final int fsize;
061: private final int size;
062: private Boolean hasNext;
063:
064: /**
065: *
066: */
067: public WindowIterator(Iterator i, int backSize, int forwardSize) {
068: this .i = i;
069: this .fsize = Math.abs(forwardSize);
070: this .bsize = Math.abs(backSize);
071: size = fsize + bsize + 1;
072: window = new Object[size];
073:
074: for (int m = 0; m < size; m++) {
075: window[m] = NOT_INITIALIZED;
076: }
077: }
078:
079: public boolean hasNext() {
080: if (hasNext == null) {
081: hasNext = (internalIterate()) ? Boolean.TRUE
082: : Boolean.FALSE;
083: }
084: return hasNext.booleanValue();
085: }
086:
087: boolean firstCall = true;
088:
089: /*
090: int whatsLeft;
091: boolean internalIteratorHadNext = true;
092: private boolean internalIterate()
093: {
094: for (int i = 1; i < size; i++)
095: {
096: window[i-1] = window[i];
097: }
098: window[size-1] = NOT_INITIALIZED;
099:
100: boolean hasNext;
101: if (internalIteratorHadNext)
102: {
103: hasNext = i.hasNext();
104: internalIteratorHadNext = hasNext;
105: if (hasNext)
106: {
107: if (firstCall)
108: {
109: for (m = 0; m <= fsize && internalIteratorHadNext; m++)
110: {
111: window[bsize + m] = i.next();
112: internalIteratorHadNext = i.hasNext();
113: whatsLeft++;
114: }
115: firstCall = false;
116: }
117: else
118: {
119: window[size-1] = i.next();
120: }
121: }
122: }
123: else
124: {
125: hasNext = (whatsLeft > 0);
126: whatsLeft--;
127: }
128:
129: return hasNext;
130: }
131: */
132:
133: private boolean internalIterate() {
134: if (firstCall) {
135: for (int m = 0; m <= fsize && i.hasNext(); m++) {
136: window[bsize + m] = i.next();
137: }
138: firstCall = false;
139: } else {
140: for (int i = 1; i < size; i++) {
141: window[i - 1] = window[i];
142: }
143:
144: if (i.hasNext()) {
145: //System.out.println("WindowIterator: i.hasNext = true");
146: window[size - 1] = i.next();
147: } else {
148: //System.out.println("WindowIterator: i.hasNext = false");
149: window[size - 1] = NOT_INITIALIZED;
150: }
151: }
152:
153: return window[bsize] != NOT_INITIALIZED;
154: }
155:
156: public Object next() {
157: if (hasNext()) {
158: hasNext = null;
159: return window[bsize];
160: } else {
161: throw new NoSuchElementException("Iterator is exhausted"); //EXCEPTION
162: }
163: }
164:
165: public void remove() {
166: throw new UnsupportedOperationException(
167: "'remove' is not implemented"); //EXCEPTION
168: }
169:
170: /**
171: * Allows retrieving a given element some distance relative to the element
172: * last returned from next().
173: */
174: public Object get(int i) {
175: if (i < 0 && (-1 * i) > bsize) {
176: throw new ArrayIndexOutOfBoundsException(
177: "window was only defined "
178: + bsize
179: + " in the negative direction. Argument was "
180: + i); //EXCEPTION
181: }
182:
183: if (i > 0 && i > fsize) {
184: throw new ArrayIndexOutOfBoundsException(
185: "window was only defined "
186: + fsize
187: + " in the positive direction. Argument was "
188: + i); //EXCEPTION
189: }
190:
191: return window[bsize + i];
192: }
193:
194: public boolean hasValue(int i) {
195: return get(i) != NOT_INITIALIZED;
196: }
197: }
198:
199: class EmptyWindowIterator extends WindowIterator {
200: EmptyWindowIterator() {
201: super (Collections.EMPTY_SET.iterator(), 0, 0);
202: }
203:
204: public boolean hasNext() {
205: return false;
206: }
207:
208: public Object next() {
209: throw new NoSuchElementException("This is an empty list."); //EXCEPTION
210: }
211:
212: public void remove() {
213: throw new IllegalStateException(
214: "next() will throw exception, it is "
215: + "not possible to call this method."); //EXCEPTION
216: }
217:
218: public Object get(int i) {
219: throw new NoSuchElementException("This is an empty list."); //EXCEPTION
220: }
221:
222: public boolean hasValue(int i) {
223: return false;
224: }
225: }
|