package org.n3r.eql.codedesc;
import lombok.SneakyThrows;
import org.n3r.eql.config.EqlConfigDecorator;
import org.n3r.eql.ex.EqlExecuteException;
import org.n3r.eql.map.EqlRun;
import org.n3r.eql.util.O;
import org.n3r.eql.util.Rs;
import org.n3r.eql.util.S;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CodeDescResultSetHandler implements InvocationHandler {
final List<CodeDesc> codeDescs;
final EqlConfigDecorator eqlConfig;
final String sqlClassPath;
final EqlRun currEqlRun;
final ResultSet resultSet;
final Map<String, Integer> codeIndex = new HashMap<String, Integer>();
private String tagSqlId;
public CodeDescResultSetHandler(EqlRun currEqlRun, EqlConfigDecorator eqlConfig, String sqlClassPath, ResultSet resultSet, List<CodeDesc> codeDescs, String tagSqlId) {
this.currEqlRun = currEqlRun;
this.eqlConfig = eqlConfig;
this.sqlClassPath = sqlClassPath;
this.resultSet = resultSet;
this.codeDescs = codeDescs;
this.tagSqlId = tagSqlId;
createCodeIndex();
}
private void createCodeIndex() {
for (CodeDesc codeDesc : codeDescs) {
codeIndex.put(codeDesc.getColumnName(), findCodeIndex(codeDesc.getColumnName()));
}
}
@SneakyThrows
private int findCodeIndex(String columnName) {
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; ++i) { // first find the desc column index
String lookupColumnName = Rs.lookupColumnName(metaData, i);
if (S.equalsIgnoreCase(columnName, lookupColumnName)) {
for (int j = i - 1; j >= 1; --j) {
// then back find the first column(not desc column) to view as code
String jColumnName = Rs.lookupColumnName(metaData, j);
if (!codeDescsContainsColumnName(jColumnName)) return j;
}
}
}
throw new EqlExecuteException("unable to find code column");
}
private boolean codeDescsContainsColumnName(String jColumnName) {
for (CodeDesc codeDesc : codeDescs) {
if (codeDesc.getColumnName().equalsIgnoreCase(jColumnName))
return true;
}
return false;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(resultSet, args);
if (!O.in(method.getName(), "getString", "getObject")) return result;
String columnName = parseArgName(args[0]);
if (columnName == null) return result;
CodeDesc codeDesc = findCodeDesc(columnName);
if (codeDesc == null) return result;
String code = resultSet.getString(codeIndex.get(codeDesc.getColumnName()));
return CodeDescs.map(currEqlRun, eqlConfig, sqlClassPath, codeDesc, code, tagSqlId);
}
private CodeDesc findCodeDesc(String columnName) {
for (CodeDesc codeDesc : codeDescs) {
if (S.equalsIgnoreCase(columnName, codeDesc.getColumnName())) {
return codeDesc;
}
}
return null;
}
private String parseArgName(Object arg) throws SQLException {
if (arg instanceof String) return (String) arg;
if (arg instanceof Integer) {
Integer index = (Integer) arg;
return Rs.lookupColumnName(resultSet.getMetaData(), index);
}
return null;
}
public ResultSet createProxy() {
return (ResultSet) Proxy.newProxyInstance(getClass().getClassLoader(),
new Class<?>[]{ResultSet.class}, this);
}
}