package com.tesora.dve.sql.parser;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class ParserInvoker {
private ParserOptions opts;
public ParserInvoker(ParserOptions opts) {
this.opts = opts;
}
protected ParserOptions getOptions() {
return this.opts;
}
public abstract String parseOneLine(LineInfo info, String line) throws Throwable;
protected String parseOneLineInternal(LineInfo info, String line) throws Throwable {
// TestParser.echo("In@" + info + ": '" + line + "'");
String out = parseOneLine(info, line);
// TestParser.echo("Out: '" + out + "'");
return out;
}
public static class LineInfoOption<T> {
protected T target;
protected String name;
public LineInfoOption(String n, T v) {
target = v;
name = n;
}
public String getName() {
return name;
}
public T getValue() {
return target;
}
public void setValue(T v) {
target = v;
}
}
public static class LineInfo {
protected Map<String, LineInfoOption<?>> values;
protected static final String LINE_NUMBER_KEY = "line";
protected static final String CONN_ID_KEY = "conn";
private ParserOptions options;
public LineInfo(List<LineInfoOption<?>> opts) {
values = new HashMap<String, LineInfoOption<?>>();
for(LineInfoOption<?> lio : opts)
values.put(lio.getName(),lio);
options = null;
}
public LineInfo(long lineno, ParserOptions opts, int connID) {
values = new HashMap<String, LineInfoOption<?>>();
addLongOption(LINE_NUMBER_KEY, lineno);
addIntOption(CONN_ID_KEY,connID);
options = opts;
}
public LineInfo(LineInfo e, ParserOptions newopt) {
values = new HashMap<String, LineInfoOption<?>>(e.values);
options = newopt;
}
public void addIntOption(String name, int v) {
values.put(name, new LineInfoOption<Integer>(name, v));
}
public Integer getIntOption(String name) {
@SuppressWarnings("unchecked")
LineInfoOption<Integer> any = (LineInfoOption<Integer>) values.get(name);
if (any == null) return null;
return any.getValue();
}
public void addStringOption(String name, String v) {
values.put(name, new LineInfoOption<String>(name,v));
}
public String getStringOption(String name) {
@SuppressWarnings("unchecked")
LineInfoOption<String> any = (LineInfoOption<String>) values.get(name);
if (any == null) return null;
return any.getValue();
}
public void addLongOption(String name, long v) {
values.put(name, new LineInfoOption<Long>(name, v));
}
public LineInfoOption<?> getOption(String name) {
return values.get(name);
}
public void setOption(LineInfoOption<?> opt) {
values.put(opt.getName(), opt);
}
public long getLineNumber() {
@SuppressWarnings("unchecked")
LineInfoOption<Long> opt = (LineInfoOption<Long>) getOption(LINE_NUMBER_KEY);
if (opt == null) return -1;
return opt.getValue();
}
public void setLineNumber(long v) {
@SuppressWarnings("unchecked")
LineInfoOption<Long> opt = (LineInfoOption<Long>) getOption(LINE_NUMBER_KEY);
opt.setValue(new Long(v));
}
public int getConnectionID() {
@SuppressWarnings("unchecked")
LineInfoOption<Integer> opt = (LineInfoOption<Integer>) getOption(CONN_ID_KEY);
if (opt == null) return -1;
return opt.getValue();
}
public ParserOptions getOptions() {
return options;
}
public LineInfo setNoisy(ParserOptions opts) {
return new LineInfo(this, opts);
}
@Override
public String toString() {
long lineno = getLineNumber();
int connID = getConnectionID();
return "stmt: " + lineno + (connID == -1 ? "" : " on conn " + connID);
}
}
public enum LineTag {
SELECT,
SELECT_ORDERED,
DISCONNECT,
CONNECT,
UPDATE,
DDL,
SESSION;
public static LineTag fromFile(String in) {
for(LineTag lt : LineTag.values()) {
if (lt.name().equals(in)) {
return lt;
}
}
throw new RuntimeException("No such line tag: '" + in + "'");
}
}
public static class TaggedLineInfo extends LineInfo {
protected static final String TAG_KEY = "tag";
protected static final String UPDATE_KEY = "update";
protected static final String TABLE_KEY = "table";
public TaggedLineInfo(List<LineInfoOption<?>> vals) {
super(vals);
}
public TaggedLineInfo(long lineno, ParserOptions opts, int connID, LineTag tag) {
this(lineno, opts, connID, tag, null);
}
@SuppressWarnings("rawtypes")
public TaggedLineInfo(long lineno, ParserOptions opts, int connID, LineTag tag, LineInfoOption[] extras) {
super(lineno, opts, connID);
setOption(new LineInfoOption<LineTag>(TAG_KEY, tag));
}
public TaggedLineInfo(TaggedLineInfo tli, ParserOptions newOpts) {
super(tli, newOpts);
}
@SuppressWarnings("unchecked")
public LineTag getTag() {
return ((LineInfoOption<LineTag>)getOption(TAG_KEY)).getValue();
}
@SuppressWarnings("unchecked")
public String getTable() {
LineInfoOption<String> lio = (LineInfoOption<String>) getOption(TABLE_KEY);
if (lio == null) return null;
return lio.getValue();
}
@Override
public LineInfo setNoisy(ParserOptions opts) {
return new TaggedLineInfo(this, opts);
}
@Override
public String toString() {
return super.toString() + " tag: " + getTag();
}
public String toFileFormat() {
StringBuffer buf = new StringBuffer();
buf.append("#pe");
for(LineInfoOption<?> lio : values.values()) {
String key = lio.getName();
Object value = lio.getValue();
buf.append(" ").append(key).append("=").append(value);
}
return buf.toString();
}
public static TaggedLineInfo fromFileFormat(String in) {
String[] parts = in.split(" ");
if ("#pe".equals(parts[0])) {
ArrayList<LineInfoOption<?>> opts = new ArrayList<LineInfoOption<?>>();
for(int i = 1; i < parts.length; i++) {
String[] kv = parts[i].split("=");
String key = kv[0];
String value = kv[1];
if (TAG_KEY.equals(key)) {
opts.add(new LineInfoOption<LineTag>(TAG_KEY,LineTag.fromFile(value)));
} else if (LINE_NUMBER_KEY.equals(key)) {
opts.add(new LineInfoOption<Long>(LINE_NUMBER_KEY,Long.parseLong(value)));
} else if (CONN_ID_KEY.equals(key)) {
opts.add(new LineInfoOption<Integer>(CONN_ID_KEY,Integer.parseInt(value)));
} else {
opts.add(new LineInfoOption<String>(key,value));
}
}
return new TaggedLineInfo(opts);
} else {
throw new RuntimeException("Unknown token '" + in + "'");
}
}
}
}