package org.atomhopper.jdbc.query;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public final class CategoryStringGenerator {
private static final char INCLUSIVE_OPERATOR = '+', ESCAPE_OPERATOR = '\\';
private static final char[] OPERATORS = {INCLUSIVE_OPERATOR, ESCAPE_OPERATOR};
private CategoryStringGenerator() {
throw new AssertionError();
}
/**
* Takes a search string, prefix map & prefix character & returns an array of strings which are arguments to the
* corresponding generated SQL statement.
*
* See SearchToSqlConverter for more details.
*
* @param searchString
* @param mapPrefix
* @param prefixSplit
*
* @return
*/
public static List<String> getPostgresCategoryString(String searchString, Map<String, String> mapPrefix, String prefixSplit ) {
List<String> finalList = new ArrayList<String>();
if (searchString == null || !(searchString.trim().length() > 0)) {
finalList.add( "{}" );
return finalList;
}
List<String> categories = parse(searchString.trim().toLowerCase());
List<String> catHolder = new ArrayList<String>();
// find if any categories are prefixed, if so, split them out.
for( String cat : categories ) {
if (cat.matches( SearchToSqlConverter.BAD_SEARCH_REGEX ) ) {
throw new IllegalArgumentException( SearchToSqlConverter.BAD_CHAR_MSG );
}
if (prefixSplit != null ) {
int index = cat.indexOf( prefixSplit );
if ( index != -1 ) {
String prefix = cat.substring( 0, index );
String value = cat.substring( index + prefixSplit.length() );
if ( mapPrefix.containsKey( prefix ) ) {
addToFinalList( finalList, catHolder );
finalList.add( value );
}
else {
catHolder.add( cat );
}
}
else {
catHolder.add( cat );
}
}
else {
catHolder.add( cat );
}
}
addToFinalList( finalList, catHolder );
return finalList;
}
private static void addToFinalList( List<String> finalList, List<String> catHolder ) {
if ( !catHolder.isEmpty() ) {
String psArray = PostgreSQLTextArray.stringArrayToPostgreSQLTextArray( catHolder.toArray( new String[ catHolder
.size() ] ) );
finalList.add( psArray );
catHolder.clear();
}
}
private static List<String> parse(String searchString) {
List<String> categories = new ArrayList<String>();
for (int charIndex = 0; charIndex < searchString.length(); charIndex++) {
final char nextOperator = searchString.charAt(charIndex);
final StringBuilder searchTermBuilder = new StringBuilder();
charIndex = readTerm(searchString, searchTermBuilder, charIndex + 1);
switch (nextOperator) {
case INCLUSIVE_OPERATOR:
if( searchTermBuilder.toString().isEmpty() ) {
throw new IllegalArgumentException( "Invalid Search Parameter: Parameter cannot be empty string." );
}
categories.add(searchTermBuilder.toString());
break;
default:
break;
}
}
return categories;
}
private static int readTerm(String searchString, StringBuilder builder, int currentCharIndex) {
int charIndex = currentCharIndex;
boolean isEscaped = false;
while( charIndex < searchString.length() ) {
final char nextChar = searchString.charAt(charIndex);
if (isEscaped || !isOperator(nextChar)) {
builder.append( nextChar );
isEscaped = false;
} else {
if (nextChar == ESCAPE_OPERATOR) {
isEscaped = true;
} else {
return charIndex - 1;
}
}
charIndex++;
}
return charIndex;
}
private static boolean isOperator(char character) {
for (char operator : OPERATORS) {
if (operator == character) {
return true;
}
}
return false;
}
}