package sk.stuba.fiit.perconik.core.resources;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import javax.annotation.Nullable;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newLinkedList;
import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.collect.Sets.newIdentityHashSet;
import static com.google.common.collect.Sets.newLinkedHashSet;
final class GenericPool<T> extends AbstractPool<T> {
private final PresenceStrategy strategy;
GenericPool(final Builder<T> builder) {
super(builder.implementation, builder.handler);
this.strategy = checkNotNull(builder.strategy);
}
public static final class Builder<T> {
Handler<T> handler;
Collection<T> implementation;
PresenceStrategy strategy;
public Builder(final Handler<T> handler) {
this.handler = checkNotNull(handler);
}
public Builder<T> arrayList() {
checkState(this.implementation == null);
this.implementation = newArrayList();
return this;
}
public Builder<T> hashSet() {
checkState(this.implementation == null);
this.implementation = newHashSet();
return this;
}
public Builder<T> linkedList() {
checkState(this.implementation == null);
this.implementation = newLinkedList();
return this;
}
public Builder<T> linkedHashSet() {
checkState(this.implementation == null);
this.implementation = newLinkedHashSet();
return this;
}
public Builder<T> identity() {
checkState(this.strategy == null);
this.strategy = PresenceStrategy.IDENTITY;
return this;
}
public Builder<T> equals() {
checkState(this.strategy == null);
this.strategy = PresenceStrategy.EQUALS;
return this;
}
public GenericPool<T> build() {
if (this.strategy == null) {
this.strategy = PresenceStrategy.DEFAULT;
}
if (this.strategy == PresenceStrategy.IDENTITY && this.implementation instanceof HashSet) {
this.implementation = newIdentityHashSet();
}
return new GenericPool<>(this);
}
}
public static <T> Builder<T> builder(final Handler<T> handler) {
return new Builder<>(handler);
}
private enum PresenceStrategy {
DEFAULT {
@Override
boolean contains(final Collection<?> collection, @Nullable final Object object) {
return collection.contains(object);
}
},
IDENTITY {
@Override
boolean contains(final Collection<?> collection, @Nullable final Object object) {
for (Object other: collection) {
if (object == other) {
return true;
}
}
return false;
}
},
EQUALS {
@Override
boolean contains(final Collection<?> collection, @Nullable final Object object) {
for (Object other: collection) {
if (equal(object, other)) {
return true;
}
}
return false;
}
};
abstract boolean contains(Collection<?> collection, @Nullable Object object);
}
public boolean contains(final Object object) {
return this.strategy.contains(this.objects, object);
}
public Collection<T> toCollection() {
return new ArrayList<>(this.objects);
}
@Override
public String toString() {
return this.getName();
}
public String getName() {
String name = this.handler.getClass().getCanonicalName();
if (name == null) {
name = this.handler.getClass().getName();
}
return name.replaceFirst("Handler\\z", "Pool");
}
}