package org.n3r.eql.param; import com.google.common.base.Splitter; import lombok.Data; import lombok.val; import org.n3r.eql.param.EqlParamsParser.PlaceHolderTemp; import org.n3r.eql.util.S; import java.sql.Types; import java.util.regex.Pattern; import static org.n3r.eql.param.EqlParamsParser.SUB; @Data public class EqlParamPlaceholder { public enum InOut {IN, OUT, INOUT;} public enum Like {None, Like, LeftLike, RightLike;} private int outType = Types.VARCHAR; private boolean lob; private Like like = Like.None; private boolean numberColumn; private String placeholder; private InOut inOut = InOut.IN; private PlaceholderType placeholderType; private int seq; private boolean escape; private String escapeValue; public void parseOption(PlaceHolderTemp holder, String evalSqlTemplate) { val splitter = Splitter.on(',').omitEmptyStrings().trimResults(); val optionParts = splitter.split(S.upperCase(holder.getPlaceHolderOptions())); for (String optionPart : optionParts) { String upperPureOption = parsePureOption(optionPart); String upperSubOption = parseSubOption(optionPart); if (S.equals("OUT", upperPureOption)) { setInOut(InOut.OUT); parseOutType(upperSubOption); } else if (S.equals("INOUT", upperPureOption)) { setInOut(InOut.INOUT); parseOutType(upperSubOption); } else if (S.equals("LOB", upperPureOption)) { setLob(true); } else if (S.equals("LIKE", upperPureOption)) { setLike(Like.Like); parseEscape(holder, evalSqlTemplate); } else if (S.equals("LEFTLIKE", upperPureOption)) { setLike(Like.LeftLike); parseEscape(holder, evalSqlTemplate); } else if (S.equals("RIGHTLIKE", upperPureOption)) { setLike(Like.RightLike); parseEscape(holder, evalSqlTemplate); } else if (S.equals("NUMBER", upperPureOption)) { setNumberColumn(true); } } } private void parseEscape(PlaceHolderTemp holder, String evalSqlTemplate) { val fromSub = S.wrap(holder.getQuestionSeq(), SUB); int fromSubIndex = evalSqlTemplate.indexOf(fromSub) + fromSub.length(); val escapePattern = Pattern.compile("\\s+ESCAPE\\s+(\\S+)", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); val substring = evalSqlTemplate.substring(fromSubIndex); val matcher = escapePattern.matcher(substring); setEscape(matcher.find()); if (!isEscape()) return; val val = S.unQuote(matcher.group(1), "'"); setEscapeValue(S.isNotEmpty(val) ? val.substring(0, 1) : "\\"); } private void parseOutType(String subOptionUpper) { if (subOptionUpper == null) return; // ref: http://docs.oracle.com/javase/1.5.0/docs/guide/jdbc/getstart/mapping.html if ("LONG".equals(subOptionUpper)) setOutType(Types.BIGINT); else if ("INT".equals(subOptionUpper)) setOutType(Types.INTEGER); } private String parseSubOption(String optionPart) { int leftBrace = optionPart.indexOf('('); if (leftBrace == -1) return null; int rightBrace = optionPart.indexOf(')', leftBrace); if (rightBrace == -1) throw new RuntimeException("option " + optionPart + " hasn't right brace"); return S.trim(optionPart.substring(leftBrace + 1, rightBrace)); } private String parsePureOption(String optionPart) { int leftBrace = optionPart.indexOf('('); if (leftBrace == -1) return optionPart; return S.trim(optionPart.substring(0, leftBrace)); } }