KickJava   Java API By Example, From Geeks To Geeks.

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


1 // $Id: SessionFactoryHelper.java,v 1.2 2005/07/20 19:35:21 steveebersole Exp $
2
package org.hibernate.hql.ast.util;
3
4 import java.util.HashMap JavaDoc;
5 import java.util.Map JavaDoc;
6
7 import org.hibernate.MappingException;
8 import org.hibernate.QueryException;
9 import org.hibernate.dialect.function.SQLFunction;
10 import org.hibernate.engine.JoinSequence;
11 import org.hibernate.engine.SessionFactoryImplementor;
12 import org.hibernate.hql.NameGenerator;
13 import org.hibernate.hql.ast.DetailedSemanticException;
14 import org.hibernate.hql.ast.QuerySyntaxException;
15 import org.hibernate.hql.ast.tree.SqlNode;
16 import org.hibernate.persister.collection.CollectionPropertyMapping;
17 import org.hibernate.persister.collection.CollectionPropertyNames;
18 import org.hibernate.persister.collection.QueryableCollection;
19 import org.hibernate.persister.entity.EntityPersister;
20 import org.hibernate.persister.entity.PropertyMapping;
21 import org.hibernate.persister.entity.Queryable;
22 import org.hibernate.type.AssociationType;
23 import org.hibernate.type.CollectionType;
24 import org.hibernate.type.EntityType;
25 import org.hibernate.type.Type;
26 import org.hibernate.type.TypeFactory;
27
28 import antlr.SemanticException;
29 import antlr.collections.AST;
30
31 /**
32  * Wraps SessionFactoryImpl, adding more lookup behaviors and encapsulating some of the error handling.
33  *
34  * @author josh Jul 24, 2004 6:44:00 PM
35  */

