/*
* Copyright (C) 2015 Noorq, Inc.
*
* 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 com.noorq.casser.support;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
public final class Immutables {
private Immutables() {
}
public static <T> Set<T> setOf(T value) {
return new SingleEntrySet<T>(value);
}
public static <T> List<T> listOf(T value) {
return new SingleEntryList<T>(value);
}
public static <K, V> Map<K, V> mapOf(K key, V value) {
return new SingleEntryMap<K, V>(key, value);
}
static class SingleEntryIterator<T> implements Iterator<T> {
T entry;
boolean processed = false;
SingleEntryIterator(T entry) {
this.entry = entry;
}
@Override
public boolean hasNext() {
return !processed;
}
@Override
public T next() {
processed = true;
return entry;
}
}
static class SingleEntryListIterator<T> extends SingleEntryIterator<T> implements ListIterator<T> {
SingleEntryListIterator(T entry) {
super(entry);
}
@Override
public boolean hasPrevious() {
return processed;
}
@Override
public T previous() {
processed = false;
return entry;
}
@Override
public int nextIndex() {
return processed ? 1 : 0;
}
@Override
public int previousIndex() {
return processed ? 0 : -1;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public void set(T e) {
throw new UnsupportedOperationException();
}
@Override
public void add(T e) {
throw new UnsupportedOperationException();
}
}
static class SingleEntryCollection<T> implements Collection<T> {
final T entry;
SingleEntryCollection( T entry) {
this.entry = entry;
}
@Override
public int size() {
return 1;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object o) {
if (entry == null) {
return o == null;
}
return entry.equals(o);
}
@Override
public Iterator<T> iterator() {
return new SingleEntryIterator<T>(entry);
}
@Override
public Object[] toArray() {
return new Object[] { entry };
}
@Override
public <V> V[] toArray(V[] a) {
if (a.length != 1) {
a = Arrays.copyOf(a, 1);
}
a[0] = (V) entry;
return a;
}
@Override
public boolean add(T e) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(Collection<?> c) {
int size = c.size();
if (size != 1) {
return false;
}
for (Object o : c) {
return contains(o);
}
return false;
}
@Override
public boolean addAll(Collection<? extends T> 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();
}
}
static final class SingleEntrySet<T> extends SingleEntryCollection<T> implements Set<T> {
SingleEntrySet(T entry) {
super(entry);
}
}
static final class SingleEntryList<T> extends SingleEntryCollection<T> implements List<T> {
SingleEntryList(T entry) {
super(entry);
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public T get(int index) {
if (index == 0) {
return entry;
}
throw new IndexOutOfBoundsException();
}
@Override
public T set(int index, T element) {
throw new UnsupportedOperationException();
}
@Override
public void add(int index, T element) {
throw new UnsupportedOperationException();
}
@Override
public T remove(int index) {
throw new UnsupportedOperationException();
}
@Override
public int indexOf(Object o) {
return contains(o) ? 0 : -1;
}
@Override
public int lastIndexOf(Object o) {
return contains(o) ? 0 : -1;
}
@Override
public ListIterator<T> listIterator() {
return new SingleEntryListIterator<T>(entry);
}
@Override
public ListIterator<T> listIterator(int index) {
if (index != 0) {
throw new IndexOutOfBoundsException();
}
return listIterator();
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
if (fromIndex == 0) {
if (toIndex == 0) {
return Collections.emptyList();
}
else if (toIndex == 1) {
return this;
}
else {
throw new IndexOutOfBoundsException();
}
}
else if (fromIndex == 1 && toIndex == 1) {
return Collections.emptyList();
}
else {
throw new IndexOutOfBoundsException();
}
}
}
static final class SingleEntryMap<K, V> implements Map<K, V> {
final K key;
final V value;
SingleEntryMap(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public int size() {
return 1;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean containsKey(Object key) {
if (this.key == null) {
return key == null;
}
return this.key.equals(key);
}
@Override
public boolean containsValue(Object value) {
if (this.value == null) {
return value == null;
}
return this.value.equals(value);
}
@Override
public V get(Object key) {
if (this.key == null) {
return key == null ? this.value : null;
}
return this.key.equals(key) ? this.value : null;
}
@Override
public V put(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public V remove(Object key) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public Set<K> keySet() {
return new SingleEntrySet<K>(this.key);
}
@Override
public Collection<V> values() {
return new SingleEntrySet<V>(this.value);
}
@Override
public Set<Entry<K, V>> entrySet() {
return new SingleEntrySet<Entry<K, V>>(new Map.Entry<K, V>() {
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
throw new UnsupportedOperationException();
}
});
}
}
}