KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > hql > ast > util > JoinProcessor


1 // $Id: JoinProcessor.java,v 1.1 2005/07/12 20:27:22 steveebersole Exp $
2
package org.hibernate.hql.ast.util;
3
4 import java.util.ArrayList JavaDoc;
5 import java.util.Iterator JavaDoc;
6 import java.util.ListIterator JavaDoc;
7
8 import org.hibernate.AssertionFailure;
9 import org.hibernate.engine.JoinSequence;
10 import org.hibernate.hql.antlr.SqlTokenTypes;
11 import org.hibernate.hql.ast.QueryTranslatorImpl;
12 import org.hibernate.hql.ast.tree.FromClause;
13 import org.hibernate.hql.ast.tree.FromElement;
14 import org.hibernate.hql.ast.tree.QueryNode;
15 import org.hibernate.sql.JoinFragment;
16 import org.hibernate.util.StringHelper;
17
18 import antlr.ASTFactory;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22
23 /**
24  * Performs the post-processing of the join information gathered during semantic analysis.
25  * The join generating classes are complex, this encapsulates some of the JoinSequence-related
26  * code.
27  *
28  * @author josh Jul 22, 2004 7:33:42 AM
29  */

30 public class JoinProcessor implements SqlTokenTypes {
31
32     private static final Log log = LogFactory.getLog( JoinProcessor.class );
33
34     private QueryTranslatorImpl queryTranslatorImpl;
35     private SyntheticAndFactory andFactory;
36
37     /**
38      * Constructs a new JoinProcessor.
39      *
40      * @param astFactory The factory for AST node creation.
41      * @param queryTranslatorImpl The query translator.
42      */

43     public JoinProcessor(ASTFactory astFactory, QueryTranslatorImpl queryTranslatorImpl) {
44         this.andFactory = new SyntheticAndFactory( astFactory );
45         this.queryTranslatorImpl = queryTranslatorImpl;
46     }
47
48     /**
49      * Translates an AST join type (i.e., the token type) into a JoinFragment.XXX join type.
50      *
51      * @param astJoinType The AST join type (from HqlSqlTokenTypes or SqlTokenTypes)
52      * @return a JoinFragment.XXX join type.
53      * @see JoinFragment
54      * @see SqlTokenTypes
55      */

56     public static int toHibernateJoinType(int astJoinType) {
57         switch ( astJoinType ) {
58             case LEFT_OUTER:
59                 return JoinFragment.LEFT_OUTER_JOIN;
60             case INNER:
61                 return JoinFragment.INNER_JOIN;
62             case RIGHT_OUTER:
63                 return JoinFragment.RIGHT_OUTER_JOIN;
64             default:
65                 throw new AssertionFailure( "undefined join type " + astJoinType );
66         }
67     }
68
69     public void processJoins(QueryNode query) {
70         final FromClause fromClause = query.getFromClause();
71
72         // TODO : found it easiest to simply reorder the FromElements here into ascending order
73
// in terms of injecting them into the resulting sql ast in orders relative to those
74
// expected by the old parser; this is definitely another of those "only needed
75
// for regression purposes". The SyntheticAndFactory, then, simply injects them as it
76
// encounters them.
77
ArrayList JavaDoc orderedFromElements = new ArrayList JavaDoc();
78         ListIterator JavaDoc liter = fromClause.getFromElements().listIterator( fromClause.getFromElements().size() );
79         while ( liter.hasPrevious() ) {
80             orderedFromElements.add( liter.previous() );
81         }
82
83         // Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
84
Iterator JavaDoc iter = orderedFromElements.iterator();
85         while ( iter.hasNext() ) {
86             final FromElement fromElement = ( FromElement ) iter.next();
87             JoinSequence join = fromElement.getJoinSequence();
88             join.setSelector(
89                     new JoinSequence.Selector() {
90                         public boolean includeSubclasses(String JavaDoc alias) {
91                             boolean shallowQuery = queryTranslatorImpl.isShallowQuery();
92                             boolean containsTableAlias = fromClause.containsTableAlias( alias );
93                             boolean includeSubclasses = fromElement.isIncludeSubclasses();
94                             boolean subQuery = fromClause.isSubQuery();
95                             return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
96                         }
97                     }
98             );
99             addJoinNodes( query, join, fromElement );
100         } // while
101

102     }
103
104     private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement) {
105         // Generate FROM and WHERE fragments for the from element.
106
JoinFragment joinFragment = join.toJoinFragment(
107                 queryTranslatorImpl.getEnabledFilters(),
108                 fromElement.useFromFragment(),
109                 fromElement.getAdHocOnClauseFragment()
110         );
111
112         String JavaDoc frag = joinFragment.toFromFragmentString();
113         String JavaDoc whereFrag = joinFragment.toWhereFragmentString();
114
115         // If the from element represents a JOIN_FRAGMENT and it is
116
// a theta-style join, convert its type from JOIN_FRAGMENT
117
// to FROM_FRAGMENT
118
if ( fromElement.getType() == JOIN_FRAGMENT &&
119                 ( join.isThetaStyle() || StringHelper.isNotEmpty( whereFrag ) ) ) {
120             fromElement.setType( FROM_FRAGMENT );
121         }
122
123         // If there is a FROM fragment and the FROM element is an explicit, then add the from part.
124
if ( fromElement.useFromFragment() /*&& StringHelper.isNotEmpty( frag )*/ ) {
125             String JavaDoc fromFragment = processFromFragment( frag, join );
126             if ( log.isDebugEnabled() ) log.debug( "Using FROM fragment [" + fromFragment + "]" );
127             fromElement.setText( fromFragment.trim() ); // Set the text of the fromElement.
128
}
129         andFactory.addWhereFragment( joinFragment, whereFrag, query, fromElement );
130     }
131
132     private String JavaDoc processFromFragment(String JavaDoc frag, JoinSequence join) {
133         String JavaDoc fromFragment = frag.trim();
134         // The FROM fragment will probably begin with ', '. Remove this if it is present.
135
if ( fromFragment.startsWith( ", " ) ) {
136             fromFragment = fromFragment.substring( 2 );
137         }
138         /*
139         // *** BEGIN FROM FRAGMENT VOODOO ***
140         // If there is more than one join, reverse the order of the tables in the FROM fragment.
141         if ( join.getJoinCount() > 1 && fromFragment.indexOf( ',' ) >= 0 ) {
142             String[] froms = StringHelper.split( ",", fromFragment );
143             StringBuffer buf = new StringBuffer();
144             for ( int i = froms.length - 1; i >= 0; i-- ) {
145                 buf.append( froms[i] );
146                 if ( i > 0 ) {
147                     buf.append( ", " );
148                 }
149             }
150             fromFragment = buf.toString();
151         }
152         // *** END OF FROM FRAGMENT VOODOO ***
153         */

154         return fromFragment;
155     }
156
157 }
158
Popular Tags