001package com.randomnoun.common.jexl.eval.function;
002
003/* (c) 2013-2018 randomnoun. All Rights Reserved. This work is licensed under a
004 * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
005 */
006
007import java.util.List;
008
009import com.randomnoun.common.jexl.eval.EvalContext;
010import com.randomnoun.common.jexl.eval.EvalException;
011import com.randomnoun.common.jexl.eval.EvalFunction;
012
013/** Defines a like() function.
014 *
015 * <p>like() takes a two parameters, the string being matched and the SQL LIKE pattern we
016 * are matching on. The LIKE pattern uses the "%" character to represent any sequence of
017 * characters, and "_" to indicate a single character. This class automatically deals
018 * with conflicts with the Java regex parser, so the pattern may contain any other
019 * Unicode or regular expression characters, which will be treated like any other
020 * character.
021 *
022 * <p>The result of the function is of type Boolean.
023 */
024public class LikeFunction
025    implements EvalFunction
026{
027    /** Implements the function as per the class description. */
028    public Object evaluate(String functionName, EvalContext context, List<Object> arguments)
029        throws EvalException
030    {
031        if (arguments.size() != 2) { throw new EvalException(functionName + "() must contain two parameters"); }
032        if (!(arguments.get(0) instanceof String)) {
033            throw new EvalException(functionName + "() parameter 1 must be a string type");
034        }
035        if (!(arguments.get(1) instanceof String)) {
036            throw new EvalException(functionName + "() parameter 2 must be a string type");
037        }
038
039        String arg0 = (String)arguments.get(0);
040        String arg1 = (String)arguments.get(1);
041        if (arg0 == null) {
042            throw new EvalException(functionName + "() first parameter cannot be null");
043        }
044        if (arg1 == null) {
045            throw new EvalException(functionName + "() second parameter cannot be null");
046        }
047
048        // convert arg1 into a regex; first escape any chars that may confuse the
049        // regex engine (see java.util.regex.Pattern class to see how this list was derived)
050        String specialChars = "\\[]^$?*+{}|().";
051        for (int i = 0; i < specialChars.length(); i++) {
052            arg1 = arg1.replaceAll("\\" + specialChars.charAt(i),
053                    "\\\\" + "\\" + specialChars.charAt(i));
054        }
055        arg1 = arg1.replaceAll("%", ".*");
056        arg1 = arg1.replaceAll("_", ".");
057        return Boolean.valueOf(arg0.matches(arg1));
058    }
059}