KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > persister > collection > AbstractCollectionPersister


1 //$Id: AbstractCollectionPersister.java,v 1.31 2005/07/19 18:28:36 maxcsaucdk Exp $
2
package org.hibernate.persister.collection;
3
4 import java.io.Serializable JavaDoc;
5 import java.sql.CallableStatement JavaDoc;
6 import java.sql.PreparedStatement JavaDoc;
7 import java.sql.ResultSet JavaDoc;
8 import java.sql.SQLException JavaDoc;
9 import java.sql.Types JavaDoc;
10 import java.util.Arrays JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.Map JavaDoc;
14
15 import org.apache.commons.logging.Log;
16 import org.apache.commons.logging.LogFactory;
17 import org.hibernate.AssertionFailure;
18 import org.hibernate.FetchMode;
19 import org.hibernate.HibernateException;
20 import org.hibernate.MappingException;
21 import org.hibernate.QueryException;
22 import org.hibernate.cache.CacheConcurrencyStrategy;
23 import org.hibernate.cache.CacheException;
24 import org.hibernate.cache.entry.CacheEntryStructure;
25 import org.hibernate.cache.entry.StructuredCollectionCacheEntry;
26 import org.hibernate.cache.entry.StructuredMapCacheEntry;
27 import org.hibernate.cache.entry.UnstructuredCacheEntry;
28 import org.hibernate.cfg.Configuration;
29 import org.hibernate.collection.PersistentCollection;
30 import org.hibernate.dialect.Dialect;
31 import org.hibernate.engine.EntityKey;
32 import org.hibernate.engine.PersistenceContext;
33 import org.hibernate.engine.SessionFactoryImplementor;
34 import org.hibernate.engine.SessionImplementor;
35 import org.hibernate.engine.SubselectFetch;
36 import org.hibernate.exception.JDBCExceptionHelper;
37 import org.hibernate.exception.SQLExceptionConverter;
38 import org.hibernate.id.IdentifierGenerator;
39 import org.hibernate.loader.collection.CollectionInitializer;
40 import org.hibernate.mapping.Collection;
41 import org.hibernate.mapping.Column;
42 import org.hibernate.mapping.Formula;
43 import org.hibernate.mapping.IdentifierCollection;
44 import org.hibernate.mapping.IndexedCollection;
45 import org.hibernate.mapping.List;
46 import org.hibernate.mapping.Selectable;
47 import org.hibernate.mapping.Table;
48 import org.hibernate.metadata.CollectionMetadata;
49 import org.hibernate.persister.entity.EntityPersister;
50 import org.hibernate.persister.entity.Loadable;
51 import org.hibernate.persister.entity.PropertyMapping;
52 import org.hibernate.pretty.MessageHelper;
53 import org.hibernate.sql.Alias;
54 import org.hibernate.sql.SelectFragment;
55 import org.hibernate.sql.Template;
56 import org.hibernate.type.AbstractComponentType;
57 import org.hibernate.type.CollectionType;
58 import org.hibernate.type.EntityType;
59 import org.hibernate.type.Type;
60 import org.hibernate.util.ArrayHelper;
61 import org.hibernate.util.CollectionHelper;
62 import org.hibernate.util.FilterHelper;
63 import org.hibernate.util.StringHelper;
64
65
66 /**
67  * Base implementation of the <tt>QueryableCollection</tt> interface.
68  *
69  * @author Gavin King
70  * @see BasicCollectionPersister
71  * @see OneToManyPersister
72  */

