/*******************************************************************************
* Copyright (c) 2007 - 2010 GreenDeltaTC. All rights reserved. This program and
* the accompanying materials are made available under the terms of the Mozilla
* Public License v1.1 which accompanies this distribution, and is available at
* http://www.openlca.org/uploads/media/MPL-1.1.html
*
* Contributors: GreenDeltaTC - initial API and implementation
* www.greendeltatc.com tel.: +49 30 4849 6030 mail: gdtc@greendeltatc.com
******************************************************************************/
package org.openlca.core.database.internal;
import java.io.BufferedReader;
import java.io.Reader;
/**
* A parser for SQL scripts.
*/
class ScriptParser {
private final String COMMENT_PREFIX = "--";
private final char DELIMITER = ';';
private ScriptHandler handler;
private StringBuilder statement;
private StringBuilder escaped = null;
private char currentEscaper = ' ';
public ScriptParser(ScriptHandler handler) {
this.handler = handler;
}
/**
* Parse the script from the given reader. The reader is buffered and closed
* within this function.
*/
public void parse(Reader reader) throws Exception {
BufferedReader bufferedReader = new BufferedReader(reader);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
processLine(line, line.trim());
}
}
private void processLine(String line, String trimmedLine) throws Exception {
if (isStatementPart(trimmedLine)) {
processStatementPart(line, trimmedLine);
}
}
private boolean isStatementPart(String trimmedLine) {
return escaped != null || !trimmedLine.isEmpty()
&& !trimmedLine.startsWith(COMMENT_PREFIX);
}
private void processStatementPart(String line, String trimmedLine)
throws Exception {
if (escaped != null)
escaped.append('\n');
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (escaped != null) {
if (c == '\\') {
if (peekEquals(line, i, currentEscaper)) {
escaped.append("\\");
escaped.append(currentEscaper);
i++;
continue;
}
if (peekEquals(line, i, '\\')) {
escaped.append("\\\\");
i++;
continue;
}
} else if (c == currentEscaper) {
escaped.append(currentEscaper);
addStatementPart(escaped.toString());
escaped = null;
continue;
}
escaped.append(c);
} else {
if (c == '\\') {
if (peekEquals(line, i, '\'')) {
addStatementPart("\\'");
i++;
continue;
}
if (peekEquals(line, i, '\"')) {
addStatementPart("\\\"");
i++;
continue;
}
if (peekEquals(line, i, '\\')) {
addStatementPart("\\\\");
i++;
continue;
}
} else if (c == '\'' || c == '"') {
escaped = new StringBuilder();
escaped.append(c);
currentEscaper = c;
continue;
} else if (c == DELIMITER) {
commitStatement();
continue;
}
addStatementPart(c);
}
}
}
private boolean peekEquals(String toPeekAt, int pos, char c) {
if (toPeekAt.length() > pos + 1) {
if (toPeekAt.charAt(pos + 1) == c) {
return true;
}
}
return false;
}
private void addStatementPart(char c) {
if (statement == null) {
statement = new StringBuilder();
}
statement.append(c);
}
private void addStatementPart(String line) {
if (statement == null) {
statement = new StringBuilder();
}
statement.append(line);
}
private void commitStatement() throws Exception {
String stmt = statement.toString().trim();
statement = null;
if (!stmt.isEmpty())
handler.statement(stmt);
}
}