Skip to content

Commit 8db2adb

Browse files
committed
HSEARCH-**** Allow to "rescope" predicate/projection factories
1 parent f98865b commit 8db2adb

File tree

26 files changed

+152
-109
lines changed

26 files changed

+152
-109
lines changed

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/logging/impl/ElasticsearchLog.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ public interface ElasticsearchLog
4040
* here to the next value.
4141
*/
4242
@LogMessage(level = TRACE)
43-
@Message(id = ID_OFFSET + 193, value = "")
43+
@Message(id = ID_OFFSET + 194, value = "")
4444
void nextLoggerIdForConvenience();
4545
}

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/logging/impl/QueryLog.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,4 +333,8 @@ SearchException vectorKnnMatchVectorTypeDiffersFromField(String absoluteFieldPat
333333
@Message(id = ID_OFFSET + 190, value = "A single-valued highlight projection requested, "
334334
+ "but the corresponding highlighter does not set number of fragments to 1.")
335335
SearchException highlighterIncompatibleCardinality();
336+
337+
@Message(id = ID_OFFSET + 193, value = "Current factory cannot be resocped to '%1$s' as it is scoped to '%2$s'.")
338+
SearchException incompatibleScopeRootType(@FormatWith(ClassFormatter.class) Class<?> requested,
339+
@FormatWith(ClassFormatter.class) Class<?> actual);
336340
}

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/predicate/dsl/impl/ElasticsearchSearchPredicateFactoryImpl.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
*/
55
package org.hibernate.search.backend.elasticsearch.search.predicate.dsl.impl;
66

7+
import org.hibernate.search.backend.elasticsearch.logging.impl.QueryLog;
78
import org.hibernate.search.backend.elasticsearch.search.predicate.dsl.ElasticsearchSearchPredicateFactory;
89
import org.hibernate.search.backend.elasticsearch.search.predicate.impl.ElasticsearchSearchPredicateIndexScope;
10+
import org.hibernate.search.engine.search.common.NonStaticMetamodelScope;
911
import org.hibernate.search.engine.search.predicate.dsl.PredicateFinalStep;
1012
import org.hibernate.search.engine.search.predicate.dsl.spi.AbstractSearchPredicateFactory;
1113
import org.hibernate.search.engine.search.predicate.dsl.spi.SearchPredicateDslContext;
@@ -32,6 +34,25 @@ public ElasticsearchSearchPredicateFactory<SR> withRoot(String objectFieldPath)
3234
dslContext.scope().withRoot( objectFieldPath ) ) );
3335
}
3436

