package org.neo4j.util; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.transaction.Synchronization; import javax.transaction.Transaction; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.kernel.impl.event.Event; import org.neo4j.kernel.impl.event.EventData; import org.neo4j.kernel.impl.event.ProActiveEventListener; /** * This succer keeps some kind of track of transactions and may filter incoming * events depending on which events have come previously in the transaction. * Optimization issues. F.ex. if ten ISE_PROPERTY_SET events comes in one * transaction for the same event then only ony may be nessecary. */ public abstract class TxAwareProActiveListener implements ProActiveEventListener { private GraphDatabaseUtil graphDbUtil; public TxAwareProActiveListener( GraphDatabaseService graphDb ) { this.graphDbUtil = new GraphDatabaseUtil( graphDb ); } private ConcurrentMap<Transaction, EventFilter> eventLists = new ConcurrentHashMap<Transaction, EventFilter>(); protected abstract Event[] getEvents(); /** * Override this please * @return */ protected EventFilter newFilter() { return EventFilter.HOLLOW_EVENT_FILTER; } /** * Registers this listener to listen to events. */ public void register() { for ( Event event : getEvents() ) { graphDbUtil.registerProActiveEventListener( this, event ); } } /** * Unregisters this listener so that no more events reaches this listener. */ public void unregister() { for ( Event event : getEvents() ) { graphDbUtil.unregisterProActiveEventListener( this, event ); } } protected abstract boolean handleEvent( Event event, EventData data ); protected void txStarted() { } protected void txEnded( boolean committed ) { } public final boolean proActiveEventReceived( Event event, EventData data ) { boolean result = true; try { final Transaction tx = graphDbUtil.getTransactionManager().getTransaction(); EventContext context = new EventContext( event, data ); EventFilter filter = this.eventLists.get( tx ); if ( filter == null ) { filter = this.newFilter(); this.eventLists.put( tx, filter ); tx.registerSynchronization( new Synchronization() { public void afterCompletion( int status ) { eventLists.remove( tx ); } public void beforeCompletion() { } } ); } if ( filter.pass( context.getEvent(), context.getData() ) ) { result = handleEvent( context.getEvent(), context.getData() ); } } catch ( Exception e ) { e.printStackTrace(); result = false; } return result; } }