com.speedment.runtime.field.internal.comparator.CombinedComparatorImpl Maven / Gradle / Ivy
/**
*
* Copyright (c) 2006-2019, Speedment, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); You may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.speedment.runtime.field.internal.comparator;
import com.speedment.runtime.field.ComparableField;
import com.speedment.runtime.field.Field;
import com.speedment.runtime.field.comparator.CombinedComparator;
import com.speedment.runtime.field.comparator.FieldComparator;
import com.speedment.runtime.field.comparator.NullOrder;
import com.speedment.runtime.field.method.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Objects.requireNonNull;
/**
* Default implementation of the {@link CombinedComparator}-interface.
*
* @author Emil Forslund
* @since 3.0.11
*/
public final class CombinedComparatorImpl
implements CombinedComparator {
private final List> comparators;
public CombinedComparatorImpl(
final List> comparators) {
this.comparators = requireNonNull(comparators);
}
@Override
public Stream> stream() {
return comparators.stream();
}
@Override
public int size() {
return comparators.size();
}
@Override
public int compare(ENTITY o1, ENTITY o2) {
for (final FieldComparator comp : comparators) {
final int c = comp.compare(o1, o2);
if (c != 0) return c;
}
return 0;
}
@Override
public CombinedComparator reversed() {
return new CombinedComparatorImpl<>(comparators.stream()
.map(FieldComparator::reversed)
.collect(Collectors.toList())
);
}
@Override
public Comparator thenComparing(Comparator other) {
return then(other);
}
@Override
public Comparator thenComparing(
final Function keyExtractor,
final Comparator keyComparator) {
if (keyExtractor instanceof Getter) {
@SuppressWarnings("unchecked")
final Getter getter = (Getter) keyExtractor;
final Optional> result = then(getter);
if (result.isPresent()) {
return result.get();
}
}
return (a, b) -> {
final int c = compare(a, b);
if (c == 0) {
return keyComparator.compare(
keyExtractor.apply(a),
keyExtractor.apply(b)
);
} else return c;
};
}
@Override
public > Comparator
thenComparing(Function keyExtractor) {
if (keyExtractor instanceof Getter) {
@SuppressWarnings("unchecked")
final Getter getter = (Getter) keyExtractor;
final Optional> result = then(getter);
if (result.isPresent()) {
return result.get();
}
}
return (a, b) -> {
final int c = compare(a, b);
if (c == 0) {
final U oa = keyExtractor.apply(a);
final U ob = keyExtractor.apply(b);
if (oa == null && ob == null) {
return 0;
} else if (oa == null) {
return 1;
} else if (ob == null) {
return -1;
} else {
return oa.compareTo(ob);
}
} else return c;
};
}
@Override
public Comparator
thenComparingInt(ToIntFunction keyExtractor) {
if (keyExtractor instanceof Getter) {
@SuppressWarnings("unchecked")
final Getter getter = (Getter) keyExtractor;
final Optional> result = then(getter);
if (result.isPresent()) {
return result.get();
}
}
return (a, b) -> {
final int c = compare(a, b);
if (c == 0) {
final int oa = keyExtractor.applyAsInt(a);
final int ob = keyExtractor.applyAsInt(b);
return Integer.compare(oa, ob);
} else return c;
};
}
@Override
public Comparator
thenComparingLong(ToLongFunction keyExtractor) {
if (keyExtractor instanceof Getter) {
@SuppressWarnings("unchecked")
final Getter getter = (Getter) keyExtractor;
final Optional> result = then(getter);
if (result.isPresent()) {
return result.get();
}
}
return (a, b) -> {
final int c = compare(a, b);
if (c == 0) {
final long oa = keyExtractor.applyAsLong(a);
final long ob = keyExtractor.applyAsLong(b);
return Long.compare(oa, ob);
} else return c;
};
}
@Override
public Comparator
thenComparingDouble(ToDoubleFunction keyExtractor) {
if (keyExtractor instanceof Getter) {
@SuppressWarnings("unchecked")
final Getter getter = (Getter) keyExtractor;
final Optional> result = then(getter);
if (result.isPresent()) {
return result.get();
}
}
return (a, b) -> {
final int c = compare(a, b);
if (c == 0) {
final double oa = keyExtractor.applyAsDouble(a);
final double ob = keyExtractor.applyAsDouble(b);
return Double.compare(oa, ob);
} else return c;
};
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof CombinedComparator)) return false;
final CombinedComparator that = (CombinedComparator) o;
final Iterator> it =
comparators.iterator();
return that.stream().allMatch(
c -> it.hasNext() && it.next().equals(c)
) && !it.hasNext();
}
@Override
public int hashCode() {
return 1299827 * comparators.hashCode();
}
@Override
public String toString() {
return "CombinedComparatorImpl" + comparators;
}
private Comparator then(Comparator other) {
if (other instanceof FieldComparator) {
@SuppressWarnings("unchecked")
final FieldComparator fc =
(FieldComparator) other;
final List> copy =
new ArrayList<>(comparators);
copy.add(fc);
return new CombinedComparatorImpl<>(copy);
} else if (other instanceof CombinedComparator) {
@SuppressWarnings("unchecked")
final CombinedComparator cc =
(CombinedComparator) other;
final List> copy =
new ArrayList<>(comparators);
cc.stream().forEachOrdered(copy::add);
return new CombinedComparatorImpl<>(copy);
} else {
return (a, b) -> {
final int c = compare(a, b);
return c == 0 ? other.compare(a, b) : c;
};
}
}
private >
Optional> then(Getter getter) {
if (getter instanceof GetByte) {
@SuppressWarnings("unchecked")
final GetByte casted = (GetByte) getter;
return Optional.of(then(new ByteFieldComparatorImpl<>(
casted.getField())
));
} else if (getter instanceof GetShort) {
@SuppressWarnings("unchecked")
final GetShort casted = (GetShort) getter;
return Optional.of(then(new ShortFieldComparatorImpl<>(
casted.getField())
));
} else if (getter instanceof GetInt) {
@SuppressWarnings("unchecked")
final GetInt casted = (GetInt) getter;
return Optional.of(then(new IntFieldComparatorImpl<>(
casted.getField())
));
} else if (getter instanceof GetLong) {
@SuppressWarnings("unchecked")
final GetLong casted = (GetLong) getter;
return Optional.of(then(new LongFieldComparatorImpl<>(
casted.getField())
));
} else if (getter instanceof GetFloat) {
@SuppressWarnings("unchecked")
final GetFloat casted = (GetFloat) getter;
return Optional.of(then(new FloatFieldComparatorImpl<>(
casted.getField())
));
} else if (getter instanceof GetDouble) {
@SuppressWarnings("unchecked")
final GetDouble casted = (GetDouble) getter;
return Optional.of(then(new DoubleFieldComparatorImpl<>(
casted.getField())
));
} else if (getter instanceof GetChar) {
@SuppressWarnings("unchecked")
final GetChar casted = (GetChar) getter;
return Optional.of(then(new CharFieldComparatorImpl<>(
casted.getField())
));
} else if (getter instanceof GetReference) {
@SuppressWarnings("unchecked")
final GetReference casted = (GetReference) getter;
final Field field = casted.getField();
if (field instanceof ComparableField) {
return Optional.of(then(new ReferenceFieldComparatorImpl<>(
(ComparableField) casted.getField(),
NullOrder.LAST
)));
}
}
return Optional.empty();
}
}