FilterHelpers.java

/*
 * Copyright 2018 Global Crop Diversity Trust
 *
 * 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 org.genesys.server.model.filters;

import java.util.Arrays;
import java.util.regex.Pattern;

import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.StringPath;

/**
 * Filter Helpers.
 */
public abstract class FilterHelpers {
	private static final Pattern pattern = Pattern.compile("[^\\w]+", Pattern.UNICODE_CHARACTER_CLASS);

	/**
	 * Create a boolean expression where the string path matches any of the
	 * keywords.
	 *
	 * @param stringPath the string path
	 * @param keywords the keywords
	 * @return the boolean expression
	 */
	public static BooleanExpression equalsAny(final StringPath stringPath, final String[] keywords) {
		BooleanExpression ex = stringPath.equalsIgnoreCase(keywords[0]);
		for (int i = 1; i < keywords.length; i++) {
			ex = ex.or(stringPath.equalsIgnoreCase(keywords[i]));
		}
		return ex;
	}

	/**
	 * Constructs an array of predicates where each string path matches any of the
	 * keywords.
	 *
	 * @param text the text to split into keywords
	 * @param stringPaths the string paths
	 * @return the predicate[]
	 */
	public static Predicate[] equalsAny(final String text, final StringPath... stringPaths) {
		final String[] kw = getKeywords(text);
		final BooleanExpression[] containsAlls = new BooleanExpression[stringPaths.length];
		for (int i = stringPaths.length - 1; i >= 0; i--) {
			containsAlls[i] = equalsAny(stringPaths[i], kw);
		}
		return containsAlls;
	}

	/**
	 * Create a boolean expression where the string path contains all keywords.
	 *
	 * @param stringPath the string path
	 * @param keywords the keywords
	 * @return the boolean expression
	 */
	public static BooleanExpression containsAll(final StringPath stringPath, final String[] keywords) {
		BooleanExpression ex = stringPath.containsIgnoreCase(keywords[0]);
		for (int i = 1; i < keywords.length; i++) {
			ex = ex.and(stringPath.containsIgnoreCase(keywords[i]));
		}
		return ex;
	}

	/**
	 * Constructs an array of predicates where each string path contains every
	 * keyword keywords.
	 *
	 * @param _text the text
	 * @param stringPaths the string paths
	 * @return the predicate[]
	 */
	public static Predicate[] containsAll(final String _text, final StringPath... stringPaths) {
		final String[] kw = getKeywords(_text);

		final BooleanExpression[] containsAlls = new BooleanExpression[stringPaths.length];
		for (int i = stringPaths.length - 1; i >= 0; i--) {
			containsAlls[i] = containsAll(stringPaths[i], kw);
		}
		return containsAlls;
	}

	/**
	 * Split the input text into keywords.
	 *
	 * @param text text to split into keywords
	 * @return array of non-null, non-blank, no-special-chars keywords
	 */
	protected static String[] getKeywords(final String text) {
		final String[] kw = Arrays.stream(pattern.split(text)).filter(s -> s.length() > 0).toArray(String[]::new);
		// System.err.println("keywords " + text + " -> " + Arrays.toString(kw));
		return kw;
	}

}