KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > accesslayer > sql > SqlQueryStatement


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

17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.Enumeration JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import org.apache.ojb.broker.PersistenceBrokerSQLException;
27 import org.apache.ojb.broker.accesslayer.JoinSyntaxTypes;
28 import org.apache.ojb.broker.metadata.ClassDescriptor;
29 import org.apache.ojb.broker.metadata.CollectionDescriptor;
30 import org.apache.ojb.broker.metadata.DescriptorRepository;
31 import org.apache.ojb.broker.metadata.FieldDescriptor;
32 import org.apache.ojb.broker.metadata.FieldHelper;
33 import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor;
34 import org.apache.ojb.broker.metadata.SuperReferenceDescriptor;
35 import org.apache.ojb.broker.platforms.Platform;
36 import org.apache.ojb.broker.query.BetweenCriteria;
37 import org.apache.ojb.broker.query.Criteria;
38 import org.apache.ojb.broker.query.ExistsCriteria;
39 import org.apache.ojb.broker.query.FieldCriteria;
40 import org.apache.ojb.broker.query.InCriteria;
41 import org.apache.ojb.broker.query.LikeCriteria;
42 import org.apache.ojb.broker.query.MtoNQuery;
43 import org.apache.ojb.broker.query.NullCriteria;
44 import org.apache.ojb.broker.query.Query;
45 import org.apache.ojb.broker.query.QueryByCriteria;
46 import org.apache.ojb.broker.query.QueryBySQL;
47 import org.apache.ojb.broker.query.SelectionCriteria;
48 import org.apache.ojb.broker.query.SqlCriteria;
49 import org.apache.ojb.broker.query.UserAlias;
50 import org.apache.ojb.broker.util.SqlHelper;
51 import org.apache.ojb.broker.util.SqlHelper.PathInfo;
52 import org.apache.ojb.broker.util.logging.Logger;
53 import org.apache.ojb.broker.util.logging.LoggerFactory;
54
55 /**
56  * Model a Statement based on Query.
57  *
58  * @author <a HREF="mailto:jbraeuchi@gmx.ch">Jakob Braeuchi</a>
59  * @version $Id: SqlQueryStatement.java,v 1.75.2.23 2005/12/22 18:25:51 brj Exp $
60  */

