KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > torque > util > BasePeer


1 package org.apache.torque.util;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements. See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership. The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License. You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied. See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */

21
22 import java.io.Serializable JavaDoc;
23 import java.sql.Connection JavaDoc;
24 import java.sql.PreparedStatement JavaDoc;
25 import java.sql.SQLException JavaDoc;
26 import java.sql.Statement JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Collections JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Set JavaDoc;
34
35 import org.apache.commons.lang.StringUtils;
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.apache.torque.Database;
39 import org.apache.torque.Torque;
40 import org.apache.torque.TorqueException;
41 import org.apache.torque.adapter.DB;
42 import org.apache.torque.map.ColumnMap;
43 import org.apache.torque.map.DatabaseMap;
44 import org.apache.torque.map.MapBuilder;
45 import org.apache.torque.map.TableMap;
46 import org.apache.torque.oid.IdGenerator;
47 import org.apache.torque.om.NumberKey;
48 import org.apache.torque.om.ObjectKey;
49 import org.apache.torque.om.SimpleKey;
50 import org.apache.torque.om.StringKey;
51
52 import com.workingdogs.village.Column;
53 import com.workingdogs.village.DataSet;
54 import com.workingdogs.village.DataSetException;
55 import com.workingdogs.village.KeyDef;
56 import com.workingdogs.village.QueryDataSet;
57 import com.workingdogs.village.Record;
58 import com.workingdogs.village.Schema;
59 import com.workingdogs.village.TableDataSet;
60
61 /**
62  * This is the base class for all Peer classes in the system. Peer
63  * classes are responsible for isolating all of the database access
64  * for a specific business object. They execute all of the SQL
65  * against the database. Over time this class has grown to include
66  * utility methods which ease execution of cross-database queries and
67  * the implementation of concrete Peers.
68  *
69  * @author <a HREF="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
70  * @author <a HREF="mailto:jmcnally@collab.net">John D. McNally</a>
71  * @author <a HREF="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
72  * @author <a HREF="mailto:stephenh@chase3000.com">Stephen Haberman</a>
73  * @author <a HREF="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
74  * @author <a HREF="mailto:vido@ldh.org">Augustin Vidovic</a>
75  * @author <a HREF="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
76  * @version $Id: BasePeer.java 493449 2007-01-06 11:46:50Z tv $
77  */

