package com.automattic.simplenote.utils;
public class SearchTokenizer {
static public final String EMPTY = "";
static public final char LITERAL = '/';
static public final char SPACE = ' ';
static public final char DOUBLE_QUOTE = '"';
static public final char SINGLE_QUOTE = '\'';
static public final char GLOB = '*';
static public final char COLON = ':';
static public final char ESCAPE = '\\';
private String mRawQuery;
public SearchTokenizer(String query) {
mRawQuery = query;
}
private String parseQuery() {
if (mRawQuery == null || mRawQuery.equals(EMPTY)) {
return EMPTY;
}
StringBuilder query = new StringBuilder(mRawQuery.length());
// iterate through each character
int length = mRawQuery.length();
// if we have an open " or not
boolean inStrictTerm = false;
// if we've detected a search term
boolean inTerm = false;
// if we're doing a literal query
boolean isLiteral = false;
// if the current char is a single or double quote
boolean isQuoteChar;
// if the previous char was an eschape char
boolean isEscaped = false;
// the current character
char current = '\0', last, quoteChar = '\0';
for (int position = 0; position < length; position++) {
last = current;
current = mRawQuery.charAt(position);
// if the last character was an \ and we weren't already escaped
isEscaped = last == ESCAPE && !isEscaped;
// if it's a ' or " and it isn't be escaped
isQuoteChar = !isEscaped && (current == SINGLE_QUOTE || current == DOUBLE_QUOTE);
// if query starts with / we're just going to give the complete query
if (position == 0 && current == LITERAL && length > 1) {
isLiteral = true;
continue;
}
// we're inside a quoted section and have found another quote, append and loop
if (inStrictTerm && current == quoteChar) {
query.append(current);
inStrictTerm = false;
inTerm = false;
continue;
}
// we're in a strict term and it's not a ", so append and continue
if (inStrictTerm) {
query.append(current);
continue;
}
// we've found a matching end quote
if (isQuoteChar) {
quoteChar = current;
// we were already in a term so end it with a glob
if (inTerm && !isLiteral) query.append(new char[]{GLOB, SPACE});
// start the strict term
query.append(current);
inStrictTerm = true;
inTerm = true;
continue;
}
if (current == COLON && inTerm) {
inTerm = false;
query.append(current);
continue;
}
if (current == SPACE) {
if (inTerm && !isLiteral) query.append(GLOB);
query.append(current);
inTerm = false;
continue;
}
inTerm = true;
query.append(current);
}
// close the strict term
if (inStrictTerm) query.append(quoteChar);
if (inTerm && !inStrictTerm && !isLiteral) query.append(GLOB);
return query.toString();
}
@Override
public String toString() {
return parseQuery();
}
}