KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > engine > JoinSequence


1 //$Id: JoinSequence.java,v 1.17 2005/06/15 17:18:14 steveebersole Exp $
2
package org.hibernate.engine;
3
4 import java.util.ArrayList JavaDoc;
5 import java.util.List JavaDoc;
6 import java.util.Map JavaDoc;
7
8 import org.hibernate.MappingException;
9 import org.hibernate.persister.entity.Joinable;
10 import org.hibernate.persister.collection.QueryableCollection;
11 import org.hibernate.sql.JoinFragment;
12 import org.hibernate.sql.QueryJoinFragment;
13 import org.hibernate.type.AssociationType;
14 import org.hibernate.util.CollectionHelper;
15
16 /**
17  * @author Gavin King
18  */

19 public class JoinSequence {
20
21     private final SessionFactoryImplementor factory;
22     private final List JavaDoc joins = new ArrayList JavaDoc();
23     private boolean useThetaStyle = false;
24     private final StringBuffer JavaDoc conditions = new StringBuffer JavaDoc();
25     private String JavaDoc rootAlias;
26     private Joinable rootJoinable;
27     private Selector selector;
28     private JoinSequence next;
29     private boolean isFromPart = false;
30
31     public String JavaDoc toString() {
32         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
33         buf.append( "JoinSequence{" );
34         if ( rootJoinable != null ) {
35             buf.append( rootJoinable )
36                     .append( '[' )
37                     .append( rootAlias )
38                     .append( ']' );
39         }
40         for ( int i = 0; i < joins.size(); i++ ) {
41             buf.append( "->" ).append( joins.get( i ) );
42         }
43         return buf.append( '}' ).toString();
44     }
45
46     final class Join {
47
48         private final AssociationType associationType;
49         private final Joinable joinable;
50         private final int joinType;
51         private final String JavaDoc alias;
52         private final String JavaDoc[] lhsColumns;
53
54         Join(AssociationType associationType, String JavaDoc alias, int joinType, String JavaDoc[] lhsColumns)
55                 throws MappingException {
56             this.associationType = associationType;
57             this.joinable = associationType.getAssociatedJoinable( factory );
58             this.alias = alias;
59             this.joinType = joinType;
60             this.lhsColumns = lhsColumns;
61         }
62
63         String JavaDoc getAlias() {
64             return alias;
65         }
66
67         AssociationType getAssociationType() {
68             return associationType;
69         }
70
71         Joinable getJoinable() {
72             return joinable;
73         }
74
75         int getJoinType() {
76             return joinType;
77         }
78
79         String JavaDoc[] getLHSColumns() {
80             return lhsColumns;
81         }
82
83         public String JavaDoc toString() {
84             return joinable.toString() + '[' + alias + ']';
85         }
86     }
87
88     public JoinSequence(SessionFactoryImplementor factory) {
89         this.factory = factory;
90     }
91
92     public JoinSequence getFromPart() {
93         JoinSequence fromPart = new JoinSequence( factory );
94         fromPart.joins.addAll( this.joins );
95         fromPart.useThetaStyle = this.useThetaStyle;
96         fromPart.rootAlias = this.rootAlias;
97         fromPart.rootJoinable = this.rootJoinable;
98         fromPart.selector = this.selector;
99         fromPart.next = this.next == null ? null : this.next.getFromPart();
100         fromPart.isFromPart = true;
101         return fromPart;
102     }
103
104     public JoinSequence copy() {
105         JoinSequence copy = new JoinSequence( factory );
106         copy.joins.addAll( this.joins );
107         copy.useThetaStyle = this.useThetaStyle;
108         copy.rootAlias = this.rootAlias;
109         copy.rootJoinable = this.rootJoinable;
110         copy.selector = this.selector;
111         copy.next = this.next == null ? null : this.next.copy();
112         copy.isFromPart = this.isFromPart;
113         copy.conditions.append( this.conditions.toString() );
114         return copy;
115     }
116
117     public JoinSequence addJoin(AssociationType associationType, String JavaDoc alias, int joinType, String JavaDoc[] referencingKey)
118             throws MappingException {
119         joins.add( new Join( associationType, alias, joinType, referencingKey ) );
120         return this;
121     }
122
123     public JoinFragment toJoinFragment() throws MappingException {
124         return toJoinFragment( CollectionHelper.EMPTY_MAP, true );
125     }
126
127     public JoinFragment toJoinFragment(Map JavaDoc enabledFilters, boolean includeExtraJoins) throws MappingException {
128         return toJoinFragment( enabledFilters, includeExtraJoins, null );
129     }
130
131     public JoinFragment toJoinFragment(Map JavaDoc enabledFilters, boolean includeExtraJoins, String JavaDoc extraOnClause) throws MappingException {
132         QueryJoinFragment joinFragment = new QueryJoinFragment( factory.getDialect(), useThetaStyle );
133         if ( rootJoinable != null ) {
134             joinFragment.addCrossJoin( rootJoinable.getTableName(), rootAlias );
135             String JavaDoc filterCondition = rootJoinable.filterFragment( rootAlias, enabledFilters );
136             // JoinProcessor needs to know if the where clause fragment came from a dynamic filter or not so it
137
// can put the where clause fragment in the right place in the SQL AST. 'hasFilterCondition' keeps track
138
// of that fact.
139
joinFragment.setHasFilterCondition( joinFragment.addCondition( filterCondition ) );
140             if (includeExtraJoins) { //TODO: not quite sure about the full implications of this!
141
addExtraJoins( joinFragment, rootAlias, rootJoinable, true );
142             }
143         }
144
145         Joinable last = rootJoinable;
146
147         for ( int i = 0; i < joins.size(); i++ ) {
148             Join join = ( Join ) joins.get( i );
149             String JavaDoc on = join.getAssociationType().getOnCondition( join.getAlias(), factory, enabledFilters );
150             String JavaDoc condition = null;
151             if ( last != null &&
152                     isManyToManyRoot( last ) &&
153                     ( ( QueryableCollection ) last ).getElementType() == join.getAssociationType() ) {
154                 // the current join represents the join between a many-to-many association table
155
// and its "target" table. Here we need to apply any additional filters
156
// defined specifically on the many-to-many
157
String JavaDoc manyToManyFilter = ( ( QueryableCollection ) last )
158                         .getManyToManyFilterFragment( join.getAlias(), enabledFilters );
159                 condition = "".equals( manyToManyFilter )
160                         ? on
161                         : "".equals( on )
162                                 ? manyToManyFilter
163                                 : on + " and " + manyToManyFilter;
164             }
165             else {
166                 condition = on;
167             }
168             if ( extraOnClause != null ) {
169                 condition += " and " + extraOnClause;
170             }
171             joinFragment.addJoin(
172                     join.getJoinable().getTableName(),
173                     join.getAlias(),
174                     join.getLHSColumns(),
175                     JoinHelper.getRHSColumnNames( join.getAssociationType(), factory ),
176                     join.joinType,
177                     condition
178             );
179             if (includeExtraJoins) { //TODO: not quite sure about the full implications of this!
180
addExtraJoins( joinFragment, join.getAlias(), join.getJoinable(), join.joinType == JoinFragment.INNER_JOIN );
181             }
182             last = join.getJoinable();
183         }
184         if ( next != null ) {
185             joinFragment.addFragment( next.toJoinFragment( enabledFilters, includeExtraJoins ) );
186         }
187         joinFragment.addCondition( conditions.toString() );
188         if ( isFromPart ) joinFragment.clearWherePart();
189         return joinFragment;
190     }
191
192     private boolean isManyToManyRoot(Joinable joinable) {
193         if ( joinable != null && joinable.isCollection() ) {
194             QueryableCollection persister = ( QueryableCollection ) joinable;
195             return persister.isManyToMany();
196         }
197         return false;
198     }
199
200     private boolean isIncluded(String JavaDoc alias) {
201         return selector != null && selector.includeSubclasses( alias );
202     }
203
204     private void addExtraJoins(JoinFragment joinFragment, String JavaDoc alias, Joinable joinable, boolean innerJoin) {
205         boolean include = isIncluded( alias );
206         joinFragment.addJoins( joinable.fromJoinFragment( alias, innerJoin, include ),
207                 joinable.whereJoinFragment( alias, innerJoin, include ) );
208     }
209
210     public JoinSequence addCondition(String JavaDoc condition) {
211         if ( condition.trim().length() != 0 ) {
212             if ( !condition.startsWith( " and " ) ) conditions.append( " and " );
213             conditions.append( condition );
214         }
215         return this;
216     }
217
218     public JoinSequence addCondition(String JavaDoc alias, String JavaDoc[] columns, String JavaDoc condition) {
219         for ( int i = 0; i < columns.length; i++ ) {
220             conditions.append( " and " )
221                     .append( alias )
222                     .append( '.' )
223                     .append( columns[i] )
224                     .append( condition );
225         }
226         return this;
227     }
228
229     public JoinSequence setRoot(Joinable joinable, String JavaDoc alias) {
230         this.rootAlias = alias;
231         this.rootJoinable = joinable;
232         return this;
233     }
234
235     public JoinSequence setNext(JoinSequence next) {
236         this.next = next;
237         return this;
238     }
239
240     public JoinSequence setSelector(Selector s) {
241         this.selector = s;
242         return this;
243     }
244
245     public JoinSequence setUseThetaStyle(boolean useThetaStyle) {
246         this.useThetaStyle = useThetaStyle;
247         return this;
248     }
249
250     public boolean isThetaStyle() {
251         return useThetaStyle;
252     }
253
254     public int getJoinCount() {
255         return joins.size();
256     }
257     
258     public static interface Selector {
259         public boolean includeSubclasses(String JavaDoc alias);
260     }
261 }
262
Popular Tags