package de.axone.data.collections; import java.io.Serializable; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.Objects; public final class SingleImmutableList<T> implements List<T>, Serializable { private static final long serialVersionUID = 1L; private final T value; public SingleImmutableList( T value ){ this.value = value; } @Override public int size() { return 1; } @Override public boolean isEmpty() { return false; } @Override public boolean contains( Object o ) { return Objects.equals( value, o ); } @Override public Iterator<T> iterator() { return new MyIterator(); } @Override public Object[] toArray() { return new Object[]{ value }; } @Override public <U> U[] toArray( U[] a ) { throw new UnsupportedOperationException( "We don't need this" ); } @Override public boolean add( T e ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public boolean remove( Object o ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public boolean containsAll( Collection<?> c ) { if( c instanceof SingleImmutableList ) return Objects.equals( value, ((SingleImmutableList<?>)c).value ); if( c.size() > 1 ) return false; if( c.size() == 0 ) return true; Object o = c.iterator().next(); return value.equals( o ); } @Override public boolean addAll( Collection<? extends T> c ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public boolean retainAll( Collection<?> c ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public boolean removeAll( Collection<?> c ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public void clear() { throw new UnsupportedOperationException( "List is immutable" ); } private class MyIterator implements ListIterator<T> { boolean hasNext = true; @Override public boolean hasNext() { return hasNext; } @Override public T next() { if( ! hasNext ) throw new NoSuchElementException(); hasNext = false; return value; } @Override public void remove() { throw new UnsupportedOperationException( "List is immutable" ); } @Override public boolean hasPrevious() { return !hasNext; } @Override public T previous() { if( hasNext ) throw new NoSuchElementException(); hasNext = true; return value; } @Override public int nextIndex() { if( hasNext ) return 0; return 1; } @Override public int previousIndex() { if( !hasNext ) return 0; else return -1; } @Override public void set( T e ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public void add( T e ) { throw new UnsupportedOperationException( "List is immutable" ); } } @Override public int hashCode() { return value == null ? 0 : value.hashCode(); } @Override public boolean equals( Object obj ) { if( this == obj ) return true; if( obj == null ) return false; if( !( obj instanceof List ) ) return false; if( ((List<?>)obj).size() != 1 ) return false; if( obj instanceof SingleImmutableList ) { return Objects.equals( value, ((SingleImmutableList<?>)obj).value ); } else { return Objects.equals( value, ((List<?>)obj).get( 0 ) ); } } @Override public String toString() { return "[" + value.toString() + "]"; } @Override public boolean addAll( int index, Collection<? extends T> c ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public T get( int index ) { if( index == 0 ) return value; else throw new IndexOutOfBoundsException(); } @Override public T set( int index, T element ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public void add( int index, T element ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public T remove( int index ) { throw new UnsupportedOperationException( "List is immutable" ); } @Override public int indexOf( Object o ) { if( Objects.equals( value, o ) ) return 0; else return -1; } @Override public int lastIndexOf( Object o ) { return indexOf( o ); } @Override public ListIterator<T> listIterator() { return null; } @Override public ListIterator<T> listIterator( int index ) { return new MyIterator(); } @Override public List<T> subList( int fromIndex, int toIndex ) { if( fromIndex == toIndex ) return Collections.emptyList(); if( fromIndex == 0 && toIndex == 1 ) return this; throw new IndexOutOfBoundsException(); }; }