001: /*
002: * Copyright 2003-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.collections.list;
017:
018: import java.util.List;
019:
020: import org.apache.commons.collections.Factory;
021:
022: /**
023: * Decorates another <code>List</code> to create objects in the list on demand.
024: * <p>
025: * When the {@link #get(int)} method is called with an index greater than
026: * the size of the list, the list will automatically grow in size and return
027: * a new object from the specified factory. The gaps will be filled by null.
028: * If a get method call encounters a null, it will be replaced with a new
029: * object from the factory. Thus this list is unsuitable for storing null
030: * objects.
031: * <p>
032: * For instance:
033: *
034: * <pre>
035: * Factory factory = new Factory() {
036: * public Object create() {
037: * return new Date();
038: * }
039: * }
040: * List lazy = LazyList.decorate(new ArrayList(), factory);
041: * Object obj = lazy.get(3);
042: * </pre>
043: *
044: * After the above code is executed, <code>obj</code> will contain
045: * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
046: * instance is the fourth element in the list. The first, second,
047: * and third element are all set to <code>null</code>.
048: * <p>
049: * This class differs from {@link GrowthList} because here growth occurs on
050: * get, where <code>GrowthList</code> grows on set and add. However, they
051: * could easily be used together by decorating twice.
052: * <p>
053: * This class is Serializable from Commons Collections 3.1.
054: *
055: * @see GrowthList
056: * @since Commons Collections 3.0
057: * @version $Revision: 170244 $ $Date: 2005-05-15 19:30:49 +0100 (Sun, 15 May 2005) $
058: *
059: * @author Stephen Colebourne
060: * @author Arron Bates
061: * @author Paul Jack
062: */
063: public class LazyList extends AbstractSerializableListDecorator {
064:
065: /** Serialization version */
066: private static final long serialVersionUID = -1708388017160694542L;
067:
068: /** The factory to use to lazily instantiate the objects */
069: protected final Factory factory;
070:
071: /**
072: * Factory method to create a lazily instantiating list.
073: *
074: * @param list the list to decorate, must not be null
075: * @param factory the factory to use for creation, must not be null
076: * @throws IllegalArgumentException if list or factory is null
077: */
078: public static List decorate(List list, Factory factory) {
079: return new LazyList(list, factory);
080: }
081:
082: //-----------------------------------------------------------------------
083: /**
084: * Constructor that wraps (not copies).
085: *
086: * @param list the list to decorate, must not be null
087: * @param factory the factory to use for creation, must not be null
088: * @throws IllegalArgumentException if list or factory is null
089: */
090: protected LazyList(List list, Factory factory) {
091: super (list);
092: if (factory == null) {
093: throw new IllegalArgumentException(
094: "Factory must not be null");
095: }
096: this .factory = factory;
097: }
098:
099: //-----------------------------------------------------------------------
100: /**
101: * Decorate the get method to perform the lazy behaviour.
102: * <p>
103: * If the requested index is greater than the current size, the list will
104: * grow to the new size and a new object will be returned from the factory.
105: * Indexes in-between the old size and the requested size are left with a
106: * placeholder that is replaced with a factory object when requested.
107: *
108: * @param index the index to retrieve
109: */
110: public Object get(int index) {
111: int size = getList().size();
112: if (index < size) {
113: // within bounds, get the object
114: Object object = getList().get(index);
115: if (object == null) {
116: // item is a place holder, create new one, set and return
117: object = factory.create();
118: getList().set(index, object);
119: return object;
120: } else {
121: // good and ready to go
122: return object;
123: }
124: } else {
125: // we have to grow the list
126: for (int i = size; i < index; i++) {
127: getList().add(null);
128: }
129: // create our last object, set and return
130: Object object = factory.create();
131: getList().add(object);
132: return object;
133: }
134: }
135:
136: public List subList(int fromIndex, int toIndex) {
137: List sub = getList().subList(fromIndex, toIndex);
138: return new LazyList(sub, factory);
139: }
140:
141: }
|