/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2014, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.filter; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.util.logging.Logging; import org.opengis.filter.PropertyIsLike; /** * Helper class that takes a LikeFilter and generates the equivalent Java Pattern syntax * * @author Andrea Aime - GeoSolutions * @since 13.x */ public class LikeToRegexConverter { static final Logger LOGGER = Logging.getLogger(String.class); String pattern; public LikeToRegexConverter(PropertyIsLike like) { String pattern = like.getLiteral(); String wildcardMulti = like.getWildCard(); String wildcardSingle = like.getSingleChar(); String escape = like.getEscape(); // The following things happen for both wildcards: // (1) If a user-defined wildcard exists, replace with Java wildcard // (2) If a user-defined escape exists, Java wildcard + user-escape // Then, test for matching pattern and return result. char esc = escape.isEmpty() ? Character.MIN_VALUE : escape.charAt(0); if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("wildcard " + wildcardMulti + " single " + wildcardSingle); LOGGER.finer("escape " + escape + " esc " + esc + " esc == \\ " + (esc == '\\')); } String escapedWildcardMulti = fixSpecials(wildcardMulti, escape); String escapedWildcardSingle = fixSpecials(wildcardSingle, escape); // escape any special chars which are not our wildcards StringBuffer tmp = new StringBuffer(""); boolean escapedMode = false; for (int i = 0; i < pattern.length(); i++) { char chr = pattern.charAt(i); if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("tmp = " + tmp + " looking at " + chr); } if (!escape.isEmpty() && pattern.regionMatches(false, i, escape, 0, escape.length())) { // skip the escape string LOGGER.finer("escape "); escapedMode = true; i += escape.length(); chr = pattern.charAt(i); } if (pattern.regionMatches(false, i, wildcardMulti, 0, wildcardMulti.length())) { // replace // with // java // wildcard LOGGER.finer("multi wildcard"); if (escapedMode) { LOGGER.finer("escaped "); tmp.append(escapedWildcardMulti); } else { tmp.append(".*"); } i += (wildcardMulti.length() - 1); escapedMode = false; continue; } if (pattern.regionMatches(false, i, wildcardSingle, 0, wildcardSingle.length())) { // replace with java single wild card LOGGER.finer("single wildcard"); if (escapedMode) { LOGGER.finer("escaped "); tmp.append(escapedWildcardSingle); } else { // From the OpenGIS filter encoding spec, // "the single singleChar character matches exactly one character" tmp.append(".{1}"); } i += (wildcardSingle.length() - 1); escapedMode = false; continue; } if (isSpecial(chr) && !escape.isEmpty()) { LOGGER.finer("special"); tmp.append(escape + chr); escapedMode = false; continue; } tmp.append(chr); escapedMode = false; } pattern = tmp.toString(); if (LOGGER.isLoggable(Level.FINER)) { LOGGER.finer("final pattern " + pattern); } this.pattern = pattern; } /** * Convenience method to determine if a character is special to the regex system. * * @param chr the character to test * * @return is the character a special character. */ private boolean isSpecial(final char chr) { return ((chr == '.') || (chr == '?') || (chr == '*') || (chr == '^') || (chr == '$') || (chr == '+') || (chr == '[') || (chr == ']') || (chr == '(') || (chr == ')') || (chr == '|') || (chr == '\\') || (chr == '&')); } /** * Convenience method to escape any character that is special to the regex system. * * @param inString the string to fix * @param escape the escape charatter * * @return the fixed string */ private String fixSpecials(final String inString, final String escape) { StringBuffer tmp = new StringBuffer(""); for (int i = 0; i < inString.length(); i++) { char chr = inString.charAt(i); if (isSpecial(chr)) { tmp.append(escape + chr); } else { tmp.append(chr); } } return tmp.toString(); } /** * Returns the equivalent Java pattern * * @return */ public String getPattern() { return pattern; } }