/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.util; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; /** Treat multiple lists as a single list */ public class JoinedList<E> implements List<E> { private List<E>[] lists; private int totalSize; public JoinedList(List<E> ... lists) { this.lists = lists; totalSize = 0; for (List<E> list : lists) { totalSize += list.size(); } } @Override public boolean add(E arg0) { throw new UnsupportedOperationException(); } @Override public void add(int arg0, E arg1) { throw new UnsupportedOperationException(); } @Override public boolean addAll(Collection<? extends E> arg0) { throw new UnsupportedOperationException(); } @Override public boolean addAll(int arg0, Collection<? extends E> arg1) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean contains(Object needle) { for (List<E> list : lists) { if (list.contains(needle)) { return true; } } return false; } @Override public boolean containsAll(Collection<?> needles) { for (Object needle : needles) { if (!contains(needle)) { return false; } } return true; } @Override public E get(int i) { for (List<E> list : lists) { if (i < list.size()) { return list.get(i); } i -= list.size(); } throw new ArrayIndexOutOfBoundsException(i); } @Override public int indexOf(Object needle) { int i = 0; for (List<E> list : lists) { int index = list.indexOf(needle); if (index >= 0) { return index + i; } i += list.size(); } return -1; } @Override public boolean isEmpty() { for (List<E> list : lists) { if (!list.isEmpty()) { return false; } } return true; } @Override public Iterator<E> iterator() { return new JoinedListIterator(); } class JoinedListIterator implements ListIterator<E> { private int listIndex; private ListIterator<E> iterator; JoinedListIterator(){ listIndex = 0; } @Override public boolean hasNext() { if (iterator == null) { iterator = lists[listIndex].listIterator(); } while (!iterator.hasNext()) { listIndex += 1; if (listIndex == lists.length) { return false; } iterator = lists[listIndex].listIterator(); } return listIndex != lists.length; } @Override public E next() { if (!hasNext()) { throw new NoSuchElementException(); } if (iterator == null) { iterator = lists[listIndex].listIterator(); } while (!iterator.hasNext()) { listIndex += 1; if (listIndex == lists.length) { throw new NoSuchElementException(); } iterator = lists[listIndex].listIterator(); } return iterator.next(); } @Override public void remove() { throw new UnsupportedOperationException(); } @Override public void add(E arg0) { throw new UnsupportedOperationException(); } @Override public boolean hasPrevious() { throw new UnsupportedOperationException(); } @Override public int nextIndex() { int nextIndex = 0; for (int i = 0; i < listIndex; ++i) { nextIndex += lists[i].size(); } return nextIndex + iterator.nextIndex(); } @Override public E previous() { throw new UnsupportedOperationException(); } @Override public int previousIndex() { throw new UnsupportedOperationException(); } @Override public void set(E arg0) { throw new UnsupportedOperationException(); } } @Override public int lastIndexOf(Object needle) { int i = totalSize; for (List<E> list : lists) { i -= list.size(); int index = list.lastIndexOf(needle); if (index >= 0) { return i + index; } } return -1; } @Override public ListIterator<E> listIterator() { return new JoinedListIterator(); } @Override public ListIterator<E> listIterator(int arg0) { //fixme: this is slow and stupid JoinedListIterator result = new JoinedListIterator(); for (int i = 0; i < arg0; ++i) { result.next(); } return result; } @Override public boolean remove(Object arg0) { throw new UnsupportedOperationException(); } @Override public E remove(int arg0) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection<?> arg0) { throw new UnsupportedOperationException(); } @Override public boolean retainAll(Collection<?> arg0) { throw new UnsupportedOperationException(); } @Override public E set(int arg0, E arg1) { throw new UnsupportedOperationException(); } @Override public int size() { return totalSize; } @Override public List<E> subList(int arg0, int arg1) { throw new UnsupportedOperationException(); } @Override public Object[] toArray() { Object[] array = new Object[totalSize]; Iterator<E> i = iterator(); int p = 0; while (i.hasNext()) { array[p++] = i.next(); } return array; } @SuppressWarnings("unchecked") @Override public <T> T[] toArray(T[] out) { if (out.length < totalSize) { out = (T[]) Arrays.copyOf(out, totalSize, out.getClass()); } Iterator<E> i = iterator(); int p = 0; while (i.hasNext()) { out[p++] = (T) i.next(); } if (out.length > totalSize) { out[p] = null; } return out; } }