package org.n3r.eql.impl; import com.google.common.collect.Lists; import org.n3r.eql.base.DynamicLanguageDriver; import org.n3r.eql.parser.*; import java.util.List; import java.util.regex.Matcher; public class DefaultDynamicLanguageDriver implements DynamicLanguageDriver { @Override public Sql parse(EqlBlock block, List<String> oneSqlLines) { return parse(oneSqlLines); } public Sql parse(List<String> oneSqlLines) { List<String> stdLines = standardLines(oneSqlLines); MultiPart multiPart = new MultiPart(); for (int i = 0, ii = stdLines.size(); i < ii; ++i) { String line = stdLines.get(i); if (line.startsWith("--")) { String clearLine = ParserUtils.substr(line, "--".length()); PartParser partParser = PartParserFactory.tryParse(clearLine); if (partParser != null) { i = partParser.parse(stdLines, i + 1) - 1; multiPart.addPart(partParser.createPart()); } continue; } Matcher matcher = ParserUtils.inlineComment.matcher(line); if (!matcher.matches()) { multiPart.addPart(new LiteralPart(line)); continue; } String cleanStr = matcher.group(1); PartParser partParser = PartParserFactory.tryParse(cleanStr); if (partParser != null) { i = partParser.parse(stdLines, i + 1) - 1; multiPart.addPart(partParser.createPart()); } else { multiPart.addPart(new LiteralPart(line)); } } if (multiPart.size() == 0) return null; if (multiPart.size() == 1 && multiPart.part(0) instanceof LiteralPart) { String sql = ((LiteralPart) multiPart.part(0)).getSql(); if (ParserUtils.inlineComment.matcher(sql).matches()) return null; return new StaticSql(sql); } return new DynamicSql(multiPart); } private List<String> standardLines(List<String> oneSqlLines) { return rearrangeLinesForInlineComments(rearrangeLinesForLineCommentsAndOthers(oneSqlLines)); } private List<String> rearrangeLinesForInlineComments(List<String> lines) { List<String> convertedLines = Lists.<String>newArrayList(); StringBuilder mergedLine = new StringBuilder(); for (String line : lines) { if (line.startsWith("--")) { mergedAdd(convertedLines, mergedLine, line); continue; } // splits /* */ to seperate lines Matcher matcher = ParserUtils.inlineComment.matcher(line); int lastStart = 0; while (matcher.find()) { int start = matcher.start(); if (start > lastStart) { mergeLine(mergedLine, line.substring(lastStart, start), false); } lastStart = matcher.end(); mergedAdd(convertedLines, mergedLine, matcher.group()); } if (lastStart < line.length()) mergeLine(mergedLine, line.substring(lastStart), true); else if (lastStart > 0) mergedLine.append('\n'); } if (mergedLine.length() > 0) convertedLines.add(mergedLine.toString()); return convertedLines; } private List<String> rearrangeLinesForLineCommentsAndOthers(List<String> oneSqlLines) { List<String> convertedLines = Lists.<String>newArrayList(); StringBuilder mergedLine = new StringBuilder(); for (String line : oneSqlLines) { if (line.startsWith("--")) { mergedAdd(convertedLines, mergedLine, line); } else { mergeLine(mergedLine, line, true); } } if (mergedLine.length() > 0) convertedLines.add(mergedLine.toString()); return convertedLines; } private void mergedAdd(List<String> merged, StringBuilder mergedLine, String line) { if (mergedLine.length() > 0) { merged.add(mergedLine.toString()); mergedLine.delete(0, mergedLine.length()); } merged.add(line); } private void mergeLine(StringBuilder mergedLine, String line, boolean newLine) { String trim = line.trim(); if (trim.length() == 0) return; String trim1 = mergeEndLfs(trimButLf(line)); mergedLine.append(trim1); if (newLine && isLastCharNotLf(trim1)) mergedLine.append('\n'); } private String mergeEndLfs(String line) { int to = line.length() - 1; while (to > 0 && to - 1 >= 0) { char c1 = line.charAt(to); char c2 = line.charAt(to - 1); if (c1 == c2 && c2 == '\n') --to; else break; } return line.substring(0, to + 1); } private boolean isLastCharNotLf(String str) { return str.charAt(str.length() - 1) != '\n'; } private String trimButLf(String line) { int from = 0; int length = line.length(); while (from < length) { char c = line.charAt(from); if (Character.isWhitespace(c)) ++from; else break; } int to = length - 1; while (to >= 0) { char c = line.charAt(to); if (Character.isWhitespace(c) && c != '\n') --to; else break; } return line.substring(from, to + 1); } }