001/* 002 * JKNIV, SQLegance keeping queries maintainable. 003 * 004 * Copyright (C) 2017, the original author or authors. 005 * 006 * This library is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2.1 of the License. 010 * 011 * This library is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software Foundation, Inc., 018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 019 */ 020package net.sf.jkniv.sqlegance.params; 021 022import java.util.ArrayList; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026import java.util.regex.Matcher; 027import java.util.regex.Pattern; 028 029public class ParamParserDollarMark extends AbstractParamParser 030{ 031 private static final Pattern PATTERN_PARAMS = Pattern.compile(REGEX_DOLLAR_MARK, Pattern.MULTILINE | Pattern.CASE_INSENSITIVE); 032 private static final ParamParser INSTANCE = new ParamParserDollarMark(); 033 034 private ParamParserDollarMark() 035 { 036 } 037 038 public static ParamParser getInstance() 039 { 040 return INSTANCE; 041 } 042 043 @Override 044 Pattern getPatternParams() 045 { 046 return PATTERN_PARAMS; 047 } 048 049 @Override 050 public String[] find(String query) 051 { 052 return parserDollar(query).toArray(new String[0]); 053 } 054 055 @Override 056 public ParamMarkType getType() 057 { 058 return ParamMarkType.DOLLAR; 059 } 060 061 /** 062 * Is {@code $} 063 */ 064 @Override 065 public String getPlaceholder() 066 { 067 return "$"; 068 } 069 070 private List<String> parserDollar(final String sentence) 071 { 072 List<String> params = new ArrayList<String>(); 073 Matcher matcherDollar = PATTERN_PARAMS.matcher(sentence); 074 int i = 0; 075 while (matcherDollar.find()) 076 { 077 if (matcherDollar.group().startsWith("'")) 078 { 079 continue; 080 } 081 else if (matcherDollar.group().startsWith(":in:")) 082 { 083 params.add(i++, sentence.subSequence(matcherDollar.start() + 1, matcherDollar.end()).toString()); 084 continue; 085 } 086 //System.out.printf("group[%s] [%s]\n", matcherTwoDots.group(), sentence.subSequence(matcherTwoDots.start() + 1, matcherTwoDots.end()).toString()); 087 params.add(i++, sentence.subSequence(matcherDollar.start() + 1, matcherDollar.end()).toString()); 088 } 089 return params; 090 } 091 092 093 @Override 094 public String replaceForPlaceholder(String query, Object params) 095 { 096 return replaceForPlaceholderWithNumber(query, params); 097 } 098 099 @Override 100 public String replaceForPlaceholderWithNumber(String query, Object params) 101 { 102 StringBuffer sb = new StringBuffer(query); 103 Matcher matcherTwoDots = getPatternParams().matcher(query); 104 Map<String, String> mapForINClauseParams = new HashMap<String, String>(); 105 int startIndex = 0; 106 int endIndex = 0; 107 int index = 1; 108 while (matcherTwoDots.find()) 109 { 110 String match = matcherTwoDots.group(); 111 if (match.startsWith("'")) 112 continue; 113 if (match.startsWith(":in:")) 114 { 115 String paramName = match.substring(4, match.length()); 116 Object[] paramsAsArray = getParamsClauseIN(params, paramName); 117 if (paramsAsArray != null 118 && paramsAsArray.length > 0 && !mapForINClauseParams.containsKey(match)) 119 { 120 StringBuilder tmp = new StringBuilder(); 121 for(int i=0; i<paramsAsArray.length; i++) 122 tmp.append( i>0? "," : "") 123 .append("\\"+getPlaceholder()+index++); 124 125 mapForINClauseParams.put(match, tmp.toString()); 126 } 127 } 128 else 129 { 130 startIndex = matcherTwoDots.start(); 131 endIndex = matcherTwoDots.end(); 132 sb.replace(startIndex, endIndex, padspace(endIndex - startIndex, index++)); 133 } 134 } 135 if (!mapForINClauseParams.isEmpty()) 136 { 137 String newSql = sb.toString(); 138 for(String key : mapForINClauseParams.keySet()) 139 newSql = newSql.replaceAll(key, mapForINClauseParams.get(key)); 140 141 sb = new StringBuffer(newSql); 142 } 143 return sb.toString(); 144 } 145 146}