73 public abstract class AbstractCollectionPersister
74         implements CollectionMetadata, SQLLoadableCollection {
75     // TODO: encapsulate the protected instance variables!
76

77     private final String JavaDoc role;
78
79     //SQL statements
80
private final String JavaDoc sqlDeleteString;
81     private final String JavaDoc sqlInsertRowString;
82     private final String JavaDoc sqlUpdateRowString;
83     private final String JavaDoc sqlDeleteRowString;
84
85     private final String JavaDoc sqlOrderByString;
86     protected final String JavaDoc sqlWhereString;
87     private final String JavaDoc sqlOrderByStringTemplate;
88     private final String JavaDoc sqlWhereStringTemplate;
89     private final boolean hasOrder;
90     protected final boolean hasWhere;
91     private final int baseIndex;
92     
93     private final String JavaDoc nodeName;
94     private final String JavaDoc elementNodeName;
95     private final String JavaDoc indexNodeName;
96
97     protected final boolean indexContainsFormula;
98     protected final boolean elementIsPureFormula;
99     
100     //types
101
private final Type keyType;
102     private final Type indexType;
103     protected final Type elementType;
104     private final Type identifierType;
105
106     //columns
107
protected final String JavaDoc[] keyColumnNames;
108     protected final String JavaDoc[] indexColumnNames;
109     protected final String JavaDoc[] indexFormulaTemplates;
110     protected final boolean[] indexColumnIsSettable;
111     protected final String JavaDoc[] elementColumnNames;
112     protected final String JavaDoc[] elementFormulaTemplates;
113     protected final boolean[] elementColumnIsSettable;
114     protected final boolean[] elementColumnIsInPrimaryKey;
115     protected final String JavaDoc[] indexColumnAliases;
116     protected final String JavaDoc[] elementColumnAliases;
117     protected final String JavaDoc[] keyColumnAliases;
118     
119     protected final String JavaDoc identifierColumnName;
120     private final String JavaDoc identifierColumnAlias;
121     //private final String unquotedIdentifierColumnName;
122

123     protected final String JavaDoc qualifiedTableName;
124
125     private final String JavaDoc queryLoaderName;
126
127     private final boolean isPrimitiveArray;
128     private final boolean isArray;
129     protected final boolean hasIndex;
130     protected final boolean hasIdentifier;
131     private final boolean isLazy;
132     private final boolean isInverse;
133     private final boolean isMutable;
134     private final boolean isVersioned;
135     protected final int batchSize;
136     private final FetchMode fetchMode;
137     private final boolean hasOrphanDelete;
138     private final boolean subselectLoadable;
139
140     //extra information about the element type
141
private final Class JavaDoc elementClass;
142     private final String JavaDoc entityName;
143
144     private final Dialect dialect;
145     private final SQLExceptionConverter sqlExceptionConverter;
146     private final SessionFactoryImplementor factory;
147     private final EntityPersister ownerPersister;
148     private final IdentifierGenerator identifierGenerator;
149     private final PropertyMapping elementPropertyMapping;
150     private final EntityPersister elementPersister;
151     private final CacheConcurrencyStrategy cache;
152     private final CollectionType collectionType;
153     private CollectionInitializer initializer;
154     
155     private final CacheEntryStructure cacheEntryStructure;
156
157     // dynamic filters for the collection
158
private final FilterHelper filterHelper;
159
160     // dynamic filters specifically for many-to-many inside the collection
161
private final FilterHelper manyToManyFilterHelper;
162
163     private final String JavaDoc manyToManyWhereString;
164     private final String JavaDoc manyToManyWhereTemplate;
165
166     // custom sql
167
private final boolean insertCallable;
168     private final boolean updateCallable;
169     private final boolean deleteCallable;
170     private final boolean deleteAllCallable;
171
172     private final Serializable JavaDoc[] spaces;
173
174     private Map JavaDoc collectionPropertyColumnAliases = new HashMap JavaDoc();
175     private Map JavaDoc collectionPropertyColumnNames = new HashMap JavaDoc();
176
177     private static final Log log = LogFactory.getLog( AbstractCollectionPersister.class );
178
179     public AbstractCollectionPersister(
180             final Collection collection,
181             final CacheConcurrencyStrategy cache,
182             final Configuration cfg,
183             final SessionFactoryImplementor factory)
184     throws MappingException, CacheException {
185
186         this.factory = factory;
187         this.cache = cache;
188         if ( factory.getSettings().isStructuredCacheEntriesEnabled() ) {
189             cacheEntryStructure = collection.isMap() ?
190                     (CacheEntryStructure) new StructuredMapCacheEntry() :
191                     (CacheEntryStructure) new StructuredCollectionCacheEntry();
192         }
193         else {
194             cacheEntryStructure = new UnstructuredCacheEntry();
195         }
196         
197         dialect = factory.getDialect();
198         sqlExceptionConverter = factory.getSQLExceptionConverter();
199         collectionType = collection.getCollectionType();
200         role = collection.getRole();
201         entityName = collection.getOwnerEntityName();
202         ownerPersister = factory.getEntityPersister(entityName);
203         queryLoaderName = collection.getLoaderName();
204         nodeName = collection.getNodeName();
205         isMutable = collection.isMutable();
206
207         Table table = collection.getCollectionTable();
208         fetchMode = collection.getElement().getFetchMode();
209         elementType = collection.getElement().getType();
210         //isSet = collection.isSet();
211
//isSorted = collection.isSorted();
212
isPrimitiveArray = collection.isPrimitiveArray();
213         isArray = collection.isArray();
214         subselectLoadable = collection.isSubselectLoadable();
215         
216         qualifiedTableName = table.getQualifiedName(
217                 dialect,
218                 factory.getSettings().getDefaultCatalogName(),
219                 factory.getSettings().getDefaultSchemaName()
220         );
221
222         int spacesSize = 1 + collection.getSynchronizedTables().size();
223         spaces = new String JavaDoc[spacesSize];
224         spaces[0] = qualifiedTableName;
225         Iterator JavaDoc iter = collection.getSynchronizedTables().iterator();
226         for ( int i = 1; i < spacesSize; i++ ) {
227             spaces[i] = (String JavaDoc) iter.next();
228         }
229         
230         sqlOrderByString = collection.getOrderBy();
231         hasOrder = sqlOrderByString != null;
232         sqlOrderByStringTemplate = hasOrder ?
233                 Template.renderOrderByStringTemplate(sqlOrderByString, dialect) :
234                 null;
235         sqlWhereString = collection.getWhere();
236         hasWhere = sqlWhereString != null;
237         sqlWhereStringTemplate = hasWhere ?
238                 Template.renderWhereStringTemplate(sqlWhereString, dialect) :
239                 null;
240
241         hasOrphanDelete = collection.hasOrphanDelete();
242
243         int batch = collection.getBatchSize();
244         if (batch==-1) batch = factory.getSettings().getDefaultBatchFetchSize();
245         batchSize = batch;
246
247         isVersioned = collection.isOptimisticLocked();
248         
249         // KEY
250

251         keyType = collection.getKey().getType();
252         iter = collection.getKey().getColumnIterator();
253         int keySpan = collection.getKey().getColumnSpan();
254         keyColumnNames = new String JavaDoc[keySpan];
255         keyColumnAliases = new String JavaDoc[keySpan];
256         int k = 0;
257         while ( iter.hasNext() ) {
258             // NativeSQL: collect key column and auto-aliases
259
Column col = ( (Column) iter.next() );
260             keyColumnNames[k] = col.getQuotedName(dialect);
261             keyColumnAliases[k] = col.getAlias(dialect);
262             k++;
263         }
264         
265         //unquotedKeyColumnNames = StringHelper.unQuote(keyColumnAliases);
266

267         //ELEMENT
268

269         String JavaDoc elemNode = collection.getElementNodeName();
270         if ( elementType.isEntityType() ) {
271             String JavaDoc entityName = ( (EntityType) elementType ).getAssociatedEntityName();
272             elementPersister = factory.getEntityPersister(entityName);
273             if ( elemNode==null ) {
274                 elemNode = cfg.getClassMapping(entityName).getNodeName();
275             }
276             // NativeSQL: collect element column and auto-aliases
277

278         }
279         else {
280             elementPersister = null;
281         }
282         elementNodeName = elemNode;
283
284         int elementSpan = collection.getElement().getColumnSpan();
285         elementColumnAliases = new String JavaDoc[elementSpan];
286         elementColumnNames = new String JavaDoc[elementSpan];
287         elementFormulaTemplates = new String JavaDoc[elementSpan];
288         elementColumnIsSettable = new boolean[elementSpan];
289         elementColumnIsInPrimaryKey = new boolean[elementSpan];
290         boolean isPureFormula = true;
291         boolean hasNotNullableColumns = false;
292         int j = 0;
293         iter = collection.getElement().getColumnIterator();
294         while ( iter.hasNext() ) {
295             Selectable selectable = (Selectable) iter.next();
296             elementColumnAliases[j] = selectable.getAlias(dialect);
297             if ( selectable.isFormula() ) {
298                 Formula form = (Formula) selectable;
299                 elementFormulaTemplates[j] = form.getTemplate(dialect);
300             }
301             else {
302                 Column col = (Column) selectable;
303                 elementColumnNames[j] = col.getQuotedName(dialect);
304                 elementColumnIsSettable[j] = true;
305                 elementColumnIsInPrimaryKey[j] = !col.isNullable();
306                 if ( !col.isNullable() ) hasNotNullableColumns = true;
307                 isPureFormula = false;
308             }
309             j++;
310         }
311         elementIsPureFormula = isPureFormula;
312         
313         //workaround, for backward compatibility of sets with no
314
//not-null columns, assume all columns are used in the
315
//row locator SQL
316
if ( !hasNotNullableColumns ) Arrays.fill(elementColumnIsInPrimaryKey, true);
317
318
319         // INDEX AND ROW SELECT
320

321         hasIndex = collection.isIndexed();
322         if (hasIndex) {
323             // NativeSQL: collect index column and auto-aliases
324
IndexedCollection indexedCollection = (IndexedCollection) collection;
325             indexType = indexedCollection.getIndex().getType();
326             int indexSpan = indexedCollection.getIndex().getColumnSpan();
327             iter = indexedCollection.getIndex().getColumnIterator();
328             indexColumnNames = new String JavaDoc[indexSpan];
329             indexFormulaTemplates = new String JavaDoc[indexSpan];
330             indexColumnIsSettable = new boolean[indexSpan];
331             indexColumnAliases = new String JavaDoc[indexSpan];
332             int i = 0;
333             boolean hasFormula = false;
334             while ( iter.hasNext() ) {
335                 Selectable s = (Selectable) iter.next();
336                 indexColumnAliases[i] = s.getAlias(dialect);
337                 if ( s.isFormula() ) {
338                     Formula indexForm = (Formula) s;
339                     indexFormulaTemplates[i] = indexForm.getTemplate(dialect);
340                     hasFormula = true;
341                 }
342                 else {
343                     Column indexCol = (Column) s;
344                     indexColumnNames[i] = indexCol.getQuotedName(dialect);
345                     indexColumnIsSettable[i] = true;
346                 }
347                 i++;
348             }
349             indexContainsFormula = hasFormula;
350             baseIndex = indexedCollection.isList() ?
351                     ( (List) indexedCollection ).getBaseIndex() : 0;
352
353             indexNodeName = indexedCollection.getIndexNodeName();
354
355         }
356         else {
357             indexContainsFormula = false;
358             indexColumnIsSettable = null;
359             indexFormulaTemplates = null;
360             indexType = null;
361             indexColumnNames = null;
362             indexColumnAliases = null;
363             baseIndex = 0;
364             indexNodeName = null;
365         }
366         
367         hasIdentifier = collection.isIdentified();
368         if (hasIdentifier) {
369             if ( collection.isOneToMany() ) {
370                 throw new MappingException( "one-to-many collections with identifiers are not supported" );
371             }
372             IdentifierCollection idColl = (IdentifierCollection) collection;
373             identifierType = idColl.getIdentifier().getType();
374             iter = idColl.getIdentifier().getColumnIterator();
375             Column col = ( Column ) iter.next();
376             identifierColumnName = col.getQuotedName(dialect);
377             identifierColumnAlias = col.getAlias(dialect);
378             //unquotedIdentifierColumnName = identifierColumnAlias;
379
identifierGenerator = idColl.getIdentifier().createIdentifierGenerator(
380                     factory.getDialect(),
381                     factory.getSettings().getDefaultCatalogName(),
382                     factory.getSettings().getDefaultSchemaName(),
383                     null
384                 );
385         }
386         else {
387             identifierType = null;
388             identifierColumnName = null;
389             identifierColumnAlias = null;
390             //unquotedIdentifierColumnName = null;
391
identifierGenerator = null;
392         }
393         
394         //GENERATE THE SQL:
395

396         //sqlSelectString = sqlSelectString();
397
if ( collection.getCustomSQLDeleteAll() == null ) {
398             sqlDeleteString = generateDeleteString();
399             deleteAllCallable = false;
400         }
401         else {
402             sqlDeleteString = collection.getCustomSQLDeleteAll();
403             deleteAllCallable = collection.isCustomDeleteAllCallable();
404         }
405         //sqlSelectRowString = sqlSelectRowString();
406
if ( collection.getCustomSQLInsert() == null ) {
407             sqlInsertRowString = generateInsertRowString();
408             insertCallable = false;
409         }
410         else {
411             sqlInsertRowString = collection.getCustomSQLInsert();
412             insertCallable = collection.isCustomInsertCallable();
413         }
414
415         if ( collection.getCustomSQLUpdate() == null ) {
416             sqlUpdateRowString = generateUpdateRowString();
417             updateCallable = false;
418         }
419         else {
420             sqlUpdateRowString = collection.getCustomSQLUpdate();
421             updateCallable = collection.isCustomUpdateCallable();
422         }
423         if ( collection.getCustomSQLDelete() == null ) {
424             sqlDeleteRowString = generateDeleteRowString();
425             deleteCallable = false;
426         }
427         else {
428             sqlDeleteRowString = collection.getCustomSQLDelete();
429             deleteCallable = collection.isCustomDeleteCallable();
430         }
431         logStaticSQL();
432         isLazy = collection.isLazy();
433
434         isInverse = collection.isInverse();
435
436         if ( collection.isArray() ) {
437             elementClass = ( (org.hibernate.mapping.Array) collection ).getElementClass();
438         }
439         else {
440             // for non-arrays, we don't need to know the element class
441
elementClass = null; //elementType.returnedClass();
442
}
443
444         if ( elementType.isComponentType() ) {
445             elementPropertyMapping = new CompositeElementPropertyMapping(
446                     elementColumnNames,
447                     elementFormulaTemplates,
448                     (AbstractComponentType) elementType,
449                     factory
450                 );
451         }
452         else if ( !elementType.isEntityType() ) {
453             elementPropertyMapping = new ElementPropertyMapping(
454                     elementColumnNames,
455                     elementType
456                 );
457         }
458         else {
459             if ( elementPersister instanceof PropertyMapping ) { //not all classpersisters implement PropertyMapping!
460
elementPropertyMapping = (PropertyMapping) elementPersister;
461             }
462             else {
463                 elementPropertyMapping = new ElementPropertyMapping(
464                         elementColumnNames,
465                         elementType
466                     );
467             }
468         }
469             
470         // Handle any filters applied to this collection
471
filterHelper = new FilterHelper( collection.getFilterMap(), dialect );
472
473         // Handle any filters applied to this collection for many-to-many
474
manyToManyFilterHelper = new FilterHelper( collection.getManyToManyFilterMap(), dialect );
475         manyToManyWhereString = collection.getManyToManyWhere();
476         manyToManyWhereTemplate = manyToManyWhereString == null ?
477                 null :
478                 Template.renderWhereStringTemplate( manyToManyWhereString, factory.getDialect() );
479
480         initCollectionPropertyMap();
481     }
482
483     public void postInstantiate() throws MappingException {
484         initializer = queryLoaderName == null ?
485                 createCollectionInitializer( CollectionHelper.EMPTY_MAP ) :
486                 new NamedQueryCollectionInitializer( queryLoaderName, this );
487     }
488
489     protected void logStaticSQL() {
490         if ( log.isDebugEnabled() ) {
491             log.debug( "Static SQL for collection: " + getRole() );
492             if ( getSQLInsertRowString() != null ) log.debug( " Row insert: " + getSQLInsertRowString() );
493             if ( getSQLUpdateRowString() != null ) log.debug( " Row update: " + getSQLUpdateRowString() );
494             if ( getSQLDeleteRowString() != null ) log.debug( " Row delete: " + getSQLDeleteRowString() );
495             if ( getSQLDeleteString() != null ) log.debug( " One-shot delete: " + getSQLDeleteString() );
496         }
497     }
498
499     public void initialize(Serializable JavaDoc key, SessionImplementor session) throws HibernateException {
500         getAppropriateInitializer( key, session ).initialize( key, session );
501     }
502
503     protected CollectionInitializer getAppropriateInitializer(Serializable JavaDoc key, SessionImplementor session) {
504         if ( queryLoaderName != null ) {
505             //if there is a user-specified loader, return that
506
//TODO: filters!?
507
return initializer;
508         }
509         CollectionInitializer subselectInitializer = getSubselectInitializer( key, session );
510         if ( subselectInitializer != null ) {
511             return subselectInitializer;
512         }
513         else if ( session.getEnabledFilters().isEmpty() ) {
514             return initializer;
515         }
516         else {
517             return createCollectionInitializer( session.getEnabledFilters() );
518         }
519     }
520
521     private CollectionInitializer getSubselectInitializer(Serializable JavaDoc key, SessionImplementor session) {
522         
523         if ( !isSubselectLoadable() ) return null;
524         
525         final PersistenceContext persistenceContext = session.getPersistenceContext();
526         
527         SubselectFetch subselect = persistenceContext.getBatchFetchQueue()
528             .getSubselect( new EntityKey( key, getOwnerEntityPersister(), session.getEntityMode() ) );
529         
530         if (subselect == null) {
531             return null;
532         }
533         else {
534             
535             // Take care of any entities that might have
536
// been evicted!
537
Iterator JavaDoc iter = subselect.getResult().iterator();
538             while ( iter.hasNext() ) {
539                 if ( !persistenceContext.containsEntity( (EntityKey) iter.next() ) ) {
540                     iter.remove();
541                 }
542             }
543             
544             // Run a subquery loader
545
return createSubselectInitializer( subselect, session );
546         }
547     }
548
549     protected abstract CollectionInitializer createSubselectInitializer(SubselectFetch subselect, SessionImplementor session);
550
551     protected abstract CollectionInitializer createCollectionInitializer(Map JavaDoc enabledFilters)
552             throws MappingException;
553
554     public CacheConcurrencyStrategy getCache() {
555         return cache;
556     }
557
558     public boolean hasCache() {
559         return cache != null;
560     }
561
562     public CollectionType getCollectionType() {
563         return collectionType;
564     }
565
566     protected String JavaDoc getSQLWhereString(String JavaDoc alias) {
567         return StringHelper.replace( sqlWhereStringTemplate, Template.TEMPLATE, alias );
568     }
569
570     public String JavaDoc getSQLOrderByString(String JavaDoc alias) {
571         return hasOrdering() ?
572             StringHelper.replace( sqlOrderByStringTemplate, Template.TEMPLATE, alias ) : "";
573     }
574
575     public FetchMode getFetchMode() {
576         return fetchMode;
577     }
578
579     public boolean hasOrdering() {
580         return hasOrder;
581     }
582
583     public boolean hasWhere() {
584         return hasWhere;
585     }
586
587     protected String JavaDoc getSQLDeleteString() {
588         return sqlDeleteString;
589     }
590
591     protected String JavaDoc getSQLInsertRowString() {
592         return sqlInsertRowString;
593     }
594
595     protected String JavaDoc getSQLUpdateRowString() {
596         return sqlUpdateRowString;
597     }
598
599     protected String JavaDoc getSQLDeleteRowString() {
600         return sqlDeleteRowString;
601     }
602
603     public Type getKeyType() {
604         return keyType;
605     }
606
607     public Type getIndexType() {
608         return indexType;
609     }
610
611     public Type getElementType() {
612         return elementType;
613     }
614
615     /**
616      * Return the element class of an array, or null otherwise
617      */

618     public Class JavaDoc getElementClass() { //needed by arrays
619
return elementClass;
620     }
621
622     public Object JavaDoc readElement(ResultSet JavaDoc rs, Object JavaDoc owner, String JavaDoc[] aliases, SessionImplementor session) throws HibernateException, SQLException JavaDoc {
623         Object JavaDoc element = getElementType().nullSafeGet( rs, aliases, session, owner );
624         return element;
625     }
626
627     public Object JavaDoc readIndex(ResultSet JavaDoc rs, String JavaDoc[] aliases, SessionImplementor session) throws HibernateException, SQLException JavaDoc {
628         Object JavaDoc index = getIndexType().nullSafeGet( rs, aliases, session, null );
629         if ( index == null ) {
630             throw new HibernateException( "null index column for collection: " + role );
631         }
632         if (baseIndex!=0) {
633             index = new Integer JavaDoc( ( (Integer JavaDoc) index ).intValue() - baseIndex );
634         }
635         return index;
636     }
637
638     public Object JavaDoc readIdentifier(ResultSet JavaDoc rs, String JavaDoc alias, SessionImplementor session) throws HibernateException, SQLException JavaDoc {
639         Object JavaDoc id = getIdentifierType().nullSafeGet( rs, alias, session, null );
640         if ( id == null ) throw new HibernateException( "null identifier column for collection: " + role );
641         return id;
642     }
643
644     public Object JavaDoc readKey(ResultSet JavaDoc rs, String JavaDoc[] aliases, SessionImplementor session) throws HibernateException, SQLException JavaDoc {
645         return getKeyType().nullSafeGet( rs, aliases, session, null );
646     }
647
648     /**
649      * Write the key to a JDBC <tt>PreparedStatement</tt>
650      */

651     protected int writeKey(PreparedStatement JavaDoc st, Serializable JavaDoc key, int i, SessionImplementor session)
652             throws HibernateException, SQLException JavaDoc {
653         
654         if ( key == null ) throw new NullPointerException JavaDoc( "null key for collection: " + role ); //an assertion
655
getKeyType().nullSafeSet( st, key, i, session );
656         return i + keyColumnAliases.length;
657     }
658
659     /**
660      * Write the element to a JDBC <tt>PreparedStatement</tt>
661      */

662     protected int writeElement(PreparedStatement JavaDoc st, Object JavaDoc elt, int i, SessionImplementor session)
663             throws HibernateException, SQLException JavaDoc {
664         getElementType().nullSafeSet(st, elt, i, elementColumnIsSettable, session);
665         return i + ArrayHelper.countTrue(elementColumnIsSettable);
666
667     }
668
669     /**
670      * Write the index to a JDBC <tt>PreparedStatement</tt>
671      */

672     protected int writeIndex(PreparedStatement JavaDoc st, Object JavaDoc index, int i, SessionImplementor session)
673             throws HibernateException, SQLException JavaDoc {
674         if (baseIndex!=0) {
675             index = new Integer JavaDoc( ( (Integer JavaDoc) index ).intValue() + baseIndex );
676         }
677         getIndexType().nullSafeSet( st, index, i, indexColumnIsSettable, session );
678         return i + ArrayHelper.countTrue(indexColumnIsSettable);
679     }
680
681     /**
682      * Write the element to a JDBC <tt>PreparedStatement</tt>
683      */

684     protected int writeElementToWhere(PreparedStatement JavaDoc st, Object JavaDoc elt, int i, SessionImplementor session)
685             throws HibernateException, SQLException JavaDoc {
686         if (elementIsPureFormula) throw new AssertionFailure("cannot use a formula-based element in the where condition");
687         getElementType().nullSafeSet(st, elt, i, elementColumnIsInPrimaryKey, session);
688         return i + elementColumnAliases.length;
689
690     }
691
692     /**
693      * Write the index to a JDBC <tt>PreparedStatement</tt>
694      */

695     protected int writeIndexToWhere(PreparedStatement JavaDoc st, Object JavaDoc index, int i, SessionImplementor session)
696             throws HibernateException, SQLException JavaDoc {
697         if (indexContainsFormula) throw new AssertionFailure("cannot use a formula-based index in the where condition");
698         if (baseIndex!=0) {
699             index = new Integer JavaDoc( ( (Integer JavaDoc) index ).intValue() + baseIndex );
700         }
701         getIndexType().nullSafeSet( st, index, i, session );
702         return i + indexColumnAliases.length;
703     }
704
705     /**
706      * Write the identifier to a JDBC <tt>PreparedStatement</tt>
707      */

708     public int writeIdentifier(PreparedStatement JavaDoc st, Object JavaDoc id, int i, SessionImplementor session)
709             throws HibernateException, SQLException JavaDoc {
710         
711         getIdentifierType().nullSafeSet( st, id, i, session );
712         return i + 1;
713     }
714
715     public boolean isPrimitiveArray() {
716         return isPrimitiveArray;
717     }
718
719     public boolean isArray() {
720         return isArray;
721     }
722
723     public String JavaDoc[] getKeyColumnAliases(String JavaDoc suffix) {
724         return new Alias( suffix ).toAliasStrings( keyColumnAliases );
725     }
726
727     public String JavaDoc[] getElementColumnAliases(String JavaDoc suffix) {
728         return new Alias( suffix ).toAliasStrings( elementColumnAliases );
729     }
730
731     public String JavaDoc[] getIndexColumnAliases(String JavaDoc suffix) {
732         if ( hasIndex ) {
733             return new Alias( suffix ).toAliasStrings( indexColumnAliases );
734         }
735         else {
736             return null;
737         }
738     }
739
740     public String JavaDoc getIdentifierColumnAlias(String JavaDoc suffix) {
741         if ( hasIdentifier ) {
742             return new Alias( suffix ).toAliasString( identifierColumnAlias );
743         }
744         else {
745             return null;
746         }
747     }
748
749     /**
750      * Generate a list of collection index, key and element columns
751      */

752     public String JavaDoc selectFragment(String JavaDoc alias, String JavaDoc columnSuffix) {
753         SelectFragment frag = generateSelectFragment( alias, columnSuffix );
754         appendElementColumns( frag, alias );
755         appendIndexColumns( frag, alias );
756         appendIdentifierColumns( frag, alias );
757
758         return frag.toFragmentString()
759                 .substring( 2 ); //strip leading ','
760
}
761
762     protected SelectFragment generateSelectFragment(String JavaDoc alias, String JavaDoc columnSuffix) {
763         SelectFragment frag = new SelectFragment()
764                 .setSuffix( columnSuffix )
765                 .addColumns( alias, keyColumnNames, keyColumnAliases );
766         return frag;
767     }
768
769     protected void appendElementColumns(SelectFragment frag, String JavaDoc elemAlias) {
770         for ( int i=0; i<elementColumnIsSettable.length; i++ ) {
771             if ( elementColumnIsSettable[i] ) {
772                 frag.addColumn( elemAlias, elementColumnNames[i], elementColumnAliases[i] );
773             }
774             else {
775                 frag.addFormula( elemAlias, elementFormulaTemplates[i], elementColumnAliases[i] );
776             }
777         }
778     }
779
780     protected void appendIndexColumns(SelectFragment frag, String JavaDoc alias) {
781         if ( hasIndex ) {
782             for ( int i=0; i<indexColumnIsSettable.length; i++ ) {
783                 if ( indexColumnIsSettable[i] ) {
784                     frag.addColumn( alias, indexColumnNames[i], indexColumnAliases[i] );
785                 }
786                 else {
787                     frag.addFormula( alias, indexFormulaTemplates[i], indexColumnAliases[i] );
788                 }
789             }
790         }
791     }
792
793     protected void appendIdentifierColumns(SelectFragment frag, String JavaDoc alias) {
794         if ( hasIdentifier ) frag.addColumn( alias, identifierColumnName, identifierColumnAlias );
795     }
796
797     public String JavaDoc[] getIndexColumnNames() {
798         return indexColumnNames;
799     }
800
801     public String JavaDoc[] getIndexColumnNames(String JavaDoc alias) {
802         return qualify(alias, indexColumnNames, indexFormulaTemplates);
803
804     }
805
806     public String JavaDoc[] getElementColumnNames(String JavaDoc alias) {
807         return qualify(alias, elementColumnNames, elementFormulaTemplates);
808     }
809     
810     private static final String JavaDoc[] qualify(String JavaDoc alias, String JavaDoc[] columnNames, String JavaDoc[] formulaTemplates) {
811         int span = columnNames.length;
812         String JavaDoc[] result = new String JavaDoc[span];
813         for (int i=0; i<span; i++) {
814             if ( columnNames[i]==null ) {
815                 result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE, alias );
816             }
817             else {
818                 result[i] = StringHelper.qualify( alias, columnNames[i] );
819             }
820         }
821         return result;
822     }
823
824     public String JavaDoc[] getElementColumnNames() {
825         return elementColumnNames; //TODO: something with formulas...
826
}
827
828     public String JavaDoc[] getKeyColumnNames() {
829         return keyColumnNames;
830     }
831
832     public boolean hasIndex() {
833         return hasIndex;
834     }
835
836     public boolean isLazy() {
837         return isLazy;
838     }
839
840     public boolean isInverse() {
841         return isInverse;
842     }
843
844     public String JavaDoc getTableName() {
845         return qualifiedTableName;
846     }
847
848     public void remove(Serializable JavaDoc id, SessionImplementor session) throws HibernateException {
849
850         if ( !isInverse && isRowDeleteEnabled() ) {
851
852             if ( log.isDebugEnabled() ) {
853                 log.debug( "Deleting collection: " + MessageHelper.collectionInfoString( this, id, getFactory() ) );
854             }
855
856             // Remove all the old entries
857

858             try {
859                 int offset = 1;
860                 PreparedStatement JavaDoc st = null;
861                 if ( isDeleteCallable() ) {
862                     CallableStatement JavaDoc callstatement = session.getBatcher()
863                         .prepareBatchCallableStatement( getSQLDeleteString() );
864                     callstatement.registerOutParameter( offset++, Types.NUMERIC ); // TODO: should we require users to return number of update rows ?
865
st = callstatement;
866                 }
867                 else {
868                     st = session.getBatcher().prepareBatchStatement( getSQLDeleteString() );
869                 }
870
871                 try {
872                     writeKey( st, id, offset, session );
873                     session.getBatcher().addToBatch( -1 );
874                 }
875                 catch ( SQLException JavaDoc sqle ) {
876                     session.getBatcher().abortBatch( sqle );
877                     throw sqle;
878                 }
879
880                 if ( log.isDebugEnabled() ) log.debug( "done deleting collection" );
881             }
882             catch ( SQLException JavaDoc sqle ) {
883                 throw JDBCExceptionHelper.convert(
884                         sqlExceptionConverter,
885                         sqle,
886                         "could not delete collection: " +
887                         MessageHelper.collectionInfoString( this, id, getFactory() ),
888                         getSQLDeleteString()
889                     );
890             }
891
892         }
893
894     }
895
896     public void recreate(PersistentCollection collection, Serializable JavaDoc id, SessionImplementor session)
897             throws HibernateException {
898
899         if ( !isInverse && isRowInsertEnabled() ) {
900
901             if ( log.isDebugEnabled() ) {
902                 log.debug( "Inserting collection: " + MessageHelper.collectionInfoString( this, id, getFactory() ) );
903             }
904
905             try {
906                 //create all the new entries
907
Iterator JavaDoc entries = collection.entries(this);
908                 if ( entries.hasNext() ) {
909                     try {
910                         collection.preInsert( this );
911                         int i = 0;
912                         int count = 0;
913                         while ( entries.hasNext() ) {
914
915                             final Object JavaDoc entry = entries.next();
916                             if ( collection.entryExists( entry, i ) ) {
917                                 int offset = 1;
918                                 PreparedStatement JavaDoc st = null;
919                                 if ( isInsertCallable() ) {
920                                     CallableStatement JavaDoc callstatement = session.getBatcher()
921                                         .prepareBatchCallableStatement( getSQLInsertRowString() );
922                                     callstatement.registerOutParameter( offset++, Types.NUMERIC ); // TODO: should we require users to return number of update rows ?
923
st = callstatement;
924                                 }
925                                 else {
926                                     st = session.getBatcher().prepareBatchStatement( getSQLInsertRowString() );
927                                 }
928                                 //TODO: copy/paste from insertRows()
929
int loc = writeKey( st, id, offset, session );
930                                 if ( hasIdentifier ) {
931                                     loc = writeIdentifier( st, collection.getIdentifier(entry, i), loc, session );
932                                 }
933                                 if ( hasIndex /*&& !indexIsFormula*/ ) {
934                                     loc = writeIndex( st, collection.getIndex(entry, i, this), loc, session );
935                                 }
936                                 //if ( !elementIsFormula ) {
937
loc = writeElement(st, collection.getElement(entry), loc, session );
938                                 //}
939
session.getBatcher().addToBatch( 1 );
940                                 collection.afterRowInsert( this, entry, i );
941                                 count++;
942                             }
943                             i++;
944                         }
945                         if ( log.isDebugEnabled() ) log.debug( "done inserting collection: " + count + " rows inserted" );
946                     }
947                     catch ( SQLException JavaDoc sqle ) {
948                         session.getBatcher().abortBatch( sqle );
949                         throw sqle;
950                     }
951
952                 }
953                 else {
954                     if ( log.isDebugEnabled() ) log.debug( "collection was empty" );
955                 }
956             }
957             catch ( SQLException JavaDoc sqle ) {
958                 throw JDBCExceptionHelper.convert(
959                         sqlExceptionConverter,
960                         sqle,
961                         "could not insert collection: " +
962                         MessageHelper.collectionInfoString( this, id, getFactory() ),
963                         getSQLInsertRowString()
964                     );
965             }
966         }
967     }
968     
969     protected boolean isRowDeleteEnabled() {
970         return true;
971     }
972
973     public void deleteRows(PersistentCollection collection, Serializable JavaDoc id, SessionImplementor session)
974             throws HibernateException {
975
976         if ( !isInverse && isRowDeleteEnabled() ) {
977
978             if ( log.isDebugEnabled() ) {
979                 log.debug( "Deleting rows of collection: " + MessageHelper.collectionInfoString( this, id, getFactory() ) );
980             }
981             
982             boolean deleteByIndex = !isOneToMany() && hasIndex && !indexContainsFormula;
983             
984             try {
985                 //delete all the deleted entries
986
Iterator JavaDoc deletes = collection.getDeletes( this, !deleteByIndex );
987                 if ( deletes.hasNext() ) {
988                     int offset = 1;
989                     int count = 0;
990                     PreparedStatement JavaDoc st = null;
991                     if ( isDeleteCallable() ) {
992                         CallableStatement JavaDoc callstatement = session.getBatcher()
993                             .prepareBatchCallableStatement( getSQLDeleteRowString() );
994                         callstatement.registerOutParameter( offset++, Types.NUMERIC ); // TODO: should we require users to return number of update rows ?
995
st = callstatement;
996                     }
997                     else {
998                         st = session.getBatcher().prepareBatchStatement( getSQLDeleteRowString() );
999                     }
1000
1001                    try {
1002                        int i=0;
1003                        while ( deletes.hasNext() ) {
1004                            Object JavaDoc entry = deletes.next();
1005                            int loc = offset;
1006                            if ( hasIdentifier ) {
1007                                loc = writeIdentifier( st, entry, loc, session );
1008                            }
1009                            else {
1010                                //if ( !isOneToMany() ) {
1011
loc = writeKey( st, id, loc, session );
1012                                //}
1013
if (deleteByIndex) {
1014                                    loc = writeIndexToWhere( st, entry, loc, session );
1015                                }
1016                                else {
1017                                    loc = writeElementToWhere( st, entry, loc, session );
1018                                }
1019                            }
1020                            session.getBatcher().addToBatch( -1 );
1021                            count++;
1022                            i++;
1023                        }
1024                    }
1025                    catch ( SQLException JavaDoc sqle ) {
1026                        session.getBatcher().abortBatch( sqle );
1027                        throw sqle;
1028                    }
1029
1030                    if ( log.isDebugEnabled() ) log.debug( "done deleting collection rows: " + count + " deleted" );
1031                }
1032                else {
1033                    if ( log.isDebugEnabled() ) log.debug( "no rows to delete" );
1034                }
1035            }
1036            catch ( SQLException JavaDoc sqle ) {
1037                throw JDBCExceptionHelper.convert(
1038                        sqlExceptionConverter,
1039                        sqle,
1040                        "could not delete collection rows: " +
1041                        MessageHelper.collectionInfoString( this, id, getFactory() ),
1042                        getSQLDeleteRowString()
1043                    );
1044            }
1045        }
1046    }
1047    
1048    protected boolean isRowInsertEnabled() {
1049        return true;
1050    }
1051
1052    public void insertRows(PersistentCollection collection, Serializable JavaDoc id, SessionImplementor session)
1053            throws HibernateException {
1054
1055        if ( !isInverse && isRowInsertEnabled() ) {
1056
1057            if ( log.isDebugEnabled() ) {
1058                log.debug( "Inserting rows of collection: " + MessageHelper.collectionInfoString( this, id, getFactory() ) );
1059            }
1060
1061            try {
1062                //insert all the new entries
1063
Iterator JavaDoc entries = collection.entries(this);
1064                boolean callable = isInsertCallable();
1065                try {
1066                    collection.preInsert( this );
1067                    int i = 0;
1068                    int count = 0;
1069                    int offset = 1;
1070                    while ( entries.hasNext() ) {
1071                        Object JavaDoc entry = entries.next();
1072                        PreparedStatement JavaDoc st = null;
1073                        if ( collection.needsInserting( entry, i, elementType ) ) {
1074                            if ( st == null ) {
1075                                if ( callable ) {
1076                                    CallableStatement JavaDoc callstatement = session.getBatcher()
1077                                        .prepareBatchCallableStatement( getSQLInsertRowString() );
1078                                    callstatement.registerOutParameter( offset++, Types.NUMERIC ); // TODO: should we require users to return number of update rows ?
1079
st = callstatement;
1080                                }
1081                                else {
1082                                    st = session.getBatcher().prepareBatchStatement( getSQLInsertRowString() );
1083                                }
1084                            }
1085                            //TODO: copy/paste from recreate()
1086
int loc = writeKey( st, id, offset, session );
1087                            if ( hasIdentifier ) {
1088                                loc = writeIdentifier( st, collection.getIdentifier(entry, i), loc, session );
1089                            }
1090                            if ( hasIndex /*&& !indexIsFormula*/ ) {
1091                                loc = writeIndex( st, collection.getIndex(entry, i, this), loc, session );
1092                            }
1093                            //if ( !elementIsFormula ) {
1094
loc = writeElement(st, collection.getElement(entry), loc, session );
1095                            //}
1096
session.getBatcher().addToBatch( 1 );
1097                            collection.afterRowInsert( this, entry, i );
1098                            count++;
1099                        }
1100                        i++;
1101                    }
1102                    if ( log.isDebugEnabled() ) log.debug( "done inserting rows: " + count + " inserted" );
1103                }
1104                catch ( SQLException JavaDoc sqle ) {
1105                    session.getBatcher().abortBatch( sqle );
1106                    throw sqle;
1107                }
1108            }
1109            catch ( SQLException JavaDoc sqle ) {
1110                throw JDBCExceptionHelper.convert(
1111                        sqlExceptionConverter,
1112                        sqle,
1113                        "could not insert collection rows: " +
1114                        MessageHelper.collectionInfoString( this, id, getFactory() ),
1115                        getSQLInsertRowString()
1116                    );
1117            }
1118
1119        }
1120    }
1121
1122
1123    public String JavaDoc getRole() {
1124        return role;
1125    }
1126
1127    public String JavaDoc getOwnerEntityName() {
1128        return entityName;
1129    }
1130
1131    public EntityPersister getOwnerEntityPersister() {
1132        return ownerPersister;
1133    }
1134
1135    public IdentifierGenerator getIdentifierGenerator() {
1136        return identifierGenerator;
1137    }
1138
1139    public Type getIdentifierType() {
1140        return identifierType;
1141    }
1142
1143    public boolean hasOrphanDelete() {
1144        return hasOrphanDelete;
1145    }
1146
1147    public Type toType(String JavaDoc propertyName) throws QueryException {
1148        if ( "index".equals( propertyName ) ) return indexType;
1149        return elementPropertyMapping.toType( propertyName );
1150    }
1151
1152    public abstract boolean isManyToMany();
1153
1154    public String JavaDoc getManyToManyFilterFragment(String JavaDoc alias, Map JavaDoc enabledFilters) {
1155        StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1156        manyToManyFilterHelper.render( buffer, alias, enabledFilters );
1157
1158        if ( manyToManyWhereString != null ) {
1159            buffer.append( " and " )
1160                    .append( StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, alias ) );
1161        }
1162
1163        return buffer.toString();
1164    }
1165
1166    public String JavaDoc[] toColumns(String JavaDoc alias, String JavaDoc propertyName)
1167            throws QueryException {
1168
1169        if ( "index".equals( propertyName ) ) {
1170            if ( isManyToMany() ) {
1171                throw new QueryException( "index() function not supported for many-to-many association" );
1172            }
1173            return StringHelper.qualify( alias, indexColumnNames );
1174        }
1175
1176        return elementPropertyMapping.toColumns( alias, propertyName );
1177    }
1178
1179    public String JavaDoc[] toColumns(String JavaDoc propertyName)
1180            throws QueryException {
1181
1182        if ( "index".equals( propertyName ) ) {
1183            if ( isManyToMany() ) {
1184                throw new QueryException( "index() function not supported for many-to-many association" );
1185            }
1186            return indexColumnNames;
1187        }
1188
1189        return elementPropertyMapping.toColumns( propertyName );
1190    }
1191
1192    public Type getType() {
1193        return elementPropertyMapping.getType(); //==elementType ??
1194
}
1195
1196    public String JavaDoc getName() {
1197        return getRole();
1198    }
1199
1200    public EntityPersister getElementPersister() {
1201        if ( elementPersister == null ) throw new AssertionFailure( "not an association" );
1202        return ( Loadable ) elementPersister;
1203    }
1204
1205    public boolean isCollection() {
1206        return true;
1207    }
1208
1209    public Serializable JavaDoc[] getCollectionSpaces() {
1210        return spaces;
1211    }
1212
1213    protected abstract String JavaDoc generateDeleteString();
1214
1215    protected abstract String JavaDoc generateDeleteRowString();
1216
1217    protected abstract String JavaDoc generateUpdateRowString();
1218
1219    protected abstract String JavaDoc generateInsertRowString();
1220
1221    public void updateRows(PersistentCollection collection, Serializable JavaDoc id, SessionImplementor session)
1222    throws HibernateException {
1223
1224        if ( !isInverse && collection.isRowUpdatePossible() ) {
1225
1226            if ( log.isDebugEnabled() ) log.debug( "Updating rows of collection: " + role + "#" + id );
1227
1228            //update all the modified entries
1229
int count = doUpdateRows( id, collection, session );
1230
1231            if ( log.isDebugEnabled() ) log.debug( "done updating rows: " + count + " updated" );
1232        }
1233    }
1234
1235    protected abstract int doUpdateRows(Serializable JavaDoc key, PersistentCollection collection, SessionImplementor session)
1236    throws HibernateException;
1237
1238    public CollectionMetadata getCollectionMetadata() {
1239        return this;
1240    }
1241
1242    public SessionFactoryImplementor getFactory() {
1243        return factory;
1244    }
1245
1246    protected String JavaDoc filterFragment(String JavaDoc alias) throws MappingException {
1247        return hasWhere() ? " and " + getSQLWhereString( alias ) : "";
1248    }
1249
1250    public String JavaDoc filterFragment(String JavaDoc alias, Map JavaDoc enabledFilters) throws MappingException {
1251
1252        StringBuffer JavaDoc sessionFilterFragment = new StringBuffer JavaDoc();
1253        filterHelper.render( sessionFilterFragment, alias, enabledFilters );
1254
1255        return sessionFilterFragment.append( filterFragment( alias ) ).toString();
1256    }
1257
1258    public String JavaDoc oneToManyFilterFragment(String JavaDoc alias) throws MappingException {
1259        return "";
1260    }
1261
1262    protected boolean isInsertCallable() {
1263        return insertCallable;
1264    }
1265
1266    protected boolean isUpdateCallable() {
1267        return updateCallable;
1268    }
1269
1270    protected boolean isDeleteCallable() {
1271        return deleteCallable;
1272    }
1273
1274    protected boolean isDeleteAllCallable() {
1275        return deleteAllCallable;
1276    }
1277
1278    public String JavaDoc toString() {
1279        return StringHelper.unqualify( getClass().getName() ) + '(' + role + ')';
1280    }
1281
1282    public boolean isVersioned() {
1283        return isVersioned && getOwnerEntityPersister().isVersioned();
1284    }
1285    
1286    public String JavaDoc getNodeName() {
1287        return nodeName;
1288    }
1289
1290    public String JavaDoc getElementNodeName() {
1291        return elementNodeName;
1292    }
1293
1294    public String JavaDoc getIndexNodeName() {
1295        return indexNodeName;
1296    }
1297
1298    protected SQLExceptionConverter getSQLExceptionConverter() {
1299        return sqlExceptionConverter;
1300    }
1301
1302    public CacheEntryStructure getCacheEntryStructure() {
1303        return cacheEntryStructure;
1304    }
1305
1306    public boolean isAffectedByEnabledFilters(SessionImplementor session) {
1307        return filterHelper.isAffectedBy( session.getEnabledFilters() ) ||
1308                ( isManyToMany() && manyToManyFilterHelper.isAffectedBy( session.getEnabledFilters() ) );
1309    }
1310
1311    public boolean isSubselectLoadable() {
1312        return subselectLoadable;
1313    }
1314    
1315    public boolean isMutable() {
1316        return isMutable;
1317    }
1318
1319    public String JavaDoc[] getCollectionPropertyColumnAliases(String JavaDoc propertyName, String JavaDoc suffix) {
1320        String JavaDoc rawAliases[] = (String JavaDoc[]) collectionPropertyColumnAliases.get(propertyName);
1321         
1322        if(rawAliases==null) return null;
1323        
1324        String JavaDoc result[] = new String JavaDoc[rawAliases.length];
1325        for ( int i=0; i<rawAliases.length; i++ ) {
1326            result[i] = new Alias(suffix).toUnquotedAliasString( rawAliases[i] );
1327        }
1328        return result;
1329    }
1330    
1331    //TODO: formulas ?
1332
public void initCollectionPropertyMap() {
1333
1334        initCollectionPropertyMap( "key", keyType, keyColumnAliases, keyColumnNames );
1335        initCollectionPropertyMap( "element", elementType, elementColumnAliases, elementColumnNames );
1336        if(hasIndex) {
1337            initCollectionPropertyMap( "index", indexType, indexColumnAliases, indexColumnNames );
1338        }
1339        if(hasIdentifier) {
1340            initCollectionPropertyMap( "id", identifierType, new String JavaDoc[] { identifierColumnAlias }, new String JavaDoc[] { identifierColumnName } );
1341        }
1342    }
1343
1344    private void initCollectionPropertyMap(String JavaDoc aliasName, Type type, String JavaDoc[] columnAliases, String JavaDoc[] columnNames) {
1345        
1346        collectionPropertyColumnAliases.put(aliasName, columnAliases);
1347        collectionPropertyColumnNames.put(aliasName, columnNames);
1348    
1349        if( type.isComponentType() ) {
1350            AbstractComponentType ct = (AbstractComponentType) type;
1351            String JavaDoc[] propertyNames = ct.getPropertyNames();
1352            for (int i = 0; i < propertyNames.length; i++) {
1353                String JavaDoc name = propertyNames[i];
1354                collectionPropertyColumnAliases.put(aliasName + "." + name, columnAliases[i]);
1355                collectionPropertyColumnAliases.put(aliasName + "." + name, columnNames[i]);
1356            }
1357        }
1358        
1359    }
1360}
1361
Popular Tags