/*
* Copyright 2013 Cameron Beccario
*
* 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 net.nullschool.grains;
import net.nullschool.collect.*;
import net.nullschool.collect.basic.BasicConstList;
import net.nullschool.collect.basic.BasicConstSet;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.*;
import static net.nullschool.collect.basic.BasicCollections.*;
/**
* 2013-03-11<p/>
*
* A partial implementation of Grain that provides a MapIterator implementation and const behavior for the
* {@link #keySet}, {@link #values}, and {@link #entrySet} views built on {@link BasicConstList} and
* {@link BasicConstSet}.
*
* @author Cameron Beccario
*/
public abstract class AbstractGrain extends AbstractIterableMap<String, Object> implements Grain {
/**
* {@inheritDoc}
*
* <p/>This method must be overridden by AbstractGrain implementers as it is used for basis iteration.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
@Override public abstract Object get(Object key);
protected class BasisIter implements MapIterator<String, Object> {
private static final int BAD = -1;
private final String[] keys; // the keys to iterator over
private final int maxIndex; // the index of the last key
private int cursor = BAD; // the index of the key that was most recently returned by next(), or BAD if none
public BasisIter(String[] keys) {
this.keys = keys;
this.maxIndex = keys.length - 1;
}
@Override public boolean hasNext() {
return cursor != maxIndex;
}
@Override public String next() {
final int i = cursor;
if (i != maxIndex) { // if we are not currently sitting at the last key
return keys[cursor = i + 1]; // advance to the next key
}
throw new NoSuchElementException();
}
@Override public Object value() {
final int i = cursor;
if (i != BAD) {
return get(keys[i]);
}
throw new IllegalStateException();
}
@Override public Entry<String, Object> entry() {
final int i = cursor;
if (i != BAD) {
final String key = keys[i];
return new SimpleImmutableEntry<>(key, get(key));
}
throw new IllegalStateException();
}
@Override public void remove() {
throw new UnsupportedOperationException();
}
}
// -------------------------------------------------------------------------
// Mutation methods marked final, always throw UnsupportedOperationException
@Deprecated @Override public final Object put(String key, Object value) { throw unsupported(); }
@Deprecated @Override public final void putAll(Map<? extends String, ?> map) { throw unsupported(); }
@Deprecated @Override protected final boolean removeKey(Object key) { throw unsupported(); }
@Deprecated @Override protected final boolean removeValue(Object value) { throw unsupported(); }
@Deprecated @Override protected final boolean removeEntry(Object key, Object value) { throw unsupported(); }
@Deprecated @Override public final Object remove(Object key) { throw unsupported(); }
@Deprecated @Override public final void clear() { throw unsupported(); }
// =================================================================================================================
// KeySet View
protected class ConstKeysView extends KeysView implements ConstSet<String> {
@Override public ConstSet<String> with(String key) {
return contains(key) ? this : asSet(this).with(key);
}
@Override public ConstSet<String> withAll(Collection<? extends String> c) {
return c.isEmpty() ? this : asSet(this).withAll(c);
}
@Override public ConstSet<String> without(Object key) {
return !contains(key) ? this : asSet(this).without(key);
}
@Override public ConstSet<String> withoutAll(Collection<?> c) {
return c.isEmpty() ? this : asSet(this).withoutAll(c);
}
// -------------------------------------------------------------------------
// Mutation methods marked final, always throw UnsupportedOperationException
@Deprecated @Override public final boolean add(String s) { throw unsupported(); }
@Deprecated @Override public final boolean addAll(Collection<? extends String> c) { throw unsupported(); }
@Deprecated @Override public final boolean remove(Object o) { throw unsupported(); }
@Deprecated @Override public final boolean removeAll(Collection<?> c) { throw unsupported(); }
@Deprecated @Override public final boolean retainAll(Collection<?> c) { throw unsupported(); }
@Deprecated @Override public final void clear() { throw unsupported(); }
}
@Override public ConstSet<String> keySet() {
return new ConstKeysView();
}
// =================================================================================================================
// Values View
protected class ConstValuesView extends ValuesView implements ConstCollection<Object> {
@Override public ConstCollection<Object> with(Object value) {
return contains(value) ? this : asList(this).with(value);
}
@Override public ConstCollection<Object> withAll(Collection<?> c) {
return c.isEmpty() ? this : asList(this).withAll(c);
}
@Override public ConstCollection<Object> without(Object value) {
return !contains(value) ? this : asList(this).without(value);
}
@Override public ConstCollection<Object> withoutAll(Collection<?> c) {
return c.isEmpty() ? this : asList(this).withoutAll(c);
}
// -------------------------------------------------------------------------
// Mutation methods marked final, always throw UnsupportedOperationException
@Deprecated @Override public final boolean add(Object s) { throw unsupported(); }
@Deprecated @Override public final boolean addAll(Collection<?> c) { throw unsupported(); }
@Deprecated @Override public final boolean remove(Object o) { throw unsupported(); }
@Deprecated @Override public final boolean removeAll(Collection<?> c) { throw unsupported(); }
@Deprecated @Override public final boolean retainAll(Collection<?> c) { throw unsupported(); }
@Deprecated @Override public final void clear() { throw unsupported(); }
}
@Override public ConstCollection<Object> values() {
return new ConstValuesView();
}
// =================================================================================================================
// EntrySet View
protected class ConstEntriesView extends EntriesView implements ConstSet<Entry<String, Object>> {
@Override public ConstSet<Entry<String, Object>> with(Entry<String, Object> entry) {
return contains(entry) ? this : asSet(this).with(entry);
}
@Override public ConstSet<Entry<String, Object>> withAll(Collection<? extends Entry<String, Object>> c) {
return c.isEmpty() ? this : asSet(this).withAll(c);
}
@Override public ConstSet<Entry<String, Object>> without(Object entry) {
return !contains(entry) ? this : asSet(this).without(entry);
}
@Override public ConstSet<Entry<String, Object>> withoutAll(Collection<?> c) {
return c.isEmpty() ? this : asSet(this).withoutAll(c);
}
// -------------------------------------------------------------------------
// Mutation methods marked final, always throw UnsupportedOperationException
@Deprecated
@Override public final boolean addAll(Collection<? extends Entry<String, Object>> c) { throw unsupported(); }
@Deprecated @Override public final boolean add(Entry<String, Object> entry) { throw unsupported(); }
@Deprecated @Override public final boolean remove(Object o) { throw unsupported(); }
@Deprecated @Override public final boolean removeAll(Collection<?> c) { throw unsupported(); }
@Deprecated @Override public final boolean retainAll(Collection<?> c) { throw unsupported(); }
@Deprecated @Override public final void clear() { throw unsupported(); }
}
@Override public ConstSet<Entry<String, Object>> entrySet() {
return new ConstEntriesView();
}
private static UnsupportedOperationException unsupported() {
return new UnsupportedOperationException();
}
}