61 public abstract class SqlQueryStatement implements SqlStatement, JoinSyntaxTypes
62 {
63     private static final String JavaDoc ALIAS_SEPARATOR = ".";
64     private static final String JavaDoc M_N_ALIAS = "M_N";
65     private String JavaDoc sql;
66     
67     private SqlQueryStatement m_parentStatement;
68     /** the logger */
69     private Logger m_logger;
70     /** the target table of the query */
71     private TableAlias m_root;
72     /** the search table of the query */
73     private TableAlias m_search;
74     /** the query */
75     private QueryByCriteria m_query;
76     /** the mapping of paths to TableAliases. the key is built using the path and the path class hints. */
77     private HashMap JavaDoc m_pathToAlias = new HashMap JavaDoc();
78     /** the mapping of ClassDescriptor to TableAliases */
79     private HashMap JavaDoc m_cldToAlias = new HashMap JavaDoc();
80     /** maps trees of joins to criteria */
81     private HashMap JavaDoc m_joinTreeToCriteria = new HashMap JavaDoc();
82
83     private Platform m_platform;
84     private ClassDescriptor m_baseCld;
85     private ClassDescriptor m_searchCld;
86
87     private int m_aliasCount = 0;
88     protected HashMap JavaDoc m_attrToFld = new HashMap JavaDoc(); //attribute -> FieldDescriptor
89

90     /**
91      * Constructor for SqlCriteriaStatement.
92      *
93      * @param pf the Platform
94      * @param cld the ClassDescriptor
95      * @param query the Query
96      * @param logger the Logger
97      */

98     public SqlQueryStatement(Platform pf, ClassDescriptor cld, Query query, Logger logger)
99     {
100         this(null, pf, cld, query, logger);
101     }
102
103     /**
104      * Constructor for SqlCriteriaStatement.
105      *
106      * @param parent the Parent Query
107      * @param pf the Platform
108      * @param cld the ClassDescriptor
109      * @param query the Query
110      * @param logger the Logger
111      */

112     public SqlQueryStatement(SqlQueryStatement parent, Platform pf, ClassDescriptor cld, Query query, Logger logger)
113     {
114         m_logger = logger != null ? logger : LoggerFactory.getLogger(SqlQueryStatement.class);
115         m_parentStatement = parent;
116         m_query = (QueryByCriteria) query;
117         m_platform = pf;
118         m_searchCld = cld;
119
120         if ((m_query == null) || (m_query.getBaseClass() == m_query.getSearchClass()))
121         {
122             m_baseCld = m_searchCld;
123         }
124         else
125         {
126             m_baseCld = cld.getRepository().getDescriptorFor(query.getBaseClass());
127         }
128
129         m_root = createTableAlias(m_baseCld, null, "");
130         
131         // BRJ: create a special alias for the indirection table
132
if (m_query instanceof MtoNQuery)
133         {
134             MtoNQuery mnQuery = (MtoNQuery)m_query;
135             TableAlias mnAlias = new TableAlias(mnQuery.getIndirectionTable(), M_N_ALIAS);
136             setTableAliasForPath(mnQuery.getIndirectionTable(), null, mnAlias);
137         }
138
139         if (m_searchCld == m_baseCld)
140         {
141             m_search = m_root;
142         }
143         else
144         {
145             m_search = getTableAlias(m_query.getObjectProjectionAttribute(), false, null, null, m_query.getPathClasses());
146         }
147
148         // Walk the super reference-descriptor
149
buildSuperJoinTree(m_root, m_baseCld, "" ,false);
150
151         buildMultiJoinTree(m_root, m_baseCld, "", true);
152
153         // In some cases it is necessary to split the query criteria
154
// and then to generate UNION of several SELECTs
155
// We build the joinTreeToCriteria mapping,
156
if (query != null)
157         {
158             splitCriteria();
159         }
160     }
161
162     protected ClassDescriptor getBaseClassDescriptor()
163     {
164         return m_baseCld;
165     }
166
167     protected ClassDescriptor getSearchClassDescriptor()
168     {
169         return m_searchCld;
170     }
171
172     /**
173      * Return the TableAlias and the PathInfo for an Attribute name<br>
174      * field names in functions (ie: sum(name) ) are tried to resolve ie: name
175      * from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
176      * also resolve pathExpression adress.city or owner.konti.saldo
177      * @param attr
178      * @param useOuterJoins
179      * @param aUserAlias
180      * @param pathClasses
181      * @return ColumnInfo
182      */

183     protected AttributeInfo getAttributeInfo(String JavaDoc attr, boolean useOuterJoins, UserAlias aUserAlias, Map JavaDoc pathClasses)
184     {
185         AttributeInfo result = new AttributeInfo();
186         TableAlias tableAlias;
187         SqlHelper.PathInfo pathInfo = SqlHelper.splitPath(attr);
188         String JavaDoc colName = pathInfo.column;
189         int sp;
190
191         // BRJ:
192
// check if we refer to an attribute in the parent query
193
// this prefix is temporary !
194
if (colName.startsWith(Criteria.PARENT_QUERY_PREFIX) && m_parentStatement != null)
195         {
196             String JavaDoc[] fieldNameRef = {colName.substring(Criteria.PARENT_QUERY_PREFIX.length())};
197             return m_parentStatement.getAttributeInfo(fieldNameRef[0], useOuterJoins, aUserAlias, pathClasses);
198         }
199
200         sp = colName.lastIndexOf(".");
201         if (sp == -1)
202         {
203             tableAlias = getRoot();
204         }
205         else
206         {
207             String JavaDoc pathName = colName.substring(0, sp);
208             String JavaDoc[] fieldNameRef = {colName.substring(sp + 1)};
209
210             tableAlias = getTableAlias(pathName, useOuterJoins, aUserAlias, fieldNameRef, pathClasses);
211             /**
212              * if we have not found an alias by the pathName or
213              * aliasName (if given), try again because pathName
214              * may be an aliasname. it can be only and only if it is not
215              * a path, which means there may be no path separators (,)
216              * in the pathName.
217              */

218             if ((tableAlias == null) && (colName.lastIndexOf(".") == -1))
219             {
220                 /**
221                  * pathName might be an alias, so check this first
222                  */

223                 tableAlias = getTableAlias(pathName, useOuterJoins, new UserAlias(pathName, pathName, pathName), null, pathClasses);
224             }
225
226             if (tableAlias != null)
227             {
228                 // correct column name to match the alias
229
// productGroup.groupName -> groupName
230
pathInfo.column = fieldNameRef[0];
231             }
232         }
233
234         result.tableAlias = tableAlias;
235         result.pathInfo = pathInfo;
236         return result;
237     }
238
239     /**
240      * Answer the column name for alias and path info<br>
241      * if translate try to convert attribute name into column name otherwise use attribute name<br>
242      * if a FieldDescriptor is found for the attribute name the column name is taken from
243      * there prefixed with the alias (firstname -> A0.F_NAME).
244      */

245     protected String JavaDoc getColName(TableAlias aTableAlias, PathInfo aPathInfo, boolean translate)
246     {
247         String JavaDoc result = null;
248
249         // no translation required, use attribute name
250
if (!translate)
251         {
252             return aPathInfo.column;
253         }
254
255         // BRJ: special alias for the indirection table has no ClassDescriptor
256
if (aTableAlias.cld == null && M_N_ALIAS.equals(aTableAlias.alias))
257         {
258             return getIndirectionTableColName(aTableAlias, aPathInfo.path);
259         }
260
261         // translate attribute name into column name
262
FieldDescriptor fld = getFieldDescriptor(aTableAlias, aPathInfo);
263
264         if (fld != null)
265         {
266             m_attrToFld.put(aPathInfo.path, fld);
267
268             // added to suport the super reference descriptor
269
if (!fld.getClassDescriptor().getFullTableName().equals(aTableAlias.table) && aTableAlias.hasJoins())
270             {
271                 Iterator JavaDoc itr = aTableAlias.joins.iterator();
272                 while (itr.hasNext())
273                 {
274                     Join join = (Join) itr.next();
275                     if (join.right.table.equals(fld.getClassDescriptor().getFullTableName()))
276                     {
277                         result = join.right.alias + "." + fld.getColumnName();
278                         break;
279                     }
280                 }
281
282                 if (result == null)
283                 {
284                     result = aPathInfo.column;
285                 }
286             }
287             else
288             {
289                 result = aTableAlias.alias + "." + fld.getColumnName();
290             }
291         }
292         else if ("*".equals(aPathInfo.column))
293         {
294             result = aPathInfo.column;
295         }
296         else
297         {
298             // throw new IllegalArgumentException("No Field found for : " + aPathInfo.column);
299
result = aPathInfo.column;
300         }
301
302         return result;
303     }
304
305     /**
306      * Add the Column to the StringBuffer <br>
307      *
308      * @param aTableAlias
309      * @param aPathInfo
310      * @param translate flag to indicate translation of pathInfo
311      * @param buf
312      * @return true if appended
313      */

314     protected boolean appendColName(TableAlias aTableAlias, PathInfo aPathInfo, boolean translate, StringBuffer JavaDoc buf)
315     {
316         String JavaDoc prefix = aPathInfo.prefix;
317         String JavaDoc suffix = aPathInfo.suffix;
318         String JavaDoc colName = getColName(aTableAlias, aPathInfo, translate);
319
320         if (prefix != null) // rebuild function contains (
321
{
322             buf.append(prefix);
323         }
324
325         buf.append(colName);
326
327         if (suffix != null) // rebuild function
328
{
329             buf.append(suffix);
330         }
331
332         return true;
333     }
334
335     /**
336      * Get the FieldDescriptor for the PathInfo
337      *
338      * @param aTableAlias
339      * @param aPathInfo
340      * @return FieldDescriptor
341      */

342     protected FieldDescriptor getFieldDescriptor(TableAlias aTableAlias, PathInfo aPathInfo)
343     {
344         FieldDescriptor fld = null;
345         String JavaDoc colName = aPathInfo.column;
346
347         if (aTableAlias != null)
348         {
349             fld = aTableAlias.cld.getFieldDescriptorByName(colName);
350             if (fld == null)
351             {
352                 ObjectReferenceDescriptor ord = aTableAlias.cld.getObjectReferenceDescriptorByName(colName);
353                 if (ord != null)
354                 {
355                     fld = getFldFromReference(aTableAlias, ord);
356                 }
357                 else
358                 {
359                     fld = getFldFromJoin(aTableAlias, colName);
360                 }
361             }
362         }
363
364         return fld;
365     }
366
367     /**
368      * Get FieldDescriptor from joined superclass.
369      */

370     private FieldDescriptor getFldFromJoin(TableAlias aTableAlias, String JavaDoc aColName)
371     {
372         FieldDescriptor fld = null;
373
374         // Search Join Structure for attribute
375
if (aTableAlias.joins != null)
376         {
377             Iterator JavaDoc itr = aTableAlias.joins.iterator();
378             while (itr.hasNext())
379             {
380                 Join join = (Join) itr.next();
381                 ClassDescriptor cld = join.right.cld;
382
383                 if (cld != null)
384                 {
385                     fld = cld.getFieldDescriptorByName(aColName);
386                     if (fld != null)
387                     {
388                         break;
389                     }
390
391                 }
392             }
393         }
394         return fld;
395     }
396
397     /**
398      * Get FieldDescriptor from Reference
399      */

400     private FieldDescriptor getFldFromReference(TableAlias aTableAlias, ObjectReferenceDescriptor anOrd)
401     {
402         FieldDescriptor fld = null;
403
404         if (aTableAlias == getRoot())
405         {
406             // no path expression
407
FieldDescriptor[] fk = anOrd.getForeignKeyFieldDescriptors(aTableAlias.cld);
408             if (fk.length > 0)
409             {
410                 fld = fk[0];
411             }
412         }
413         else
414         {
415             // attribute with path expression
416
/**
417              * MBAIRD
418              * potentially people are referring to objects, not to the object's primary key,
419              * and then we need to take the primary key attribute of the referenced object
420              * to help them out.
421              */

422             ClassDescriptor cld = aTableAlias.cld.getRepository().getDescriptorFor(anOrd.getItemClass());
423             if (cld != null)
424             {
425                 fld = aTableAlias.cld.getFieldDescriptorByName(cld.getPkFields()[0].getPersistentField().getName());
426             }
427         }
428
429         return fld;
430     }
431
432     /**
433      * Append the appropriate ColumnName to the buffer<br>
434      * if a FIELDDESCRIPTOR is found for the Criteria the colName is taken from
435      * there otherwise its taken from Criteria. <br>
436      * field names in functions (ie: sum(name) ) are tried to resolve
437      * ie: name from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
438      * also resolve pathExpression adress.city or owner.konti.saldo
439      */

440     protected boolean appendColName(String JavaDoc attr, boolean useOuterJoins, UserAlias aUserAlias, StringBuffer JavaDoc buf)
441     {
442         AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias, getQuery().getPathClasses());
443         TableAlias tableAlias = attrInfo.tableAlias;
444
445         return appendColName(tableAlias, attrInfo.pathInfo, (tableAlias != null), buf);
446     }
447
448     /**
449      * Append the appropriate ColumnName to the buffer<br>
450      * if a FIELDDESCRIPTOR is found for the Criteria the colName is taken from
451      * there otherwise its taken from Criteria. <br>
452      * field names in functions (ie: sum(name) ) are tried to resolve
453      * ie: name from FIELDDESCRIPTOR , UPPER(name_test) from Criteria<br>
454      * also resolve pathExpression adress.city or owner.konti.saldo
455      */

