/*
* blanco Framework
* Copyright (C) 2004-2006 WATANABE Yoshinori
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*/
package blanco.commons.sql.format;
List<BlancoSqlToken> list = fParser.parse(argSql);
list = format(list);
// 変換結果を文字列に戻す。
String after = "";
for (int index = 0; index < list.size(); index++) {
BlancoSqlToken token = list.get(index);
after += token.getString();
}
if (isSqlEndsWithNewLine) {
after += "\n";
}
return after;
} catch (Exception ex) {
final BlancoSqlFormatterException sqlException = new BlancoSqlFormatterException(
ex.toString());
sqlException.initCause(ex);
throw sqlException;
}
}
// インデントを整える。
int indent = 0;
// 丸カッコのインデント位置を覚える。
final Stack<Integer> bracketIndent = new Stack<Integer>();
BlancoSqlToken prev = new BlancoSqlToken(BlancoSqlTokenConstants.SPACE,
" ");
boolean encounterBetween = false;
for (int index = 0; index < argList.size(); index++) {
token = argList.get(index);
if (token.getType() == BlancoSqlTokenConstants.SYMBOL) {
// indentを1つ増やし、'('のあとで改行。
if (token.getString().equals("(")) {
functionBracket
.push(fRule.isFunction(prev.getString()) ? Boolean.TRUE
: Boolean.FALSE);
bracketIndent.push(new Integer(indent));
indent++;
index += insertReturnAndIndent(argList, index + 1, indent);
}
// indentを1つ増やし、')'の前と後ろで改行。
else if (token.getString().equals(")")) {
indent = bracketIndent.pop().intValue();
index += insertReturnAndIndent(argList, index, indent);
functionBracket.pop();
}
// ','の前で改行
else if (token.getString().equals(",")) {
index += insertReturnAndIndent(argList, index, indent);
} else if (token.getString().equals(";")) {
// 2005.07.26 Tosiki Iga とりあえずセミコロンでSQL文がつぶれないように改良
indent = 0;
index += insertReturnAndIndent(argList, index, indent);
}
} else if (token.getType() == BlancoSqlTokenConstants.KEYWORD) {
// indentを2つ増やし、キーワードの後ろで改行
if (token.getString().equalsIgnoreCase("DELETE")
|| token.getString().equalsIgnoreCase("SELECT")
|| token.getString().equalsIgnoreCase("UPDATE")) {
indent += 2;
index += insertReturnAndIndent(argList, index + 1, indent);
}
// indentを1つ増やし、キーワードの後ろで改行
if (token.getString().equalsIgnoreCase("INSERT")
|| token.getString().equalsIgnoreCase("INTO")
|| token.getString().equalsIgnoreCase("CREATE")
|| token.getString().equalsIgnoreCase("DROP")
|| token.getString().equalsIgnoreCase("TRUNCATE")
|| token.getString().equalsIgnoreCase("TABLE")
|| token.getString().equalsIgnoreCase("CASE")) {
indent++;
index += insertReturnAndIndent(argList, index + 1, indent);
}
// キーワードの前でindentを1つ減らして改行、キーワードの後ろでindentを戻して改行。
if (token.getString().equalsIgnoreCase("FROM")
|| token.getString().equalsIgnoreCase("WHERE")
|| token.getString().equalsIgnoreCase("SET")
|| token.getString().equalsIgnoreCase("ORDER BY")
|| token.getString().equalsIgnoreCase("GROUP BY")
|| token.getString().equalsIgnoreCase("HAVING")) {
index += insertReturnAndIndent(argList, index, indent - 1);
index += insertReturnAndIndent(argList, index + 1, indent);
}
// epinszteinic added start
// キーワードの前でindentを1つ減らして改行。
if (token.getString().equalsIgnoreCase("INNER JOIN")
|| token.getString().equalsIgnoreCase("LEFT JOIN")
|| token.getString().equalsIgnoreCase("RIGHT JOIN")
|| token.getString().equalsIgnoreCase("LEFT OUTER JOIN")
|| token.getString().equalsIgnoreCase("RIGHT OUTER JOIN")) {
index += insertReturnAndIndent(argList, index, indent - 1);
}
// epinszteinic added end
// キーワードの前でindentを1つ減らして改行、キーワードの後ろでindentを戻して改行。
if (token.getString().equalsIgnoreCase("VALUES")) {
indent--;
index += insertReturnAndIndent(argList, index, indent);
}
// キーワードの前でindentを1つ減らして改行
if (token.getString().equalsIgnoreCase("END")) {
indent--;
index += insertReturnAndIndent(argList, index, indent);
}
// キーワードの前で改行
if (token.getString().equalsIgnoreCase("OR")
|| token.getString().equalsIgnoreCase("THEN")
|| token.getString().equalsIgnoreCase("ELSE")) {
index += insertReturnAndIndent(argList, index, indent);
}
// キーワードの前で改行
// epinszteinic modified start
// if (token.getString().equalsIgnoreCase("ON")
// || token.getString().equalsIgnoreCase("USING")) {
// index += insertReturnAndIndent(argList, index, indent + 1);
// }
if (token.getString().equalsIgnoreCase("USING")) {
index += insertReturnAndIndent(argList, index, indent + 1);
}
if (token.getString().equalsIgnoreCase("ON")) {
index += insertReturnAndIndent(argList, index, indent);
}
// epinszteinic modified end
// キーワードの前で改行。indentを強制的に0にする。
if (token.getString().equalsIgnoreCase("UNION")
|| token.getString().equalsIgnoreCase("INTERSECT")
|| token.getString().equalsIgnoreCase("EXCEPT")) {
indent -= 2;
index += insertReturnAndIndent(argList, index, indent);
index += insertReturnAndIndent(argList, index + 1, indent);
}
if (token.getString().equalsIgnoreCase("BETWEEN")) {
encounterBetween = true;
}
if (token.getString().equalsIgnoreCase("AND")) {
// BETWEEN のあとのANDは改行しない。
if (!encounterBetween) {
index += insertReturnAndIndent(argList, index, indent);
}
encounterBetween = false;
}
} else if (token.getType() == BlancoSqlTokenConstants.COMMENT) {
if (token.getString().startsWith("/*")) {
// マルチラインコメントの後に改行を入れる。
index += insertReturnAndIndent(argList, index + 1, indent);
}
}
prev = token;
}
// 丸カッコで囲まれた (ひとつの項目)については特別扱いを行う。 @author tosiki iga
for (int index = argList.size() - 1; index >= 4; index--) {
if (index >= argList.size()) {
continue;
}
// テストディレクトリ内のファイルを一括で変換する。
final File[] files = new File("Test").listFiles();
for (int i = 0; i < files.length; i++) {
System.out.println("-- " + files[i]);
// ファイルのSQLを読み込む.
final BufferedReader reader = new BufferedReader(new FileReader(
files[i]));
String before = "";
while (reader.ready()) {
String line = reader.readLine();
if (line == null)
break;
before += line + "\n";
}
reader.close();