/******************************************************************************* * Copyright 2013 Geoscience Australia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package au.gov.ga.earthsci.common.collection.adapter; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /** * Adapter for a list. * <p/> * Allows a list of one type to be used as a list of another type, using an * {@link IAdapter} to adapt between the elements. * * @author Michael de Hoog (michael.dehoog@ga.gov.au) */ public class ListAdapter<E, A> implements List<E> { private final List<A> list; private final IAdapter<E, A> adapter; public ListAdapter(List<A> list, IAdapter<E, A> adapter) { this.list = list; this.adapter = adapter; } @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { try { @SuppressWarnings("unchecked") A a = adapter.adaptTo((E) o); return list.contains(a); } catch (ClassCastException e) { return false; } } @Override public boolean containsAll(Collection<?> c) { for (Object o : c) { if (!contains(o)) { return false; } } return true; } @Override public Object[] toArray() { Object[] array = list.toArray(); for (int i = 0; i < array.length; i++) { @SuppressWarnings("unchecked") E adapted = adapter.adaptFrom((A) array[i]); array[i] = adapted; } return array; } @Override public <T> T[] toArray(T[] a) { Object[] array = list.toArray(); if (a.length > array.length) { a[array.length] = null; //according to method contract } else if (a.length < array.length) { @SuppressWarnings("unchecked") T[] t = (T[]) Array.newInstance(a.getClass().getComponentType(), array.length); a = t; } for (int i = 0; i < array.length; i++) { @SuppressWarnings("unchecked") T adapted = (T) adapter.adaptFrom((A) array[i]); a[i] = adapted; } return a; } @Override public boolean add(E e) { A a = adapter.adaptTo(e); return list.add(a); } @Override public void add(int index, E element) { A a = adapter.adaptTo(element); list.add(index, a); } @Override public boolean remove(Object o) { try { @SuppressWarnings("unchecked") A a = adapter.adaptTo((E) o); return list.remove(a); } catch (ClassCastException e) { return false; } } @Override public E remove(int index) { A a = list.remove(index); return adapter.adaptFrom(a); } @Override public boolean addAll(Collection<? extends E> c) { for (E e : c) { add(e); } return !c.isEmpty(); } @Override public boolean addAll(int index, Collection<? extends E> c) { for (E e : c) { add(index++, e); } return !c.isEmpty(); } @Override public boolean removeAll(Collection<?> c) { boolean result = true; for (Object o : c) { result |= remove(o); } return result; } @Override public boolean retainAll(Collection<?> c) { List<Object> retain = new ArrayList<Object>(c.size()); for (Object o : c) { try { @SuppressWarnings("unchecked") A a = adapter.adaptTo((E) o); retain.add(a); } catch (ClassCastException e) { //ignore, won't be retained } } return list.retainAll(retain); } @Override public void clear() { list.clear(); } @Override public E get(int index) { A a = list.get(index); return adapter.adaptFrom(a); } @Override public E set(int index, E element) { A a = adapter.adaptTo(element); a = list.set(index, a); return adapter.adaptFrom(a); } @Override public int indexOf(Object o) { try { @SuppressWarnings("unchecked") A adapted = adapter.adaptTo((E) o); return list.indexOf(adapted); } catch (ClassCastException e) { return -1; } } @Override public int lastIndexOf(Object o) { try { @SuppressWarnings("unchecked") A adapted = adapter.adaptTo((E) o); return list.lastIndexOf(adapted); } catch (ClassCastException e) { return -1; } } @Override public Iterator<E> iterator() { return new IteratorAdapter<E, A>(list.iterator(), adapter); } @Override public ListIterator<E> listIterator() { return new ListIteratorAdapter<E, A>(list.listIterator(), adapter); } @Override public ListIterator<E> listIterator(int index) { return new ListIteratorAdapter<E, A>(list.listIterator(index), adapter); } @Override public List<E> subList(int fromIndex, int toIndex) { List<A> subList = list.subList(fromIndex, toIndex); return new ListAdapter<E, A>(subList, adapter); } }