001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2004-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2004, Institut de Recherche pour le Développement
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.resources;
018:
019: // J2SE direct dependencies
020: import java.util.AbstractSet;
021: import java.util.Iterator;
022:
023: /**
024: * An immutable set built from an iterator, which will be filled only when needed. This
025: * implementation do <strong>not</strong> check if all elements in the iterator are really
026: * unique; we assume that it was already verified by {@link javax.imageio.spi.ServiceRegistry}.
027: * This set is constructed by {@link org.geotools.referencing.FactoryFinder}.
028: *
029: * @since 2.0
030: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/resources/LazySet.java $
031: * @version $Id: LazySet.java 22443 2006-10-27 20:47:22Z desruisseaux $
032: * @author Martin Desruisseaux
033: */
034: public final class LazySet extends AbstractSet {
035: /**
036: * The iterator to use for filling this set.
037: */
038: private final Iterator iterator;
039:
040: /**
041: * The elements in this set. This array will grown as needed.
042: */
043: private Object[] elements = new Object[4];
044:
045: /**
046: * The current size of this set. This size will increases as long as there is some elements
047: * remaining in the iterator. This is <strong>not</strong> the size returned by {@link #size()}.
048: */
049: private int size;
050:
051: /**
052: * Construct a set to be filled using the specified iterator.
053: * Iteration in the given iterator will occurs only when needed.
054: */
055: public LazySet(final Iterator iterator) {
056: this .iterator = iterator;
057: }
058:
059: /**
060: * Add the next element from the iterator to this set. This method doesn't check
061: * if more element were available; the check must have been done before to invoke
062: * this method.
063: */
064: private void addNext() {
065: if (size >= elements.length) {
066: final Object[] old = elements;
067: elements = new Object[size * 2];
068: System.arraycopy(old, 0, elements, 0, size);
069: }
070: elements[size++] = iterator.next();
071: }
072:
073: /**
074: * Returns an iterator over the elements contained in this set.
075: * This is not the same iterator than the one given to the constructor.
076: */
077: public Iterator iterator() {
078: return new Iter();
079: }
080:
081: /**
082: * Returns the number of elements in this set. Invoking this method
083: * force the set to immediately iterates through all remaining elements.
084: */
085: public int size() {
086: while (iterator.hasNext()) {
087: addNext();
088: }
089: return size;
090: }
091:
092: /**
093: * Tests if this set has no elements.
094: */
095: public boolean isEmpty() {
096: return size == 0 && !iterator.hasNext();
097: }
098:
099: /**
100: * Returns {@code true} if an element exists at the given index.
101: * The element is not loaded immediately.
102: *
103: * <strong>NOTE: This method is for use by iterators only.</strong>
104: * It is not suited for more general usage since it doesn't check
105: * for negative index and for skipped elements.
106: */
107: final boolean exists(final int index) {
108: return index < size || iterator.hasNext();
109: }
110:
111: /**
112: * Returns the element at the specified position in this set.
113: */
114: public Object get(final int index) {
115: while (index >= size) {
116: if (!iterator.hasNext()) {
117: throw new IndexOutOfBoundsException(String
118: .valueOf(index));
119: }
120: addNext();
121: }
122: return elements[index];
123: }
124:
125: /**
126: * The iterator implementation for the {@linkplain LazySet lazy set}.
127: */
128: private final class Iter implements Iterator {
129: /** Index of the next element to be returned. */
130: private int cursor;
131:
132: /** Check if there is more elements. */
133: public boolean hasNext() {
134: return exists(cursor);
135: }
136:
137: /** Returns the next element. */
138: public Object next() {
139: return get(cursor++);
140: }
141:
142: /** Always throws an exception, since {@link LazySet} are immutable. */
143: public void remove() {
144: throw new UnsupportedOperationException();
145: }
146: }
147: }
|