1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dbforms.event.datalist.dao;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import org.dbforms.config.Constants;
30 import org.dbforms.config.DbFormsConfigRegistry;
31 import org.dbforms.config.Field;
32 import org.dbforms.config.FieldValue;
33 import org.dbforms.config.FieldValues;
34
35 import org.dbforms.dom.DOMFactory;
36
37 import org.dbforms.util.Util;
38
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41
42 import java.net.URL;
43
44 import java.sql.Connection;
45 import java.sql.SQLException;
46
47 import java.util.Hashtable;
48 import java.util.Iterator;
49 import java.util.Vector;
50
51
52
53 /***
54 * Special implementation of DataSource. This class deals with xml data
55 *
56 * @author hkk
57 */
58 public class DataSourceXML extends AbstractDataSource {
59 private Hashtable keys;
60 private Log logCat = LogFactory.getLog(this.getClass().getName());
61 private String sqlFilter;
62 private XMLDataResult data;
63 private Object[][] dataObject = null;
64 private FieldValue[] filterConstraint;
65 private FieldValue[] orderConstraint;
66 private FieldValue[] sqlFilterParams;
67
68
69 /***
70 * Set the filterConstraint and orderConstraint used to build the SQL Select
71 * condition.
72 *
73 * @param filterConstraint FieldValue array used to build a cumulation of
74 * rules for filtering fields.
75 * @param orderConstraint FieldValue array used to build a cumulation of
76 * rules for ordering (sorting) and restricting fields.
77 * @param sqlFilter sql condition to add to where clause
78 * @param sqlFilterParams list of FieldValues to fill the sqlFilter with
79 */
80 public void setSelect(FieldValue[] filterConstraint,
81 FieldValue[] orderConstraint,
82 String sqlFilter,
83 FieldValue[] sqlFilterParams) {
84 this.filterConstraint = filterConstraint;
85 this.orderConstraint = orderConstraint;
86 this.sqlFilter = sqlFilter;
87 this.sqlFilterParams = sqlFilterParams;
88 }
89
90
91 /***
92 * performs an update into the DataSource
93 *
94 * @param con DOCUMENT ME!
95 * @param fieldValues FieldValues to update
96 * @param keyValuesStr keyValueStr to the row to update<br>
97 * key format: FieldID ":" Length ":" Value<br>
98 * example: if key id = 121 and field id=2 then keyValueStr contains "2:3:121"<br>
99 * If the key consists of more than one fields, the key values are
100 * seperated through "-"<br>
101 * example: value of field 1=12, value of field 3=1992, then we'll
102 * get "1:2:12-3:4:1992"
103 *
104 * @throws SQLException if any error occurs
105 */
106 public void doUpdate(Connection con,
107 FieldValues fieldValues,
108 String keyValuesStr) throws SQLException {
109 Integer row = (Integer) keys.get(keyValuesStr);
110
111 if (row != null) {
112 int r = row.intValue();
113 Iterator iter = fieldValues.elements();
114
115 while (iter.hasNext()) {
116 FieldValue fv = (FieldValue) iter.next();
117 Field f = fv.getField();
118 data.setItemValue(r,
119 Util.isNull(f.getExpression()) ? f.getName()
120 : f.getExpression(),
121 f.getType(), fv.getFieldValueAsObject());
122 }
123
124 dataObject[r] = null;
125 }
126 }
127
128
129 /***
130 * should retrieve the row at an special index as an Object[]
131 *
132 * @param currRow index of row to fetch
133 *
134 * @return Object[] of the fetched row
135 *
136 * @throws SQLException
137 */
138 protected final Object[] getRow(int currRow) throws SQLException {
139 if ((currRow < 0) || (currRow >= size())) {
140 return null;
141 }
142
143 if (dataObject[currRow] == null) {
144 Vector fields = getTable()
145 .getFields();
146 Object[] objectRow = new Object[fields.size()];
147 String[] stringRow = new String[fields.size()];
148
149 for (int i = 0; i < fields.size(); i++) {
150 Field f = (Field) fields.elementAt(i);
151 objectRow[i] = data.getItemValue(currRow,
152 Util.isNull(f.getExpression())
153 ? f.getName()
154 : f.getExpression(), f.getType());
155 stringRow[i] = (objectRow[i] != null) ? objectRow[i].toString()
156 : null;
157 }
158
159 String key = getTable()
160 .getKeyPositionString(stringRow);
161 keys.put(key, new Integer(currRow));
162 dataObject[currRow] = objectRow;
163 }
164
165 return dataObject[currRow];
166 }
167
168
169 /***
170 * should close all open datasets
171 */
172 protected final void close() {
173 if ((data != null) && data.hasChanged()) {
174 try {
175 String url = getFilePath() + getQuery();
176 write(url, data.getRoot());
177 } catch (Exception e) {
178 logCat.error(e);
179 }
180 }
181
182 if (keys != null) {
183 keys.clear();
184 }
185
186 dataObject = null;
187 }
188
189
190 /***
191 * maps the startRow to the internal index
192 *
193 * @param startRow keyValueStr to the row<br>
194 * key format: FieldID ":" Length ":" Value<br>
195 * example: if key id = 121 and field id=2 then keyValueStr contains "2:3:121"<br>
196 * If the key consists of more than one fields, the key values are
197 * seperated through "-"<br>
198 * example: value of field 1=12, value of field 3=1992, then we'll
199 * get "1:2:12-3:4:1992"
200 *
201 * @return the index of the row, 0 as first row if not found
202 *
203 * @throws SQLException
204 */
205 protected final int findStartRow(String startRow) throws SQLException {
206 Integer res = null;
207
208 if (!Util.isNull(startRow)) {
209 res = (Integer) keys.get(startRow);
210 }
211
212 return (res != null) ? res.intValue()
213 : 0;
214 }
215
216
217 /***
218 * Will be called to open all datasets
219 *
220 * @throws SQLException
221 */
222 protected final void open() throws SQLException {
223 if (dataObject == null) {
224 try {
225 String qry = getQuery();
226 String url = getFilePath() + qry;
227
228 try {
229 URL u = new URL(url);
230 qry = u.getQuery();
231 } catch (Exception e) {
232 logCat.info("open", e);
233 }
234
235 Document doc = read(url);
236
237 if (doc != null) {
238 Element elem = doc.getDocumentElement();
239 data = new XMLDataResult(elem, qry);
240 }
241 } catch (Exception e) {
242 logCat.error("open", e);
243 throw new SQLException(e.getMessage());
244 }
245
246 keys = new Hashtable();
247 dataObject = new Object[size()][];
248 }
249 }
250
251
252 /***
253 * Must return the size of the whole resultset with all data fetch
254 *
255 * @return size of whole resultset
256 *
257 * @throws SQLException
258 */
259 protected final int size() throws SQLException {
260 return (data != null) ? data.size()
261 : 0;
262 }
263
264
265 /***
266 * return true if there are more records to fetch then the given record
267 * number
268 *
269 * @param i index of last fetched row.
270 *
271 * @return true if there are more records to fetch then the given record
272 * number
273 *
274 * @throws SQLException
275 */
276 protected boolean hasMore(int i) throws SQLException {
277 return (i < size());
278 }
279
280
281 /***
282 * gets the document from the remote system.
283 *
284 * @param url the uri to query
285 *
286 * @return NODE the result
287 *
288 * @throws Exception Exception during processing IO
289 */
290 protected Document read(String url) throws Exception {
291 return DOMFactory.instance()
292 .read(url);
293 }
294
295
296 /***
297 * saves the document to the remote system.
298 *
299 * @param url DOCUMENT ME!
300 * @param root DOCUMENT ME!
301 *
302 * @throws Exception Exception during processing IO
303 */
304 protected void write(String url,
305 Element root) throws Exception {
306 DOMFactory.instance()
307 .write(url, root);
308 }
309
310
311 private String getFilePath() throws Exception {
312 return DbFormsConfigRegistry.instance().lookup().replaceVariables(getTable().getAlias());
313 }
314
315
316 private String getQuery() throws SQLException {
317 StringBuffer buf = new StringBuffer();
318
319 String filter = getWhereClause();
320 String psqlFilter = getSQLFilter();
321
322 if (!Util.isNull(filter) || !Util.isNull(sqlFilter)) {
323 buf.append("[");
324 buf.append(filter);
325
326 if (!Util.isNull(psqlFilter)) {
327 if (!Util.isNull(filter)) {
328 buf.append(" and ");
329 }
330
331 buf.append(sqlFilter);
332 }
333
334 buf.append("]");
335 }
336
337 return buf.toString();
338 }
339
340
341 private String getSQLFilter() {
342 if (sqlFilter == null)
343 return null;
344 /*** substitute ? with corresponding value in list */
345 int p1 = 0;
346 int p2 = sqlFilter.indexOf('?', p1);
347 StringBuffer buf = new StringBuffer();
348 int cnt = 0;
349
350 while (p2 > -1) {
351
352 buf.append(sqlFilter.substring(p1, p2));
353
354
355 if (cnt >= sqlFilterParams.length) {
356 logCat.error("reference to a missing filterValue in " + sqlFilter);
357
358 return null;
359 }
360
361
362 String value = sqlFilterParams[cnt].getFieldValue();
363
364 if (!Util.isNull(value)) {
365
366 buf.append("\"");
367 buf.append(value);
368 buf.append("\"");
369 }
370
371
372 p1 = p2 + 1;
373 p2 = sqlFilter.indexOf('?', p1);
374 cnt++;
375 }
376
377
378 buf.append(sqlFilter.substring(p1));
379
380 return buf.toString();
381 }
382
383
384 private String getWhereClause() throws SQLException {
385 StringBuffer buf = new StringBuffer();
386
387 if (!FieldValue.isNull(filterConstraint)) {
388 for (int i = 0; i < filterConstraint.length; i++) {
389 if (i != 0) {
390 if (filterConstraint[i].getLogicalOR()) {
391 buf.append(" or ");
392 } else {
393 buf.append(" and ");
394 }
395 }
396
397 Field f = filterConstraint[i].getField();
398 buf.append(Util.isNull(f.getExpression()) ? f.getName()
399 : f.getExpression());
400
401
402 switch (filterConstraint[i].getOperator()) {
403 case Constants.FILTER_EQUAL:
404 buf.append("=");
405
406 break;
407
408 case Constants.FILTER_NOT_EQUAL:
409 buf.append("!=");
410
411 break;
412
413 case Constants.FILTER_GREATER_THEN:
414 buf.append(">");
415
416 break;
417
418 case Constants.FILTER_SMALLER_THEN:
419 buf.append("<");
420
421 break;
422
423 case Constants.FILTER_GREATER_THEN_EQUAL:
424 buf.append(">=");
425
426 break;
427
428 case Constants.FILTER_SMALLER_THEN_EQUAL:
429 buf.append("<=");
430
431 break;
432 }
433
434 buf.append("\"");
435 buf.append(filterConstraint[i].getFieldValueAsObject().toString());
436 buf.append("\"");
437 }
438 }
439
440 return buf.toString();
441 }
442 }