Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.calcite.linq4j.function.Functions Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you 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 org.apache.calcite.linq4j.function;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.checkerframework.framework.qual.TypeUseLocation;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.RandomAccess;
import java.util.function.IntFunction;
/**
* Utilities relating to functions.
*/
public abstract class Functions {
private Functions() {}
public static final Map, Class> FUNCTION_RESULT_TYPES =
Collections.unmodifiableMap(
map(Function0.class, Object.class,
Function1.class, Object.class,
Function2.class, Object.class,
BigDecimalFunction1.class, BigDecimal.class,
DoubleFunction1.class, Double.TYPE,
FloatFunction1.class, Float.TYPE,
IntegerFunction1.class, Integer.TYPE,
LongFunction1.class, Long.TYPE,
NullableBigDecimalFunction1.class, BigDecimal.class,
NullableDoubleFunction1.class, Double.class,
NullableFloatFunction1.class, Float.class,
NullableIntegerFunction1.class, Integer.class,
NullableLongFunction1.class, Long.class));
private static final Map> FUNCTION1_CLASSES =
Collections.unmodifiableMap(
new HashMap<>(inverse(FUNCTION_RESULT_TYPES)));
private static final Comparator NULLS_FIRST_COMPARATOR =
new NullsFirstComparator();
private static final Comparator NULLS_LAST_COMPARATOR =
new NullsLastComparator();
private static final Comparator NULLS_LAST_REVERSE_COMPARATOR =
new NullsLastReverseComparator();
private static final Comparator NULLS_FIRST_REVERSE_COMPARATOR =
new NullsFirstReverseComparator();
private static final EqualityComparer IDENTITY_COMPARER =
new IdentityEqualityComparer();
private static final EqualityComparer<@Nullable Object[]> ARRAY_COMPARER =
new ArrayEqualityComparer();
private static final Function1 CONSTANT_NULL_FUNCTION1 =
(Function1) s -> null;
private static final Function1 TO_STRING_FUNCTION1 =
(Function1) Object::toString;
@SuppressWarnings("unchecked")
private static Map map(K k, V v, Object... rest) {
final Map map = new HashMap<>();
map.put(k, v);
for (int i = 0; i < rest.length; i++) {
map.put((K) rest[i++], (V) rest[i++]);
}
return map;
}
private static Map inverse(Map map) {
HashMap inverseMap = new HashMap<>();
for (Map.Entry entry : map.entrySet()) {
inverseMap.put(entry.getValue(), entry.getKey());
}
return inverseMap;
}
/** Returns a 1-parameter function that always returns the same value. */
public static Function1 constant(final R r) {
return s -> r;
}
/** Returns a 1-parameter function that always returns null. */
@SuppressWarnings("unchecked")
public static Function1 constantNull() {
return CONSTANT_NULL_FUNCTION1;
}
/**
* A predicate with one parameter that always returns {@code true}.
*
* @param First parameter type
*
* @return Predicate that always returns true
*/
public static Predicate1 truePredicate1() {
//noinspection unchecked
return (Predicate1) Predicate1.TRUE;
}
/**
* A predicate with one parameter that always returns {@code true}.
*
* @param First parameter type
*
* @return Predicate that always returns true
*/
public static Predicate1 falsePredicate1() {
//noinspection unchecked
return (Predicate1) Predicate1.FALSE;
}
/**
* A predicate with two parameters that always returns {@code true}.
*
* @param First parameter type
* @param Second parameter type
*
* @return Predicate that always returns true
*/
public static Predicate2 truePredicate2() {
//noinspection unchecked
return (Predicate2) Predicate2.TRUE;
}
/**
* A predicate with two parameters that always returns {@code false}.
*
* @param First parameter type
* @param Second parameter type
*
* @return Predicate that always returns false
*/
public static Predicate2 falsePredicate2() {
//noinspection unchecked
return (Predicate2) Predicate2.FALSE;
}
public static Function1 identitySelector() {
//noinspection unchecked
return (Function1) Function1.IDENTITY;
}
/** Returns a selector that calls the {@link Object#toString()} method on
* each element. */
public static Function1 toStringSelector() {
//noinspection unchecked
return TO_STRING_FUNCTION1;
}
/**
* Creates a predicate that returns whether an object is an instance of a
* particular type or is null.
*
* @param clazz Desired type
* @param Type of objects to test
* @param Desired type
*
* @return Predicate that tests for desired type
*/
public static Predicate1 ofTypePredicate(final Class clazz) {
return v1 -> v1 == null || clazz.isInstance(v1);
}
public static Predicate2 toPredicate2(
final Predicate1 p1) {
return (v1, v2) -> p1.apply(v1);
}
/**
* Converts a 2-parameter function to a predicate.
*/
public static Predicate2 toPredicate(
final Function2 function) {
return function::apply;
}
/**
* Returns the appropriate interface for a lambda function with
* 1 argument and the given return type.
*
* For example:
* functionClass(Integer.TYPE) returns IntegerFunction1.class;
* functionClass(String.class) returns Function1.class.
*
* @param aClass Return type
*
* @return Function class
*/
public static Class extends Function> functionClass(Type aClass) {
Class extends Function> c = FUNCTION1_CLASSES.get(aClass);
if (c != null) {
return c;
}
return Function1.class;
}
/**
* Adapts an {@link IntegerFunction1} (that returns an {@code int}) to
* an {@link Function1} returning an {@link Integer}.
*/
public static Function1 adapt(
final IntegerFunction1 f) {
return f::apply;
}
/**
* Adapts a {@link DoubleFunction1} (that returns a {@code double}) to
* an {@link Function1} returning a {@link Double}.
*/
public static Function1 adapt(final DoubleFunction1 f) {
return f::apply;
}
/**
* Adapts a {@link LongFunction1} (that returns a {@code long}) to
* an {@link Function1} returning a {@link Long}.
*/
public static Function1 adapt(final LongFunction1 f) {
return f::apply;
}
/**
* Adapts a {@link FloatFunction1} (that returns a {@code float}) to
* an {@link Function1} returning a {@link Float}.
*/
public static Function1 adapt(final FloatFunction1 f) {
return f::apply;
}
/**
* Creates a view of a list that applies a function to each element.
*
* @deprecated Use {@link com.google.common.collect.Lists#transform}
*/
@Deprecated // to be removed before 2.0
public static List adapt(final List list,
final Function1 f) {
return new AbstractList() {
@Override public R get(int index) {
return f.apply(list.get(index));
}
@Override public int size() {
return list.size();
}
};
}
/**
* Creates a view of an array that applies a function to each element.
*
* @deprecated Use {@link com.google.common.collect.Lists#transform}
* and {@link Arrays#asList(Object[])}
*/
@Deprecated // to be removed before 2.0
public static List adapt(final T[] ts,
final Function1 f) {
return new AbstractList() {
@Override public R get(int index) {
return f.apply(ts[index]);
}
@Override public int size() {
return ts.length;
}
};
}
/**
* Creates a copy of a list, applying a function to each element.
*/
public static List apply(final List list,
final Function1 f) {
final List list2 = new ArrayList<>(list.size());
for (T1 t : list) {
list2.add(f.apply(t));
}
return list2;
}
/** Returns a list that contains only elements of {@code list} that match
* {@code predicate}. Avoids allocating a list if all elements match or no
* elements match. */
@SuppressWarnings("MixedMutabilityReturnType")
public static List filter(List list, Predicate1 predicate) {
sniff:
{
int hitCount = 0;
int missCount = 0;
for (E e : list) {
if (predicate.apply(e)) {
if (missCount > 0) {
break sniff;
}
++hitCount;
} else {
if (hitCount > 0) {
break sniff;
}
++missCount;
}
}
if (hitCount == 0) {
return Collections.emptyList();
}
if (missCount == 0) {
return list;
}
}
final List list2 = new ArrayList<>(list.size());
for (E e : list) {
if (predicate.apply(e)) {
list2.add(e);
}
}
return list2;
}
/** Returns whether there is an element in {@code list} for which
* {@code predicate} is true. */
public static boolean exists(List extends E> list,
Predicate1 predicate) {
for (E e : list) {
if (predicate.apply(e)) {
return true;
}
}
return false;
}
/** Returns whether {@code predicate} is true for all elements of
* {@code list}. */
public static boolean all(List extends E> list,
Predicate1 predicate) {
for (E e : list) {
if (!predicate.apply(e)) {
return false;
}
}
return true;
}
/** Returns a list generated by applying a function to each index between
* 0 and {@code size} - 1. */
public static List generate(final int size,
final IntFunction fn) {
if (size < 0) {
throw new IllegalArgumentException();
}
return new GeneratingList<>(size, fn);
}
/**
* Returns a function of arity 0 that does nothing.
*
* @param Return type
* @return Function that does nothing.
*/
public static Function0 ignore0() {
//noinspection unchecked
return Ignore.INSTANCE;
}
/**
* Returns a function of arity 1 that does nothing.
*
* @param Return type
* @param Type of parameter 0
* @return Function that does nothing.
*/
public static Function1 ignore1() {
//noinspection unchecked
return Ignore.INSTANCE;
}
/**
* Returns a function of arity 2 that does nothing.
*
* @param Return type
* @param Type of parameter 0
* @param Type of parameter 1
* @return Function that does nothing.
*/
public static Function2 ignore2() {
//noinspection unchecked
return Ignore.INSTANCE;
}
/**
* Returns a {@link Comparator} that handles null values.
*
* @param nullsFirst Whether nulls come before all other values
* @param reverse Whether to reverse the usual order of {@link Comparable}s
*/
@SuppressWarnings("unchecked")
public static > Comparator nullsComparator(
boolean nullsFirst,
boolean reverse) {
return (Comparator)
(reverse
? (nullsFirst
? NULLS_FIRST_REVERSE_COMPARATOR
: NULLS_LAST_REVERSE_COMPARATOR)
: (nullsFirst
? NULLS_FIRST_COMPARATOR
: NULLS_LAST_COMPARATOR));
}
/**
* Returns a {@link Comparator} that handles null values.
*
* @param nullsFirst Whether nulls come before all other values
* @param reverse Whether to reverse the usual order of {@link Comparable}s
* @param comparator Comparator to be used for comparison
*/
@SuppressWarnings("unchecked")
public static > Comparator nullsComparator(
boolean nullsFirst,
boolean reverse,
Comparator comparator) {
return (T o1, T o2) -> {
if (o1 == o2) {
return 0;
}
if (o1 == null) {
return nullsFirst ? -1 : 1;
}
if (o2 == null) {
return nullsFirst ? 1 : -1;
}
return reverse ? -comparator.compare(o1, o2) : comparator.compare(o1, o2);
};
}
/**
* Returns an {@link EqualityComparer} that uses object identity and hash
* code.
*/
@SuppressWarnings("unchecked")
public static EqualityComparer identityComparer() {
return (EqualityComparer) IDENTITY_COMPARER;
}
/**
* Returns an {@link EqualityComparer} that works on arrays of objects.
*/
@SuppressWarnings("unchecked")
public static EqualityComparer arrayComparer() {
return (EqualityComparer) ARRAY_COMPARER;
}
/**
* Returns an {@link EqualityComparer} that uses a selector function.
*/
public static EqualityComparer selectorComparer(
Function1 selector) {
return new SelectorEqualityComparer<>(selector);
}
/** Array equality comparer. */
private static class ArrayEqualityComparer
implements EqualityComparer<@Nullable Object[]> {
@Override public boolean equal(@Nullable Object[] v1, @Nullable Object[] v2) {
return Arrays.deepEquals(v1, v2);
}
@Override public int hashCode(@Nullable Object[] t) {
return Arrays.deepHashCode(t);
}
}
/** Identity equality comparer. */
private static class IdentityEqualityComparer
implements EqualityComparer {
@Override public boolean equal(Object v1, Object v2) {
return Objects.equals(v1, v2);
}
@Override public int hashCode(Object t) {
return t == null ? 0x789d : t.hashCode();
}
}
/** Selector equality comparer.
*
* @param element type
* @param target type */
private static final class SelectorEqualityComparer
implements EqualityComparer {
private final Function1 selector;
SelectorEqualityComparer(Function1 selector) {
this.selector = selector;
}
@Override public boolean equal(T v1, T v2) {
return v1 == v2
|| v1 != null
&& v2 != null
&& Objects.equals(selector.apply(v1), selector.apply(v2));
}
@Override public int hashCode(T t) {
return t == null ? 0x789d : Objects.hashCode(selector.apply(t));
}
}
/** Nulls first comparator. */
private static class NullsFirstComparator
implements Comparator, Serializable {
@Override public int compare(Comparable o1, Comparable o2) {
if (o1 == o2) {
return 0;
}
if (o1 == null) {
return -1;
}
if (o2 == null) {
return 1;
}
//noinspection unchecked
return o1.compareTo(o2);
}
}
/** Nulls last comparator. */
private static class NullsLastComparator
implements Comparator, Serializable {
@Override public int compare(Comparable o1, Comparable o2) {
if (o1 == o2) {
return 0;
}
if (o1 == null) {
return 1;
}
if (o2 == null) {
return -1;
}
//noinspection unchecked
return o1.compareTo(o2);
}
}
/** Nulls first reverse comparator. */
private static class NullsFirstReverseComparator
implements Comparator, Serializable {
@Override public int compare(Comparable o1, Comparable o2) {
if (o1 == o2) {
return 0;
}
if (o1 == null) {
return -1;
}
if (o2 == null) {
return 1;
}
//noinspection unchecked
return -o1.compareTo(o2);
}
}
/** Nulls last reverse comparator. */
private static class NullsLastReverseComparator
implements Comparator, Serializable {
@Override public int compare(Comparable o1, Comparable o2) {
if (o1 == o2) {
return 0;
}
if (o1 == null) {
return 1;
}
if (o2 == null) {
return -1;
}
//noinspection unchecked
return -o1.compareTo(o2);
}
}
/** Ignore.
*
* @param result type
* @param first argument type
* @param second argument type */
private static final class Ignore<@Nullable R, T0, T1>
implements Function0, Function1, Function2 {
@Override public R apply() {
return null;
}
@Override public R apply(T0 p0) {
return null;
}
@Override public R apply(T0 p0, T1 p1) {
return null;
}
@DefaultQualifier(
value = Nullable.class,
locations = {
TypeUseLocation.LOWER_BOUND,
TypeUseLocation.UPPER_BOUND,
})
static final Ignore INSTANCE = new Ignore<>();
}
/** List that generates each element using a function.
*
* @param element type */
private static class GeneratingList extends AbstractList
implements RandomAccess {
private final int size;
private final IntFunction fn;
GeneratingList(int size, IntFunction fn) {
this.size = size;
this.fn = fn;
}
@Override public int size() {
return size;
}
@Override public E get(int index) {
return fn.apply(index);
}
}
}