/* * 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.impl; import java.lang.reflect.Constructor; import java.util.Map; import org.hibernate.boot.registry.StandardServiceInitiator; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.ogm.cfg.OgmProperties; import org.hibernate.ogm.compensation.impl.InvocationCollectingGridDialect; import org.hibernate.ogm.datastore.spi.DatastoreProvider; import org.hibernate.ogm.dialect.batch.spi.BatchableGridDialect; import org.hibernate.ogm.dialect.batch.spi.GroupingByEntityDialect; import org.hibernate.ogm.dialect.eventstate.impl.EventContextManager; import org.hibernate.ogm.dialect.spi.GridDialect; import org.hibernate.ogm.util.configurationreader.impl.DefaultClassPropertyReaderContext; import org.hibernate.ogm.util.configurationreader.impl.Instantiator; import org.hibernate.ogm.util.configurationreader.spi.ConfigurationPropertyReader; import org.hibernate.ogm.util.impl.Log; import org.hibernate.ogm.util.impl.LoggerFactory; import org.hibernate.service.spi.ServiceRegistryImplementor; /** * Contributes the {@link GridDialect} service, based on the configuration via {@link OgmProperties#GRID_DIALECT}, using * the implementation returned by {@link DatastoreProvider#getDefaultDialect()} as fallback. * * @author Emmanuel Bernard <emmanuel@hibernate.org> * @author Gunnar Morling */ public class GridDialectInitiator implements StandardServiceInitiator<GridDialect> { public static final GridDialectInitiator INSTANCE = new GridDialectInitiator(); private static final Log log = LoggerFactory.make(); private GridDialectInitiator() { } @Override public Class<GridDialect> getServiceInitiated() { return GridDialect.class; } @Override public GridDialect initiateService(Map configurationValues, ServiceRegistryImplementor registry) { DatastoreProvider datastore = registry.getService( DatastoreProvider.class ); boolean errorHandlerConfigured = configurationValues.containsKey( OgmProperties.ERROR_HANDLER ); EventContextManager eventContext = registry.getService( EventContextManager.class ); ConfigurationPropertyReader propertyReader = new ConfigurationPropertyReader( configurationValues, registry.getService( ClassLoaderService.class ) ); return ( (DefaultClassPropertyReaderContext<GridDialect>) propertyReader.property( OgmProperties.GRID_DIALECT, GridDialect.class ) .instantiate() ) .withDefaultImplementation( registry.getService( DatastoreProvider.class ).getDefaultDialect() ) .withInstantiator( new GridDialectInstantiator( datastore, errorHandlerConfigured, eventContext ) ) .getValue(); } private static class GridDialectInstantiator implements Instantiator<GridDialect> { private final DatastoreProvider datastore; private final boolean errorHandlerConfigured; private final EventContextManager eventContext; public GridDialectInstantiator(DatastoreProvider datastore, boolean errorHandlerConfigured, EventContextManager eventContext) { this.datastore = datastore; this.errorHandlerConfigured = errorHandlerConfigured; this.eventContext = eventContext; } @Override public GridDialect newInstance(Class<? extends GridDialect> clazz) { try { // FIXME not sure I like this constructor business. Argue with Sanne // to me that's blocking the doors for future enhancements (ie injecting more things) // an alternative is to pass the ServiceRegistry verbatim but I'm not sure that's enough either Constructor<?> injector = null; for ( Constructor<?> constructor : clazz.getConstructors() ) { Class<?>[] parameterTypes = constructor.getParameterTypes(); if ( parameterTypes.length == 1 && DatastoreProvider.class.isAssignableFrom( parameterTypes[0] ) ) { injector = constructor; break; } } if ( injector == null ) { throw log.gridDialectHasNoProperConstructor( clazz ); } GridDialect gridDialect = (GridDialect) injector.newInstance( datastore ); if ( errorHandlerConfigured ) { gridDialect = new InvocationCollectingGridDialect( gridDialect, eventContext ); } if ( GridDialects.hasFacet( gridDialect, BatchableGridDialect.class ) || GridDialects.hasFacet( gridDialect, GroupingByEntityDialect.class ) ) { gridDialect = new BatchOperationsDelegator( gridDialect, eventContext ); } log.useGridDialect( gridDialect.getClass() ); if ( GridDialectLogger.activationNeeded() ) { gridDialect = new GridDialectLogger( gridDialect ); log.info( "Grid dialect logs are active" ); } else { log.info( "Grid dialect logs are disabled" ); } return gridDialect; } catch ( Exception e ) { throw log.cannotInstantiateGridDialect( clazz, e ); } } } }