/*
* Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 com.amazonaws.hal.client;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import static com.amazonaws.hal.client.ConversionUtil.convert;
public class ConvertingList
implements List {
//-------------------------------------------------------------
// Variables - Private
//-------------------------------------------------------------
private Type type;
private List backingList;
//-------------------------------------------------------------
// Constructors
//-------------------------------------------------------------
public ConvertingList(Type type, List backingList) {
this.type = type;
this.backingList = backingList;
}
//-------------------------------------------------------------
// Implementation - Collection
//-------------------------------------------------------------
@Override
public int size() {
return backingList.size();
}
@Override
public boolean isEmpty() {
return backingList.isEmpty();
}
@Override
public boolean contains(Object o) {
throw new UnsupportedOperationException();
}
@Override
public Object[] toArray() {
throw new UnsupportedOperationException();
}
@Override
public Object[] toArray(Object[] a) {
throw new UnsupportedOperationException();
}
@Override
public boolean add(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(Collection c) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection c) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
//-------------------------------------------------------------
// Implementation - Iterable
//-------------------------------------------------------------
@Override
public Iterator iterator() {
return new ConvertingIterator();
}
//-------------------------------------------------------------
// Implementation - List
//-------------------------------------------------------------
@Override
public Object get(int index) {
Object value = backingList.get(index);
// When a value is accessed, it's intended type can either be a
// class or some other type (like a ParameterizedType).
//
// If the target type is a class and the value is of that type,
// we return it. If the value is not of that type, we convert
// it and store the converted value (trusting it was converted
// properly) back to the backing store.
//
// If the target type is not a class, it may be ParameterizedType
// like List<T> or Map<K, V>. We check if the value is already
// a converting type and if so, we return it. If the value is
// not, we convert it and if it's now a converting type, we store
// the new value in the backing store.
if (type instanceof Class) {
if (!((Class) type).isInstance(value)) {
value = convert(type, value);
//noinspection unchecked
backingList.set(index, value);
}
} else {
if (!(value instanceof ConvertingMap) && !(value instanceof ConvertingList)) {
value = convert(type, value);
if (value instanceof ConvertingMap || value instanceof ConvertingList) {
//noinspection unchecked
backingList.set(index, value);
}
}
}
return value;
}
@Override
public List subList(int fromIndex, int toIndex) {
return new ConvertingList(type, backingList.subList(fromIndex, toIndex));
}
@Override
public ListIterator listIterator() {
throw new UnsupportedOperationException();
}
@Override
public ListIterator listIterator(int index) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(int index, Collection c) {
throw new UnsupportedOperationException();
}
@Override
public Object set(int index, Object element) {
throw new UnsupportedOperationException();
}
@Override
public void add(int index, Object element) {
throw new UnsupportedOperationException();
}
@Override
public Object remove(int index) {
throw new UnsupportedOperationException();
}
@Override
public int indexOf(Object o) {
throw new UnsupportedOperationException();
}
@Override
public int lastIndexOf(Object o) {
throw new UnsupportedOperationException();
}
//-------------------------------------------------------------
// Inner Classes
//-------------------------------------------------------------
private final class ConvertingIterator
implements Iterator {
Iterator backingIterator = backingList.iterator();
@Override
public boolean hasNext() {
return backingIterator.hasNext();
}
@Override
public Object next() {
// TODO: Re-store this in the backingIterator, but beware ConcurrentModificationException
return convert(type, backingIterator.next());
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}