001: package com.teamkonzept.db;
002:
003: import java.sql.*;
004: import java.util.*;
005:
006: import com.teamkonzept.lib.*;
007: import org.apache.log4j.Category;
008:
009: /**
010: *
011: * @author $Author: alex $
012: * @version $Revision: 1.13 $
013: */
014: public abstract class CompositeQuery extends TKQuery {
015:
016: /** Logging Category */
017: private static Category cat = Category
018: .getInstance(CompositeQuery.class);
019:
020: /** query objects in the order they are to be executed*/
021: TKVector queries = new TKVector();
022:
023: /** behaviour during execute(): */
024: boolean defaultParameterPropagation = false;
025:
026: /** nested hash, 3 levels:
027: 1) destQuery
028: 2) sourceQuery
029: 3) destParam
030: 4) sourceParam
031: */
032: TKHashtable parameterMapping = new TKHashtable();
033:
034: /**
035: hash to store resultsets
036: */
037: TKHashtable queryResults = new TKHashtable();
038:
039: /**
040: hash to store conditons for execution
041: key: query
042: value: TKVector of parameters
043: */
044: TKHashtable requiredParams = new TKHashtable();
045:
046: /**
047: if relevantQuery is not null, it is used by fetchResultSet()
048: */
049: TKQuery relevantQuery = null;
050:
051: /**
052: template method.
053: implemented by concrete subclass
054:
055: should contain:
056: 1) calls to registerQuery
057: 2) callsto setInternalParameter
058: */
059: protected abstract void initConcreteCompositeQuery()
060: throws SQLException;
061:
062: /*
063: boolean initCompositeQuery()throws SQLException{
064: initConcreteCompositeQuery();
065: return true;
066: }
067: */
068: public void initQuery(final TKSQLTypeConverter conv,
069: final TKDBConnection tkdbConn, Object queryID) {
070:
071: queryParams = new TKHashtable();
072:
073: // initialisation
074: /*
075: try{
076: initCompositeQuery();
077: }
078: catch(SQLException e){
079: throw new Error(e.getMessage());
080: }
081: */
082: }
083:
084: /**
085: to ignore:
086: */
087: public void initQuery(final Connection conn) {
088: //NOP
089: }
090:
091: /**
092: template method
093: */
094: protected boolean beforeExecution(int i) {
095: return true;
096: }
097:
098: /**
099: registers and creates query object
100: */
101: protected TKQuery registerQuery(Class queryClass)
102: throws SQLException {
103: TKQuery query = TKDBManager.newQuery(queryClass);
104:
105: // store query:
106: queries.addElement(query);
107:
108: return query;
109: }
110:
111: /**
112: defines that destParam of destQuery will be assigned
113: the value sourceParam of the resultset of sourceQuery
114: */
115: protected boolean setInternalParameter(TKQuery destQuery,
116: TKQuery sourceQuery, String destParam, String sourceParam)
117: throws SQLException {
118:
119: // check if input param exists
120: if (!new TKVector(((TKPrepQuery) destQuery).paramOrder)
121: .contains(destParam)) {
122: throw new SQLException(
123: " Attempt to reference nonexisting query input parameter: "
124: + destParam + " in query " + destQuery
125: + " by CompositeQuery " + this );
126: }
127:
128: // store information
129: Object[] keyList = { destQuery, sourceQuery, destParam };
130: parameterMapping.put(keyList, sourceParam);
131:
132: return true;
133: }
134:
135: /**
136: fetches parameters from resultsets and sets them into queries
137: */
138: boolean internalParamsPropagation(int i) throws SQLException {
139: TKQuery destQuery = getQuery(i);
140: TKHashtable sourceQueries = (TKHashtable) parameterMapping
141: .get(destQuery);
142: // no internal parameters for this query
143: if (sourceQueries == null) {
144: return true;
145: }
146: Enumeration sourceQueriesEnum = sourceQueries.keys();
147: while (sourceQueriesEnum.hasMoreElements()) {
148: TKQuery sourceQuery = (TKQuery) sourceQueriesEnum
149: .nextElement();
150: TKHashtable paramPairs = (TKHashtable) sourceQueries
151: .get(sourceQuery);
152: Enumeration destParams = paramPairs.keys();
153: while (destParams.hasMoreElements()) {
154: String destParameter = (String) destParams
155: .nextElement();
156: String sourceParameter = (String) paramPairs
157: .get(destParameter);
158: Object parameterValue = getResult(sourceQuery,
159: sourceParameter);
160: destQuery.setQueryParams(destParameter, parameterValue);
161: // report
162: }
163: }
164: return true;
165: }
166:
167: Object getResult(TKQuery query, String resultName)
168: throws SQLException {
169: ResultSet rs = (ResultSet) getResultSet(query);
170: if (rs != null && hasColumn(query, resultName)) {
171: return rs.getObject(resultName);
172: } else
173: return null;
174: }
175:
176: /**
177: Fetches ResultSet of cache or query, sets it on the first row, and stores it for later use.
178: */
179: ResultSet getResultSet(TKQuery query) throws SQLException {
180: ResultSet rs = (ResultSet) queryResults.get(query);
181: if (rs == null) {
182: rs = query.fetchResultSet();
183: if (rs != null && rs.next()) {
184:
185: queryResults.put(query, rs);
186: }
187: }
188: return rs;
189: }
190:
191: /*
192: ResultSet getResultSet(TKQuery query)throws SQLException{
193: //ResultSet rs = (ResultSet)queryResults.get(query);
194: ResultSet rs;
195: Object obj = queryResults.get(query);
196: if(obj == null){
197: rs = query.fetchResultSet();
198: if(rs != null){
199: rs.next();
200: queryResults.put(query, rs);
201: }
202: else{
203: queryResults.put(query, new TKNull())
204: }
205: }
206: if(obj instanceof TKNull){
207: return null;
208: }
209: return rs;
210: }
211: */
212: /**
213: OBSOLETE
214: checks if the resultset of this query is required by following queries, eventually stores it.
215: relies on:
216: 1. that the query renders the relevant resultset as the first one.
217: 2. the ResultSet has only one row of interest.
218: */
219: /*
220: void storeResultSet(TKQuery query, boolean conditional)throws SQLException{
221:
222: if(sourceQueries().contains(query)){
223: storeResultSet(query);
224: }
225: }
226: void storeResultSet(TKQuery query)throws SQLException{
227: ResultSet rs = query.fetchResultSet();
228: if (rs!= null && rs.next()){
229: queryResults.put(query, rs);
230: }
231: }
232: */
233: /**
234: finds all the queries that are used to retrieve internal parameters
235:
236: */
237: TKVector sourceQueries() {
238: TKVector allSourceQueries = new TKVector();
239: Enumeration sourceHashes = parameterMapping.elements();
240: while (sourceHashes.hasMoreElements()) {
241: TKHashtable currSourceHash = (TKHashtable) sourceHashes
242: .nextElement();
243: Enumeration currSourceQueries = currSourceHash.keys();
244: while (currSourceQueries.hasMoreElements()) {
245: allSourceQueries.addElement(currSourceQueries
246: .nextElement());
247: }
248: }
249: return allSourceQueries;
250: }
251:
252: protected void setDefaultParameterPropagation() {
253: defaultParameterPropagation = true;
254: }
255:
256: boolean defaultPropagation(int i) throws SQLException {
257: if (queries.elementAt(i) instanceof TKNull) {
258: return false;
259: }
260: TKPrepQuery destQ = (TKPrepQuery) getQuery(i);
261: for (int j = 0; j < i; j++) {
262: TKQuery sourceQuery = getQuery(j);
263: if (sourceQuery == null) {
264: continue;
265: }
266: retrieveValues(destQ, sourceQuery);
267:
268: }
269: return true;
270: }
271:
272: boolean retrieveValues(TKPrepQuery destQ, TKQuery sourceQ)
273: throws SQLException {
274: TKVector unsetParams = getUnsetParams(destQ);
275: ListIterator unsetParamsIter = unsetParams.listIterator();
276: while (unsetParamsIter.hasNext()) {
277: String paramName = (String) unsetParamsIter.next();
278: Object paramVal = getResult(sourceQ, paramName);
279: if (paramVal != null) {
280: destQ.setQueryParams(paramName, paramVal);
281: cat.debug(" sets " + paramName + " to " + paramVal
282: + " from " + sourceQ);
283:
284: }
285:
286: }
287: return true;
288: }
289:
290: /**
291: propagates parameters to all registered queries
292: */
293: protected void setQueryParams() {
294: Enumeration queryEnum = queriesEnumeration();
295: while (queryEnum.hasMoreElements()) {
296: TKQuery query = (TKQuery) queryEnum.nextElement();
297: Enumeration names = queryParams.keys();
298: while (names.hasMoreElements()) {
299: String name = (String) names.nextElement();
300: query.setQueryParams(name, queryParams.get(name));
301: }
302: }
303: }
304:
305: /*
306: public void setQueryParams( String param, Object val){
307: Enumeration queryEnum = queriesEnumeration();
308: while( queryEnum.hasMoreElements() ){
309: TKQuery curr = (TKQuery) queryEnum.nextElement();
310: curr.setQueryParams(param, val);
311: }
312: }
313: */
314:
315: /**
316: * fuehrt die Query aus
317: * @throws SQLException vom Treiber geschmissen
318: * @return ob ein ResultSet vorhanden ist
319: */
320: public boolean execute() throws SQLException {
321:
322: initConcreteCompositeQuery();
323:
324: setQueryParams();
325:
326: boolean hasResultset = false;
327:
328: for (int i = 0; i < queries.size(); i++) {
329:
330: // will be assigned the return value of
331: // the template method
332: boolean doIt;
333:
334: TKQuery query = getQuery(i);
335: if (query == null) {
336: continue;
337: }
338: // transfer parametervalues from resultsets to queries
339: internalParamsPropagation(i);
340:
341: //call template method
342: doIt = beforeExecution(i);
343:
344: doIt = checkRequiredParameters(query);
345:
346: if (doIt) {
347: if (defaultParameterPropagation) {
348: defaultPropagation(i);
349: }
350: cat.debug(" execute " + query);
351: cat.debug(" with set params: " + query.queryParams);
352: if (query instanceof TKPrepQuery)
353: cat.debug(" and with unset params: "
354: + getUnsetParams((TKPrepQuery) query));
355: TKVector req = (TKVector) requiredParams.get(query);
356: cat.debug(" requiredParams: "
357: + (req != null ? req.toString() : "NULL"));
358: hasResultset = query.execute();
359: } else {
360: queries.set(i, new TKNull());
361: }
362: //storeResultSet(query, true);
363:
364: }
365: return hasResultset;
366: }
367:
368: /** returnes the resultset of the query executed as last */
369: public ResultSet fetchResultSet() {
370: TKQuery query;
371: if (relevantQuery != null) {
372: query = relevantQuery;
373: } else {
374: query = getQuery(queries.size() - 1);
375: }
376: if (query == null) { // we should better check whether query is null...
377: return null;
378: }
379: return query.fetchResultSet();
380: }
381:
382: public void close() throws SQLException {
383: Enumeration queryEnum = queriesEnumeration();
384: while (queryEnum.hasMoreElements()) {
385: Object next = queryEnum.nextElement();
386: if (next instanceof TKQuery) {
387: TKQuery query = (TKQuery) next;
388: query.close();
389: }
390: }
391: }
392:
393: public TKQuery getQuery(int i) {
394: TKQuery query;
395: Object obj = queries.get(i);
396: if (obj == null || obj instanceof TKNull) {
397: return null;
398: } else {
399: query = (TKQuery) queries.get(i);
400: return query;
401: }
402: }
403:
404: public Enumeration queriesEnumeration() {
405: return queries.elements();
406: }
407:
408: public void specClose() {
409: //NOP
410: }
411:
412: // methods for control of execution
413: protected void setRequiredParam(TKQuery query, String[] params) {
414: for (int i = 0; i < params.length; i++) {
415: setRequiredParam(query, params[i]);
416: }
417: }
418:
419: protected void setRequiredParam(TKQuery query, String param) {
420:
421: TKVector paramsVector = (TKVector) requiredParams.get(query);
422: if (paramsVector == null) {
423: paramsVector = new TKVector();
424: requiredParams.put(query, paramsVector);
425: }
426: paramsVector.add(param);
427: }
428:
429: /**
430: Returns true <=> all strings in requiredParams for a certain query
431: are set as parameters of this query.
432:
433: */
434:
435: public boolean checkRequiredParameters(TKQuery query) {
436: //TKQuery query = getQuery(i);
437: //Set allreadySetParams = query.queryParams.keySet();
438:
439: TKVector reqParams = (TKVector) requiredParams.get(query);
440: if (reqParams == null) {
441: return true;
442: }
443: Enumeration reqParamsEnum = reqParams.elements();
444: while (reqParamsEnum.hasMoreElements()) {
445: String reqParam = (String) reqParamsEnum.nextElement();
446:
447: //boolean cont = allreadySetParams.contains(reqParam);
448: Object setParam = query.queryParams.get(reqParam);
449: if (setParam == null) {
450: return false;
451: } else if (setParam instanceof TKNull) {
452: return false;
453: }
454: }
455: return true;
456: }
457:
458: // methods for default parameter propagation
459: public boolean areAllParamsSet(TKPrepQuery query) {
460: return (getUnsetParams(query).size() == 0);
461: }
462:
463: public boolean isParameterSet(String paramName) {
464: if (queryParams == null)
465: return false;
466: Object parameterValue = queryParams.get(paramName);
467: return parameterValue != null
468: && !(parameterValue instanceof TKNull);
469: }
470:
471: /*
472: public boolean isParameterSet( String paramName){
473: Enumeration queryEnum = queriesEnumeration();
474: while(queryEnum.hasMoreElements()){
475: Object obj = queryEnum.nextElement();
476: if( !(obj instanceof TKNull)){
477: TKPrepQuery query = (TKPrepQuery) obj;
478: if(isParameterSet(query, paramName)){
479: return true;
480: }
481: }
482: }
483: return false;
484: }
485: */
486:
487: public boolean isParameterSet(TKPrepQuery query, String paramName) {
488: Object parameterValue = query.queryParams.get(paramName);
489: return parameterValue != null
490: && !(parameterValue instanceof TKNull);
491: }
492:
493: public TKVector getUnsetParams(TKPrepQuery query) {
494: TKVector unsParams = new TKVector();
495: if (query.paramOrder == null)
496: return unsParams;
497: for (int i = 0; i < query.paramOrder.length; i++) {
498: String currParam = query.paramOrder[i];
499: Object currVal = query.queryParams.get(currParam);
500: if (currVal == null || (currVal instanceof TKNull)) {
501: unsParams.addElement(currParam);
502: }
503: /*
504: if(!query.queryParams.containsKey(currParam)){
505: unsParams.addElement(currParam);
506: }
507: */
508: }
509: return unsParams;
510: }
511:
512: public boolean hasColumn(TKQuery query, String colName)
513: throws SQLException {
514: ResultSet rs = getResultSet(query);
515: if (rs != null) {
516: return hasColumn(rs, colName);
517: } else
518: return false;
519: }
520:
521: public boolean hasColumn(ResultSet rs, String colName)
522: throws SQLException {
523: ResultSetMetaData meta = rs.getMetaData();
524: int colCount = meta.getColumnCount();
525: for (int i = 1; i <= colCount; i++) {
526: if (colName.equals(meta.getColumnName(i).toUpperCase())) {
527: return true;
528: }
529:
530: }
531: return false;
532: }
533:
534: protected Object searchParamInResults(String paramName) {
535: return null;
536:
537: }
538:
539: public void setRelevantQuery(TKQuery query) {
540: relevantQuery = query;
541: }
542: }
|