/*
* Copyright 2004-2009 the original author or authors.
*
* 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 org.compass.gps.device.hibernate.lifecycle;
import java.util.ArrayList;
import org.compass.gps.device.hibernate.HibernateGpsDevice;
import org.compass.gps.device.hibernate.HibernateGpsDeviceException;
import org.hibernate.SessionFactory;
import org.hibernate.event.EventListeners;
import org.hibernate.event.PostDeleteEventListener;
import org.hibernate.event.PostInsertEventListener;
import org.hibernate.event.PostUpdateEventListener;
import org.hibernate.impl.SessionFactoryImpl;
/**
* Injects lifecycle listeners directly into Hibernate for mirroring operations.
*
* <p>By default, registers with plain insert/update/delete listeners, which will be triggered
* by Hibernate before committing (and up to Hibernate flushing logic). Also allows to be created
* with setting the <code>registerPostCommitListeneres</code> to <code>true</code> which will cause
* the insert/update/delete listeneres to be registered as post commit events.
*
* @author kimchy
*/
public class DefaultHibernateEntityLifecycleInjector implements HibernateEntityLifecycleInjector {
protected boolean registerPostCommitListeneres = false;
protected boolean marshallIds = false;
protected boolean pendingCascades = true;
protected boolean processCollection = true;
public DefaultHibernateEntityLifecycleInjector() {
this(false);
}
/**
* 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 DefaultHibernateEntityLifecycleInjector(boolean registerPostCommitListeneres) {
this.registerPostCommitListeneres = registerPostCommitListeneres;
}
/**
* Should the listener try and marshall ids for the event listener of post insert. Some
* Hibernate versions won't put the generated ids in the object that is inserted. Defaults
* to <code>false</code>.
*/
public void setMarshallIds(boolean marshallIds) {
this.marshallIds = marshallIds;
}
/**
* Should the listener try and handle pending cascades avoiding trying to save/update relationships in Compass
* before they were processed by Hibernate. Default to <code>true<code>.
*
* <p>Note, if set, might cause Compass event processing to be a *tad* slower.
*/
public void setPendingCascades(boolean pendingCascades) {
this.pendingCascades = pendingCascades;
}
/**
* Should the event listener automatically set the processed flag on collections that are created as a result
* of the marshalling process of Compass. Defaults to <code>true</code>.
*/
public void setProcessCollection(boolean processCollection) {
this.processCollection = processCollection;
}
public void injectLifecycle(SessionFactory sessionFactory, HibernateGpsDevice device) throws HibernateGpsDeviceException {
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) sessionFactory;
EventListeners eventListeners = sessionFactoryImpl.getEventListeners();
Object hibernateEventListener = doCreateListener(device);
if (hibernateEventListener instanceof PostInsertEventListener) {
PostInsertEventListener[] postInsertEventListeners;
if (registerPostCommitListeneres) {
postInsertEventListeners = eventListeners.getPostCommitInsertEventListeners();
} else {
postInsertEventListeners = eventListeners.getPostInsertEventListeners();
}
PostInsertEventListener[] tempPostInsertEventListeners = new PostInsertEventListener[postInsertEventListeners.length + 1];
System.arraycopy(postInsertEventListeners, 0, tempPostInsertEventListeners, 0, postInsertEventListeners.length);
tempPostInsertEventListeners[postInsertEventListeners.length] = (PostInsertEventListener) hibernateEventListener;
if (registerPostCommitListeneres) {
eventListeners.setPostCommitInsertEventListeners(tempPostInsertEventListeners);
} else {
eventListeners.setPostInsertEventListeners(tempPostInsertEventListeners);
}
}
if (hibernateEventListener instanceof PostUpdateEventListener) {
PostUpdateEventListener[] postUpdateEventListeners;
if (registerPostCommitListeneres) {
postUpdateEventListeners = eventListeners.getPostCommitUpdateEventListeners();
} else {
postUpdateEventListeners = eventListeners.getPostUpdateEventListeners();
}
PostUpdateEventListener[] tempPostUpdateEventListeners = new PostUpdateEventListener[postUpdateEventListeners.length + 1];
System.arraycopy(postUpdateEventListeners, 0, tempPostUpdateEventListeners, 0, postUpdateEventListeners.length);
tempPostUpdateEventListeners[postUpdateEventListeners.length] = (PostUpdateEventListener) hibernateEventListener;
if (registerPostCommitListeneres) {
eventListeners.setPostCommitUpdateEventListeners(tempPostUpdateEventListeners);
} else {
eventListeners.setPostUpdateEventListeners(tempPostUpdateEventListeners);
}
}
if (hibernateEventListener instanceof PostDeleteEventListener) {
PostDeleteEventListener[] postDeleteEventListeners;
if (registerPostCommitListeneres) {
postDeleteEventListeners = eventListeners.getPostCommitDeleteEventListeners();
} else {
postDeleteEventListeners = eventListeners.getPostDeleteEventListeners();
}
PostDeleteEventListener[] tempPostDeleteEventListeners = new PostDeleteEventListener[postDeleteEventListeners.length + 1];
System.arraycopy(postDeleteEventListeners, 0, tempPostDeleteEventListeners, 0, postDeleteEventListeners.length);
tempPostDeleteEventListeners[postDeleteEventListeners.length] = (PostDeleteEventListener) hibernateEventListener;
if (registerPostCommitListeneres) {
eventListeners.setPostCommitDeleteEventListeners(tempPostDeleteEventListeners);
} else {
eventListeners.setPostDeleteEventListeners(tempPostDeleteEventListeners);
}
}
}
public void removeLifecycle(SessionFactory sessionFactory, HibernateGpsDevice device) throws HibernateGpsDeviceException {
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) sessionFactory;
EventListeners eventListeners = sessionFactoryImpl.getEventListeners();
PostInsertEventListener[] postInsertEventListeners;
if (registerPostCommitListeneres) {
postInsertEventListeners = eventListeners.getPostCommitInsertEventListeners();
} else {
postInsertEventListeners = eventListeners.getPostInsertEventListeners();
}
ArrayList tempPostInsertEventListeners = new ArrayList();
for (int i = 0; i < postInsertEventListeners.length; i++) {
PostInsertEventListener postInsertEventListener = postInsertEventListeners[i];
if (!(postInsertEventListener instanceof HibernateEventListener)) {
tempPostInsertEventListeners.add(postInsertEventListener);
}
}
if (registerPostCommitListeneres) {
eventListeners.setPostCommitInsertEventListeners((PostInsertEventListener[]) tempPostInsertEventListeners.toArray(new PostInsertEventListener[tempPostInsertEventListeners.size()]));
} else {
eventListeners.setPostInsertEventListeners((PostInsertEventListener[]) tempPostInsertEventListeners.toArray(new PostInsertEventListener[tempPostInsertEventListeners.size()]));
}
PostUpdateEventListener[] postUpdateEventListeners;
if (registerPostCommitListeneres) {
postUpdateEventListeners = eventListeners.getPostCommitUpdateEventListeners();
} else {
postUpdateEventListeners = eventListeners.getPostUpdateEventListeners();
}
ArrayList tempPostUpdateEventListeners = new ArrayList();
for (int i = 0; i < postUpdateEventListeners.length; i++) {
PostUpdateEventListener postUpdateEventListener = postUpdateEventListeners[i];
if (!(postUpdateEventListener instanceof HibernateEventListener)) {
tempPostUpdateEventListeners.add(postUpdateEventListener);
}
}
if (registerPostCommitListeneres) {
eventListeners.setPostCommitUpdateEventListeners((PostUpdateEventListener[]) tempPostUpdateEventListeners.toArray(new PostUpdateEventListener[tempPostUpdateEventListeners.size()]));
} else {
eventListeners.setPostUpdateEventListeners((PostUpdateEventListener[]) tempPostUpdateEventListeners.toArray(new PostUpdateEventListener[tempPostUpdateEventListeners.size()]));
}
PostDeleteEventListener[] postDeleteEventListeners;
if (registerPostCommitListeneres) {
postDeleteEventListeners = eventListeners.getPostCommitDeleteEventListeners();
} else {
postDeleteEventListeners = eventListeners.getPostDeleteEventListeners();
}
ArrayList tempPostDeleteEventListeners = new ArrayList();
for (int i = 0; i < postDeleteEventListeners.length; i++) {
PostDeleteEventListener postDeleteEventListener = postDeleteEventListeners[i];
if (!(postDeleteEventListener instanceof HibernateEventListener)) {
tempPostDeleteEventListeners.add(postDeleteEventListener);
}
}
if (registerPostCommitListeneres) {
eventListeners.setPostCommitDeleteEventListeners((PostDeleteEventListener[]) tempPostDeleteEventListeners.toArray(new PostDeleteEventListener[tempPostDeleteEventListeners.size()]));
} else {
eventListeners.setPostDeleteEventListeners((PostDeleteEventListener[]) tempPostDeleteEventListeners.toArray(new PostDeleteEventListener[tempPostDeleteEventListeners.size()]));
}
}
protected Object doCreateListener(HibernateGpsDevice device) {
return new HibernateEventListener(device, marshallIds, pendingCascades, processCollection);
}
}