37+
@SuppressWarnings("unchecked") // well because we check ;)
38+
@Override
39+
public <SR2> ElasticsearchSearchPredicateFactory<SR2> withScopeRoot(Class<SR2> scopeRootType) {
40+
if ( this.scopeRootType.equals( scopeRootType ) ) {
41+
return (ElasticsearchSearchPredicateFactory<SR2>) this;
42+
}
43+
if (
44+
// if we want the "untyped" version of the factory we can get it from any other factory
45+
// e.g. we have one tied to a Book__ and we want to use some "raw" string paths in a named predicate.
46+
scopeRootType.equals( NonStaticMetamodelScope.class )
47+
// scope type is in the same hierarchy:
48+
|| this.scopeRootType.isAssignableFrom( scopeRootType )
49+
|| scopeRootType.isAssignableFrom( this.scopeRootType )
50+
) {
51+
return new ElasticsearchSearchPredicateFactoryImpl<>( scopeRootType, dslContext );
52+
}
53+
throw QueryLog.INSTANCE.incompatibleScopeRootType( scopeRootType, this.scopeRootType );
54+
}
55+
3556
@Override
3657
public PredicateFinalStep fromJson(String jsonString) {
3758
return new StaticPredicateFinalStep( dslContext.scope().predicateBuilders().fromJson( jsonString ) );

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/predicate/impl/ElasticsearchNamedPredicate.java

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.hibernate.search.engine.search.predicate.SearchPredicate;
1717
import org.hibernate.search.engine.search.predicate.definition.PredicateDefinition;
1818
import org.hibernate.search.engine.search.predicate.definition.TypedPredicateDefinition;
19+
import org.hibernate.search.engine.search.predicate.dsl.ExtendedSearchPredicateFactory;
1920
import org.hibernate.search.engine.search.predicate.dsl.SearchPredicateFactory;
2021
import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory;
2122
import org.hibernate.search.engine.search.predicate.dsl.spi.SearchPredicateFactoryDelegate;
@@ -138,19 +139,8 @@ private static class BasicBuilder extends Builder {
138139

139140
@SuppressWarnings("unchecked")
140141
@Override
141-
public void factory(TypedSearchPredicateFactory<?> factory) {
142-
if ( isCompatible( factory ) ) {
143-
this.factory =
144-
new SearchPredicateFactoryDelegate( (TypedSearchPredicateFactory<NonStaticMetamodelScope>) factory );
145-
}
146-
else {
147-
throw new IllegalArgumentException( "Current search predicate factory is incompatible with this \""
148-
+ predicateName + "\" name predicate." );
149-
}
150-
}
151-
152-
private boolean isCompatible(TypedSearchPredicateFactory<?> factory) {
153-
return factory.isCompatibleWithScopeRootType( NonStaticMetamodelScope.class );
142+
public void factory(ExtendedSearchPredicateFactory<?, ?> factory) {
143+
this.factory = new SearchPredicateFactoryDelegate( factory.withScopeRoot( NonStaticMetamodelScope.class ) );
154144
}
155145

156146
@Override
@@ -175,18 +165,8 @@ private static class TypedBuilder<SR> extends Builder {
175165

176166
@SuppressWarnings("unchecked")
177167
@Override
178-
public void factory(TypedSearchPredicateFactory<?> factory) {
179-
if ( isCompatible( factory ) ) {
180-
this.factory = (TypedSearchPredicateFactory<SR>) factory;
181-
}
182-
else {
183-
throw new IllegalArgumentException( "Current search predicate factory is incompatible with this \""
184-
+ predicateName + "\" name predicate." );
185-
}
186-
}
187-
188-
private boolean isCompatible(TypedSearchPredicateFactory<?> factory) {
189-
return factory.isCompatibleWithScopeRootType( definition.scopeRootType() );
168+
public void factory(ExtendedSearchPredicateFactory<?, ?> factory) {
169+
this.factory = factory.withScopeRoot( definition.scopeRootType() );
190170
}
191171

192172
@Override

backend/elasticsearch/src/main/java/org/hibernate/search/backend/elasticsearch/search/projection/dsl/impl/ElasticsearchSearchProjectionFactoryImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import org.hibernate.search.backend.elasticsearch.search.projection.dsl.ElasticsearchSearchProjectionFactory;
88
import org.hibernate.search.backend.elasticsearch.search.projection.impl.ElasticsearchSearchProjectionIndexScope;
9+
import org.hibernate.search.engine.search.projection.dsl.ExtendedSearchProjectionFactory;
910
import org.hibernate.search.engine.search.projection.dsl.ProjectionFinalStep;
1011
import org.hibernate.search.engine.search.projection.dsl.spi.AbstractSearchProjectionFactory;
1112
import org.hibernate.search.engine.search.projection.dsl.spi.SearchProjectionDslContext;
@@ -33,6 +34,11 @@ public ElasticsearchSearchProjectionFactory<SR, R, E> withRoot(String objectFiel
3334
dslContext.scope().withRoot( objectFieldPath ) ) );
3435
}
3536

37+
@Override
38+
public <SR2> ExtendedSearchProjectionFactory<SR2, ?, R, E> withScopeRoot(Class<SR2> scopeRootType) {
39+
return new ElasticsearchSearchProjectionFactoryImpl<>( dslContext );
40+
}
41+
3642
@Override
3743
public ProjectionFinalStep<JsonObject> source() {
3844
return new StaticProjectionFinalStep<>( dslContext.scope().projectionBuilders().source() );

backend/lucene/src/main/java/org/hibernate/search/backend/lucene/logging/impl/LuceneLog.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,6 @@ public interface LuceneLog
6363
* here to the next value.
6464
*/
6565
@LogMessage(level = TRACE)
66-
@Message(id = ID_OFFSET + 194, value = "")
66+
@Message(id = ID_OFFSET + 195, value = "")
6767
void nextLoggerIdForConvenience();
6868
}

backend/lucene/src/main/java/org/hibernate/search/backend/lucene/logging/impl/QueryLog.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,4 +324,8 @@ SearchException vectorKnnMatchVectorTypeDiffersFromField(String absoluteFieldPat
324324
@Message(id = ID_OFFSET + 186, value = "A single-valued highlight projection requested, "
325325
+ "but the corresponding highlighter does not set number of fragments to 1.")
326326
SearchException highlighterIncompatibleCardinality();
327+
328+
@Message(id = ID_OFFSET + 194, value = "Current factory cannot be resocped to '%1$s' as it is scoped to '%2$s'.")
329+
SearchException incompatibleScopeRootType(@FormatWith(ClassFormatter.class) Class<?> requested,
330+
@FormatWith(ClassFormatter.class) Class<?> actual);
327331
}

backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/predicate/dsl/impl/LuceneSearchPredicateFactoryImpl.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
*/
55
package org.hibernate.search.backend.lucene.search.predicate.dsl.impl;
66

7+
import org.hibernate.search.backend.lucene.logging.impl.QueryLog;
78
import org.hibernate.search.backend.lucene.search.predicate.dsl.LuceneSearchPredicateFactory;
89
import org.hibernate.search.backend.lucene.search.predicate.impl.LuceneSearchPredicateIndexScope;
10+
import org.hibernate.search.engine.search.common.NonStaticMetamodelScope;
911
import org.hibernate.search.engine.search.predicate.dsl.PredicateFinalStep;
1012
import org.hibernate.search.engine.search.predicate.dsl.spi.AbstractSearchPredicateFactory;
1113
import org.hibernate.search.engine.search.predicate.dsl.spi.SearchPredicateDslContext;
@@ -35,4 +37,23 @@ public LuceneSearchPredicateFactory<SR> withRoot(String objectFieldPath) {
3537
public PredicateFinalStep fromLuceneQuery(Query luceneQuery) {
3638
return new StaticPredicateFinalStep( dslContext.scope().predicateBuilders().fromLuceneQuery( luceneQuery ) );
3739
}
40+
41+
@SuppressWarnings("unchecked") // well because we check ;)
42+
@Override
43+
public <SR2> LuceneSearchPredicateFactory<SR2> withScopeRoot(Class<SR2> scopeRootType) {
44+
if ( this.scopeRootType.equals( scopeRootType ) ) {
45+
return (LuceneSearchPredicateFactory<SR2>) this;
46+
}
47+
if (
48+
// if we want the "untyped" version of the factory we can get it from any other factory
49+
// e.g. we have one tied to a Book__ and we want to use some "raw" string paths in a named predicate.
50+
scopeRootType.equals( NonStaticMetamodelScope.class )
51+
// scope type is in the same hierarchy:
52+
|| this.scopeRootType.isAssignableFrom( scopeRootType )
53+
|| scopeRootType.isAssignableFrom( this.scopeRootType )
54+
) {
55+
return new LuceneSearchPredicateFactoryImpl<>( scopeRootType, dslContext );
56+
}
57+
throw QueryLog.INSTANCE.incompatibleScopeRootType( scopeRootType, this.scopeRootType );
58+
}
3859
}

backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/predicate/impl/LuceneNamedPredicate.java

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.hibernate.search.engine.search.predicate.SearchPredicate;
1717
import org.hibernate.search.engine.search.predicate.definition.PredicateDefinition;
1818
import org.hibernate.search.engine.search.predicate.definition.TypedPredicateDefinition;
19+
import org.hibernate.search.engine.search.predicate.dsl.ExtendedSearchPredicateFactory;
1920
import org.hibernate.search.engine.search.predicate.dsl.SearchPredicateFactory;
2021
import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory;
2122
import org.hibernate.search.engine.search.predicate.dsl.spi.SearchPredicateFactoryDelegate;
@@ -133,19 +134,8 @@ private static class BasicBuilder extends Builder {
133134

134135
@SuppressWarnings("unchecked")
135136
@Override
136-
public void factory(TypedSearchPredicateFactory<?> factory) {
137-
if ( isCompatible( factory ) ) {
138-
this.factory =
139-
new SearchPredicateFactoryDelegate( (TypedSearchPredicateFactory<NonStaticMetamodelScope>) factory );
140-
}
141-
else {
142-
throw new IllegalArgumentException( "Current search predicate factory is incompatible with this \""
143-
+ predicateName + "\" name predicate." );
144-
}
145-
}
146-
147-
private boolean isCompatible(TypedSearchPredicateFactory<?> factory) {
148-
return factory.isCompatibleWithScopeRootType( NonStaticMetamodelScope.class );
137+
public void factory(ExtendedSearchPredicateFactory<?, ?> factory) {
138+
this.factory = new SearchPredicateFactoryDelegate( factory.withScopeRoot( NonStaticMetamodelScope.class ) );
149139
}
150140

151141
@Override
@@ -170,18 +160,8 @@ private static class TypedBuilder<SR> extends Builder {
170160

171161
@SuppressWarnings("unchecked")
172162
@Override
173-
public void factory(TypedSearchPredicateFactory<?> factory) {
174-
if ( isCompatible( factory ) ) {
175-
this.factory = (TypedSearchPredicateFactory<SR>) factory;
176-
}
177-
else {
178-
throw new IllegalArgumentException( "Current search predicate factory is incompatible with this \""
179-
+ predicateName + "\" name predicate." );
180-
}
181-
}
182-
183-
private boolean isCompatible(TypedSearchPredicateFactory<?> factory) {
184-
return factory.isCompatibleWithScopeRootType( definition.scopeRootType() );
163+
public void factory(ExtendedSearchPredicateFactory<?, ?> factory) {
164+
this.factory = factory.withScopeRoot( definition.scopeRootType() );
185165
}
186166

187167
@Override

backend/lucene/src/main/java/org/hibernate/search/backend/lucene/search/projection/dsl/impl/LuceneSearchProjectionFactoryImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.hibernate.search.backend.lucene.search.projection.dsl.DocumentTree;
88
import org.hibernate.search.backend.lucene.search.projection.dsl.LuceneSearchProjectionFactory;
99
import org.hibernate.search.backend.lucene.search.projection.impl.LuceneSearchProjectionIndexScope;
10+
import org.hibernate.search.engine.search.projection.dsl.ExtendedSearchProjectionFactory;
1011
import org.hibernate.search.engine.search.projection.dsl.ProjectionFinalStep;
1112
import org.hibernate.search.engine.search.projection.dsl.spi.AbstractSearchProjectionFactory;
1213
import org.hibernate.search.engine.search.projection.dsl.spi.SearchProjectionDslContext;
@@ -34,6 +35,11 @@ public LuceneSearchProjectionFactory<SR, R, E> withRoot(String objectFieldPath)
3435
dslContext.scope().withRoot( objectFieldPath ) ) );
3536
}
3637

38+
@Override
39+
public <SR2> ExtendedSearchProjectionFactory<SR2, ?, R, E> withScopeRoot(Class<SR2> scopeRootType) {
40+
return new LuceneSearchProjectionFactoryImpl<>( dslContext );
41+
}
42+
3743
@Override
3844
public ProjectionFinalStep<Document> document() {
3945
return new StaticProjectionFinalStep<>( dslContext.scope().projectionBuilders().document() );

engine/src/main/java/org/hibernate/search/engine/search/predicate/dsl/ExtendedSearchPredicateFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
*/
55
package org.hibernate.search.engine.search.predicate.dsl;
66

7+
import org.hibernate.search.util.common.SearchException;
8+
import org.hibernate.search.util.common.annotation.Incubating;
9+
710
/**
811
* A base interface for subtypes of {@link TypedSearchPredicateFactory} allowing to
912
* easily override the self type for all relevant methods.
@@ -20,4 +23,9 @@ public interface ExtendedSearchPredicateFactory<SR, S extends ExtendedSearchPred
2023
@Override
2124
S withRoot(String objectFieldPath);
2225

26+
/**
27+
* @throws SearchException In case the current factory cannot be rescoped for the {@code scopeRootType}.
28+
*/
29+
@Incubating
30+
<SR2> ExtendedSearchPredicateFactory<SR2, ?> withScopeRoot(Class<SR2> scopeRootType);
2331
}

engine/src/main/java/org/hibernate/search/engine/search/predicate/dsl/TypedSearchPredicateFactory.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,4 @@ PredicateFinalStep withParameters(
392392
@Incubating
393393
String toAbsolutePath(String relativeFieldPath);
394394

395-
/**
396-
* @param scopeRootType The scope root type to test.
397-
* @return Whether the scope root type is compatible with the current predicate factory.
398-
*/
399-
@Incubating
400-
boolean isCompatibleWithScopeRootType(Class<?> scopeRootType);
401-
402395
}

engine/src/main/java/org/hibernate/search/engine/search/predicate/dsl/impl/NamedPredicateOptionsStepImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
import org.hibernate.search.engine.search.common.spi.SearchIndexScope;
88
import org.hibernate.search.engine.search.common.spi.SearchQueryElementTypeKey;
99
import org.hibernate.search.engine.search.predicate.SearchPredicate;
10+
import org.hibernate.search.engine.search.predicate.dsl.ExtendedSearchPredicateFactory;
1011
import org.hibernate.search.engine.search.predicate.dsl.NamedPredicateOptionsStep;
11-
import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory;
1212
import org.hibernate.search.engine.search.predicate.dsl.spi.AbstractPredicateFinalStep;
1313
import org.hibernate.search.engine.search.predicate.dsl.spi.SearchPredicateDslContext;
1414
import org.hibernate.search.engine.search.predicate.spi.NamedPredicateBuilder;
@@ -20,7 +20,7 @@ public class NamedPredicateOptionsStepImpl
2020

2121
private final NamedPredicateBuilder builder;
2222

23-
public NamedPredicateOptionsStepImpl(TypedSearchPredicateFactory<?> predicateFactory,
23+
public NamedPredicateOptionsStepImpl(ExtendedSearchPredicateFactory<?, ?> predicateFactory,
2424
SearchPredicateDslContext<?> dslContext, String fieldPath, String predicateName) {
2525
super( dslContext );
2626
SearchIndexScope<?> scope = dslContext.scope();

engine/src/main/java/org/hibernate/search/engine/search/predicate/dsl/spi/AbstractSearchPredicateFactory.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,4 @@ public SearchPredicateFactoryExtensionIfSupportedStep<SR> extension() {
263263
public final String toAbsolutePath(String relativeFieldPath) {
264264
return dslContext.scope().toAbsolutePath( relativeFieldPath );
265265
}
266-
267-
@Override
268-
public boolean isCompatibleWithScopeRootType(Class<?> scopeRootType) {
269-
return this.scopeRootType.equals( scopeRootType );
270-
}
271266
}

engine/src/main/java/org/hibernate/search/engine/search/predicate/dsl/spi/SearchPredicateFactoryDelegate.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,4 @@ public String toAbsolutePath(String relativeFieldPath) {
212212
return delegate.toAbsolutePath( relativeFieldPath );
213213
}
214214

215-
@Override
216-
public boolean isCompatibleWithScopeRootType(Class<?> scopeRootType) {
217-
return NonStaticMetamodelScope.class.equals( scopeRootType );
218-
}
219215
}

engine/src/main/java/org/hibernate/search/engine/search/predicate/spi/NamedPredicateBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
*/
55
package org.hibernate.search.engine.search.predicate.spi;
66

7-
import org.hibernate.search.engine.search.predicate.dsl.TypedSearchPredicateFactory;
7+
import org.hibernate.search.engine.search.predicate.dsl.ExtendedSearchPredicateFactory;
88

99
public interface NamedPredicateBuilder extends SearchPredicateBuilder {
1010

11-
void factory(TypedSearchPredicateFactory<?> factory);
11+
void factory(ExtendedSearchPredicateFactory<?, ?> factory);
1212

1313
void param(String name, Object value);
1414

engine/src/main/java/org/hibernate/search/engine/search/projection/dsl/ExtendedSearchProjectionFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55
package org.hibernate.search.engine.search.projection.dsl;
66

7+
import org.hibernate.search.util.common.annotation.Incubating;
8+
79
/**
810
* A base interface for subtypes of {@link TypedSearchProjectionFactory} allowing to
911
* easily override the self type for all relevant methods.
@@ -20,4 +22,10 @@ public interface ExtendedSearchProjectionFactory<SR, S extends ExtendedSearchPro
2022
@Override
2123
S withRoot(String objectFieldPath);
2224

25+
/**
26+
* @throws IllegalArgumentException In case the current factory cannot be rescoped for the {@code scopeRootType}.
27+
*/
28+
@Incubating
29+
<SR2> ExtendedSearchProjectionFactory<SR2, ?, R, E> withScopeRoot(Class<SR2> scopeRootType);
30+
2331
}

0 commit comments

Comments
 (0)