package org.hibernate.jpa.event.internal;
import java.util.HashMap;
import javax.persistence.PersistenceException;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.jpa.event.spi.Callback;
import org.hibernate.jpa.event.spi.CallbackRegistry;
import org.hibernate.jpa.event.spi.CallbackType;
import org.hibernate.jpa.event.spi.CallbackBuilder;
@SuppressWarnings({"unchecked", "serial"})
public class CallbackRegistryImpl implements CallbackRegistry, CallbackBuilder.CallbackRegistrar {
private HashMap<Class, Callback[]> preCreates = new HashMap<Class, Callback[]>();
private HashMap<Class, Callback[]> postCreates = new HashMap<Class, Callback[]>();
private HashMap<Class, Callback[]> preRemoves = new HashMap<Class, Callback[]>();
private HashMap<Class, Callback[]> postRemoves = new HashMap<Class, Callback[]>();
private HashMap<Class, Callback[]> preUpdates = new HashMap<Class, Callback[]>();
private HashMap<Class, Callback[]> postUpdates = new HashMap<Class, Callback[]>();
private HashMap<Class, Callback[]> postLoads = new HashMap<Class, Callback[]>();
@Override
public boolean hasRegisteredCallbacks(Class entityClass, CallbackType callbackType) {
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callbackType );
return notEmpty( map.get( entityClass ) );
}
@Override
public void registerCallbacks(Class entityClass, Callback[] callbacks) {
if ( callbacks == null || callbacks.length == 0 ) {
return;
}
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( callbacks[0].getCallbackType() );
Callback[] entityCallbacks = map.get( entityClass );
if ( entityCallbacks != null ) {
callbacks = ArrayHelper.join( entityCallbacks, callbacks );
}
map.put( entityClass, callbacks );
}
@Override
public void preCreate(Object bean) {
callback( preCreates.get( bean.getClass() ), bean );
}
private boolean notEmpty(Callback[] callbacks) {
return callbacks != null && callbacks.length > 0;
}
@Override
public void postCreate(Object bean) {
callback( postCreates.get( bean.getClass() ), bean );
}
@Override
public boolean preUpdate(Object bean) {
return callback( preUpdates.get( bean.getClass() ), bean );
}
@Override
public void postUpdate(Object bean) {
callback( postUpdates.get( bean.getClass() ), bean );
}
@Override
public void preRemove(Object bean) {
callback( preRemoves.get( bean.getClass() ), bean );
}
@Override
public void postRemove(Object bean) {
callback( postRemoves.get( bean.getClass() ), bean );
}
@Override
public boolean postLoad(Object bean) {
return callback( postLoads.get( bean.getClass() ), bean );
}
private boolean callback(Callback[] callbacks, Object bean) {
if ( callbacks != null && callbacks.length != 0 ) {
for ( Callback callback : callbacks ) {
callback.performCallback( bean );
}
return true;
}
else {
return false;
}
}
private HashMap<Class, Callback[]> determineAppropriateCallbackMap(CallbackType callbackType) {
if ( callbackType == CallbackType.PRE_PERSIST ) {
return preCreates;
}
if ( callbackType == CallbackType.POST_PERSIST ) {
return postCreates;
}
if ( callbackType == CallbackType.PRE_REMOVE ) {
return preRemoves;
}
if ( callbackType == CallbackType.POST_REMOVE ) {
return postRemoves;
}
if ( callbackType == CallbackType.PRE_UPDATE ) {
return preUpdates;
}
if ( callbackType == CallbackType.POST_UPDATE ) {
return postUpdates;
}
if ( callbackType == CallbackType.POST_LOAD ) {
return postLoads;
}
throw new PersistenceException( "Unrecognized JPA callback type [" + callbackType + "]" );
}
public void release() {
preCreates.clear();
postCreates.clear();
preRemoves.clear();
postRemoves.clear();
preUpdates.clear();
postUpdates.clear();
postLoads.clear();
}
@Override
public boolean hasPostCreateCallbacks(Class entityClass) {
return notEmpty( preCreates.get( entityClass ) );
}
@Override
public boolean hasPostUpdateCallbacks(Class entityClass) {
return notEmpty( postUpdates.get( entityClass ) );
}
@Override
public boolean hasPostRemoveCallbacks(Class entityClass) {
return notEmpty( postRemoves.get( entityClass ) );
}
@Override
public boolean hasRegisteredCallbacks(Class entityClass, Class annotationClass) {
final HashMap<Class, Callback[]> map = determineAppropriateCallbackMap( toCallbackType( annotationClass ) );
return map != null && map.containsKey( entityClass );
}
private CallbackType toCallbackType(Class annotationClass) {
if ( annotationClass == CallbackType.POST_LOAD.getCallbackAnnotation() ) {
return CallbackType.POST_LOAD;
}
else if ( annotationClass == CallbackType.PRE_PERSIST.getCallbackAnnotation() ) {
return CallbackType.PRE_PERSIST;
}
else if ( annotationClass == CallbackType.POST_PERSIST.getCallbackAnnotation() ) {
return CallbackType.POST_PERSIST;
}
else if ( annotationClass == CallbackType.PRE_UPDATE.getCallbackAnnotation() ) {
return CallbackType.PRE_UPDATE;
}
else if ( annotationClass == CallbackType.POST_UPDATE.getCallbackAnnotation() ) {
return CallbackType.POST_UPDATE;
}
else if ( annotationClass == CallbackType.PRE_REMOVE.getCallbackAnnotation() ) {
return CallbackType.PRE_REMOVE;
}
else if ( annotationClass == CallbackType.POST_REMOVE.getCallbackAnnotation() ) {
return CallbackType.POST_REMOVE;
}
throw new PersistenceException( "Unrecognized JPA callback annotation [" + annotationClass + "]" );
}
}