456     protected boolean appendColName(String JavaDoc attr, String JavaDoc attrAlias, boolean useOuterJoins, UserAlias aUserAlias,
457             StringBuffer JavaDoc buf)
458     {
459         AttributeInfo attrInfo = getAttributeInfo(attr, useOuterJoins, aUserAlias, getQuery().getPathClasses());
460         TableAlias tableAlias = attrInfo.tableAlias;
461         PathInfo pi = attrInfo.pathInfo;
462
463         if (pi.suffix != null)
464         {
465             pi.suffix = pi.suffix + " as " + attrAlias;
466         }
467         else
468         {
469             pi.suffix = " as " + attrAlias;
470         }
471
472         return appendColName(tableAlias, pi, true, buf);
473     }
474
475     /**
476      * Builds the Join for columns if they are not found among the existingColumns.
477      * @param columns the list of columns represented by Criteria.Field to ensure
478      * @param existingColumns the list of column names (String) that are already appended
479      */

480     protected void ensureColumns(List JavaDoc columns, List JavaDoc existingColumns)
481     {
482         if (columns == null || columns.isEmpty())
483         {
484             return;
485         }
486         
487         Iterator JavaDoc iter = columns.iterator();
488
489         while (iter.hasNext())
490         {
491             FieldHelper cf = (FieldHelper) iter.next();
492             if (!existingColumns.contains(cf.name))
493             {
494                 getAttributeInfo(cf.name, false, null, getQuery().getPathClasses());
495             }
496         }
497     }
498
499     /**
500      * Builds the Join for columns if they are not found among the existingColumns.
501      * These <b>columns are added to the statement</b> using a column-alias "ojb_col_x",
502      * x being the number of existing columns
503      * @param columns the list of columns represented by Criteria.Field to ensure
504      * @param existingColumns the list of column names (String) that are already appended
505      * @param buf the statement
506      * @return List of existingColumns including ojb_col_x
507      */

