blob: 497baafdc104dfe10efa11b7acac80bf0e6aaae0 [file] [log] [blame]
/*
* 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.ignite.internal.util;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.ignite.internal.util.lang.GridFunc;
import org.apache.ignite.internal.util.lang.GridNodePredicate;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.P1;
import org.apache.ignite.internal.util.typedef.internal.A;
import org.apache.ignite.lang.IgnitePredicate;
import org.jetbrains.annotations.Nullable;
/**
* Internal utility class that contains not peer-deployable
* predicates for use in internal logic.
*/
public class F0 {
/**
* Negates given predicates.
* <p>
* Gets predicate (not peer-deployable) that evaluates to {@code true} if any of given predicates
* evaluates to {@code false}. If all predicates evaluate to {@code true} the
* result predicate will evaluate to {@code false}.
*
* @param p Predicate to negate.
* @param <T> Type of the free variable, i.e. the element the predicate is called on.
* @return Negated predicate (not peer-deployable).
*/
@SuppressWarnings("unchecked")
public static <T> IgnitePredicate<T> not(@Nullable final IgnitePredicate<? super T>... p) {
return F.isAlwaysFalse(p) ? F.<T>alwaysTrue() : F.isAlwaysTrue(p) ? F.<T>alwaysFalse() : new P1<T>() {
@Override public boolean apply(T t) {
return !F.isAll(t, p);
}
};
}
/**
* Gets predicate (not peer-deployable) that evaluates to {@code true} if its free variable is not equal
* to {@code target} or both are {@code null}.
*
* @param target Object to compare free variable to.
* @param <T> Type of the free variable, i.e. the element the predicate is called on.
* @return Predicate (not peer-deployable) that evaluates to {@code true} if its free variable is not equal
* to {@code target} or both are {@code null}.
*/
public static <T> IgnitePredicate<T> notEqualTo(@Nullable final T target) {
return new P1<T>() {
@Override public boolean apply(T t) {
return !F.eq(t, target);
}
};
}
/**
* Gets predicate (not peer-deployable) that returns {@code true} if its free variable
* is not contained in given collection.
*
* @param c Collection to check for containment.
* @param <T> Type of the free variable for the predicate and type of the
* collection elements.
* @return Predicate (not peer-deployable) that returns {@code true} if its free variable is not
* contained in given collection.
*/
public static <T> IgnitePredicate<T> notIn(@Nullable final Collection<? extends T> c) {
return F.isEmpty(c) ? GridFunc.<T>alwaysTrue() : new P1<T>() {
@Override public boolean apply(T t) {
return !c.contains(t);
}
};
}
/**
* Gets predicate (not perr-deployable) that evaluates to {@code true} if its free variable is equal
* to {@code target} or both are {@code null}.
*
* @param target Object to compare free variable to.
* @param <T> Type of the free variable, i.e. the element the predicate is called on.
* @return Predicate that evaluates to {@code true} if its free variable is equal to
* {@code target} or both are {@code null}.
*/
public static <T> IgnitePredicate<T> equalTo(@Nullable final T target) {
return new P1<T>() {
@Override public boolean apply(T t) {
return F.eq(t, target);
}
};
}
/**
* Get a predicate (non peer-deployable) that evaluates to {@code true} if each of its component predicates
* evaluates to {@code true}. The components are evaluated in order they are supplied.
* Evaluation will be stopped as soon as first predicate evaluates to {@code false}.
* Passed in predicates are NOT copied. If no predicates are passed in the returned
* predicate will always evaluate to {@code false}.
*
* @param p1 Passed in predicates.
* @param p2 Passed in predicates.
* @param <T> Type of the free variable, i.e. the element the predicate is called on.
* @return Predicate that evaluates to {@code true} if each of its component predicates
* evaluates to {@code true}.
*/
@SuppressWarnings({"unchecked", "ConfusingArgumentToVarargsMethod"})
public static <T> IgnitePredicate<T> and(@Nullable final IgnitePredicate<? super T>[] p1,
@Nullable final IgnitePredicate<? super T>... p2) {
if (F.isAlwaysFalse(p1) || F.isAlwaysFalse(p2))
return F.alwaysFalse();
if (F.isAlwaysTrue(p1) && F.isAlwaysTrue(p2))
return F.alwaysTrue();
final boolean e1 = F.isEmpty(p1);
final boolean e2 = F.isEmpty(p2);
if (e1 && e2)
return F.alwaysTrue();
if (e1) {
if (p2.length == 1)
return (IgnitePredicate<T>)p2[0];
}
if (!e1 && e2) {
if (p1.length == 1)
return (IgnitePredicate<T>)p1[0];
}
if ((e1 || isAllNodePredicates(p1)) && (e2 || isAllNodePredicates(p2))) {
Set<UUID> ids = new GridLeanSet<>();
if (!e1) {
for (IgnitePredicate<? super T> p : p1)
ids.addAll(((GridNodePredicate)p).nodeIds());
}
if (!e2) {
for (IgnitePredicate<? super T> p : p2)
ids.addAll(((GridNodePredicate)p).nodeIds());
}
// T must be <T extends ClusterNode>.
return (IgnitePredicate<T>)new GridNodePredicate(ids);
}
else {
return new P1<T>() {
@Override public boolean apply(T t) {
if (!e1) {
for (IgnitePredicate<? super T> p : p1)
if (p != null && !p.apply(t))
return false;
}
if (!e2) {
for (IgnitePredicate<? super T> p : p2)
if (p != null && !p.apply(t))
return false;
}
return true;
}
};
}
}
/**
* Get a predicate (not peer-deployable) that evaluates to {@code true} if each of its component predicates
* evaluates to {@code true}. The components are evaluated in order they are supplied.
* Evaluation will be stopped as soon as first predicate evaluates to {@code false}.
* Passed in predicates are NOT copied. If no predicates are passed in the returned
* predicate will always evaluate to {@code false}.
*
* @param ps Passed in predicate. If none provided - always-{@code false} predicate is
* returned.
* @param <T> Type of the free variable, i.e. the element the predicate is called on.
* @return Predicate that evaluates to {@code true} if each of its component predicates
* evaluates to {@code true}.
*/
@SuppressWarnings({"unchecked", "ConfusingArgumentToVarargsMethod", "ConstantConditions"})
public static <T> IgnitePredicate<T> and(
@Nullable final IgnitePredicate<? super T> p,
@Nullable final IgnitePredicate<? super T>... ps
) {
if (p == null && F.isEmptyOrNulls(ps))
return F.alwaysTrue();
if (F.isAlwaysFalse(p) && F.isAlwaysFalse(ps))
return F.alwaysFalse();
if (F.isAlwaysTrue(p) && F.isAlwaysTrue(ps))
return F.alwaysTrue();
if (isAllNodePredicates(p) && isAllNodePredicates(ps)) {
assert ps != null;
Set<UUID> ids = new GridLeanSet<>();
for (IgnitePredicate<? super T> p0 : ps) {
Collection<UUID> list = ((GridNodePredicate)p0).nodeIds();
if (ids.isEmpty())
ids.addAll(list);
else
ids.retainAll(list);
}
Collection<UUID> list = ((GridNodePredicate)p).nodeIds();
if (ids.isEmpty())
ids.addAll(list);
else
ids.retainAll(list);
// T must be <T extends ClusterNode>.
return (IgnitePredicate<T>)new GridNodePredicate(ids);
}
else {
return new P1<T>() {
@Override public boolean apply(T t) {
assert ps != null;
if (p != null && !p.apply(t))
return false;
for (IgnitePredicate<? super T> p : ps)
if (p != null && !p.apply(t))
return false;
return true;
}
};
}
}
/**
* Gets predicate (not peer-deployable) that returns {@code true} if its free variable is contained
* in given collection.
*
* @param c Collection to check for containment.
* @param <T> Type of the free variable for the predicate and type of the
* collection elements.
* @return Predicate (not peer-deployable) that returns {@code true} if its free variable is
* contained in given collection.
*/
public static <T> IgnitePredicate<T> in(@Nullable final Collection<? extends T> c) {
return F.isEmpty(c) ? GridFunc.<T>alwaysFalse() : new P1<T>() {
@Override public boolean apply(T t) {
return c.contains(t);
}
};
}
/**
* Provides predicate (not peer-deployable) which returns {@code true} if it receives an element
* that is contained in the passed in collection.
*
* @param c Collection used for predicate filter.
* @param <T> Element type.
* @return Predicate which returns {@code true} if it receives an element
* that is contained in the passed in collection.
*/
public static <T> IgnitePredicate<T> contains(@Nullable final Collection<T> c) {
return c == null || c.isEmpty() ? GridFunc.<T>alwaysFalse() : new P1<T>() {
@Override public boolean apply(T t) {
return c.contains(t);
}
};
}
/**
* Provides predicate (not peer-deployable) which returns {@code true} if it receives an element
* that is not contained in the passed in collection.
*
* @param c Collection used for predicate filter.
* @param <T> Element type.
* @return Predicate which returns {@code true} if it receives an element
* that is not contained in the passed in collection.
*/
public static <T> IgnitePredicate<T> notContains(@Nullable final Collection<T> c) {
return c == null || c.isEmpty() ? GridFunc.<T>alwaysTrue() : new P1<T>() {
@Override public boolean apply(T t) {
return !c.contains(t);
}
};
}
/**
* Tests if all passed in predicates are instances of {@link GridNodePredicate} class.
*
* @param ps Collection of predicates to test.
* @return {@code True} if all passed in predicates are instances of {@link GridNodePredicate} class.
*/
public static boolean isAllNodePredicates(@Nullable IgnitePredicate<?>... ps) {
if (F.isEmpty(ps))
return false;
for (IgnitePredicate<?> p : ps)
if (!(p instanceof GridNodePredicate))
return false;
return true;
}
/**
* Creates map with given values, adding a strict not-null check for value.
*
* @param key Key.
* @param val Value.
* @param <K> Key's type.
* @param <V> Value's type.
* @return Created map.
*/
public static <K, V> Map<K, V> asMap(K key, V val) {
A.notNull(val, "val");
return F.asMap(key, val);
}
}