KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > scriptella > driver > text > TextQueryExecutor


1 /*
2  * Copyright 2006-2007 The Scriptella Project Team.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package scriptella.driver.text;
17
18 import scriptella.expression.PropertiesSubstitutor;
19 import scriptella.spi.AbstractConnection;
20 import scriptella.spi.ParametersCallback;
21 import scriptella.spi.QueryCallback;
22 import scriptella.util.ExceptionUtils;
23 import scriptella.util.IOUtils;
24 import scriptella.util.StringUtils;
25
26 import java.io.BufferedReader JavaDoc;
27 import java.io.Closeable JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.Reader JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.logging.Level JavaDoc;
33 import java.util.logging.Logger JavaDoc;
34 import java.util.regex.Matcher JavaDoc;
35 import java.util.regex.Pattern JavaDoc;
36
37 /**
38  * This class executes a regex query over a text file content.
39  * <p>The query has a standard regex syntax.
40  * Matching is performed for each line of the text file.
41  * <p><u>Example:</u></p>
42  * <b>Query:</b> <code>.*;(2\d+);.*</code><br>
43  * <b>Text File:</b>
44  * <code>
45  * <pre>
46  * 1;100;record 1
47  * 2;200;record 2
48  * 3;250;record 3
49  * </pre>
50  * </code>
51  * As the result of the query execution the following result set is produced:
52  * <table border=1>
53  * <tr>
54  * <th>Column name/<br>row number</th>
55  * <th>0</th>
56  * <th>1</th>
57  * </tr>
58  * <tr>
59  * <td>1</td>
60  * <td>2;200;record 2</td>
61  * <td>200</td>
62  * </tr>
63  * <tr>
64  * <td>2</td>
65  * <td>3;250;record 3</td>
66  * <td>250</td>
67  * </tr>
68  * </table>
69  * Where column name corresponds to the matched regex group name.
70  *
71  * @author Fyodor Kupolov
72  * @version 1.0
73  */

74 class TextQueryExecutor implements ParametersCallback, Closeable JavaDoc {
75     private static final Logger JavaDoc LOG = Logger.getLogger(TextQueryExecutor.class.getName());
76     private final ParametersCallback params;
77     private final PropertiesSubstitutor ps;
78     private Pattern JavaDoc[] query;
79     private BufferedReader JavaDoc reader;
80     private Matcher JavaDoc result;
81     private boolean trim;
82     private static final String JavaDoc COLUMN_PREFIX = "column";
83
84     public TextQueryExecutor(final Reader JavaDoc queryReader, final boolean trim, final Reader JavaDoc in, final ParametersCallback parentParametersCallback) {
85         if (queryReader == null) {
86             throw new IllegalArgumentException JavaDoc("Query cannot be null");
87         }
88         this.trim = trim;
89         this.params = parentParametersCallback;
90         ps = new PropertiesSubstitutor(params);
91         //Compiles patterns loaded from specified reader.
92
//Patterns are read line-by-line.
93
BufferedReader JavaDoc r = IOUtils.asBuffered(queryReader);
94         List JavaDoc<Pattern JavaDoc> result = new ArrayList JavaDoc<Pattern JavaDoc>();
95         try {
96             for (String JavaDoc s; (s = r.readLine()) != null;) {
97                 if (trim) {
98                     s = s.trim();
99                 }
100                 s = ps.substitute(s);
101                 if (s.length() > 0) { //Not empty string
102
try {
103                         result.add(Pattern.compile(s, Pattern.CASE_INSENSITIVE));
104                     } catch (Exception JavaDoc e) {
105                         throw new TextProviderException("Specified query is not a valid regex: " + s, e);
106                     }
107                 }
108             }
109         } catch (IOException JavaDoc e) {
110             throw new TextProviderException("Unable to read query content", e);
111         } finally {
112             IOUtils.closeSilently(r);
113         }
114         if (result.isEmpty()) {
115             LOG.fine("Empty query matches all lines");
116             result.add(Pattern.compile(".*"));
117         }
118         query = result.toArray(new Pattern JavaDoc[result.size()]);
119         reader = IOUtils.asBuffered(in);
120
121     }
122
123     /**
124      * Executes a query and iterates the resultset using the callback.
125      *
126      * @param qc callback to notify on each row.
127      * @param counter statements counter.
128      */

129     public void execute(final QueryCallback qc, AbstractConnection.StatementCounter counter) {
130         int qCount = query.length;
131         try {
132             Matcher JavaDoc[] matchers = new Matcher JavaDoc[qCount];
133             for (String JavaDoc line; (line = reader.readLine()) != null;) {
134                 if (trim) {
135                     line = line.trim();
136                 }
137                 for (int i = 0; i < qCount; i++) {
138                     Matcher JavaDoc m = matchers[i];
139                     if (m == null) { //First time initialization
140
m = query[i].matcher(line);
141                         matchers[i] = m;
142                     } else { //Reuse matcher for better performance
143
m.reset(line);
144                     }
145                     if (m.matches()) {
146                         if (LOG.isLoggable(Level.FINE)) {
147                             LOG.info("Pattern matched: " + m);
148                         }
149                         result = m;
150                         qc.processRow(this);
151                     }
152                 }
153             }
154         } catch (IOException JavaDoc e) {
155             throw new TextProviderException("Unable to read a text file", e);
156         }
157         counter.statements+=qCount;
158     }
159
160
161     /**
162      * Returns the value of the named parameter.
163      * <p>Use index of the captured group to obtain the value of the matched substring.
164      *
165      * @param name parameter name.
166      * @return parameter value.
167      */

168     public Object JavaDoc getParameter(final String JavaDoc name) {
169         String JavaDoc str = name;
170         if (str != null && str.startsWith(COLUMN_PREFIX)) {
171             str = name.substring(COLUMN_PREFIX.length());
172         }
173         if (StringUtils.isDecimalInt(str)) {
174             try {
175                 int ind = Integer.parseInt(str);
176                 if (ind >= 0 && ind <= result.groupCount()) {
177                     return result.group(ind);
178                 }
179             } catch (NumberFormatException JavaDoc e) {
180                 ExceptionUtils.ignoreThrowable(e);
181             }
182         }
183         return params.getParameter(name);
184     }
185
186     public void close() throws IOException JavaDoc {
187         IOUtils.closeSilently(reader);
188         reader = null;
189     }
190 }
191
Popular Tags