package org.hibernate.event.internal;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.pretty.MessageHelper;
public class EntityCopyAllowedLoggedObserver extends EntityCopyAllowedObserver {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( EntityCopyAllowedLoggedObserver.class );
public static final String SHORT_NAME = "log";
private Map<String, Integer> countsByEntityName;
private Map<Object, Set<Object>> managedToMergeEntitiesXref = null;
public static boolean isDebugLoggingEnabled() {
return LOG.isDebugEnabled();
}
@Override
public void entityCopyDetected(
Object managedEntity,
Object mergeEntity1,
Object mergeEntity2,
EventSource session) {
final String entityName = session.getEntityName( managedEntity );
LOG.trace(
String.format(
"More than one representation of the same persistent entity being merged for: %s",
MessageHelper.infoString(
entityName,
session.getIdentifier( managedEntity )
)
)
);
Set<Object> detachedEntitiesForManaged = null;
if ( managedToMergeEntitiesXref == null ) {
managedToMergeEntitiesXref = new IdentityHashMap<Object, Set<Object>>();
}
else {
detachedEntitiesForManaged = managedToMergeEntitiesXref.get( managedEntity );
}
if ( detachedEntitiesForManaged == null ) {
detachedEntitiesForManaged = new IdentitySet();
managedToMergeEntitiesXref.put( managedEntity, detachedEntitiesForManaged );
incrementEntityNameCount( entityName );
}
detachedEntitiesForManaged.add( mergeEntity1 );
detachedEntitiesForManaged.add( mergeEntity2 );
}
private void incrementEntityNameCount(String entityName) {
Integer countBeforeIncrement = 0;
if ( countsByEntityName == null ) {
countsByEntityName = new TreeMap<String, Integer>();
}
else {
countBeforeIncrement = countsByEntityName.get( entityName );
if ( countBeforeIncrement == null ) {
countBeforeIncrement = 0;
}
}
countsByEntityName.put( entityName, countBeforeIncrement + 1 );
}
public void clear() {
if ( managedToMergeEntitiesXref != null ) {
managedToMergeEntitiesXref.clear();
managedToMergeEntitiesXref = null;
}
if ( countsByEntityName != null ) {
countsByEntityName.clear();
countsByEntityName = null;
}
}
@Override
public void topLevelMergeComplete(EventSource session) {
if ( countsByEntityName != null ) {
for ( Map.Entry<String, Integer> entry : countsByEntityName.entrySet() ) {
final String entityName = entry.getKey();
final int count = entry.getValue();
LOG.debug(
String.format(
"Summary: number of %s entities with multiple representations merged: %d",
entityName,
count
)
);
}
}
else {
LOG.debug( "No entity copies merged." );
}
if ( managedToMergeEntitiesXref != null ) {
for ( Map.Entry<Object,Set<Object>> entry : managedToMergeEntitiesXref.entrySet() ) {
Object managedEntity = entry.getKey();
Set mergeEntities = entry.getValue();
StringBuilder sb = new StringBuilder( "Details: merged ")
.append( mergeEntities.size() )
.append( " representations of the same entity " )
.append(
MessageHelper.infoString(
session.getEntityName( managedEntity ),
session.getIdentifier( managedEntity )
)
)
.append( " being merged: " );
boolean first = true;
for ( Object mergeEntity : mergeEntities ) {
if ( first ) {
first = false;
}
else {
sb.append( ", " );
}
sb.append( getManagedOrDetachedEntityString( managedEntity, mergeEntity ) );
}
sb.append( "; resulting managed entity: [" ).append( managedEntity ).append( ']' );
LOG.debug( sb.toString());
}
}
}
private String getManagedOrDetachedEntityString(Object managedEntity, Object mergeEntity ) {
if ( mergeEntity == managedEntity) {
return "Managed: [" + mergeEntity + "]";
}
else {
return "Detached: [" + mergeEntity + "]";
}
}
}