508     protected List JavaDoc ensureColumns(List JavaDoc columns, List JavaDoc existingColumns, StringBuffer JavaDoc buf)
509     {
510         if (columns == null || columns.isEmpty())
511         {
512             return existingColumns;
513         }
514
515         Iterator JavaDoc iter = columns.iterator();
516         int ojb_col = existingColumns.size() + 1;
517
518         while (iter.hasNext())
519         {
520             FieldHelper cf = (FieldHelper) iter.next();
521             if (!existingColumns.contains(cf.name))
522             {
523                 existingColumns.add(cf.name);
524                 
525                 buf.append(",");
526                 appendColName(cf.name, "ojb_col_" + ojb_col, false, null, buf);
527                 ojb_col++;
528             }
529         }
530         
531         return existingColumns;
532     }
533
534
535     /**
536      * appends a WHERE-clause to the Statement
537      * @param where
538      * @param crit
539      * @param stmt
540      */

541     protected void appendWhereClause(StringBuffer JavaDoc where, Criteria crit, StringBuffer JavaDoc stmt)
542     {
543         if (where.length() == 0)
544         {
545             where = null;
546         }
547
548         if (where != null || (crit != null && !crit.isEmpty()))
549         {
550             stmt.append(" WHERE ");
551             appendClause(where, crit, stmt);
552         }
553     }
554
555     /**
556      * appends a HAVING-clause to the Statement
557      * @param having
558      * @param crit
559      * @param stmt
560      */

