package com.netfever.dbmanager.queries;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.netfever.dbmanager.DbManager;
import com.netfever.dbmanager.object.DefineStatement;
import com.netfever.dbmanager.object.Query;
import com.netfever.dbmanager.object.Statement;
import com.netfever.dbmanager.object.StatementParameter;
import com.netfever.dbmanager.object.AbstractParameter.StatementParameterType;
public class QueryBuilder {
private Connection connection = null;
private DbManager manager = null;
public QueryBuilder(Connection connection, DbManager manager) {
super();
this.connection = connection;
this.manager = manager;
}
private String expandKeyword(String keyword) {
String value;
keyword = keyword.substring(2, keyword.length() - 1);
value = this.manager.getConstants().get(keyword);
if (value == null)
return "";
return value;
}
private String expandString(String original) {
Pattern pattern;
Matcher matcher;
boolean found;
String keyword;
String expandedKeyword;
String res;
res = original;
pattern = Pattern.compile("\\$\\{.*?\\}");
found = true;
while (found) {
matcher = pattern.matcher(original);
found = false;
while (matcher.find()) {
found = true;
keyword = original.substring(matcher.start(), matcher.end());
expandedKeyword = expandKeyword(keyword);
res = res.replace(keyword, expandedKeyword);
}
original = res;
}
return res;
}
public RunnableQuery getQueryStatement(Query query, Statement statement)
throws QueryBuilderException {
String s;
StatementParameterType paramType;
int i;
DefineStatement defineStatement;
Map<String, StatementParameter> statementParameters;
ArrayList<Object> parameters;
try {
switch (statement.getTypeAsEnum()) {
case SQL:
s = expandString(statement.getSql());
return new RunnableQuery(this.connection, query.getName(),
statement.getName(), s, null);
case STATEMENT:
defineStatement = this.manager.getDefineStatements().get(
statement.getDefine());
if (defineStatement == null)
throw new QueryBuilderException(
"Could not find defined-statement '"
+ statement.getDefine() + "'");
i = 1;
statementParameters = defineStatement.getStatementParameters();
parameters = new ArrayList<Object>();
while (true) {
s = Integer.toString(i++);
if (statementParameters.containsKey(s))
paramType = statementParameters.get(s).getTypeAsEnum();
else
break;
if (statement.getVariables().containsKey(s))
s = expandString(statement.getVariables().get(s));
else
break;
switch (paramType) {
case STRING:
parameters.add(s);
break;
case INT:
parameters.add(new Integer(s));
break;
}
}
s = expandString(defineStatement.getSql());
return new RunnableQuery(this.connection, query.getName(),
statement.getName(), s, parameters.toArray());
default:
return null;
}
} catch (QueryBuilderException e) {
throw (QueryBuilderException) e;
} catch (Exception e) {
throw new QueryBuilderException(e.getMessage(), e);
}
}
public RunnableQuery getQueryStatement(String queryName,
String statementName) throws QueryBuilderException {
Query query;
Statement statement;
if (queryName == null)
throw new QueryBuilderException(
"queryName parameter cannot be null.");
if (statementName == null)
throw new QueryBuilderException(
"queryName parameter cannot be null.");
query = this.manager.getQueries().get(queryName);
if (query == null)
throw new QueryBuilderException("Query '" + queryName
+ "' not found.");
statement = query.getStatements().get(statementName);
if (statement == null)
throw new QueryBuilderException("Statement '" + statementName
+ "' not found.");
return getQueryStatement(query, statement);
}
public RunnableQuery[] getAllQueryStatement(String statementName) {
ArrayList<RunnableQuery> res;
Map<String, Query> queries;
Iterator<String> iterator;
RunnableQuery runnableQuery;
Query query;
Statement statement;
res = new ArrayList<RunnableQuery>();
queries = this.manager.getQueries();
iterator = queries.keySet().iterator();
while (iterator.hasNext()) {
query = queries.get(iterator.next());
statement = query.getStatements().get(statementName);
try {
if (statement != null) {
runnableQuery = getQueryStatement(query, statement);
res.add(runnableQuery);
}
} catch (QueryBuilderException e) {
runnableQuery = new RunnableQuery(e, query.getName(),
statement.getName());
res.add(runnableQuery);
}
}
return res.toArray(new RunnableQuery[0]);
}
public void close() {
try {
this.connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}