package jetbrains.mps.internal.collections.runtime.impl;
/*Generated by MPS */
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.AbstractSequence;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ISequence;
import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes;
import jetbrains.mps.internal.collections.runtime.SelectComparator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ListIterator;
public class SortingSequence<U> extends Sequence<U> implements Iterable<U> {
private final AbstractSequence<U> input;
private final Comparator<? super U> comparator;
public SortingSequence(AbstractSequence<U> input, Comparator<? super U> comparator, boolean ascending) {
if (input == null || comparator == null) {
throw new NullPointerException();
}
this.input = input;
if (ascending) {
this.comparator = comparator;
} else {
this.comparator = new SortingSequence.InversedComparator<U>(comparator);
}
}
public SortingSequence(AbstractSequence<U> input, Comparator<U> comparator) {
if (input == null || comparator == null) {
throw new NullPointerException();
}
this.input = input;
this.comparator = comparator;
}
@Override
public Iterator<U> iterator() {
List<U> sortedInput = inputSortedWithSelector();
return new SortingSequence.UnmodifiableIterator<U>(sortedInput.listIterator());
}
@Override
public ISequence<U> alsoSort(_FunctionTypes._return_P1_E0<? extends Comparable<?>, ? super U> selector, boolean ascending) {
SelectComparator<U> selectComparator = new SelectComparator<U>(selector);
return new SortingSequence<U>(input, new SortingSequence.CompoundComparator<U>(comparator, (ascending ? selectComparator : new SortingSequence.InversedComparator<U>(selectComparator))));
}
@SuppressWarnings(value = "unchecked")
private List<U> inputSortedWithSelector() {
ArrayList<U> cache = new ArrayList<U>();
for (U u : input) {
cache.add(u);
}
U[] array = (U[]) cache.toArray();
Arrays.sort(array, comparator);
return Arrays.asList(array);
}
private static class UnmodifiableIterator<U> implements Iterator<U> {
private final ListIterator<U> source;
public UnmodifiableIterator(ListIterator<U> source) {
this.source = source;
}
@Override
public boolean hasNext() {
return source.hasNext();
}
@Override
public U next() {
return source.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
private static class InversedComparator<T> implements Comparator<T> {
private final Comparator<? super T> primary;
public InversedComparator(Comparator<? super T> primary) {
this.primary = primary;
}
@Override
public int compare(T a, T b) {
return -primary.compare(a, b);
}
}
private static class CompoundComparator<T> implements Comparator<T> {
private final Comparator<? super T> secondary;
private final Comparator<? super T> primary;
public CompoundComparator(Comparator<? super T> primary, Comparator<? super T> secondary) {
this.primary = primary;
this.secondary = secondary;
}
@Override
public int compare(T a, T b) {
int c = primary.compare(a, b);
return (c == 0 ? secondary.compare(a, b) : c);
}
}
}