blob: 7565959e25d04346ce1451018e6789cca9d7f5eb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 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.declarative;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.eclipse.epsilon.common.util.CollectionUtil;
import org.eclipse.epsilon.eol.dom.Expression;
import org.eclipse.epsilon.eol.dom.NameExpression;
import org.eclipse.epsilon.eol.dom.Parameter;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.prettyprinting.PrettyPrinterManager;
import org.eclipse.epsilon.eol.types.EolSequence;
import org.eclipse.epsilon.eol.types.NumberUtil;
public class SortByOperation extends CollectBasedOperation {
@Override
public EolSequence<Object> execute(Object target, NameExpression operationNameExpression, List<Parameter> iterators, List<Expression> expressions, IEolContext context) throws EolRuntimeException {
Collection<Object> source = resolveSource(target, iterators, context);
if (source.isEmpty()) return new EolSequence<>(0);
final List<?> collected = CollectionUtil.asList(getDelegateOperation().execute(target, operationNameExpression, iterators, expressions, context));
final int colSize = collected.size();
assert colSize == source.size();
DecoratedObject[] decoratedObjects = new DecoratedObject[colSize];
Iterator<?> sourceIter = source.iterator(), collectedIter = collected.iterator();
for (int i = 0; i < colSize; i++) {
decoratedObjects[i] = new DecoratedObject(sourceIter.next(), collectedIter.next());
}
// This will automatically become a sequential sort if array size is small.
Arrays.parallelSort(decoratedObjects, new DecoratedObjectComparator(context.getPrettyPrinterManager()));
// Build a new collection of the original collection elements
// ordered by the result of sorting the collected items
final EolSequence<Object> result = new EolSequence<>(decoratedObjects.length);
for (DecoratedObject decorated : decoratedObjects) {
result.add(decorated.object);
}
return result;
}
protected static class DecoratedObjectComparator implements Comparator<DecoratedObject> {
protected PrettyPrinterManager p;
public DecoratedObjectComparator(PrettyPrinterManager p) {
this.p = p;
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public int compare(DecoratedObject do1, DecoratedObject do2) {
Object o1 = do1.decoration;
Object o2 = do2.decoration;
if (o1 instanceof Number && o2 instanceof Number) {
if (NumberUtil.greaterThan((Number) o2, (Number) o1)) return -1;
else if (NumberUtil.greaterThan((Number) o1, (Number) o2)) return 1;
else return 0;
}
else if (o1 instanceof Comparable && o2 instanceof Comparable) {
return ((Comparable) o1).compareTo(o2);
}
else {
return p.print(o1).compareTo(p.print(o2));
}
}
}
protected static class DecoratedObject {
public final Object object, decoration;
public DecoratedObject(Object object, Object decoration) {
this.object = object;
this.decoration = decoration;
}
}
}