package org.hibernate.cache.spi;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Arrays;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.ValueHolder;
import org.hibernate.internal.util.compare.EqualsHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
public class NaturalIdCacheKey implements Serializable {
private final Serializable[] naturalIdValues;
private final String entityName;
private final String tenantId;
private final int hashCode;
private transient ValueHolder<String> toString;
public NaturalIdCacheKey(
final Object[] naturalIdValues,
final EntityPersister persister,
final SessionImplementor session) {
this.entityName = persister.getRootEntityName();
this.tenantId = session.getTenantIdentifier();
this.naturalIdValues = new Serializable[naturalIdValues.length];
final SessionFactoryImplementor factory = session.getFactory();
final int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties();
final Type[] propertyTypes = persister.getPropertyTypes();
final int prime = 31;
int result = 1;
result = prime * result + ( ( this.entityName == null ) ? 0 : this.entityName.hashCode() );
result = prime * result + ( ( this.tenantId == null ) ? 0 : this.tenantId.hashCode() );
for ( int i = 0; i < naturalIdValues.length; i++ ) {
final int naturalIdPropertyIndex = naturalIdPropertyIndexes[i];
final Type type = propertyTypes[naturalIdPropertyIndex];
final Object value = naturalIdValues[i];
result = prime * result + (value != null ? type.getHashCode( value, factory ) : 0);
if (type instanceof EntityType && type.getSemiResolvedType( factory ).getReturnedClass().isInstance( value )) {
this.naturalIdValues[i] = (Serializable) value;
}
else {
this.naturalIdValues[i] = type.disassemble( value, session, null );
}
}
this.hashCode = result;
initTransients();
}
private void initTransients() {
this.toString = new ValueHolder<String>(
new ValueHolder.DeferredInitializer<String>() {
@Override
public String initialize() {
final StringBuilder toStringBuilder = new StringBuilder( entityName ).append( "##NaturalId[" );
for ( int i = 0; i < naturalIdValues.length; i++ ) {
toStringBuilder.append( naturalIdValues[i] );
if ( i + 1 < naturalIdValues.length ) {
toStringBuilder.append( ", " );
}
}
toStringBuilder.append( "]" );
return toStringBuilder.toString();
}
}
);
}
@SuppressWarnings( {"UnusedDeclaration"})
public String getEntityName() {
return entityName;
}
@SuppressWarnings( {"UnusedDeclaration"})
public String getTenantId() {
return tenantId;
}
@SuppressWarnings( {"UnusedDeclaration"})
public Serializable[] getNaturalIdValues() {
return naturalIdValues;
}
@Override
public String toString() {
return toString.getValue();
}
@Override
public int hashCode() {
return this.hashCode;
}
@Override
public boolean equals(Object o) {
if ( o == null ) {
return false;
}
if ( this == o ) {
return true;
}
if ( hashCode != o.hashCode() || !( o instanceof NaturalIdCacheKey ) ) {
return false;
}
final NaturalIdCacheKey other = (NaturalIdCacheKey) o;
return EqualsHelper.equals( entityName, other.entityName )
&& EqualsHelper.equals( tenantId, other.tenantId )
&& Arrays.deepEquals( this.naturalIdValues, other.naturalIdValues );
}
private void readObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException {
ois.defaultReadObject();
initTransients();
}
}