package com.bergerkiller.bukkit.common.collections; import java.util.AbstractList; import java.util.ArrayList; import java.util.List; /** * Keeps instances of elements available even after clearing to avoid the creation of new instances. * This can be used to store an infinite or undefined amount of elements. The get and set operations * allow operating outside the size of the buffer, and dynamically allocate the new capacity needed.<br><br> * * The {@link #createElement()} method needs to be implemented to use this buffer. * * @param <E> - Instance element type */ public abstract class InstanceBuffer<E> extends AbstractList<E> { private final ArrayList<E> buffer = new ArrayList<E>(); private int size = 0; /** * Creates a new Element to use in the buffer * * @return new element instance */ public abstract E createElement(); /** * Gets the next element and increases size by one. * * @return next element added or obtained */ public E add() { ensureCapacity(size + 1); return buffer.get(size - 1); } /** * Gets the given amount of next elements and increases the size by the amount * * @param amount to add and get * @return next elements added or obtained */ public List<E> addAll(int amount) { int startIndex = size - 1; ensureCapacity(size + amount); return buffer.subList(startIndex, startIndex + amount); } @Override public E remove(int index) { E element = buffer.remove(index); size--; return element; } @Override public E get(int index) { ensureCapacity(index + 1); return buffer.get(index); } @Override public E set(int index, E element) { if (index < size) { return buffer.set(index, element); } size = index + 1; if (buffer.size() >= size) { // Buffer is larger, set the element without resizing buffer.set(index, element); } else { // Resize the buffer till size - 1 and add the element buffer.ensureCapacity(size); while (buffer.size() < (size - 1)) { buffer.add(createElement()); } buffer.add(element); } return null; } @Override public void add(int index, E element) { if (index > size) { // Element out of range, set the element instead set(index, element); } else { // Element in range, add it to the buffer buffer.add(index, element); size++; } } private void ensureCapacity(int capacity) { if (capacity < size) { return; } size = capacity; buffer.ensureCapacity(capacity); while (buffer.size() < size) { buffer.add(createElement()); } } @Override public int size() { return this.size; } @Override public void clear() { clear(false); } /** * Sets the element count back to 0, optionally clearing the backing buffer * * @param clearBuffer option: True to clear the backing buffer instances */ public void clear(boolean clearBuffer) { size = 0; if (clearBuffer) { buffer.clear(); } } }