package org.araqne.logdb.query.parser;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.araqne.logdb.AbstractQueryCommandParser;
import org.araqne.logdb.LookupHandlerRegistry;
import org.araqne.logdb.QueryCommand;
import org.araqne.logdb.QueryContext;
import org.araqne.logdb.QueryErrorMessage;
import org.araqne.logdb.QueryParseException;
import org.araqne.logdb.Strings;
import org.araqne.logdb.query.command.Lookup;
public class LookupParser extends AbstractQueryCommandParser {
private LookupHandlerRegistry registry;
public LookupParser(LookupHandlerRegistry registry) {
this.registry = registry;
setDescriptions("Lookup field by key.", "매핑 테이블을 조회하여 특정한 필드 값을 다른 값으로 변환합니다.");
}
@Override
public String getCommandName() {
return "lookup";
}
@Override
public Map<String, QueryErrorMessage> getErrorMessages() {
Map<String, QueryErrorMessage> m = new HashMap<String, QueryErrorMessage>();
m.put("20700", new QueryErrorMessage("output-token-not-found", "lookup 명령에서 output 구문이 누락되었습니다."));
m.put("20701", new QueryErrorMessage("invalid-lookup-name", "lookup 명령에서 [table]은 유효하지 않는 매핑 테이블입니다."));
m.put("20702", new QueryErrorMessage("invalid-lookup-field", "lookup 필드 문법이 유효하지 않습니다. `필드 as 별칭` 문법을 사용하십시오."));
m.put("20703", new QueryErrorMessage("as-token-not-found", "lookup 명령의 [as] 자리에 as가 와야 합니다."));
return m;
}
@Override
public QueryCommand parse(QueryContext context, String commandString) {
int last = getCommandName().length();
int p = QueryTokenizer.skipSpaces(commandString, last);
p = commandString.indexOf(' ', p);
if (p < 0)
throw new QueryParseException("20701", -1, -1, params("table", "빈 값"));
String handlerName = commandString.substring(last, p).trim();
if (registry != null && registry.getLookupHandler(handlerName) == null)
throw new QueryParseException("20701", last + 1, p - 1, params("table", handlerName));
last = p;
p = commandString.toLowerCase().indexOf(" output ", last);
if (p < 0)
throw new QueryParseException("20700", getCommandName().length() + 1, commandString.length() - 1, null);
String inputToken = commandString.substring(last, p);
List<String> outputTokens = Strings.tokenize(commandString.substring(p + " output ".length()), ",");
LookupField src = parseLookupField(inputToken, last, p);
Map<String, String> outputFields = new HashMap<String, String>();
for (String outputToken : outputTokens) {
LookupField f = parseLookupField(outputToken, p + " output ".length(), commandString.length() - 1);
outputFields.put(f.first, f.second);
}
return new Lookup(registry, handlerName, src.first, src.second, outputFields);
}
private LookupField parseLookupField(String s, int begin, int end) {
LookupField field = new LookupField();
List<String> tokens = Strings.tokenize(s, " ");
if (tokens.size() == 1) {
field.first = tokens.get(0);
field.second = field.first;
return field;
}
if (tokens.size() != 3)
throw new QueryParseException("20702", begin, end, null);
if (!tokens.get(1).equalsIgnoreCase("as"))
throw new QueryParseException("20703", begin, end, params("as", tokens.get(1)));
field.first = tokens.get(0);
field.second = tokens.get(2);
return field;
}
private class LookupField {
private String first;
private String second;
}
}