78 public abstract class BasePeer
79         implements Serializable JavaDoc
80 {
81     /** Constant criteria key to reference ORDER BY columns. */
82     public static final String JavaDoc ORDER_BY = "ORDER BY";
83
84     /**
85      * Constant criteria key to remove Case Information from
86      * search/ordering criteria.
87      */

88     public static final String JavaDoc IGNORE_CASE = "IgNOrE cAsE";
89
90     /** Classes that implement this class should override this value. */
91     public static final String JavaDoc TABLE_NAME = "TABLE_NAME";
92
93     /** the log */
94     protected static final Log log = LogFactory.getLog(BasePeer.class);
95
96     private static void throwTorqueException(Exception JavaDoc e)
97         throws TorqueException
98     {
99         if (e instanceof TorqueException)
100         {
101             throw (TorqueException) e;
102         }
103         else
104         {
105             throw new TorqueException(e);
106         }
107     }
108
109     /**
110      * Sets up a Schema for a table. This schema is then normally
111      * used as the argument for initTableColumns().
112      *
113      * @param tableName The name of the table.
114      * @return A Schema.
115      */

116     public static Schema initTableSchema(String JavaDoc tableName)
117     {
118         return initTableSchema(tableName, Torque.getDefaultDB());
119     }
120
121     /**
122      * Sets up a Schema for a table. This schema is then normally
123      * used as the argument for initTableColumns
124      *
125      * @param tableName The propery name for the database in the
126      * configuration file.
127      * @param dbName The name of the database.
128      * @return A Schema.
129      */

130     public static Schema initTableSchema(String JavaDoc tableName, String JavaDoc dbName)
131     {
132         Schema schema = null;
133         Connection JavaDoc con = null;
134
135         try
136         {
137             con = Torque.getConnection(dbName);
138             schema = new Schema().schema(con, tableName);
139         }
140         catch (Exception JavaDoc e)
141         {
142             log.error(e);
143             throw new Error JavaDoc("Error in BasePeer.initTableSchema("
144                     + tableName
145                     + "): "
146                     + e.getMessage());
147         }
148         finally
149         {
150             Torque.closeConnection(con);
151         }
152         return schema;
153     }
154
155     /**
156      * Creates a Column array for a table based on its Schema.
157      *
158      * @param schema A Schema object.
159      * @return A Column[].
160      */

161     public static Column[] initTableColumns(Schema schema)
162     {
163         Column[] columns = null;
164         try
165         {
166             int numberOfColumns = schema.numberOfColumns();
167             columns = new Column[numberOfColumns];
168             for (int i = 0; i < numberOfColumns; i++)
169             {
170                 columns[i] = schema.column(i + 1);
171             }
172         }
173         catch (Exception JavaDoc e)
174         {
175             log.error(e);
176             throw new Error JavaDoc(
177                 "Error in BasePeer.initTableColumns(): " + e.getMessage());
178         }
179         return columns;
180     }
181
182     /**
183      * Convenience method to create a String array of column names.
184      *
185      * @param columns A Column[].
186      * @return A String[].
187      */

188     public static String JavaDoc[] initColumnNames(Column[] columns)
189     {
190         String JavaDoc[] columnNames = new String JavaDoc[columns.length];
191         for (int i = 0; i < columns.length; i++)
192         {
193             columnNames[i] = columns[i].name().toUpperCase();
194         }
195         return columnNames;
196     }
197
198     /**
199      * Convenience method to create a String array of criteria keys.
200      *
201      * @param tableName Name of table.
202      * @param columnNames A String[].
203      * @return A String[].
204      */

205     public static String JavaDoc[] initCriteriaKeys(
206         String JavaDoc tableName,
207         String JavaDoc[] columnNames)
208     {
209         String JavaDoc[] keys = new String JavaDoc[columnNames.length];
210         for (int i = 0; i < columnNames.length; i++)
211         {
212             keys[i] = tableName + "." + columnNames[i].toUpperCase();
213         }
214         return keys;
215     }
216
217     /**
218      * Convenience method that uses straight JDBC to delete multiple
219      * rows. Village throws an Exception when multiple rows are
220      * deleted.
221      *
222      * @param con A Connection.
223      * @param table The table to delete records from.
224      * @param column The column in the where clause.
225      * @param value The value of the column.
226      * @throws TorqueException Any exceptions caught during processing will be
227      * rethrown wrapped into a TorqueException.
228      */

229     public static void deleteAll(
230         Connection JavaDoc con,
231         String JavaDoc table,
232         String JavaDoc column,
233         int value)
234         throws TorqueException
235     {
236         Statement JavaDoc statement = null;
237         try
238         {
239             statement = con.createStatement();
240
241             StringBuffer JavaDoc query = new StringBuffer JavaDoc();
242             query.append("DELETE FROM ")
243                 .append(table)
244                 .append(" WHERE ")
245                 .append(column)
246                 .append(" = ")
247                 .append(value);
248
249             statement.executeUpdate(query.toString());
250         }
251         catch (SQLException JavaDoc e)
252         {
253             throw new TorqueException(e);
254         }
255         finally
256         {
257             if (statement != null)
258             {
259                 try
260                 {
261                     statement.close();
262                 }
263                 catch (SQLException JavaDoc e)
264                 {
265                     throw new TorqueException(e);
266                 }
267             }
268         }
269     }
270
271     /**
272      * Convenience method that uses straight JDBC to delete multiple
273      * rows. Village throws an Exception when multiple rows are
274      * deleted. This method attempts to get the default database from
275      * the pool.
276      *
277      * @param table The table to delete records from.
278      * @param column The column in the where clause.
279      * @param value The value of the column.
280      * @throws TorqueException Any exceptions caught during processing will be
281      * rethrown wrapped into a TorqueException.
282      */

283     public static void deleteAll(String JavaDoc table, String JavaDoc column, int value)
284         throws TorqueException
285     {
286         Connection JavaDoc con = null;
287         try
288         {
289             // Get a connection to the db.
290
con = Torque.getConnection(Torque.getDefaultDB());
291             deleteAll(con, table, column, value);
292         }
293         finally
294         {
295             Torque.closeConnection(con);
296         }
297     }
298
299     /**
300      * Method to perform deletes based on values and keys in a
301      * Criteria.
302      *
303      * @param criteria The criteria to use.
304      * @throws TorqueException Any exceptions caught during processing will be
305      * rethrown wrapped into a TorqueException.
306      */

307     public static void doDelete(Criteria criteria) throws TorqueException
308     {
309         Connection JavaDoc con = null;
310         try
311         {
312             con = Transaction.beginOptional(
313                     criteria.getDbName(),
314                     criteria.isUseTransaction());
315             doDelete(criteria, con);
316             Transaction.commit(con);
317         }
318         catch (TorqueException e)
319         {
320             Transaction.safeRollback(con);
321             throw e;
322         }
323     }
324
325     /**
326      * Method to perform deletes based on values and keys in a Criteria.
327      *
328      * @param criteria The criteria to use.
329      * @param con A Connection.
330      * @throws TorqueException Any exceptions caught during processing will be
331      * rethrown wrapped into a TorqueException.
332      */

333     public static void doDelete(Criteria criteria, Connection JavaDoc con)
334         throws TorqueException
335     {
336         String JavaDoc dbName = criteria.getDbName();
337         final DatabaseMap dbMap = Torque.getDatabaseMap(dbName);
338
339         // This Callback adds all tables to the Table set which
340
// are referenced from a cascading criteria. As a result, all
341
// data that is referenced through foreign keys will also be
342
// deleted.
343
SQLBuilder.TableCallback tc = new SQLBuilder.TableCallback() {
344                 public void process (Set JavaDoc tables, String JavaDoc key, Criteria crit)
345                 {
346                     if (crit.isCascade())
347                     {
348                         // This steps thru all the columns in the database.
349
TableMap[] tableMaps = dbMap.getTables();
350                         for (int i = 0; i < tableMaps.length; i++)
351                         {
352                             ColumnMap[] columnMaps = tableMaps[i].getColumns();
353
354                             for (int j = 0; j < columnMaps.length; j++)
355                             {
356                                 // Only delete rows where the foreign key is
357
// also a primary key. Other rows need
358
// updating, but that is not implemented.
359
if (columnMaps[j].isForeignKey()
360                                         && columnMaps[j].isPrimaryKey()
361                                         && key.equals(columnMaps[j].getRelatedName()))
362                                 {
363                                     tables.add(tableMaps[i].getName());
364                                     crit.add(columnMaps[j].getFullyQualifiedName(),
365                                             crit.getValue(key));
366                                 }
367                             }
368                         }
369                     }
370                 }
371             };
372
373         Set JavaDoc tables = SQLBuilder.getTableSet(criteria, tc);
374
375         try
376         {
377             processTables(criteria, tables, con, new ProcessCallback() {
378                     public void process(String JavaDoc table, String JavaDoc dbName, Record rec)
379                         throws Exception JavaDoc
380                     {
381                         rec.markToBeDeleted();
382                         rec.save();
383                     }
384                 });
385         }
386         catch (Exception JavaDoc e)
387         {
388             throwTorqueException(e);
389         }
390     }
391
392     /**
393      * Method to perform inserts based on values and keys in a
394      * Criteria.
395      * <p>
396      * If the primary key is auto incremented the data in Criteria
397      * will be inserted and the auto increment value will be returned.
398      * <p>
399      * If the primary key is included in Criteria then that value will
400      * be used to insert the row.
401      * <p>
402      * If no primary key is included in Criteria then we will try to
403      * figure out the primary key from the database map and insert the
404      * row with the next available id using util.db.IDBroker.
405      * <p>
406      * If no primary key is defined for the table the values will be
407      * inserted as specified in Criteria and -1 will be returned.
408      *
409      * @param criteria Object containing values to insert.
410      * @return An Object which is the id of the row that was inserted
411      * (if the table has a primary key) or null (if the table does not
412      * have a primary key).
413      * @throws TorqueException Any exceptions caught during processing will be
414      * rethrown wrapped into a TorqueException.
415      */

416     public static ObjectKey doInsert(Criteria criteria) throws TorqueException
417     {
418         Connection JavaDoc con = null;
419         ObjectKey id = null;
420
421         try
422         {
423             con = Transaction.beginOptional(
424                     criteria.getDbName(),
425                     criteria.isUseTransaction());
426             id = doInsert(criteria, con);
427             Transaction.commit(con);
428         }
429         catch (TorqueException e)
430         {
431             Transaction.safeRollback(con);
432             throw e;
433         }
434
435         return id;
436     }
437
438     /**
439      * Method to perform inserts based on values and keys in a
440      * Criteria.
441      * <p>
442      * If the primary key is auto incremented the data in Criteria
443      * will be inserted and the auto increment value will be returned.
444      * <p>
445      * If the primary key is included in Criteria then that value will
446      * be used to insert the row.
447      * <p>
448      * If no primary key is included in Criteria then we will try to
449      * figure out the primary key from the database map and insert the
450      * row with the next available id using util.db.IDBroker.
451      * <p>
452      * If no primary key is defined for the table the values will be
453      * inserted as specified in Criteria and null will be returned.
454      *
455      * @param criteria Object containing values to insert.
456      * @param con A Connection.
457      * @return An Object which is the id of the row that was inserted
458      * (if the table has a primary key) or null (if the table does not
459      * have a primary key).
460      * @throws TorqueException Any exceptions caught during processing will be
461      * rethrown wrapped into a TorqueException.
462      */

463     public static ObjectKey doInsert(Criteria criteria, Connection JavaDoc con)
464         throws TorqueException
465     {
466         SimpleKey id = null;
467
468         // Get the table name and method for determining the primary
469
// key value.
470
String JavaDoc table = null;
471         Iterator JavaDoc keys = criteria.keySet().iterator();
472         if (keys.hasNext())
473         {
474             table = criteria.getTableName((String JavaDoc) keys.next());
475         }
476         else
477         {
478             throw new TorqueException("Database insert attempted without "
479                     + "anything specified to insert");
480         }
481
482         String JavaDoc dbName = criteria.getDbName();
483         Database database = Torque.getDatabase(dbName);
484         DatabaseMap dbMap = database.getDatabaseMap();
485         TableMap tableMap = dbMap.getTable(table);
486         Object JavaDoc keyInfo = tableMap.getPrimaryKeyMethodInfo();
487         IdGenerator keyGen
488                 = database.getIdGenerator(tableMap.getPrimaryKeyMethod());
489
490         ColumnMap pk = getPrimaryKey(criteria);
491
492         // If the keyMethod is SEQUENCE or IDBROKERTABLE, get the id
493
// before the insert.
494
if (keyGen != null && keyGen.isPriorToInsert())
495         {
496             // pk will be null if there is no primary key defined for the table
497
// we're inserting into.
498
if (pk != null && !criteria.containsKey(pk.getFullyQualifiedName()))
499             {
500                 id = getId(pk, keyGen, con, keyInfo);
501                 criteria.add(pk.getFullyQualifiedName(), id);
502             }
503         }
504
505         // Use Village to perform the insert.
506
TableDataSet tds = null;
507         try
508         {
509             String JavaDoc tableName = SQLBuilder.getFullTableName(table, dbName);
510             tds = new TableDataSet(con, tableName);
511             Record rec = tds.addRecord();
512             // not the fully qualified name, insertOrUpdateRecord wants to use table as an index...
513
BasePeer.insertOrUpdateRecord(rec, table, dbName, criteria);
514         }
515         catch (DataSetException e)
516         {
517             throwTorqueException(e);
518         }
519         catch (SQLException JavaDoc e)
520         {
521             throwTorqueException(e);
522         }
523         catch (TorqueException e)
524         {
525             throwTorqueException(e);
526         }
527         finally
528         {
529             VillageUtils.close(tds);
530         }
531
532         // If the primary key column is auto-incremented, get the id
533
// now.
534
if (keyGen != null && keyGen.isPostInsert())
535         {
536             id = getId(pk, keyGen, con, keyInfo);
537         }
538
539         return id;
540     }
541
542     /**
543      * Create an Id for insertion in the Criteria
544      *
545      * @param pk ColumnMap for the Primary key
546      * @param keyGen The Id Generator object
547      * @param con The SQL Connection to run the id generation under
548      * @param keyInfo KeyInfo Parameter from the Table map
549      *
550      * @return A simple Key representing the new Id value
551      * @throws TorqueException Possible errors get wrapped in here.
552      */

553     private static SimpleKey getId(ColumnMap pk, IdGenerator keyGen, Connection JavaDoc con, Object JavaDoc keyInfo)
554             throws TorqueException
555     {
556         SimpleKey id = null;
557
558         try
559         {
560             if (pk != null && keyGen != null)
561             {
562                 if (pk.getType() instanceof Number JavaDoc)
563                 {
564                     id = new NumberKey(
565                             keyGen.getIdAsBigDecimal(con, keyInfo));
566                 }
567                 else
568                 {
569                     id = new StringKey(keyGen.getIdAsString(con, keyInfo));
570                 }
571             }
572         }
573         catch (Exception JavaDoc e)
574         {
575             throwTorqueException(e);
576         }
577         return id;
578     }
579
580     /**
581      * Grouping of code used in both doInsert() and doUpdate()
582      * methods. Sets up a Record for saving.
583      *
584      * @param rec A Record.
585      * @param table Name of table.
586      * @param criteria A Criteria.
587      * @throws TorqueException Any exceptions caught during processing will be
588      * rethrown wrapped into a TorqueException.
589      */

590     private static void insertOrUpdateRecord(
591         Record rec,
592         String JavaDoc table,
593         String JavaDoc dbName,
594         Criteria criteria)
595         throws TorqueException
596     {
597         DatabaseMap dbMap = Torque.getDatabaseMap(dbName);
598
599         ColumnMap[] columnMaps = dbMap.getTable(table).getColumns();
600         boolean shouldSave = false;
601         for (int j = 0; j < columnMaps.length; j++)
602         {
603             ColumnMap colMap = columnMaps[j];
604             String JavaDoc colName = colMap.getColumnName();
605             String JavaDoc key = new StringBuffer JavaDoc(colMap.getTableName())
606                     .append('.')
607                     .append(colName)
608                     .toString();
609             if (criteria.containsKey(key))
610             {
611                 try
612                 {
613                     VillageUtils.setVillageValue(criteria, key, rec, colName);
614                     shouldSave = true;
615                 }
616                 catch (Exception JavaDoc e)
617                 {
618                     throwTorqueException(e);
619                 }
620             }
621         }
622
623         if (shouldSave)
624         {
625             try
626             {
627                 rec.save();
628             }
629             catch (Exception JavaDoc e)
630             {
631                 throwTorqueException(e);
632             }
633         }
634         else
635         {
636             throw new TorqueException("No changes to save");
637         }
638     }
639
640     /**
641      * Method to create an SQL query for display only based on values in a
642      * Criteria.
643      *
644      * @param criteria A Criteria.
645      * @return the SQL query for display
646      * @exception TorqueException Trouble creating the query string.
647      */

648     static String JavaDoc createQueryDisplayString(Criteria criteria)
649         throws TorqueException
650     {
651         return createQuery(criteria).toString();
652     }
653
654     /**
655      * Method to create an SQL query for actual execution based on values in a
656      * Criteria.
657      *
658      * @param criteria A Criteria.
659      * @return the SQL query for actual execution
660      * @exception TorqueException Trouble creating the query string.
661      */

662     public static String JavaDoc createQueryString(Criteria criteria)
663         throws TorqueException
664     {
665         Query query = createQuery(criteria);
666         return query.toString();
667     }
668
669     /**
670      * Method to create an SQL query based on values in a Criteria. Note that
671      * final manipulation of the limit and offset are performed when the query
672      * is actually executed.
673      *
674      * @param criteria A Criteria.
675      * @return the sql query
676      * @exception TorqueException Trouble creating the query string.
677      */

678     static Query createQuery(Criteria criteria)
679         throws TorqueException
680     {
681         return SQLBuilder.buildQueryClause(criteria, null, new SQLBuilder.QueryCallback() {
682                 public String JavaDoc process(Criteria.Criterion criterion, List JavaDoc params)
683                 {
684                     return criterion.toString();
685                 }
686             });
687     }
688
689     /**
690      * Returns all results.
691      *
692      * @param criteria A Criteria.
693      * @return List of Record objects.
694      * @throws TorqueException Any exceptions caught during processing will be
695      * rethrown wrapped into a TorqueException.
696      */

697     public static List JavaDoc doSelect(Criteria criteria) throws TorqueException
698     {
699         Connection JavaDoc con = null;
700         List JavaDoc results = null;
701
702         try
703         {
704             con = Transaction.beginOptional(
705                     criteria.getDbName(),
706                     criteria.isUseTransaction());
707             results = doSelect(criteria, con);
708             Transaction.commit(con);
709         }
710         catch (TorqueException e)
711         {
712             Transaction.safeRollback(con);
713             throw e;
714         }
715         return results;
716     }
717
718     /**
719      * Returns all results.
720      *
721      * @param criteria A Criteria.
722      * @param con A Connection.
723      * @return List of Record objects.
724      * @throws TorqueException Any exceptions caught during processing will be
725      * rethrown wrapped into a TorqueException.
726      */

727     public static List JavaDoc doSelect(Criteria criteria, Connection JavaDoc con)
728         throws TorqueException
729     {
730         Query query = createQuery(criteria);
731         DB dbadapter = Torque.getDB(criteria.getDbName());
732
733         // Call Village depending on the capabilities of the DB
734
return executeQuery(query.toString(),
735                 dbadapter.supportsNativeOffset() ? 0 : criteria.getOffset(),
736                 dbadapter.supportsNativeLimit() ? -1 : criteria.getLimit(),
737                 criteria.isSingleRecord(),
738                 con);
739     }
740
741     /**
742      * Utility method which executes a given sql statement. This
743      * method should be used for select statements only. Use
744      * executeStatement for update, insert, and delete operations.
745      *
746      * @param queryString A String with the sql statement to execute.
747      * @return List of Record objects.
748      * @throws TorqueException Any exceptions caught during processing will be
749      * rethrown wrapped into a TorqueException.
750      */

751     public static List JavaDoc executeQuery(String JavaDoc queryString) throws TorqueException
752     {
753         return executeQuery(queryString, Torque.getDefaultDB(), false);
754     }
755
756     /**
757      * Utility method which executes a given sql statement. This
758      * method should be used for select statements only. Use
759      * executeStatement for update, insert, and delete operations.
760      *
761      * @param queryString A String with the sql statement to execute.
762      * @param dbName The database to connect to.
763      * @return List of Record objects.
764      * @throws TorqueException Any exceptions caught during processing will be
765      * rethrown wrapped into a TorqueException.
766      */

767     public static List JavaDoc executeQuery(String JavaDoc queryString, String JavaDoc dbName)
768         throws TorqueException
769     {
770         return executeQuery(queryString, dbName, false);
771     }
772
773     /**
774      * Method for performing a SELECT. Returns all results.
775      *
776      * @param queryString A String with the sql statement to execute.
777      * @param dbName The database to connect to.
778      * @param singleRecord Whether or not we want to select only a
779      * single record.
780      * @return List of Record objects.
781      * @throws TorqueException Any exceptions caught during processing will be
782      * rethrown wrapped into a TorqueException.
783      */

784     public static List JavaDoc executeQuery(
785         String JavaDoc queryString,
786         String JavaDoc dbName,
787         boolean singleRecord)
788         throws TorqueException
789     {
790         return executeQuery(queryString, 0, -1, dbName, singleRecord);
791     }
792
793     /**
794      * Method for performing a SELECT. Returns all results.
795      *
796      * @param queryString A String with the sql statement to execute.
797      * @param singleRecord Whether or not we want to select only a
798      * single record.
799      * @param con A Connection.
800      * @return List of Record objects.
801      * @throws TorqueException Any exceptions caught during processing will be
802      * rethrown wrapped into a TorqueException.
803      */

804     public static List JavaDoc executeQuery(
805         String JavaDoc queryString,
806         boolean singleRecord,
807         Connection JavaDoc con)
808         throws TorqueException
809     {
810         return executeQuery(queryString, 0, -1, singleRecord, con);
811     }
812
813     /**
814      * Method for performing a SELECT.
815      *
816      * @param queryString A String with the sql statement to execute.
817      * @param start The first row to return.
818      * @param numberOfResults The number of rows to return.
819      * @param dbName The database to connect to.
820      * @param singleRecord Whether or not we want to select only a
821      * single record.
822      * @return List of Record objects.
823      * @throws TorqueException Any exceptions caught during processing will be
824      * rethrown wrapped into a TorqueException.
825      */

826     public static List JavaDoc executeQuery(
827         String JavaDoc queryString,
828         int start,
829         int numberOfResults,
830         String JavaDoc dbName,
831         boolean singleRecord)
832         throws TorqueException
833     {
834         Connection JavaDoc con = null;
835         List JavaDoc results = null;
836         try
837         {
838             con = Torque.getConnection(dbName);
839             // execute the query
840
results = executeQuery(
841                     queryString,
842                     start,
843                     numberOfResults,
844                     singleRecord,
845                     con);
846         }
847         finally
848         {
849             Torque.closeConnection(con);
850         }
851         return results;
852     }
853
854     /**
855      * Method for performing a SELECT. Returns all results.
856      *
857      * @param queryString A String with the sql statement to execute.
858      * @param start The first row to return.
859      * @param numberOfResults The number of rows to return.
860      * @param singleRecord Whether or not we want to select only a
861      * single record.
862      * @param con A Connection.
863      * @return List of Record objects.
864      * @throws TorqueException Any exceptions caught during processing will be
865      * rethrown wrapped into a TorqueException.
866      */

867     public static List JavaDoc executeQuery(
868         String JavaDoc queryString,
869         int start,
870         int numberOfResults,
871         boolean singleRecord,
872         Connection JavaDoc con)
873         throws TorqueException
874     {
875         QueryDataSet qds = null;
876         List JavaDoc results = Collections.EMPTY_LIST;
877         try
878         {
879             // execute the query
880
long startTime = System.currentTimeMillis();
881             qds = new QueryDataSet(con, queryString);
882             if (log.isDebugEnabled())
883             {
884                 log.debug("Elapsed time="
885                         + (System.currentTimeMillis() - startTime) + " ms");
886             }
887             results = getSelectResults(
888                     qds, start, numberOfResults, singleRecord);
889         }
890         catch (DataSetException e)
891         {
892             throwTorqueException(e);
893         }
894         catch (SQLException JavaDoc e)
895         {
896             throwTorqueException(e);
897         }
898         finally
899         {
900             VillageUtils.close(qds);
901         }
902         return results;
903     }
904
905     /**
906      * Returns all records in a QueryDataSet as a List of Record
907      * objects. Used for functionality like util.LargeSelect.
908      *
909      * @see #getSelectResults(QueryDataSet, int, int, boolean)
910      * @param qds the QueryDataSet
911      * @return a List of Record objects
912      * @throws TorqueException Any exceptions caught during processing will be
913      * rethrown wrapped into a TorqueException.
914      */

915     public static List JavaDoc getSelectResults(QueryDataSet qds)
916         throws TorqueException
917     {
918         return getSelectResults(qds, 0, -1, false);
919     }
920
921     /**
922      * Returns all records in a QueryDataSet as a List of Record
923      * objects. Used for functionality like util.LargeSelect.
924      *
925      * @see #getSelectResults(QueryDataSet, int, int, boolean)
926      * @param qds the QueryDataSet
927      * @param singleRecord
928      * @return a List of Record objects
929      * @throws TorqueException Any exceptions caught during processing will be
930      * rethrown wrapped into a TorqueException.
931      */

932     public static List JavaDoc getSelectResults(QueryDataSet qds, boolean singleRecord)
933         throws TorqueException
934     {
935         return getSelectResults(qds, 0, -1, singleRecord);
936     }
937
938     /**
939      * Returns numberOfResults records in a QueryDataSet as a List
940      * of Record objects. Starting at record 0. Used for
941      * functionality like util.LargeSelect.
942      *
943      * @see #getSelectResults(QueryDataSet, int, int, boolean)
944      * @param qds the QueryDataSet
945      * @param numberOfResults
946      * @param singleRecord
947      * @return a List of Record objects
948      * @throws TorqueException Any exceptions caught during processing will be
949      * rethrown wrapped into a TorqueException.
950      */

951     public static List JavaDoc getSelectResults(
952         QueryDataSet qds,
953         int numberOfResults,
954         boolean singleRecord)
955         throws TorqueException
956     {
957         List JavaDoc results = null;
958         if (numberOfResults != 0)
959         {
960             results = getSelectResults(qds, 0, numberOfResults, singleRecord);
961         }
962         return results;
963     }
964
965     /**
966      * Returns numberOfResults records in a QueryDataSet as a List
967      * of Record objects. Starting at record start. Used for
968      * functionality like util.LargeSelect.
969      *
970      * @param qds The <code>QueryDataSet</code> to extract results
971      * from.
972      * @param start The index from which to start retrieving
973      * <code>Record</code> objects from the data set.
974      * @param numberOfResults The number of results to return (or
975      * <code> -1</code> for all results).
976      * @param singleRecord Whether or not we want to select only a
977      * single record.
978      * @return A <code>List</code> of <code>Record</code> objects.
979      * @exception TorqueException If any <code>Exception</code> occurs.
980      */

981     public static List JavaDoc getSelectResults(
982         QueryDataSet qds,
983         int start,
984         int numberOfResults,
985         boolean singleRecord)
986         throws TorqueException
987     {
988         List JavaDoc results = null;
989         try
990         {
991             if (numberOfResults < 0)
992             {
993                 results = new ArrayList JavaDoc();
994                 qds.fetchRecords();
995             }
996             else
997             {
998                 results = new ArrayList JavaDoc(numberOfResults);
999                 qds.fetchRecords(start, numberOfResults);
1000            }
1001
1002            int startRecord = 0;
1003
1004            //Offset the correct number of records
1005
if (start > 0 && numberOfResults <= 0)
1006            {
1007                startRecord = start;
1008            }
1009
1010            // Return a List of Record objects.
1011
for (int i = startRecord; i < qds.size(); i++)
1012            {
1013                Record rec = qds.getRecord(i);
1014                results.add(rec);
1015            }
1016
1017            if (results.size() > 1 && singleRecord)
1018            {
1019                handleMultipleRecords(qds);
1020            }
1021        }
1022        catch (Exception JavaDoc e)
1023        {
1024            throwTorqueException(e);
1025        }
1026        return results;
1027    }
1028
1029    /**
1030     * Helper method which returns the primary key contained
1031     * in the given Criteria object.
1032     *
1033     * @param criteria A Criteria.
1034     * @return ColumnMap if the Criteria object contains a primary
1035     * key, or null if it doesn't.
1036     * @throws TorqueException Any exceptions caught during processing will be
1037     * rethrown wrapped into a TorqueException.
1038     */

1039    private static ColumnMap getPrimaryKey(Criteria criteria)
1040        throws TorqueException
1041    {
1042        // Assume all the keys are for the same table.
1043
String JavaDoc key = (String JavaDoc) criteria.keys().nextElement();
1044
1045        String JavaDoc table = criteria.getTableName(key);
1046        ColumnMap pk = null;
1047
1048        if (!table.equals(""))
1049        {
1050            DatabaseMap dbMap = Torque.getDatabaseMap(criteria.getDbName());
1051            if (dbMap == null)
1052            {
1053                throw new TorqueException("dbMap is null");
1054            }
1055            if (dbMap.getTable(table) == null)
1056            {
1057                throw new TorqueException("dbMap.getTable() is null");
1058            }
1059
1060            ColumnMap[] columns = dbMap.getTable(table).getColumns();
1061
1062            for (int i = 0; i < columns.length; i++)
1063            {
1064                if (columns[i].isPrimaryKey())
1065                {
1066                    pk = columns[i];
1067                    break;
1068                }
1069            }
1070        }
1071        return pk;
1072    }
1073
1074    /**
1075     * Convenience method used to update rows in the DB. Checks if a
1076     * <i>single</i> int primary key is specified in the Criteria
1077     * object and uses it to perform the udpate. If no primary key is
1078     * specified an Exception will be thrown.
1079     * <p>
1080     * Use this method for performing an update of the kind:
1081     * <p>
1082     * "WHERE primary_key_id = an int"
1083     * <p>
1084     * To perform an update with non-primary key fields in the WHERE
1085     * clause use doUpdate(criteria, criteria).
1086     *
1087     * @param updateValues A Criteria object containing values used in
1088     * set clause.
1089     * @throws TorqueException Any exceptions caught during processing will be
1090     * rethrown wrapped into a TorqueException.
1091     */

1092    public static void doUpdate(Criteria updateValues) throws TorqueException
1093    {
1094        Connection JavaDoc con = null;
1095        try
1096        {
1097            con = Transaction.beginOptional(
1098                    updateValues.getDbName(),
1099                    updateValues.isUseTransaction());
1100            doUpdate(updateValues, con);
1101            Transaction.commit(con);
1102        }
1103        catch (TorqueException e)
1104        {
1105            Transaction.safeRollback(con);
1106            throw e;
1107        }
1108    }
1109
1110    /**
1111     * Convenience method used to update rows in the DB. Checks if a
1112     * <i>single</i> int primary key is specified in the Criteria
1113     * object and uses it to perform the udpate. If no primary key is
1114     * specified an Exception will be thrown.
1115     * <p>
1116     * Use this method for performing an update of the kind:
1117     * <p>
1118     * "WHERE primary_key_id = an int"
1119     * <p>
1120     * To perform an update with non-primary key fields in the WHERE
1121     * clause use doUpdate(criteria, criteria).
1122     *
1123     * @param updateValues A Criteria object containing values used in
1124     * set clause.
1125     * @param con A Connection.
1126     * @throws TorqueException Any exceptions caught during processing will be
1127     * rethrown wrapped into a TorqueException.
1128     */

1129    public static void doUpdate(Criteria updateValues, Connection JavaDoc con)
1130        throws TorqueException
1131    {
1132        ColumnMap pk = getPrimaryKey(updateValues);
1133        Criteria selectCriteria = null;
1134
1135        if (pk != null && updateValues.containsKey(pk.getFullyQualifiedName()))
1136        {
1137            selectCriteria = new Criteria(2);
1138            selectCriteria.put(pk.getFullyQualifiedName(),
1139                updateValues.remove(pk.getFullyQualifiedName()));
1140        }
1141        else
1142        {
1143            throw new TorqueException("No PK specified for database update");
1144        }
1145
1146        doUpdate(selectCriteria, updateValues, con);
1147    }
1148
1149    /**
1150     * Method used to update rows in the DB. Rows are selected based
1151     * on selectCriteria and updated using values in updateValues.
1152     * <p>
1153     * Use this method for performing an update of the kind:
1154     * <p>
1155     * WHERE some_column = some value AND could_have_another_column =
1156     * another value AND so on...
1157     *
1158     * @param selectCriteria A Criteria object containing values used in where
1159     * clause.
1160     * @param updateValues A Criteria object containing values used in set
1161     * clause.
1162     * @throws TorqueException Any exceptions caught during processing will be
1163     * rethrown wrapped into a TorqueException.
1164     */

1165    public static void doUpdate(Criteria selectCriteria, Criteria updateValues)
1166        throws TorqueException
1167    {
1168        Connection JavaDoc con = null;
1169        try
1170        {
1171            con = Transaction.beginOptional(
1172                    selectCriteria.getDbName(),
1173                    updateValues.isUseTransaction());
1174            doUpdate(selectCriteria, updateValues, con);
1175            Transaction.commit(con);
1176        }
1177        catch (TorqueException e)
1178        {
1179            Transaction.safeRollback(con);
1180            throw e;
1181        }
1182    }
1183
1184    /**
1185     * Method used to update rows in the DB. Rows are selected based
1186     * on criteria and updated using values in updateValues.
1187     * <p>
1188     * Use this method for performing an update of the kind:
1189     * <p>
1190     * WHERE some_column = some value AND could_have_another_column =
1191     * another value AND so on.
1192     *
1193     * @param criteria A Criteria object containing values used in where
1194     * clause.
1195     * @param updateValues A Criteria object containing values used in set
1196     * clause.
1197     * @param con A Connection.
1198     * @throws TorqueException Any exceptions caught during processing will be
1199     * rethrown wrapped into a TorqueException.
1200     */

1201    public static void doUpdate(
1202        Criteria criteria,
1203        final Criteria updateValues,
1204        Connection JavaDoc con)
1205        throws TorqueException
1206    {
1207        Set JavaDoc tables = SQLBuilder.getTableSet(criteria, null);
1208
1209        try
1210        {
1211            processTables(criteria, tables, con, new ProcessCallback() {
1212                    public void process (String JavaDoc table, String JavaDoc dbName, Record rec)
1213                        throws Exception JavaDoc
1214                    {
1215                        // Callback must be called with table name without Schema!
1216
BasePeer.insertOrUpdateRecord(rec, table, dbName, updateValues);
1217                    }
1218                });
1219        }
1220        catch (Exception JavaDoc e)
1221        {
1222            throwTorqueException(e);
1223        }
1224    }
1225
1226    /**
1227     * Utility method which executes a given sql statement. This
1228     * method should be used for update, insert, and delete
1229     * statements. Use executeQuery() for selects.
1230     *
1231     * @param statementString A String with the sql statement to execute.
1232     * @return The number of rows affected.
1233     * @throws TorqueException Any exceptions caught during processing will be
1234     * rethrown wrapped into a TorqueException.
1235     */

1236    public static int executeStatement(String JavaDoc statementString) throws TorqueException
1237    {
1238        return executeStatement(statementString, Torque.getDefaultDB());
1239    }
1240
1241    /**
1242     * Utility method which executes a given sql statement. This
1243     * method should be used for update, insert, and delete
1244     * statements. Use executeQuery() for selects.
1245     *
1246     * @param statementString A String with the sql statement to execute.
1247     * @param dbName Name of database to connect to.
1248     * @return The number of rows affected.
1249     * @throws TorqueException Any exceptions caught during processing will be
1250     * rethrown wrapped into a TorqueException.
1251     */

1252    public static int executeStatement(String JavaDoc statementString, String JavaDoc dbName)
1253        throws TorqueException
1254    {
1255        Connection JavaDoc con = null;
1256        int rowCount = -1;
1257        try
1258        {
1259            con = Torque.getConnection(dbName);
1260            rowCount = executeStatement(statementString, con);
1261        }
1262        finally
1263        {
1264            Torque.closeConnection(con);
1265        }
1266        return rowCount;
1267    }
1268
1269    /**
1270     * Utility method which executes a given sql statement. This
1271     * method should be used for update, insert, and delete
1272     * statements. Use executeQuery() for selects.
1273     *
1274     * @param statementString A String with the sql statement to execute.
1275     * @param con A Connection.
1276     * @return The number of rows affected.
1277     * @throws TorqueException Any exceptions caught during processing will be
1278     * rethrown wrapped into a TorqueException.
1279     */

1280    public static int executeStatement(String JavaDoc statementString, Connection JavaDoc con)
1281        throws TorqueException
1282    {
1283        int rowCount = -1;
1284        Statement JavaDoc statement = null;
1285        try
1286        {
1287            statement = con.createStatement();
1288            rowCount = statement.executeUpdate(statementString);
1289        }
1290        catch (SQLException JavaDoc e)
1291        {
1292            throw new TorqueException(e);
1293        }
1294        finally
1295        {
1296            if (statement != null)
1297            {
1298                try
1299                {
1300                    statement.close();
1301                }
1302                catch (SQLException JavaDoc e)
1303                {
1304                    throw new TorqueException(e);
1305                }
1306            }
1307        }
1308        return rowCount;
1309    }
1310
1311    /**
1312     * If the user specified that (s)he only wants to retrieve a
1313     * single record and multiple records are retrieved, this method
1314     * is called to handle the situation. The default behavior is to
1315     * throw an exception, but subclasses can override this method as
1316     * needed.
1317     *
1318     * @param ds The DataSet which contains multiple records.
1319     * @exception TorqueException Couldn't handle multiple records.
1320     */

1321    protected static void handleMultipleRecords(DataSet ds)
1322        throws TorqueException
1323    {
1324        throw new TorqueException("Criteria expected single Record and "
1325                + "Multiple Records were selected");
1326    }
1327
1328    /**
1329     * This method returns the MapBuilder specified in the name
1330     * parameter. You should pass in the full path to the class, ie:
1331     * org.apache.torque.util.db.map.TurbineMapBuilder. The
1332     * MapBuilder instances are cached in the TorqueInstance for speed.
1333     *
1334     * @param name name of the MapBuilder
1335     * @return A MapBuilder, not null
1336     * @throws TorqueException if the Map Builder cannot be instantiated
1337     * @deprecated Use Torque.getMapBuilder(name) instead
1338     */

1339    public static MapBuilder getMapBuilder(String JavaDoc name)
1340        throws TorqueException
1341    {
1342        return Torque.getMapBuilder(name);
1343    }
1344
1345    /**
1346     * Performs a SQL <code>select</code> using a PreparedStatement.
1347     * Note: this method does not handle null criteria values.
1348     *
1349     * @param criteria
1350     * @param con
1351     * @return a List of Record objects.
1352     * @throws TorqueException Error performing database query.
1353     */

1354    public static List JavaDoc doPSSelect(Criteria criteria, Connection JavaDoc con)
1355        throws TorqueException
1356    {
1357        List JavaDoc v = null;
1358
1359        StringBuffer JavaDoc qry = new StringBuffer JavaDoc();
1360        List JavaDoc params = new ArrayList JavaDoc(criteria.size());
1361
1362        createPreparedStatement(criteria, qry, params);
1363
1364        PreparedStatement JavaDoc statement = null;
1365        try
1366        {
1367            statement = con.prepareStatement(qry.toString());
1368
1369            for (int i = 0; i < params.size(); i++)
1370            {
1371                Object JavaDoc param = params.get(i);
1372                if (param instanceof java.sql.Date JavaDoc)
1373                {
1374                    statement.setDate(i + 1, (java.sql.Date JavaDoc) param);
1375                }
1376                else if (param instanceof NumberKey)
1377                {
1378                    statement.setBigDecimal(i + 1,
1379                        ((NumberKey) param).getBigDecimal());
1380                }
1381                else
1382                {
1383                    statement.setString(i + 1, param.toString());
1384                }
1385            }
1386
1387            QueryDataSet qds = null;
1388            try
1389            {
1390                qds = new QueryDataSet(statement.executeQuery());
1391                v = getSelectResults(qds);
1392            }
1393            finally
1394            {
1395                VillageUtils.close(qds);
1396            }
1397        }
1398        catch (DataSetException e)
1399        {
1400            throwTorqueException(e);
1401        }
1402        catch (SQLException JavaDoc e)
1403        {
1404            throwTorqueException(e);
1405        }
1406        finally
1407        {
1408            if (statement != null)
1409            {
1410                try
1411                {
1412                    statement.close();
1413                }
1414                catch (SQLException JavaDoc e)
1415                {
1416                    throw new TorqueException(e);
1417                }
1418            }
1419        }
1420        return v;
1421    }
1422
1423    /**
1424     * Do a Prepared Statement select according to the given criteria
1425     *
1426     * @param criteria
1427     * @return a List of Record objects.
1428     * @throws TorqueException Any exceptions caught during processing will be
1429     * rethrown wrapped into a TorqueException.
1430     */

1431    public static List JavaDoc doPSSelect(Criteria criteria) throws TorqueException
1432    {
1433        Connection JavaDoc con = Torque.getConnection(criteria.getDbName());
1434        List JavaDoc v = null;
1435
1436        try
1437        {
1438            v = doPSSelect(criteria, con);
1439        }
1440        finally
1441        {
1442            Torque.closeConnection(con);
1443        }
1444        return v;
1445    }
1446
1447    /**
1448     * Create a new PreparedStatement. It builds a string representation
1449     * of a query and a list of PreparedStatement parameters.
1450     *
1451     * @param criteria
1452     * @param queryString
1453     * @param params
1454     * @throws TorqueException Any exceptions caught during processing will be
1455     * rethrown wrapped into a TorqueException.
1456     */

1457    public static void createPreparedStatement(
1458        Criteria criteria,
1459        StringBuffer JavaDoc queryString,
1460        List JavaDoc params)
1461        throws TorqueException
1462    {
1463        Query query = SQLBuilder.buildQueryClause(criteria, params, new SQLBuilder.QueryCallback() {
1464                public String JavaDoc process(Criteria.Criterion criterion, List JavaDoc params)
1465                {
1466                    StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1467                    criterion.appendPsTo(sb, params);
1468                    return sb.toString();
1469                }
1470            });
1471
1472        String JavaDoc sql = query.toString();
1473        log.debug(sql);
1474
1475        queryString.append(sql);
1476    }
1477
1478    /**
1479     * Checks all columns in the criteria to see whether
1480     * booleanchar and booleanint columns are queried with a boolean.
1481     * If yes, the query values are mapped onto values the database
1482     * does understand, i.e. 0 and 1 for booleanints and N and Y for
1483     * booleanchar columns.
1484     *
1485     * @param criteria The criteria to be checked for booleanint and booleanchar
1486     * columns.
1487     * @param defaultTableMap the table map to be used if the table name is
1488     * not given in a column.
1489     * @throws TorqueException if the database map for the criteria cannot be
1490     * retrieved.
1491     */

1492    public static void correctBooleans(
1493            Criteria criteria,
1494            TableMap defaultTableMap)
1495        throws TorqueException
1496    {
1497        Iterator JavaDoc keyIt = criteria.keySet().iterator();
1498        while (keyIt.hasNext())
1499        {
1500            String JavaDoc key = (String JavaDoc) keyIt.next();
1501            String JavaDoc columnName;
1502            TableMap tableMap = null;
1503            int dotPosition = key.lastIndexOf(".");
1504            if (dotPosition == -1)
1505            {
1506                columnName = key;
1507                tableMap = defaultTableMap;
1508            }
1509            else
1510            {
1511                columnName = key.substring(dotPosition + 1);
1512                String JavaDoc tableName = key.substring(0, dotPosition);
1513                String JavaDoc databaseName = criteria.getDbName();
1514                if (databaseName == null)
1515                {
1516                    databaseName = Torque.getDefaultDB();
1517                }
1518                DatabaseMap databaseMap = Torque.getDatabaseMap(databaseName);
1519                if (databaseMap != null)
1520                {
1521                    tableMap = databaseMap.getTable(tableName);
1522                }
1523                if (tableMap == null)
1524                {
1525                    // try aliases
1526
Map JavaDoc aliases = criteria.getAliases();
1527                    if (aliases != null && aliases.get(tableName) != null)
1528                    {
1529                        tableName = (String JavaDoc) aliases.get(tableName);
1530                        tableMap = databaseMap.getTable(tableName);
1531                    }
1532                }
1533                if (tableMap == null)
1534                {
1535                    // no description of table available, do not modify anything
1536
break;
1537                }
1538            }
1539
1540            ColumnMap columnMap = tableMap.getColumn(columnName);
1541            if (columnMap != null)
1542            {
1543                if ("BOOLEANINT".equals(columnMap.getTorqueType()))
1544                {
1545                    Criteria.Criterion criterion = criteria.getCriterion(key);
1546                    replaceBooleanValues(
1547                            criterion,
1548                            new Integer JavaDoc(1),
1549                            new Integer JavaDoc(0));
1550                }
1551                else if ("BOOLEANCHAR".equals(columnMap.getTorqueType()))
1552                {
1553                    Criteria.Criterion criterion = criteria.getCriterion(key);
1554                    replaceBooleanValues(criterion, "Y", "N");
1555                 }
1556            }
1557        }
1558    }
1559
1560    /**
1561     * Replaces any Boolean value in the criterion and its attached Criterions
1562     * by trueValue if the Boolean equals <code>Boolean.TRUE</code>
1563     * and falseValue if the Boolean equals <code>Boolean.FALSE</code>.
1564     *
1565     * @param criterion the criterion to replace Boolean values in.
1566     * @param trueValue the value by which Boolean.TRUE should be replaced.
1567     * @param falseValue the value by which Boolean.FALSE should be replaced.
1568     */

1569    private static void replaceBooleanValues(
1570            Criteria.Criterion criterion,
1571            Object JavaDoc trueValue,
1572            Object JavaDoc falseValue)
1573    {
1574        // attachedCriterions also contains the criterion itself,
1575
// so no additional treatment is needed for the criterion itself.
1576
Criteria.Criterion[] attachedCriterions
1577            = criterion.getAttachedCriterion();
1578        for (int i = 0; i < attachedCriterions.length; ++i)
1579        {
1580            Object JavaDoc criterionValue
1581                    = attachedCriterions[i].getValue();
1582            if (criterionValue instanceof Boolean JavaDoc)
1583            {
1584                Boolean JavaDoc booleanValue = (Boolean JavaDoc) criterionValue;
1585                attachedCriterions[i].setValue(
1586                        Boolean.TRUE.equals(booleanValue)
1587                                ? trueValue
1588                                : falseValue);
1589            }
1590
1591        }
1592
1593    }
1594
1595    /**
1596     * Process the result of a Table list generation.
1597     * This runs the statements onto the list of tables and
1598     * provides a callback hook to add functionality.
1599     *
1600     * This method should've been in SQLBuilder, but is uses the handleMultipleRecords callback thingie..
1601     *
1602     * @param crit The criteria
1603     * @param tables A set of Tables to run on
1604     * @param con The SQL Connection to run the statements on
1605     * @param pc A ProcessCallback object
1606     *
1607     * @throws Exception An Error occured (should be wrapped into TorqueException)
1608     */

1609    private static void processTables(Criteria crit, Set JavaDoc tables, Connection JavaDoc con, ProcessCallback pc)
1610            throws Exception JavaDoc
1611    {
1612        String JavaDoc dbName = crit.getDbName();
1613        DB db = Torque.getDB(dbName);
1614        DatabaseMap dbMap = Torque.getDatabaseMap(dbName);
1615
1616        // create the statements for the tables
1617
for (Iterator JavaDoc it = tables.iterator(); it.hasNext();)
1618        {
1619            String JavaDoc table = (String JavaDoc) it.next();
1620            KeyDef kd = new KeyDef();
1621            Set JavaDoc whereClause = new HashSet JavaDoc();
1622
1623            ColumnMap[] columnMaps = dbMap.getTable(table).getColumns();
1624
1625            for (int j = 0; j < columnMaps.length; j++)
1626            {
1627                ColumnMap colMap = columnMaps[j];
1628                if (colMap.isPrimaryKey())
1629                {
1630                    kd.addAttrib(colMap.getColumnName());
1631                }
1632
1633                String JavaDoc key = new StringBuffer JavaDoc(colMap.getTableName())
1634                        .append('.')
1635                        .append(colMap.getColumnName())
1636                        .toString();
1637
1638                if (crit.containsKey(key))
1639                {
1640                    if (crit
1641                            .getComparison(key)
1642                            .equals(Criteria.CUSTOM))
1643                    {
1644                        whereClause.add(crit.getString(key));
1645                    }
1646                    else
1647                    {
1648                        whereClause.add(
1649                                SqlExpression.build(
1650                                        colMap.getColumnName(),
1651                                        crit.getValue(key),
1652                                        crit.getComparison(key),
1653                                        crit.isIgnoreCase(),
1654                                        db));
1655                    }
1656                }
1657            }
1658
1659            // Execute the statement for each table
1660
TableDataSet tds = null;
1661            try
1662            {
1663                String JavaDoc tableName = SQLBuilder.getFullTableName(table, dbName);
1664
1665                // Get affected records.
1666
tds = new TableDataSet(con, tableName, kd);
1667                String JavaDoc sqlSnippet = StringUtils.join(whereClause.iterator(), " AND ");
1668
1669                if (log.isDebugEnabled())
1670                {
1671                    log.debug("BasePeer: whereClause=" + sqlSnippet);
1672                }
1673
1674                tds.where(sqlSnippet);
1675                tds.fetchRecords();
1676
1677                if (tds.size() > 1 && crit.isSingleRecord())
1678                {
1679                    handleMultipleRecords(tds);
1680                }
1681
1682                for (int j = 0; j < tds.size(); j++)
1683                {
1684                    Record rec = tds.getRecord(j);
1685
1686                    if (pc != null)
1687                    {
1688                        // Table name _without_ schema!
1689
pc.process(table, dbName, rec);
1690                    }
1691                }
1692            }
1693            finally
1694            {
1695                VillageUtils.close(tds);
1696            }
1697        }
1698    }
1699
1700    /**
1701     * Inner Interface that defines the Callback method for
1702     * the Record Processing
1703     */

1704    protected interface ProcessCallback
1705    {
1706        void process (String JavaDoc table, String JavaDoc dbName, Record rec)
1707                throws Exception JavaDoc;
1708    }
1709}
1710
Popular Tags