blob: 62501bcc8ad6d5153519aab9f36073e8c7403e10 [file] [log] [blame] [raw]
package net.glowstone.util.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* Generic super collection.
*/
public abstract class SuperCollection<E> implements Collection<E> {
private final List<? extends Collection<E>> parents;
private ResultMode resultMode = ResultMode.ANY;
private AdditionMode additionMode;
public SuperCollection(AdditionMode additionMode) {
this(new ArrayList<Collection<E>>(), additionMode);
}
public SuperCollection(List<? extends Collection<E>> parents, AdditionMode additionMode) {
this.parents = parents;
this.additionMode = additionMode;
}
/**
* Returns the list of parents.
* @return Parent list.
*/
public List<? extends Collection<E>> getParents() {
return parents;
}
/**
* Sets what will this collection returns for certain operations.
* If mode is set to ANY, operations will return "true" as long as the parents returned "true" at least once.
* If mode is set to ALL, operations will only return "true" if all parents also returned "true".
*/
public void setResultMode(ResultMode resultMode) {
this.resultMode = resultMode;
}
/**
* Returns current result mode.
* @return Result mode.
*/
public ResultMode getResultMode() {
return resultMode;
}
/**
* Sets how this collection will behave to additions.
* If mode is set to ALL, the addition will be performed on every parent. Default for sets.
* If mode is set to LAST, the operation will be performed on the last parent only. Default for lists.
*/
public void setAdditionMode(AdditionMode additionMode) {
this.additionMode = additionMode;
}
/**
* Returns current addition mode.
* @return Addition mode.
*/
public AdditionMode getAdditionMode() {
return additionMode;
}
/**
* Returns a new collection with the same contents as the parents.
* @return New mutable collection.
*/
public abstract Collection<E> asClone();
/**
* Returns the class this SuperCollection implements.
* @return Collection class.
*/
protected abstract Class<? extends Collection> getCollectionClass();
protected boolean resultBoolean(int modified) {
switch (resultMode) {
case ANY:
return modified > 0;
case ALL:
return modified >= parents.size();
}
return false;
}
@Override
public boolean add(E object) {
switch (additionMode) {
case ALL: {
int modified = 0;
for (Collection<E> parent : parents) {
if (parent.add(object)) {
modified++;
}
}
return resultBoolean(modified);
}
case LAST: {
return parents.get(parents.size() - 1).add(object);
}
}
throw new IllegalStateException("This SuperCollection has an invalid addition mode!");
}
@Override
public boolean addAll(Collection<? extends E> objects) {
switch (additionMode) {
case ALL: {
int modified = 0;
for (Collection<E> parent : parents) {
if (parent.addAll(objects)) {
modified++;
}
}
}
case LAST: {
return parents.get(parents.size() - 1).addAll(objects);
}
}
throw new IllegalStateException("This SuperCollection has an invalid addition mode!");
}
@Override
public void clear() {
for (Collection<E> parent : parents) {
parent.clear();
}
}
@Override
public boolean contains(Object object) {
for (Collection<E> parent : parents) {
if (parent.contains(object)) {
return true;
}
}
return false;
}
@Override
public boolean containsAll(Collection<?> objects) {
for (Object object : objects) {
if (!contains(object)) {
return false;
}
}
return true;
}
@Override
public boolean equals(Object object) {
// Avoid cloning if possible
if (object == null) {
return false;
}
if (object == this) {
return true;
}
if (!(getCollectionClass().isInstance(object))) {
return false;
}
// If trivial comparisons didn't work, fall back to clone (to remove duplicates) and compare
return asClone().equals(object);
}
@Override
public int hashCode() {
int code = 0;
for (Collection<E> parent : parents) {
code += parent.hashCode();
}
return code;
}
@Override
public boolean isEmpty() {
for (Collection<E> parent : parents) {
if (!parent.isEmpty()) {
return false;
}
}
return true;
}
@Override
public Iterator<E> iterator() {
// Override if possible, because this is *really* slow
return asClone().iterator();
}
@Override
public boolean remove(Object object) {
int modified = 0;
for (Collection<E> parent : parents) {
if (parent.remove(object)) {
modified++;
}
}
return resultBoolean(modified);
}
@Override
public boolean removeAll(Collection<?> objects) {
int modified = 0;
for (Collection<E> parent : parents) {
if (parent.removeAll(objects)) {
modified++;
}
}
return resultBoolean(modified);
}
@Override
public boolean retainAll(Collection<?> objects) {
int modified = 0;
for (Collection<E> parent : parents) {
if (parent.retainAll(objects)) {
modified++;
}
}
return resultBoolean(modified);
}
@Override
public int size() {
// Override if possible
return asClone().size();
}
@Override
public Object[] toArray() {
// Override if possible
return asClone().toArray();
}
@Override
public <T> T[] toArray(T[] array) {
// Override if possible
return asClone().<T>toArray(array);
}
public static enum ResultMode {
NEVER,
ALL,
ANY,
;
}
public static enum AdditionMode {
ALL,
LAST,
;
}
}