561     protected void appendHavingClause(StringBuffer JavaDoc having, Criteria crit, StringBuffer JavaDoc stmt)
562     {
563         if (having.length() == 0)
564         {
565             having = null;
566         }
567
568         if (having != null || crit != null)
569         {
570             stmt.append(" HAVING ");
571             appendClause(having, crit, stmt);
572         }
573     }
574
575     /**
576      * appends a WHERE/HAVING-clause to the Statement
577      * @param clause
578      * @param crit
579      * @param stmt
580      */

581     protected void appendClause(StringBuffer JavaDoc clause, Criteria crit, StringBuffer JavaDoc stmt)
582     {
583         /**
584          * MBAIRD
585          * when generating the "WHERE/HAVING" clause we need to append the criteria for multi-mapped
586          * tables. We only need to do this for the root classdescriptor and not for joined tables
587          * because we assume you cannot make a relation of the wrong type upon insertion. Of course,
588          * you COULD mess the data up manually and this would cause a problem.
589          */

590
591         if (clause != null)
592         {
593             stmt.append(clause.toString());
594         }
595         if (crit != null)
596         {
597             if (clause == null)
598             {
599                 stmt.append(asSQLStatement(crit));
600             }
601             else
602             {
603                 stmt.append(" AND (");
604                 stmt.append(asSQLStatement(crit));
605                 stmt.append(")");
606             }
607
608         }
609     }
610
611     /**
612      * Create SQL-String based on Criteria
613      */

