KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.List JavaDoc;
23
24 import org.apache.torque.TorqueException;
25 import org.apache.torque.adapter.DB;
26 import org.apache.torque.map.DatabaseMap;
27
28 /**
29  * Factored out code that is used to generate Join Code. This code comes
30  * from BasePeer and is put here to reduce complexity in the BasePeer class.
31  * You should not use the methods here directly!
32  *
33  * @author <a HREF="mailto:fischer@seitenbau.de">Thomas Fischer</a>
34  * @author <a HREF="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
35  * @version $Id: JoinBuilder.java 476550 2006-11-18 16:08:37Z tfischer $
36  */

37 public final class JoinBuilder
38 {
39     /**
40      * Private constructor to prevent initialisation.
41      *
42      * Class contains only static methods and should therefore not be
43      * instantiated.
44      */

45     private JoinBuilder()
46     {
47     }
48
49     /**
50      * adds the Joins from the criteria to the query
51      * @param criteria the criteria from which the Joins are taken
52      * @param query the query to which the Joins should be added
53      * @throws TorqueException if the Joins can not be processed
54      */

55     public static void processJoins(
56             final DB db,
57             final DatabaseMap dbMap,
58             final Criteria criteria,
59             final Query query)
60             throws TorqueException
61     {
62         List JavaDoc criteriaJoins = criteria.getJoins();
63
64         if (criteriaJoins == null)
65         {
66             return;
67         }
68
69         UniqueList queryFromClause = query.getFromClause();
70         UniqueList queryWhereClause = query.getWhereClause();
71
72         for (int i = 0; i < criteriaJoins.size(); i++)
73         {
74             Criteria.Join join = (Criteria.Join) criteriaJoins.get(i);
75             String JavaDoc leftColumn = join.getLeftColumn();
76             String JavaDoc rightColumn = join.getRightColumn();
77
78             // check if the column names make sense
79
if (leftColumn.indexOf('.') == -1)
80             {
81                 SQLBuilder.throwMalformedColumnNameException("join", leftColumn);
82             }
83             if (rightColumn.indexOf('.') == -1)
84             {
85                 SQLBuilder.throwMalformedColumnNameException("join", rightColumn);
86             }
87
88             // get the table names
89
// (and the alias names for them if necessary))
90
// Also check whether a case insensitive comparison is needed
91
int dot = leftColumn.lastIndexOf('.');
92             String JavaDoc leftTableName = leftColumn.substring(0, dot);
93
94             leftTableName =
95                     SQLBuilder.getTableNameForFromClause(leftTableName, criteria);
96
97             dot = rightColumn.lastIndexOf('.');
98             String JavaDoc rightTableName = rightColumn.substring(0, dot);
99             String JavaDoc dbTableName
100                     = criteria.getTableForAlias(rightTableName);
101
102             if (dbTableName == null)
103             {
104                 dbTableName = rightTableName;
105             }
106
107             String JavaDoc columnName = rightColumn.substring(
108                     dot + 1,
109                     rightColumn.length());
110
111             boolean ignoreCase = (criteria.isIgnoreCase()
112                     && (dbMap
113                             .getTable(dbTableName)
114                             .getColumn(columnName)
115                             .getType()
116                             instanceof String JavaDoc));
117
118             rightTableName = SQLBuilder.getTableNameForFromClause(
119                     rightTableName, criteria);
120
121             // now check the join type and add the join to the
122
// appropriate places in the query
123
SqlEnum joinType = join.getJoinType();
124
125             if (joinType == null)
126             {
127                 // Do not treat join as explicit join, but add
128
// the join condition to the where clauses
129
if (!SQLBuilder.fromClauseContainsTableName(
130                             queryFromClause,
131                             leftTableName))
132                 {
133                     Query.FromElement fromElement
134                             = new Query.FromElement(
135                                     leftTableName, null, null);
136                     queryFromClause.add(fromElement);
137                 }
138                 if (!SQLBuilder.fromClauseContainsTableName(
139                             queryFromClause,
140                             rightTableName))
141                 {
142                     Query.FromElement fromElement
143                             = new Query.FromElement(
144                                     rightTableName, null, null);
145                     queryFromClause.add(fromElement);
146                 }
147                 queryWhereClause.add(
148                         SqlExpression.buildInnerJoin(
149                                 leftColumn, rightColumn, ignoreCase, db));
150             }
151             else
152             {
153                 // check whether the order of the join must be "reversed"
154
// This if the case if the fromClause already contains
155
// rightTableName
156

157                 if (!SQLBuilder.fromClauseContainsTableName(
158                             queryFromClause,
159                             rightTableName))
160                 {
161                     if (!SQLBuilder.fromClauseContainsTableName(
162                                 queryFromClause,
163                                 leftTableName))
164                     {
165                         Query.FromElement fromElement
166                                 = new Query.FromElement(
167                                         leftTableName, null, null);
168                         queryFromClause.add(fromElement);
169                     }
170
171                     Query.FromElement fromElement
172                             = new Query.FromElement(
173                                     rightTableName, joinType,
174                                     SqlExpression.buildInnerJoin(
175                                             leftColumn, rightColumn,
176                                             ignoreCase, db));
177                     queryFromClause.add(fromElement);
178                 }
179                 else
180                 {
181                     if (SQLBuilder.fromClauseContainsTableName(
182                                 queryFromClause,
183                                 leftTableName))
184                     {
185                         // We cannot add an explicit join if both tables
186
// are alredy present in the from clause
187
throw new TorqueException(
188                                 "Unable to create a " + joinType
189                                 + "because both table names "
190                                 + leftTableName + " and " + rightTableName
191                                 + " are already in use. "
192                                 + "Try to create an(other) alias.");
193                     }
194                     // now add the join in reverse order
195
// rightTableName must not be added
196
// because it is already present
197
Query.FromElement fromElement
198                             = new Query.FromElement(
199                                     leftTableName, reverseJoinType(joinType),
200                                     SqlExpression.buildInnerJoin(
201                                             rightColumn, leftColumn,
202                                             ignoreCase, db));
203                     queryFromClause.add(fromElement);
204                 }
205             }
206         }
207     }
208
209     /**
210      * returns the reversed Join type, i.e. the join type which would produce
211      * the same result if also the joined tables were exchanged:
212      * Example:<br />
213      * table_a left join table_b <br />
214      * produces the same result as <br />
215      * table_b right join table_a<br />
216      * So "left join" is the reverse of "right join"
217      * @param joinType the join type to be reversed
218      * @return the reversed join type
219      */

220     private static SqlEnum reverseJoinType(final SqlEnum joinType)
221     {
222         if (SqlEnum.LEFT_JOIN.equals(joinType))
223         {
224             return SqlEnum.RIGHT_JOIN;
225         }
226         else if (SqlEnum.RIGHT_JOIN.equals(joinType))
227         {
228             return SqlEnum.LEFT_JOIN;
229         }
230         else
231         {
232             return joinType;
233         }
234     }
235 }
236
Popular Tags