package org.osgl.util;
import org.osgl.$;
import org.osgl.exception.NotAppliedException;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.EnumSet;
public abstract class SetBase<T> extends AbstractSet<T> implements C.Set<T> {
@Override
public C.Set<T> parallel() {
setFeature(C.Feature.PARALLEL);
return this;
}
@Override
public C.Set<T> sequential() {
unsetFeature(C.Feature.PARALLEL);
return this;
}
@Override
public C.Set<T> lazy() {
setFeature(C.Feature.LAZY);
return this;
}
@Override
public C.Set<T> eager() {
unsetFeature(C.Feature.LAZY);
return this;
}
@Override
public C.Set<T> filter($.Function<? super T, Boolean> predicate) {
boolean immutable = isImmutable();
int sz = size();
// TODO: handle lazy filter
if (immutable) {
if (0 == sz) {
return Nil.set();
}
ListBuilder<T> lb = new ListBuilder<T>(sz);
forEach($.predicate(predicate).ifThen(C.F.addTo(lb)));
return lb.toSet();
} else {
if (0 == sz) {
return C.newSet();
}
C.Set<T> set = C.newSet();
forEach($.predicate(predicate).ifThen(C.F.addTo(set)));
return set;
}
}
@Override
public SetBase<T> accept($.Function<? super T, ?> visitor) {
return forEach(visitor);
}
@Override
public <R> C.Set<R> map($.Function<? super T, ? extends R> mapper) {
boolean immutable = isImmutable();
int sz = size();
if (immutable) {
if (0 == sz) {
return Nil.set();
}
ListBuilder<R> lb = new ListBuilder<R>(sz);
forEach($.f1(mapper).andThen(C.F.addTo(lb)));
return C.set(lb.toList());
} else {
if (0 == sz) {
return C.newSet();
}
C.List<R> l = C.newSizedList(sz);
forEach($.f1(mapper).andThen(C.F.addTo(l)));
return C.set(l);
}
}
@Override
public <R> C.Set<R> flatMap($.Function<? super T, ? extends Iterable<? extends R>> mapper) {
C.Set<R> set = C.newSet();
for (T t : this) {
Iterable<? extends R> iterable = mapper.apply(t);
set.addAll(C.list(iterable));
}
return set;
}
@Override
public <R> R reduce(R identity, $.Func2<R, T, R> accumulator) {
return null;
}
@Override
public $.Option<T> reduce($.Func2<T, T, T> accumulator) {
return null;
}
@Override
public boolean allMatch($.Function<? super T, Boolean> predicate) {
return false;
}
@Override
public boolean anyMatch($.Function<? super T, Boolean> predicate) {
return false;
}
@Override
public boolean noneMatch($.Function<? super T, Boolean> predicate) {
return false;
}
@Override
public $.Option<T> findOne($.Function<? super T, Boolean> predicate) {
return null;
}
// utilities
protected final boolean isLazy() {
return is(C.Feature.LAZY);
}
protected final boolean isImmutable() {
return is(C.Feature.IMMUTABLE);
}
protected final boolean isReadOnly() {
return is(C.Feature.READONLY);
}
protected final boolean isMutable() {
return !isImmutable() && !isReadOnly();
}
/**
* Sub class could override this method to implement iterating in parallel.
*
* <p>The iterating support partial function visitor by ignoring the
* {@link org.osgl.exception.NotAppliedException} thrown out by visitor's apply
* method call</p>
*
* @param visitor the visitor
* @throws $.Break if visitor needs to terminate the iteration
*/
public SetBase<T> forEach($.Function<? super T, ?> visitor) throws $.Break {
for (T t : this) {
try {
visitor.apply(t);
} catch (NotAppliedException e) {
// ignore
}
}
return this;
}
@Override
public SetBase<T> each($.Function<? super T, ?> visitor) {
return forEach(visitor);
}
@Override
public C.Set<T> onlyIn(Collection<? extends T> col) {
C.Set<T> others = C.newSet(col);
others.removeAll(this);
if (isImmutable()) {
return ImmutableSet.of(others);
}
return others;
}
@Override
public C.Set<T> withIn(Collection<T> col) {
C.Set<T> others = C.newSet(col);
others.retainAll(this);
if (isImmutable()) {
return ImmutableSet.of(others);
}
return others;
}
@Override
public C.Set<T> without(Collection<? super T> col) {
C.Set<T> copy = C.newSet(this);
copy.removeAll(col);
if (isImmutable()) {
return ImmutableSet.of(copy);
}
return copy;
}
@Override
public C.Set<T> without(T element) {
return null;
}
@Override
public C.Set<T> without(T element, T... elements) {
return null;
}
// --- Featured methods
volatile private EnumSet<C.Feature> features_;
protected final EnumSet<C.Feature> features_() {
if (null == features_) {
synchronized (this) {
if (null == features_) {
features_ = initFeatures();
assert(null != features_);
}
}
}
return features_;
}
/**
* Sub class should override this method to provide initial feature
* set for the feature based instance
*
* @return the initial feature set configuration
*/
abstract protected EnumSet<C.Feature> initFeatures();
@Override
public final EnumSet<C.Feature> features() {
return EnumSet.copyOf(features_());
}
@Override
public final boolean is(C.Feature feature) {
return features_().contains(feature);
}
protected SetBase<T> setFeature(C.Feature feature) {
features_().add(feature);
return this;
}
protected SetBase<T> unsetFeature(C.Feature feature) {
features_().remove(feature);
return this;
}
// --- eof Featured methods
}