blob: fef8ba21e35494f4d9578ee740ed0d31d4b74fdb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 The University of York.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Dimitrios Kolovos - initial API and implementation
******************************************************************************/
package org.eclipse.epsilon.eol.execute.operations.contributors;
import java.util.*;
import java.util.stream.StreamSupport;
import org.eclipse.epsilon.common.util.CollectionUtil;
import org.eclipse.epsilon.eol.types.*;
public class IterableOperationContributor extends OperationContributor {
public IterableOperationContributor() {}
public static void main(String[] args) {
Collection<Object> c = new ArrayList<>();
for (int i = 0; i < 100; i++) {
c.add(i);
}
IterableOperationContributor ioc = new IterableOperationContributor(c);
System.out.println(ioc.first(10));
}
public IterableOperationContributor(Iterable<?> target) {
setTarget(target);
}
@Override
protected Iterable<?> getTarget() {
return (Iterable<?>) super.getTarget();
}
@SuppressWarnings("unchecked")
protected Iterable<Object> getIterable() {
return (Iterable<Object>) getTarget();
}
protected boolean isCollection() {
return getTarget() instanceof Collection;
}
@SuppressWarnings("unchecked")
protected Collection<Object> getCollection() {
return (Collection<Object>) getTarget();
}
protected boolean isList() {
return getTarget() instanceof List;
}
protected List<?> getList() {
return (List<?>) getTarget();
}
protected boolean isSet() {
return getTarget() instanceof Set;
}
protected Set<?> getSet() {
return (Set<?>) getTarget();
}
@Override
public boolean contributesTo(Object target) {
return target instanceof Iterable;
}
public Object random() {
if (isEmpty()) return null;
final int size = size();
return nth(size > 0 ? new Random().nextInt(size) : 0);
}
public int size() {
if (isCollection()) {
return getCollection().size();
} else {
int size = 0;
for (Iterator<?> it = getTarget().iterator(); it.hasNext(); ++size) {
it.next();
}
return size;
}
}
public Object at(int index) {
if (isList()) {
return getList().get(index);
}
else {
int i = 0;
for (Object next : getTarget()) {
if (i == index) return next;
else i++;
}
}
return null;
}
public Object removeAt(int index) {
if (isList()) {
return getList().remove(index);
}
else {
Object toRemove = null;
Iterator<?> it = getTarget().iterator();
int i;
for (i = 0; it.hasNext() && i <= index; ++i) {
toRemove = it.next();
}
if (toRemove != null && i == index + 1) {
it.remove();
}
return toRemove;
}
}
public List<Object> asSequence() {
EolSequence<Object> copy = new EolSequence<>();
copy(getIterable(), copy);
return copy;
}
public EolSet<Object> asSet() {
EolSet<Object> copy = new EolSet<>();
copy(getIterable(), copy);
return copy;
}
public EolBag<Object> asBag() {
EolBag<Object> copy = new EolBag<>();
copy(getIterable(), copy);
return copy;
}
public EolOrderedSet<Object> asOrderedSet() {
EolOrderedSet<Object> copy = new EolOrderedSet<>();
copy(getIterable(), copy);
return copy;
}
public Number sum() {
return StreamSupport.stream(getTarget().spliterator(), true)
.filter(Number.class::isInstance)
.map(Number.class::cast)
.reduce(0, (i, sum) -> NumberUtil.add(sum, i));
}
public Number product() {
if (isEmpty()) return 0.0f;
return StreamSupport.stream(getTarget().spliterator(), true)
.filter(Number.class::isInstance)
.map(Number.class::cast)
.reduce(1, (product, i) -> NumberUtil.multiply(product, i));
}
public boolean isEmpty() {
Object target = getTarget();
if (target instanceof Collection<?>) return ((Collection<?>) target).isEmpty();
return !getTarget().iterator().hasNext();
}
public boolean notEmpty() {
return !isEmpty();
}
protected <T> void copy(Iterable<T> source, Collection<T> target) {
for (
Iterator<T> it = source.iterator();
it.hasNext();
target.add(it.next())
);
}
@Override
public Collection<?> clone() {
// May require its own contributor
if (isCollection()) {
return EolCollectionType.clone(getCollection());
}
return null;
}
public boolean includes(Object key) {
if (isCollection()) {
return getCollection().contains(key);
}
else {
Iterator<?> it = getTarget().iterator();
while (it.hasNext()) {
if (Objects.equals(it.next(), key)) {
return true;
}
}
return false;
}
}
public boolean excludes(Object o) {
return !includes(o);
}
public boolean includesAll(Collection<?> col) {
for (Object item : col) {
if (!includes(item)) return false;
}
return true;
}
public boolean excludesAll(Collection<?> col) {
for (Object item : col) {
if (includes(item)) return false;
}
return true;
}
public int count(Object o) {
return StreamSupport.stream(getTarget().spliterator(), false)
.filter(item -> Objects.equals(item, o))
.mapToInt(item -> 1).sum();
}
public Collection<Object> includingAll(Collection<Object> col) {
Collection<Object> result = createCollection();
addAll(getTarget(), result);
addAll(col, result);
return result;
}
public Collection<Object> including(Object o) {
Collection<Object> result = createCollection();
addAll(getTarget(), result);
result.add(o);
return result;
}
/**
* TODO : See this
* @return
*/
public Collection<Object> flatten() {
Collection<Object> col;
if (isCollection()) {
col = getCollection();
}
else {
col = createCollection();
addAll(getTarget(), col);
}
return CollectionUtil.flatten(col);
}
public Collection<Object> excluding(Object o) {
Collection<Object> excluding = createCollection();
addAll(getTarget(), excluding);
while (excluding.contains(o)) {
excluding.remove(o);
}
return excluding;
}
public Collection<Object> excludingAll(Collection<?> col) {
Collection<Object> difference = createCollection();
for (Object next : getTarget()) {
if (!col.contains(next)) {
difference.add(next);
}
}
/*
* The normal way would be to use the removeAll method like following
* but the MDR IndexSetWrapper does not support it.
*/
return difference;
}
public Collection<Object> first(int number) {
Iterator<?> it = getTarget().iterator();
ArrayList<Object> result = new ArrayList<>(number);
for (int i = 0; it.hasNext() && i++ < number; result.add(it.next()));
return result;
}
public Object first() {
return nth(0);
}
public Object second() {
return nth(1);
}
public Object third() {
return nth(2);
}
public Object fourth() {
return nth(3);
}
public Object last() {
if (isCollection()) {
return nth(getCollection().size() - 1);
}
else {
Object o = null;
for (Iterator<?> it = getTarget().iterator(); it.hasNext(); o = it.next());
return o;
}
}
public int indexOf(Object o) {
if (isList()) {
return getList().indexOf(o);
}
else {
int counter = 0;
for (Object item : getTarget()) {
if (Objects.equals(item, o)) {
return counter;
}
counter++;
}
return -1;
}
}
private Object nth(int index) {
if (isEmpty()) return null;
return at(index);
}
public String concat() {
return concat("");
}
public String concat(String delimiter) {
return CollectionUtil.join(getTarget(), delimiter,
//FIXME : Use the pretty printer manager here
element -> Objects.toString(element, "")
);
}
public Number max() {
return max(0);
}
public Number max(Number default_) {
Number max = null;
for (Object next : getTarget()) {
if (next instanceof Number) {
Number nextNumber = (Number) next;
if (max == null || NumberUtil.greaterThan(nextNumber, max)) {
max = nextNumber;
}
}
}
if (max == null) {
max = default_;
}
return max;
}
public Number min() {
return min(0);
}
public Number min(Number default_) {
Number min = null;
for (Object next : getTarget()) {
if (next instanceof Number) {
Number nextNumber = (Number) next;
if (min == null || NumberUtil.lessThan(nextNumber, min)) {
min = nextNumber;
}
}
}
if (min == null) {
min = default_;
}
return min;
}
public Collection<Object> invert() {
EolSequence<Object> sequence = new EolSequence<>();
for (Object o : getTarget()) {
sequence.add(0, o);
}
return sequence;
}
public Collection<Object> createCollection() {
if (isCollection()) {
return EolCollectionType.createSameType(getCollection());
} else {
return new EolSequence<>();
}
}
public Set<Set<Object>> powerset() {
List<Object> originalSet = asSequence();
Set<Set<Object>> sets = new HashSet<>();
if (originalSet.isEmpty()) {
sets.add(new HashSet<>());
return sets;
}
Object head = originalSet.get(0);
Set<Object> rest = new HashSet<>(originalSet.subList(1, originalSet.size()));
for (Set<Object> set : new IterableOperationContributor(rest).powerset()) {
Set<Object> newSet = new HashSet<>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
return sets;
}
private static void addAll(final Iterable<?> elements, Collection<Object> target) {
if (elements instanceof Collection) {
target.addAll((Collection<?>)elements);
}
else {
for (Object o : elements) {
target.add(o);
}
}
}
}