/*
* Copyright (C) 2013-2017 NTT DATA Corporation
*
* 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.terasoluna.gfw.common.query;
/**
* An object to escape like condition in a query.<br>
* @since 1.0.2
*/
public class LikeConditionEscape {
/**
* whether to escape full-width wildcards.
*/
private final boolean escapeFullWithWildcards;
/**
* Escape character used in the pattern string of LIKE value. Escape character is '~'.
*/
public static final char LIKE_ESC_CHAR = '~';
/**
* Constructor
* @param escapeFullWithWildcards whether to escape full-width wildcards.
*/
private LikeConditionEscape(boolean escapeFullWithWildcards) {
this.escapeFullWithWildcards = escapeFullWithWildcards;
}
/**
* Constructor to escape like condition in a query (including full-with wildcards).
* @return LikeConditionEscape instance for including full-with wildcards
*/
public static LikeConditionEscape withFullWidthWildcardsEscape() {
return new LikeConditionEscape(true);
}
/**
* Constructor to escape like condition in a query (<strong>NOT</strong> including full-with wildcards). @return
* LikeConditionEscape instance for NOT including full-with wildcards
*/
public static LikeConditionEscape withoutFullWidthWildcardsEscape() {
return new LikeConditionEscape(false);
}
/**
* <p>
* Convert a search criteria string to the escaped string of LIKE condition.
* </p>
* <p>
* Conversion rules are as follows:
* </p>
* <ol>
* <li>Escape {@link #LIKE_ESC_CHAR} using {@link #LIKE_ESC_CHAR}.</li>
* <li>Escape '%' and '_' using {@link #LIKE_ESC_CHAR}.</li>
* <li>Escape '%' and '_' using {@link #LIKE_ESC_CHAR} if <code>escapeFullWithWildcards</code> is <code>true</code>.</li>
* </ol>
* <p>
* For example.<br>
*
* <pre>
* <code>
*
* toLikeCondition("a") -> "a"
* toLikeCondition("a~") -> "a~~"
* toLikeCondition("a%") -> "a~%"
* toLikeCondition("a_") -> "a~_"
* toLikeCondition("_a%") -> "~_a~%"
* toLikeCondition("a%") -> "a~%" (if escapeFullWithWildcards is true)
* toLikeCondition("a%") -> "a%" (if escapeFullWithWildcards is false)
* toLikeCondition("a_") -> "a~_" (if escapeFullWithWildcards is true)
* toLikeCondition("a_") -> "a_" (if escapeFullWithWildcards is false)
* toLikeCondition(" ") -> " "
* toLikeCondition("") -> ""
* toLikeCondition(null) -> null
* toLikeCondition(null) -> null
* </code>
* </pre>
* <p>
* return likeCondition of argument when condition is <code>null</code>.<br>
* Returned value is not appended "%" keyword.
* </p>
* @param condition search criteria string.
* @param likeCondition instance of StringBuilder for storing a converted search criteria string. <br>
* if arguments is null, create new instance of StringBuilder and stored a converted search criteria string.
* @return instance of StringBuilder that are stored a converted search criteria string.
*/
public StringBuilder toLikeCondition(String condition,
StringBuilder likeCondition) {
StringBuilder storingLikeCondition = likeCondition;
if (storingLikeCondition == null) {
storingLikeCondition = new StringBuilder();
}
if (condition == null) {
return storingLikeCondition;
}
for (int i = 0; i < condition.length(); i++) {
char c = condition.charAt(i);
if (c == LIKE_ESC_CHAR) {
storingLikeCondition.append(LIKE_ESC_CHAR);
} else if (c == '%' || c == '_') {
storingLikeCondition.append(LIKE_ESC_CHAR);
} else if (escapeFullWithWildcards && (c == '_' || c == '%')) {
storingLikeCondition.append(LIKE_ESC_CHAR);
}
storingLikeCondition.append(c);
}
return storingLikeCondition;
}
/**
* Convert a search criteria string to the escaped string of LIKE condition
* <p>
* Conversion rules see JavaDoc of {@link #toLikeCondition(String, StringBuilder)}.
* </p>
* <p>
* return null when condition is <code>null</code>.<br>
* Returned value is appended "%" keyword to the front, if not null or blank string.
* </p>
* @param condition search criteria string.
* @return converted search criteria string.
*/
public String toLikeCondition(String condition) {
if (condition == null) {
return null;
}
return toLikeCondition(condition, new StringBuilder()).toString();
}
/**
* Convert a search criteria string to the escaped string of LIKE condition ,and append "%" keyword to the front.
* <p>
* Conversion rules see JavaDoc of {@link #toLikeCondition(String, StringBuilder)}.
* </p>
* <p>
* return null when condition is <code>null</code>.<br>
* Returned value is appended "%" keyword to the front, if not null.
* </p>
* @param condition search criteria string.
* @return converted search criteria string.
*/
public String toStartingWithCondition(String condition) {
if (condition == null) {
return null;
}
return toLikeCondition(condition, new StringBuilder()).append("%")
.toString();
}
/**
* Convert a search criteria string to the escaped string of LIKE condition ,and append "%" keyword to the backward.
* <p>
* Conversion rules see JavaDoc of {@link #toLikeCondition(String, StringBuilder)}.
* </p>
* <p>
* return null when condition is <code>null</code>.<br>
* Returned value is appended "%" keyword to the backward, if not null.
* </p>
* @param condition search criteria string.
* @return converted search criteria string.
*/
public String toEndingWithCondition(String condition) {
if (condition == null) {
return null;
}
return toLikeCondition(condition, new StringBuilder("%")).toString();
}
/**
* Convert a search criteria string to the escaped string of LIKE condition ,and append "%" keyword to the back and forth.
* <p>
* Conversion rules see JavaDoc of {@link #toLikeCondition(String, StringBuilder)}.
* </p>
* <p>
* return null when condition is <code>null</code>.<br>
* Returned value is appended "%" keyword to the back and forth, if not null.
* </p>
* @param condition search criteria string.
* @return converted search criteria string.
*/
public String toContainingCondition(String condition) {
if (condition == null) {
return null;
}
return toLikeCondition(condition, new StringBuilder("%")).append("%")
.toString();
}
}