1. /*
  2. * Copyright 2003-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.collections.list;
  17. import java.util.List;
  18. import org.apache.commons.collections.Factory;
  19. /**
  20. * Decorates another <code>List</code> to create objects in the list on demand.
  21. * <p>
  22. * When the {@link #get(int)} method is called with an index greater than
  23. * the size of the list, the list will automatically grow in size and return
  24. * a new object from the specified factory. The gaps will be filled by null.
  25. * If a get method call encounters a null, it will be replaced with a new
  26. * object from the factory. Thus this list is unsuitable for storing null
  27. * objects.
  28. * <p>
  29. * For instance:
  30. *
  31. * <pre>
  32. * Factory factory = new Factory() {
  33. * public Object create() {
  34. * return new Date();
  35. * }
  36. * }
  37. * List lazy = LazyList.decorate(new ArrayList(), factory);
  38. * Object obj = lazy.get(3);
  39. * </pre>
  40. *
  41. * After the above code is executed, <code>obj</code> will contain
  42. * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
  43. * instance is the fourth element in the list. The first, second,
  44. * and third element are all set to <code>null</code>.
  45. * <p>
  46. * This class is Serializable from Commons Collections 3.1.
  47. *
  48. * @since Commons Collections 3.0
  49. * @version $Revision: 1.6 $ $Date: 2004/06/03 22:02:13 $
  50. *
  51. * @author Stephen Colebourne
  52. * @author Arron Bates
  53. * @author Paul Jack
  54. */
  55. public class LazyList extends AbstractSerializableListDecorator {
  56. /** Serialization version */
  57. private static final long serialVersionUID = -1708388017160694542L;
  58. /** The factory to use to lazily instantiate the objects */
  59. protected final Factory factory;
  60. /**
  61. * Factory method to create a lazily instantiating list.
  62. *
  63. * @param list the list to decorate, must not be null
  64. * @param factory the factory to use for creation, must not be null
  65. * @throws IllegalArgumentException if list or factory is null
  66. */
  67. public static List decorate(List list, Factory factory) {
  68. return new LazyList(list, factory);
  69. }
  70. //-----------------------------------------------------------------------
  71. /**
  72. * Constructor that wraps (not copies).
  73. *
  74. * @param list the list to decorate, must not be null
  75. * @param factory the factory to use for creation, must not be null
  76. * @throws IllegalArgumentException if list or factory is null
  77. */
  78. protected LazyList(List list, Factory factory) {
  79. super(list);
  80. if (factory == null) {
  81. throw new IllegalArgumentException("Factory must not be null");
  82. }
  83. this.factory = factory;
  84. }
  85. //-----------------------------------------------------------------------
  86. /**
  87. * Decorate the get method to perform the lazy behaviour.
  88. * <p>
  89. * If the requested index is greater than the current size, the list will
  90. * grow to the new size and a new object will be returned from the factory.
  91. * Indexes in-between the old size and the requested size are left with a
  92. * placeholder that is replaced with a factory object when requested.
  93. *
  94. * @param index the index to retrieve
  95. */
  96. public Object get(int index) {
  97. int size = getList().size();
  98. if (index < size) {
  99. // within bounds, get the object
  100. Object object = getList().get(index);
  101. if (object == null) {
  102. // item is a place holder, create new one, set and return
  103. object = factory.create();
  104. getList().set(index, object);
  105. return object;
  106. } else {
  107. // good and ready to go
  108. return object;
  109. }
  110. } else {
  111. // we have to grow the list
  112. for (int i = size; i < index; i++) {
  113. getList().add(null);
  114. }
  115. // create our last object, set and return
  116. Object object = factory.create();
  117. getList().add(object);
  118. return object;
  119. }
  120. }
  121. public List subList(int fromIndex, int toIndex) {
  122. List sub = getList().subList(fromIndex, toIndex);
  123. return new LazyList(sub, factory);
  124. }
  125. }