/* * 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.io.Serializable; import java.util.List; import java.util.Map; import org.hibernate.LockMode; import org.hibernate.dialect.lock.LockingStrategy; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.ogm.dialect.batch.spi.BatchableGridDialect; import org.hibernate.ogm.dialect.batch.spi.GroupingByEntityDialect; import org.hibernate.ogm.dialect.batch.spi.OperationsQueue; import org.hibernate.ogm.dialect.identity.spi.IdentityColumnAwareGridDialect; import org.hibernate.ogm.dialect.multiget.spi.MultigetGridDialect; import org.hibernate.ogm.dialect.optimisticlock.spi.OptimisticLockingAwareGridDialect; import org.hibernate.ogm.dialect.query.spi.BackendQuery; import org.hibernate.ogm.dialect.query.spi.ClosableIterator; import org.hibernate.ogm.dialect.query.spi.ParameterMetadataBuilder; import org.hibernate.ogm.dialect.query.spi.QueryParameters; import org.hibernate.ogm.dialect.query.spi.QueryableGridDialect; import org.hibernate.ogm.dialect.spi.AssociationContext; import org.hibernate.ogm.dialect.spi.AssociationTypeContext; import org.hibernate.ogm.dialect.spi.DuplicateInsertPreventionStrategy; import org.hibernate.ogm.dialect.spi.GridDialect; import org.hibernate.ogm.dialect.spi.ModelConsumer; import org.hibernate.ogm.dialect.spi.NextValueRequest; import org.hibernate.ogm.dialect.spi.OperationContext; import org.hibernate.ogm.dialect.spi.SessionFactoryLifecycleAwareDialect; import org.hibernate.ogm.dialect.spi.TupleContext; import org.hibernate.ogm.dialect.spi.TupleTypeContext; import org.hibernate.ogm.entityentry.impl.TuplePointer; import org.hibernate.ogm.model.key.spi.AssociationKey; import org.hibernate.ogm.model.key.spi.AssociationKeyMetadata; import org.hibernate.ogm.model.key.spi.EntityKey; import org.hibernate.ogm.model.key.spi.EntityKeyMetadata; import org.hibernate.ogm.model.spi.Association; import org.hibernate.ogm.model.spi.Tuple; import org.hibernate.ogm.type.spi.GridType; import org.hibernate.ogm.util.impl.Contracts; import org.hibernate.persister.entity.Lockable; import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.ServiceRegistryAwareService; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.type.Type; /** * A {@link GridDialect} which delegates all the operations to another dialect implementation. Useful as base class for * dialect wrappers which wish to override only a few methods of the {@code GridDialect}, while delegating all the * others. * <p> * <b>Note:</b> This class implements all the dialect facet interfaces such as {@link QueryableGridDialect}, one * therefore must not use {@code instanceof} to determine the capabilities of a dialect, but rather * {@link GridDialects#getDialectFacetOrNull(GridDialect, Class)} should be used. * * @author Gunnar Morling */ public class ForwardingGridDialect<T extends Serializable> implements GridDialect, BatchableGridDialect, SessionFactoryLifecycleAwareDialect, IdentityColumnAwareGridDialect, QueryableGridDialect<T>, OptimisticLockingAwareGridDialect, Configurable, ServiceRegistryAwareService, MultigetGridDialect, GroupingByEntityDialect { private final GridDialect gridDialect; private final BatchableGridDialect batchableGridDialect; private final GroupingByEntityDialect groupingByEntityGridDialect; private final QueryableGridDialect<T> queryableGridDialect; private final SessionFactoryLifecycleAwareDialect sessionFactoryAwareDialect; private final IdentityColumnAwareGridDialect identityColumnAwareGridDialect; private final OptimisticLockingAwareGridDialect optimisticLockingAwareGridDialect; private final MultigetGridDialect multigetGridDialect; @SuppressWarnings("unchecked") public ForwardingGridDialect(GridDialect gridDialect) { Contracts.assertParameterNotNull( gridDialect, "gridDialect" ); this.gridDialect = gridDialect; this.batchableGridDialect = GridDialects.getDialectFacetOrNull( gridDialect, BatchableGridDialect.class ); this.groupingByEntityGridDialect = GridDialects.getDialectFacetOrNull( gridDialect, GroupingByEntityDialect.class ); this.queryableGridDialect = GridDialects.getDialectFacetOrNull( gridDialect, QueryableGridDialect.class ); this.sessionFactoryAwareDialect = GridDialects.getDialectFacetOrNull( gridDialect, SessionFactoryLifecycleAwareDialect.class ); this.identityColumnAwareGridDialect = GridDialects.getDialectFacetOrNull( gridDialect, IdentityColumnAwareGridDialect.class ); this.optimisticLockingAwareGridDialect = GridDialects.getDialectFacetOrNull( gridDialect, OptimisticLockingAwareGridDialect.class ); this.multigetGridDialect = GridDialects.getDialectFacetOrNull( gridDialect, MultigetGridDialect.class ); } /** * Get the underlying grid dialect. * * @return the wrapped dialect implementation. */ public GridDialect getGridDialect() { return gridDialect; } /* * @see org.hibernate.ogm.dialect.spi.GridDialect */ @Override public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) { return gridDialect.getLockingStrategy( lockable, lockMode ); } @Override public Tuple getTuple(EntityKey key, OperationContext operationContext) { return gridDialect.getTuple( key, operationContext ); } @Override public Tuple createTuple(EntityKey key, OperationContext operationContext) { return gridDialect.createTuple( key, operationContext ); } @Override public void insertOrUpdateTuple(EntityKey key, TuplePointer tuplePointer, TupleContext tupleContext) { gridDialect.insertOrUpdateTuple( key, tuplePointer, tupleContext ); } @Override public void removeTuple(EntityKey key, TupleContext tupleContext) { gridDialect.removeTuple( key, tupleContext ); } @Override public Association getAssociation(AssociationKey key, AssociationContext associationContext) { return gridDialect.getAssociation( key, associationContext ); } @Override public Association createAssociation(AssociationKey key, AssociationContext associationContext) { return gridDialect.createAssociation( key, associationContext ); } @Override public void insertOrUpdateAssociation(AssociationKey key, Association association, AssociationContext associationContext) { gridDialect.insertOrUpdateAssociation( key, association, associationContext ); } @Override public void removeAssociation(AssociationKey key, AssociationContext associationContext) { gridDialect.removeAssociation( key, associationContext ); } @Override public boolean isStoredInEntityStructure(AssociationKeyMetadata associationKeyMetadata, AssociationTypeContext associationTypeContext) { return gridDialect.isStoredInEntityStructure( associationKeyMetadata, associationTypeContext ); } @Override public Number nextValue(NextValueRequest request) { return gridDialect.nextValue( request ); } @Override public boolean supportsSequences() { return gridDialect.supportsSequences(); } @Override public GridType overrideType(Type type) { return gridDialect.overrideType( type ); } @Override public void forEachTuple(ModelConsumer consumer, TupleTypeContext tupleTypeContext, EntityKeyMetadata entityKeyMetadata) { gridDialect.forEachTuple( consumer, tupleTypeContext, entityKeyMetadata ); } @Override public DuplicateInsertPreventionStrategy getDuplicateInsertPreventionStrategy(EntityKeyMetadata entityKeyMetadata) { return gridDialect.getDuplicateInsertPreventionStrategy( entityKeyMetadata ); } /* * @see org.hibernate.ogm.dialect.batch.spi.BatchableGridDialect * @see org.hibernate.ogm.dialect.batch.spi.GroupingByEntityDialect */ @Override public void executeBatch(OperationsQueue queue) { if ( batchableGridDialect != null ) { batchableGridDialect.executeBatch( queue ); } else if ( groupingByEntityGridDialect != null ) { groupingByEntityGridDialect.executeBatch( queue ); } } /* * @see org.hibernate.ogm.dialect.queryable.spi.QueryableGridDialect */ @Override public ClosableIterator<Tuple> executeBackendQuery(BackendQuery<T> query, QueryParameters queryParameters, TupleContext tupleContext) { return queryableGridDialect.executeBackendQuery( query, queryParameters, tupleContext ); } @Override public int executeBackendUpdateQuery(BackendQuery<T> query, QueryParameters queryParameters, TupleContext tupleContext) { return queryableGridDialect.executeBackendUpdateQuery( query, queryParameters, tupleContext ); } @Override public ParameterMetadataBuilder getParameterMetadataBuilder() { return queryableGridDialect.getParameterMetadataBuilder(); } @Override public T parseNativeQuery(String nativeQuery) { return queryableGridDialect.parseNativeQuery( nativeQuery ); } /* * @see org.hibernate.ogm.dialect.optimisticlock.spi.OptimisticLockingAwareGridDialect */ @Override public boolean updateTupleWithOptimisticLock(EntityKey entityKey, Tuple oldLockState, Tuple tuple, TupleContext tupleContext) { return optimisticLockingAwareGridDialect.updateTupleWithOptimisticLock( entityKey, oldLockState, tuple, tupleContext ); } @Override public boolean removeTupleWithOptimisticLock(EntityKey entityKey, Tuple oldLockState, TupleContext tupleContext) { return optimisticLockingAwareGridDialect.removeTupleWithOptimisticLock( entityKey, oldLockState, tupleContext ); } /* * @see org.hibernate.ogm.dialect.spi.SessionFactoryLifecycleAwareDialect */ @Override public void sessionFactoryCreated(SessionFactoryImplementor sessionFactoryImplementor) { sessionFactoryAwareDialect.sessionFactoryCreated( sessionFactoryImplementor ); } /* * @see org.hibernate.ogm.dialect.identitycolumnaware.IdentityColumnAwareGridDialect */ @Override public Tuple createTuple(EntityKeyMetadata entityKeyMetadata, OperationContext operationContext) { return identityColumnAwareGridDialect.createTuple( entityKeyMetadata, operationContext ); } @Override public void insertTuple(EntityKeyMetadata entityKeyMetadata, Tuple tuple, TupleContext tupleContext) { identityColumnAwareGridDialect.insertTuple( entityKeyMetadata, tuple, tupleContext ); } /* * @see org.hibernate.ogm.dialect.multiget.spi.MultigetGridDialect */ @Override public List<Tuple> getTuples(EntityKey[] keys, TupleContext tupleContext) { return multigetGridDialect.getTuples( keys, tupleContext ); } /* * @see org.hibernate.service.spi.ServiceRegistryAwareService */ @Override public void injectServices(ServiceRegistryImplementor serviceRegistry) { if ( gridDialect instanceof ServiceRegistryAwareService ) { ( (ServiceRegistryAwareService) gridDialect ).injectServices( serviceRegistry ); } } /* * @see org.hibernate.service.spi.Configurable */ @Override public void configure(Map configurationValues) { if ( gridDialect instanceof Configurable ) { ( (Configurable) gridDialect ).configure( configurationValues ); } } @Override public String toString() { StringBuilder sb = new StringBuilder( getClass().getSimpleName() ); sb.append( " -> " ); GridDialect delegate = gridDialect; while ( delegate instanceof ForwardingGridDialect ) { sb.append( delegate.getClass().getSimpleName() ); sb.append( " -> " ); delegate = ( (ForwardingGridDialect<?>) delegate ).getGridDialect(); } sb.append( delegate.getClass().getSimpleName() ); sb.append( "]" ); return sb.toString(); } @Override public void flushPendingOperations(EntityKey entityKey, TupleContext tupleContext) { groupingByEntityGridDialect.flushPendingOperations( entityKey, tupleContext ); } @Override public boolean usesNavigationalInformationForInverseSideOfAssociations() { return gridDialect.usesNavigationalInformationForInverseSideOfAssociations(); } }