LazyList.java
/*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2015-2016 ForgeRock AS.
*/
package org.forgerock.util;
// Java SE
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* A list with lazy initialization. The factory is called to initialize the list
* on the first call to one of this object's methods.
*
* @param <E>
* The type of element contained in this list.
*/
public class LazyList<E> implements List<E> {
/** The list that this lazy list exposes, once initialized. */
private List<E> list;
/** Factory to create the instance of the list to expose. */
protected Factory<List<E>> factory;
/**
* Constructs a new lazy list. Allows factory to be set in subclass
* constructor.
*/
protected LazyList() {
}
/**
* Constructs a new lazy list.
*
* @param factory
* factory to create the list instance to expose.
*/
public LazyList(Factory<List<E>> factory) {
this.factory = factory;
}
/**
* Performs lazy initialization of the list if not already performed, and
* returns the initialized list.
*/
private List<E> lazy() {
if (list == null) {
synchronized (this) {
if (list == null) {
list = factory.newInstance();
}
}
}
return list;
}
/**
* Returns the number of elements in this list.
*/
@Override
public int size() {
return lazy().size();
}
/**
* Returns {@code true} if this list contains no elements.
*/
@Override
public boolean isEmpty() {
return lazy().isEmpty();
}
/**
* Returns {@code true} if this list contains the specified element.
*
* @param o
* the element whose presence in this list is to be tested.
* @return {@code true} if this list contains the specified element.
*/
@Override
public boolean contains(Object o) {
return lazy().contains(o);
}
/**
* Returns an iterator over the elements in this list in proper sequence.
*/
@Override
public Iterator<E> iterator() {
return lazy().iterator();
}
/**
* Returns an array containing all of the elements in this list in proper
* sequence (from first to last element).
*/
@Override
public Object[] toArray() {
return lazy().toArray();
}
/**
* Returns an array containing all of the elements in this list in proper
* sequence (from first to last element); the runtime type of the returned
* array is that of the specified array. If the list fits in the specified
* array, it is returned therein. Otherwise, a new array is allocated with
* the runtime type of the specified array and the size of this list.
*
* @param a
* the array into which the elements of this list are to be
* stored.
* @return an array containing the elements of this list.
*/
@Override
public <T> T[] toArray(T[] a) {
return lazy().toArray(a);
}
/**
* Appends the specified element to the end of this list.
*
* @param e
* the element to be appended to this list.
* @return {@code true} if this list changed as a result of the call.
*/
@Override
public boolean add(E e) {
return lazy().add(e);
}
/**
* Removes the first occurrence of the specified element from this list, if
* it is present.
*
* @param o
* the element to be removed from this list, if present.
* @return true if this list contained the specified element.
*/
@Override
public boolean remove(Object o) {
return lazy().remove(o);
}
/**
* Returns {@code true} if this list contains all of the elements of the
* specified collection.
*
* @param c
* the collection to be checked for containment in this list.
* @return {@code true} if this list contains all of the elements of the
* specified collection.
*/
@Override
public boolean containsAll(Collection<?> c) {
return lazy().containsAll(c);
}
/**
* Appends all of the elements in the specified collection to the end of
* this list, in the order that they are returned by the specified
* collection's iterator.
*
* @param c
* the collection containing elements to be added to this list.
* @return {@code true} if this list changed as a result of the call.
*/
@Override
public boolean addAll(Collection<? extends E> c) {
return lazy().addAll(c);
}
/**
* Inserts all of the elements in the specified collection into this list at
* the specified position.
*
* @param index
* the index at which to insert the first element from the
* specified collection.
* @param c
* the collection containing elements to be added to this list.
* @return {@code true} if this list changed as a result of the call.
*/
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return lazy().addAll(index, c);
}
/**
* Removes from this list all of its elements that are contained in the
* specified collection.
*
* @param c
* the collection containing elements to be removed from this
* list.
* @return {@code true} if this list changed as a result of the call.
*/
@Override
public boolean removeAll(Collection<?> c) {
return lazy().removeAll(c);
}
/**
* Retains only the elements in this list that are contained in the
* specified collection.
*
* @param c
* the collection containing elements to be retained in this
* list.
* @return {@code true} if this list changed as a result of the call.
*/
@Override
public boolean retainAll(Collection<?> c) {
return lazy().retainAll(c);
}
/**
* Removes all of the elements from this list.
*/
@Override
public void clear() {
lazy().clear();
}
/**
* Compares the specified object with this list for equality.
*
* @param o
* the object to be compared for equality with this list.
* @return {@code true} if the specified object is equal to this list.
*/
@Override
public boolean equals(Object o) {
return lazy().equals(o);
}
/**
* Returns the hash code value for this list.
*/
@Override
public int hashCode() {
return lazy().hashCode();
}
/**
* Returns the element at the specified position in this list.
*
* @param index
* the index of the element to return.
* @return the element at the specified position in this list.
*/
@Override
public E get(int index) {
return lazy().get(index);
}
/**
* Replaces the element at the specified position in this list with the
* specified element.
*
* @param index
* the index of the element to replace.
* @param element
* the element to be stored at the specified position.
* @return the element previously at the specified position.
*/
@Override
public E set(int index, E element) {
return lazy().set(index, element);
}
/**
* Inserts the specified element at the specified position in this list.
*
* @param index
* the index at which the specified element is to be inserted.
* @param element
* the element to be inserted.
*/
@Override
public void add(int index, E element) {
lazy().add(index, element);
}
/**
* Removes the element at the specified position in this list.
*
* @param index
* the index of the element to be removed.
* @return the element previously at the specified position.
*/
@Override
public E remove(int index) {
return lazy().remove(index);
}
/**
* Returns the index of the first occurrence of the specified element in
* this list, or {@code -1} if this list does not contain the element.
*
* @param o
* element to search for.
* @return the index of the first occurrence, or {@code -1} if no such
* element.
*/
@Override
public int indexOf(Object o) {
return lazy().indexOf(o);
}
/**
* Returns the index of the last occurrence of the specified element in this
* list, or {@code -1} if this list does not contain the element.
*
* @param o
* the element to search for.
* @return the index of the last occurrence, or {@code -1} if no such
* element.
*/
@Override
public int lastIndexOf(Object o) {
return lazy().lastIndexOf(o);
}
/**
* Returns a list iterator over the elements in this list (in proper
* sequence).
*/
@Override
public ListIterator<E> listIterator() {
return lazy().listIterator();
}
/**
* Returns a list iterator over the elements in this list (in proper
* sequence), starting at the specified position in the list.
*
* @param index
* the index of the first element to be returned from the list
* iterator.
* @return a list iterator, starting at the specified position in the list.
*/
@Override
public ListIterator<E> listIterator(int index) {
return lazy().listIterator(index);
}
/**
* Returns a view of the portion of this list between the specified
* fromIndex, inclusive, and toIndex, exclusive.
*
* @param fromIndex
* low endpoint (inclusive) of the subList.
* @param toIndex
* high endpoint (exclusive) of the subList.
* @return a view of the specified range within this list.
*/
@Override
public List<E> subList(int fromIndex, int toIndex) {
return lazy().subList(fromIndex, toIndex);
}
}