package org.n3r.eql.codedesc;
import lombok.SneakyThrows;
import lombok.val;
import org.n3r.eql.config.EqlConfigDecorator;
import org.n3r.eql.ex.EqlConfigException;
import org.n3r.eql.map.EqlRun;
import org.n3r.eql.parser.EqlBlock;
import org.n3r.eql.spec.Spec;
import org.n3r.eql.spec.SpecParser;
import org.n3r.eql.util.Rs;
import org.n3r.eql.util.S;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
public class CodeDescs {
public static ResultSet codeDescWrap(
EqlRun currEqlRun, EqlBlock eqlBlock,
EqlConfigDecorator eqlConfig,
String sqlClassPath, ResultSet rs, String tagSqlId) {
List<CodeDesc> descs = eqlBlock.getCodeDescs();
if (descs == null) return rs;
if (!existsReturnDescColumns(descs, rs)) return rs;
return new CodeDescResultSetHandler(currEqlRun, eqlConfig,
sqlClassPath, rs, descs, tagSqlId).createProxy();
}
@SneakyThrows
private static boolean existsReturnDescColumns(List<CodeDesc> descs, ResultSet rs) {
ResultSetMetaData metaData = rs.getMetaData();
for (int i = 0, ii = metaData.getColumnCount(); i < ii; ++i) {
String columnName = Rs.lookupColumnName(metaData, i + 1);
for (CodeDesc codeDesc : descs) {
if (codeDesc.getColumnName().equals(columnName)) return true;
}
}
return false;
}
public static List<CodeDesc> parseOption(EqlBlock eqlBlock, String desc) {
if (S.isBlank(desc)) return null;
List<CodeDesc> codeDescs = new ArrayList<CodeDesc>();
DescOptionValueParser descOptionValueParser = new DescOptionValueParser();
int pos = 0;
int size = desc.length();
while (pos < size) {
val oo = descOptionValueParser.parseValueOption(desc.substring(pos));
if (oo == null) break;
pos += oo.getOffset();
CodeDesc codeDesc = parseCodeDesc(eqlBlock, oo.getOptionValue());
codeDescs.add(codeDesc);
}
return codeDescs.size() == 0 ? null : codeDescs;
}
private static CodeDesc parseCodeDesc(EqlBlock eqlBlock, String descPart) {
int atPos = descPart.indexOf('@');
check(eqlBlock, atPos > 0);
String columnName = descPart.substring(0, atPos);
String reference = descPart.substring(atPos);
Spec spec = SpecParser.parseSpec(reference);
return new CodeDesc(columnName, spec);
}
private static void check(EqlBlock eqlBlock, boolean expr) {
if (expr) return;
throw new EqlConfigException(eqlBlock.getUniqueSqlIdStr()
+ "'s desc format is invalid");
}
public static String map(final EqlRun currEqlRun,
final EqlConfigDecorator eqlConfig,
final String sqlClassPath,
final CodeDesc codeDesc,
final String code,
String tagSqlId) {
String desc = CodeDescSettings.map(codeDesc, code);
if (desc != null) return desc;
final EqlBlock eqlBlock = findEqlBlock(eqlConfig, sqlClassPath, codeDesc);
if (eqlBlock == null) return null;
val mapper = CodeDescCache.getCachedMapper(sqlClassPath, codeDesc,
currEqlRun, eqlConfig, eqlBlock, tagSqlId);
return mapper == null ? null : mapper.map(code);
}
private static EqlBlock findEqlBlock(EqlConfigDecorator eqlConfig,
String sqlClassPath,
CodeDesc codeDesc) {
try {
val sqlResourceLoader = eqlConfig.getSqlResourceLoader();
return sqlResourceLoader.loadEqlBlock(sqlClassPath, codeDesc.getDescLabel());
} catch (Exception ex) {
return null;
}
}
}