変更の可/不可を切り替えられるコレクション

public class ConditionalModifiableCollection<T> implements Collection<T> {

  private class ConditionalModifiableIterator implements Iterator<T> {

    private Iterator<T> it = baseCollection.iterator();

    @Override
    public boolean hasNext() {
      return it.hasNext();
    }

    @Override
    public T next() {
      return it.next();
    }

    @Override
    public void remove() {
      if (!isModifiable()) {
        throw new IllegalStateException();
      }
      it.remove();
    }
  }

  private Collection<T> baseCollection;
  private boolean modifiable = true;

  public ConditionalModifiableCollection(Collection<T> collection) {
    baseCollection = collection;
  }

  public boolean isModifiable() {
    return modifiable;
  }

  public void setModifiable(boolean value) {
    modifiable = value;
  }

  @Override
  public int size() {
    return baseCollection.size();
  }

  @Override
  public boolean isEmpty() {
    return baseCollection.isEmpty();
  }

  @Override
  public boolean contains(Object o) {
    return baseCollection.contains(o);
  }

  @Override
  public Object[] toArray() {
    return baseCollection.toArray();
  }

  @Override
  public <T> T[] toArray(T[] a) {
    return baseCollection.toArray(a);
  }

  @Override
  public boolean containsAll(Collection<?> c) {
    return baseCollection.containsAll(c);
  }

  @Override
  public Iterator<T> iterator() {
    return new ConditionalModifiableIterator();
  }

  @Override
  public boolean add(T e) {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    return baseCollection.add(e);
  }

  @Override
  public boolean remove(Object o) {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    return baseCollection.remove(o);
  }

  @Override
  public boolean addAll(Collection<? extends T> c) {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    return baseCollection.addAll(c);
  }

  @Override
  public boolean removeAll(Collection<?> c) {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    return baseCollection.removeAll(c);
  }

  @Override
  public boolean retainAll(Collection<?> c) {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    return baseCollection.retainAll(c);
  }

  @Override
  public void clear() {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    baseCollection.clear();
  }

}
public class ConditionalModifiableMap<K, V> implements Map<K, V> {

  private class InnerCollection<T> extends ConditionalModifiableCollection<T> {

    public InnerCollection(Collection<T> set) {
      super(set);
    }

    @Override
    public boolean isModifiable() {
      return ConditionalModifiableMap.this.isModifiable();
    }

    @Override
    public void setModifiable(boolean value) {
      throw new UnsupportedOperationException();
    }

  }

  private class InnerSet<T> extends InnerCollection<T> implements Set<T> {

    public InnerSet(Set<T> set) {
      super(set);
    }

  }

  private class InnerEntrySet extends InnerSet<Map.Entry<K, V>> {

    private class InnerEntry implements Map.Entry<K, V> {

      private Map.Entry<K, V> entry;

      private InnerEntry(Map.Entry<K, V> entry) {
        this.entry = entry;
      }

      @Override
      public K getKey() {
        return entry.getKey();
      }

      @Override
      public V getValue() {
        return entry.getValue();
      }

      @Override
      public V setValue(V value) {
        if (!isModifiable()) {
          throw new IllegalStateException();
        }
        return entry.setValue(value);
      }
    }

    private class InnerEntrySetIterator implements Iterator<Map.Entry<K, V>> {

      private Iterator<Map.Entry<K, V>> iterator;

      private InnerEntrySetIterator(Iterator<Map.Entry<K, V>> iterator) {
        this.iterator = iterator;
      }

      @Override
      public boolean hasNext() {
        return iterator.hasNext();
      }

      @Override
      public Map.Entry<K, V> next() {
        return new InnerEntry(iterator.next());
      }

      @Override
      public void remove() {
        // iteratorはConditionalModifiableIteratorでしかあり得ないが省略するとわかりにくいのでチェックする
        if (!isModifiable()) {
          throw new IllegalStateException();
        }
        iterator.remove();
      }
    }

    private InnerEntrySet(Set<Entry<K, V>> set) {
      super(set);
    }

    @Override
    public Iterator<Map.Entry<K, V>> iterator() {
      return new InnerEntrySetIterator(super.iterator());
    }
  }

  private Map<K, V> baseMap;
  private boolean modifiable  = true;

  public ConditionalModifiableMap(Map<K, V> map) {
    baseMap = map;
  }

  public boolean isModifiable() {
    return modifiable;
  }

  public void setModifiable(boolean value) {
    modifiable = value;
  }

  @Override
  public int size() {
    return baseMap.size();
  }

  @Override
  public boolean isEmpty() {
    return baseMap.isEmpty();
  }

  @Override
  public boolean containsKey(Object key) {
    return baseMap.containsKey(key);
  }

  @Override
  public boolean containsValue(Object value) {
    return baseMap.containsValue(value);
  }

  @Override
  public V get(Object key) {
    return baseMap.get(key);
  }

  @Override
  public V put(K key, V value) {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    return baseMap.put(key, value);
  }

  @Override
  public V remove(Object key) {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    return baseMap.remove(key);
  }

  @Override
  public void putAll(Map<? extends K, ? extends V> m) {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    baseMap.putAll(m);
  }

  @Override
  public void clear() {
    if (!isModifiable()) {
      throw new IllegalStateException();
    }
    baseMap.clear();
  }

  @Override
  public Set<K> keySet() {
    return new InnerSet<>(baseMap.keySet());
  }

  @Override
  public Collection<V> values() {
    return new InnerCollection<>(baseMap.values());
  }

  @Override
  public Set<Map.Entry<K, V>> entrySet() {
    return new InnerEntrySet(baseMap.entrySet());
  }

}

Listもいる?