package com.redspr.redquerybuilder.sample;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class MetaServlet extends HttpServlet {
private final ResourceBundle bundle = PropertyResourceBundle.getBundle("meta");
class ForeignKey {
private String name;
private String label;
private String reverseLabel;
private String fkTableName;
private final List<String> pkColumnNames = new ArrayList<String>();
private final List<String> fkColumnNames = new ArrayList<String>();
JSONObject toJson() throws JSONException {
JSONObject fk = new JSONObject();
fk.put("name", name);
fk.put("label", label);
fk.put("reverseLabel", reverseLabel);
fk.put("referencedTableName", fkTableName);
fk.put("referencedKeyNames", fkColumnNames);
fk.put("foreignKeyNames", pkColumnNames);
return fk;
}
}
private String getLocal(String key) {
String x = bundle.getString(key);
if (x == null) {
return key;
}
return x;
}
private JSONObject op(String name, String label) throws JSONException {
return op(name, label, "ONE");
}
private JSONObject op(String name, String label, String card)
throws JSONException {
JSONObject op = new JSONObject();
op.put("name", name);
op.put("label", label);
op.put("cardinality", card);
return op;
}
private JSONArray stringOps() throws JSONException {
JSONArray ops = new JSONArray();
ops.put(op("=", "is"));
ops.put(op("<>", "is not"));
ops.put(op("LIKE", "like"));
ops.put(op("<", "less than"));
ops.put(op(">", "greater than"));
return ops;
}
private JSONArray numberOps() throws JSONException {
JSONArray ops = new JSONArray();
ops.put(op("=", "is"));
ops.put(op("<>", "is not"));
ops.put(op("<", "less than"));
ops.put(op(">", "greater than"));
return ops;
}
private JSONArray booleanOps() throws JSONException {
JSONArray ops = new JSONArray();
ops.put(op("=", "is"));
return ops;
}
private JSONObject type(String name, String editor, JSONArray ops)
throws JSONException {
JSONObject obj = new JSONObject();
obj.put("name", name);
obj.put("editor", editor);
obj.put("operators", ops);
return obj;
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
try {
// TODO 02 fk names - mandatory for i18n purposes?
// TODO 01 config for this
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:db1",
"sa", "");
DatabaseMetaData dmd = conn.getMetaData();
JSONObject root = new JSONObject();
{
JSONArray types = new JSONArray();
root.put("types", types);
types.put(type("CHAR", "SUGGEST", stringOps()));
types.put(type("NUMERIC", "NUMBER", numberOps()));
types.put(type("INTEGER", "NUMBER", numberOps()));
types.put(type("DECIMAL", "NUMBER", numberOps()));
types.put(type("SMALLINT", "NUMBER", numberOps()));
types.put(type("BOOLEAN", "SELECT", booleanOps()));
}
{
JSONArray tables = new JSONArray();
root.put("tables", tables);
ResultSet rs = dmd.getTables(null, null, null,
new String[] {"TABLE" });
while (rs.next()) {
JSONObject table = new JSONObject();
tables.put(table);
String tableName = rs.getString("TABLE_NAME");
table.put("name", tableName);
JSONArray columns = new JSONArray();
table.put("columns", columns);
ResultSet rsCols = dmd.getColumns(null, null, tableName,
null);
while (rsCols.next()) {
JSONObject meta = new JSONObject();
columns.put(meta);
String columnName = rsCols.getString("COLUMN_NAME");
meta.put("label", columnName);
meta.put("name", columnName);
meta.put("size", rsCols.getInt("COLUMN_SIZE"));
String type = rsCols.getString("TYPE_NAME");
if ("ISOFFICIAL".equals(columnName)) {
type = "BOOLEAN";
}
meta.put("type", type);
}
JSONArray fks = new JSONArray();
table.put("fks", fks);
{
ResultSet rs2 = dmd.getExportedKeys(null, null,
tableName);
ForeignKey fk = null;
List<ForeignKey> fksx = new ArrayList<ForeignKey>();
while (rs2.next()) {
int keySeq = rs2.getInt("KEY_SEQ");
if (keySeq == 1) {
fk = new ForeignKey();
String name = rs2.getString("FK_NAME");
fk.name = name;
fksx.add(fk);
String key = "fk." + name;
fk.label = getLocal(key);
fk.reverseLabel = getLocal(key + ".reverse");
fk.fkTableName = rs2.getString("FKTABLE_NAME");
}
fk.fkColumnNames.add(rs2
.getString("FKCOLUMN_NAME"));
fk.pkColumnNames.add(rs2
.getString("PKCOLUMN_NAME"));
}
for (ForeignKey foo2 : fksx) {
fks.put(foo2.toJson());
}
}
}
}
res.setContentType("application/json");
root.write(res.getWriter());
} catch (SQLException ex) {
throw new ServletException(ex);
} catch (JSONException ex) {
throw new ServletException(ex);
} catch (ClassNotFoundException ex) {
throw new ServletException(ex);
}
}
}