1 16 package scriptella.driver.csv; 17 18 import au.com.bytecode.opencsv.CSVReader; 19 import scriptella.expression.PropertiesSubstitutor; 20 import scriptella.spi.AbstractConnection; 21 import scriptella.spi.ParametersCallback; 22 import scriptella.spi.QueryCallback; 23 import scriptella.util.ColumnsMap; 24 import scriptella.util.ExceptionUtils; 25 26 import java.io.Closeable ; 27 import java.io.IOException ; 28 import java.util.ArrayList ; 29 import java.util.List ; 30 import java.util.regex.Matcher ; 31 import java.util.regex.Pattern ; 32 33 39 public class CsvQuery implements ParametersCallback, Closeable { 40 private CSVReader reader; 41 private final boolean headers; 42 private final boolean trim; 43 private ColumnsMap columnsMap; 44 private String [] row; 45 private Pattern [][] patterns; 46 private Matcher [][] matchers; 47 private PropertiesSubstitutor substitutor = new PropertiesSubstitutor(); 48 49 56 public CsvQuery(CSVReader reader, boolean headers, boolean trim) { 57 if (reader == null) { 58 throw new IllegalArgumentException ("CSV reader cannot be null"); 59 } 60 this.reader = reader; 61 this.headers = headers; 62 this.trim = trim; 63 } 64 65 74 public void execute(CSVReader queryReader, ParametersCallback parametersCallback, QueryCallback queryCallback, AbstractConnection.StatementCounter counter) throws IOException { 75 try { 76 substitutor.setParameters(parametersCallback); 77 compileQueries(queryReader); 78 79 columnsMap = new ColumnsMap(); 80 if (headers) { 81 String [] row = reader.readNext(); 82 for (int i = 0; i < row.length; i++) { 83 columnsMap.registerColumn(row[i], i + 1); 84 } 85 } 86 88 while ((row = reader.readNext()) != null) { 89 if (rowMatches()) { 90 queryCallback.processRow(this); 91 } 92 } 93 } finally { try { 95 queryReader.close(); 96 } catch (Exception e) { 97 ExceptionUtils.ignoreThrowable(e); 98 } 99 } 100 if (patterns != null) { 101 counter.statements += patterns.length; 102 } 103 } 104 105 110 boolean rowMatches() { 111 Pattern [][] ptrs = patterns; 113 int columnsCount = row.length; 114 if (ptrs == null) { 115 return true; 116 } else if (columnsCount == 0) { 117 return false; 118 } 119 120 for (int i = 0; i < ptrs.length; i++) { 121 Pattern [] rowPatterns = ptrs[i]; 122 Matcher [] rowMatchers = matchers[i]; 123 boolean rowMatches = true; 124 int patternsCount = rowPatterns.length; 125 if (patternsCount > columnsCount) { continue; } 128 for (int j = 0; j < patternsCount; j++) { 129 Pattern columnPtr = rowPatterns[j]; 130 if (columnPtr != null) { 131 Matcher m = rowMatchers[j]; 132 String col = row[j]; if (m == null) { m = columnPtr.matcher(col); 135 rowMatchers[j] = m; 136 } else { m.reset(col); 138 } 139 if (!m.matches()) { 140 rowMatches = false; 141 break; 142 } 143 } 144 } 145 if (rowMatches) { return true; 147 } } 149 return false; 151 152 } 153 154 159 @SuppressWarnings ("unchecked") 160 void compileQueries(final CSVReader r) { 161 List <String []> list; 162 try { 163 list = r.readAll(); 164 } catch (IOException e) { 165 throw new CsvProviderException("Unable to read CSV query", e); 166 } 167 List <Pattern []> res = null; 168 for (String [] columns : list) { 169 Pattern [] patterns = null; 170 for (int i = 0; i < columns.length; i++) { 171 String s = trim(columns[i]); 172 if (s != null && s.length() > 0) { 173 if (patterns == null) { 174 patterns = new Pattern [columns.length]; 175 } 176 try { 177 patterns[i] = Pattern.compile(substitutor.substitute(s), Pattern.CASE_INSENSITIVE | Pattern.DOTALL); 178 } catch (Exception e) { 179 throw new CsvProviderException("Illegal regular expression syntax for query", e, s); 180 } 181 } 182 } 183 if (patterns != null) { if (res == null) { 185 res = new ArrayList <Pattern []>(); 186 } 187 res.add(patterns); 188 } 189 } 190 if (res != null) { 191 int len = res.size(); 192 Pattern [][] ptrs = res.toArray(new Pattern [len][]); 193 Matcher [][] matchers = new Matcher [len][]; 195 for (int i = 0; i < len; i++) { 196 matchers[i] = new Matcher [ptrs[i].length]; 197 } 198 this.patterns = ptrs; 199 this.matchers = matchers; 200 } 201 202 } 203 204 210 private String trim(String s) { 211 return (trim && s != null) ? s.trim() : s; 212 } 213 214 public Object getParameter(final String name) { 215 if (reader == null) { 216 throw new IllegalStateException ("CSV Resultset is closed"); 217 } 218 Integer col = columnsMap.find(name); 219 if (col != null && col > 0 && col <= row.length) { return row[col - 1]; 221 } else { return substitutor.getParameters().getParameter(name); 223 } 224 } 225 226 public void close() throws IOException { 227 if (reader != null) { 228 reader.close(); 229 reader = null; 230 columnsMap = null; 231 } 232 } 233 } 234 | Popular Tags |