package de.invesdwin.util.collections;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
public abstract class ADelegateCollection<E> implements Collection<E> {
private final Collection<E> delegate = newDelegate();
public Collection<E> getDelegate() {
return delegate;
}
protected abstract Collection<E> newDelegate();
@Override
public int size() {
return getDelegate().size();
}
@Override
public boolean isEmpty() {
return getDelegate().isEmpty();
}
@Override
public boolean contains(final Object o) {
return getDelegate().contains(o);
}
@Override
public Iterator<E> iterator() {
return getDelegate().iterator();
}
@Override
public Object[] toArray() {
return getDelegate().toArray();
}
@Override
public <T> T[] toArray(final T[] a) {
return getDelegate().toArray(a);
}
@Override
public boolean add(final E e) {
if (isAddAllowed(e)) {
return getDelegate().add(e);
} else {
return false;
}
}
@Override
public boolean remove(final Object o) {
return getDelegate().remove(o);
}
@Override
public boolean containsAll(final Collection<?> c) {
return getDelegate().containsAll(c);
}
@Override
public boolean addAll(final Collection<? extends E> c) {
final Collection<E> allowedElements = filterAllowedElements(c);
return getDelegate().addAll(allowedElements);
}
protected Collection<E> filterAllowedElements(final Collection<? extends E> c) {
final List<E> allowedElements = new ArrayList<E>();
for (final E e : c) {
if (isAddAllowed(e)) {
allowedElements.add(e);
}
}
return allowedElements;
}
@Override
public boolean removeAll(final Collection<?> c) {
return getDelegate().removeAll(c);
}
@Override
public boolean retainAll(final Collection<?> c) {
return getDelegate().retainAll(c);
}
@Override
public void clear() {
getDelegate().clear();
}
/**
* Can be overwritten to add restrictions
*/
public boolean isAddAllowed(final E e) {
return true;
}
@Override
public String toString() {
return getDelegate().toString();
}
@Override
public boolean equals(final Object obj) {
return getDelegate().equals(obj);
}
@Override
public int hashCode() {
return getDelegate().hashCode();
}
public static <T> Collection<T> maybeUnwrapToRoot(final Collection<T> collection) {
Collection<T> cur = collection;
while (cur instanceof ADelegateCollection) {
final ADelegateCollection<T> c = (ADelegateCollection<T>) cur;
cur = c.getDelegate();
}
return cur;
}
}