1
// $Id: Collection.java 11495 2007-05-09 03:52:56Z steve.ebersole@jboss.com $
2
package org.hibernate.mapping;
4
import java.util.Comparator;
5
import java.util.HashMap;
6
import java.util.HashSet;
7
import java.util.Iterator;
8
import java.util.Properties;
10
import org.hibernate.FetchMode;
11
import org.hibernate.MappingException;
12
import org.hibernate.engine.Mapping;
13
import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
14
import org.hibernate.type.CollectionType;
15
import org.hibernate.type.Type;
16
import org.hibernate.type.TypeFactory;
17
import org.hibernate.util.ArrayHelper;
18
import org.hibernate.util.EmptyIterator;
19
import org.hibernate.util.ReflectHelper;
22
* Mapping for a collection. Subclasses specialize to particular collection styles.
26
public abstract class Collection implements Fetchable, Value, Filterable {
28
public static final String DEFAULT_ELEMENT_COLUMN_NAME = "elt";
29
public static final String DEFAULT_KEY_COLUMN_NAME = "id";
32
private Value element;
33
private Table collectionTable;
36
private boolean extraLazy;
37
private boolean inverse;
38
private boolean mutable = true;
39
private boolean subselectLoadable;
40
private String cacheConcurrencyStrategy;
41
private String cacheRegionName;
42
private String orderBy;
44
private String manyToManyWhere;
45
private String manyToManyOrderBy;
46
private PersistentClass owner;
47
private String referencedPropertyName;
48
private String nodeName;
49
private String elementNodeName;
50
private boolean sorted;
51
private Comparator comparator;
52
private String comparatorClassName;
53
private boolean orphanDelete;
54
private int batchSize = -1;
55
private FetchMode fetchMode;
56
private boolean embedded = true;
57
private boolean optimisticLocked = true;
58
private Class collectionPersisterClass;
59
private String typeName;
60
private Properties typeParameters;
61
private final java.util.Map filters = new HashMap();
62
private final java.util.Map manyToManyFilters = new HashMap();
63
private final java.util.Set synchronizedTables = new HashSet();
65
private String customSQLInsert;
66
private boolean customInsertCallable;
67
private ExecuteUpdateResultCheckStyle insertCheckStyle;
68
private String customSQLUpdate;
69
private boolean customUpdateCallable;
70
private ExecuteUpdateResultCheckStyle updateCheckStyle;
71
private String customSQLDelete;
72
private boolean customDeleteCallable;
73
private ExecuteUpdateResultCheckStyle deleteCheckStyle;
74
private String customSQLDeleteAll;
75
private boolean customDeleteAllCallable;
76
private ExecuteUpdateResultCheckStyle deleteAllCheckStyle;
78
private String loaderName;
80
protected Collection(PersistentClass owner) {
84
public boolean isSet() {
88
public KeyValue getKey() {
92
public Value getElement() {
96
public boolean isIndexed() {
100
public Table getCollectionTable() {
101
return collectionTable;
104
public void setCollectionTable(Table table) {
105
this.collectionTable = table;
108
public boolean isSorted() {
112
public Comparator getComparator() {
113
if ( comparator == null && comparatorClassName != null ) {
115
setComparator( (Comparator) ReflectHelper.classForName( comparatorClassName ).newInstance() );
117
catch ( Exception e ) {
118
throw new MappingException(
119
"Could not instantiate comparator class [" + comparatorClassName
120
+ "] for collection " + getRole()
127
public boolean isLazy() {
131
public void setLazy(boolean lazy) {
135
public String getRole() {
139
public abstract CollectionType getDefaultCollectionType() throws MappingException;
141
public boolean isPrimitiveArray() {
145
public boolean isArray() {
149
public boolean hasFormula() {
153
public boolean isOneToMany() {
154
return element instanceof OneToMany;
157
public boolean isInverse() {
161
public String getOwnerEntityName() {
162
return owner.getEntityName();
165
public String getOrderBy() {
169
public void setComparator(Comparator comparator) {
170
this.comparator = comparator;
173
public void setElement(Value element) {
174
this.element = element;
177
public void setKey(KeyValue key) {
181
public void setOrderBy(String orderBy) {
182
this.orderBy = orderBy;
185
public void setRole(String role) {
186
this.role = role==null ? null : role.intern();
189
public void setSorted(boolean sorted) {
190
this.sorted = sorted;
193
public void setInverse(boolean inverse) {
194
this.inverse = inverse;
197
public PersistentClass getOwner() {
201
public void setOwner(PersistentClass owner) {
205
public String getWhere() {
209
public void setWhere(String where) {
213
public String getManyToManyWhere() {
214
return manyToManyWhere;
217
public void setManyToManyWhere(String manyToManyWhere) {
218
this.manyToManyWhere = manyToManyWhere;
221
public String getManyToManyOrdering() {
222
return manyToManyOrderBy;
225
public void setManyToManyOrdering(String orderFragment) {
226
this.manyToManyOrderBy = orderFragment;
229
public boolean isIdentified() {
233
public boolean hasOrphanDelete() {
237
public void setOrphanDelete(boolean orphanDelete) {
238
this.orphanDelete = orphanDelete;
241
public int getBatchSize() {
245
public void setBatchSize(int i) {
249
public FetchMode getFetchMode() {
253
public void setFetchMode(FetchMode fetchMode) {
254
this.fetchMode = fetchMode;
257
public void setCollectionPersisterClass(Class persister) {
258
this.collectionPersisterClass = persister;
261
public Class getCollectionPersisterClass() {
262
return collectionPersisterClass;
265
public void validate(Mapping mapping) throws MappingException {
266
if ( getKey().isCascadeDeleteEnabled() && ( !isInverse() || !isOneToMany() ) ) {
267
throw new MappingException(
268
"only inverse one-to-many associations may use on-delete=\"cascade\": "
271
if ( !getKey().isValid( mapping ) ) {
272
throw new MappingException(
273
"collection foreign key mapping has wrong number of columns: "
276
+ getKey().getType().getName() );
278
if ( !getElement().isValid( mapping ) ) {
279
throw new MappingException(
280
"collection element mapping has wrong number of columns: "
283
+ getElement().getType().getName() );
286
checkColumnDuplication();
288
if ( elementNodeName!=null && elementNodeName.startsWith("@") ) {
289
throw new MappingException("element node must not be an attribute: " + elementNodeName );
291
if ( elementNodeName!=null && elementNodeName.equals(".") ) {
292
throw new MappingException("element node must not be the parent: " + elementNodeName );
294
if ( nodeName!=null && nodeName.indexOf('@')>-1 ) {
295
throw new MappingException("collection node must not be an attribute: " + elementNodeName );
299
private void checkColumnDuplication(java.util.Set distinctColumns, Iterator columns)
300
throws MappingException {
301
while ( columns.hasNext() ) {
302
Selectable s = (Selectable) columns.next();
303
if ( !s.isFormula() ) {
304
Column col = (Column) s;
305
if ( !distinctColumns.add( col.getName() ) ) {
306
throw new MappingException( "Repeated column in mapping for collection: "
315
private void checkColumnDuplication() throws MappingException {
316
HashSet cols = new HashSet();
317
checkColumnDuplication( cols, getKey().getColumnIterator() );
319
checkColumnDuplication( cols, ( (IndexedCollection) this )
321
.getColumnIterator() );
323
if ( isIdentified() ) {
324
checkColumnDuplication( cols, ( (IdentifierCollection) this )
326
.getColumnIterator() );
328
if ( !isOneToMany() ) {
329
checkColumnDuplication( cols, getElement().getColumnIterator() );
333
public Iterator getColumnIterator() {
334
return EmptyIterator.INSTANCE;
337
public int getColumnSpan() {
341
public Type getType() throws MappingException {
342
return getCollectionType();
345
public CollectionType getCollectionType() {
346
if ( typeName == null ) {
347
return getDefaultCollectionType();
350
return TypeFactory.customCollection( typeName, typeParameters, role, referencedPropertyName, isEmbedded() );
354
public boolean isNullable() {
358
public boolean isAlternateUniqueKey() {
362
public Table getTable() {
363
return owner.getTable();
366
public void createForeignKey() {
369
public boolean isSimpleValue() {
373
public boolean isValid(Mapping mapping) throws MappingException {
377
private void createForeignKeys() throws MappingException {
378
// if ( !isInverse() ) { // for inverse collections, let the "other end" handle it
379
if ( referencedPropertyName == null ) {
380
getElement().createForeignKey();
381
key.createForeignKeyOfEntity( getOwner().getEntityName() );
386
abstract void createPrimaryKey();
388
public void createAllKeys() throws MappingException {
390
if ( !isInverse() ) createPrimaryKey();
393
public String getCacheConcurrencyStrategy() {
394
return cacheConcurrencyStrategy;
397
public void setCacheConcurrencyStrategy(String cacheConcurrencyStrategy) {
398
this.cacheConcurrencyStrategy = cacheConcurrencyStrategy;
401
public void setTypeUsingReflection(String className, String propertyName) {
404
public String getCacheRegionName() {
405
return cacheRegionName == null ? role : cacheRegionName;
408
public void setCacheRegionName(String cacheRegionName) {
409
this.cacheRegionName = cacheRegionName;
414
public void setCustomSQLInsert(String customSQLInsert, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
415
this.customSQLInsert = customSQLInsert;
416
this.customInsertCallable = callable;
417
this.insertCheckStyle = checkStyle;
420
public String getCustomSQLInsert() {
421
return customSQLInsert;
424
public boolean isCustomInsertCallable() {
425
return customInsertCallable;
428
public ExecuteUpdateResultCheckStyle getCustomSQLInsertCheckStyle() {
429
return insertCheckStyle;
432
public void setCustomSQLUpdate(String customSQLUpdate, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
433
this.customSQLUpdate = customSQLUpdate;
434
this.customUpdateCallable = callable;
435
this.updateCheckStyle = checkStyle;
438
public String getCustomSQLUpdate() {
439
return customSQLUpdate;
442
public boolean isCustomUpdateCallable() {
443
return customUpdateCallable;
446
public ExecuteUpdateResultCheckStyle getCustomSQLUpdateCheckStyle() {
447
return updateCheckStyle;
450
public void setCustomSQLDelete(String customSQLDelete, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
451
this.customSQLDelete = customSQLDelete;
452
this.customDeleteCallable = callable;
453
this.deleteCheckStyle = checkStyle;
456
public String getCustomSQLDelete() {
457
return customSQLDelete;
460
public boolean isCustomDeleteCallable() {
461
return customDeleteCallable;
464
public ExecuteUpdateResultCheckStyle getCustomSQLDeleteCheckStyle() {
465
return deleteCheckStyle;
468
public void setCustomSQLDeleteAll(String customSQLDeleteAll, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
469
this.customSQLDeleteAll = customSQLDeleteAll;
470
this.customDeleteAllCallable = callable;
471
this.deleteAllCheckStyle = checkStyle;
474
public String getCustomSQLDeleteAll() {
475
return customSQLDeleteAll;
478
public boolean isCustomDeleteAllCallable() {
479
return customDeleteAllCallable;
482
public ExecuteUpdateResultCheckStyle getCustomSQLDeleteAllCheckStyle() {
483
return deleteAllCheckStyle;
486
public void addFilter(String name, String condition) {
487
filters.put( name, condition );
490
public java.util.Map getFilterMap() {
494
public void addManyToManyFilter(String name, String condition) {
495
manyToManyFilters.put( name, condition );
498
public java.util.Map getManyToManyFilterMap() {
499
return manyToManyFilters;
502
public String toString() {
503
return getClass().getName() + '(' + getRole() + ')';
506
public java.util.Set getSynchronizedTables() {
507
return synchronizedTables;
510
public String getLoaderName() {
514
public void setLoaderName(String name) {
515
this.loaderName = name==null ? null : name.intern();
518
public String getReferencedPropertyName() {
519
return referencedPropertyName;
522
public void setReferencedPropertyName(String propertyRef) {
523
this.referencedPropertyName = propertyRef==null ? null : propertyRef.intern();
526
public boolean isOptimisticLocked() {
527
return optimisticLocked;
530
public void setOptimisticLocked(boolean optimisticLocked) {
531
this.optimisticLocked = optimisticLocked;
534
public boolean isMap() {
538
public String getTypeName() {
542
public void setTypeName(String typeName) {
543
this.typeName = typeName;
546
public Properties getTypeParameters() {
547
return typeParameters;
550
public void setTypeParameters(Properties parameterMap) {
551
this.typeParameters = parameterMap;
554
public boolean[] getColumnInsertability() {
555
return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
558
public boolean[] getColumnUpdateability() {
559
return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
562
public String getNodeName() {
566
public void setNodeName(String nodeName) {
567
this.nodeName = nodeName;
570
public String getElementNodeName() {
571
return elementNodeName;
574
public void setElementNodeName(String elementNodeName) {
575
this.elementNodeName = elementNodeName;
578
public boolean isEmbedded() {
582
public void setEmbedded(boolean embedded) {
583
this.embedded = embedded;
586
public boolean isSubselectLoadable() {
587
return subselectLoadable;
591
public void setSubselectLoadable(boolean subqueryLoadable) {
592
this.subselectLoadable = subqueryLoadable;
595
public boolean isMutable() {
599
public void setMutable(boolean mutable) {
600
this.mutable = mutable;
603
public boolean isExtraLazy() {
607
public void setExtraLazy(boolean extraLazy) {
608
this.extraLazy = extraLazy;
611
public boolean hasOrder() {
612
return orderBy!=null || manyToManyOrderBy!=null;
615
public void setComparatorClassName(String comparatorClassName) {
616
this.comparatorClassName = comparatorClassName;
619
public String getComparatorClassName() {
620
return comparatorClassName;
b'\\ No newline at end of file'