614     private String JavaDoc asSQLStatement(Criteria crit)
615     {
616         Enumeration JavaDoc e = crit.getElements();
617         StringBuffer JavaDoc statement = new StringBuffer JavaDoc();
618
619         while (e.hasMoreElements())
620         {
621             Object JavaDoc o = e.nextElement();
622             if (o instanceof Criteria)
623             {
624                 Criteria pc = (Criteria) o;
625                 
626                 if (pc.isEmpty())
627                 {
628                     continue; //skip empty criteria
629
}
630                 
631                 String JavaDoc addAtStart = "";
632                 String JavaDoc addAtEnd = "";
633
634                 // need to add parenthesises?
635
if (pc.isEmbraced())
636                 {
637                     addAtStart = " (";
638                     addAtEnd = ")";
639                 }
640
641                 switch (pc.getType())
642                 {
643                     case (Criteria.OR) :
644                         {
645                             if (statement.length() > 0)
646                             {
647                                 statement.append(" OR ");
648                             }
649                             statement.append(addAtStart);
650                             statement.append(asSQLStatement(pc));
651                             statement.append(addAtEnd);
652                             break;
653                         }
654                     case (Criteria.AND) :
655                         {
656                             if (statement.length() > 0)
657                             {
658                                 statement.insert(0, "( ");
659                                 statement.append(") AND ");
660                             }
661                             statement.append(addAtStart);
662                             statement.append(asSQLStatement(pc));
663                             statement.append(addAtEnd);
664                             break;
665                         }
666                 }
667             }
668             else
669             {
670                 SelectionCriteria c = (SelectionCriteria) o;
671                 if (statement.length() > 0)
672                 {
673                     statement.insert(0, "(");
674                     statement.append(") AND ");
675                 }
676                 appendSQLClause(c, statement);
677             }
678         } // while
679

680         // BRJ : negative Criteria surrounded by NOT (...)
681
if (crit.isNegative())
682         {
683             statement.insert(0, " NOT (");
684             statement.append(")");
685         }
686         
687         return (statement.length() == 0 ? null : statement.toString());
688     }
689
690     /**
691      * Answer the SQL-Clause for a BetweenCriteria
692      *
693      * @param alias
694      * @param pathInfo
695      * @param c BetweenCriteria
696      * @param buf
697      */

698     private void appendBetweenCriteria(TableAlias alias, PathInfo pathInfo, BetweenCriteria c, StringBuffer JavaDoc buf)
699     {
700         appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
701         buf.append(c.getClause());
702         appendParameter(c.getValue(), buf);
703         buf.append(" AND ");
704         appendParameter(c.getValue2(), buf);
705     }
706
707     /**
708      * Answer the SQL-Clause for an ExistsCriteria
709      * @param c ExistsCriteria
710      */

