All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.query.Predicates Maven / Gradle / Ivy

There is a newer version: 62
Show newest version
/*
 * Copyright (c) 2008-2019, Hazelcast, 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.hazelcast.query;

import com.hazelcast.query.impl.FalsePredicate;
import com.hazelcast.query.impl.predicates.AndPredicate;
import com.hazelcast.query.impl.predicates.BetweenPredicate;
import com.hazelcast.query.impl.predicates.EqualPredicate;
import com.hazelcast.query.impl.predicates.GreaterLessPredicate;
import com.hazelcast.query.impl.predicates.ILikePredicate;
import com.hazelcast.query.impl.predicates.InPredicate;
import com.hazelcast.query.impl.predicates.InstanceOfPredicate;
import com.hazelcast.query.impl.predicates.LikePredicate;
import com.hazelcast.query.impl.predicates.NotEqualPredicate;
import com.hazelcast.query.impl.predicates.NotPredicate;
import com.hazelcast.query.impl.predicates.OrPredicate;
import com.hazelcast.query.impl.predicates.RegexPredicate;

import java.util.Date;

/**
 * A utility class to create {@link com.hazelcast.query.Predicate} instances.
 * 

* Special Attributes *

* The predicate factory methods accepting an attribute name support two special attributes: *

    *
  • {@link QueryConstants#KEY_ATTRIBUTE_NAME "__key"} - instructs the predicate to act on the key associated * with an item. *
  • {@link QueryConstants#THIS_ATTRIBUTE_NAME "this"} - instructs the predicate to act on the value associated * with an item. *
*

* Attribute Paths *

* Dot notation may be used for attribute name to instruct the predicate to act on the attribute located at deeper * level of an item: given {@code "fullName.firstName"} path the predicate will act on {@code firstName} attribute * of the value fetched by {@code fullName} attribute from the item itself. If any of the attributes along the path * can't be resolved, {@link IllegalArgumentException} will be thrown. Reading of any attribute from {@code null} * will produce {@code null} value. *

* Square brackets notation may be used to instruct the predicate to act on the array/collection element at the * specified index: given {@code "names[0]"} path the predicate will act on the first item of the array/collection * fetched by {@code names} attribute from the item. The index must be non-negative, otherwise * {@link IllegalArgumentException} will be thrown. Reading from the index pointing beyond the end of the collection/array * will produce {@code null} value. *

* Special {@code any} keyword may be used to act on every array/collection element: given * {@code "names[any].fullName.firstName"} path the predicate will act on {@code firstName} attribute of the value * fetched by {@code fullName} attribute from every array/collection element stored in the item itself under {@code names} * attribute. *

* Handling of {@code null} *

* The predicate factory methods can accept {@code null} as a value to compare with or a pattern to match against * if and only if that is explicitly stated in the method documentation. In this case, the usual {@code null} equality * logic applies: if {@code null} is provided, the predicate passes an item if and only if the value stored under the * item attribute in question is also {@code null}. *

* Special care must be taken while comparing with {@code null} values stored inside items being filtered * through the predicates created by the following methods: {@link #greaterThan}, {@link #greaterEqual}, {@link #lessThan}, * {@link #lessEqual}, {@link #between}. The predicates produced by these methods intentionally violate {@link Comparable} * contract by not throwing {@link NullPointerException} for {@code null} values. Instead, they always evaluate to * {@code false} and therefore never pass such items. *

* Implicit Type Conversion *

* If the type of the stored value doesn't match the type of the value provided to the predicate, implicit type conversion * is performed before predicate evaluation. The provided value is converted to match the type of the stored attribute value. * If no conversion matching the type exists, {@link IllegalArgumentException} is thrown. *

* Depending on the attribute type following conversions may apply: *

    *
  • {@link Number Numeric types} *
      *
    • Strings are parsed in attempt to extract the represented numeric value from them in the same way as * {@link Integer#parseInt(String)} and analogous methods of other types do. Strings containing no meaningful * representation will produce {@link NumberFormatException}. *
    • Widening conversion may be performed in the same way as described in JLS 5.1.2 Widening Primitive Conversions. *
    • Narrowing conversion may be performed in the same way as described in JLS 5.1.3 Narrowing Primitive Conversions. *
    *
  • {@link Boolean} type *
      *
    • A string that case-insensitively equals to {@code "true"} is converted to {@code true}, all other strings are * converted to {@code false}. *
    • Any non-zero numeric value is converted to {@code true}, the zero is converted to {@code false}. *
    *
  • String type *
      *
    • {@link Object#toString()} is invoked to produce the string representation for non-string values. *
    *
  • {@link Character} type *
      *
    • The first character of a string is used for the conversion. Empty strings are not allowed and will produce * {@link IllegalArgumentException}. *
    • Any numeric value is converted to an integer value representing a single UTF-16 code unit to create a character * from. This process may involve widening and narrowing conversions as described in JLS 5.1.2 Widening Primitive * Conversions and 5.1.3 Narrowing Primitive Conversions. *
    *
  • Enum types *
      *
    • Any non-string value is converted to a string using {@link Object#toString()}, which is interpreted as a * case-sensitive enum member name. *
    *
  • {@link java.math.BigInteger BigInteger} type *
      *
    • Numeric values are converted to {@link java.math.BigInteger BigInteger} by applying widening or narrowing * conversion as described in JLS 5.1.2 Widening Primitive Conversions and 5.1.3 Narrowing Primitive Conversions. *
    • Boolean {@code true} and {@code false} are converted to {@link java.math.BigInteger#ONE BigInteger.ONE} * and {@link java.math.BigInteger#ZERO BigInteger.ZERO} respectively. *
    • A value of any other type is converted to string using {@link Object#toString()}, which is interpreted as * a base 10 representation in the same way as {@link java.math.BigInteger#BigInteger(String) BigInteger(String)} does. * If the representation is invalid, {@link NumberFormatException} will be thrown. *
    *
  • {@link java.math.BigDecimal BigDecimal} type *
      *
    • Numeric value are converted to {@link java.math.BigDecimal BigDecimal} by applying widening conversion as * described in JLS 5.1.2 Widening Primitive Conversions. *
    • Boolean {@code true} and {@code false} are converted to {@link java.math.BigDecimal#ONE BigDecimal.ONE} * and {@link java.math.BigDecimal#ZERO BigDecimal.ZERO} respectively. *
    • A value of any other type is converted to string using {@link Object#toString()}, which is interpreted as * a base 10 representation in the same way as {@link java.math.BigDecimal#BigDecimal(String) BigDecimal(String)} does. * If the representation is invalid, {@link NumberFormatException} will be thrown. *
    *
  • {@link java.sql.Timestamp SQL Timestamp} type *
      *
    • Date values are converted to {@link java.sql.Timestamp SQL Timestamp} by applying {@link Date#getTime()} on them. *
    • String values are interpreted in the same way as {@link java.sql.Timestamp#valueOf(String)} does. * {@link RuntimeException} wrapping {@link java.text.ParseException} is thrown for invalid representations. *
    • Any numeric value is interpreted as the number of milliseconds since January 1, 1970, 00:00:00 GMT by * applying widening or narrowing conversion as described in JLS 5.1.2 Widening Primitive Conversions and 5.1.3 * Narrowing Primitive Conversions. *
    *
  • {@link java.sql.Date SQL Date} type *
      *
    • String values are interpreted in the same way as {@link java.sql.Date#valueOf(String)} does. * {@link RuntimeException} wrapping {@link java.text.ParseException} is thrown for invalid representations. *
    • Any numeric value is interpreted as the number of milliseconds since January 1, 1970, 00:00:00 GMT * by applying widening or narrowing conversion as described in JLS 5.1.2 Widening Primitive Conversions and * 5.1.3 Narrowing Primitive Conversions. *
    *
  • {@link Date} type *
      *
    • String values are interpreted as having EEE MMM dd HH:mm:ss zzz yyyy format and * {@link java.util.Locale#US US} locale in the same way as {@link java.text.SimpleDateFormat} does. * {@link RuntimeException} wrapping {@link java.text.ParseException} is thrown for invalid representations. *
    • Any numeric value is interpreted as the number of milliseconds since January 1, 1970, 00:00:00 GMT by * applying widening or narrowing conversion as described in JLS 5.1.2 Widening Primitive Conversions and 5.1.3 * Narrowing Primitive Conversions. *
    *
  • {@link java.util.UUID UUID} type *
      *
    • String values are interpreted in the same way as {@link java.util.UUID#fromString(String)} does. * {@link IllegalArgumentException} is thrown for invalid representations. *
    *
*/ public final class Predicates { //we don't want instances. private constructor. private Predicates() { } /** * Creates an always true predicate that will pass all items. */ public static Predicate alwaysTrue() { return new TruePredicate(); } /** * Creates an always false predicate that will filter out all items. */ public static Predicate alwaysFalse() { return new FalsePredicate(); } /** * Creates an instance of predicate that will pass entries for which * the value class is an {@code instanceof} the given {@code klass}. * * @param klass the class the created predicate will check for. * @return the created instance of predicate. */ public static Predicate instanceOf(final Class klass) { return new InstanceOfPredicate(klass); } /** * Creates an and predicate that will perform the logical and operation on the given {@code predicates}. *

* If the given {@code predicates} list is empty, the created predicate will always evaluate to {@code true} * and will pass any item. * * @param predicates the child predicates to form the resulting and predicate from. * @return the created and predicate instance. */ public static Predicate and(Predicate... predicates) { return new AndPredicate(predicates); } /** * Creates a not predicate that will negate the result of the given {@code predicate}. * * @param predicate the predicate to negate the value of. * @return the created not predicate instance. */ public static Predicate not(Predicate predicate) { return new NotPredicate(predicate); } /** * Creates an or predicate that will perform the logical or operation on the given {@code predicates}. *

* If the given {@code predicates} list is empty, the created predicate will always evaluate to {@code false} * and will never pass any items. * * @param predicates the child predicates to form the resulting or predicate from. * @return the created or predicate instance. */ public static Predicate or(Predicate... predicates) { return new OrPredicate(predicates); } /** * Creates a not equal predicate that will pass items if the given {@code value} and the value stored under * the given item {@code attribute} are not equal. *

* See also Special Attributes, Attribute Paths, Handling of {@code null} and * Implicit Type Conversion sections of {@link Predicates}. * * @param attribute the attribute to fetch the value for comparison from. * @param value the value to compare the attribute value against. Can be {@code null}. * @return the created not equal predicate instance. * @throws IllegalArgumentException if the {@code attribute} does not exist. */ public static Predicate notEqual(String attribute, Comparable value) { return new NotEqualPredicate(attribute, value); } /** * Creates an equal predicate that will pass items if the given {@code value} and the value stored under * the given item {@code attribute} are equal. *

* See also Special Attributes, Attribute Paths, Handling of {@code null} and * Implicit Type Conversion sections of {@link Predicates}. * * @param attribute the attribute to fetch the value for comparison from. * @param value the value to compare the attribute value against. Can be {@code null}. * @return the created equal predicate instance. * @throws IllegalArgumentException if the {@code attribute} does not exist. */ public static Predicate equal(String attribute, Comparable value) { return new EqualPredicate(attribute, value); } /** * Creates a like predicate that will pass items if the given {@code pattern} matches the value stored under * the given item {@code attribute}. *

* See also Special Attributes, Attribute Paths and Handling of {@code null} sections of * {@link Predicates}. * * @param attribute the attribute to fetch the value for matching from. * @param pattern the pattern to match the attribute value against. The % (percentage sign) is a placeholder for * multiple characters, the _ (underscore) is a placeholder for a single character. If you need to * match the percentage sign or the underscore character itself, escape it with the backslash, * for example {@code "\\%"} string will match the percentage sign. Can be {@code null}. * @return the created like predicate instance. * @throws IllegalArgumentException if the {@code attribute} does not exist. * @see #ilike(String, String) * @see #regex(String, String) */ public static Predicate like(String attribute, String pattern) { return new LikePredicate(attribute, pattern); } /** * Creates a case-insensitive like predicate that will pass items if the given {@code pattern} matches the value * stored under the given item {@code attribute} in a case-insensitive manner. *

* See also Special Attributes, Attribute Paths and Handling of {@code null} sections of * {@link Predicates}. * * @param attribute the attribute to fetch the value for matching from. * @param pattern the pattern to match the attribute value against. The % (percentage sign) is a placeholder for * multiple characters, the _ (underscore) is a placeholder for a single character. If you need to * match the percentage sign or the underscore character itself, escape it with the backslash, * for example {@code "\\%"} string will match the percentage sign. Can be {@code null}. * @return the created case-insensitive like predicate instance. * @throws IllegalArgumentException if the {@code attribute} does not exist. * @see #like(String, String) * @see #regex(String, String) */ public static Predicate ilike(String attribute, String pattern) { return new ILikePredicate(attribute, pattern); } /** * Creates a regex predicate that will pass items if the given {@code pattern} matches the value stored under * the given item {@code attribute}. *

* See also Special Attributes, Attribute Paths and Handling of {@code null} sections of * {@link Predicates}. * * @param attribute the attribute to fetch the value for matching from. * @param pattern the pattern to match the attribute value against. The pattern interpreted exactly the same as * described in {@link java.util.regex.Pattern}. Can be {@code null}. * @return the created regex predicate instance. * @throws IllegalArgumentException if the {@code attribute} does not exist. * @see #like(String, String) * @see #ilike(String, String) */ public static Predicate regex(String attribute, String pattern) { return new RegexPredicate(attribute, pattern); } /** * Creates a greater than predicate that will pass items if the value stored under the given * item {@code attribute} is greater than the given {@code value}. *

* See also Special Attributes, Attribute Paths, Handling of {@code null} and * Implicit Type Conversion sections of {@link Predicates}. * * @param attribute the left-hand side attribute to fetch the value for comparison from. * @param value the right-hand side value to compare the attribute value against. * @return the created greater than predicate. * @throws IllegalArgumentException if the {@code attribute} does not exist. */ public static Predicate greaterThan(String attribute, Comparable value) { return new GreaterLessPredicate(attribute, value, false, false); } /** * Creates a greater than or equal to predicate that will pass items if the value stored under the given * item {@code attribute} is greater than or equal to the given {@code value}. *

* See also Special Attributes, Attribute Paths, Handling of {@code null} and * Implicit Type Conversion sections of {@link Predicates}. * * @param attribute the left-hand side attribute to fetch the value for comparison from. * @param value the right-hand side value to compare the attribute value against. * @return the created greater than or equal to predicate. * @throws IllegalArgumentException if the {@code attribute} does not exist. */ public static Predicate greaterEqual(String attribute, Comparable value) { return new GreaterLessPredicate(attribute, value, true, false); } /** * Creates a less than predicate that will pass items if the value stored under the given item {@code attribute} * is less than the given {@code value}. *

* See also Special Attributes, Attribute Paths, Handling of {@code null} and * Implicit Type Conversion sections of {@link Predicates}. * * @param attribute the left-hand side attribute to fetch the value for comparison from. * @param value the right-hand side value to compare the attribute value against. * @return the created less than predicate. * @throws IllegalArgumentException if the {@code attribute} does not exist. */ public static Predicate lessThan(String attribute, Comparable value) { return new GreaterLessPredicate(attribute, value, false, true); } /** * Creates a less than or equal to predicate that will pass items if the value stored under the given * item {@code attribute} is less than or equal to the given {@code value}. *

* See also Special Attributes, Attribute Paths, Handling of {@code null} and * Implicit Type Conversion sections of {@link Predicates}. * * @param attribute the left-hand side attribute to fetch the value for comparison from. * @param value the right-hand side value to compare the attribute value against. * @return the created less than or equal to predicate. * @throws IllegalArgumentException if the {@code attribute} does not exist. */ public static Predicate lessEqual(String attribute, Comparable value) { return new GreaterLessPredicate(attribute, value, true, true); } /** * Creates a between predicate that will pass items if the value stored under the given item {@code attribute} * is contained inside the given range. The range begins at the given {@code from} bound and ends at * the given {@code to} bound. The bounds are inclusive. *

* See also Special Attributes, Attribute Paths, Handling of {@code null} and * Implicit Type Conversion sections of {@link Predicates}. * * @param attribute the attribute to fetch the value to check from. * @param from the inclusive lower bound of the range to check. * @param to the inclusive upper bound of the range to check. * @return the created between predicate. * @throws IllegalArgumentException if the {@code attribute} does not exist. */ public static Predicate between(String attribute, Comparable from, Comparable to) { return new BetweenPredicate(attribute, from, to); } /** * Creates a in predicate that will pass items if the value stored under the given item {@code attribute} * is a member of the given {@code values} set. *

* See also Special Attributes, Attribute Paths, Handling of {@code null} and * Implicit Type Conversion sections of {@link Predicates}. * * @param attribute the attribute to fetch the value to test from. * @param values the values set to test the membership in. Individual values can be {@code null}. * @return the created in predicate. * @throws IllegalArgumentException if the {@code attribute} does not exist. */ public static Predicate in(String attribute, Comparable... values) { return new InPredicate(attribute, values); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy