package net.glowstone.util.collection; import java.util.*; /** * List which delegates to other lists. */ public class SuperList<E> extends SuperCollection<E> implements List<E> { public SuperList() { super(SuperCollection.AdditionMode.LAST); } public SuperList(List<List<E>> parents) { super(parents, SuperCollection.AdditionMode.LAST); } @Override public List<List<E>> getParents() { return (List<List<E>>) super.getParents(); } @Override public List<E> asClone() { List<E> output = new ArrayList<>(); for (List<E> parent : getParents()) { output.addAll(parent); } return output; } @Override protected Class<? extends Collection> getCollectionClass() { return List.class; } @Override public void add(int index, E object) { int relativePos = index; for (List<E> parent : getParents()) { int parentSize = parent.size(); if (parentSize <= relativePos) { parent.add(relativePos, object); return; } relativePos -= parentSize; } throw new IndexOutOfBoundsException("This list does not contain position " + index); } @Override public boolean addAll(int index, Collection<? extends E> objects) { int relativePos = index; int modified = 0; for (List<E> parent : getParents()) { int parentSize = parent.size(); if (parentSize <= relativePos) { return parent.addAll(relativePos, objects); } relativePos -= parentSize; } throw new IndexOutOfBoundsException("This list does not contain position " + index); } @Override public boolean equals(Object object) { if (object == null) { return false; } if (object == this) { return true; } if (!(object instanceof List)) { return false; } List other = (List) object; if (other.size() != size()) { return false; } Iterator thisIterator = iterator(); Iterator otherIterator = other.iterator(); while (thisIterator.hasNext()) { if (!thisIterator.next().equals(otherIterator.next())) { return false; } } return true; } @Override public E get(int index) { int relativePos = index; for (List<E> parent : getParents()) { int parentSize = parent.size(); if (relativePos < parentSize) { return parent.get(relativePos); } relativePos -= parentSize; } throw new IndexOutOfBoundsException("This list does not contain position " + index); } @Override public Iterator<E> iterator() { return new SuperIterator(getParents()); } @Override public E remove(int index) { int relativePos = index; for (List<E> parent : getParents()) { int parentSize = parent.size(); if (relativePos < parentSize) { return parent.remove(relativePos); } relativePos -= parentSize; } throw new IndexOutOfBoundsException("This list does not contain position " + index); } @Override public int indexOf(Object object) { int relativePos = 0; for (List<E> parent : getParents()) { int parentIndex = parent.indexOf(object); if (parentIndex >= 0) { return relativePos + parentIndex; } relativePos += parent.size(); } return -1; } @Override public int lastIndexOf(Object object) { List<List<E>> parents = getParents(); ListIterator<List<E>> iterator = parents.listIterator(parents.size()); int index = -1; while (iterator.hasPrevious()) { List<E> parent = iterator.previous(); if (index < 0) { index = parent.lastIndexOf(object); } else { index += parent.size(); } } return index; } @Override public ListIterator<E> listIterator() { return new SuperListIterator(getParents()); } @Override public ListIterator<E> listIterator(int index) { return new SuperListIterator(getParents(), index); } @Override public E set(int index, E object) { int relativePos = index; for (List<E> parent : getParents()) { int parentSize = parent.size(); if (relativePos < parentSize) { return parent.set(relativePos, object); } relativePos -= parentSize; } throw new IndexOutOfBoundsException("This list does not contain position " + index); } @Override public int size() { int size = 0; for (List<E> parent : getParents()) { size += parent.size(); } return size; } @Override public List<E> subList(int fromIndex, int toIndex) { // Kinda slow. If this is ever going to be used heavily, you'll probably want to implement a "SubList" class, since neither Java nor Guava provides a public implementation. return asClone().subList(fromIndex, toIndex); } }