/*
* Hibernate OGM, Domain model persistence for NoSQL datastores
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.ogm.dialect.eventstate.impl;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.ogm.cfg.OgmProperties;
import org.hibernate.ogm.compensation.impl.ErrorHandlerEnabledTransactionCoordinatorDecorator;
import org.hibernate.ogm.compensation.impl.OperationCollector;
import org.hibernate.ogm.dialect.batch.spi.OperationsQueue;
import org.hibernate.ogm.dialect.impl.BatchOperationsDelegator;
import org.hibernate.ogm.dialect.impl.GridDialects;
import org.hibernate.ogm.dialect.spi.GridDialect;
import org.hibernate.ogm.util.impl.Immutable;
import org.hibernate.service.spi.ServiceRegistryImplementor;
/**
* Holds all known {@link EventStateLifecycle}s.
*
* @author Gunnar Morling
*/
class EventStateLifecycles {
public static final EventStateLifecycles INSTANCE = new EventStateLifecycles();
@Immutable
private final Map<Class<?>, EventStateLifecycle<?>> lifecycles;
private EventStateLifecycles() {
Map<Class<?>, EventStateLifecycle<?>> lifecycles = new HashMap<>();
lifecycles.put( OperationCollector.class, OperationCollectorLifecycle.INSTANCE );
lifecycles.put( OperationsQueue.class, OperationsQueueLifecycle.INSTANCE );
this.lifecycles = Collections.unmodifiableMap( lifecycles );
}
public Map<Class<?>, EventStateLifecycle<?>> getEnabledLifecycles(ServiceRegistryImplementor serviceRegistry) {
Map<Class<?>, EventStateLifecycle<?>> enabledLifecycles = new HashMap<>();
for ( Entry<Class<?>, EventStateLifecycle<?>> lifecycle : lifecycles.entrySet() ) {
if ( lifecycle.getValue().mustBeEnabled( serviceRegistry ) ) {
enabledLifecycles.put( lifecycle.getKey(), lifecycle.getValue() );
}
}
return enabledLifecycles;
}
/**
* Initializes the {@link OperationCollector} if accessed for the first time during a given event cycle.
*/
private static class OperationCollectorLifecycle implements EventStateLifecycle<OperationCollector> {
private static EventStateLifecycle<?> INSTANCE = new OperationCollectorLifecycle();
@Override
public boolean mustBeEnabled(ServiceRegistryImplementor serviceRegistry) {
return serviceRegistry.getService( ConfigurationService.class ).getSettings().containsKey( OgmProperties.ERROR_HANDLER );
}
@Override
public OperationCollector create(SessionImplementor session) {
return ( (ErrorHandlerEnabledTransactionCoordinatorDecorator) session.getTransactionCoordinator() ).getOperationCollector();
}
@Override
public void onFinish(OperationCollector state, SessionImplementor session) {
// nothing to do
}
}
/**
* Initializes the {@link OperationsQueue} if accessed for the first time during a given event cycle and executes
* the operations it batches upon event finish.
*
* @author Gunnar Morling
*/
private static class OperationsQueueLifecycle implements EventStateLifecycle<OperationsQueue> {
private static EventStateLifecycle<?> INSTANCE = new OperationsQueueLifecycle();
@Override
public boolean mustBeEnabled(ServiceRegistryImplementor serviceRegistry) {
GridDialect gridDialect = serviceRegistry.getService( GridDialect.class );
BatchOperationsDelegator batchDelegator = GridDialects.getDelegateOrNull( gridDialect, BatchOperationsDelegator.class );
return batchDelegator != null;
}
@Override
public OperationsQueue create(SessionImplementor session) {
return new OperationsQueue();
}
@Override
public void onFinish(OperationsQueue operationsQueue, SessionImplementor session) {
GridDialect gridDialect = session.getFactory()
.getServiceRegistry()
.getService( GridDialect.class );
if ( operationsQueue.size() > 0 ) {
GridDialects.getDelegateOrNull( gridDialect, BatchOperationsDelegator.class ).executeBatch( operationsQueue );
}
operationsQueue.close();
}
}
}