From 6133c600d0fc15ce3482aaf9c3a29b4a222c98e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Fri, 2 Feb 2024 17:43:02 +0100 Subject: [PATCH] HSEARCH-5068 Move loading strategy configuration and retrieval to pojo-base --- .../impl/MappingFinalizationContextImpl.java | 11 +- .../common/impl/SearchIntegrationBuilder.java | 30 +--- ...earchIntegrationPartialBuildStateImpl.java | 25 ++- .../mapper/mapping/building/spi/Mapper.java | 5 +- .../building/spi/MappingAbortedException.java | 31 ++++ .../spi/MappingFinalizationContext.java | 3 + .../building/spi/MappingFinalizer.java | 5 +- .../util/impl/EntityTypeDescriptor.java | 3 +- .../AbstractHibernateOrmLoadingStrategy.java | 105 +++++++++++- ...rnateOrmEntityIdEntityLoadingStrategy.java | 48 +++--- .../impl/HibernateOrmMassEntityLoader.java | 4 +- .../HibernateOrmMassIdentifierLoader.java | 4 +- ...va => HibernateOrmMassLoadingContext.java} | 16 +- ...EntityIdPropertyEntityLoadingStrategy.java | 45 +++--- ...mSelectionEntityByNonIdPropertyLoader.java | 8 +- .../HibernateOrmSelectionLoadingContext.java | 69 +------- .../HibernateOrmEntityLoadingStrategy.java | 31 +--- .../loading/spi/LoadingMappingContext.java | 3 + .../loading/spi/LoadingSessionContext.java | 7 +- .../orm/loading/spi/LoadingTypeContext.java | 7 +- .../search/mapper/orm/logging/impl/Log.java | 11 -- .../impl/AbstractHibernateOrmTypeContext.java | 72 ++++----- .../HibernateOrmContainedTypeContext.java | 15 +- .../impl/HibernateOrmEntityLoadingBinder.java | 42 +++++ ...rnateOrmEntityTypeMetadataContributor.java | 1 + .../impl/HibernateOrmIndexedTypeContext.java | 19 ++- .../orm/mapping/impl/HibernateOrmMapping.java | 13 +- .../HibernateOrmMappingPartialBuildState.java | 8 +- .../HibernateOrmTypeContextContainer.java | 55 ++----- .../impl/HibernateOrmMassIndexingContext.java | 144 ++--------------- ...ibernateOrmMassIndexingMappingContext.java | 14 +- .../HibernateOrmScopeIndexedTypeContext.java | 29 ---- .../orm/scope/impl/SearchScopeImpl.java | 7 +- .../impl/HibernateOrmSearchSession.java | 2 +- ...bernateOrmSearchSessionMappingContext.java | 3 - ...ibernateOrmSessionTypeContextProvider.java | 3 +- .../PojoRootIdentityMappingCollector.java | 2 +- .../spi/PojoEntityLoadingBindingContext.java | 28 ++++ .../pojo/loading/impl/PojoLoadingPlan.java | 2 +- .../impl/PojoMultiLoaderLoadingPlan.java | 2 +- .../impl/PojoSingleLoaderLoadingPlan.java | 4 +- .../spi/PojoLoadingSessionContext.java} | 8 +- .../loading/spi/PojoLoadingTypeContext.java | 17 ++ .../spi/PojoLoadingTypeContextProvider.java} | 7 +- .../spi/PojoMassEntityLoadingContext.java} | 13 +- .../spi/PojoMassIdentifierLoadingContext.java | 31 ++++ .../loading/spi/PojoMassLoadingContext.java | 19 +++ .../loading/spi/PojoMassLoadingStrategy.java | 59 +++++++ .../spi/PojoSelectionEntityLoader.java | 2 +- .../spi/PojoSelectionLoadingContext.java | 27 +--- .../spi/PojoSelectionLoadingStrategy.java | 7 +- .../search/mapper/pojo/logging/impl/Log.java | 23 +++ .../mapping/building/impl/PojoMapper.java | 20 ++- .../spi/PojoTypeExtendedMappingCollector.java | 14 ++ .../mapping/impl/AbstractPojoTypeManager.java | 104 +++++++++++- .../impl/PojoContainedTypeManager.java | 4 +- .../mapping/impl/PojoIndexedTypeManager.java | 16 +- .../mapping/impl/PojoMappingDelegateImpl.java | 14 +- .../impl/PojoTypeManagerContainer.java | 30 +++- .../spi/AbstractPojoMappingImplementor.java | 9 +- .../pojo/mapping/spi/PojoMappingDelegate.java | 6 + .../impl/PojoDefaultMassIndexer.java | 11 +- .../PojoMassIndexingBatchCoordinator.java | 6 +- ...ojoMassIndexingBatchIndexingWorkspace.java | 20 ++- ...dexingEntityIdentifierLoadingRunnable.java | 26 +-- ...PojoMassIndexingEntityLoadingRunnable.java | 26 +-- .../PojoMassIndexingIndexedTypeContext.java | 8 +- .../PojoMassIndexingIndexedTypeGroup.java | 80 ++++++---- .../spi/PojoMassIndexingContext.java | 11 +- .../spi/PojoMassIndexingContextBuilder.java | 27 ---- ...oMassIndexingIdentifierLoadingContext.java | 36 ----- .../spi/PojoMassIndexingLoadingStrategy.java | 47 ------ ...joEntityTypeAdditionalMetadataBuilder.java | 9 +- ...tionalMetadataCollectorEntityTypeNode.java | 7 + .../PojoEntityTypeAdditionalMetadata.java | 9 +- .../PojoSearchLoadingIndexedTypeContext.java | 2 - .../pojo/work/impl/PojoWorkTypeContext.java | 2 - .../loading/impl/LoadingTypeContext.java | 25 --- .../impl/LoadingTypeContextProvider.java | 19 --- .../impl/StandalonePojoLoadingContext.java | 88 +---------- .../impl/StandalonePojoLoadingTypeGroup.java | 28 ++-- .../StandalonePojoMassLoadingStrategy.java | 82 ++++++++++ ...onePojoSelectionLoadingContextBuilder.java | 4 +- ...tandalonePojoSelectionLoadingStrategy.java | 52 ++++++ .../pojo/standalone/logging/impl/Log.java | 4 - .../AbstractStandalonePojoTypeContext.java | 50 +++--- .../StandalonePojoContainedTypeContext.java | 5 +- .../StandalonePojoEntityTypeContributor.java | 34 ---- .../StandalonePojoEntityTypeMetadata.java | 68 ++++++++ .../StandalonePojoIndexedTypeContext.java | 16 +- .../impl/StandalonePojoMapperDelegate.java | 10 +- .../mapping/impl/StandalonePojoMapping.java | 15 +- .../impl/StandalonePojoMappingInitiator.java | 25 +-- ...alonePojoTypeConfigurationContributor.java | 19 +-- .../StandalonePojoTypeContextContainer.java | 21 +-- .../mapping/metadata/EntityConfigurer.java | 2 +- .../StandalonePojoEntityTypeMetadata.java | 49 ------ ...ndalonePojoEntityTypeMetadataProvider.java | 149 ------------------ ...dalonePojoMassIndexingLoadingStrategy.java | 84 ---------- .../scope/impl/SearchScopeImpl.java | 4 +- ...StandalonePojoScopeIndexedTypeContext.java | 23 --- ...ePojoSearchSessionTypeContextProvider.java | 3 +- .../impl/SearchIndexingPlanTypeContext.java | 6 +- 103 files changed, 1214 insertions(+), 1364 deletions(-) rename mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/{HibernateOrmMassLoadingOptions.java => HibernateOrmMassLoadingContext.java} (51%) create mode 100644 mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmEntityLoadingBinder.java delete mode 100644 mapper/orm/src/main/java/org/hibernate/search/mapper/orm/scope/impl/HibernateOrmScopeIndexedTypeContext.java create mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/definition/spi/PojoEntityLoadingBindingContext.java rename mapper/{orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingIndexedTypeContext.java => pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingSessionContext.java} (52%) rename mapper/{orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/LoadingIndexedTypeContextProvider.java => pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingTypeContextProvider.java} (55%) rename mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/{massindexing/spi/PojoMassIndexingEntityLoadingContext.java => loading/spi/PojoMassEntityLoadingContext.java} (55%) create mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassIdentifierLoadingContext.java create mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassLoadingContext.java create mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassLoadingStrategy.java delete mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingContextBuilder.java delete mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingIdentifierLoadingContext.java delete mode 100644 mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingLoadingStrategy.java delete mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/LoadingTypeContext.java delete mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/LoadingTypeContextProvider.java create mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoMassLoadingStrategy.java create mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoSelectionLoadingStrategy.java delete mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoEntityTypeContributor.java create mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoEntityTypeMetadata.java delete mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/impl/StandalonePojoEntityTypeMetadata.java delete mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/impl/StandalonePojoEntityTypeMetadataProvider.java delete mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/impl/StandalonePojoMassIndexingLoadingStrategy.java delete mode 100644 mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/scope/impl/StandalonePojoScopeIndexedTypeContext.java diff --git a/engine/src/main/java/org/hibernate/search/engine/common/impl/MappingFinalizationContextImpl.java b/engine/src/main/java/org/hibernate/search/engine/common/impl/MappingFinalizationContextImpl.java index 86e8e141cbf..18229b8a5a6 100644 --- a/engine/src/main/java/org/hibernate/search/engine/common/impl/MappingFinalizationContextImpl.java +++ b/engine/src/main/java/org/hibernate/search/engine/common/impl/MappingFinalizationContextImpl.java @@ -9,17 +9,26 @@ import org.hibernate.search.engine.cfg.ConfigurationPropertySource; import org.hibernate.search.engine.environment.bean.BeanResolver; import org.hibernate.search.engine.mapper.mapping.building.spi.MappingFinalizationContext; +import org.hibernate.search.engine.reporting.spi.ContextualFailureCollector; class MappingFinalizationContextImpl implements MappingFinalizationContext { + private final ContextualFailureCollector failureCollector; private final ConfigurationPropertySource propertySource; private final BeanResolver beanResolver; - MappingFinalizationContextImpl(ConfigurationPropertySource propertySource, BeanResolver beanResolver) { + MappingFinalizationContextImpl(ContextualFailureCollector failureCollector, + ConfigurationPropertySource propertySource, BeanResolver beanResolver) { + this.failureCollector = failureCollector; this.propertySource = propertySource; this.beanResolver = beanResolver; } + @Override + public ContextualFailureCollector failureCollector() { + return failureCollector; + } + @Override public ConfigurationPropertySource configurationPropertySource() { return propertySource; diff --git a/engine/src/main/java/org/hibernate/search/engine/common/impl/SearchIntegrationBuilder.java b/engine/src/main/java/org/hibernate/search/engine/common/impl/SearchIntegrationBuilder.java index 04c75928531..d5bbcd2b11b 100644 --- a/engine/src/main/java/org/hibernate/search/engine/common/impl/SearchIntegrationBuilder.java +++ b/engine/src/main/java/org/hibernate/search/engine/common/impl/SearchIntegrationBuilder.java @@ -43,7 +43,6 @@ import org.hibernate.search.engine.reporting.FailureHandler; import org.hibernate.search.engine.reporting.impl.EngineEventContextMessages; import org.hibernate.search.engine.reporting.impl.FailSafeFailureHandlerWrapper; -import org.hibernate.search.engine.reporting.spi.ContextualFailureCollector; import org.hibernate.search.engine.reporting.spi.RootFailureCollector; import org.hibernate.search.util.common.AssertionFailure; import org.hibernate.search.util.common.SearchException; @@ -289,7 +288,7 @@ void partiallyBuildAndAddTo(Map, MappingPartialBuildState> mapp mappings.put( mappingKey, partiallyBuiltMapping ); } catch (MappingAbortedException e) { - handleMappingAborted( e ); + e.collectSilentlyAndCheck( buildContext.failureCollector() ); } } @@ -299,33 +298,6 @@ public void closeOnFailure() { } } - private void handleMappingAborted(MappingAbortedException e) { - ContextualFailureCollector failureCollector = buildContext.failureCollector(); - - if ( !failureCollector.hasFailure() ) { - throw new AssertionFailure( - "Caught " + MappingAbortedException.class.getSimpleName() - + ", but the mapper did not collect any failure.", - e - ); - } - - /* - * This generally shouldn't do anything, because we don't expect a cause nor suppressed exceptions - * in the MappingAbortedException, but ignoring exceptions can lead to - * spending some really annoying hours debugging. - * So let's be extra cautious not to lose these. - */ - Throwable cause = e.getCause(); - if ( cause != null ) { - failureCollector.add( cause ); - } - Throwable[] suppressed = e.getSuppressed(); - for ( Throwable throwable : suppressed ) { - failureCollector.add( throwable ); - } - } - private class MappingConfigurationCollectorImpl implements MappingConfigurationCollector { private final TypeMetadataContributorProvider.Builder builder; diff --git a/engine/src/main/java/org/hibernate/search/engine/common/impl/SearchIntegrationPartialBuildStateImpl.java b/engine/src/main/java/org/hibernate/search/engine/common/impl/SearchIntegrationPartialBuildStateImpl.java index ce73d3b847c..39cb4875d98 100644 --- a/engine/src/main/java/org/hibernate/search/engine/common/impl/SearchIntegrationPartialBuildStateImpl.java +++ b/engine/src/main/java/org/hibernate/search/engine/common/impl/SearchIntegrationPartialBuildStateImpl.java @@ -29,6 +29,7 @@ import org.hibernate.search.engine.environment.bean.BeanResolver; import org.hibernate.search.engine.environment.bean.spi.BeanProvider; import org.hibernate.search.engine.environment.thread.impl.ThreadPoolProviderImpl; +import org.hibernate.search.engine.mapper.mapping.building.spi.MappingAbortedException; import org.hibernate.search.engine.mapper.mapping.building.spi.MappingFinalizationContext; import org.hibernate.search.engine.mapper.mapping.building.spi.MappingFinalizer; import org.hibernate.search.engine.mapper.mapping.building.spi.MappingKey; @@ -36,6 +37,7 @@ import org.hibernate.search.engine.mapper.mapping.spi.MappingImplementor; import org.hibernate.search.engine.reporting.FailureHandler; import org.hibernate.search.engine.reporting.impl.EngineEventContextMessages; +import org.hibernate.search.engine.reporting.spi.ContextualFailureCollector; import org.hibernate.search.engine.reporting.spi.RootFailureCollector; import org.hibernate.search.util.common.AssertionFailure; import org.hibernate.search.util.common.impl.Closer; @@ -125,6 +127,8 @@ public SearchIntegrationFinalizer finalizer(ConfigurationPropertySource property private class SearchIntegrationFinalizerImpl implements SearchIntegrationFinalizer { + private final RootFailureCollector failureCollector = + new RootFailureCollector( EngineEventContextMessages.INSTANCE.bootstrap() ); private final ConfigurationPropertySource propertySource; private final ConfigurationPropertyChecker propertyChecker; @@ -146,10 +150,22 @@ public M finalizeMapping(MappingKey mappingKey, ); } + ContextualFailureCollector mappingFailureCollector = failureCollector.withContext( mappingKey ); MappingFinalizationContext mappingFinalizationContext = - new MappingFinalizationContextImpl( propertySource, beanResolver ); + new MappingFinalizationContextImpl( mappingFailureCollector, propertySource, beanResolver ); + + MappingImplementor mapping = null; + try { + mapping = finalizer.finalizeMapping( mappingFinalizationContext, partiallyBuiltMapping ); + } + catch (RuntimeException e) { + mappingFailureCollector.add( e ); + } + catch (MappingAbortedException e) { + e.collectSilentlyAndCheck( mappingFailureCollector ); + } + failureCollector.checkNoFailure(); - MappingImplementor mapping = finalizer.finalizeMapping( mappingFinalizationContext, partiallyBuiltMapping ); fullyBuiltNonStartedMappings.put( mappingKey, new MappingNonStartedState( mappingKey, mapping ) ); partiallyBuiltMappings.remove( mappingKey ); @@ -158,15 +174,14 @@ public M finalizeMapping(MappingKey mappingKey, @Override public SearchIntegration finalizeIntegration() { + failureCollector.checkNoFailure(); + if ( !partiallyBuiltMappings.isEmpty() ) { throw new AssertionFailure( "Some mappings were not fully built. Partially built mappings: " + partiallyBuiltMappings ); } - RootFailureCollector failureCollector = - new RootFailureCollector( EngineEventContextMessages.INSTANCE.bootstrap() ); - // Start backends for ( Map.Entry entry : nonStartedBackends.entrySet() ) { startedBackends.put( diff --git a/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/Mapper.java b/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/Mapper.java index 3cda3c19a77..8059e112298 100644 --- a/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/Mapper.java +++ b/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/Mapper.java @@ -6,8 +6,6 @@ */ package org.hibernate.search.engine.mapper.mapping.building.spi; -import org.hibernate.search.engine.reporting.spi.ContextualFailureCollector; - /** * @param The Java type of the partial build state of the produced mapping. */ @@ -48,8 +46,7 @@ public interface Mapper { * Called exactly once just after {@link #mapTypes(MappedIndexManagerFactory)}. * * @return The partially-built mapping. - * @throws MappingAbortedException When aborting the mapping due to - * {@link ContextualFailureCollector#add(Throwable) collected} failures. + * @throws MappingAbortedException If something went wrong when preparing the mapping. */ MPBS prepareBuild() throws MappingAbortedException; diff --git a/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingAbortedException.java b/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingAbortedException.java index aa44afb9bc3..bfc01b2a473 100644 --- a/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingAbortedException.java +++ b/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingAbortedException.java @@ -7,6 +7,7 @@ package org.hibernate.search.engine.mapper.mapping.building.spi; import org.hibernate.search.engine.reporting.spi.ContextualFailureCollector; +import org.hibernate.search.util.common.AssertionFailure; /** * An exception thrown by {@link Mapper#prepareBuild()} when detecting that failures were @@ -15,4 +16,34 @@ * which would make the failure report unclear. */ public class MappingAbortedException extends Exception { + /** + * Collects the cause/suppressed of this exception, if any, in the failure collector, + * and throws an exception if there is nothing to explain the abortion + * (neither in the failure collector or in this exceptions' cause/suppressed). + * @param failureCollector A failure collector for the mapping that was just aborted. + */ + public void collectSilentlyAndCheck(ContextualFailureCollector failureCollector) { + /* + * This generally shouldn't do anything, because we don't expect a cause nor suppressed exceptions + * in the MappingAbortedException, but ignoring exceptions can lead to + * spending some really annoying hours debugging. + * So let's be extra cautious not to lose these. + */ + Throwable cause = getCause(); + if ( cause != null ) { + failureCollector.add( cause ); + } + Throwable[] suppressed = getSuppressed(); + for ( Throwable throwable : suppressed ) { + failureCollector.add( throwable ); + } + + if ( !failureCollector.hasFailure() ) { + throw new AssertionFailure( + "Caught " + MappingAbortedException.class.getSimpleName() + + ", but the mapper did not collect any failure.", + this + ); + } + } } diff --git a/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingFinalizationContext.java b/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingFinalizationContext.java index 97629dd1f1c..4d21c7b3cb6 100644 --- a/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingFinalizationContext.java +++ b/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingFinalizationContext.java @@ -8,12 +8,15 @@ import org.hibernate.search.engine.cfg.ConfigurationPropertySource; import org.hibernate.search.engine.environment.bean.BeanResolver; +import org.hibernate.search.engine.reporting.spi.ContextualFailureCollector; /** * The context passed to the mapper during the very last step of bootstrap. */ public interface MappingFinalizationContext { + ContextualFailureCollector failureCollector(); + ConfigurationPropertySource configurationPropertySource(); BeanResolver beanResolver(); diff --git a/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingFinalizer.java b/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingFinalizer.java index 4d75323a16b..6fdaf3e2256 100644 --- a/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingFinalizer.java +++ b/engine/src/main/java/org/hibernate/search/engine/mapper/mapping/building/spi/MappingFinalizer.java @@ -22,7 +22,10 @@ public interface MappingFinalizer { * @param context The context, including configuration properties. * @param partiallyBuiltMapping The partially built mapping. * @return The fully-built mapping. + * @throws RuntimeException If something went wrong when finalizing the mapping. + * @throws MappingAbortedException If something went wrong when finalizing the mapping. */ - MappingImplementor finalizeMapping(MappingFinalizationContext context, PBM partiallyBuiltMapping); + MappingImplementor finalizeMapping(MappingFinalizationContext context, PBM partiallyBuiltMapping) + throws MappingAbortedException; } diff --git a/mapper/orm-jakarta-batch/core/src/main/java/org/hibernate/search/jakarta/batch/core/massindexing/util/impl/EntityTypeDescriptor.java b/mapper/orm-jakarta-batch/core/src/main/java/org/hibernate/search/jakarta/batch/core/massindexing/util/impl/EntityTypeDescriptor.java index 5c306ac0f10..38fafca888e 100644 --- a/mapper/orm-jakarta-batch/core/src/main/java/org/hibernate/search/jakarta/batch/core/massindexing/util/impl/EntityTypeDescriptor.java +++ b/mapper/orm-jakarta-batch/core/src/main/java/org/hibernate/search/jakarta/batch/core/massindexing/util/impl/EntityTypeDescriptor.java @@ -7,6 +7,7 @@ package org.hibernate.search.jakarta.batch.core.massindexing.util.impl; import java.util.List; +import java.util.Set; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; @@ -79,7 +80,7 @@ public SelectionQuery createLoadingQuery(SessionImplementor session, } private HibernateOrmQueryLoader queryLoader(List conditions, String order) { - return loadingStrategy.createQueryLoader( sessionFactory, List.of( delegate ), conditions, order ); + return loadingStrategy.createQueryLoader( sessionFactory, Set.of( delegate.delegate() ), conditions, order ); } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/AbstractHibernateOrmLoadingStrategy.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/AbstractHibernateOrmLoadingStrategy.java index 0b064b0741c..14e856739fa 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/AbstractHibernateOrmLoadingStrategy.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/AbstractHibernateOrmLoadingStrategy.java @@ -11,14 +11,27 @@ import java.util.List; import java.util.Set; +import org.hibernate.FlushMode; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.search.mapper.orm.common.impl.HibernateOrmUtils; import org.hibernate.search.mapper.orm.loading.spi.ConditionalExpression; import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmEntityLoadingStrategy; import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmQueryLoader; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntitySink; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierSink; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionEntityLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingContext; import org.hibernate.search.util.common.AssertionFailure; +import org.hibernate.search.util.common.impl.SuppressingCloser; public abstract class AbstractHibernateOrmLoadingStrategy implements HibernateOrmEntityLoadingStrategy { @@ -31,16 +44,96 @@ public abstract class AbstractHibernateOrmLoadingStrategy this.queryFactory = queryFactory; } + @Override + public final PojoSelectionEntityLoader createEntityLoader( + Set> expectedTypes, + PojoSelectionLoadingContext context) { + var ormContext = (HibernateOrmSelectionLoadingContext) context; + return createEntityLoader( expectedTypes, ormContext ); + } + + public abstract PojoSelectionEntityLoader createEntityLoader( + Set> targetEntityTypeContexts, + HibernateOrmSelectionLoadingContext loadingContext); + + @Override + public final boolean groupingAllowed(PojoLoadingTypeContext type, PojoMassLoadingContext context) { + // Only allow grouping for types that don't have a conditional expression: + // it's too complicated to apply a condition to multiple types in the same query. + // TODO HSEARCH-4252 Apply a condition to multiple types in the same query + return ( (HibernateOrmMassLoadingContext) context ).conditionalExpression( type ).isEmpty(); + } + + @Override + public final PojoMassIdentifierLoader createIdentifierLoader( + Set> expectedTypes, + PojoMassIdentifierLoadingContext context) { + var ormContext = (HibernateOrmMassLoadingContext) context.parent(); + SessionFactoryImplementor sessionFactory = ormContext.mapping().sessionFactory(); + + HibernateOrmQueryLoader queryLoader = createQueryLoader( sessionFactory, expectedTypes, + conditionalExpressions( expectedTypes, ormContext ) ); + SharedSessionContractImplementor session = (SharedSessionContractImplementor) sessionFactory + .withStatelessOptions() + .tenantIdentifier( (Object) context.tenantIdentifier() ) + .openStatelessSession(); + try { + PojoMassIdentifierSink sink = context.createSink(); + return new HibernateOrmMassIdentifierLoader<>( queryLoader, ormContext, sink, session ); + } + catch (RuntimeException e) { + new SuppressingCloser( e ).push( SharedSessionContractImplementor::close, session ); + throw e; + } + } + + @Override + public final PojoMassEntityLoader createEntityLoader(Set> expectedTypes, + PojoMassEntityLoadingContext context) { + var ormContext = (HibernateOrmMassLoadingContext) context.parent(); + SessionFactoryImplementor sessionFactory = ormContext.mapping().sessionFactory(); + + HibernateOrmQueryLoader queryLoader = createQueryLoader( sessionFactory, expectedTypes, + conditionalExpressions( expectedTypes, ormContext ) ); + SessionImplementor session = (SessionImplementor) sessionFactory + .withOptions() + .tenantIdentifier( (Object) context.tenantIdentifier() ) + .openSession(); + try { + session.setHibernateFlushMode( FlushMode.MANUAL ); + session.setCacheMode( ormContext.cacheMode() ); + session.setDefaultReadOnly( true ); + + PojoMassEntitySink sink = context.createSink( ormContext.mapping().sessionContext( session ) ); + return new HibernateOrmMassEntityLoader<>( queryLoader, ormContext, sink, session ); + } + catch (RuntimeException e) { + new SuppressingCloser( e ).push( SessionImplementor::close, session ); + throw e; + } + } + + private List conditionalExpressions(Set> expectedTypes, + HibernateOrmMassLoadingContext context) { + if ( expectedTypes.size() != 1 ) { + // We know there's no condition, see groupingAllowed() + // TODO HSEARCH-4252 Apply a condition to multiple types in the same query + return List.of(); + } + var condition = context.conditionalExpression( expectedTypes.iterator().next() ); + return condition.isPresent() ? List.of( condition.get() ) : List.of(); + } + @Override public HibernateOrmQueryLoader createQueryLoader(SessionFactoryImplementor sessionFactory, - List> typeContexts, + Set> typeContexts, List conditionalExpressions) { return createQueryLoader( sessionFactory, typeContexts, conditionalExpressions, null ); } @Override public HibernateOrmQueryLoader createQueryLoader(SessionFactoryImplementor sessionFactory, - List> typeContexts, + Set> typeContexts, List conditionalExpressions, String order) { var rootEntityMappingType = HibernateOrmUtils.entityMappingType( sessionFactory, rootEntityName ); Set> includedTypesFilter; @@ -50,17 +143,19 @@ public HibernateOrmQueryLoader createQueryLoader(SessionFactoryImplementor } else { includedTypesFilter = new HashSet<>( typeContexts.size() ); - for ( LoadingTypeContext typeContext : typeContexts ) { + for ( PojoLoadingTypeContext typeContext : typeContexts ) { includedTypesFilter.add( typeContext.typeIdentifier().javaClass() ); } } if ( !conditionalExpressions.isEmpty() || order != null ) { if ( typeContexts.size() != 1 ) { + // TODO HSEARCH-4252 Apply a condition to multiple types in the same query throw new AssertionFailure( "conditional/order expression is always defined on a single type" ); } - EntityMappingType entityMappingType = typeContexts.get( 0 ).entityMappingType(); + EntityMappingType entityMappingType = HibernateOrmUtils.entityMappingType( sessionFactory, + typeContexts.iterator().next().secondaryEntityName() ); return new HibernateOrmQueryLoaderImpl<>( queryFactory, entityMappingType, includedTypesFilter, conditionalExpressions, order ); } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmEntityIdEntityLoadingStrategy.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmEntityIdEntityLoadingStrategy.java index 90c0ced0431..c97935d4452 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmEntityIdEntityLoadingStrategy.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmEntityIdEntityLoadingStrategy.java @@ -10,15 +10,16 @@ import java.util.stream.Collectors; import org.hibernate.AssertionFailure; +import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.RootClass; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.search.mapper.orm.common.impl.HibernateOrmUtils; import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmEntityLoadingStrategy; import org.hibernate.search.mapper.orm.loading.spi.LoadingSessionContext; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; import org.hibernate.search.mapper.orm.loading.spi.MutableEntityLoadingOptions; import org.hibernate.search.mapper.orm.search.loading.EntityLoadingCacheLookupStrategy; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionEntityLoader; public class HibernateOrmEntityIdEntityLoadingStrategy @@ -65,25 +66,11 @@ public int hashCode() { } @Override - public PojoSelectionEntityLoader createLoader(Set> targetEntityTypeContexts, - LoadingSessionContext sessionContext, EntityLoadingCacheLookupStrategy cacheLookupStrategy, - MutableEntityLoadingOptions loadingOptions) { - if ( targetEntityTypeContexts.size() == 1 ) { - LoadingTypeContext targetEntityTypeContext = - targetEntityTypeContexts.iterator().next(); - /* - * This cast is safe: the loader will only return instances of E2. - * See PojoLoader.castToExactTypeOrNull() and its callers for more information, - * in particular runtime checks handling edge cases. - */ - @SuppressWarnings("unchecked") - PojoSelectionEntityLoader result = - (PojoSelectionEntityLoader) doCreate( targetEntityTypeContext.entityMappingType(), sessionContext, - cacheLookupStrategy, loadingOptions ); - return result; - } - - EntityMappingType commonSuperType = toMostSpecificCommonEntitySuperType( targetEntityTypeContexts ); + public PojoSelectionEntityLoader createEntityLoader( + Set> targetEntityTypeContexts, + HibernateOrmSelectionLoadingContext loadingContext) { + var sessionFactory = loadingContext.sessionImplementor().getSessionFactory(); + EntityMappingType commonSuperType = toMostSpecificCommonEntitySuperType( sessionFactory, targetEntityTypeContexts ); if ( commonSuperType == null ) { throw invalidTypesException( targetEntityTypeContexts ); } @@ -100,9 +87,9 @@ public PojoSelectionEntityLoader createLoader(Set result = - (PojoSelectionEntityLoader) doCreate( commonSuperType, sessionContext, cacheLookupStrategy, - loadingOptions ); + PojoSelectionEntityLoader result = + (PojoSelectionEntityLoader) doCreate( commonSuperType, loadingContext.sessionContext(), + loadingContext.cacheLookupStrategy(), loadingContext.loadingOptions() ); return result; } @@ -159,10 +146,12 @@ private PojoSelectionEntityLoader doCreate(EntityMappingType entityMappingTyp } private static EntityMappingType toMostSpecificCommonEntitySuperType( - Iterable> targetEntityTypeContexts) { + SessionFactoryImplementor sessionFactory, + Iterable> targetEntityTypeContexts) { EntityMappingType result = null; - for ( LoadingTypeContext targetTypeContext : targetEntityTypeContexts ) { - EntityMappingType type = targetTypeContext.entityMappingType(); + for ( PojoLoadingTypeContext targetTypeContext : targetEntityTypeContexts ) { + EntityMappingType type = HibernateOrmUtils.entityMappingType( sessionFactory, + targetTypeContext.secondaryEntityName() ); if ( result == null ) { result = type; } @@ -182,15 +171,14 @@ private AssertionFailure invalidTypeException(EntityMappingType otherEntityMappi } private AssertionFailure invalidTypesException( - Set> targetEntityTypeContexts) { + Set> targetEntityTypeContexts) { return new AssertionFailure( "Some types among the targeted entity types are not subclasses of the expected root entity type." + " Expected entity name: " + rootEntityName + " Targeted entity names: " + targetEntityTypeContexts.stream() - .map( LoadingTypeContext::entityMappingType ) - .map( EntityMappingType::getEntityName ) - .collect( Collectors.toList() ) + .map( PojoLoadingTypeContext::secondaryEntityName ) + .collect( Collectors.toUnmodifiableList() ) ); } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassEntityLoader.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassEntityLoader.java index eb8b004eb9e..a122c8d4ebd 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassEntityLoader.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassEntityLoader.java @@ -21,13 +21,13 @@ public final class HibernateOrmMassEntityLoader implements PojoMassEntityL private static final String ID_PARAMETER_NAME = "ids"; private final HibernateOrmQueryLoader typeQueryLoader; - private final HibernateOrmMassLoadingOptions options; + private final HibernateOrmMassLoadingContext options; private final PojoMassEntitySink sink; private final SessionImplementor session; private final TransactionHelper transactionHelper; public HibernateOrmMassEntityLoader(HibernateOrmQueryLoader typeGroupLoader, - HibernateOrmMassLoadingOptions options, + HibernateOrmMassLoadingContext options, PojoMassEntitySink sink, SessionImplementor session) { this.typeQueryLoader = typeGroupLoader; diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassIdentifierLoader.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassIdentifierLoader.java index 5234e6cf934..ee39b48e1ea 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassIdentifierLoader.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassIdentifierLoader.java @@ -24,7 +24,7 @@ public final class HibernateOrmMassIdentifierLoader implements PojoMassIde private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); - private final HibernateOrmMassLoadingOptions options; + private final HibernateOrmMassLoadingContext options; private final PojoMassIdentifierSink sink; private final SharedSessionContractImplementor session; private final TransactionHelper transactionHelper; @@ -33,7 +33,7 @@ public final class HibernateOrmMassIdentifierLoader implements PojoMassIde private final ScrollableResults results; public HibernateOrmMassIdentifierLoader(HibernateOrmQueryLoader typeQueryLoader, - HibernateOrmMassLoadingOptions options, + HibernateOrmMassLoadingContext options, PojoMassIdentifierSink sink, SharedSessionContractImplementor session) { this.options = options; diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassLoadingOptions.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassLoadingContext.java similarity index 51% rename from mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassLoadingOptions.java rename to mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassLoadingContext.java index df9701d7ba6..f52661f00b9 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassLoadingOptions.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmMassLoadingContext.java @@ -6,9 +6,17 @@ */ package org.hibernate.search.mapper.orm.loading.impl; +import java.util.Optional; + import org.hibernate.CacheMode; +import org.hibernate.search.mapper.orm.loading.spi.ConditionalExpression; +import org.hibernate.search.mapper.orm.loading.spi.LoadingMappingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; +import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; + +public interface HibernateOrmMassLoadingContext extends PojoMassIndexingContext { -public interface HibernateOrmMassLoadingOptions { + LoadingMappingContext mapping(); /** * @return the transaction timeout @@ -35,4 +43,10 @@ public interface HibernateOrmMassLoadingOptions { */ int idFetchSize(); + /** + * @return The conditional expression to apply when loading the given type, + * inherited from supertypes by default, + * or {@link Optional#empty()} if there is no condition to apply. + */ + Optional conditionalExpression(PojoLoadingTypeContext typeContext); } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmNonEntityIdPropertyEntityLoadingStrategy.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmNonEntityIdPropertyEntityLoadingStrategy.java index 81fbc51e854..2bdfa727ff6 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmNonEntityIdPropertyEntityLoadingStrategy.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmNonEntityIdPropertyEntityLoadingStrategy.java @@ -12,15 +12,14 @@ import java.util.stream.Collectors; import org.hibernate.mapping.PersistentClass; -import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.search.mapper.orm.common.impl.HibernateOrmUtils; import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmEntityLoadingStrategy; import org.hibernate.search.mapper.orm.loading.spi.LoadingSessionContext; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; import org.hibernate.search.mapper.orm.loading.spi.MutableEntityLoadingOptions; import org.hibernate.search.mapper.orm.logging.impl.Log; import org.hibernate.search.mapper.orm.model.impl.DocumentIdSourceProperty; import org.hibernate.search.mapper.orm.search.loading.EntityLoadingCacheLookupStrategy; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionEntityLoader; import org.hibernate.search.util.common.AssertionFailure; import org.hibernate.search.util.common.logging.impl.LoggerFactory; @@ -75,7 +74,7 @@ public boolean equals(Object obj) { HibernateOrmNonEntityIdPropertyEntityLoadingStrategy other = (HibernateOrmNonEntityIdPropertyEntityLoadingStrategy) obj; // If the entity type or document ID property is different, - // the factories work in separate ID spaces and should be used separately. + // the factories may be working with separate ID spaces and should be used separately. return entityName.equals( other.entityName ) && documentIdSourcePropertyName.equals( other.documentIdSourcePropertyName ) && documentIdSourceHandle.equals( other.documentIdSourceHandle ); @@ -87,32 +86,37 @@ public int hashCode() { } @Override - public PojoSelectionEntityLoader createLoader(Set> targetEntityTypeContexts, - LoadingSessionContext sessionContext, - EntityLoadingCacheLookupStrategy cacheLookupStrategy, MutableEntityLoadingOptions loadingOptions) { + public PojoSelectionEntityLoader createEntityLoader( + Set> targetEntityTypeContexts, + HibernateOrmSelectionLoadingContext loadingContext) { if ( targetEntityTypeContexts.size() != 1 ) { throw multipleTypesException( targetEntityTypeContexts ); } - return doCreate( targetEntityTypeContexts.iterator().next(), sessionContext, cacheLookupStrategy, loadingOptions ); + return doCreate( targetEntityTypeContexts.iterator().next(), loadingContext.sessionContext(), + loadingContext.cacheLookupStrategy(), loadingContext.loadingOptions() ); } - private PojoSelectionEntityLoader doCreate(LoadingTypeContext targetEntityTypeContext, + private PojoSelectionEntityLoader doCreate(PojoLoadingTypeContext targetEntityTypeContext, LoadingSessionContext sessionContext, EntityLoadingCacheLookupStrategy cacheLookupStrategy, MutableEntityLoadingOptions loadingOptions) { - if ( !entityName.equals( targetEntityTypeContext.entityMappingType().getEntityName() ) ) { - throw invalidTypeException( targetEntityTypeContext.entityMappingType() ); + if ( !entityName.equals( targetEntityTypeContext.secondaryEntityName() ) ) { + throw invalidTypeException( targetEntityTypeContext ); } + var sessionFactory = sessionContext.session().getSessionFactory(); + var entityMapping = HibernateOrmUtils.entityMappingType( sessionFactory, + targetEntityTypeContext.secondaryEntityName() ); + /* * We checked just above that "entityMappingType" is equal to "targetEntityTypeContext.entityMappingType()", - * so this loader will actually return entities of type E2. + * so this loader will actually return entities of type E. */ @SuppressWarnings("unchecked") - PojoSelectionEntityLoader result = new HibernateOrmSelectionEntityByNonIdPropertyLoader<>( - targetEntityTypeContext.entityMappingType(), (LoadingTypeContext) targetEntityTypeContext, - (TypeQueryFactory) queryFactory, + PojoSelectionEntityLoader result = new HibernateOrmSelectionEntityByNonIdPropertyLoader<>( + entityMapping, (PojoLoadingTypeContext) targetEntityTypeContext, + queryFactory, documentIdSourcePropertyName, documentIdSourceHandle, sessionContext, loadingOptions ); @@ -126,30 +130,29 @@ private PojoSelectionEntityLoader doCreate(LoadingTypeContext target * Let's log something, at least. */ log.skippingPreliminaryCacheLookupsForNonEntityIdEntityLoader( - targetEntityTypeContext.jpaEntityName(), cacheLookupStrategy + targetEntityTypeContext.entityName(), cacheLookupStrategy ); } return result; } - private AssertionFailure invalidTypeException(EntityMappingType otherEntityMappingType) { + private AssertionFailure invalidTypeException(PojoLoadingTypeContext otherType) { throw new AssertionFailure( "Attempt to use a criteria-based entity loader with an unexpected target entity type." + " Expected entity name: " + entityName - + " Targeted entity name: " + otherEntityMappingType.getEntityName() + + " Targeted entity name: " + otherType.secondaryEntityName() ); } - private AssertionFailure multipleTypesException(Set> targetEntityTypeContexts) { + private AssertionFailure multipleTypesException(Set> targetEntityTypeContexts) { return new AssertionFailure( "Attempt to use a criteria-based entity loader with multiple target entity types." + " Expected entity name: " + entityName + " Targeted entity names: " + targetEntityTypeContexts.stream() - .map( LoadingTypeContext::entityMappingType ) - .map( EntityMappingType::getEntityName ) - .collect( Collectors.toList() ) + .map( PojoLoadingTypeContext::secondaryEntityName ) + .collect( Collectors.toUnmodifiableList() ) ); } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmSelectionEntityByNonIdPropertyLoader.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmSelectionEntityByNonIdPropertyLoader.java index 81e6f978f52..be5d484a759 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmSelectionEntityByNonIdPropertyLoader.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmSelectionEntityByNonIdPropertyLoader.java @@ -15,9 +15,9 @@ import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.query.Query; import org.hibernate.search.mapper.orm.loading.spi.LoadingSessionContext; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; import org.hibernate.search.mapper.orm.loading.spi.MutableEntityLoadingOptions; import org.hibernate.search.mapper.orm.logging.impl.Log; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; import org.hibernate.search.util.common.impl.CollectionHelper; import org.hibernate.search.util.common.logging.impl.LoggerFactory; import org.hibernate.search.util.common.reflect.spi.ValueReadHandle; @@ -32,12 +32,12 @@ class HibernateOrmSelectionEntityByNonIdPropertyLoader extends AbstractHibern private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); - private final LoadingTypeContext targetEntityTypeContext; + private final PojoLoadingTypeContext targetEntityTypeContext; private final String documentIdSourcePropertyName; private final ValueReadHandle documentIdSourceHandle; HibernateOrmSelectionEntityByNonIdPropertyLoader(EntityMappingType entityMappingType, - LoadingTypeContext targetEntityTypeContext, + PojoLoadingTypeContext targetEntityTypeContext, TypeQueryFactory queryFactory, String documentIdSourcePropertyName, ValueReadHandle documentIdSourceHandle, @@ -84,7 +84,7 @@ private void addResults(Map resultMap, List loadedEntiti Object documentIdSourceValue = documentIdSourceHandle.get( unproxied ); Object previous = resultMap.put( documentIdSourceValue, loadedEntity ); if ( previous != null ) { - throw log.foundMultipleEntitiesForDocumentId( targetEntityTypeContext.jpaEntityName(), + throw log.foundMultipleEntitiesForDocumentId( targetEntityTypeContext.entityName(), documentIdSourcePropertyName, documentIdSourceValue ); } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmSelectionLoadingContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmSelectionLoadingContext.java index ce883373374..e1c37729f20 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmSelectionLoadingContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/HibernateOrmSelectionLoadingContext.java @@ -7,9 +7,6 @@ package org.hibernate.search.mapper.orm.loading.impl; import java.lang.invoke.MethodHandles; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; import jakarta.persistence.EntityGraph; @@ -17,19 +14,14 @@ import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.RootGraph; import org.hibernate.search.mapper.orm.loading.spi.EntityGraphHint; -import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmEntityLoadingStrategy; import org.hibernate.search.mapper.orm.loading.spi.LoadingMappingContext; import org.hibernate.search.mapper.orm.loading.spi.LoadingSessionContext; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; import org.hibernate.search.mapper.orm.loading.spi.MutableEntityLoadingOptions; import org.hibernate.search.mapper.orm.logging.impl.Log; import org.hibernate.search.mapper.orm.search.loading.EntityLoadingCacheLookupStrategy; import org.hibernate.search.mapper.orm.search.loading.dsl.SearchLoadingOptionsStep; -import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; -import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionEntityLoader; import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingContext; import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingContextBuilder; -import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingStrategy; import org.hibernate.search.mapper.pojo.model.spi.PojoRuntimeIntrospector; import org.hibernate.search.util.common.impl.Contracts; import org.hibernate.search.util.common.logging.impl.LoggerFactory; @@ -38,13 +30,11 @@ public final class HibernateOrmSelectionLoadingContext implements PojoSelectionL private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); - private final LoadingIndexedTypeContextProvider typeContextProvider; private final LoadingSessionContext sessionContext; private final MutableEntityLoadingOptions loadingOptions; private final EntityLoadingCacheLookupStrategy cacheLookupStrategy; private HibernateOrmSelectionLoadingContext(Builder builder) { - typeContextProvider = builder.typeContextProvider; sessionContext = builder.sessionContext; loadingOptions = builder.loadingOptions; cacheLookupStrategy = builder.cacheLookupStrategy; @@ -65,16 +55,8 @@ public PojoRuntimeIntrospector runtimeIntrospector() { return sessionContext.runtimeIntrospector(); } - @Override - public PojoSelectionLoadingStrategy loadingStrategy(PojoLoadingTypeContext type) { - return new HibernateOrmSelectionLoadingStrategy<>( - typeContextProvider.forExactType( type.typeIdentifier() ).loadingStrategy() ); - } - - @Override - public Optional> loadingStrategyOptional(PojoLoadingTypeContext type) { - // With the ORM mapper, all (indexed) types can be loaded. - return Optional.of( loadingStrategy( type ) ); + public LoadingSessionContext sessionContext() { + return sessionContext; } public SessionImplementor sessionImplementor() { @@ -85,16 +67,18 @@ public MutableEntityLoadingOptions loadingOptions() { return loadingOptions; } + public EntityLoadingCacheLookupStrategy cacheLookupStrategy() { + return cacheLookupStrategy; + } + public static final class Builder implements PojoSelectionLoadingContextBuilder, SearchLoadingOptionsStep { - private final LoadingIndexedTypeContextProvider typeContextProvider; private final LoadingSessionContext sessionContext; private final MutableEntityLoadingOptions loadingOptions; private EntityLoadingCacheLookupStrategy cacheLookupStrategy; - public Builder(LoadingMappingContext mappingContext, LoadingIndexedTypeContextProvider typeContextProvider, + public Builder(LoadingMappingContext mappingContext, LoadingSessionContext sessionContext) { - this.typeContextProvider = typeContextProvider; this.sessionContext = sessionContext; this.loadingOptions = new MutableEntityLoadingOptions( mappingContext ); this.cacheLookupStrategy = mappingContext.cacheLookupStrategy(); @@ -134,43 +118,4 @@ public PojoSelectionLoadingContext build() { return new HibernateOrmSelectionLoadingContext( this ); } } - - private class HibernateOrmSelectionLoadingStrategy implements PojoSelectionLoadingStrategy { - - private final HibernateOrmEntityLoadingStrategy delegate; - - public HibernateOrmSelectionLoadingStrategy(HibernateOrmEntityLoadingStrategy delegate) { - this.delegate = delegate; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - HibernateOrmSelectionLoadingStrategy that = (HibernateOrmSelectionLoadingStrategy) o; - return delegate.equals( that.delegate ); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public PojoSelectionEntityLoader createLoader( - Set> expectedTypes) { - Set> typeContexts = new HashSet<>(); - for ( PojoLoadingTypeContext type : expectedTypes ) { - LoadingTypeContext typeContext = - typeContextProvider.forExactType( type.typeIdentifier() ); - typeContexts.add( typeContext ); - } - return delegate.createLoader( typeContexts, sessionContext, cacheLookupStrategy, loadingOptions ); - } - - } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/HibernateOrmEntityLoadingStrategy.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/HibernateOrmEntityLoadingStrategy.java index e448e8c4ff9..ec5ed8244e0 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/HibernateOrmEntityLoadingStrategy.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/HibernateOrmEntityLoadingStrategy.java @@ -10,40 +10,23 @@ import java.util.Set; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.search.mapper.orm.search.loading.EntityLoadingCacheLookupStrategy; -import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionEntityLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingStrategy; +import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingStrategy; /** * @param The type of loaded entities. * @param The type of entity identifiers. */ -public interface HibernateOrmEntityLoadingStrategy { - - /** - * @param obj Another strategy - * @return {@code true} if the other strategy returns the same type of loaders, - * able to target the exact same entity types. - * {@code false} otherwise or when unsure. - */ - @Override - boolean equals(Object obj); - - /* - * Hashcode must be overridden to be consistent with equals. - */ - @Override - int hashCode(); - - PojoSelectionEntityLoader createLoader(Set> targetEntityTypeContexts, - LoadingSessionContext sessionContext, EntityLoadingCacheLookupStrategy cacheLookupStrategy, - MutableEntityLoadingOptions loadingOptions); +public interface HibernateOrmEntityLoadingStrategy + extends PojoSelectionLoadingStrategy, PojoMassLoadingStrategy { HibernateOrmQueryLoader createQueryLoader(SessionFactoryImplementor sessionFactory, - List> typeContexts, + Set> typeContexts, List conditionalExpressions); HibernateOrmQueryLoader createQueryLoader(SessionFactoryImplementor sessionFactory, - List> typeContexts, + Set> typeContexts, List conditionalExpressions, String order); } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingMappingContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingMappingContext.java index b551ce65454..beb637edd7e 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingMappingContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingMappingContext.java @@ -8,6 +8,7 @@ import jakarta.persistence.EntityManager; +import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.search.mapper.orm.search.loading.EntityLoadingCacheLookupStrategy; public interface LoadingMappingContext { @@ -16,6 +17,8 @@ public interface LoadingMappingContext { int fetchSize(); + SessionFactoryImplementor sessionFactory(); + LoadingSessionContext sessionContext(EntityManager entityManager); } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingSessionContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingSessionContext.java index 3a14cb9a2ee..04292e0d8bc 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingSessionContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingSessionContext.java @@ -7,12 +7,11 @@ package org.hibernate.search.mapper.orm.loading.spi; import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.search.mapper.pojo.model.spi.PojoRuntimeIntrospector; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingSessionContext; +import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingSessionContext; -public interface LoadingSessionContext { +public interface LoadingSessionContext extends PojoLoadingSessionContext, PojoMassIndexingSessionContext { SessionImplementor session(); - PojoRuntimeIntrospector runtimeIntrospector(); - } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingTypeContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingTypeContext.java index 90fa5d20e3f..b4767b8d684 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingTypeContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/spi/LoadingTypeContext.java @@ -6,9 +6,8 @@ */ package org.hibernate.search.mapper.orm.loading.spi; -import java.util.List; - import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; public interface LoadingTypeContext { @@ -20,6 +19,8 @@ public interface LoadingTypeContext { PojoRawTypeIdentifier typeIdentifier(); + PojoLoadingTypeContext delegate(); + /** * @return The entity mapping type, giving access to a representation of the entity type in the Hibernate ORM metamodel. */ @@ -27,6 +28,4 @@ public interface LoadingTypeContext { HibernateOrmEntityLoadingStrategy loadingStrategy(); - List> ascendingSuperTypes(); - } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/logging/impl/Log.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/logging/impl/Log.java index c92e5ddd6ab..c45b4e0bf82 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/logging/impl/Log.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/logging/impl/Log.java @@ -251,12 +251,6 @@ SearchException foundMultipleEntitiesForDocumentId(String entityName, String doc + " See the reference documentation for more information.") SearchException cannotSetFetchSize(); - @Message(id = ID_OFFSET + 58, value = "No matching entity type for type identifier '%1$s'." - + " Either this type is not an entity type, or the entity type is not mapped in Hibernate Search." - + " Valid identifiers for mapped entity types are: %2$s") - SearchException unknownTypeIdentifierForMappedEntityType(PojoRawTypeIdentifier invalidTypeId, - Collection> validTypeIds); - @Message(id = ID_OFFSET + 59, value = "No matching indexed entity type for type identifier '%1$s'." + " Either this type is not an entity type, or the entity type is not indexed in Hibernate Search." + " Valid identifiers for indexed entity types are: %2$s") @@ -274,11 +268,6 @@ SearchException unknownClassForMappedEntityType(@FormatWith(ClassFormatter.class + " Valid names for mapped entity types are: %2$s") SearchException unknownEntityNameForMappedEntityType(String invalidName, Collection validNames); - @Message(id = ID_OFFSET + 63, value = "No matching indexed entity type for name '%1$s'." - + " Either this is not the JPA name of an entity type, or the entity type is not indexed in Hibernate Search." - + " Valid JPA names for indexed entities are: %2$s") - SearchException unknownJpaEntityNameForIndexedEntityType(String invalidName, Collection validNames); - @Message(id = ID_OFFSET + 64, value = "No matching entity type for name '%1$s'." + " Either this is not the Hibernate ORM name of an entity type, or the entity type is not mapped in Hibernate Search." + " Valid Hibernate ORM names for mapped entities are: %2$s") diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/AbstractHibernateOrmTypeContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/AbstractHibernateOrmTypeContext.java index 18d5ac32da8..8197b2e90ab 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/AbstractHibernateOrmTypeContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/AbstractHibernateOrmTypeContext.java @@ -6,20 +6,17 @@ */ package org.hibernate.search.mapper.orm.mapping.impl; -import java.util.List; -import java.util.stream.Collectors; - import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.PersistentClass; import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.search.mapper.orm.event.impl.HibernateOrmListenerTypeContext; -import org.hibernate.search.mapper.orm.loading.impl.HibernateOrmEntityIdEntityLoadingStrategy; -import org.hibernate.search.mapper.orm.loading.impl.HibernateOrmNonEntityIdPropertyEntityLoadingStrategy; import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmEntityLoadingStrategy; import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; import org.hibernate.search.mapper.orm.model.impl.DocumentIdSourceProperty; import org.hibernate.search.mapper.orm.session.impl.HibernateOrmSessionTypeContext; +import org.hibernate.search.mapper.pojo.loading.definition.spi.PojoEntityLoadingBindingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoTypeExtendedMappingCollector; import org.hibernate.search.mapper.pojo.model.path.spi.PojoPathFilter; import org.hibernate.search.mapper.pojo.model.spi.PojoPropertyModel; @@ -32,43 +29,24 @@ abstract class AbstractHibernateOrmTypeContext LoadingTypeContext { private final PojoRawTypeIdentifier typeIdentifier; + private final PojoLoadingTypeContext delegate; private final String jpaEntityName; private final EntityMappingType entityMappingType; private final boolean documentIdIsEntityId; private final HibernateOrmEntityLoadingStrategy loadingStrategy; private final PojoPathFilter dirtyFilter; private final PojoPathFilter dirtyContainingAssociationFilter; - private final List> ascendingSuperTypes; - // Casts are safe because the loading strategy will target either "E" or "? super E", by contract - @SuppressWarnings("unchecked") - AbstractHibernateOrmTypeContext(AbstractBuilder builder, SessionFactoryImplementor sessionFactory) { + AbstractHibernateOrmTypeContext(Builder builder, PojoLoadingTypeContext delegate, + SessionFactoryImplementor sessionFactory) { this.typeIdentifier = builder.typeIdentifier; + this.delegate = delegate; this.jpaEntityName = builder.jpaEntityName; MappingMetamodel metamodel = sessionFactory.getMappingMetamodel(); this.entityMappingType = metamodel.getEntityDescriptor( builder.hibernateOrmEntityName ); - this.ascendingSuperTypes = builder.ascendingSuperTypes; - if ( builder.documentIdSourceProperty != null ) { - var idProperty = builder.persistentClass.getIdentifierProperty(); - if ( idProperty != null && builder.documentIdSourceProperty.name.equals( idProperty.getName() ) ) { - documentIdIsEntityId = true; - loadingStrategy = (HibernateOrmEntityLoadingStrategy) HibernateOrmEntityIdEntityLoadingStrategy - .create( builder.persistentClass ); - } - else { - // The entity ID is not the property used to generate the document ID - // We need to use a criteria query to load entities from the document IDs - documentIdIsEntityId = false; - loadingStrategy = (HibernateOrmEntityLoadingStrategy) HibernateOrmNonEntityIdPropertyEntityLoadingStrategy.create( builder.persistentClass, - builder.documentIdSourceProperty ); - } - } - else { - // Can only happen for contained types, which may not be loadable. - documentIdIsEntityId = false; - loadingStrategy = null; - } + this.documentIdIsEntityId = builder.documentIdSourceProperty != null + && builder.documentIdSourceProperty.name.equals( entityMappingType.getIdentifierMapping().getAttributeName() ); + this.loadingStrategy = builder.loadingStrategy; this.dirtyFilter = builder.dirtyFilter; this.dirtyContainingAssociationFilter = builder.dirtyContainingAssociationFilter; } @@ -83,6 +61,11 @@ public PojoRawTypeIdentifier typeIdentifier() { return typeIdentifier; } + @Override + public PojoLoadingTypeContext delegate() { + return delegate; + } + @Override public String jpaEntityName() { return jpaEntityName; @@ -102,11 +85,6 @@ public EntityMappingType entityMappingType() { return loadingStrategy; } - @Override - public List> ascendingSuperTypes() { - return ascendingSuperTypes; - } - @Override public Object toIndexingPlanProvidedId(Object entityId) { if ( documentIdIsEntityId ) { @@ -129,24 +107,21 @@ public PojoPathFilter dirtyContainingAssociationFilter() { return dirtyContainingAssociationFilter; } - abstract static class AbstractBuilder implements PojoTypeExtendedMappingCollector { - private final PojoRawTypeIdentifier typeIdentifier; + public abstract static class Builder implements PojoTypeExtendedMappingCollector { + public final PojoRawTypeIdentifier typeIdentifier; private final PersistentClass persistentClass; private final String jpaEntityName; private final String hibernateOrmEntityName; private DocumentIdSourceProperty documentIdSourceProperty; private PojoPathFilter dirtyFilter; private PojoPathFilter dirtyContainingAssociationFilter; - private final List> ascendingSuperTypes; + private HibernateOrmEntityLoadingStrategy loadingStrategy; - AbstractBuilder(PojoRawTypeModel typeModel, PersistentClass persistentClass) { + Builder(PojoRawTypeModel typeModel, PersistentClass persistentClass) { this.typeIdentifier = typeModel.typeIdentifier(); this.persistentClass = persistentClass; this.jpaEntityName = persistentClass.getJpaEntityName(); this.hibernateOrmEntityName = persistentClass.getEntityName(); - this.ascendingSuperTypes = typeModel.ascendingSuperTypes() - .map( PojoRawTypeModel::typeIdentifier ) - .collect( Collectors.toList() ); } @Override @@ -163,6 +138,17 @@ public void dirtyFilter(PojoPathFilter dirtyFilter) { public void dirtyContainingAssociationFilter(PojoPathFilter filter) { this.dirtyContainingAssociationFilter = filter; } + + @Override + public void applyLoadingBinder(Object binder, PojoEntityLoadingBindingContext context) { + @SuppressWarnings("unchecked") // We make sure of that when contributing the loading binder, see org.hibernate.search.mapper.pojo.standalone.mapping.StandalonePojoMappingConfigurationContext.addEntityType(java.lang.Class, org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurer) + var castBinder = (HibernateOrmEntityLoadingBinder) binder; + this.loadingStrategy = castBinder.createLoadingStrategy( persistentClass, documentIdSourceProperty ); + if ( this.loadingStrategy != null ) { + context.selectionLoadingStrategy( typeIdentifier.javaClass(), this.loadingStrategy ); + context.massLoadingStrategy( typeIdentifier.javaClass(), this.loadingStrategy ); + } + } } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmContainedTypeContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmContainedTypeContext.java index 33d61a8c4ad..3ea674100d8 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmContainedTypeContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmContainedTypeContext.java @@ -8,14 +8,16 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.mapping.PersistentClass; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContextProvider; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoContainedTypeExtendedMappingCollector; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; class HibernateOrmContainedTypeContext extends AbstractHibernateOrmTypeContext { private HibernateOrmContainedTypeContext(HibernateOrmContainedTypeContext.Builder builder, - SessionFactoryImplementor sessionFactory) { - super( builder, sessionFactory ); + PojoLoadingTypeContext delegate, SessionFactoryImplementor sessionFactory) { + super( builder, delegate, sessionFactory ); } @Override @@ -25,14 +27,17 @@ public Object toIndexingPlanProvidedId(Object entityId) { return entityId; } - static class Builder extends AbstractBuilder implements PojoContainedTypeExtendedMappingCollector { + static class Builder extends AbstractHibernateOrmTypeContext.Builder + implements PojoContainedTypeExtendedMappingCollector { Builder(PojoRawTypeModel typeModel, PersistentClass persistentClass) { super( typeModel, persistentClass ); } - HibernateOrmContainedTypeContext build(SessionFactoryImplementor sessionFactory) { - return new HibernateOrmContainedTypeContext<>( this, sessionFactory ); + HibernateOrmContainedTypeContext build(PojoLoadingTypeContextProvider delegateProvider, + SessionFactoryImplementor sessionFactory) { + return new HibernateOrmContainedTypeContext<>( this, delegateProvider.forExactType( typeIdentifier ), + sessionFactory ); } } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmEntityLoadingBinder.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmEntityLoadingBinder.java new file mode 100644 index 00000000000..dbdad1f1bd7 --- /dev/null +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmEntityLoadingBinder.java @@ -0,0 +1,42 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.orm.mapping.impl; + +import org.hibernate.mapping.PersistentClass; +import org.hibernate.search.mapper.orm.loading.impl.HibernateOrmEntityIdEntityLoadingStrategy; +import org.hibernate.search.mapper.orm.loading.impl.HibernateOrmNonEntityIdPropertyEntityLoadingStrategy; +import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmEntityLoadingStrategy; +import org.hibernate.search.mapper.orm.model.impl.DocumentIdSourceProperty; + +public class HibernateOrmEntityLoadingBinder { + + public HibernateOrmEntityLoadingBinder() { + } + + // Casts are safe because the loading strategy will target either "E" or "? super E", by contract + @SuppressWarnings("unchecked") + public HibernateOrmEntityLoadingStrategy createLoadingStrategy( + PersistentClass persistentClass, DocumentIdSourceProperty documentIdSourceProperty) { + if ( documentIdSourceProperty != null ) { + var idProperty = persistentClass.getIdentifierProperty(); + if ( idProperty != null && documentIdSourceProperty.name.equals( idProperty.getName() ) ) { + return (HibernateOrmEntityLoadingStrategy) HibernateOrmEntityIdEntityLoadingStrategy + .create( persistentClass ); + } + else { + // The entity ID is not the property used to generate the document ID + // We need to use a criteria query to load entities from the document IDs + return (HibernateOrmEntityLoadingStrategy) HibernateOrmNonEntityIdPropertyEntityLoadingStrategy + .create( persistentClass, documentIdSourceProperty ); + } + } + else { + // No loading. Can only happen for contained types, which may not be loadable. + return null; + } + } +} diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmEntityTypeMetadataContributor.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmEntityTypeMetadataContributor.java index b2a5786eaed..f861bbd9a19 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmEntityTypeMetadataContributor.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmEntityTypeMetadataContributor.java @@ -58,5 +58,6 @@ public void contributeAdditionalMetadata(PojoAdditionalMetadataCollectorTypeNode node.pathDefinitionProvider( new HibernateOrmPathDefinitionProvider( typeModel, persistentClass ) ); node.entityIdPropertyName( identifierPropertyNameOptional.orElse( null ) ); + node.loadingBinder( new HibernateOrmEntityLoadingBinder<>() ); } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmIndexedTypeContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmIndexedTypeContext.java index 02214cb8234..8a5f4efa626 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmIndexedTypeContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmIndexedTypeContext.java @@ -13,18 +13,20 @@ import org.hibernate.search.engine.search.projection.spi.ProjectionMappedTypeContext; import org.hibernate.search.mapper.orm.automaticindexing.impl.AutomaticIndexingIndexedTypeContext; import org.hibernate.search.mapper.orm.entity.SearchIndexedEntity; -import org.hibernate.search.mapper.orm.scope.impl.HibernateOrmScopeIndexedTypeContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContextProvider; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoIndexedTypeExtendedMappingCollector; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; class HibernateOrmIndexedTypeContext extends AbstractHibernateOrmTypeContext implements ProjectionMappedTypeContext, - SearchIndexedEntity, HibernateOrmScopeIndexedTypeContext, AutomaticIndexingIndexedTypeContext { + SearchIndexedEntity, AutomaticIndexingIndexedTypeContext { private final MappedIndexManager indexManager; - private HibernateOrmIndexedTypeContext(Builder builder, SessionFactoryImplementor sessionFactory) { - super( builder, sessionFactory ); + private HibernateOrmIndexedTypeContext(Builder builder, PojoLoadingTypeContext delegate, + SessionFactoryImplementor sessionFactory) { + super( builder, delegate, sessionFactory ); this.indexManager = builder.indexManager; } @@ -53,7 +55,8 @@ public IndexManager indexManager() { return indexManager.toAPI(); } - static class Builder extends AbstractBuilder implements PojoIndexedTypeExtendedMappingCollector { + static class Builder extends AbstractHibernateOrmTypeContext.Builder + implements PojoIndexedTypeExtendedMappingCollector { private MappedIndexManager indexManager; Builder(PojoRawTypeModel typeModel, PersistentClass persistentClass) { @@ -65,8 +68,10 @@ public void indexManager(MappedIndexManager indexManager) { this.indexManager = indexManager; } - public HibernateOrmIndexedTypeContext build(SessionFactoryImplementor sessionFactory) { - return new HibernateOrmIndexedTypeContext<>( this, sessionFactory ); + public HibernateOrmIndexedTypeContext build(PojoLoadingTypeContextProvider delegateProvider, + SessionFactoryImplementor sessionFactory) { + return new HibernateOrmIndexedTypeContext<>( this, delegateProvider.forExactType( typeIdentifier ), + sessionFactory ); } } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMapping.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMapping.java index 84bbb8893e2..ad5933952ca 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMapping.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMapping.java @@ -29,7 +29,6 @@ import org.hibernate.search.engine.mapper.mapping.spi.MappingImplementor; import org.hibernate.search.engine.mapper.mapping.spi.MappingPreStopContext; import org.hibernate.search.engine.mapper.mapping.spi.MappingStartContext; -import org.hibernate.search.engine.search.projection.spi.ProjectionMappedTypeContext; import org.hibernate.search.mapper.orm.automaticindexing.impl.AutomaticIndexingQueueEventProcessingPlanImpl; import org.hibernate.search.mapper.orm.automaticindexing.spi.AutomaticIndexingMappingContext; import org.hibernate.search.mapper.orm.automaticindexing.spi.AutomaticIndexingQueueEventProcessingPlan; @@ -45,7 +44,6 @@ import org.hibernate.search.mapper.orm.reporting.impl.HibernateOrmMappingHints; import org.hibernate.search.mapper.orm.schema.management.SchemaManagementStrategyName; import org.hibernate.search.mapper.orm.schema.management.impl.SchemaManagementListener; -import org.hibernate.search.mapper.orm.scope.impl.HibernateOrmScopeIndexedTypeContext; import org.hibernate.search.mapper.orm.scope.impl.HibernateOrmScopeMappingContext; import org.hibernate.search.mapper.orm.scope.impl.HibernateOrmScopeSessionContext; import org.hibernate.search.mapper.orm.scope.impl.SearchScopeImpl; @@ -217,11 +215,6 @@ public BackendMappingHints hints() { return HibernateOrmMappingHints.INSTANCE; } - @Override - public ProjectionMappedTypeContext mappedTypeContext(String mappedTypeName) { - return typeContextContainer.indexedByJpaEntityName().getOrFail( mappedTypeName ); - } - @Override public SearchScopeImpl scope(Class type) { return scope( Collections.singleton( type ) ); @@ -400,7 +393,7 @@ public HibernateOrmTypeContextContainer typeContextProvider() { public SearchScopeImpl createScope(Collection> classes) { PojoScopeDelegate> scopeDelegate = + SearchIndexedEntity> scopeDelegate = delegate().createPojoScopeForClasses( this, classes, @@ -415,7 +408,7 @@ public SearchScopeImpl createScope(Collection SearchScopeImpl createScope(Class expectedSuperType, Collection entityNames) { PojoScopeDelegate> scopeDelegate = + SearchIndexedEntity> scopeDelegate = delegate().createPojoScopeForEntityNames( this, expectedSuperType, entityNames, @@ -450,7 +443,7 @@ private SearchIntegration searchIntegration() { private Optional> createAllScope() { return delegate().>createPojoAllScope( + SearchIndexedEntity>createPojoAllScope( this, typeContextContainer::indexedForExactType ) diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMappingPartialBuildState.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMappingPartialBuildState.java index dce0840becf..8806087ed65 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMappingPartialBuildState.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmMappingPartialBuildState.java @@ -35,12 +35,12 @@ public class HibernateOrmMappingPartialBuildState implements MappingPartialBuild public MappingImplementor bindToSessionFactory( MappingFinalizationContext context, - SessionFactoryImplementor sessionFactoryImplementor) { - return HibernateOrmMapping.create( - mappingDelegate, typeContextContainerBuilder.build( sessionFactoryImplementor ), + SessionFactoryImplementor sessionFactory) { + return HibernateOrmMapping.create( mappingDelegate, + typeContextContainerBuilder.build( mappingDelegate.typeContextProvider(), sessionFactory ), coordinationStrategyHolder, configuredAutomaticIndexingStrategy, - sessionFactoryImplementor, + sessionFactory, context.configurationPropertySource() ); } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmTypeContextContainer.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmTypeContextContainer.java index e448ee8a38f..66519373a01 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmTypeContextContainer.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/mapping/impl/HibernateOrmTypeContextContainer.java @@ -16,11 +16,11 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.search.mapper.orm.automaticindexing.impl.AutomaticIndexingTypeContextProvider; import org.hibernate.search.mapper.orm.event.impl.HibernateOrmListenerTypeContextProvider; -import org.hibernate.search.mapper.orm.loading.impl.LoadingIndexedTypeContextProvider; import org.hibernate.search.mapper.orm.logging.impl.Log; import org.hibernate.search.mapper.orm.model.impl.HibernateOrmBasicTypeMetadataProvider; import org.hibernate.search.mapper.orm.session.impl.HibernateOrmSessionTypeContextProvider; import org.hibernate.search.mapper.orm.spi.BatchTypeContextProvider; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContextProvider; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; import org.hibernate.search.util.common.data.spi.KeyValueProvider; @@ -28,35 +28,30 @@ class HibernateOrmTypeContextContainer implements HibernateOrmListenerTypeContextProvider, HibernateOrmSessionTypeContextProvider, - AutomaticIndexingTypeContextProvider, LoadingIndexedTypeContextProvider, BatchTypeContextProvider { + AutomaticIndexingTypeContextProvider, BatchTypeContextProvider { private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); - private final KeyValueProvider, AbstractHibernateOrmTypeContext> byTypeIdentifier; private final KeyValueProvider, HibernateOrmIndexedTypeContext> indexedByTypeIdentifier; private final KeyValueProvider, AbstractHibernateOrmTypeContext> byExactClass; private final KeyValueProvider, HibernateOrmIndexedTypeContext> indexedByExactClass; private final KeyValueProvider> byEntityName; private final KeyValueProvider> indexedByEntityName; private final KeyValueProvider> byHibernateOrmEntityName; - private final KeyValueProvider> indexedByJpaEntityName; - private HibernateOrmTypeContextContainer(Builder builder, SessionFactoryImplementor sessionFactory) { + private HibernateOrmTypeContextContainer(Builder builder, PojoLoadingTypeContextProvider delegate, + SessionFactoryImplementor sessionFactory) { // Use a LinkedHashMap for deterministic iteration - Map, AbstractHibernateOrmTypeContext> byTypeIdentifierContent = new LinkedHashMap<>(); Map, HibernateOrmIndexedTypeContext> indexedByTypeIdentifierContent = new LinkedHashMap<>(); Map, AbstractHibernateOrmTypeContext> byExactClassContent = new LinkedHashMap<>(); Map, HibernateOrmIndexedTypeContext> indexedByExactClassContent = new LinkedHashMap<>(); Map> byEntityNameContent = new LinkedHashMap<>(); Map> indexedByEntityNameContent = new LinkedHashMap<>(); - Map> byJpaEntityNameContent = new LinkedHashMap<>(); - Map> indexedByJpaEntityNameContent = new LinkedHashMap<>(); Map> byHibernateOrmEntityNameContent = new LinkedHashMap<>(); - for ( HibernateOrmIndexedTypeContext.Builder contextBuilder : builder.indexedTypeContextBuilders ) { - HibernateOrmIndexedTypeContext typeContext = contextBuilder.build( sessionFactory ); + for ( HibernateOrmIndexedTypeContext.Builder contextBuilder : builder.indexed ) { + HibernateOrmIndexedTypeContext typeContext = contextBuilder.build( delegate, sessionFactory ); PojoRawTypeIdentifier typeIdentifier = typeContext.typeIdentifier(); - byTypeIdentifierContent.put( typeIdentifier, typeContext ); indexedByTypeIdentifierContent.put( typeIdentifier, typeContext ); if ( !typeIdentifier.isNamed() ) { @@ -71,17 +66,12 @@ private HibernateOrmTypeContextContainer(Builder builder, SessionFactoryImplemen byEntityNameContent.putIfAbsent( typeContext.hibernateOrmEntityName(), typeContext ); indexedByEntityNameContent.putIfAbsent( typeContext.hibernateOrmEntityName(), typeContext ); - byJpaEntityNameContent.put( typeContext.jpaEntityName(), typeContext ); - indexedByJpaEntityNameContent.put( typeContext.jpaEntityName(), typeContext ); - byHibernateOrmEntityNameContent.put( typeContext.hibernateOrmEntityName(), typeContext ); } - for ( HibernateOrmContainedTypeContext.Builder contextBuilder : builder.containedTypeContextBuilders ) { - HibernateOrmContainedTypeContext typeContext = contextBuilder.build( sessionFactory ); + for ( HibernateOrmContainedTypeContext.Builder contextBuilder : builder.contained ) { + HibernateOrmContainedTypeContext typeContext = contextBuilder.build( delegate, sessionFactory ); PojoRawTypeIdentifier typeIdentifier = typeContext.typeIdentifier(); - byTypeIdentifierContent.put( typeIdentifier, typeContext ); - if ( !typeIdentifier.isNamed() ) { byExactClassContent.put( typeIdentifier.javaClass(), typeContext ); } @@ -91,12 +81,8 @@ private HibernateOrmTypeContextContainer(Builder builder, SessionFactoryImplemen // see org.hibernate.search.mapper.orm.model.impl.HibernateOrmRawTypeIdentifierResolver.Builder.addByName byEntityNameContent.putIfAbsent( typeContext.hibernateOrmEntityName(), typeContext ); - byJpaEntityNameContent.put( typeContext.jpaEntityName(), typeContext ); - byHibernateOrmEntityNameContent.put( typeContext.hibernateOrmEntityName(), typeContext ); } - this.byTypeIdentifier = - new KeyValueProvider<>( byTypeIdentifierContent, log::unknownTypeIdentifierForMappedEntityType ); this.indexedByTypeIdentifier = new KeyValueProvider<>( indexedByTypeIdentifierContent, log::unknownTypeIdentifierForIndexedEntityType ); this.byExactClass = new KeyValueProvider<>( byExactClassContent, log::unknownClassForMappedEntityType ); @@ -104,18 +90,10 @@ private HibernateOrmTypeContextContainer(Builder builder, SessionFactoryImplemen this.byEntityName = new KeyValueProvider<>( byEntityNameContent, log::unknownEntityNameForMappedEntityType ); this.indexedByEntityName = new KeyValueProvider<>( indexedByEntityNameContent, log::unknownEntityNameForIndexedEntityType ); - this.indexedByJpaEntityName = - new KeyValueProvider<>( indexedByJpaEntityNameContent, log::unknownJpaEntityNameForIndexedEntityType ); this.byHibernateOrmEntityName = new KeyValueProvider<>( byHibernateOrmEntityNameContent, log::unknownHibernateOrmEntityNameForMappedEntityType ); } - @Override - @SuppressWarnings("unchecked") - public AbstractHibernateOrmTypeContext forExactType(PojoRawTypeIdentifier typeIdentifier) { - return (AbstractHibernateOrmTypeContext) byTypeIdentifier.getOrFail( typeIdentifier ); - } - @Override @SuppressWarnings("unchecked") public HibernateOrmIndexedTypeContext indexedForExactType(PojoRawTypeIdentifier typeIdentifier) { @@ -142,10 +120,6 @@ public KeyValueProvider> indexedByEnti return indexedByEntityName; } - public KeyValueProvider> indexedByJpaEntityName() { - return indexedByJpaEntityName; - } - @Override public KeyValueProvider> byHibernateOrmEntityName() { return byHibernateOrmEntityName; @@ -158,8 +132,8 @@ Collection> allIndexed() { static class Builder { private final HibernateOrmBasicTypeMetadataProvider basicTypeMetadataProvider; - private final List> indexedTypeContextBuilders = new ArrayList<>(); - private final List> containedTypeContextBuilders = new ArrayList<>(); + public final List> indexed = new ArrayList<>(); + public final List> contained = new ArrayList<>(); Builder(HibernateOrmBasicTypeMetadataProvider basicTypeMetadataProvider) { this.basicTypeMetadataProvider = basicTypeMetadataProvider; @@ -169,7 +143,7 @@ HibernateOrmIndexedTypeContext.Builder addIndexed(PojoRawTypeModel typ String hibernateOrmEntityName = basicTypeMetadataProvider.getHibernateOrmEntityNameByJpaEntityName( jpaEntityName ); HibernateOrmIndexedTypeContext.Builder builder = new HibernateOrmIndexedTypeContext.Builder<>( typeModel, basicTypeMetadataProvider.getPersistentClass( hibernateOrmEntityName ) ); - indexedTypeContextBuilders.add( builder ); + indexed.add( builder ); return builder; } @@ -177,12 +151,13 @@ HibernateOrmContainedTypeContext.Builder addContained(PojoRawTypeModel String hibernateOrmEntityName = basicTypeMetadataProvider.getHibernateOrmEntityNameByJpaEntityName( jpaEntityName ); HibernateOrmContainedTypeContext.Builder builder = new HibernateOrmContainedTypeContext.Builder<>( typeModel, basicTypeMetadataProvider.getPersistentClass( hibernateOrmEntityName ) ); - containedTypeContextBuilders.add( builder ); + contained.add( builder ); return builder; } - HibernateOrmTypeContextContainer build(SessionFactoryImplementor sessionFactory) { - return new HibernateOrmTypeContextContainer( this, sessionFactory ); + HibernateOrmTypeContextContainer build(PojoLoadingTypeContextProvider delegate, + SessionFactoryImplementor sessionFactory) { + return new HibernateOrmTypeContextContainer( this, delegate, sessionFactory ); } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingContext.java index be57ce1b759..e561a7e6087 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingContext.java @@ -7,40 +7,20 @@ package org.hibernate.search.mapper.orm.massindexing.impl; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.stream.Collectors; import org.hibernate.CacheMode; -import org.hibernate.FlushMode; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.engine.spi.SessionImplementor; -import org.hibernate.engine.spi.SharedSessionContractImplementor; -import org.hibernate.search.mapper.orm.loading.impl.HibernateOrmMassEntityLoader; -import org.hibernate.search.mapper.orm.loading.impl.HibernateOrmMassIdentifierLoader; -import org.hibernate.search.mapper.orm.loading.impl.HibernateOrmMassLoadingOptions; +import org.hibernate.search.mapper.orm.loading.impl.HibernateOrmMassLoadingContext; import org.hibernate.search.mapper.orm.loading.spi.ConditionalExpression; -import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmEntityLoadingStrategy; -import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmQueryLoader; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; -import org.hibernate.search.mapper.orm.session.impl.HibernateOrmSessionTypeContextProvider; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoader; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntitySink; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierSink; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingEntityLoadingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingIdentifierLoadingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingLoadingStrategy; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; -import org.hibernate.search.util.common.impl.SuppressingCloser; public final class HibernateOrmMassIndexingContext - implements PojoMassIndexingContext, HibernateOrmMassLoadingOptions { - private final HibernateOrmMassIndexingMappingContext mappingContext; - private final HibernateOrmSessionTypeContextProvider typeContextProvider; + implements PojoMassIndexingContext, HibernateOrmMassLoadingContext { + + private final HibernateOrmMassIndexingMappingContext mapping; private final Map, ConditionalExpression> conditionalExpressions = new HashMap<>(); private CacheMode cacheMode = CacheMode.IGNORE; private Integer idLoadingTransactionTimeout; @@ -48,17 +28,13 @@ public final class HibernateOrmMassIndexingContext private int objectLoadingBatchSize = 10; private long objectsLimit = 0; //means no limit at all - public HibernateOrmMassIndexingContext(HibernateOrmMassIndexingMappingContext mappingContext, - HibernateOrmSessionTypeContextProvider typeContextContainer) { - this.mappingContext = mappingContext; - this.typeContextProvider = typeContextContainer; + public HibernateOrmMassIndexingContext(HibernateOrmMassIndexingMappingContext mapping) { + this.mapping = mapping; } @Override - public PojoMassIndexingLoadingStrategy loadingStrategy(PojoRawTypeIdentifier expectedType) { - LoadingTypeContext typeContext = typeContextProvider.forExactType( expectedType ); - return new HibernateOrmMassIndexingLoadingStrategy<>( typeContext.loadingStrategy(), - conditionalExpression( typeContext ), typeContextProvider ); + public HibernateOrmMassIndexingMappingContext mapping() { + return mapping; } public void idLoadingTransactionTimeout(int timeoutInSeconds) { @@ -117,110 +93,16 @@ ConditionalExpression reindexOnly(Class type, String conditionalExpression) { return expression; } - private Optional conditionalExpression(LoadingTypeContext typeContext) { + @Override + public Optional conditionalExpression(PojoLoadingTypeContext typeContext) { if ( conditionalExpressions.isEmpty() ) { return Optional.empty(); } - return typeContext.ascendingSuperTypes() - .stream() - .map( type -> conditionalExpressions.get( type.javaClass() ) ) + return typeContext.ascendingSuperTypes().stream() + .map( typeId -> conditionalExpressions.get( typeId.javaClass() ) ) .filter( Objects::nonNull ) .findFirst(); } - private final class HibernateOrmMassIndexingLoadingStrategy implements PojoMassIndexingLoadingStrategy { - - private final HibernateOrmEntityLoadingStrategy delegate; - private final Optional conditionalExpression; - private final HibernateOrmSessionTypeContextProvider typeContextProvider; - - public HibernateOrmMassIndexingLoadingStrategy(HibernateOrmEntityLoadingStrategy delegate, - Optional conditionalExpression, - HibernateOrmSessionTypeContextProvider typeContextProvider) { - this.delegate = delegate; - this.conditionalExpression = conditionalExpression; - this.typeContextProvider = typeContextProvider; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - HibernateOrmMassIndexingLoadingStrategy that = (HibernateOrmMassIndexingLoadingStrategy) o; - if ( conditionalExpression.isPresent() || that.conditionalExpression.isPresent() ) { - // Never merge strategies with conditional expressions, it's too complicated to apply a condition to multiple types - // TODO-4252 Verify if there is a good way to do that - return false; - } - return Objects.equals( delegate, that.delegate ); - } - - @Override - public int hashCode() { - return Objects.hash( delegate, conditionalExpression ); - } - - @Override - public PojoMassIdentifierLoader createIdentifierLoader(PojoMassIndexingIdentifierLoadingContext context) { - SessionFactoryImplementor sessionFactory = mappingContext.sessionFactory(); - List> typeContexts = context.includedTypes().stream() - .map( typeContextProvider::forExactType ) - .collect( Collectors.toList() ); - - HibernateOrmQueryLoader typeQueryLoader = createQueryLoader( sessionFactory, typeContexts ); - SharedSessionContractImplementor session = (SharedSessionContractImplementor) sessionFactory - .withStatelessOptions() - .tenantIdentifier( (Object) context.tenantIdentifier() ) - .openStatelessSession(); - try { - PojoMassIdentifierSink sink = context.createSink(); - return new HibernateOrmMassIdentifierLoader<>( typeQueryLoader, - HibernateOrmMassIndexingContext.this, sink, session ); - } - catch (RuntimeException e) { - new SuppressingCloser( e ).push( SharedSessionContractImplementor::close, session ); - throw e; - } - } - - @Override - public PojoMassEntityLoader createEntityLoader(PojoMassIndexingEntityLoadingContext context) { - SessionFactoryImplementor sessionFactory = mappingContext.sessionFactory(); - List> typeContexts = context.includedTypes().stream() - .map( typeContextProvider::forExactType ) - .collect( Collectors.toList() ); - - HibernateOrmQueryLoader typeQueryLoader = createQueryLoader( sessionFactory, typeContexts ); - SessionImplementor session = (SessionImplementor) sessionFactory - .withOptions() - .tenantIdentifier( (Object) context.tenantIdentifier() ) - .openSession(); - try { - session.setHibernateFlushMode( FlushMode.MANUAL ); - session.setCacheMode( cacheMode() ); - session.setDefaultReadOnly( true ); - - PojoMassEntitySink sink = context.createSink( mappingContext.sessionContext( session ) ); - return new HibernateOrmMassEntityLoader<>( typeQueryLoader, - HibernateOrmMassIndexingContext.this, sink, session ); - } - catch (RuntimeException e) { - new SuppressingCloser( e ).push( SessionImplementor::close, session ); - throw e; - } - } - - private HibernateOrmQueryLoader createQueryLoader(SessionFactoryImplementor sessionFactory, - List> typeContexts) { - return delegate.createQueryLoader( sessionFactory, typeContexts, conditionalExpression.isPresent() - ? List.of( conditionalExpression.get() ) - : List.of() ); - } - - } } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingMappingContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingMappingContext.java index f53155e2aff..18cd443eb5c 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingMappingContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingMappingContext.java @@ -6,18 +6,10 @@ */ package org.hibernate.search.mapper.orm.massindexing.impl; -import jakarta.persistence.EntityManager; - -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.search.mapper.orm.scope.impl.HibernateOrmScopeSessionContext; -import org.hibernate.search.mapper.orm.session.impl.HibernateOrmSessionTypeContextProvider; +import org.hibernate.search.mapper.orm.loading.spi.LoadingMappingContext; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingMappingContext; -public interface HibernateOrmMassIndexingMappingContext extends PojoMassIndexingMappingContext { - - SessionFactoryImplementor sessionFactory(); - - HibernateOrmScopeSessionContext sessionContext(EntityManager entityManager); +public interface HibernateOrmMassIndexingMappingContext + extends PojoMassIndexingMappingContext, LoadingMappingContext { - HibernateOrmSessionTypeContextProvider typeContextProvider(); } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/scope/impl/HibernateOrmScopeIndexedTypeContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/scope/impl/HibernateOrmScopeIndexedTypeContext.java deleted file mode 100644 index f366858a1f7..00000000000 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/scope/impl/HibernateOrmScopeIndexedTypeContext.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.orm.scope.impl; - -import org.hibernate.search.mapper.orm.entity.SearchIndexedEntity; -import org.hibernate.search.mapper.orm.loading.spi.HibernateOrmEntityLoadingStrategy; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; -import org.hibernate.search.mapper.orm.massindexing.impl.HibernateOrmMassIndexingIndexedTypeContext; -import org.hibernate.search.mapper.pojo.scope.spi.PojoScopeDelegate; - -/** - * A mapper-specific indexed type context, - * accessible through {@link PojoScopeDelegate#includedIndexedTypes()} - * in particular. - * - * @param The entity type mapped to the index. - */ -public interface HibernateOrmScopeIndexedTypeContext - extends SearchIndexedEntity, LoadingTypeContext, - HibernateOrmMassIndexingIndexedTypeContext { - - @Override - HibernateOrmEntityLoadingStrategy loadingStrategy(); - -} diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/scope/impl/SearchScopeImpl.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/scope/impl/SearchScopeImpl.java index 6460ae737d5..bb3e69e720e 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/scope/impl/SearchScopeImpl.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/scope/impl/SearchScopeImpl.java @@ -43,13 +43,13 @@ public class SearchScopeImpl implements SearchScope, BatchScopeContext private final TenancyConfiguration tenancyConfiguration; private final PojoScopeDelegate> delegate; + SearchIndexedEntity> delegate; public SearchScopeImpl(HibernateOrmScopeMappingContext mappingContext, TenancyConfiguration tenancyConfiguration, PojoScopeDelegate> delegate) { + SearchIndexedEntity> delegate) { this.mappingContext = mappingContext; this.tenancyConfiguration = tenancyConfiguration; this.delegate = delegate; @@ -128,8 +128,7 @@ public MassIndexer massIndexer(Set tenantIds) { tenantIds = tenancyConfiguration.tenantIdsOrFail(); } - HibernateOrmMassIndexingContext massIndexingContext = new HibernateOrmMassIndexingContext( mappingContext, - mappingContext.typeContextProvider() ); + HibernateOrmMassIndexingContext massIndexingContext = new HibernateOrmMassIndexingContext( mappingContext ); PojoMassIndexer massIndexerDelegate = delegate .massIndexer( massIndexingContext, tenantIds ); diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java index e7ca79d6e43..20b186cab36 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSession.java @@ -321,7 +321,7 @@ public ConfiguredIndexingPlanSynchronizationStrategy configuredAutomaticIndexing } private HibernateOrmSelectionLoadingContext.Builder loadingContextBuilder() { - return new HibernateOrmSelectionLoadingContext.Builder( mappingContext, typeContextProvider, this ); + return new HibernateOrmSelectionLoadingContext.Builder( mappingContext, this ); } private void registerSynchronization(SessionImplementor sessionImplementor, Synchronization synchronization) { diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionMappingContext.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionMappingContext.java index 861f95867e9..33dffe365bf 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionMappingContext.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSearchSessionMappingContext.java @@ -8,7 +8,6 @@ import java.util.Collection; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.search.engine.reporting.FailureHandler; import org.hibernate.search.mapper.orm.loading.spi.LoadingMappingContext; @@ -23,8 +22,6 @@ public interface HibernateOrmSearchSessionMappingContext @Override FailureHandler failureHandler(); - SessionFactoryImplementor sessionFactory(); - SearchScopeImpl createScope(Collection> types); SearchScopeImpl createScope(Class expectedSuperType, Collection entityNames); diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSessionTypeContextProvider.java b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSessionTypeContextProvider.java index a3fcfca4186..e7a00184e0d 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSessionTypeContextProvider.java +++ b/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/session/impl/HibernateOrmSessionTypeContextProvider.java @@ -6,12 +6,11 @@ */ package org.hibernate.search.mapper.orm.session.impl; -import org.hibernate.search.mapper.orm.loading.impl.LoadingIndexedTypeContextProvider; import org.hibernate.search.mapper.orm.model.impl.HibernateOrmRuntimeIntrospectorTypeContextProvider; import org.hibernate.search.mapper.orm.work.impl.SearchIndexingPlanTypeContextProvider; public interface HibernateOrmSessionTypeContextProvider extends HibernateOrmRuntimeIntrospectorTypeContextProvider, - SearchIndexingPlanTypeContextProvider, LoadingIndexedTypeContextProvider { + SearchIndexingPlanTypeContextProvider { } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/identity/impl/PojoRootIdentityMappingCollector.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/identity/impl/PojoRootIdentityMappingCollector.java index 7ee6bcbad82..29e120fa9b5 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/identity/impl/PojoRootIdentityMappingCollector.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/identity/impl/PojoRootIdentityMappingCollector.java @@ -75,7 +75,7 @@ public void identifierBridge(BoundPojoModelPathPropertyNode modelPath, } public IdentifierMappingImplementor buildAndContributeTo( - PojoTypeExtendedMappingCollector extendedMappingCollector, IdentityMappingMode mode) { + PojoTypeExtendedMappingCollector extendedMappingCollector, IdentityMappingMode mode) { applyDefaults( mode ); if ( documentIdSourceProperty != null ) { diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/definition/spi/PojoEntityLoadingBindingContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/definition/spi/PojoEntityLoadingBindingContext.java new file mode 100644 index 00000000000..6b541971736 --- /dev/null +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/definition/spi/PojoEntityLoadingBindingContext.java @@ -0,0 +1,28 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.pojo.loading.definition.spi; + +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingStrategy; +import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingStrategy; + +public interface PojoEntityLoadingBindingContext { + + /** + * @param expectedEntitySuperType An expected entity supertype that the strategy can handle. + * @param strategy The strategy for selection loading, used in particular during search. + * @param An expected entity supertype that the strategy can handle. + */ + void selectionLoadingStrategy(Class expectedEntitySuperType, PojoSelectionLoadingStrategy strategy); + + /** + * @param expectedEntitySuperType An expected entity supertype that the strategy can handle. + * @param strategy The strategy for mass loading, used in particular during mass indexing. + * @param An expected entity supertype that the strategy can handle. + */ + void massLoadingStrategy(Class expectedEntitySuperType, PojoMassLoadingStrategy strategy); + +} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoLoadingPlan.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoLoadingPlan.java index e02ead23d30..a0eb918ccfc 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoLoadingPlan.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoLoadingPlan.java @@ -26,7 +26,7 @@ static PojoLoadingPlan create(PojoSelectionLoadingContext context, PojoSelectionLoadingStrategy strategy = null; for ( PojoLoadingTypeContext typeContext : targetTypes ) { Optional> thisTypeStrategyOptional = - context.loadingStrategyOptional( typeContext ); + typeContext.selectionLoadingStrategyOptional(); if ( !thisTypeStrategyOptional.isPresent() ) { // One of the types cannot be loaded -- something is wrong. // Forget about the optimization, and fail later, diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoMultiLoaderLoadingPlan.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoMultiLoaderLoadingPlan.java index 941155c506d..62380887c17 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoMultiLoaderLoadingPlan.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoMultiLoaderLoadingPlan.java @@ -57,7 +57,7 @@ private PojoSingleLoaderLoadingPlan delegate(PojoLoad return delegate; } - PojoSelectionLoadingStrategy loadingStrategy = context.loadingStrategy( type ); + PojoSelectionLoadingStrategy loadingStrategy = type.selectionLoadingStrategy(); delegate = (PojoSingleLoaderLoadingPlan) planByLoadingStrategy.get( loadingStrategy ); if ( delegate != null ) { planByType.put( type, delegate ); diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoSingleLoaderLoadingPlan.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoSingleLoaderLoadingPlan.java index bb59746010f..5992cbaf83a 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoSingleLoaderLoadingPlan.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/impl/PojoSingleLoaderLoadingPlan.java @@ -51,7 +51,7 @@ public void loadBlocking(Deadline deadline) { return; } try { - PojoSelectionEntityLoader loader = loadingStrategy.createLoader( expectedTypes ); + PojoSelectionEntityLoader loader = loadingStrategy.createEntityLoader( expectedTypes, context ); singleConcreteTypeInEntityHierarchy = expectedTypes.size() == 1 && expectedTypes.iterator().next().isSingleConcreteTypeInEntityHierarchy(); loaded = loader.loadBlocking( identifiers, deadline ); @@ -106,7 +106,7 @@ public void clear() { * * @param The expected type for the entity instance. * @param expectedType The expected type for the entity instance. Must be one of the types passed - * to {@link PojoSelectionLoadingStrategy#createLoader(Set)} + * to {@link PojoSelectionLoadingStrategy#createEntityLoader(Set, PojoSelectionLoadingContext)} * when creating this loader. * @param loadedObject A loaded object, i.e. an element from {@link #loaded}. * @return The given {@code loadedObject} if is an instance of {@code expectedType} exactly (not an instance of a subtype). diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingIndexedTypeContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingSessionContext.java similarity index 52% rename from mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingIndexedTypeContext.java rename to mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingSessionContext.java index 8d1586d3b01..a23be5acf74 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/massindexing/impl/HibernateOrmMassIndexingIndexedTypeContext.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingSessionContext.java @@ -4,10 +4,12 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or . */ -package org.hibernate.search.mapper.orm.massindexing.impl; +package org.hibernate.search.mapper.pojo.loading.spi; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; +import org.hibernate.search.mapper.pojo.model.spi.PojoRuntimeIntrospector; -public interface HibernateOrmMassIndexingIndexedTypeContext extends LoadingTypeContext { +public interface PojoLoadingSessionContext { + + PojoRuntimeIntrospector runtimeIntrospector(); } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingTypeContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingTypeContext.java index d61a0a69c7e..5546d88bc65 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingTypeContext.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingTypeContext.java @@ -6,12 +6,29 @@ */ package org.hibernate.search.mapper.pojo.loading.spi; +import java.util.List; +import java.util.Optional; + import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; public interface PojoLoadingTypeContext { + String entityName(); + + String secondaryEntityName(); + PojoRawTypeIdentifier typeIdentifier(); + List> ascendingSuperTypes(); + boolean isSingleConcreteTypeInEntityHierarchy(); + PojoSelectionLoadingStrategy selectionLoadingStrategy(); + + Optional> selectionLoadingStrategyOptional(); + + PojoMassLoadingStrategy massLoadingStrategy(); + + Optional> massLoadingStrategyOptional(); + } diff --git a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/LoadingIndexedTypeContextProvider.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingTypeContextProvider.java similarity index 55% rename from mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/LoadingIndexedTypeContextProvider.java rename to mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingTypeContextProvider.java index a373ee3d22a..2daa5f20d3e 100644 --- a/mapper/orm/src/main/java/org/hibernate/search/mapper/orm/loading/impl/LoadingIndexedTypeContextProvider.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoLoadingTypeContextProvider.java @@ -4,13 +4,12 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or . */ -package org.hibernate.search.mapper.orm.loading.impl; +package org.hibernate.search.mapper.pojo.loading.spi; -import org.hibernate.search.mapper.orm.loading.spi.LoadingTypeContext; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; -public interface LoadingIndexedTypeContextProvider { +public interface PojoLoadingTypeContextProvider { - LoadingTypeContext forExactType(PojoRawTypeIdentifier typeIdentifier); + PojoLoadingTypeContext forExactType(PojoRawTypeIdentifier typeIdentifier); } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingEntityLoadingContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassEntityLoadingContext.java similarity index 55% rename from mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingEntityLoadingContext.java rename to mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassEntityLoadingContext.java index 94cb8d5109b..05339075e83 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingEntityLoadingContext.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassEntityLoadingContext.java @@ -4,24 +4,23 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or . */ -package org.hibernate.search.mapper.pojo.massindexing.spi; +package org.hibernate.search.mapper.pojo.loading.spi; import java.util.Set; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntitySink; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; +import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingSessionContext; /** - * The context passed to {@link PojoMassIndexingLoadingStrategy#createEntityLoader(PojoMassIndexingEntityLoadingContext)}. + * The context passed to {@link PojoMassLoadingStrategy#createEntityLoader(Set, PojoMassEntityLoadingContext)}. * * @param The type of loaded entities. */ -public interface PojoMassIndexingEntityLoadingContext { +public interface PojoMassEntityLoadingContext { /** - * @return The identifiers of the types of all entities that will be loaded by the entity loader. + * @return The parent, mapper-specific loading context. */ - Set> includedTypes(); + PojoMassLoadingContext parent(); /** * @param sessionContext The session context, used to create an indexer in particular. diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassIdentifierLoadingContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassIdentifierLoadingContext.java new file mode 100644 index 00000000000..bc823a5d192 --- /dev/null +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassIdentifierLoadingContext.java @@ -0,0 +1,31 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.pojo.loading.spi; + +/** + * The context passed to {@link PojoMassLoadingStrategy#createIdentifierLoader(java.util.Set, PojoMassIdentifierLoadingContext)}. + * + * @param The type of entity identifiers. + */ +public interface PojoMassIdentifierLoadingContext { + + /** + * @return The parent, mapper-specific loading context. + */ + PojoMassLoadingContext parent(); + + /** + * @return A sink that the loader will add loaded entities to. + */ + PojoMassIdentifierSink createSink(); + + /** + * @return The tenant identifier to use ({@code null} if none). + */ + String tenantIdentifier(); + +} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassLoadingContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassLoadingContext.java new file mode 100644 index 00000000000..e0c1a557110 --- /dev/null +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassLoadingContext.java @@ -0,0 +1,19 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.pojo.loading.spi; + +/** + * Context exposed to {@link PojoMassLoadingStrategy}. + *

+ * Mappers will generally need to cast this type to the mapper-specific subtype. + * @see PojoMassIdentifierLoadingContext#parent() + * @see PojoMassEntityLoadingContext#parent() + * @see PojoMassLoadingStrategy#groupingAllowed(PojoLoadingTypeContext, PojoMassLoadingContext) + */ +public interface PojoMassLoadingContext { + +} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassLoadingStrategy.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassLoadingStrategy.java new file mode 100644 index 00000000000..0577ec2a40d --- /dev/null +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoMassLoadingStrategy.java @@ -0,0 +1,59 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.pojo.loading.spi; + +import java.util.Set; + +/** + * A strategy for entity loading during mass indexing. + * + * @param The type of loaded entities. + * @param The type of entity identifiers. + */ +public interface PojoMassLoadingStrategy { + + /** + * @param obj Another strategy + * @return {@code true} if the other strategy targets the same entity hierarchy + * and can be used as a replacement for this one. + * {@code false} otherwise or when unsure. + */ + @Override + boolean equals(Object obj); + + /* + * Hashcode must be overridden to be consistent with equals. + */ + @Override + int hashCode(); + + /** + * @param type A type that Hibernate Search would like to load together with another one that uses the same strategy. + * @param context Mapper-specific loading context. + * @return {@code true} if this type + */ + boolean groupingAllowed(PojoLoadingTypeContext type, PojoMassLoadingContext context); + + /** + * @param expectedTypes The expected types of loaded entities. + * The types are guaranteed to be {@link PojoLoadingTypeContext#massLoadingStrategy() assigned this strategy}. + * @param context A context, used to retrieve information about the loading environment and options. + * @return An entity identifier loader. + */ + PojoMassIdentifierLoader createIdentifierLoader(Set> expectedTypes, + PojoMassIdentifierLoadingContext context); + + /** + * @param expectedTypes The expected types of loaded entities. + * The types are guaranteed to be {@link PojoLoadingTypeContext#massLoadingStrategy() assigned this strategy}. + * @param context A context, used to retrieve information about the loading environment and options. + * @return An entity loader. + */ + PojoMassEntityLoader createEntityLoader(Set> expectedTypes, + PojoMassEntityLoadingContext context); + +} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionEntityLoader.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionEntityLoader.java index cba034d0f54..5360f77f2d6 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionEntityLoader.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionEntityLoader.java @@ -36,7 +36,7 @@ public interface PojoSelectionEntityLoader { * but it means some timeouts in Hibernate Search will not work properly. * @return A list of entities, in the same order the references were given. * {@code null} is inserted when an object is not found or has an excluded types - * (see {@link PojoSelectionLoadingStrategy#createLoader(Set)}). + * (see {@link PojoSelectionLoadingStrategy#createEntityLoader(Set, PojoSelectionLoadingContext)}). */ List loadBlocking(List identifiers, Deadline deadline); diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionLoadingContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionLoadingContext.java index 97b3f7505cc..9fa05186acf 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionLoadingContext.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionLoadingContext.java @@ -6,11 +6,13 @@ */ package org.hibernate.search.mapper.pojo.loading.spi; -import java.util.Optional; -import java.util.Set; - import org.hibernate.search.mapper.pojo.model.spi.PojoRuntimeIntrospector; +/** + * Context passed {@link PojoMassLoadingStrategy}. + *

+ * Mappers will generally need to cast this type to the mapper-specific subtype. + */ public interface PojoSelectionLoadingContext { /** @@ -20,23 +22,4 @@ public interface PojoSelectionLoadingContext { PojoRuntimeIntrospector runtimeIntrospector(); - /** - * @param The type of entities that will have to be loaded. - * @param type The type of entities that will have to be loaded. - * @return A loading strategy. - * Note that different types with the same strategy will be grouped together and loaded with a single loader. - * @throws org.hibernate.search.util.common.SearchException if the given type cannot be loaded and thus has no loading strategy. - * @see PojoSelectionLoadingStrategy#createLoader(Set) - */ - PojoSelectionLoadingStrategy loadingStrategy(PojoLoadingTypeContext type); - - /** - * @param The type of entities that will have to be loaded. - * @param type The type of entities that will have to be loaded. - * @return A loading strategy, or {@link Optional#empty()} if the given type cannot be loaded and thus has no loading strategy. - * Note that different types with the same strategy will be grouped together and loaded with a single loader. - * @see PojoSelectionLoadingStrategy#createLoader(Set) - */ - Optional> loadingStrategyOptional(PojoLoadingTypeContext type); - } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionLoadingStrategy.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionLoadingStrategy.java index 57f49beb20e..e7791f522c3 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionLoadingStrategy.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/loading/spi/PojoSelectionLoadingStrategy.java @@ -32,9 +32,12 @@ public interface PojoSelectionLoadingStrategy { /** * @param expectedTypes The expected types of loaded objects. - * The types are guaranteed to be {@link PojoSelectionLoadingContext#loadingStrategy(PojoLoadingTypeContext) assigned this strategy}. + * The types are guaranteed to be {@link PojoLoadingTypeContext#selectionLoadingStrategy() assigned this strategy}. + * @param context + * * @return A loader. */ - PojoSelectionEntityLoader createLoader(Set> expectedTypes); + PojoSelectionEntityLoader createEntityLoader(Set> expectedTypes, + PojoSelectionLoadingContext context); } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/logging/impl/Log.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/logging/impl/Log.java index d77b8ae40bf..3cd7b9803f4 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/logging/impl/Log.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/logging/impl/Log.java @@ -975,4 +975,27 @@ SearchException invalidIndexedSuperTypeClasses( @FormatWith(CommaSeparatedClassesFormatter.class) Collection> invalidClasses, @FormatWith(CommaSeparatedClassesFormatter.class) Collection> validClasses); + @Message(id = ID_OFFSET + 154, + value = "No matching indexed entity type for name '%1$s'." + + " Either this is not the name of an entity type, or the entity type is not indexed in Hibernate Search." + + " Valid names for indexed entity types are: %2$s") + SearchException unknownEntityNameForIndexedEntityType(String invalidName, Collection validNames); + + @Message(id = ID_OFFSET + 155, + value = "Cannot load entities of type '%s': no selection loading strategy registered for this type.") + SearchException noSelectionLoadingStrategy(String entityName); + + @Message(id = ID_OFFSET + 156, + value = "Cannot load entities of type '%s': no mass loading strategy registered for this type.") + SearchException noMassLoadingStrategy(String entityName); + + @Message(id = ID_OFFSET + 157, + value = "Type mismatch when applying loading binder to type '%1$s': the binder expects the entity type to extend '%2$s'," + + " but entity type '%1$s' does not." + ) + SearchException loadingConfigurationTypeMismatch( + @FormatWith(MappableTypeModelFormatter.class) PojoRawTypeModel entityType, + @FormatWith(ClassFormatter.class) Class expectedSuperType); + + } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/building/impl/PojoMapper.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/building/impl/PojoMapper.java index 6ecddb18df9..44a541ff8db 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/building/impl/PojoMapper.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/building/impl/PojoMapper.java @@ -10,6 +10,7 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; +import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -281,7 +282,8 @@ private void mapIndexedType(PojoRawTypeModel indexedEntityType, Collections.emptyList() ); var extendedMappingCollector = delegate.createIndexedTypeExtendedMappingCollector( indexedEntityType, entityName ); - typeManagerContainerBuilder.addIndexed( indexedEntityType, entityName, identityMappingCollector, + typeManagerContainerBuilder.addIndexed( indexedEntityType, + entityName, entityTypeMetadata.getSecondaryEntityName(), identityMappingCollector, extendedMappingCollector, routingBridge, indexingProcessorBuilder, indexManagerBuilder ); collectIndexMapping( indexedEntityType, indexingProcessorBuilder ); } @@ -398,8 +400,17 @@ private void preBuildIndexed(PojoIndexedTypeManager.Builder builder, private void preBuildOtherMetadata(AbstractPojoTypeManager.Builder builder, PojoImplicitReindexingResolverBuildingHelper helper) { - builder.preBuildOtherMetadata( helper.isSingleConcreteTypeInEntityHierarchy( builder.typeModel ), - helper.runtimePathsBuildingHelper( builder.typeModel ).pathOrdinals() ); + PojoRawTypeModel typeModel = builder.typeModel; + var loadingBinderOptional = typeModel.ascendingSuperTypes() + .map( superType -> typeAdditionalMetadataProvider.get( superType ) + .getEntityTypeMetadata() + .map( PojoEntityTypeAdditionalMetadata::getLoadingBinder ) + .orElse( null ) ) + .filter( Objects::nonNull ) + .findFirst(); + builder.preBuildOtherMetadata( helper.isSingleConcreteTypeInEntityHierarchy( typeModel ), + helper.runtimePathsBuildingHelper( typeModel ).pathOrdinals(), + loadingBinderOptional ); } private void preBuildIfContained(PojoRawTypeModel entityType, @@ -426,7 +437,8 @@ private void preBuildIfContained(PojoRawTypeModel entityType, var extendedMappingCollector = delegate.createContainedTypeExtendedMappingCollector( entityType, entityName ); var identityMappingCollector = new PojoRootIdentityMappingCollector<>( entityType, mappingHelper, Optional.empty(), providedIdentifierBridge ); - var builder = typeManagerContainerBuilder.addContained( entityType, entityName, identityMappingCollector, + var builder = typeManagerContainerBuilder.addContained( entityType, + entityName, entityTypeMetadata.getSecondaryEntityName(), identityMappingCollector, extendedMappingCollector ); collectIndexMapping( entityType, identityMappingCollector.toMappingCollectorRootNode() ); diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/building/spi/PojoTypeExtendedMappingCollector.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/building/spi/PojoTypeExtendedMappingCollector.java index 2b2b512f0dc..af5999b6354 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/building/spi/PojoTypeExtendedMappingCollector.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/building/spi/PojoTypeExtendedMappingCollector.java @@ -6,7 +6,9 @@ */ package org.hibernate.search.mapper.pojo.mapping.building.spi; +import org.hibernate.search.engine.environment.bean.spi.ParameterizedBeanReference; import org.hibernate.search.mapper.pojo.identity.spi.IdentifierMapping; +import org.hibernate.search.mapper.pojo.loading.definition.spi.PojoEntityLoadingBindingContext; import org.hibernate.search.mapper.pojo.model.path.spi.PojoPathFilter; import org.hibernate.search.mapper.pojo.model.spi.PojoPropertyModel; @@ -34,4 +36,16 @@ default void dirtyContainingAssociationFilter(PojoPathFilter filter) { // Default implementation: ignore this information. } + /** + * Apply a mapper-specific loading binder. + *

+ * This is guaranteed to be called very late, + * and in particular after {@link #documentIdSourceProperty(PojoPropertyModel)}. + * + * @param binder The binder passed to + * {@link org.hibernate.search.mapper.pojo.model.additionalmetadata.building.spi.PojoAdditionalMetadataCollectorEntityTypeNode#loadingBinder(ParameterizedBeanReference)}. + * @param context A context to get information and bind loading, e.g. set loading strategies. + */ + void applyLoadingBinder(Object binder, PojoEntityLoadingBindingContext context); + } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/AbstractPojoTypeManager.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/AbstractPojoTypeManager.java index dc712a8042b..687b27dc6cc 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/AbstractPojoTypeManager.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/AbstractPojoTypeManager.java @@ -7,8 +7,10 @@ package org.hibernate.search.mapper.pojo.mapping.impl; import java.lang.invoke.MethodHandles; +import java.util.List; import java.util.Optional; import java.util.function.Supplier; +import java.util.stream.Collectors; import org.hibernate.search.engine.common.EntityReference; import org.hibernate.search.mapper.pojo.automaticindexing.impl.PojoImplicitReindexingResolver; @@ -17,6 +19,9 @@ import org.hibernate.search.mapper.pojo.identity.impl.IdentifierMappingImplementor; import org.hibernate.search.mapper.pojo.identity.impl.IdentityMappingMode; import org.hibernate.search.mapper.pojo.identity.impl.PojoRootIdentityMappingCollector; +import org.hibernate.search.mapper.pojo.loading.definition.spi.PojoEntityLoadingBindingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingStrategy; +import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingStrategy; import org.hibernate.search.mapper.pojo.logging.impl.Log; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoTypeExtendedMappingCollector; import org.hibernate.search.mapper.pojo.model.path.impl.PojoPathOrdinals; @@ -37,26 +42,36 @@ * @param The identifier type for the entity type. * @param The entity type. */ -public class AbstractPojoTypeManager +public abstract class AbstractPojoTypeManager implements AutoCloseable, ToStringTreeAppendable, PojoWorkTypeContext { private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); protected final PojoRawTypeIdentifier typeIdentifier; + private final List> ascendingSuperTypes; protected final PojoCaster caster; protected final String entityName; + protected final String secondaryEntityName; private final boolean singleConcreteTypeInEntityHierarchy; protected final IdentifierMappingImplementor identifierMapping; private final PojoPathOrdinals pathOrdinals; protected final PojoImplicitReindexingResolver reindexingResolver; + private final Optional> selectionLoadingStrategyOptional; + private final Optional> massLoadingStrategyOptional; public AbstractPojoTypeManager(Builder builder, IdentifierMappingImplementor identifierMapping) { this.typeIdentifier = builder.typeModel.typeIdentifier(); + this.ascendingSuperTypes = builder.typeModel.ascendingSuperTypes() + .map( PojoRawTypeModel::typeIdentifier ) + .collect( Collectors.toUnmodifiableList() ); this.caster = builder.typeModel.caster(); this.entityName = builder.entityName; + this.secondaryEntityName = builder.secondaryEntityName; this.singleConcreteTypeInEntityHierarchy = builder.singleConcreteTypeInEntityHierarchy; this.identifierMapping = identifierMapping; this.pathOrdinals = builder.pathOrdinals; this.reindexingResolver = builder.reindexingResolver; + this.selectionLoadingStrategyOptional = Optional.ofNullable( builder.selectionLoadingStrategy ); + this.massLoadingStrategyOptional = Optional.ofNullable( builder.massLoadingStrategy ); } @Override @@ -91,7 +106,9 @@ public void appendTo(ToStringTreeAppender appender) { appender.attribute( "entityName", entityName ) .attribute( "typeIdentifier", typeIdentifier ) .attribute( "identifierMapping", identifierMapping ) - .attribute( "reindexingResolver", reindexingResolver ); + .attribute( "reindexingResolver", reindexingResolver ) + .attribute( "selectionLoadingStrategy", selectionLoadingStrategyOptional.orElse( null ) ) + .attribute( "massLoadingStrategy", massLoadingStrategyOptional.orElse( null ) ); } @Override @@ -99,6 +116,11 @@ public final PojoRawTypeIdentifier typeIdentifier() { return typeIdentifier; } + @Override + public final List> ascendingSuperTypes() { + return ascendingSuperTypes; + } + @Override public Optional> asIndexed() { return Optional.empty(); @@ -114,6 +136,23 @@ public String entityName() { return entityName; } + @Override + public String secondaryEntityName() { + return secondaryEntityName; + } + + public String name() { + return entityName; + } + + public Class javaClass() { + return typeIdentifier.javaClass(); + } + + public boolean loadingAvailable() { + return selectionLoadingStrategyOptional.isPresent(); + } + @Override public final boolean isSingleConcreteTypeInEntityHierarchy() { return singleConcreteTypeInEntityHierarchy; @@ -167,9 +206,32 @@ public final void resolveEntitiesToReindex(PojoReindexingCollector collector, Po } } + @Override + public PojoSelectionLoadingStrategy selectionLoadingStrategy() { + return selectionLoadingStrategyOptional() + .orElseThrow( () -> log.noSelectionLoadingStrategy( entityName ) ); + } + + @Override + public Optional> selectionLoadingStrategyOptional() { + return selectionLoadingStrategyOptional; + } + + @Override + public PojoMassLoadingStrategy massLoadingStrategy() { + return massLoadingStrategyOptional() + .orElseThrow( () -> log.noMassLoadingStrategy( entityName ) ); + } + + @Override + public Optional> massLoadingStrategyOptional() { + return massLoadingStrategyOptional; + } + public abstract static class Builder { public final PojoRawTypeModel typeModel; private final String entityName; + private final String secondaryEntityName; private PojoRootIdentityMappingCollector identityMappingCollector; protected IdentifierMappingImplementor identifierMapping; @@ -178,13 +240,16 @@ public abstract static class Builder { private Boolean singleConcreteTypeInEntityHierarchy; private PojoPathOrdinals pathOrdinals; + private PojoSelectionLoadingStrategy selectionLoadingStrategy; + private PojoMassLoadingStrategy massLoadingStrategy; protected boolean closed = false; - Builder(PojoRawTypeModel typeModel, String entityName, + Builder(PojoRawTypeModel typeModel, String entityName, String secondaryEntityName, PojoRootIdentityMappingCollector identityMappingCollector) { this.typeModel = typeModel; this.entityName = entityName; + this.secondaryEntityName = secondaryEntityName; this.identityMappingCollector = identityMappingCollector; } @@ -226,9 +291,40 @@ public void reindexingResolver(PojoImplicitReindexingResolver reindexingResol } public void preBuildOtherMetadata(boolean singleConcreteTypeInEntityHierarchy, - PojoPathOrdinals pathOrdinals) { + PojoPathOrdinals pathOrdinals, Optional loadingBinderOptional) { this.singleConcreteTypeInEntityHierarchy = singleConcreteTypeInEntityHierarchy; this.pathOrdinals = pathOrdinals; + preBuildLoadingConfiguration( loadingBinderOptional ); + } + + private void preBuildLoadingConfiguration(Optional loadingBinderOptional) { + if ( loadingBinderOptional.isEmpty() ) { + return; + } + extendedMappingCollector().applyLoadingBinder( loadingBinderOptional.get(), + new PojoEntityLoadingBindingContext() { + @Override + @SuppressWarnings("unchecked") // Checked using reflection + public void selectionLoadingStrategy(Class expectedEntitySuperType, + PojoSelectionLoadingStrategy strategy) { + checkEntitySuperType( expectedEntitySuperType ); + selectionLoadingStrategy = (PojoSelectionLoadingStrategy) strategy; + } + + @Override + @SuppressWarnings("unchecked") // Checked using reflection + public void massLoadingStrategy(Class expectedEntitySuperType, + PojoMassLoadingStrategy strategy) { + checkEntitySuperType( expectedEntitySuperType ); + massLoadingStrategy = (PojoMassLoadingStrategy) strategy; + } + + private void checkEntitySuperType(Class expectedEntitySuperType) { + if ( !expectedEntitySuperType.isAssignableFrom( typeModel.typeIdentifier().javaClass() ) ) { + throw log.loadingConfigurationTypeMismatch( typeModel, expectedEntitySuperType ); + } + } + } ); } public abstract AbstractPojoTypeManager build(); diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoContainedTypeManager.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoContainedTypeManager.java index 3438d4603f9..faf1121aabc 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoContainedTypeManager.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoContainedTypeManager.java @@ -33,10 +33,10 @@ public Optional> asContained() { public static class Builder extends AbstractPojoTypeManager.Builder { private final PojoContainedTypeExtendedMappingCollector extendedMappingCollector; - Builder(PojoRawTypeModel typeModel, String entityName, + Builder(PojoRawTypeModel typeModel, String entityName, String secondaryEntityName, PojoRootIdentityMappingCollector identityMappingCollector, PojoContainedTypeExtendedMappingCollector extendedMappingCollector) { - super( typeModel, entityName, identityMappingCollector ); + super( typeModel, entityName, secondaryEntityName, identityMappingCollector ); this.extendedMappingCollector = extendedMappingCollector; } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoIndexedTypeManager.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoIndexedTypeManager.java index 264c70428be..f1f5adba7de 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoIndexedTypeManager.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoIndexedTypeManager.java @@ -21,6 +21,7 @@ import org.hibernate.search.engine.mapper.mapping.building.spi.MappedIndexManagerBuilder; import org.hibernate.search.engine.mapper.mapping.spi.MappedIndexManager; import org.hibernate.search.engine.mapper.scope.spi.MappedIndexScopeBuilder; +import org.hibernate.search.engine.search.projection.spi.ProjectionMappedTypeContext; import org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoIndexingDependencyCollectorTypeNode; import org.hibernate.search.mapper.pojo.automaticindexing.impl.PojoImplicitReindexingResolver; import org.hibernate.search.mapper.pojo.bridge.RoutingBridge; @@ -52,7 +53,7 @@ */ public class PojoIndexedTypeManager extends AbstractPojoTypeManager implements PojoWorkIndexedTypeContext, PojoScopeIndexedTypeContext, - PojoMassIndexingIndexedTypeContext { + PojoMassIndexingIndexedTypeContext, ProjectionMappedTypeContext { private final DocumentRouter documentRouter; private final PojoIndexingProcessor processor; private final MappedIndexManager indexManager; @@ -78,13 +79,10 @@ public void close() { @Override public void appendTo(ToStringTreeAppender appender) { - appender.attribute( "entityName", entityName ) - .attribute( "typeIdentifier", typeIdentifier ) - .attribute( "indexManager", indexManager ) - .attribute( "identifierMapping", identifierMapping ) - .attribute( "documentRouter", documentRouter ) + super.appendTo( appender ); + appender.attribute( "documentRouter", documentRouter ) .attribute( "processor", processor ) - .attribute( "reindexingResolver", reindexingResolver ); + .attribute( "indexManager", indexManager ); } @Override @@ -154,13 +152,13 @@ public static class Builder extends AbstractPojoTypeManager.Builder { private MappedIndexManagerBuilder indexManagerBuilder; private MappedIndexManager indexManager; - Builder(PojoRawTypeModel typeModel, String entityName, + Builder(PojoRawTypeModel typeModel, String entityName, String secondaryEntityName, PojoRootIdentityMappingCollector identityMappingCollector, PojoIndexedTypeExtendedMappingCollector extendedMappingCollector, BoundRoutingBridge routingBridge, PojoIndexingProcessorOriginalTypeNodeBuilder indexingProcessorBuilder, MappedIndexManagerBuilder indexManagerBuilder) { - super( typeModel, entityName, identityMappingCollector ); + super( typeModel, entityName, secondaryEntityName, identityMappingCollector ); this.extendedMappingCollector = extendedMappingCollector; this.routingBridge = routingBridge; this.indexManagerBuilder = indexManagerBuilder; diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoMappingDelegateImpl.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoMappingDelegateImpl.java index c0eda67f700..2ad7b2a386c 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoMappingDelegateImpl.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoMappingDelegateImpl.java @@ -17,8 +17,10 @@ import org.hibernate.search.engine.environment.thread.spi.ThreadPoolProvider; import org.hibernate.search.engine.reporting.FailureHandler; import org.hibernate.search.engine.search.projection.definition.spi.ProjectionRegistry; +import org.hibernate.search.engine.search.projection.spi.ProjectionMappedTypeContext; import org.hibernate.search.engine.tenancy.spi.TenancyMode; import org.hibernate.search.mapper.pojo.common.spi.PojoEntityReferenceFactoryDelegate; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContextProvider; import org.hibernate.search.mapper.pojo.logging.impl.Log; import org.hibernate.search.mapper.pojo.mapping.spi.PojoMappingDelegate; import org.hibernate.search.mapper.pojo.mapping.spi.PojoRawTypeIdentifierResolver; @@ -85,6 +87,11 @@ public PojoRawTypeIdentifierResolver typeIdentifierResolver() { return typeManagers; } + @Override + public PojoLoadingTypeContextProvider typeContextProvider() { + return typeManagers; + } + @Override public TenancyMode tenancyMode() { return tenancyMode; @@ -95,6 +102,11 @@ public ProjectionRegistry projectionRegistry() { return searchQueryElementRegistry; } + @Override + public ProjectionMappedTypeContext mappedTypeContext(String name) { + return typeManagers.indexedByEntityName().getOrFail( name ); + } + @Override public PojoEntityReferenceFactory createEntityReferenceFactory(PojoEntityReferenceFactoryDelegate delegate) { return new PojoEntityReferenceFactory( delegate, typeManagers ); @@ -128,7 +140,7 @@ public PojoScopeDelegate createPojoSc for ( PojoIndexedTypeManager typeContext : typeContexts ) { Class actualJavaType = typeContext.typeIdentifier().javaClass(); if ( !expectedSuperType.isAssignableFrom( actualJavaType ) ) { - throw log.invalidEntitySuperType( typeContext.entityName(), expectedSuperType, actualJavaType ); + throw log.invalidEntitySuperType( typeContext.name(), expectedSuperType, actualJavaType ); } } return PojoScopeDelegateImpl.create( diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoTypeManagerContainer.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoTypeManagerContainer.java index 8a99f084f72..819950f1f79 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoTypeManagerContainer.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/impl/PojoTypeManagerContainer.java @@ -18,6 +18,7 @@ import org.hibernate.search.engine.mapper.mapping.building.spi.MappedIndexManagerBuilder; import org.hibernate.search.mapper.pojo.bridge.binding.impl.BoundRoutingBridge; import org.hibernate.search.mapper.pojo.identity.impl.PojoRootIdentityMappingCollector; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContextProvider; import org.hibernate.search.mapper.pojo.logging.impl.Log; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoContainedTypeExtendedMappingCollector; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoIndexedTypeExtendedMappingCollector; @@ -34,7 +35,8 @@ import org.hibernate.search.util.common.logging.impl.LoggerFactory; public class PojoTypeManagerContainer - implements AutoCloseable, PojoWorkTypeContextProvider, PojoScopeTypeContextProvider, PojoRawTypeIdentifierResolver { + implements AutoCloseable, PojoWorkTypeContextProvider, PojoScopeTypeContextProvider, + PojoRawTypeIdentifierResolver, PojoLoadingTypeContextProvider { private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); public static Builder builder() { @@ -44,6 +46,7 @@ public static Builder builder() { private final KeyValueProvider, AbstractPojoTypeManager> byExactType; private final KeyValueProvider, PojoIndexedTypeManager> indexedByExactType; private final KeyValueProvider> byEntityName; + private final KeyValueProvider> indexedByEntityName; private final KeyValueProvider> typeIdentifierByEntityName; private final KeyValueProvider> typeIdentifierBySecondaryEntityName; @@ -66,6 +69,7 @@ private PojoTypeManagerContainer(Builder builder) { Map, Set>> bySuperTypeContent = new LinkedHashMap<>(); Map, Set>> indexedBySuperTypeContent = new LinkedHashMap<>(); Map> byEntityNameContent = new LinkedHashMap<>(); + Map> indexedByEntityNameContent = new LinkedHashMap<>(); for ( PojoIndexedTypeManager.Builder typeManagerBuilder : builder.indexed.values() ) { PojoRawTypeModel typeModel = typeManagerBuilder.typeModel; PojoRawTypeIdentifier typeIdentifier = typeModel.typeIdentifier(); @@ -75,7 +79,9 @@ private PojoTypeManagerContainer(Builder builder) { byExactTypeContent.put( typeIdentifier, typeManager ); indexedByExactTypeContent.put( typeIdentifier, typeManager ); - byEntityNameContent.put( typeManager.entityName(), typeManager ); + String entityName = typeManager.name(); + byEntityNameContent.put( entityName, typeManager ); + indexedByEntityNameContent.put( entityName, typeManager ); registerSuperTypes( bySuperTypeContent, typeModel, typeManager ); registerSuperTypes( indexedBySuperTypeContent, typeModel, typeManager ); @@ -88,7 +94,7 @@ private PojoTypeManagerContainer(Builder builder) { byExactTypeContent.put( typeIdentifier, typeManager ); - byEntityNameContent.put( typeManager.entityName(), typeManager ); + byEntityNameContent.put( typeManager.name(), typeManager ); registerSuperTypes( bySuperTypeContent, typeModel, typeManager ); } @@ -96,6 +102,8 @@ private PojoTypeManagerContainer(Builder builder) { this.indexedByExactType = new KeyValueProvider<>( indexedByExactTypeContent, log::unknownTypeIdentifierForIndexedEntityType ); this.byEntityName = new KeyValueProvider<>( byEntityNameContent, log::unknownEntityNameForMappedEntityType ); + this.indexedByEntityName = + new KeyValueProvider<>( indexedByEntityNameContent, log::unknownEntityNameForIndexedEntityType ); indexedBySuperTypeContent.replaceAll( (k, v) -> Collections.unmodifiableSet( v ) ); this.indexedBySuperType = KeyValueProvider.createWithMultiKeyException( indexedBySuperTypeContent, log::invalidIndexedSuperTypes ); @@ -256,6 +264,10 @@ public PojoRawTypeIdentifier nonInterfaceSuperTypeIdentifierForClass(Clas return byEntityName; } + public KeyValueProvider> indexedByEntityName() { + return indexedByEntityName; + } + @Override public KeyValueProvider> typeIdentifierByEntityName() { return typeIdentifierByEntityName; @@ -293,22 +305,26 @@ public static class Builder { private Builder() { } - public PojoIndexedTypeManager.Builder addIndexed(PojoRawTypeModel typeModel, String entityName, + public PojoIndexedTypeManager.Builder addIndexed(PojoRawTypeModel typeModel, + String entityName, String secondaryEntityName, PojoRootIdentityMappingCollector identityMappingCollector, PojoIndexedTypeExtendedMappingCollector extendedMappingCollector, BoundRoutingBridge routingBridge, PojoIndexingProcessorOriginalTypeNodeBuilder indexingProcessorBuilder, MappedIndexManagerBuilder indexManagerBuilder) { - var builder = new PojoIndexedTypeManager.Builder<>( typeModel, entityName, identityMappingCollector, + var builder = new PojoIndexedTypeManager.Builder<>( typeModel, + entityName, secondaryEntityName, identityMappingCollector, extendedMappingCollector, routingBridge, indexingProcessorBuilder, indexManagerBuilder ); indexed.put( typeModel, builder ); return builder; } - public PojoContainedTypeManager.Builder addContained(PojoRawTypeModel typeModel, String entityName, + public PojoContainedTypeManager.Builder addContained(PojoRawTypeModel typeModel, + String entityName, String secondaryEntityName, PojoRootIdentityMappingCollector identityMappingCollector, PojoContainedTypeExtendedMappingCollector extendedMappingCollector) { - var builder = new PojoContainedTypeManager.Builder<>( typeModel, entityName, identityMappingCollector, + var builder = new PojoContainedTypeManager.Builder<>( typeModel, + entityName, secondaryEntityName, identityMappingCollector, extendedMappingCollector ); contained.put( typeModel, builder ); return builder; diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/spi/AbstractPojoMappingImplementor.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/spi/AbstractPojoMappingImplementor.java index ab4d1f40f57..c9bd2ef62ec 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/spi/AbstractPojoMappingImplementor.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/spi/AbstractPojoMappingImplementor.java @@ -20,6 +20,7 @@ import org.hibernate.search.engine.mapper.mapping.spi.MappingStartContext; import org.hibernate.search.engine.reporting.FailureHandler; import org.hibernate.search.engine.search.projection.definition.spi.ProjectionRegistry; +import org.hibernate.search.engine.search.projection.spi.ProjectionMappedTypeContext; import org.hibernate.search.mapper.pojo.bridge.runtime.IdentifierBridgeToDocumentIdentifierContext; import org.hibernate.search.mapper.pojo.bridge.runtime.ValueBridgeToIndexedValueContext; import org.hibernate.search.mapper.pojo.bridge.runtime.impl.IdentifierBridgeToDocumentIdentifierContextImpl; @@ -130,10 +131,15 @@ public final ToDocumentValueConvertContext toDocumentValueConvertContext() { } @Override - public ProjectionRegistry projectionRegistry() { + public final ProjectionRegistry projectionRegistry() { return delegate.projectionRegistry(); } + @Override + public final ProjectionMappedTypeContext mappedTypeContext(String mappedTypeName) { + return delegate.mappedTypeContext( mappedTypeName ); + } + @Override public final IdentifierBridgeToDocumentIdentifierContext identifierBridgeToDocumentIdentifierContext() { return toDocumentIdentifierContext; @@ -173,5 +179,4 @@ protected final PojoMappingDelegate delegate() { protected void doStop() { } - } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/spi/PojoMappingDelegate.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/spi/PojoMappingDelegate.java index 93da0a69047..18e2c604f55 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/spi/PojoMappingDelegate.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/mapping/spi/PojoMappingDelegate.java @@ -16,8 +16,10 @@ import org.hibernate.search.engine.environment.thread.spi.ThreadPoolProvider; import org.hibernate.search.engine.reporting.FailureHandler; import org.hibernate.search.engine.search.projection.definition.spi.ProjectionRegistry; +import org.hibernate.search.engine.search.projection.spi.ProjectionMappedTypeContext; import org.hibernate.search.engine.tenancy.spi.TenancyMode; import org.hibernate.search.mapper.pojo.common.spi.PojoEntityReferenceFactoryDelegate; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContextProvider; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; import org.hibernate.search.mapper.pojo.scope.spi.PojoScopeDelegate; import org.hibernate.search.mapper.pojo.scope.spi.PojoScopeMappingContext; @@ -41,10 +43,14 @@ public interface PojoMappingDelegate extends AutoCloseable { PojoRawTypeIdentifierResolver typeIdentifierResolver(); + PojoLoadingTypeContextProvider typeContextProvider(); + TenancyMode tenancyMode(); ProjectionRegistry projectionRegistry(); + ProjectionMappedTypeContext mappedTypeContext(String name); + EntityReferenceFactory createEntityReferenceFactory(PojoEntityReferenceFactoryDelegate delegate); /** diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoDefaultMassIndexer.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoDefaultMassIndexer.java index 5c0dab21183..798f5bac56d 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoDefaultMassIndexer.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoDefaultMassIndexer.java @@ -46,7 +46,7 @@ public void afterExecution(Context context) { } }; - private final PojoMassIndexingContext indexingContext; + private final PojoMassIndexingContext massIndexingContext; private final PojoMassIndexingMappingContext mappingContext; private final PojoMassIndexingTypeContextProvider typeContextProvider; private final Set> targetedIndexedTypes; @@ -67,14 +67,14 @@ public void afterExecution(Context context) { private MassIndexingMonitor monitor; private MassIndexingEnvironment environment; - public PojoDefaultMassIndexer(PojoMassIndexingContext indexingContext, + public PojoDefaultMassIndexer(PojoMassIndexingContext massIndexingContext, PojoMassIndexingMappingContext mappingContext, PojoMassIndexingTypeContextProvider typeContextProvider, Set> targetedIndexedTypes, PojoScopeSchemaManager scopeSchemaManager, Set tenantIds, PojoScopeDelegate pojoScopeDelegate) { - this.indexingContext = indexingContext; + this.massIndexingContext = massIndexingContext; this.mappingContext = mappingContext; this.typeContextProvider = typeContextProvider; this.targetedIndexedTypes = targetedIndexedTypes; @@ -166,7 +166,7 @@ public void startAndWait() throws InterruptedException { private PojoMassIndexingBatchCoordinator createCoordinator() { List> typeGroupsToIndex = PojoMassIndexingIndexedTypeGroup.disjoint( - indexingContext, mappingContext, typeContextProvider, targetedIndexedTypes + mappingContext, typeContextProvider, targetedIndexedTypes, massIndexingContext ); typesToIndexInParallel = Math.min( typesToIndexInParallel, typeGroupsToIndex.size() ); PojoMassIndexingNotifier notifier = new PojoMassIndexingNotifier( @@ -182,7 +182,8 @@ private PojoMassIndexingBatchCoordinator createCoordinator() { return new PojoMassIndexingBatchCoordinator( mappingContext, notifier, - typeGroupsToIndex, scopeSchemaManager, + typeGroupsToIndex, massIndexingContext, + scopeSchemaManager, tenantIds, pojoScopeDelegate, resolvedMassIndexingEnvironment(), typesToIndexInParallel, documentBuilderThreads, diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchCoordinator.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchCoordinator.java index a478ec0800f..0909c001888 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchCoordinator.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchCoordinator.java @@ -21,6 +21,7 @@ import org.hibernate.search.engine.reporting.spi.RootFailureCollector; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexerAgent; +import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingMappingContext; import org.hibernate.search.mapper.pojo.reporting.impl.PojoEventContextMessages; import org.hibernate.search.mapper.pojo.schema.management.spi.PojoScopeSchemaManager; @@ -42,6 +43,7 @@ public class PojoMassIndexingBatchCoordinator extends PojoMassIndexingFailureHan private final PojoMassIndexingMappingContext mappingContext; private final PojoMassIndexerAgentStartContextImpl agentStartContext; private final List> typeGroupsToIndex; + private final PojoMassIndexingContext massIndexingContext; private final PojoScopeSchemaManager scopeSchemaManager; private final Set tenantIds; @@ -61,6 +63,7 @@ public class PojoMassIndexingBatchCoordinator extends PojoMassIndexingFailureHan public PojoMassIndexingBatchCoordinator(PojoMassIndexingMappingContext mappingContext, PojoMassIndexingNotifier notifier, List> typeGroupsToIndex, + PojoMassIndexingContext massIndexingContext, PojoScopeSchemaManager scopeSchemaManager, Set tenantIds, PojoScopeDelegate pojoScopeDelegate, @@ -74,6 +77,7 @@ public PojoMassIndexingBatchCoordinator(PojoMassIndexingMappingContext mappingCo this.scopeSchemaManager = scopeSchemaManager; this.tenantIds = tenantIds; this.pojoScopeDelegate = pojoScopeDelegate; + this.massIndexingContext = massIndexingContext; this.typesToIndexInParallel = typesToIndexInParallel; this.documentBuilderThreads = documentBuilderThreads; this.mergeSegmentsOnFinish = mergeSegmentsOnFinish; @@ -194,7 +198,7 @@ private void doBatchWork() throws InterruptedException { PojoMassIndexingIndexedTypeGroup typeGroup, SessionContext context) { return new PojoMassIndexingBatchIndexingWorkspace<>( mappingContext, getNotifier(), getMassIndexingEnvironment(), typeGroup, - typeGroup.loadingStrategy(), + typeGroup.loadingStrategy(), massIndexingContext, documentBuilderThreads, context.tenantIdentifier() ); diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchIndexingWorkspace.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchIndexingWorkspace.java index 2307dfba61a..8e34cf7af83 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchIndexingWorkspace.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingBatchIndexingWorkspace.java @@ -13,9 +13,10 @@ import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingStrategy; import org.hibernate.search.mapper.pojo.logging.impl.Log; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingLoadingStrategy; +import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingMappingContext; import org.hibernate.search.util.common.AssertionFailure; import org.hibernate.search.util.common.impl.Futures; @@ -39,7 +40,8 @@ public class PojoMassIndexingBatchIndexingWorkspace extends PojoMassIndexi private final List> indexingFutures = new ArrayList<>(); private final PojoMassIndexingMappingContext mappingContext; private final PojoMassIndexingIndexedTypeGroup typeGroup; - private final PojoMassIndexingLoadingStrategy loadingStrategy; + private final PojoMassLoadingStrategy loadingStrategy; + private final PojoMassIndexingContext massIndexingContext; private final int entityExtractingThreads; private final String tenantId; @@ -48,12 +50,14 @@ public class PojoMassIndexingBatchIndexingWorkspace extends PojoMassIndexi PojoMassIndexingNotifier notifier, MassIndexingEnvironment environment, PojoMassIndexingIndexedTypeGroup typeGroup, - PojoMassIndexingLoadingStrategy loadingStrategy, + PojoMassLoadingStrategy loadingStrategy, + PojoMassIndexingContext massIndexingContext, int entityExtractingThreads, String tenantId) { super( notifier, environment ); this.mappingContext = mappingContext; this.typeGroup = typeGroup; this.loadingStrategy = loadingStrategy; + this.massIndexingContext = massIndexingContext; this.entityExtractingThreads = entityExtractingThreads; this.tenantId = tenantId; } @@ -100,8 +104,9 @@ private void cancelPendingTasks() { private void startProducingPrimaryKeys(PojoProducerConsumerQueue> identifierQueue) { final Runnable runnable = new PojoMassIndexingEntityIdentifierLoadingRunnable<>( getNotifier(), - getMassIndexingEnvironment(), - typeGroup, loadingStrategy, identifierQueue, tenantId + massIndexingContext, getMassIndexingEnvironment(), + typeGroup, loadingStrategy, + identifierQueue, tenantId ); //execIdentifiersLoader has size 1 and is not configurable: ensures the list is consistent as produced by one transaction final ThreadPoolExecutor identifierProducingExecutor = mappingContext.threadPoolProvider().newFixedThreadPool( @@ -119,8 +124,9 @@ private void startProducingPrimaryKeys(PojoProducerConsumerQueue> identi private void startIndexing(PojoProducerConsumerQueue> identifierQueue) { final Runnable runnable = new PojoMassIndexingEntityLoadingRunnable<>( getNotifier(), - getMassIndexingEnvironment(), - typeGroup, loadingStrategy, identifierQueue, tenantId + massIndexingContext, getMassIndexingEnvironment(), + typeGroup, loadingStrategy, + identifierQueue, tenantId ); final ThreadPoolExecutor indexingExecutor = mappingContext.threadPoolProvider().newFixedThreadPool( entityExtractingThreads, diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityIdentifierLoadingRunnable.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityIdentifierLoadingRunnable.java index c9dff20bad7..857e977636b 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityIdentifierLoadingRunnable.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityIdentifierLoadingRunnable.java @@ -9,15 +9,15 @@ import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.List; -import java.util.Set; import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoadingContext; import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierSink; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingStrategy; import org.hibernate.search.mapper.pojo.logging.impl.Log; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingIdentifierLoadingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingLoadingStrategy; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; +import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; import org.hibernate.search.util.common.logging.impl.LoggerFactory; public class PojoMassIndexingEntityIdentifierLoadingRunnable @@ -25,17 +25,20 @@ public class PojoMassIndexingEntityIdentifierLoadingRunnable private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); + private final PojoMassIndexingContext massIndexingContext; private final PojoMassIndexingIndexedTypeGroup typeGroup; - private final PojoMassIndexingLoadingStrategy loadingStrategy; + private final PojoMassLoadingStrategy loadingStrategy; private final PojoProducerConsumerQueue> identifierQueue; private final String tenantId; private final MassIndexingEnvironment.EntityIdentifierLoadingContext identifierLoadingContext; public PojoMassIndexingEntityIdentifierLoadingRunnable(PojoMassIndexingNotifier notifier, - MassIndexingEnvironment environment, PojoMassIndexingIndexedTypeGroup typeGroup, - PojoMassIndexingLoadingStrategy loadingStrategy, + PojoMassIndexingContext massIndexingContext, MassIndexingEnvironment environment, + PojoMassIndexingIndexedTypeGroup typeGroup, + PojoMassLoadingStrategy loadingStrategy, PojoProducerConsumerQueue> identifierQueue, String tenantId) { super( notifier, environment ); + this.massIndexingContext = massIndexingContext; this.loadingStrategy = loadingStrategy; this.typeGroup = typeGroup; this.identifierQueue = identifierQueue; @@ -48,7 +51,8 @@ public PojoMassIndexingEntityIdentifierLoadingRunnable(PojoMassIndexingNotifier protected void runWithFailureHandler() throws InterruptedException { log.trace( "started" ); LoadingContext context = new LoadingContext(); - try ( PojoMassIdentifierLoader loader = loadingStrategy.createIdentifierLoader( context ) ) { + try ( PojoMassIdentifierLoader loader = + loadingStrategy.createIdentifierLoader( typeGroup.includedTypes(), context ) ) { long totalCount = loader.totalCount(); getNotifier().reportAddedTotalCount( totalCount ); do { @@ -89,12 +93,12 @@ protected String operationName() { return log.massIndexerFetchingIds( typeGroup.notifiedGroupName() ); } - private class LoadingContext implements PojoMassIndexingIdentifierLoadingContext { + private class LoadingContext implements PojoMassIdentifierLoadingContext { private boolean done = false; @Override - public Set> includedTypes() { - return typeGroup.includedTypesIdentifiers(); + public PojoMassLoadingContext parent() { + return massIndexingContext; } @Override diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityLoadingRunnable.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityLoadingRunnable.java index 2e73aae092c..cb2a59a4cd2 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityLoadingRunnable.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingEntityLoadingRunnable.java @@ -8,20 +8,20 @@ import java.lang.invoke.MethodHandles; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Set; import java.util.concurrent.CompletableFuture; import org.hibernate.search.engine.backend.work.execution.DocumentCommitStrategy; import org.hibernate.search.engine.backend.work.execution.DocumentRefreshStrategy; import org.hibernate.search.engine.backend.work.execution.OperationSubmitter; import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoadingContext; import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntitySink; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingStrategy; import org.hibernate.search.mapper.pojo.logging.impl.Log; import org.hibernate.search.mapper.pojo.massindexing.MassIndexingEnvironment; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingEntityLoadingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingLoadingStrategy; +import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingSessionContext; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; import org.hibernate.search.mapper.pojo.work.spi.PojoIndexer; @@ -34,18 +34,21 @@ public class PojoMassIndexingEntityLoadingRunnable private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); + private final PojoMassIndexingContext massIndexingContext; private final PojoMassIndexingIndexedTypeGroup typeGroup; - private final PojoMassIndexingLoadingStrategy loadingStrategy; + private final PojoMassLoadingStrategy loadingStrategy; private final PojoProducerConsumerQueue> identifierQueue; private final String tenantId; private final MassIndexingEnvironment.EntityLoadingContext entityLoadingContext; protected PojoMassIndexingEntityLoadingRunnable(PojoMassIndexingNotifier notifier, - MassIndexingEnvironment environment, PojoMassIndexingIndexedTypeGroup typeGroup, - PojoMassIndexingLoadingStrategy loadingStrategy, + PojoMassIndexingContext massIndexingContext, MassIndexingEnvironment environment, + PojoMassIndexingIndexedTypeGroup typeGroup, + PojoMassLoadingStrategy loadingStrategy, PojoProducerConsumerQueue> identifierQueue, String tenantId) { super( notifier, environment ); + this.massIndexingContext = massIndexingContext; this.typeGroup = typeGroup; this.loadingStrategy = loadingStrategy; this.identifierQueue = identifierQueue; @@ -58,7 +61,8 @@ protected PojoMassIndexingEntityLoadingRunnable(PojoMassIndexingNotifier notifie protected void runWithFailureHandler() throws InterruptedException { log.trace( "started" ); LoadingContext context = new LoadingContext(); - try ( PojoMassEntityLoader entityLoader = loadingStrategy.createEntityLoader( context ) ) { + try ( PojoMassEntityLoader entityLoader = + loadingStrategy.createEntityLoader( typeGroup.includedTypes(), context ) ) { List idList; do { idList = identifierQueue.take(); @@ -104,7 +108,7 @@ protected String operationName() { return log.massIndexingLoadingAndExtractingEntityData( typeGroup.notifiedGroupName() ); } - private final class LoadingContext implements PojoMassIndexingEntityLoadingContext { + private final class LoadingContext implements PojoMassEntityLoadingContext { // The traditional implementation was equivalent to using 1. // Theoretically we could raise this above 2, but it would only help // if loading performance is inconsistent, so as to provide a "buffer" @@ -124,8 +128,8 @@ public LoadingContext() { } @Override - public Set> includedTypes() { - return Collections.unmodifiableSet( typeGroup.includedTypesIdentifiers() ); + public PojoMassLoadingContext parent() { + return massIndexingContext; } @Override diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingIndexedTypeContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingIndexedTypeContext.java index cefa4960212..c539aeb9b29 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingIndexedTypeContext.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingIndexedTypeContext.java @@ -9,17 +9,13 @@ import java.util.function.Supplier; import org.hibernate.search.mapper.pojo.identity.impl.IdentifierMappingImplementor; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; import org.hibernate.search.mapper.pojo.work.spi.PojoWorkSessionContext; /** * @param The entity type mapped to the index. */ -public interface PojoMassIndexingIndexedTypeContext { - - PojoRawTypeIdentifier typeIdentifier(); - - String entityName(); +public interface PojoMassIndexingIndexedTypeContext extends PojoLoadingTypeContext { Supplier toEntitySupplier(PojoWorkSessionContext sessionContext, Object entity); diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingIndexedTypeGroup.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingIndexedTypeGroup.java index 8d4c6cbb8a1..49da1b7b4a4 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingIndexedTypeGroup.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/impl/PojoMassIndexingIndexedTypeGroup.java @@ -15,8 +15,8 @@ import java.util.stream.Collectors; import org.hibernate.search.engine.common.EntityReference; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingLoadingStrategy; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingStrategy; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingMappingContext; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingSessionContext; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; @@ -33,19 +33,21 @@ public class PojoMassIndexingIndexedTypeGroup { * For example, without this, we could end up reindexing type B in one thread, * and its superclass A (which will include all instances of B) in another. * - * @param indexingContext A conficuration contextural information. - * @param mappingContext A mappings contextural information. + * @param mappingContext The mapping context. + * @param typeContextProvider A provider of type contexts, used for some reflection operations. * @param indexedTypeContexts A set of indexed types to group together. + * @param loadingContext Mapper-specific loading context. + * * @return One or more type groups that are guaranteed to be disjoint. */ - public static List> disjoint(PojoMassIndexingContext indexingContext, - PojoMassIndexingMappingContext mappingContext, + public static List> disjoint(PojoMassIndexingMappingContext mappingContext, PojoMassIndexingTypeContextProvider typeContextProvider, - Set> indexedTypeContexts) { + Set> indexedTypeContexts, + PojoMassLoadingContext loadingContext) { List> typeGroups = new ArrayList<>(); for ( PojoMassIndexingIndexedTypeContext typeContext : indexedTypeContexts ) { - PojoMassIndexingIndexedTypeGroup typeGroup = PojoMassIndexingIndexedTypeGroup.single( indexingContext, - mappingContext, typeContextProvider, typeContext ); + PojoMassIndexingIndexedTypeGroup typeGroup = PojoMassIndexingIndexedTypeGroup.single( + mappingContext, typeContextProvider, typeContext, loadingContext ); // First try to merge this new type group with an existing one ListIterator> iterator = typeGroups.listIterator(); while ( iterator.hasNext() ) { @@ -63,35 +65,39 @@ public static List> disjoint(PojoMassIndexin return typeGroups; } - private static PojoMassIndexingIndexedTypeGroup single(PojoMassIndexingContext indexingContext, - PojoMassIndexingMappingContext mappingContext, - PojoMassIndexingTypeContextProvider typeContextProvider, - PojoMassIndexingIndexedTypeContext typeContext) { - PojoMassIndexingLoadingStrategy strategy = - indexingContext.loadingStrategy( typeContext.typeIdentifier() ); - return new PojoMassIndexingIndexedTypeGroup<>( strategy, typeContext, indexingContext, mappingContext, - typeContextProvider, Collections.singleton( typeContext ) ); + private static PojoMassIndexingIndexedTypeGroup single(PojoMassIndexingMappingContext mappingContext, + PojoMassIndexingTypeContextProvider typeContextProvider, PojoMassIndexingIndexedTypeContext typeContext, + PojoMassLoadingContext loadingContext) { + PojoMassLoadingStrategy strategy = typeContext.massLoadingStrategy(); + return new PojoMassIndexingIndexedTypeGroup<>( strategy, typeContext, mappingContext, typeContextProvider, + Collections.singleton( typeContext ), loadingContext ); } - private final PojoMassIndexingLoadingStrategy loadingStrategy; + private final PojoMassLoadingStrategy loadingStrategy; private final PojoMassIndexingIndexedTypeContext commonSuperType; - private final PojoMassIndexingContext indexingContext; private final PojoMassIndexingMappingContext mappingContext; private final PojoMassIndexingTypeContextProvider typeContextProvider; private final Set> includedTypes; + private final PojoMassLoadingContext loadingContext; + private Boolean groupingAllowed; - private PojoMassIndexingIndexedTypeGroup(PojoMassIndexingLoadingStrategy loadingStrategy, + private PojoMassIndexingIndexedTypeGroup(PojoMassLoadingStrategy loadingStrategy, PojoMassIndexingIndexedTypeContext commonSuperType, - PojoMassIndexingContext indexingContext, PojoMassIndexingMappingContext mappingContext, PojoMassIndexingTypeContextProvider typeContextProvider, - Set> includedTypes) { + Set> includedTypes, + PojoMassLoadingContext loadingContext) { this.commonSuperType = commonSuperType; - this.indexingContext = indexingContext; this.mappingContext = mappingContext; this.typeContextProvider = typeContextProvider; this.loadingStrategy = loadingStrategy; this.includedTypes = includedTypes; + this.loadingContext = loadingContext; + if ( includedTypes.size() > 1 ) { + // We're already grouping, so obviously it's allowed. + groupingAllowed = true; + } + // else: evaluate groupingAllowed lazily (see getter) } @Override @@ -108,9 +114,15 @@ public String notifiedGroupName() { .collect( Collectors.joining( "," ) ); } - public Set> includedTypesIdentifiers() { - return includedTypes.stream().map( PojoMassIndexingIndexedTypeContext::typeIdentifier ) - .collect( Collectors.toCollection( LinkedHashSet::new ) ); + public Set> includedTypes() { + return includedTypes; + } + + private boolean groupingAllowed() { + if ( groupingAllowed == null ) { + groupingAllowed = loadingStrategy.groupingAllowed( includedTypes.iterator().next(), loadingContext ); + } + return groupingAllowed; } public EntityReference extractReference(PojoMassIndexingSessionContext sessionContext, Object entity) { @@ -132,14 +144,15 @@ public Object extractIdentifier(PojoMassIndexingIndexedTypeContext type typeContext.toEntitySupplier( sessionContext, entity ) ); } - public PojoMassIndexingLoadingStrategy loadingStrategy() { + public PojoMassLoadingStrategy loadingStrategy() { return loadingStrategy; } /** * Merge this group with the other group if - * the other group uses the same loading strategy and - * the other group's {@code commonSuperType} represents a supertype or subtype + * the other group uses the same loading strategy, + * and the loading strategy {@link PojoMassLoadingStrategy#groupingAllowed allows grouping for these types}, + * and the other group's {@code commonSuperType} represents a supertype or subtype * of this group's {@code commonSuperType}. * @param other The other group to merge with (if possible). * @return The merged group, or {@code null} if @@ -152,7 +165,9 @@ private PojoMassIndexingIndexedTypeGroup mergeOrNull(PojoMassIndexingIndexedT if ( !loadingStrategy.equals( other.loadingStrategy ) ) { return null; } - + if ( !groupingAllowed() || !other.groupingAllowed() ) { + return null; + } // We know both types are indexed types, which means both types are entity types, // so if they share the same loading strategy, we can assume they also share the same identifier space. // If one is the supertype of the other, make sure to load them in the same group: @@ -179,7 +194,8 @@ private PojoMassIndexingIndexedTypeGroup withAdditionalTypes( Set> otherIncludedSubTypes) { Set> mergedIncludedSubTypes = new LinkedHashSet<>( includedTypes ); mergedIncludedSubTypes.addAll( otherIncludedSubTypes ); - return new PojoMassIndexingIndexedTypeGroup<>( loadingStrategy, commonSuperType, indexingContext, mappingContext, - typeContextProvider, mergedIncludedSubTypes ); + return new PojoMassIndexingIndexedTypeGroup<>( loadingStrategy, commonSuperType, mappingContext, + typeContextProvider, mergedIncludedSubTypes, loadingContext + ); } } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingContext.java index 670f0d072f7..60a7304d143 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingContext.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingContext.java @@ -6,18 +6,11 @@ */ package org.hibernate.search.mapper.pojo.massindexing.spi; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingContext; /** * Contextual information about a mass indexing proccess. */ -public interface PojoMassIndexingContext { - - /** - * @param The exposed type of indexed entities. - * @param expectedType The expected types of indexed objects. - * @return A loading strategy. - */ - PojoMassIndexingLoadingStrategy loadingStrategy(PojoRawTypeIdentifier expectedType); +public interface PojoMassIndexingContext extends PojoMassLoadingContext { } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingContextBuilder.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingContextBuilder.java deleted file mode 100644 index d1e5b50b779..00000000000 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingContextBuilder.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.massindexing.spi; - -/** - * A builder for {@link PojoMassIndexingContext}, - * allowing changes to the parameters of object loading, - * for example while a query is being built. - * - * @param The type of the initial step of the mass indexing loading options definition DSL - */ -public interface PojoMassIndexingContextBuilder { - - /** - * @return The inital step of the mass indexing loading options definition DSL passed to user-defined consumers added through - */ - LOS toAPI(); - - /** - * @return The configured loading context. - */ - PojoMassIndexingContext build(); -} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingIdentifierLoadingContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingIdentifierLoadingContext.java deleted file mode 100644 index 3e799ea4b6a..00000000000 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingIdentifierLoadingContext.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.massindexing.spi; - -import java.util.Set; - -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierSink; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; - -/** - * The context passed to {@link PojoMassIndexingLoadingStrategy#createIdentifierLoader(PojoMassIndexingIdentifierLoadingContext)}. - * - * @param The type of loaded entities. - * @param The type of entity identifiers. - */ -public interface PojoMassIndexingIdentifierLoadingContext { - - /** - * @return The identifiers of the types of all entities that will be loaded by the entity loader. - */ - Set> includedTypes(); - - /** - * @return A sink that the loader will add loaded entities to. - */ - PojoMassIdentifierSink createSink(); - - /** - * @return The tenant identifier to use ({@code null} if none). - */ - String tenantIdentifier(); -} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingLoadingStrategy.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingLoadingStrategy.java deleted file mode 100644 index db02272b3e2..00000000000 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/massindexing/spi/PojoMassIndexingLoadingStrategy.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.massindexing.spi; - -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoader; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; - -/** - * A strategy for entity loading during mass indexing. - * - * @param The type of loaded entities. - * @param The type of entity identifiers. - */ -public interface PojoMassIndexingLoadingStrategy { - - /** - * @param obj Another strategy - * @return {@code true} if the other strategy targets the same entity hierarchy - * and can be used as a replacement for this one. - * {@code false} otherwise or when unsure. - */ - @Override - boolean equals(Object obj); - - /* - * Hashcode must be overridden to be consistent with equals. - */ - @Override - int hashCode(); - - /** - * @param context A context, used to retrieve information about targeted types and to create the sink. - * @return An entity identifier loader. - */ - PojoMassIdentifierLoader createIdentifierLoader(PojoMassIndexingIdentifierLoadingContext context); - - /** - * @param context A context, used to retrieve information about targeted types and to create the sink. - * @return An entity loader. - */ - PojoMassEntityLoader createEntityLoader(PojoMassIndexingEntityLoadingContext context); - -} diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/building/impl/PojoEntityTypeAdditionalMetadataBuilder.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/building/impl/PojoEntityTypeAdditionalMetadataBuilder.java index 9a44a940ded..2fa69019180 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/building/impl/PojoEntityTypeAdditionalMetadataBuilder.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/building/impl/PojoEntityTypeAdditionalMetadataBuilder.java @@ -25,6 +25,7 @@ class PojoEntityTypeAdditionalMetadataBuilder implements PojoAdditionalMetadataC private String secondaryEntityName; private PojoPathDefinitionProvider pathDefinitionProvider; private String entityIdPropertyName; + private Object loadingBinder; PojoEntityTypeAdditionalMetadataBuilder() { } @@ -61,12 +62,18 @@ public void entityIdPropertyName(String propertyName) { this.entityIdPropertyName = propertyName; } + @Override + public void loadingBinder(Object binder) { + this.loadingBinder = binder; + } + public PojoEntityTypeAdditionalMetadata build(PojoRawTypeModel typeModel) { return new PojoEntityTypeAdditionalMetadata( entityName != null ? entityName : typeModel.typeIdentifier().javaClass().getSimpleName(), secondaryEntityName, pathDefinitionProvider != null ? pathDefinitionProvider : new SimplePojoPathsDefinitionProvider(), - Optional.ofNullable( entityIdPropertyName ) + Optional.ofNullable( entityIdPropertyName ), + loadingBinder ); } } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/building/spi/PojoAdditionalMetadataCollectorEntityTypeNode.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/building/spi/PojoAdditionalMetadataCollectorEntityTypeNode.java index 6d7a605ddd9..27eea6c2d02 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/building/spi/PojoAdditionalMetadataCollectorEntityTypeNode.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/building/spi/PojoAdditionalMetadataCollectorEntityTypeNode.java @@ -6,6 +6,7 @@ */ package org.hibernate.search.mapper.pojo.model.additionalmetadata.building.spi; +import org.hibernate.search.mapper.pojo.loading.definition.spi.PojoEntityLoadingBindingContext; import org.hibernate.search.mapper.pojo.model.path.spi.PojoPathDefinitionProvider; public interface PojoAdditionalMetadataCollectorEntityTypeNode extends PojoAdditionalMetadataCollector { @@ -36,4 +37,10 @@ public interface PojoAdditionalMetadataCollectorEntityTypeNode extends PojoAddit */ void entityIdPropertyName(String propertyName); + /** + * @param binder A binder for loading of entities of this type. + * @see org.hibernate.search.mapper.pojo.mapping.building.spi.PojoIndexedTypeExtendedMappingCollector#applyLoadingBinder(Object, PojoEntityLoadingBindingContext) + */ + void loadingBinder(Object binder); + } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/impl/PojoEntityTypeAdditionalMetadata.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/impl/PojoEntityTypeAdditionalMetadata.java index 82404e2417b..88b1aba9ac0 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/impl/PojoEntityTypeAdditionalMetadata.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/model/additionalmetadata/impl/PojoEntityTypeAdditionalMetadata.java @@ -15,14 +15,17 @@ public class PojoEntityTypeAdditionalMetadata { private final String secondaryEntityName; private final PojoPathDefinitionProvider pathDefinitionProvider; private final Optional entityIdPropertyName; + private final Object loadingBinder; public PojoEntityTypeAdditionalMetadata(String entityName, String secondaryEntityName, PojoPathDefinitionProvider pathDefinitionProvider, - Optional entityIdPropertyName) { + Optional entityIdPropertyName, + Object loadingBinder) { this.entityName = entityName; this.secondaryEntityName = secondaryEntityName; this.pathDefinitionProvider = pathDefinitionProvider; this.entityIdPropertyName = entityIdPropertyName; + this.loadingBinder = loadingBinder; } public String getEntityName() { @@ -40,4 +43,8 @@ public PojoPathDefinitionProvider pathDefinitionProvider() { public Optional getEntityIdPropertyName() { return entityIdPropertyName; } + + public Object getLoadingBinder() { + return loadingBinder; + } } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/search/loading/impl/PojoSearchLoadingIndexedTypeContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/search/loading/impl/PojoSearchLoadingIndexedTypeContext.java index 9c78eb97706..679b644a292 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/search/loading/impl/PojoSearchLoadingIndexedTypeContext.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/search/loading/impl/PojoSearchLoadingIndexedTypeContext.java @@ -11,8 +11,6 @@ public interface PojoSearchLoadingIndexedTypeContext extends PojoLoadingTypeContext { - String entityName(); - IdentifierMapping identifierMapping(); } diff --git a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/work/impl/PojoWorkTypeContext.java b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/work/impl/PojoWorkTypeContext.java index e70f4e451e9..4b76508971e 100644 --- a/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/work/impl/PojoWorkTypeContext.java +++ b/mapper/pojo-base/src/main/java/org/hibernate/search/mapper/pojo/work/impl/PojoWorkTypeContext.java @@ -31,8 +31,6 @@ public interface PojoWorkTypeContext extends PojoLoadingTypeContext { String toDocumentIdentifier(PojoWorkSessionContext sessionContext, I identifier); - String entityName(); - PojoImplicitReindexingResolver reindexingResolver(); E toEntity(Object unproxiedEntity); diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/LoadingTypeContext.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/LoadingTypeContext.java deleted file mode 100644 index 19f00174302..00000000000 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/LoadingTypeContext.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.standalone.loading.impl; - -import java.util.Optional; - -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; -import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingStrategy; -import org.hibernate.search.mapper.pojo.standalone.loading.SelectionLoadingStrategy; - -public interface LoadingTypeContext { - - PojoRawTypeIdentifier typeIdentifier(); - - String name(); - - Optional> selectionLoadingStrategy(); - - Optional> massLoadingStrategy(); - -} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/LoadingTypeContextProvider.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/LoadingTypeContextProvider.java deleted file mode 100644 index 0d70c7e235b..00000000000 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/LoadingTypeContextProvider.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.standalone.loading.impl; - -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; - -public interface LoadingTypeContextProvider { - - LoadingTypeContext forExactType(PojoRawTypeIdentifier typeIdentifier); - - LoadingTypeContext forExactTypeOrNull(PojoRawTypeIdentifier typeIdentifier); - - LoadingTypeContext indexedForExactClass(Class typeIdentifier); - -} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoLoadingContext.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoLoadingContext.java index bd0e9413f96..0516a671a5f 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoLoadingContext.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoLoadingContext.java @@ -6,45 +6,27 @@ */ package org.hibernate.search.mapper.pojo.standalone.loading.impl; -import java.lang.invoke.MethodHandles; import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.Map; -import java.util.Optional; -import java.util.Set; -import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; -import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionEntityLoader; import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingContext; -import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingStrategy; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingLoadingStrategy; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; import org.hibernate.search.mapper.pojo.model.spi.PojoRuntimeIntrospector; import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingOptions; -import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingStrategy; import org.hibernate.search.mapper.pojo.standalone.loading.SelectionLoadingOptions; -import org.hibernate.search.mapper.pojo.standalone.loading.SelectionLoadingStrategy; import org.hibernate.search.mapper.pojo.standalone.loading.dsl.SelectionLoadingOptionsStep; -import org.hibernate.search.mapper.pojo.standalone.logging.impl.Log; -import org.hibernate.search.mapper.pojo.standalone.massindexing.impl.StandalonePojoMassIndexingLoadingStrategy; import org.hibernate.search.mapper.pojo.standalone.massindexing.impl.StandalonePojoMassIndexingMappingContext; -import org.hibernate.search.util.common.logging.impl.LoggerFactory; public final class StandalonePojoLoadingContext implements PojoSelectionLoadingContext, PojoMassIndexingContext, MassLoadingOptions, SelectionLoadingOptions { - private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); - private final StandalonePojoMassIndexingMappingContext mappingContext; - private final LoadingTypeContextProvider typeContextProvider; private int batchSize = 10; private final Map, Object> contextData; private StandalonePojoLoadingContext(Builder builder) { this.mappingContext = builder.mappingContext; - this.typeContextProvider = builder.typeContextProvider; this.contextData = builder.contextData; } @@ -81,42 +63,16 @@ public PojoRuntimeIntrospector runtimeIntrospector() { return mappingContext.runtimeIntrospector(); } - @Override - public PojoSelectionLoadingStrategy loadingStrategy(PojoLoadingTypeContext type) { - return loadingStrategyOptional( type ) - .orElseThrow( () -> log.entityLoadingStrategyNotRegistered( type.typeIdentifier() ) ); - } - - @Override - public Optional> loadingStrategyOptional( - PojoLoadingTypeContext type) { - PojoRawTypeIdentifier typeId = type.typeIdentifier(); - return typeContextProvider.forExactType( typeId ).selectionLoadingStrategy() - // Eclipse will complain about a raw type if we use a method reference here... for some reason. - .map( s -> new StandalonePojoSelectionLoadingStrategy<>( s ) ); - } - - @Override - public PojoMassIndexingLoadingStrategy loadingStrategy( - PojoRawTypeIdentifier expectedType) { - LoadingTypeContext typeContext = typeContextProvider.forExactType( expectedType ); - Optional> strategyOptional = typeContext.massLoadingStrategy(); - if ( !strategyOptional.isPresent() ) { - throw log.entityLoadingStrategyNotRegistered( typeContext.typeIdentifier() ); - } - return new StandalonePojoMassIndexingLoadingStrategy<>( mappingContext, typeContextProvider, - strategyOptional.get(), this ); + public StandalonePojoMassIndexingMappingContext mapping() { + return mappingContext; } public static final class Builder implements StandalonePojoSelectionLoadingContextBuilder, SelectionLoadingOptionsStep { private final StandalonePojoMassIndexingMappingContext mappingContext; - private final LoadingTypeContextProvider typeContextProvider; private final Map, Object> contextData = new HashMap<>(); - public Builder(StandalonePojoMassIndexingMappingContext mappingContext, - LoadingTypeContextProvider typeContextProvider) { + public Builder(StandalonePojoMassIndexingMappingContext mappingContext) { this.mappingContext = mappingContext; - this.typeContextProvider = typeContextProvider; } @Override @@ -135,42 +91,4 @@ public StandalonePojoLoadingContext build() { } } - private class StandalonePojoSelectionLoadingStrategy implements PojoSelectionLoadingStrategy { - - private final SelectionLoadingStrategy delegate; - - private StandalonePojoSelectionLoadingStrategy(SelectionLoadingStrategy delegate) { - this.delegate = delegate; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - StandalonePojoSelectionLoadingStrategy that = (StandalonePojoSelectionLoadingStrategy) o; - return delegate.equals( that.delegate ); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public PojoSelectionEntityLoader createLoader( - Set> expectedTypes) { - Set> includedTypeIdentifiers = new LinkedHashSet<>(); - for ( PojoLoadingTypeContext expectedType : expectedTypes ) { - includedTypeIdentifiers.add( expectedType.typeIdentifier() ); - } - StandalonePojoLoadingTypeGroup includedTypes = new StandalonePojoLoadingTypeGroup<>( - typeContextProvider, includedTypeIdentifiers, runtimeIntrospector() ); - return new StandalonePojoSelectionEntityLoader<>( - delegate.createEntityLoader( includedTypes, StandalonePojoLoadingContext.this ) ); - } - } } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoLoadingTypeGroup.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoLoadingTypeGroup.java index 539d702e7d4..bc09c38cc52 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoLoadingTypeGroup.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoLoadingTypeGroup.java @@ -7,36 +7,30 @@ package org.hibernate.search.mapper.pojo.standalone.loading.impl; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; import org.hibernate.search.mapper.pojo.model.spi.PojoRuntimeIntrospector; import org.hibernate.search.mapper.pojo.standalone.loading.LoadingTypeGroup; public final class StandalonePojoLoadingTypeGroup implements LoadingTypeGroup { - private final LoadingTypeContextProvider typeContextProvider; private final PojoRuntimeIntrospector introspector; - private final Set> includedTypes; + private final Set> includedTypes; - public StandalonePojoLoadingTypeGroup(LoadingTypeContextProvider typeContextProvider, - Set> includedTypeIdentifiers, + public StandalonePojoLoadingTypeGroup(Set> includedTypes, PojoRuntimeIntrospector introspector) { - this.typeContextProvider = typeContextProvider; this.introspector = introspector; - this.includedTypes = new LinkedHashSet<>(); - for ( PojoRawTypeIdentifier includedTypeIdentifier : includedTypeIdentifiers ) { - includedTypes.add( typeContextProvider.forExactType( includedTypeIdentifier ) ); - } + this.includedTypes = includedTypes; } @Override public Map> includedTypesMap() { return includedTypes.stream() - .collect( Collectors.toMap( LoadingTypeContext::name, + .collect( Collectors.toMap( PojoLoadingTypeContext::entityName, t -> t.typeIdentifier().javaClass(), (o1, o2) -> o1, LinkedHashMap::new ) ); } @@ -44,16 +38,20 @@ public Map> includedTypesMap() { @Override public boolean includesInstance(Object entity) { PojoRawTypeIdentifier targetType = introspector.detectEntityType( entity ); - LoadingTypeContext typeContextOrNull = typeContextProvider.forExactTypeOrNull( targetType ); - if ( typeContextOrNull == null ) { + if ( targetType == null ) { return false; } - return includedTypes.contains( typeContextOrNull ); + for ( PojoLoadingTypeContext includedType : includedTypes ) { + if ( includedType.typeIdentifier().equals( targetType ) ) { + return true; + } + } + return false; } @Override public String toString() { - return includedTypes.stream().map( LoadingTypeContext::name ) + return includedTypes.stream().map( PojoLoadingTypeContext::entityName ) .collect( Collectors.joining( "," ) ); } } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoMassLoadingStrategy.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoMassLoadingStrategy.java new file mode 100644 index 00000000000..79fc17c3fb8 --- /dev/null +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoMassLoadingStrategy.java @@ -0,0 +1,82 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.pojo.standalone.loading.impl; + +import java.util.Set; + +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoMassLoadingStrategy; +import org.hibernate.search.mapper.pojo.standalone.loading.MassEntitySink; +import org.hibernate.search.mapper.pojo.standalone.loading.MassIdentifierSink; +import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingStrategy; +import org.hibernate.search.mapper.pojo.standalone.massindexing.impl.StandalonePojoMassIndexingSessionContext; +import org.hibernate.search.util.common.impl.SuppressingCloser; + +public class StandalonePojoMassLoadingStrategy + implements PojoMassLoadingStrategy { + private final MassLoadingStrategy delegate; + + public StandalonePojoMassLoadingStrategy(MassLoadingStrategy delegate) { + this.delegate = delegate; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + StandalonePojoMassLoadingStrategy that = (StandalonePojoMassLoadingStrategy) o; + return delegate.equals( that.delegate ); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public boolean groupingAllowed(PojoLoadingTypeContext type, PojoMassLoadingContext context) { + // No restriction. + return true; + } + + @Override + public PojoMassIdentifierLoader createIdentifierLoader( + Set> expectedTypes, PojoMassIdentifierLoadingContext context) { + StandalonePojoLoadingContext parentContext = (StandalonePojoLoadingContext) context.parent(); + StandalonePojoLoadingTypeGroup includedTypes = new StandalonePojoLoadingTypeGroup<>( + expectedTypes, parentContext.runtimeIntrospector() ); + MassIdentifierSink sink = new StandalonePojoMassIdentifierSink<>( context.createSink() ); + return new StandalonePojoMassIdentifierLoader( delegate.createIdentifierLoader( includedTypes, sink, parentContext ) ); + } + + @Override + public PojoMassEntityLoader createEntityLoader(Set> expectedTypes, + PojoMassEntityLoadingContext context) { + StandalonePojoLoadingContext parentContext = (StandalonePojoLoadingContext) context.parent(); + StandalonePojoMassIndexingSessionContext session = parentContext.mapping().createSession( context.tenantIdentifier() ); + try { + StandalonePojoLoadingTypeGroup includedTypes = new StandalonePojoLoadingTypeGroup<>( + expectedTypes, parentContext.runtimeIntrospector() ); + MassEntitySink sink = new StandalonePojoMassEntitySink<>( context.createSink( session ) ); + return new StandalonePojoMassEntityLoader<>( session, + delegate.createEntityLoader( includedTypes, sink, parentContext ) ); + } + catch (RuntimeException e) { + new SuppressingCloser( e ).push( session ); + throw e; + } + } +} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoSelectionLoadingContextBuilder.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoSelectionLoadingContextBuilder.java index 989bf946636..b330c7c2ce4 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoSelectionLoadingContextBuilder.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoSelectionLoadingContextBuilder.java @@ -7,12 +7,10 @@ package org.hibernate.search.mapper.pojo.standalone.loading.impl; import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingContextBuilder; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingContextBuilder; import org.hibernate.search.mapper.pojo.standalone.loading.dsl.SelectionLoadingOptionsStep; public interface StandalonePojoSelectionLoadingContextBuilder - extends PojoSelectionLoadingContextBuilder, - PojoMassIndexingContextBuilder { + extends PojoSelectionLoadingContextBuilder { @Override StandalonePojoLoadingContext build(); diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoSelectionLoadingStrategy.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoSelectionLoadingStrategy.java new file mode 100644 index 00000000000..8bc0e46db36 --- /dev/null +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/loading/impl/StandalonePojoSelectionLoadingStrategy.java @@ -0,0 +1,52 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.pojo.standalone.loading.impl; + +import java.util.Set; + +import org.hibernate.search.mapper.pojo.loading.spi.PojoLoadingTypeContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionEntityLoader; +import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingContext; +import org.hibernate.search.mapper.pojo.loading.spi.PojoSelectionLoadingStrategy; +import org.hibernate.search.mapper.pojo.standalone.loading.SelectionLoadingStrategy; + +public class StandalonePojoSelectionLoadingStrategy implements PojoSelectionLoadingStrategy { + + private final SelectionLoadingStrategy delegate; + + public StandalonePojoSelectionLoadingStrategy(SelectionLoadingStrategy delegate) { + this.delegate = delegate; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + StandalonePojoSelectionLoadingStrategy that = (StandalonePojoSelectionLoadingStrategy) o; + return delegate.equals( that.delegate ); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public PojoSelectionEntityLoader createEntityLoader( + Set> expectedTypes, PojoSelectionLoadingContext context) { + StandalonePojoLoadingTypeGroup includedTypes = new StandalonePojoLoadingTypeGroup<>( + expectedTypes, + context.runtimeIntrospector() + ); + return new StandalonePojoSelectionEntityLoader<>( delegate.createEntityLoader( + includedTypes, (StandalonePojoLoadingContext) context ) ); + } +} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/logging/impl/Log.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/logging/impl/Log.java index 29d04c00ca6..64d76349cc8 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/logging/impl/Log.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/logging/impl/Log.java @@ -58,10 +58,6 @@ SearchException unknownClassForIndexedEntityType(@FormatWith(ClassFormatter.clas value = "Invalid String value for the bean provider: '%s'. The bean provider must be an instance of '%s'.") SearchException invalidStringForBeanProvider(String value, Class expectedType); - @Message(id = ID_OFFSET + 12, - value = "Unable to set up entity loading for type '%s', because no entity loading strategy was registered for this type.") - SearchException entityLoadingStrategyNotRegistered(PojoRawTypeIdentifier typeIdentifier); - @Message(id = ID_OFFSET + 14, value = "Unable to access search session: %1$s") SearchException hibernateSessionAccessError(String causeMessage); diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/AbstractStandalonePojoTypeContext.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/AbstractStandalonePojoTypeContext.java index 4a33382fd96..03a9c40806f 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/AbstractStandalonePojoTypeContext.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/AbstractStandalonePojoTypeContext.java @@ -6,29 +6,28 @@ */ package org.hibernate.search.mapper.pojo.standalone.mapping.impl; -import java.util.Optional; - +import org.hibernate.search.mapper.pojo.loading.definition.spi.PojoEntityLoadingBindingContext; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoTypeExtendedMappingCollector; import org.hibernate.search.mapper.pojo.model.path.spi.PojoPathFilter; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingStrategy; import org.hibernate.search.mapper.pojo.standalone.loading.SelectionLoadingStrategy; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.LoadingTypeContext; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl.StandalonePojoEntityTypeMetadata; +import org.hibernate.search.mapper.pojo.standalone.loading.impl.StandalonePojoMassLoadingStrategy; +import org.hibernate.search.mapper.pojo.standalone.loading.impl.StandalonePojoSelectionLoadingStrategy; +import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurationContext; +import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurer; import org.hibernate.search.mapper.pojo.standalone.work.impl.SearchIndexingPlanTypeContext; abstract class AbstractStandalonePojoTypeContext - implements SearchIndexingPlanTypeContext, LoadingTypeContext { + implements SearchIndexingPlanTypeContext { private final PojoRawTypeIdentifier typeIdentifier; private final String entityName; - private final StandalonePojoEntityTypeMetadata metadata; private final PojoPathFilter dirtyFilter; AbstractStandalonePojoTypeContext(AbstractBuilder builder) { this.typeIdentifier = builder.typeIdentifier; this.entityName = builder.entityName; - this.metadata = builder.metadata; this.dirtyFilter = builder.dirtyFilter; } @@ -42,7 +41,6 @@ public PojoRawTypeIdentifier typeIdentifier() { return typeIdentifier; } - @Override public String name() { return entityName; } @@ -51,16 +49,6 @@ public Class javaClass() { return typeIdentifier.javaClass(); } - @Override - public Optional> selectionLoadingStrategy() { - return metadata.selectionLoadingStrategy; - } - - @Override - public Optional> massLoadingStrategy() { - return metadata.massLoadingStrategy; - } - @Override public PojoPathFilter dirtyFilter() { return dirtyFilter; @@ -69,19 +57,37 @@ public PojoPathFilter dirtyFilter() { abstract static class AbstractBuilder implements PojoTypeExtendedMappingCollector { private final PojoRawTypeIdentifier typeIdentifier; private final String entityName; - private final StandalonePojoEntityTypeMetadata metadata; private PojoPathFilter dirtyFilter; - AbstractBuilder(PojoRawTypeIdentifier typeIdentifier, String entityName, - StandalonePojoEntityTypeMetadata metadata) { + AbstractBuilder(PojoRawTypeIdentifier typeIdentifier, String entityName) { this.typeIdentifier = typeIdentifier; this.entityName = entityName; - this.metadata = metadata; } @Override public void dirtyFilter(PojoPathFilter dirtyFilter) { this.dirtyFilter = dirtyFilter; } + + @Override + public void applyLoadingBinder(Object binder, PojoEntityLoadingBindingContext context) { + @SuppressWarnings("unchecked") // We make sure of that in APIs, see org.hibernate.search.mapper.pojo.standalone.mapping.StandalonePojoMappingConfigurationContext.addEntityType(java.lang.Class, org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurer) + var castConfigurer = (EntityConfigurer) binder; + castConfigurer.configure( new EntityConfigurationContext<>() { + @Override + public void selectionLoadingStrategy(SelectionLoadingStrategy strategy) { + context.selectionLoadingStrategy( typeIdentifier.javaClass(), strategy == null + ? null + : new StandalonePojoSelectionLoadingStrategy<>( strategy ) ); + } + + @Override + public void massLoadingStrategy(MassLoadingStrategy strategy) { + context.massLoadingStrategy( typeIdentifier.javaClass(), strategy == null + ? null + : new StandalonePojoMassLoadingStrategy<>( strategy ) ); + } + } ); + } } } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoContainedTypeContext.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoContainedTypeContext.java index ba781c5668c..68952b76688 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoContainedTypeContext.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoContainedTypeContext.java @@ -8,7 +8,6 @@ import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoContainedTypeExtendedMappingCollector; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl.StandalonePojoEntityTypeMetadata; class StandalonePojoContainedTypeContext extends AbstractStandalonePojoTypeContext { @@ -17,8 +16,8 @@ private StandalonePojoContainedTypeContext(Builder builder) { } static class Builder extends AbstractBuilder implements PojoContainedTypeExtendedMappingCollector { - Builder(PojoRawTypeIdentifier typeIdentifier, String entityName, StandalonePojoEntityTypeMetadata metadata) { - super( typeIdentifier, entityName, metadata ); + Builder(PojoRawTypeIdentifier typeIdentifier, String entityName) { + super( typeIdentifier, entityName ); } StandalonePojoContainedTypeContext build() { diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoEntityTypeContributor.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoEntityTypeContributor.java deleted file mode 100644 index 52bbf929c0b..00000000000 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoEntityTypeContributor.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.standalone.mapping.impl; - -import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoTypeMetadataContributor; -import org.hibernate.search.mapper.pojo.model.additionalmetadata.building.spi.PojoAdditionalMetadataCollectorTypeNode; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; - -class StandalonePojoEntityTypeContributor implements PojoTypeMetadataContributor { - - private final PojoRawTypeIdentifier typeIdentifier; - private final String entityName; - - StandalonePojoEntityTypeContributor(PojoRawTypeIdentifier typeIdentifier, String entityName) { - this.typeIdentifier = typeIdentifier; - this.entityName = entityName; - } - - @Override - public void contributeAdditionalMetadata(PojoAdditionalMetadataCollectorTypeNode collector) { - if ( !typeIdentifier.equals( collector.typeIdentifier() ) ) { - // Entity metadata is not inherited; only contribute it to the exact type. - return; - } - var node = collector.markAsEntity(); - if ( entityName != null ) { - node.entityName( entityName ); - } - } -} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoEntityTypeMetadata.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoEntityTypeMetadata.java new file mode 100644 index 00000000000..509dbc5b2b2 --- /dev/null +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoEntityTypeMetadata.java @@ -0,0 +1,68 @@ +/* + * Hibernate Search, full-text search for your domain model + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.search.mapper.pojo.standalone.mapping.impl; + +import java.lang.invoke.MethodHandles; + +import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoTypeMetadataContributor; +import org.hibernate.search.mapper.pojo.model.additionalmetadata.building.spi.PojoAdditionalMetadataCollectorTypeNode; +import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; +import org.hibernate.search.mapper.pojo.standalone.logging.impl.Log; +import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurer; +import org.hibernate.search.util.common.logging.impl.LoggerFactory; + +class StandalonePojoEntityTypeMetadata implements PojoTypeMetadataContributor { + private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); + + final PojoRawTypeModel type; + final String entityName; + final EntityConfigurer configurerOrNull; + + StandalonePojoEntityTypeMetadata(PojoRawTypeModel type, + String entityName, EntityConfigurer configurerOrNull) { + this.type = type; + this.entityName = entityName; + this.configurerOrNull = configurerOrNull; + } + + StandalonePojoEntityTypeMetadata mergeWith(StandalonePojoEntityTypeMetadata unknownTypeOther) { + if ( !type.equals( unknownTypeOther.type ) ) { + throw log.multipleEntityTypeDefinitions( type ); + } + @SuppressWarnings("unchecked") + StandalonePojoEntityTypeMetadata other = (StandalonePojoEntityTypeMetadata) unknownTypeOther; + if ( !entityName.equals( other.entityName ) ) { + throw log.multipleEntityTypeDefinitions( type ); + } + EntityConfigurer configurerOrNull; + if ( this.configurerOrNull == null ) { + configurerOrNull = other.configurerOrNull; + } + else if ( other.configurerOrNull == null ) { + configurerOrNull = this.configurerOrNull; + } + else { + throw log.multipleEntityTypeDefinitions( type ); + } + return new StandalonePojoEntityTypeMetadata<>( type, entityName, configurerOrNull ); + } + + @Override + public void contributeAdditionalMetadata(PojoAdditionalMetadataCollectorTypeNode collector) { + if ( !type.typeIdentifier().equals( collector.typeIdentifier() ) ) { + // Entity metadata is not inherited; only contribute it to the exact type. + return; + } + var node = collector.markAsEntity(); + if ( entityName != null ) { + node.entityName( entityName ); + } + if ( configurerOrNull != null ) { + node.loadingBinder( configurerOrNull ); + } + } +} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoIndexedTypeContext.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoIndexedTypeContext.java index e3ea4ed9d0b..c002e5c3b10 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoIndexedTypeContext.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoIndexedTypeContext.java @@ -8,16 +8,13 @@ import org.hibernate.search.engine.backend.index.IndexManager; import org.hibernate.search.engine.mapper.mapping.spi.MappedIndexManager; -import org.hibernate.search.engine.search.projection.spi.ProjectionMappedTypeContext; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoIndexedTypeExtendedMappingCollector; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl.StandalonePojoEntityTypeMetadata; -import org.hibernate.search.mapper.pojo.standalone.scope.impl.StandalonePojoScopeIndexedTypeContext; +import org.hibernate.search.mapper.pojo.standalone.entity.SearchIndexedEntity; import org.hibernate.search.mapper.pojo.standalone.session.impl.StandalonePojoSessionIndexedTypeContext; class StandalonePojoIndexedTypeContext extends AbstractStandalonePojoTypeContext - implements ProjectionMappedTypeContext, - StandalonePojoScopeIndexedTypeContext, StandalonePojoSessionIndexedTypeContext { + implements SearchIndexedEntity, StandalonePojoSessionIndexedTypeContext { private final MappedIndexManager indexManager; @@ -26,11 +23,6 @@ private StandalonePojoIndexedTypeContext(Builder builder) { this.indexManager = builder.indexManager; } - @Override - public boolean loadingAvailable() { - return selectionLoadingStrategy().isPresent(); - } - @Override public IndexManager indexManager() { return indexManager.toAPI(); @@ -39,8 +31,8 @@ public IndexManager indexManager() { static class Builder extends AbstractBuilder implements PojoIndexedTypeExtendedMappingCollector { private MappedIndexManager indexManager; - Builder(PojoRawTypeIdentifier typeIdentifier, String entityName, StandalonePojoEntityTypeMetadata metadata) { - super( typeIdentifier, entityName, metadata ); + Builder(PojoRawTypeIdentifier typeIdentifier, String entityName) { + super( typeIdentifier, entityName ); } @Override diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMapperDelegate.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMapperDelegate.java index 4741da3a6f0..8c7b02b9ab0 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMapperDelegate.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMapperDelegate.java @@ -12,20 +12,16 @@ import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoMapperDelegate; import org.hibernate.search.mapper.pojo.mapping.spi.PojoMappingDelegate; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl.StandalonePojoEntityTypeMetadataProvider; import org.hibernate.search.mapper.pojo.standalone.reporting.impl.StandalonePojoMappingHints; import org.hibernate.search.mapper.pojo.standalone.schema.management.impl.SchemaManagementListener; public final class StandalonePojoMapperDelegate implements PojoMapperDelegate { - private final StandalonePojoEntityTypeMetadataProvider metadataProvider; private final StandalonePojoTypeContextContainer.Builder typeContextContainerBuilder; private final SchemaManagementListener schemaManagementListener; - public StandalonePojoMapperDelegate(StandalonePojoEntityTypeMetadataProvider metadataProvider, - SchemaManagementListener schemaManagementListener) { - this.metadataProvider = metadataProvider; + public StandalonePojoMapperDelegate(SchemaManagementListener schemaManagementListener) { this.typeContextContainerBuilder = new StandalonePojoTypeContextContainer.Builder(); this.schemaManagementListener = schemaManagementListener; } @@ -38,13 +34,13 @@ public void closeOnFailure() { @Override public PojoIndexedTypeExtendedMappingCollector createIndexedTypeExtendedMappingCollector( PojoRawTypeModel rawTypeModel, String entityName) { - return typeContextContainerBuilder.addIndexed( rawTypeModel, entityName, metadataProvider.get( rawTypeModel ) ); + return typeContextContainerBuilder.addIndexed( rawTypeModel, entityName ); } @Override public PojoContainedTypeExtendedMappingCollector createContainedTypeExtendedMappingCollector( PojoRawTypeModel rawTypeModel, String entityName) { - return typeContextContainerBuilder.addContained( rawTypeModel, entityName, metadataProvider.get( rawTypeModel ) ); + return typeContextContainerBuilder.addContained( rawTypeModel, entityName ); } @Override diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMapping.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMapping.java index 21f98cb25df..894d4ef94f7 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMapping.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMapping.java @@ -18,7 +18,6 @@ import org.hibernate.search.engine.common.spi.SearchIntegration; import org.hibernate.search.engine.mapper.mapping.spi.MappingPreStopContext; import org.hibernate.search.engine.mapper.mapping.spi.MappingStartContext; -import org.hibernate.search.engine.search.projection.spi.ProjectionMappedTypeContext; import org.hibernate.search.mapper.pojo.mapping.spi.AbstractPojoMappingImplementor; import org.hibernate.search.mapper.pojo.mapping.spi.PojoMappingDelegate; import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexerAgent; @@ -34,7 +33,6 @@ import org.hibernate.search.mapper.pojo.standalone.schema.management.impl.SchemaManagementListener; import org.hibernate.search.mapper.pojo.standalone.scope.SearchScope; import org.hibernate.search.mapper.pojo.standalone.scope.impl.SearchScopeImpl; -import org.hibernate.search.mapper.pojo.standalone.scope.impl.StandalonePojoScopeIndexedTypeContext; import org.hibernate.search.mapper.pojo.standalone.session.SearchSession; import org.hibernate.search.mapper.pojo.standalone.session.SearchSessionBuilder; import org.hibernate.search.mapper.pojo.standalone.session.impl.StandalonePojoSearchSession; @@ -113,11 +111,6 @@ public BackendMappingHints hints() { return StandalonePojoMappingHints.INSTANCE; } - @Override - public ProjectionMappedTypeContext mappedTypeContext(String mappedTypeName) { - return typeContextContainer.indexedByEntityName().getOrFail( mappedTypeName ); - } - @Override public PojoRuntimeIntrospector runtimeIntrospector() { return PojoRuntimeIntrospector.simple(); @@ -150,7 +143,7 @@ public SearchSessionBuilder createSessionWithOptions() { @Override public SearchScopeImpl createScope(Collection> classes) { - PojoScopeDelegate> scopeDelegate = + PojoScopeDelegate> scopeDelegate = delegate().createPojoScopeForClasses( this, classes, @@ -163,7 +156,7 @@ public SearchScopeImpl createScope(Collection SearchScopeImpl createScope(Class expectedSuperType, Collection entityNames) { - PojoScopeDelegate> scopeDelegate = + PojoScopeDelegate> scopeDelegate = delegate().createPojoScopeForEntityNames( this, expectedSuperType, entityNames, @@ -206,7 +199,7 @@ public Backend backend(String backendName) { @Override public StandalonePojoLoadingContext.Builder loadingContextBuilder() { - return new StandalonePojoLoadingContext.Builder( this, typeContextContainer ); + return new StandalonePojoLoadingContext.Builder( this ); } @Override @@ -226,7 +219,7 @@ private SearchIntegration searchIntegration() { private Optional> createAllScope() { return delegate() - .>createPojoAllScope( + .>createPojoAllScope( this, typeContextContainer::indexedForExactType ) diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMappingInitiator.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMappingInitiator.java index 90997e20f7f..36892735f58 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMappingInitiator.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoMappingInitiator.java @@ -6,7 +6,9 @@ */ package org.hibernate.search.mapper.pojo.standalone.mapping.impl; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import org.hibernate.search.engine.cfg.spi.ConfigurationProperty; import org.hibernate.search.engine.cfg.spi.OptionalConfigurationProperty; @@ -18,11 +20,11 @@ import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoMapperDelegate; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoTypeMetadataContributor; import org.hibernate.search.mapper.pojo.mapping.spi.AbstractPojoMappingInitiator; +import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; import org.hibernate.search.mapper.pojo.standalone.cfg.StandalonePojoMapperSettings; import org.hibernate.search.mapper.pojo.standalone.mapping.StandalonePojoMappingConfigurationContext; import org.hibernate.search.mapper.pojo.standalone.mapping.StandalonePojoMappingConfigurer; import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurer; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl.StandalonePojoEntityTypeMetadataProvider; import org.hibernate.search.mapper.pojo.standalone.model.impl.StandalonePojoBootstrapIntrospector; import org.hibernate.search.mapper.pojo.standalone.schema.management.SchemaManagementStrategyName; import org.hibernate.search.mapper.pojo.standalone.schema.management.impl.SchemaManagementListener; @@ -49,15 +51,15 @@ public class StandalonePojoMappingInitiator extends AbstractPojoMappingInitiator .withDefault( StandalonePojoMapperSettings.Defaults.MULTI_TENANCY_ENABLED ) .build(); - private final StandalonePojoEntityTypeMetadataProvider.Builder entityTypeMetadataProviderBuilder; - - private StandalonePojoEntityTypeMetadataProvider entityTypeMetadataProvider; + private final StandalonePojoBootstrapIntrospector introspector; + // Use a LinkedHashMap for deterministic iteration + private final Map, StandalonePojoEntityTypeMetadata> entityTypeMetadataByType = + new LinkedHashMap<>(); private SchemaManagementListener schemaManagementListener; public StandalonePojoMappingInitiator(StandalonePojoBootstrapIntrospector introspector) { super( introspector ); - entityTypeMetadataProviderBuilder = new StandalonePojoEntityTypeMetadataProvider.Builder( introspector ); - + this.introspector = introspector; // Enable annotated type discovery by default annotationMapping() .discoverAnnotatedTypesFromRootMappingAnnotations( true ) @@ -67,8 +69,9 @@ public StandalonePojoMappingInitiator(StandalonePojoBootstrapIntrospector intros public StandalonePojoMappingInitiator addEntityType(Class clazz, String entityName, EntityConfigurer configurerOrNull) { - entityTypeMetadataProviderBuilder.addEntityType( clazz, entityName, configurerOrNull ); - + PojoRawTypeModel type = introspector.typeModel( clazz ); + entityTypeMetadataByType.merge( type, new StandalonePojoEntityTypeMetadata<>( type, entityName, configurerOrNull ), + StandalonePojoEntityTypeMetadata::mergeWith ); return this; } @@ -91,19 +94,17 @@ public void configure(MappingBuildContext buildContext, } } ); - entityTypeMetadataProvider = entityTypeMetadataProviderBuilder.build(); - SchemaManagementStrategyName schemaManagementStrategyName = SCHEMA_MANAGEMENT_STRATEGY.get( buildContext.configurationPropertySource() ); schemaManagementListener = new SchemaManagementListener( schemaManagementStrategyName ); - addConfigurationContributor( new StandalonePojoTypeConfigurationContributor( entityTypeMetadataProvider ) ); + addConfigurationContributor( new StandalonePojoTypeConfigurationContributor( entityTypeMetadataByType.values() ) ); super.configure( buildContext, configurationCollector ); } @Override protected PojoMapperDelegate createMapperDelegate() { - return new StandalonePojoMapperDelegate( entityTypeMetadataProvider, schemaManagementListener ); + return new StandalonePojoMapperDelegate( schemaManagementListener ); } } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoTypeConfigurationContributor.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoTypeConfigurationContributor.java index 211a56a6805..186fa5d5e54 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoTypeConfigurationContributor.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoTypeConfigurationContributor.java @@ -6,32 +6,27 @@ */ package org.hibernate.search.mapper.pojo.standalone.mapping.impl; +import java.util.Collection; + import org.hibernate.search.engine.mapper.mapping.building.spi.MappingBuildContext; import org.hibernate.search.engine.mapper.mapping.building.spi.MappingConfigurationCollector; import org.hibernate.search.mapper.pojo.mapping.building.spi.PojoTypeMetadataContributor; import org.hibernate.search.mapper.pojo.mapping.spi.PojoMappingConfigurationContext; import org.hibernate.search.mapper.pojo.mapping.spi.PojoMappingConfigurationContributor; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl.StandalonePojoEntityTypeMetadataProvider; class StandalonePojoTypeConfigurationContributor implements PojoMappingConfigurationContributor { - private final StandalonePojoEntityTypeMetadataProvider entityTypeMetadataProvider; + private final Collection> entityTypeMetadata; - public StandalonePojoTypeConfigurationContributor( - StandalonePojoEntityTypeMetadataProvider entityTypeMetadataProvider) { - this.entityTypeMetadataProvider = entityTypeMetadataProvider; + public StandalonePojoTypeConfigurationContributor(Collection> entityTypeMetadata) { + this.entityTypeMetadata = entityTypeMetadata; } @Override public void configure(MappingBuildContext buildContext, PojoMappingConfigurationContext configurationContext, MappingConfigurationCollector configurationCollector) { - for ( PojoRawTypeModel type : entityTypeMetadataProvider.allEntityTypes() ) { - configurationCollector.collectContributor( - type, - new StandalonePojoEntityTypeContributor( - type.typeIdentifier(), entityTypeMetadataProvider.get( type ).name ) - ); + for ( var metadata : entityTypeMetadata ) { + configurationCollector.collectContributor( metadata.type, metadata ); } } } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoTypeContextContainer.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoTypeContextContainer.java index fe4839b3542..57d3cfcfd81 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoTypeContextContainer.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/impl/StandalonePojoTypeContextContainer.java @@ -15,15 +15,13 @@ import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.LoadingTypeContextProvider; import org.hibernate.search.mapper.pojo.standalone.logging.impl.Log; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl.StandalonePojoEntityTypeMetadata; import org.hibernate.search.mapper.pojo.standalone.session.impl.StandalonePojoSearchSessionTypeContextProvider; import org.hibernate.search.util.common.data.spi.KeyValueProvider; import org.hibernate.search.util.common.logging.impl.LoggerFactory; public class StandalonePojoTypeContextContainer - implements StandalonePojoSearchSessionTypeContextProvider, LoadingTypeContextProvider { + implements StandalonePojoSearchSessionTypeContextProvider { private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); private final KeyValueProvider, AbstractStandalonePojoTypeContext> byTypeIdentifier; @@ -77,12 +75,6 @@ public AbstractStandalonePojoTypeContext forExactType(PojoRawTypeIdentifi return (AbstractStandalonePojoTypeContext) byTypeIdentifier.getOrFail( typeIdentifier ); } - @Override - @SuppressWarnings("unchecked") - public AbstractStandalonePojoTypeContext forExactTypeOrNull(PojoRawTypeIdentifier typeIdentifier) { - return (AbstractStandalonePojoTypeContext) byTypeIdentifier.getOrNull( typeIdentifier ); - } - @SuppressWarnings("unchecked") public StandalonePojoIndexedTypeContext indexedForExactType(PojoRawTypeIdentifier typeIdentifier) { return (StandalonePojoIndexedTypeContext) indexedByTypeIdentifier.getOrFail( typeIdentifier ); @@ -94,7 +86,6 @@ public AbstractStandalonePojoTypeContext forExactClass(Class clazz) { return (AbstractStandalonePojoTypeContext) byExactClass.getOrFail( clazz ); } - @Override @SuppressWarnings("unchecked") public StandalonePojoIndexedTypeContext indexedForExactClass(Class clazz) { return (StandalonePojoIndexedTypeContext) indexedByExactClass.getOrFail( clazz ); @@ -114,18 +105,16 @@ static class Builder { private final List> indexedTypeContextBuilders = new ArrayList<>(); private final List> containedTypeContextBuilders = new ArrayList<>(); - StandalonePojoIndexedTypeContext.Builder addIndexed(PojoRawTypeModel typeModel, String entityName, - StandalonePojoEntityTypeMetadata metadata) { + StandalonePojoIndexedTypeContext.Builder addIndexed(PojoRawTypeModel typeModel, String entityName) { StandalonePojoIndexedTypeContext.Builder builder = - new StandalonePojoIndexedTypeContext.Builder<>( typeModel.typeIdentifier(), entityName, metadata ); + new StandalonePojoIndexedTypeContext.Builder<>( typeModel.typeIdentifier(), entityName ); indexedTypeContextBuilders.add( builder ); return builder; } - StandalonePojoContainedTypeContext.Builder addContained(PojoRawTypeModel typeModel, String entityName, - StandalonePojoEntityTypeMetadata metadata) { + StandalonePojoContainedTypeContext.Builder addContained(PojoRawTypeModel typeModel, String entityName) { StandalonePojoContainedTypeContext.Builder builder = - new StandalonePojoContainedTypeContext.Builder<>( typeModel.typeIdentifier(), entityName, metadata ); + new StandalonePojoContainedTypeContext.Builder<>( typeModel.typeIdentifier(), entityName ); containedTypeContextBuilders.add( builder ); return builder; } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/EntityConfigurer.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/EntityConfigurer.java index 0459af7d09a..4b9786eeb4e 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/EntityConfigurer.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/EntityConfigurer.java @@ -14,7 +14,7 @@ *

* If a configurer is assigned to a given entity type, * it will also apply to its subtypes, - * but its configuration can be overridden in a subtype by assigning another configurer to that subtype. + * except for subtypes that have another configurer assigned. */ @Incubating public interface EntityConfigurer { diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/impl/StandalonePojoEntityTypeMetadata.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/impl/StandalonePojoEntityTypeMetadata.java deleted file mode 100644 index d6c72e9dd7e..00000000000 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/impl/StandalonePojoEntityTypeMetadata.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl; - -import java.util.Optional; - -import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingStrategy; -import org.hibernate.search.mapper.pojo.standalone.loading.SelectionLoadingStrategy; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurationContext; - -public class StandalonePojoEntityTypeMetadata { - public final String name; - public final Optional> selectionLoadingStrategy; - public final Optional> massLoadingStrategy; - - private StandalonePojoEntityTypeMetadata(String name, Builder builder) { - this.name = name; - this.selectionLoadingStrategy = Optional.ofNullable( builder.selectionLoadingStrategy ); - this.massLoadingStrategy = Optional.ofNullable( builder.massLoadingStrategy ); - } - - public static class Builder implements EntityConfigurationContext { - private final String name; - private SelectionLoadingStrategy selectionLoadingStrategy; - private MassLoadingStrategy massLoadingStrategy; - - public Builder(String name) { - this.name = name; - } - - @Override - public void selectionLoadingStrategy(SelectionLoadingStrategy strategy) { - this.selectionLoadingStrategy = strategy; - } - - @Override - public void massLoadingStrategy(MassLoadingStrategy strategy) { - this.massLoadingStrategy = strategy; - } - - public StandalonePojoEntityTypeMetadata build() { - return new StandalonePojoEntityTypeMetadata<>( name, this ); - } - } -} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/impl/StandalonePojoEntityTypeMetadataProvider.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/impl/StandalonePojoEntityTypeMetadataProvider.java deleted file mode 100644 index 4b07a4791c8..00000000000 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/mapping/metadata/impl/StandalonePojoEntityTypeMetadataProvider.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.standalone.mapping.metadata.impl; - -import java.lang.invoke.MethodHandles; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; - -import org.hibernate.search.engine.mapper.model.spi.TypeMetadataContributorProvider; -import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeModel; -import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingStrategy; -import org.hibernate.search.mapper.pojo.standalone.loading.SelectionLoadingStrategy; -import org.hibernate.search.mapper.pojo.standalone.logging.impl.Log; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurationContext; -import org.hibernate.search.mapper.pojo.standalone.mapping.metadata.EntityConfigurer; -import org.hibernate.search.mapper.pojo.standalone.model.impl.StandalonePojoBootstrapIntrospector; -import org.hibernate.search.util.common.logging.impl.LoggerFactory; - -public class StandalonePojoEntityTypeMetadataProvider { - - private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() ); - - private final Map, StandalonePojoEntityTypeMetadata> entityTypeMetadata; - - private StandalonePojoEntityTypeMetadataProvider( - Map, StandalonePojoEntityTypeMetadata> entityTypeMetadata) { - this.entityTypeMetadata = entityTypeMetadata; - } - - public Set> allEntityTypes() { - return entityTypeMetadata.keySet(); - } - - @SuppressWarnings("unchecked") - public StandalonePojoEntityTypeMetadata get(PojoRawTypeModel type) { - return (StandalonePojoEntityTypeMetadata) entityTypeMetadata.get( type ); - } - - public static class Builder { - - private final StandalonePojoBootstrapIntrospector introspector; - - // Use a LinkedHashMap for deterministic iteration - private final Map, EntityDefinition> entityDefinitionByType = new LinkedHashMap<>(); - - public Builder(StandalonePojoBootstrapIntrospector introspector) { - this.introspector = introspector; - } - - public void addEntityType(Class clazz, String entityName, EntityConfigurer configurerOrNull) { - PojoRawTypeModel type = introspector.typeModel( clazz ); - entityDefinitionByType.merge( type, new EntityDefinition<>( type, entityName, configurerOrNull ), - EntityDefinition::mergeWith ); - } - - public StandalonePojoEntityTypeMetadataProvider build() { - TypeMetadataContributorProvider> contributorProvider = - buildMetadataContributorProvider(); - // Use a LinkedHashMap for deterministic iteration - Map, StandalonePojoEntityTypeMetadata> entityTypeMetadata = new LinkedHashMap<>(); - for ( Map.Entry, EntityDefinition> entry : entityDefinitionByType.entrySet() ) { - entityTypeMetadata.put( - entry.getKey(), - buildEntityTypeMetadata( entry.getValue(), contributorProvider ) - ); - } - return new StandalonePojoEntityTypeMetadataProvider( entityTypeMetadata ); - } - - TypeMetadataContributorProvider> buildMetadataContributorProvider() { - TypeMetadataContributorProvider.Builder> builder = - TypeMetadataContributorProvider.builder(); - for ( Map.Entry, EntityDefinition> entry : entityDefinitionByType.entrySet() ) { - EntityConfigurer configurerOrNull = entry.getValue().configurerOrNull; - if ( configurerOrNull != null ) { - builder.contributor( entry.getKey(), configurerOrNull ); - } - } - return builder.build(); - } - - private StandalonePojoEntityTypeMetadata buildEntityTypeMetadata(EntityDefinition definition, - TypeMetadataContributorProvider> contributorProvider) { - StandalonePojoEntityTypeMetadata.Builder builder = - new StandalonePojoEntityTypeMetadata.Builder<>( definition.entityName ); - for ( EntityConfigurer configurer : contributorProvider.get( definition.type ) ) { - @SuppressWarnings("unchecked") // By constructions, all configurers returned here apply to supertypes of E - EntityConfigurer castConfigurer = (EntityConfigurer) configurer; - castConfigurer.configure( toConfigurationContext( builder ) ); - } - return builder.build(); - } - - private static EntityConfigurationContext toConfigurationContext( - StandalonePojoEntityTypeMetadata.Builder builder) { - return new EntityConfigurationContext() { - @Override - public void selectionLoadingStrategy(SelectionLoadingStrategy strategy) { - builder.selectionLoadingStrategy( strategy ); - } - - @Override - public void massLoadingStrategy(MassLoadingStrategy strategy) { - builder.massLoadingStrategy( strategy ); - } - }; - } - } - - private static class EntityDefinition { - private final PojoRawTypeModel type; - private final String entityName; - private final EntityConfigurer configurerOrNull; - - private EntityDefinition(PojoRawTypeModel type, - String entityName, EntityConfigurer configurerOrNull) { - this.type = type; - this.entityName = entityName; - this.configurerOrNull = configurerOrNull; - } - - public EntityDefinition mergeWith(EntityDefinition unknownTypeOther) { - if ( !type.equals( unknownTypeOther.type ) ) { - throw log.multipleEntityTypeDefinitions( type ); - } - @SuppressWarnings("unchecked") - EntityDefinition other = (EntityDefinition) unknownTypeOther; - if ( !entityName.equals( other.entityName ) ) { - throw log.multipleEntityTypeDefinitions( type ); - } - EntityConfigurer configurerOrNull; - if ( this.configurerOrNull == null ) { - configurerOrNull = other.configurerOrNull; - } - else if ( other.configurerOrNull == null ) { - configurerOrNull = this.configurerOrNull; - } - else { - throw log.multipleEntityTypeDefinitions( type ); - } - return new EntityDefinition<>( type, entityName, configurerOrNull ); - } - } -} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/impl/StandalonePojoMassIndexingLoadingStrategy.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/impl/StandalonePojoMassIndexingLoadingStrategy.java deleted file mode 100644 index 686b590bb8f..00000000000 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/massindexing/impl/StandalonePojoMassIndexingLoadingStrategy.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.standalone.massindexing.impl; - -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassEntityLoader; -import org.hibernate.search.mapper.pojo.loading.spi.PojoMassIdentifierLoader; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingEntityLoadingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingIdentifierLoadingContext; -import org.hibernate.search.mapper.pojo.massindexing.spi.PojoMassIndexingLoadingStrategy; -import org.hibernate.search.mapper.pojo.standalone.loading.MassEntitySink; -import org.hibernate.search.mapper.pojo.standalone.loading.MassIdentifierSink; -import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingOptions; -import org.hibernate.search.mapper.pojo.standalone.loading.MassLoadingStrategy; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.LoadingTypeContextProvider; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.StandalonePojoLoadingTypeGroup; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.StandalonePojoMassEntityLoader; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.StandalonePojoMassEntitySink; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.StandalonePojoMassIdentifierLoader; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.StandalonePojoMassIdentifierSink; -import org.hibernate.search.util.common.impl.SuppressingCloser; - -public class StandalonePojoMassIndexingLoadingStrategy - implements PojoMassIndexingLoadingStrategy { - - private final StandalonePojoMassIndexingMappingContext mappingContext; - private final LoadingTypeContextProvider typeContextProvider; - private final MassLoadingStrategy delegate; - private final MassLoadingOptions options; - - public StandalonePojoMassIndexingLoadingStrategy(StandalonePojoMassIndexingMappingContext mappingContext, - LoadingTypeContextProvider typeContextProvider, - MassLoadingStrategy delegate, - MassLoadingOptions options) { - this.mappingContext = mappingContext; - this.typeContextProvider = typeContextProvider; - this.delegate = delegate; - this.options = options; - } - - @Override - public boolean equals(Object o) { - if ( this == o ) { - return true; - } - if ( o == null || getClass() != o.getClass() ) { - return false; - } - StandalonePojoMassIndexingLoadingStrategy that = (StandalonePojoMassIndexingLoadingStrategy) o; - return delegate.equals( that.delegate ); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public PojoMassIdentifierLoader createIdentifierLoader(PojoMassIndexingIdentifierLoadingContext context) { - StandalonePojoLoadingTypeGroup includedTypes = new StandalonePojoLoadingTypeGroup<>( - typeContextProvider, context.includedTypes(), mappingContext.runtimeIntrospector() ); - MassIdentifierSink sink = new StandalonePojoMassIdentifierSink<>( context.createSink() ); - return new StandalonePojoMassIdentifierLoader( delegate.createIdentifierLoader( includedTypes, sink, options ) ); - } - - @Override - public PojoMassEntityLoader createEntityLoader(PojoMassIndexingEntityLoadingContext context) { - StandalonePojoMassIndexingSessionContext session = mappingContext.createSession( context.tenantIdentifier() ); - try { - StandalonePojoLoadingTypeGroup includedTypes = new StandalonePojoLoadingTypeGroup<>( - typeContextProvider, context.includedTypes(), mappingContext.runtimeIntrospector() ); - MassEntitySink sink = new StandalonePojoMassEntitySink<>( context.createSink( session ) ); - return new StandalonePojoMassEntityLoader<>( session, - delegate.createEntityLoader( includedTypes, sink, options ) ); - } - catch (RuntimeException e) { - new SuppressingCloser( e ).push( session ); - throw e; - } - } -} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/scope/impl/SearchScopeImpl.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/scope/impl/SearchScopeImpl.java index d8cad7f99af..9a529e1adc7 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/scope/impl/SearchScopeImpl.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/scope/impl/SearchScopeImpl.java @@ -36,10 +36,10 @@ public class SearchScopeImpl implements SearchScope { private final StandalonePojoScopeMappingContext mappingContext; - private final PojoScopeDelegate> delegate; + private final PojoScopeDelegate> delegate; public SearchScopeImpl(StandalonePojoScopeMappingContext mappingContext, - PojoScopeDelegate> delegate) { + PojoScopeDelegate> delegate) { this.mappingContext = mappingContext; this.delegate = delegate; } diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/scope/impl/StandalonePojoScopeIndexedTypeContext.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/scope/impl/StandalonePojoScopeIndexedTypeContext.java deleted file mode 100644 index 18587dbb4e8..00000000000 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/scope/impl/StandalonePojoScopeIndexedTypeContext.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Hibernate Search, full-text search for your domain model - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.search.mapper.pojo.standalone.scope.impl; - -import org.hibernate.search.mapper.pojo.scope.spi.PojoScopeDelegate; -import org.hibernate.search.mapper.pojo.standalone.entity.SearchIndexedEntity; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.LoadingTypeContext; - -/** - * A mapper-specific indexed type context, - * accessible through {@link PojoScopeDelegate#includedIndexedTypes()} - * in particular. - * - * @param The entity type mapped to the index. - */ -public interface StandalonePojoScopeIndexedTypeContext - extends SearchIndexedEntity, LoadingTypeContext { - -} diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/session/impl/StandalonePojoSearchSessionTypeContextProvider.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/session/impl/StandalonePojoSearchSessionTypeContextProvider.java index 5fb5042fdf8..17ce2daf6d6 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/session/impl/StandalonePojoSearchSessionTypeContextProvider.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/session/impl/StandalonePojoSearchSessionTypeContextProvider.java @@ -6,12 +6,11 @@ */ package org.hibernate.search.mapper.pojo.standalone.session.impl; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.LoadingTypeContextProvider; import org.hibernate.search.mapper.pojo.standalone.work.impl.SearchIndexingPlanTypeContextProvider; import org.hibernate.search.util.common.data.spi.KeyValueProvider; public interface StandalonePojoSearchSessionTypeContextProvider - extends SearchIndexingPlanTypeContextProvider, LoadingTypeContextProvider { + extends SearchIndexingPlanTypeContextProvider { KeyValueProvider> indexedByEntityName(); diff --git a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/work/impl/SearchIndexingPlanTypeContext.java b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/work/impl/SearchIndexingPlanTypeContext.java index d51a44c34e0..0642a526e51 100644 --- a/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/work/impl/SearchIndexingPlanTypeContext.java +++ b/mapper/pojo-standalone/src/main/java/org/hibernate/search/mapper/pojo/standalone/work/impl/SearchIndexingPlanTypeContext.java @@ -7,9 +7,11 @@ package org.hibernate.search.mapper.pojo.standalone.work.impl; import org.hibernate.search.mapper.pojo.model.path.spi.PojoPathFilter; -import org.hibernate.search.mapper.pojo.standalone.loading.impl.LoadingTypeContext; +import org.hibernate.search.mapper.pojo.model.spi.PojoRawTypeIdentifier; -public interface SearchIndexingPlanTypeContext extends LoadingTypeContext { +public interface SearchIndexingPlanTypeContext { + + PojoRawTypeIdentifier typeIdentifier(); PojoPathFilter dirtyFilter();