001: /*
002: * $Header: /cvsroot/webman-cms/source/webman/com/teamkonzept/db/TKExtendedPrepQuery.java,v 1.8 2002/02/16 15:37:07 alex Exp $
003: *
004: */
005: package com.teamkonzept.db;
006:
007: import java.sql.*;
008: import java.util.Vector;
009: import java.util.Stack;
010: import java.util.Enumeration;
011: import java.util.NoSuchElementException;
012:
013: import com.teamkonzept.lib.*;
014: import com.teamkonzept.webman.db.TKWebmanDBManager;
015: import com.teamkonzept.webman.mainint.WebmanExceptionHandler;
016:
017: import org.apache.log4j.Category;
018:
019: /**
020: * This class represents queries that allow parameters to be set.
021: * It is primary used to construct queries that will be executed
022: * seperately, that is, it is up to the implementor of query classes
023: * to provided sort of a workflow for all queries. <br>
024: * All subclasses must implement method <tt>execute()</tt> where the
025: * <code>TKQuery</code> should be used to set and retrieve
026: * values of all queries (and subclasses of it).
027: * @see com.teamkonzept.db.TKPrepQuery
028: * @see java.sql.PreparedStatement
029: *
030: * @author $Author: alex $
031: * @version $Revision: 1.8 $
032: */
033: public abstract class TKExtendedPrepQuery extends TKPrepQuery {
034:
035: /** Logging Category */
036: static Category cat = Category
037: .getInstance(TKExtendedPrepQuery.class.getName());
038:
039: /**
040: * Contains all result set produced by this query class.
041: */
042: protected Vector results = null;
043:
044: /**
045: * Holds all atomic queries.
046: */
047: protected TKPrepQuery[] queries = null;
048:
049: /**
050: * Holds classes passed as argument to method <tt>init(Class[])</tt>.
051: * Used for caching.
052: */
053: private Class[] prevClasses = null;
054:
055: /**
056: * Adds a result set in order to reuse it (e.g. <tt>fetchResultSet()</tt>).
057: * @param rs das ResultSet was dazu soll
058: */
059: protected void addResult(ResultSet rs) {
060: if (rs != null) {
061: if (results == null) {
062: results = new Vector();
063: }
064: //results.push(rs);
065: results.addElement(rs);
066: }
067: }
068:
069: /**
070: * Adds one or more result set(s) in order to reuse it (e.g. <tt>fetchResultSet()</tt>).
071: */
072: protected void addResults(ResultSet[] rs) {
073: if (rs != null) {
074: if (results == null) {
075: results = new Vector();
076: }
077: for (int i = 0; i < rs.length; i++) {
078: //results.push(rs);
079: results.addElement(rs);
080: }
081: }
082: }
083:
084: /**
085: * This method is intended to be used for execution of multiple queries that
086: * may depend on each other. Since this method has been declared abstract
087: * all subclasses must provide an implementation and should control the
088: * logic by means of handling all dependencies of subsequent queries.
089: */
090: public abstract boolean execute() throws SQLException;
091:
092: /**
093: * Initializes query objects as given in an array of classes. Note
094: * that the classes objects should be an instance of TKPrepQuery.
095: */
096: protected void init(Class[] classes) throws SQLException,
097: ClassCastException {
098: if (classes == null) {
099: return;
100: }
101: if (prevClasses == null || !classes.equals(prevClasses)) {
102: prevClasses = classes;
103: queries = new TKPrepQuery[classes.length];
104: for (int i = 0; i < classes.length; i++) {
105: queries[i] = (TKPrepQuery) TKWebmanDBManager
106: .newQuery(classes[i]);
107: }
108: }
109: }
110:
111: /**
112: * Returns the current result set. Multiple calls of this
113: * method will return subsequent result sets.
114: * @return the current result set or <tt>null</tt> if no more
115: * result sets are available.
116: */
117: public ResultSet fetchResultSet() {
118: if (results != null && results.size() > 0) { // if we have at least one element
119: ResultSet tmp = (ResultSet) results.elementAt(0);
120: results.removeElementAt(0);
121: return tmp;
122: }
123: return null;
124: }
125:
126: /**
127: * Returns <code>true</code> if this (complex) query expects one
128: * or more results, <code>false</code> otherwise. That is, if at least
129: * one ResultSet has been added (with methods <code>addResult(ResultSet)</code>
130: * or <code>addResults(ResultSet[])</code>, respectively.
131: */
132: protected boolean hasResults() {
133: return results != null && results.size() > 0;
134: }
135:
136: /**
137: * Prints all parameters and type information stored in <code>queryParams</code>
138: * for each query to a <code>TKLog</code> stream only if
139: * <code>TKQuery.DEBUG</code> is set to true.
140: */
141: protected void debugParams() {
142: if (cat.isDebugEnabled()) {
143: if (paramOrder == null) {
144: cat.debug("paramOrder is null!");
145: return;
146: }
147: StringBuffer buf = new StringBuffer("Parameters of class ");
148: buf.append(getClass().getName());
149: String currentParamName = null;
150: Object currentParam = null;
151: buf.append(": {");
152: for (int i = 0; i < paramOrder.length; i++) {
153: currentParamName = paramOrder[i];
154: currentParam = queryParams.get(currentParamName);
155: buf.append(currentParamName);
156: buf.append("=");
157: buf.append(currentParam);
158: buf.append(" [type: ");
159: buf.append(currentParam.getClass().getName());
160: buf.append("]");
161: if (i < (paramOrder.length - 1)) {
162: buf.append(", ");
163: }
164: }
165: buf.append("}");
166: cat.debug(buf.toString());
167: }
168: }
169:
170: /**
171: * Returns all <code>TKPrepQuery</code> objects.
172: */
173: protected Enumeration queries() {
174: return new Enumeration() {
175: int count = 0;
176: int elementCount = queries.length;
177:
178: public boolean hasMoreElements() {
179: return count < elementCount;
180: }
181:
182: public Object nextElement() {
183: if (count < elementCount) {
184: return queries[count++].sqlString;
185: }
186: throw new NoSuchElementException(
187: "Statement Enumeration");
188: }
189: };
190: }
191:
192: /**
193: * Closes all queries associated with this extended query.
194: * @see com.teamkonzept.db.TKPrepQuery.close()
195: */
196: public void close() throws SQLException {
197: if (queries == null) {
198: return;
199: }
200: cat.debug("queries to close: " + queries.length);
201: for (int i = 0; i < queries.length; i++) {
202: queries[i].close();
203: }
204: cat.debug("queries closed");
205: }
206: }
|