package org.uqbar.jimplify.protocol;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.uqbar.jimplify.errors.ObjectNotFoundException;
public class SimpleCollection<T> implements EasyCollection <T>{
private Collection<T> realCollection;
public static <T> SimpleCollection<T> of (Collection<T> realCollection){
SimpleCollection<T> instance = new SimpleCollection<>();
instance.realCollection=realCollection;
return instance;
}
public Collection<T> select(Predicate<T> condition) {
return this.realCollection
.stream()
.filter(condition)
.collect(Collectors.toCollection(createBestCollectionFromWrappedTypeLambda()));
}
public <R> Collection<R> collect(Function<T, R> transformation) {
return this.realCollection
.stream()
.map(transformation)
.collect(Collectors.toCollection(createBestCollectionFromWrappedTypeLambda()));
}
public Boolean anySatisfy(Predicate<T> condition) {
return this.realCollection
.stream()
.anyMatch(condition);
}
public Boolean allSatisfy(Predicate<T> condition) {
return this.realCollection
.stream()
.allMatch(condition);
}
public T find(Predicate<T> condition) {
return this.realCollection
.stream()
.filter(condition)
.findFirst()
.orElseThrow(() -> new ObjectNotFoundException("Not element found to satisfy the condition"));
}
public <R> R injectInto(R initValue, BiFunction<R, T, R> operation) {
return this.realCollection
.stream()
.reduce(initValue, operation, (id, value) -> value);
}
/**
* Supplier to create the result collection.
* Tries to create a new instance from the same type of the wrapped collection.
* If cannot, creates an ArrayList
* @return: an empty collection subclass of realCollection or ArrayList
*/
@SuppressWarnings("unchecked")
protected <C> Supplier<Collection<C>> createBestCollectionFromWrappedTypeLambda() {
return (() ->{
try {
return realCollection.getClass().getConstructor().newInstance();
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
return new ArrayList<C>();
}
});
}
}