711     private void appendExistsCriteria(ExistsCriteria c, StringBuffer JavaDoc buf)
712     {
713         Query subQuery = (Query) c.getValue();
714
715         buf.append(c.getClause());
716         appendSubQuery(subQuery, buf);
717     }
718
719     /**
720      * Answer the SQL-Clause for a FieldCriteria<br>
721      * The value of the FieldCriteria will be translated
722      *
723      * @param alias
724      * @param pathInfo
725      * @param c ColumnCriteria
726      * @param buf
727      */

728     private void appendFieldCriteria(TableAlias alias, PathInfo pathInfo, FieldCriteria c, StringBuffer JavaDoc buf)
729     {
730         appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
731         buf.append(c.getClause());
732
733         if (c.isTranslateField())
734         {
735             appendColName((String JavaDoc) c.getValue(), false, c.getUserAlias(), buf);
736         }
737         else
738         {
739             buf.append(c.getValue());
740         }
741     }
742     
743     /**
744      * Get the column name from the indirection table.
745      * @param mnAlias
746      * @param path
747      */

748     private String JavaDoc getIndirectionTableColName(TableAlias mnAlias, String JavaDoc path)
749     {
750         int dotIdx = path.lastIndexOf(".");
751         String JavaDoc column = path.substring(dotIdx);
752         return mnAlias.alias + column;
753     }
754
755     /**
756      * Answer the SQL-Clause for an InCriteria
757      *
758      * @param alias
759      * @param pathInfo
760      * @param c InCriteria
761      * @param buf
762      */

763     private void appendInCriteria(TableAlias alias, PathInfo pathInfo, InCriteria c, StringBuffer JavaDoc buf)
764     {
765         appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
766         buf.append(c.getClause());
767
768         if (c.getValue() instanceof Collection JavaDoc)
769         {
770             Object JavaDoc[] values = ((Collection JavaDoc) c.getValue()).toArray();
771             int size = ((Collection JavaDoc) c.getValue()).size();
772
773             buf.append("(");
774             if (size > 0)
775             {
776                 for (int i = 0; i < size - 1; i++)
777                 {
778                     appendParameter(values[i], buf);
779                     buf.append(",");
780                 }
781                 appendParameter(values[size - 1], buf);
782             }
783             buf.append(")");
784         }
785         else
786         {
787             appendParameter(c.getValue(), buf);
788         }
789     }
790
791     /**
792      * Answer the SQL-Clause for a NullCriteria
793      *
794      * @param alias
795      * @param pathInfo
796      * @param c NullCriteria
797      * @param buf
798      */

799     private void appendNullCriteria(TableAlias alias, PathInfo pathInfo, NullCriteria c, StringBuffer JavaDoc buf)
800     {
801         appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
802         buf.append(c.getClause());
803     }
804
805     /**
806      * Answer the SQL-Clause for a SqlCriteria
807      *
808      */

809     private void appendSQLCriteria(SqlCriteria c, StringBuffer JavaDoc buf)
810     {
811         buf.append(c.getClause());
812     }
813
814     /**
815      * Answer the SQL-Clause for a SelectionCriteria
816      *
817      * @param c
818      * @param buf
819      */

820     private void appendSelectionCriteria(TableAlias alias, PathInfo pathInfo, SelectionCriteria c, StringBuffer JavaDoc buf)
821     {
822         appendColName(alias, pathInfo, c.isTranslateAttribute(), buf);
823         buf.append(c.getClause());
824         appendParameter(c.getValue(), buf);
825     }
826
827     /**
828      * Answer the SQL-Clause for a LikeCriteria
829      *
830      * @param c
831      * @param buf
832      */

833     private void appendLikeCriteria(TableAlias alias, PathInfo pathInfo, LikeCriteria c, StringBuffer JavaDoc</