/* * 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.tinkerpop.gremlin.process.traversal; import org.apache.tinkerpop.gremlin.process.traversal.util.AndP; import org.apache.tinkerpop.gremlin.process.traversal.util.OrP; import java.io.Serializable; import java.util.Arrays; import java.util.Collection; import java.util.function.BiPredicate; import java.util.function.Predicate; /** * @author Marko A. Rodriguez (http://markorodriguez.com) * @author Stephen Mallette (http://stephen.genoprime.com) */ public class P<V> implements Predicate<V>, Serializable, Cloneable { protected BiPredicate<V, V> biPredicate; protected V value; protected V originalValue; public P(final BiPredicate<V, V> biPredicate, final V value) { this.value = value; this.originalValue = value; this.biPredicate = biPredicate; } public BiPredicate<V, V> getBiPredicate() { return this.biPredicate; } /** * Gets the original value used at time of construction of the {@code P}. This value can change its type * in some cases. */ public V getOriginalValue() { return originalValue; } /** * Gets the current value to be passed to the predicate for testing. */ public V getValue() { return this.value; } public void setValue(final V value) { this.value = value; } @Override public boolean test(final V testValue) { return this.biPredicate.test(testValue, this.value); } @Override public int hashCode() { int result = this.biPredicate.hashCode(); if (null != this.originalValue) result ^= this.originalValue.hashCode(); return result; } @Override public boolean equals(final Object other) { return other instanceof P && ((P) other).getClass().equals(this.getClass()) && ((P) other).getBiPredicate().equals(this.biPredicate) && ((((P) other).getOriginalValue() == null && this.originalValue == null) || ((P) other).getOriginalValue().equals(this.originalValue)); } @Override public String toString() { return null == this.originalValue ? this.biPredicate.toString() : this.biPredicate.toString() + "(" + this.originalValue + ")"; } @Override public P<V> negate() { return new P<>(this.biPredicate.negate(), this.originalValue); } @Override public P<V> and(final Predicate<? super V> predicate) { if (!(predicate instanceof P)) throw new IllegalArgumentException("Only P predicates can be and'd together"); return new AndP<>(Arrays.asList(this, (P<V>) predicate)); } @Override public P<V> or(final Predicate<? super V> predicate) { if (!(predicate instanceof P)) throw new IllegalArgumentException("Only P predicates can be or'd together"); return new OrP<>(Arrays.asList(this, (P<V>) predicate)); } public P<V> clone() { try { return (P<V>) super.clone(); } catch (final CloneNotSupportedException e) { throw new IllegalStateException(e.getMessage(), e); } } //////////////// statics public static <V> P<V> eq(final V value) { return new P(Compare.eq, value); } public static <V> P<V> neq(final V value) { return new P(Compare.neq, value); } public static <V> P<V> lt(final V value) { return new P(Compare.lt, value); } public static <V> P<V> lte(final V value) { return new P(Compare.lte, value); } public static <V> P<V> gt(final V value) { return new P(Compare.gt, value); } public static <V> P<V> gte(final V value) { return new P(Compare.gte, value); } public static <V> P<V> inside(final V first, final V second) { return new AndP<V>(Arrays.asList(new P(Compare.gt, first), new P(Compare.lt, second))); } public static <V> P<V> outside(final V first, final V second) { return new OrP<V>(Arrays.asList(new P(Compare.lt, first), new P(Compare.gt, second))); } public static <V> P<V> between(final V first, final V second) { return new AndP<V>(Arrays.asList(new P(Compare.gte, first), new P(Compare.lt, second))); } public static <V> P<V> within(final V... values) { return P.within(Arrays.asList(values)); } public static <V> P<V> within(final Collection<V> value) { return new P(Contains.within, value); } public static <V> P<V> without(final V... values) { return P.without(Arrays.asList(values)); } public static <V> P<V> without(final Collection<V> value) { return new P(Contains.without, value); } public static P test(final BiPredicate biPredicate, final Object value) { return new P(biPredicate, value); } public static <V> P<V> not(final P<V> predicate) { return predicate.negate(); } }