36 public class SessionFactoryHelper {
37     private SessionFactoryImplementor sfi;
38     private Map JavaDoc collectionPropertyMappingByRole;
39
40     /**
41      * Construct a new SessionFactoryHelper instance.
42      *
43      * @param sfi The SessionFactory impl to be encapsualted.
44      */

45     public SessionFactoryHelper(SessionFactoryImplementor sfi) {
46         this.sfi = sfi;
47         collectionPropertyMappingByRole = new HashMap JavaDoc();
48     }
49
50     /**
51      * Get a handle to the encapsulated SessionFactory.
52      *
53      * @return The encapsulated SessionFactory.
54      */

55     public SessionFactoryImplementor getFactory() {
56         return sfi;
57     }
58
59     /**
60      * Does the given persister define a physical discriminator column
61      * for the purpose of inheritence discrimination?
62      *
63      * @param persister The persister to be checked.
64      * @return True if the persister does define an actual discriminator column.
65      */

66     public boolean hasPhysicalDiscriminatorColumn(Queryable persister) {
67         if ( persister.getDiscriminatorType() != null ) {
68             String JavaDoc discrimColumnName = persister.getDiscriminatorColumnName();
69             // Needed the "clazz_" check to work around union-subclasses
70
// TODO : is there a way to tell whether a persister is truly discrim-column based inheritence?
71
if ( discrimColumnName != null && !"clazz_".equals( discrimColumnName ) ) {
72                 return true;
73             }
74         }
75         return false;
76     }
77
78     /**
79      * Given a (potentially unqualified) class name, locate its imported qualified name.
80      *
81      * @param className The potentially unqualified class name
82      * @return The qualified class name.
83      */

84     public String JavaDoc getImportedClassName(String JavaDoc className) {
85         return sfi.getImportedClassName( className );
86     }
87
88     /**
89      * Given a (potentially unqualified) class name, locate its persister.
90      *
91      * @param className The (potentially unqualified) class name.
92      * @return The defined persister for this class, or null if none found.
93      */

94     public Queryable findQueryableUsingImports(String JavaDoc className) {
95         final String JavaDoc importedClassName = sfi.getImportedClassName( className );
96         if ( importedClassName == null ) {
97             return null;
98         }
99         try {
100             return ( Queryable ) sfi.getEntityPersister( importedClassName );
101         }
102         catch ( MappingException me ) {
103             return null;
104         }
105     }
106
107     /**
108      * Locate the persister by class or entity name.
109      *
110      * @param name The class or entity name
111      * @return The defined persister for this entity, or null if none found.
112      * @throws MappingException
113      */

114     private EntityPersister findEntityPersisterByName(String JavaDoc name) throws MappingException {
115         // First, try to get the persister using the class name directly.
116
try {
117             return sfi.getEntityPersister( name );
118         }
119         catch ( MappingException ignore ) {
120             // unable to locate it using this name
121
}
122
123         // If that didn't work, try using the 'import' name.
124
String JavaDoc importedClassName = sfi.getImportedClassName( name );
125         if ( importedClassName == null ) {
126             return null;
127         }
128         return sfi.getEntityPersister( importedClassName );
129     }
130
131     /**
132      * Locate the persister by class or entity name, requiring that such a persister
133      * exist.
134      *
135      * @param name The class or entity name
136      * @return The defined persister for this entity
137      * @throws SemanticException Indicates the persister could not be found
138      */

139     public EntityPersister requireClassPersister(String JavaDoc name) throws SemanticException {
140         EntityPersister cp;
141         try {
142             cp = findEntityPersisterByName( name );
143             if ( cp == null ) {
144 // throw new SemanticException( name + " is not mapped." );
145
throw new QuerySyntaxException( new SemanticException( name + " is not mapped." ) );
146             }
147         }
148         catch ( MappingException e ) {
149             throw new DetailedSemanticException( e.getMessage(), e );
150         }
151         return cp;
152     }
153
154     /**
155      * Locate the collection persister by the collection role.
156      *
157      * @param role The collection role name.
158      * @return The defined CollectionPersister for this collection role, or null.
159      */

160     public QueryableCollection getCollectionPersister(String JavaDoc role) {
161         try {
162             return ( QueryableCollection ) sfi.getCollectionPersister( role );
163         }
164         catch ( ClassCastException JavaDoc cce ) {
165             throw new QueryException( "collection is not queryable: " + role );
166         }
167         catch ( Exception JavaDoc e ) {
168             throw new QueryException( "collection not found: " + role );
169         }
170     }
171
172     /**
173      * Locate the collection persister by the collection role, requiring that
174      * such a persister exist.
175      *
176      * @param role The collection role name.
177      * @return The defined CollectionPersister for this collection role.
178      * @throws QueryException Indicates that the collection persister could not be found.
179      */

180     public QueryableCollection requireQueryableCollection(String JavaDoc role) throws QueryException {
181         try {
182             QueryableCollection queryableCollection = ( QueryableCollection ) sfi.getCollectionPersister( role );
183             if ( queryableCollection != null ) {
184                 collectionPropertyMappingByRole.put( role, new CollectionPropertyMapping( queryableCollection ) );
185             }
186             return queryableCollection;
187         }
188         catch ( ClassCastException JavaDoc cce ) {
189             throw new QueryException( "collection role is not queryable: " + role );
190         }
191         catch ( Exception JavaDoc e ) {
192             throw new QueryException( "collection role not found: " + role );
193         }
194     }
195
196     /**
197      * Retreive a PropertyMapping describing the given collection role.
198      *
199      * @param role The collection role for whcih to retrieve the property mapping.
200      * @return The property mapping.
201      */

202     private PropertyMapping getCollectionPropertyMapping(String JavaDoc role) {
203         return ( PropertyMapping ) collectionPropertyMappingByRole.get( role );
204     }
205
206     /**
207      * Retrieves the column names corresponding to the collection elements for the given
208      * collection role.
209      *
210      * @param role The collection role
211      * @param roleAlias The sql column-qualification alias (i.e., the table alias)
212      * @return
213      */

214     public String JavaDoc[] getCollectionElementColumns(String JavaDoc role, String JavaDoc roleAlias) {
215         return getCollectionPropertyMapping( role ).toColumns( roleAlias, CollectionPropertyNames.COLLECTION_ELEMENTS );
216     }
217
218     /**
219      * Generate an empty join sequence instance.
220      *
221      * @return The generate join sequence.
222      */

223     public JoinSequence createJoinSequence() {
224         return new JoinSequence( sfi );
225     }
226
227     /**
228      * Generate a join sequence representing the given association type.
229      *
230      * @param implicit Should implicit joins (theta-style) or explicit joins (ANSI-style) be rendered
231      * @param associationType The type representing the thing to be joined into.
232      * @param tableAlias The table alias to use in qualifing the join conditions
233      * @param joinType The type of join to render (inner, outer, etc); see {@link org.hibernate.sql.JoinFragment}
234      * @param columns The columns making up the condition of the join.
235      * @return The generated join sequence.
236      */

237     public JoinSequence createJoinSequence(boolean implicit, AssociationType associationType, String JavaDoc tableAlias, int joinType, String JavaDoc[] columns) {
238         JoinSequence joinSequence = createJoinSequence();
239         joinSequence.setUseThetaStyle( implicit ); // Implicit joins use theta style (WHERE pk = fk), explicit joins use JOIN (after from)
240
joinSequence.addJoin( associationType, tableAlias, joinType, columns );
241         return joinSequence;
242     }
243
244     /**
245      * Create a join sequence rooted at the given collection.
246      *
247      * @param collPersister The persister for the collection at which the join should be rooted.
248      * @param collectionName The alias to use for qualifying column references.
249      * @return The generated join sequence.
250      */

251     public JoinSequence createCollectionJoinSequence(QueryableCollection collPersister, String JavaDoc collectionName) {
252         JoinSequence joinSequence = createJoinSequence();
253         joinSequence.setRoot( collPersister, collectionName );
254         joinSequence.setUseThetaStyle( true ); // TODO: figure out how this should be set.
255
///////////////////////////////////////////////////////////////////////////////
256
// This was the reason for failures regarding INDEX_OP and subclass joins on
257
// theta-join dialects; not sure what behaviour we were trying to emulate ;)
258
// joinSequence = joinSequence.getFromPart(); // Emulate the old addFromOnly behavior.
259
return joinSequence;
260     }
261
262     /**
263      * Determine the name of the property for the entity encapsulated by the
264      * given type which represents the id or unique-key.
265      *
266      * @param entityType The type representing the entity.
267      * @return The corresponding property name
268      * @throws QueryException Indicates such a property could not be found.
269      */

270     public String JavaDoc getIdentifierOrUniqueKeyPropertyName(EntityType entityType) {
271         try {
272             return entityType.getIdentifierOrUniqueKeyPropertyName( sfi );
273         }
274         catch ( MappingException me ) {
275             throw new QueryException( me );
276         }
277     }
278
279     /**
280      * Retreive the number of columns represented by this type.
281      *
282      * @param type The type.
283      * @return The number of columns.
284      */

285     public int getColumnSpan(Type type) {
286         return type.getColumnSpan( sfi );
287     }
288
289     /**
290      * Given a collection type, determine the entity name of the elements
291      * contained within instance of that collection.
292      *
293      * @param collectionType The collection type to check.
294      * @return The entity name of the elements of this collection.
295      */

296     public String JavaDoc getAssociatedEntityName(CollectionType collectionType) {
297         return collectionType.getAssociatedEntityName( sfi );
298     }
299
300     /**
301      * Given a collection type, determine the Type representing elements
302      * within instances of that collection.
303      *
304      * @param collectionType The collection type to be checked.
305      * @return The Type of the elements of the collection.
306      */

307     private Type getElementType(CollectionType collectionType) {
308         return collectionType.getElementType( sfi );
309     }
310
311     /**
312      * Essentially the same as {@link #getElementType}, but requiring that the
313      * element type be an association type.
314      *
315      * @param collectionType The collection type to be checked.
316      * @return The AssociationType of the elements of the collection.
317      */

318     public AssociationType getElementAssociationType(CollectionType collectionType) {
319         return ( AssociationType ) getElementType( collectionType );
320     }
321
322     /**
323      * Locate a registered sql function by name.
324      *
325      * @param functionName The name of the function to locate
326      * @return The sql function, or null if not found.
327      */

328     public SQLFunction findSQLFunction(String JavaDoc functionName) {
329         return ( SQLFunction ) sfi.getDialect().getFunctions().get( functionName.toLowerCase() );
330     }
331
332     /**
333      * Locate a registered sql function by name, requiring that such a registered function exist.
334      *
335      * @param functionName The name of the function to locate
336      * @return The sql function.
337      * @throws QueryException Indicates no matching sql functions could be found.
338      */

339     private SQLFunction requireSQLFunction(String JavaDoc functionName) {
340         SQLFunction f = findSQLFunction( functionName );
341         if ( f == null ) {
342             throw new QueryException( "Unable to find SQL function: " + functionName );
343         }
344         return f;
345     }
346
347     /**
348      * Find the function return type given the function name and the first argument expression node.
349      *
350      * @param functionName The function name.
351      * @param first The first argument expression.
352      * @return the function return type given the function name and the first argument expression node.
353      */

354     public Type findFunctionReturnType(String JavaDoc functionName, AST first) {
355         Type argumentType = null;
356         if ( "cast".equals(functionName) ) {
357             argumentType = TypeFactory.heuristicType( first.getNextSibling().getText() );
358         }
359         else if ( first != null && first instanceof SqlNode ) {
360             argumentType = ( (SqlNode) first ).getDataType();
361         }
362         // This implementation is a bit strange, but then that's why this helper exists.
363
return requireSQLFunction( functionName ).getReturnType( argumentType, sfi );
364     }
365
366     public String JavaDoc[][] generateColumnNames(Type[] sqlResultTypes) {
367         return NameGenerator.generateColumnNames( sqlResultTypes, sfi );
368     }
369 }
370
Popular Tags