/**
* Copyright 2010 Molindo GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package at.molindo.esi4j.module.hibernate;
import static org.hibernate.event.spi.EventType.*;
import java.util.Iterator;
import org.hibernate.SessionFactory;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PostCollectionRecreateEventListener;
import org.hibernate.event.spi.PostCollectionRemoveEventListener;
import org.hibernate.event.spi.PostCollectionUpdateEventListener;
import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import at.molindo.esi4j.chain.Esi4JBatchedEventProcessor;
/**
* Injects lifecycle listeners directly into Hibernate for mirroring operations.
*/
public class DefaultHibernateLifecycleInjector implements HibernateLifecycleInjector {
private final boolean registerPostCommitListeneres;
private Object _listener;
public DefaultHibernateLifecycleInjector() {
this(true);
}
/**
* Creates a new lifecycle injector. Allows to control if the insert/update/delete even listeners will be registered
* with post commit listeres (flag it <code>true</code>) or with plain post events (triggered based on Hibrenate
* flushing logic).
*
* @param registerPostCommitListeneres
* <code>true</code> if post commit listeners will be registered. <code>false</code> for plain listeners.
*/
public DefaultHibernateLifecycleInjector(final boolean registerPostCommitListeneres) {
this.registerPostCommitListeneres = registerPostCommitListeneres;
}
@Override
public synchronized void injectLifecycle(final SessionFactory sessionFactory, final Esi4JBatchedEventProcessor batchedEventProcessor) {
if (_listener != null) {
throw new IllegalStateException("already injected");
}
final SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) sessionFactory;
final EventListenerRegistry registry = sessionFactoryImpl.getServiceRegistry()
.getService(EventListenerRegistry.class);
_listener = doCreateListener(sessionFactoryImpl, batchedEventProcessor);
if (_listener instanceof PostInsertEventListener) {
if (registerPostCommitListeneres) {
registry.appendListeners(EventType.POST_COMMIT_INSERT, (PostInsertEventListener) _listener);
} else {
registry.appendListeners(EventType.POST_INSERT, (PostInsertEventListener) _listener);
}
}
if (_listener instanceof PostUpdateEventListener) {
if (registerPostCommitListeneres) {
registry.appendListeners(EventType.POST_COMMIT_UPDATE, (PostUpdateEventListener) _listener);
} else {
registry.appendListeners(EventType.POST_UPDATE, (PostUpdateEventListener) _listener);
}
}
if (_listener instanceof PostDeleteEventListener) {
if (registerPostCommitListeneres) {
registry.appendListeners(EventType.POST_COMMIT_DELETE, (PostDeleteEventListener) _listener);
} else {
registry.appendListeners(EventType.POST_DELETE, (PostDeleteEventListener) _listener);
}
}
// collections
if (!registerPostCommitListeneres) {
if (_listener instanceof PostCollectionRecreateEventListener) {
registry.appendListeners(EventType.POST_COLLECTION_RECREATE, (PostCollectionRecreateEventListener) _listener);
}
if (_listener instanceof PostCollectionRemoveEventListener) {
registry.appendListeners(EventType.POST_COLLECTION_REMOVE, (PostCollectionRemoveEventListener) _listener);
}
if (_listener instanceof PostCollectionUpdateEventListener) {
registry.appendListeners(EventType.POST_COLLECTION_UPDATE, (PostCollectionUpdateEventListener) _listener);
}
}
}
@Override
public synchronized void removeLifecycle(final SessionFactory sessionFactory) {
if (_listener == null) {
return;
}
final SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) sessionFactory;
final EventListenerRegistry registry = sessionFactoryImpl.getServiceRegistry()
.getService(EventListenerRegistry.class);
if (registerPostCommitListeneres) {
removeListeners(registry, _listener, POST_COMMIT_INSERT, POST_COMMIT_UPDATE, POST_COMMIT_DELETE);
} else {
removeListeners(registry, _listener, POST_INSERT, POST_UPDATE, POST_DELETE, POST_COLLECTION_RECREATE, POST_COLLECTION_UPDATE, POST_COLLECTION_REMOVE);
}
_listener = null;
}
private void removeListeners(final EventListenerRegistry registry, final Object listener, final EventType<?>... eventTypes) {
for (final EventType<?> eventType : eventTypes) {
final Iterator<?> iter = registry.getEventListenerGroup(eventType).listeners().iterator();
while (iter.hasNext()) {
if (iter.next() == listener) {
iter.remove();
}
}
}
}
protected Object doCreateListener(final SessionFactoryImpl sessionFactory, final Esi4JBatchedEventProcessor batchedEventProcessor) {
return new HibernateEventListener(batchedEventProcessor);
}
}