package org.hibernate.mapping;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.Objects;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.internal.FilterConfiguration;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.CollectionType;
import org.hibernate.type.Type;
public abstract class Collection implements Fetchable, Value, Filterable {
public static final String DEFAULT_ELEMENT_COLUMN_NAME = "elt";
public static final String DEFAULT_KEY_COLUMN_NAME = "id";
private final MetadataImplementor metadata;
private MetadataBuildingContext buildingContext;
private PersistentClass owner;
private KeyValue key;
private Value element;
private Table collectionTable;
private String role;
private boolean lazy;
private boolean ;
private boolean inverse;
private boolean mutable = true;
private boolean subselectLoadable;
private String cacheConcurrencyStrategy;
private String cacheRegionName;
private String orderBy;
private String where;
private String manyToManyWhere;
private String manyToManyOrderBy;
private String referencedPropertyName;
private String mappedByProperty;
private boolean sorted;
private Comparator comparator;
private String comparatorClassName;
private boolean orphanDelete;
private int batchSize = -1;
private FetchMode fetchMode;
private boolean embedded = true;
private boolean optimisticLocked = true;
private Class collectionPersisterClass;
private String typeName;
private Properties typeParameters;
private final java.util.List filters = new ArrayList();
private final java.util.List manyToManyFilters = new ArrayList();
private final java.util.Set<String> synchronizedTables = new HashSet<String>();
private String customSQLInsert;
private boolean customInsertCallable;
private ExecuteUpdateResultCheckStyle insertCheckStyle;
private String customSQLUpdate;
private boolean customUpdateCallable;
private ExecuteUpdateResultCheckStyle updateCheckStyle;
private String customSQLDelete;
private boolean customDeleteCallable;
private ExecuteUpdateResultCheckStyle deleteCheckStyle;
private String customSQLDeleteAll;
private boolean customDeleteAllCallable;
private ExecuteUpdateResultCheckStyle deleteAllCheckStyle;
private String loaderName;
protected Collection(MetadataBuildingContext buildingContext, PersistentClass owner) {
this(buildingContext.getMetadataCollector(), owner);
this.buildingContext = buildingContext;
}
@Deprecated
protected Collection(MetadataImplementor metadata, PersistentClass owner) {
this.metadata = metadata;
this.owner = owner;
}
public MetadataImplementor getMetadata() {
return metadata;
}
@Override
public ServiceRegistry getServiceRegistry() {
return getMetadata().getMetadataBuildingOptions().getServiceRegistry();
}
public boolean isSet() {
return false;
}
public KeyValue getKey() {
return key;
}
public Value getElement() {
return element;
}
public boolean isIndexed() {
return false;
}
public Table getCollectionTable() {
return collectionTable;
}
public void setCollectionTable(Table table) {
this.collectionTable = table;
}
public boolean isSorted() {
return sorted;
}
public Comparator getComparator() {
if ( comparator == null && comparatorClassName != null ) {
try {
final ClassLoaderService classLoaderService = getMetadata().getMetadataBuildingOptions()
.getServiceRegistry()
.getService( ClassLoaderService.class );
setComparator( (Comparator) classLoaderService.classForName( comparatorClassName ).newInstance() );
}
catch (Exception e) {
throw new MappingException(
"Could not instantiate comparator class [" + comparatorClassName
+ "] for collection " + getRole()
);
}
}
return comparator;
}
public boolean isLazy() {
return lazy;
}
public void setLazy(boolean lazy) {
this.lazy = lazy;
}
public String getRole() {
return role;
}
public abstract CollectionType getDefaultCollectionType() throws MappingException;
public boolean isPrimitiveArray() {
return false;
}
public boolean isArray() {
return false;
}
public boolean hasFormula() {
return false;
}
public boolean isOneToMany() {
return element instanceof OneToMany;
}
public boolean isInverse() {
return inverse;
}
public String getOwnerEntityName() {
return owner.getEntityName();
}
public String getOrderBy() {
return orderBy;
}
public void setComparator(Comparator comparator) {
this.comparator = comparator;
}
public void setElement(Value element) {
this.element = element;
}
public void setKey(KeyValue key) {
this.key = key;
}
public void setOrderBy(String orderBy) {
this.orderBy = orderBy;
}
public void setRole(String role) {
this.role = role;
}
public void setSorted(boolean sorted) {
this.sorted = sorted;
}
public void setInverse(boolean inverse) {
this.inverse = inverse;
}
public PersistentClass getOwner() {
return owner;
}
@Deprecated
public void setOwner(PersistentClass owner) {
this.owner = owner;
}
public String getWhere() {
return where;
}
public void setWhere(String where) {
this.where = where;
}
public String getManyToManyWhere() {
return manyToManyWhere;
}
public void setManyToManyWhere(String manyToManyWhere) {
this.manyToManyWhere = manyToManyWhere;
}
public String getManyToManyOrdering() {
return manyToManyOrderBy;
}
public void setManyToManyOrdering(String orderFragment) {
this.manyToManyOrderBy = orderFragment;
}
public boolean isIdentified() {
return false;
}
public boolean hasOrphanDelete() {
return orphanDelete;
}
public void setOrphanDelete(boolean orphanDelete) {
this.orphanDelete = orphanDelete;
}
public int getBatchSize() {
return batchSize;
}
public void setBatchSize(int i) {
batchSize = i;
}
public FetchMode getFetchMode() {
return fetchMode;
}
public void setFetchMode(FetchMode fetchMode) {
this.fetchMode = fetchMode;
}
public void setCollectionPersisterClass(Class persister) {
this.collectionPersisterClass = persister;
}
public Class getCollectionPersisterClass() {
return collectionPersisterClass;
}
public void validate(Mapping mapping) throws MappingException {
assert getKey() != null : "Collection key not bound : " + getRole();
assert getElement() != null : "Collection element not bound : " + getRole();
if ( !getKey().isValid( mapping ) ) {
throw new MappingException(
"collection foreign key mapping has wrong number of columns: "
+ getRole()
+ " type: "
+ getKey().getType().getName()
);
}
if ( !getElement().isValid( mapping ) ) {
throw new MappingException(
"collection element mapping has wrong number of columns: "
+ getRole()
+ " type: "
+ getElement().getType().getName()
);
}
checkColumnDuplication();
}
private void checkColumnDuplication(java.util.Set distinctColumns, Value value)
throws MappingException {
final boolean[] insertability = value.getColumnInsertability();
final boolean[] updatability = value.getColumnUpdateability();
final Iterator<Selectable> iterator = value.getColumnIterator();
int i = 0;
while ( iterator.hasNext() ) {
Selectable s = iterator.next();
if ( !s.isFormula() && ( insertability[i] || updatability[i] ) ) {
Column col = (Column) s;
if ( !distinctColumns.add( col.getName() ) ) {
throw new MappingException(
"Repeated column in mapping for collection: "
+ getRole()
+ " column: "
+ col.getName()
);
}
}
i++;
}
}
private void checkColumnDuplication() throws MappingException {
HashSet cols = new HashSet();
checkColumnDuplication( cols, getKey() );
if ( isIndexed() ) {
checkColumnDuplication(
cols,
( (IndexedCollection) this ).getIndex()
);
}
if ( isIdentified() ) {
checkColumnDuplication(
cols,
( (IdentifierCollection) this ).getIdentifier()
);
}
if ( !isOneToMany() ) {
checkColumnDuplication( cols, getElement() );
}
}
public Iterator<Selectable> getColumnIterator() {
return Collections.<Selectable>emptyList().iterator();
}
public int getColumnSpan() {
return 0;
}
public Type getType() throws MappingException {
return getCollectionType();
}
public CollectionType getCollectionType() {
if ( typeName == null ) {
return getDefaultCollectionType();
}
else {
return getMetadata().getTypeConfiguration().getTypeResolver()
.getTypeFactory()
.customCollection( typeName, typeParameters, role, referencedPropertyName );
}
}
public boolean isNullable() {
return true;
}
public boolean isAlternateUniqueKey() {
return false;
}
public Table getTable() {
return owner.getTable();
}
public void createForeignKey() {
}
public boolean isSimpleValue() {
return false;
}
public boolean isValid(Mapping mapping) throws MappingException {
return true;
}
@Override
public boolean isSame(Value other) {
return this == other || other instanceof Collection && isSame( (Collection) other );
}
protected static boolean isSame(Value v1, Value v2) {
return v1 == v2 || v1 != null && v2 != null && v1.isSame( v2 );
}
public boolean isSame(Collection other) {
return this == other || isSame( key, other.key )
&& isSame( element, other.element )
&& Objects.equals( collectionTable, other.collectionTable )
&& Objects.equals( where, other.where )
&& Objects.equals( manyToManyWhere, other.manyToManyWhere )
&& Objects.equals( referencedPropertyName, other.referencedPropertyName )
&& Objects.equals( mappedByProperty, other.mappedByProperty )
&& Objects.equals( typeName, other.typeName )
&& Objects.equals( typeParameters, other.typeParameters );
}
private void createForeignKeys() throws MappingException {
if ( referencedPropertyName == null ) {
getElement().createForeignKey();
key.createForeignKeyOfEntity( getOwner().getEntityName() );
}
}
abstract void createPrimaryKey();
public void createAllKeys() throws MappingException {
createForeignKeys();
if ( !isInverse() ) {
createPrimaryKey();
}
}
public String getCacheConcurrencyStrategy() {
return cacheConcurrencyStrategy;
}
public void setCacheConcurrencyStrategy(String cacheConcurrencyStrategy) {
this.cacheConcurrencyStrategy = cacheConcurrencyStrategy;
}
public void setTypeUsingReflection(String className, String propertyName) {
}
public String getCacheRegionName() {
return cacheRegionName == null ? role : cacheRegionName;
}
public void setCacheRegionName(String cacheRegionName) {
this.cacheRegionName = StringHelper.nullIfEmpty( cacheRegionName );
}
public void setCustomSQLInsert(String customSQLInsert, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
this.customSQLInsert = customSQLInsert;
this.customInsertCallable = callable;
this.insertCheckStyle = checkStyle;
}
public String getCustomSQLInsert() {
return customSQLInsert;
}
public boolean isCustomInsertCallable() {
return customInsertCallable;
}
public ExecuteUpdateResultCheckStyle getCustomSQLInsertCheckStyle() {
return insertCheckStyle;
}
public void setCustomSQLUpdate(String customSQLUpdate, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
this.customSQLUpdate = customSQLUpdate;
this.customUpdateCallable = callable;
this.updateCheckStyle = checkStyle;
}
public String getCustomSQLUpdate() {
return customSQLUpdate;
}
public boolean isCustomUpdateCallable() {
return customUpdateCallable;
}
public ExecuteUpdateResultCheckStyle getCustomSQLUpdateCheckStyle() {
return updateCheckStyle;
}
public void setCustomSQLDelete(String customSQLDelete, boolean callable, ExecuteUpdateResultCheckStyle checkStyle) {
this.customSQLDelete = customSQLDelete;
this.customDeleteCallable = callable;
this.deleteCheckStyle = checkStyle;
}
public String getCustomSQLDelete() {
return customSQLDelete;
}
public boolean isCustomDeleteCallable() {
return customDeleteCallable;
}
public ExecuteUpdateResultCheckStyle getCustomSQLDeleteCheckStyle() {
return deleteCheckStyle;
}
public void setCustomSQLDeleteAll(
String customSQLDeleteAll,
boolean callable,
ExecuteUpdateResultCheckStyle checkStyle) {
this.customSQLDeleteAll = customSQLDeleteAll;
this.customDeleteAllCallable = callable;
this.deleteAllCheckStyle = checkStyle;
}
public String getCustomSQLDeleteAll() {
return customSQLDeleteAll;
}
public boolean isCustomDeleteAllCallable() {
return customDeleteAllCallable;
}
public ExecuteUpdateResultCheckStyle getCustomSQLDeleteAllCheckStyle() {
return deleteAllCheckStyle;
}
public void addFilter(
String name,
String condition,
boolean autoAliasInjection,
java.util.Map<String, String> aliasTableMap,
java.util.Map<String, String> aliasEntityMap) {
filters.add(
new FilterConfiguration(
name,
condition,
autoAliasInjection,
aliasTableMap,
aliasEntityMap,
null
)
);
}
public java.util.List getFilters() {
return filters;
}
public void addManyToManyFilter(
String name,
String condition,
boolean autoAliasInjection,
java.util.Map<String, String> aliasTableMap,
java.util.Map<String, String> aliasEntityMap) {
manyToManyFilters.add(
new FilterConfiguration(
name,
condition,
autoAliasInjection,
aliasTableMap,
aliasEntityMap,
null
)
);
}
public java.util.List getManyToManyFilters() {
return manyToManyFilters;
}
@Override
public String toString() {
return getClass().getName() + '(' + getRole() + ')';
}
public java.util.Set<String> getSynchronizedTables() {
return synchronizedTables;
}
public String getLoaderName() {
return loaderName;
}
public void setLoaderName(String name) {
this.loaderName = name;
}
public String getReferencedPropertyName() {
return referencedPropertyName;
}
public void setReferencedPropertyName(String propertyRef) {
this.referencedPropertyName = propertyRef;
}
public boolean isOptimisticLocked() {
return optimisticLocked;
}
public void setOptimisticLocked(boolean optimisticLocked) {
this.optimisticLocked = optimisticLocked;
}
public boolean isMap() {
return false;
}
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public Properties getTypeParameters() {
return typeParameters;
}
public void setTypeParameters(Properties parameterMap) {
this.typeParameters = parameterMap;
}
public void setTypeParameters(java.util.Map parameterMap) {
if ( parameterMap instanceof Properties ) {
this.typeParameters = (Properties) parameterMap;
}
else {
this.typeParameters = new Properties();
typeParameters.putAll( parameterMap );
}
}
public boolean[] getColumnInsertability() {
return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
}
public boolean[] getColumnUpdateability() {
return ArrayHelper.EMPTY_BOOLEAN_ARRAY;
}
public boolean isSubselectLoadable() {
return subselectLoadable;
}
public void setSubselectLoadable(boolean subqueryLoadable) {
this.subselectLoadable = subqueryLoadable;
}
public boolean isMutable() {
return mutable;
}
public void setMutable(boolean mutable) {
this.mutable = mutable;
}
public boolean () {
return extraLazy;
}
public void (boolean extraLazy) {
this.extraLazy = extraLazy;
}
public boolean hasOrder() {
return orderBy != null || manyToManyOrderBy != null;
}
public void setComparatorClassName(String comparatorClassName) {
this.comparatorClassName = comparatorClassName;
}
public String getComparatorClassName() {
return comparatorClassName;
}
public String getMappedByProperty() {
return mappedByProperty;
}
public void setMappedByProperty(String mappedByProperty) {
this.mappedByProperty = mappedByProperty;
}
}