KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > hql > ast > tree > FromElementType


1 // $Id: FromElementType.java,v 1.1 2005/07/12 20:27:16 steveebersole Exp $
2
package org.hibernate.hql.ast.tree;
3
4 import java.util.Map JavaDoc;
5
6 import org.hibernate.MappingException;
7 import org.hibernate.engine.JoinSequence;
8 import org.hibernate.hql.CollectionProperties;
9 import org.hibernate.hql.CollectionSubqueryFactory;
10 import org.hibernate.hql.NameGenerator;
11 import org.hibernate.persister.collection.CollectionPropertyMapping;
12 import org.hibernate.persister.collection.QueryableCollection;
13 import org.hibernate.persister.entity.EntityPersister;
14 import org.hibernate.persister.entity.Joinable;
15 import org.hibernate.persister.entity.PropertyMapping;
16 import org.hibernate.persister.entity.Queryable;
17 import org.hibernate.type.EntityType;
18 import org.hibernate.type.Type;
19 import org.hibernate.type.TypeFactory;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24 /**
25  * Delegate that handles the type and join sequence information for a FromElement.
26  *
27  * @author josh Feb 12, 2005 10:17:34 AM
28  */

29 class FromElementType {
30     private static final Log log = LogFactory.getLog( FromElementType.class );
31
32     private FromElement fromElement;
33     private EntityType entityType;
34     private EntityPersister persister;
35     private QueryableCollection queryableCollection;
36     private CollectionPropertyMapping collectionPropertyMapping;
37     private JoinSequence joinSequence;
38
39     private String JavaDoc collectionSuffix;
40
41     public FromElementType(FromElement fromElement, EntityPersister persister, EntityType entityType) {
42         this.fromElement = fromElement;
43         this.persister = persister;
44         this.entityType = entityType;
45         if ( persister != null ) {
46             fromElement.setText( ( ( Queryable ) persister ).getTableName() + " " + getTableAlias() );
47         }
48     }
49
50     private String JavaDoc getTableAlias() {
51         return fromElement.getTableAlias();
52     }
53
54     private String JavaDoc getCollectionTableAlias() {
55         return fromElement.getCollectionTableAlias();
56     }
57
58     public String JavaDoc getCollectionSuffix() {
59         return collectionSuffix;
60     }
61
62     public void setCollectionSuffix(String JavaDoc suffix) {
63         collectionSuffix = suffix;
64     }
65
66     public EntityPersister getEntityPersister() {
67         return persister;
68     }
69
70     public Type getDataType() {
71         if ( persister == null ) {
72             if ( queryableCollection == null ) {
73                 return null;
74             }
75             return queryableCollection.getType();
76         }
77         else {
78             return entityType;
79         }
80     }
81
82     public Type getSelectType() {
83         if (entityType==null) return null;
84         boolean shallow = fromElement.getFromClause().getWalker().isShallowQuery();
85         return TypeFactory.manyToOne( entityType.getAssociatedEntityName(), shallow );
86     }
87
88     /**
89      * Returns the Hibernate queryable implementation for the HQL class.
90      *
91      * @return the Hibernate queryable implementation for the HQL class.
92      */

93     public Queryable getQueryable() {
94         return ( persister instanceof Queryable ) ? ( Queryable ) persister : null;
95     }
96
97     /**
98      * Render the identifier select, but in a 'scalar' context (i.e. generate the column alias).
99      *
100      * @param i the sequence of the returned type
101      * @return the identifier select with the column alias.
102      */

103     String JavaDoc renderScalarIdentifierSelect(int i) {
104         checkInitialized();
105         String JavaDoc[] cols = getPropertyMapping( EntityPersister.ENTITY_ID ).toColumns( getTableAlias(), EntityPersister.ENTITY_ID );
106         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
107         // For property references generate <tablealias>.<columnname> as <projectionalias>
108
for ( int j = 0; j < cols.length; j++ ) {
109             String JavaDoc column = cols[j];
110             if ( j > 0 ) {
111                 buf.append( ", " );
112             }
113             buf.append( column ).append( " as " ).append( NameGenerator.scalarName( i, j ) );
114         }
115         return buf.toString();
116     }
117
118     /**
119      * Returns the identifier select SQL fragment.
120      *
121      * @param size The total number of returned types.
122      * @param k The sequence of the current returned type.
123      * @return the identifier select SQL fragment.
124      */

125     String JavaDoc renderIdentifierSelect(int size, int k) {
126         checkInitialized();
127         // Render the identifier select fragment using the table alias.
128
if ( fromElement.getFromClause().isSubQuery() ) {
129             // TODO: Replace this with a more elegant solution.
130
String JavaDoc[] idColumnNames = ( persister != null ) ?
131                     ( ( Queryable ) persister ).getIdentifierColumnNames() : new String JavaDoc[0];
132             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
133             for ( int i = 0; i < idColumnNames.length; i++ ) {
134                 buf.append( fromElement.getTableAlias() ).append( '.' ).append( idColumnNames[i] );
135                 if ( i != idColumnNames.length - 1 ) buf.append( ", " );
136             }
137             return buf.toString();
138         }
139         else {
140             String JavaDoc fragment = ( ( Queryable ) persister ).identifierSelectFragment( getTableAlias(), getSuffix( size, k ) );
141             return trimLeadingCommaAndSpaces( fragment );
142         }
143     }
144
145     private String JavaDoc getSuffix(int size, int sequence) {
146         return generateSuffix( size, sequence );
147     }
148
149     private static String JavaDoc generateSuffix(int size, int k) {
150         String JavaDoc suffix = size == 1 ? "" : Integer.toString( k ) + '_';
151         return suffix;
152     }
153
154     private void checkInitialized() {
155         fromElement.checkInitialized();
156     }
157
158     /**
159      * Returns the property select SQL fragment.
160      * @param size The total number of returned types.
161      * @param k The sequence of the current returned type.
162      * @return the property select SQL fragment.
163      */

164     String JavaDoc renderPropertySelect(int size, int k, boolean allProperties) {
165         checkInitialized();
166         if ( persister == null ) {
167             return "";
168         }
169         else {
170             String JavaDoc fragment = ( ( Queryable ) persister ).propertySelectFragment(
171                     getTableAlias(),
172                     getSuffix( size, k ),
173                     allProperties
174                 );
175             return trimLeadingCommaAndSpaces( fragment );
176         }
177     }
178
179     String JavaDoc renderCollectionSelectFragment(int size, int k) {
180         if ( queryableCollection == null ) {
181             return "";
182         }
183         else {
184             if ( collectionSuffix == null ) {
185                 collectionSuffix = generateSuffix( size, k );
186             }
187             String JavaDoc fragment = queryableCollection.selectFragment( getCollectionTableAlias(), collectionSuffix );
188             return trimLeadingCommaAndSpaces( fragment );
189         }
190     }
191
192     public String JavaDoc renderValueCollectionSelectFragment(int size, int k) {
193         if ( queryableCollection == null ) {
194             return "";
195         }
196         else {
197             if ( collectionSuffix == null ) {
198                 collectionSuffix = generateSuffix( size, k );
199             }
200             String JavaDoc fragment = queryableCollection.selectFragment( getTableAlias(), collectionSuffix );
201             return trimLeadingCommaAndSpaces( fragment );
202         }
203     }
204
205     /**
206      * This accounts for a quirk in Queryable, where it sometimes generates ', ' in front of the
207      * SQL fragment. :-P
208      *
209      * @param fragment An SQL fragment.
210      * @return The fragment, without the leading comma and spaces.
211      */

212     private static String JavaDoc trimLeadingCommaAndSpaces(String JavaDoc fragment) {
213         if ( fragment.length() > 0 && fragment.charAt( 0 ) == ',' ) {
214             fragment = fragment.substring( 1 );
215         }
216         fragment = fragment.trim();
217         return fragment.trim();
218     }
219
220     public void setJoinSequence(JoinSequence joinSequence) {
221         this.joinSequence = joinSequence;
222     }
223
224     public JoinSequence getJoinSequence() {
225         if ( joinSequence != null ) {
226             return joinSequence;
227         }
228
229         // Class names in the FROM clause result in a JoinSequence (the old FromParser does this).
230
if ( persister instanceof Joinable ) {
231             Joinable joinable = ( Joinable ) persister;
232             return fromElement.getSessionFactoryHelper().createJoinSequence().setRoot( joinable, getTableAlias() );
233         }
234         else {
235             return null; // TODO: Should this really return null? If not, figure out something better to do here.
236
}
237     }
238
239     public void setQueryableCollection(QueryableCollection queryableCollection) {
240         if ( this.queryableCollection != null ) {
241             throw new IllegalStateException JavaDoc( "QueryableCollection is already defined for " + this + "!" );
242         }
243         this.queryableCollection = queryableCollection;
244         if ( !queryableCollection.isOneToMany() ) {
245             // For many-to-many joins, use the tablename from the queryable collection for the default text.
246
fromElement.setText( queryableCollection.getTableName() + " " + getTableAlias() );
247         }
248     }
249
250     public QueryableCollection getQueryableCollection() {
251         return queryableCollection;
252     }
253
254     /**
255      * Returns the type of a property, given it's name (the last part) and the full path.
256      *
257      * @param propertyName The last part of the full path to the property.
258      * @return The type.
259      * @0param propertyPath The full property path.
260      */

261     public Type getPropertyType(String JavaDoc propertyName, String JavaDoc propertyPath) {
262         checkInitialized();
263         Type type = null;
264         // If this is an entity and the property is the identifier property, then use getIdentifierType().
265
// Note that the propertyName.equals( propertyPath ) checks whether we have a component
266
// key reference, where the component class property name is the same as the
267
// entity id property name; if the two are not equal, this is the case and
268
// we'd need to "fall through" to using the property mapping.
269
if ( persister != null && propertyName.equals( propertyPath ) && propertyName.equals( persister.getIdentifierPropertyName() ) ) {
270             type = persister.getIdentifierType();
271         }
272         else { // Otherwise, use the property mapping.
273
PropertyMapping mapping = getPropertyMapping( propertyName );
274             type = mapping.toType( propertyPath );
275         }
276         if ( type == null ) {
277             throw new MappingException( "Property " + propertyName + " does not exist in " +
278                     ( ( queryableCollection == null ) ? "class" : "collection" ) + " "
279                     + ( ( queryableCollection == null ) ? fromElement.getClassName() : queryableCollection.getRole() ) );
280         }
281         return type;
282     }
283
284     String JavaDoc[] toColumns(String JavaDoc tableAlias, String JavaDoc path, boolean inSelect) {
285         checkInitialized();
286         PropertyMapping propertyMapping = getPropertyMapping( path );
287         // If this from element is a collection and the path is a collection property (maxIndex, etc.) then
288
// generate a sub-query.
289
if ( !inSelect && queryableCollection != null && CollectionProperties.isCollectionProperty( path ) ) {
290             Map JavaDoc enabledFilters = fromElement.getWalker().getEnabledFilters();
291             String JavaDoc subquery = CollectionSubqueryFactory.createCollectionSubquery( joinSequence, enabledFilters,
292                     propertyMapping.toColumns( tableAlias, path ) );
293             if ( log.isDebugEnabled() ) {
294                 log.debug( "toColumns(" + tableAlias + "," + path + ") : subquery = " + subquery );
295             }
296             return new String JavaDoc[]{"(" + subquery + ")"};
297         }
298         else {
299             if ( fromElement.getWalker().isSelectStatement() ) {
300                 return propertyMapping.toColumns( tableAlias, path );
301             }
302             else {
303                 return propertyMapping.toColumns( path );
304             }
305         }
306     }
307
308     PropertyMapping getPropertyMapping(String JavaDoc propertyName) {
309         checkInitialized();
310         if ( queryableCollection == null ) { // Not a collection?
311
return ( PropertyMapping ) persister; // Return the entity property mapping.
312
}
313         // If the property is a special collection property name, return a CollectionPropertyMapping.
314
if ( CollectionProperties.isCollectionProperty( propertyName ) ) {
315             if ( collectionPropertyMapping == null ) {
316                 collectionPropertyMapping = new CollectionPropertyMapping( queryableCollection );
317             }
318             return collectionPropertyMapping;
319         }
320         if ( queryableCollection.getElementType().isComponentType() ) { // Collection of components.
321
if ( propertyName.equals( EntityPersister.ENTITY_ID ) ) {
322                 return ( PropertyMapping ) queryableCollection.getOwnerEntityPersister();
323             }
324         }
325         return queryableCollection;
326     }
327
328     public boolean isCollectionOfValuesOrComponents() {
329         if ( persister == null ) {
330             if ( queryableCollection == null ) {
331                 return false;
332             }
333             else {
334                 return !queryableCollection.getElementType().isEntityType();
335             }
336         }
337         else {
338             return false;
339         }
340     }
341
342     public boolean isEntity() {
343         return persister != null;
344     }
345 }
346
Popular Tags