Skip to content

Commit 0e55e82

Browse files
committed
HSEARCH-4577 Add default methods as shortcuts to accumulator calls
1 parent d4e10c4 commit 0e55e82

File tree

14 files changed

+526
-34
lines changed

14 files changed

+526
-34
lines changed

documentation/src/main/asciidoc/migration/index.adoc

+2-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ interfaces are removed in this version. They have their alternatives in a `org.h
103103
Instead, we are introducing the `org.hibernate.search.mapper.pojo.massindexing.MassIndexingTypeGroupMonitor`
104104
that can be obtained through `org.hibernate.search.mapper.pojo.massindexing.MassIndexingMonitor#typeGroupMonitor(..)`.
105105
This new type group monitor has more flexibility and also allows implementors to skip total count computations if needed.
106-
- `multi()` methods exposed in various projection DSL steps are deprecated in favour of an `accumulator(ProjectionAccumulator.Provider)`.
106+
- `multi()` methods exposed in various projection DSL steps are deprecated in favour of an `accumulator(ProjectionAccumulator.Provider)`,
107+
or one of the "shortcut-methods": `.list()`/`.set()`/`.sortedSet()`...
107108
Check the `ProjectionAccumulator` factory methods to see the list of built-in accumulators that provide support for nullable/optional single-valued projections
108109
and for multivalued ones such as lists, sets arrays and more.
109110

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

+62
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
*/
55
package org.hibernate.search.engine.search.projection.dsl;
66

7+
import java.util.Comparator;
78
import java.util.List;
9+
import java.util.Optional;
10+
import java.util.Set;
11+
import java.util.SortedSet;
812

913
import org.hibernate.search.engine.search.projection.ProjectionAccumulator;
14+
import org.hibernate.search.util.common.annotation.Incubating;
1015

1116
/**
1217
* The step in a composite projection definition
@@ -55,4 +60,61 @@ default CompositeProjectionOptionsStep<?, List<T>> multi() {
5560
*/
5661
<R> CompositeProjectionOptionsStep<?, R> accumulator(ProjectionAccumulator.Provider<T, R> accumulator);
5762

63+
/**
64+
* Defines the projection as single-valued wrapped in an {@link Optional}, i.e. returning {@code Optional<T>} instead of {@code T}.
65+
*
66+
* @return A new step to define optional parameters.
67+
*/
68+
@Incubating
69+
default CompositeProjectionOptionsStep<?, Optional<T>> optional() {
70+
return accumulator( ProjectionAccumulator.optional() );
71+
}
72+
73+
/**
74+
* Defines the projection as multivalued, i.e. returning {@code List<T>} instead of {@code T}.
75+
* @return A new step to define optional parameters.
76+
*/
77+
@Incubating
78+
default CompositeProjectionOptionsStep<?, List<T>> list() {
79+
return accumulator( ProjectionAccumulator.list() );
80+
}
81+
82+
/**
83+
* Defines the projection as multivalued, i.e. returning {@code Set<T>} instead of {@code T}.
84+
* @return A new step to define optional parameters.
85+
*/
86+
@Incubating
87+
default CompositeProjectionOptionsStep<?, Set<T>> set() {
88+
return accumulator( ProjectionAccumulator.set() );
89+
}
90+
91+
/**
92+
* Defines the projection as multivalued, i.e. returning {@code SortedSet<T>} instead of {@code T}.
93+
* @return A new step to define optional parameters.
94+
*/
95+
@Incubating
96+
default CompositeProjectionOptionsStep<?, SortedSet<T>> sortedSet() {
97+
return accumulator( ProjectionAccumulator.sortedSet() );
98+
}
99+
100+
/**
101+
* Defines the projection as multivalued, i.e. returning {@code SortedSet<T>} instead of {@code T}.
102+
* @param comparator The comparator to use for sorting elements within the set.
103+
* @return A new step to define optional parameters.
104+
*/
105+
@Incubating
106+
default CompositeProjectionOptionsStep<?, SortedSet<T>> sortedSet(Comparator<T> comparator) {
107+
return accumulator( ProjectionAccumulator.sortedSet( comparator ) );
108+
}
109+
110+
/**
111+
* Defines the projection as multivalued, i.e. returning {@code T[]} instead of {@code T}.
112+
* @param type The type of array elements.
113+
* @return A new step to define optional parameters.
114+
*/
115+
@Incubating
116+
default CompositeProjectionOptionsStep<?, T[]> array(Class<T> type) {
117+
return accumulator( ProjectionAccumulator.array( type ) );
118+
}
119+
58120
}

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

+62
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
*/
55
package org.hibernate.search.engine.search.projection.dsl;
66

7+
import java.util.Comparator;
78
import java.util.List;
9+
import java.util.Optional;
10+
import java.util.Set;
11+
import java.util.SortedSet;
812

913
import org.hibernate.search.engine.search.projection.ProjectionAccumulator;
14+
import org.hibernate.search.util.common.annotation.Incubating;
1015

1116
/**
1217
* The initial step in a "distance to field" projection definition,
@@ -51,4 +56,61 @@ default DistanceToFieldProjectionOptionsStep<?, List<T>> multi() {
5156
* @param <R> The type of the final result.
5257
*/
5358
<R> DistanceToFieldProjectionOptionsStep<?, R> accumulator(ProjectionAccumulator.Provider<T, R> accumulator);
59+
60+
/**
61+
* Defines the projection as single-valued wrapped in an {@link Optional}, i.e. returning {@code Optional<T>} instead of {@code T}.
62+
*
63+
* @return A new step to define optional parameters.
64+
*/
65+
@Incubating
66+
default DistanceToFieldProjectionOptionsStep<?, Optional<T>> optional() {
67+
return accumulator( ProjectionAccumulator.optional() );
68+
}
69+
70+
/**
71+
* Defines the projection as multivalued, i.e. returning {@code List<T>} instead of {@code T}.
72+
* @return A new step to define optional parameters.
73+
*/
74+
@Incubating
75+
default DistanceToFieldProjectionOptionsStep<?, List<T>> list() {
76+
return accumulator( ProjectionAccumulator.list() );
77+
}
78+
79+
/**
80+
* Defines the projection as multivalued, i.e. returning {@code Set<T>} instead of {@code T}.
81+
* @return A new step to define optional parameters.
82+
*/
83+
@Incubating
84+
default DistanceToFieldProjectionOptionsStep<?, Set<T>> set() {
85+
return accumulator( ProjectionAccumulator.set() );
86+
}
87+
88+
/**
89+
* Defines the projection as multivalued, i.e. returning {@code SortedSet<T>} instead of {@code T}.
90+
* @return A new step to define optional parameters.
91+
*/
92+
@Incubating
93+
default DistanceToFieldProjectionOptionsStep<?, SortedSet<T>> sortedSet() {
94+
return accumulator( ProjectionAccumulator.sortedSet() );
95+
}
96+
97+
/**
98+
* Defines the projection as multivalued, i.e. returning {@code SortedSet<T>} instead of {@code T}.
99+
* @param comparator The comparator to use for sorting elements within the set.
100+
* @return A new step to define optional parameters.
101+
*/
102+
@Incubating
103+
default DistanceToFieldProjectionOptionsStep<?, SortedSet<T>> sortedSet(Comparator<T> comparator) {
104+
return accumulator( ProjectionAccumulator.sortedSet( comparator ) );
105+
}
106+
107+
/**
108+
* Defines the projection as multivalued, i.e. returning {@code T[]} instead of {@code T}.
109+
* @param type The type of array elements.
110+
* @return A new step to define optional parameters.
111+
*/
112+
@Incubating
113+
default DistanceToFieldProjectionOptionsStep<?, T[]> array(Class<T> type) {
114+
return accumulator( ProjectionAccumulator.array( type ) );
115+
}
54116
}

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

+63-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
*/
55
package org.hibernate.search.engine.search.projection.dsl;
66

7+
import java.util.Comparator;
78
import java.util.List;
9+
import java.util.Optional;
10+
import java.util.Set;
11+
import java.util.SortedSet;
812

913
import org.hibernate.search.engine.search.projection.ProjectionAccumulator;
14+
import org.hibernate.search.util.common.annotation.Incubating;
1015

1116
/**
1217
* The initial step in a "field" projection definition,
@@ -42,7 +47,7 @@ default FieldProjectionOptionsStep<?, List<T>> multi() {
4247
/**
4348
* Defines how to accumulate field projection values.
4449
* <p>
45-
* Calling {@code .accumulator(someMultiValuedAccumulatorProvider) } is mandatory for multi-valued fields,
50+
* Calling {@code .accumulator(someMultiValuedAccumulatorProvider) } is mandatory for multivalued fields,
4651
* e.g. {@code .accumulator(ProjectionAccumulator.list())},
4752
* otherwise the projection will throw an exception upon creating the query.
4853
*
@@ -51,4 +56,61 @@ default FieldProjectionOptionsStep<?, List<T>> multi() {
5156
* @param <R> The type of the final result.
5257
*/
5358
<R> FieldProjectionOptionsStep<?, R> accumulator(ProjectionAccumulator.Provider<T, R> accumulator);
59+
60+
/**
61+
* Defines the projection as single-valued wrapped in an {@link Optional}, i.e. returning {@code Optional<T>} instead of {@code T}.
62+
*
63+
* @return A new step to define optional parameters.
64+
*/
65+
@Incubating
66+
default FieldProjectionOptionsStep<?, Optional<T>> optional() {
67+
return accumulator( ProjectionAccumulator.optional() );
68+
}
69+
70+
/**
71+
* Defines the projection as multivalued, i.e. returning {@code List<T>} instead of {@code T}.
72+
* @return A new step to define optional parameters.
73+
*/
74+
@Incubating
75+
default FieldProjectionOptionsStep<?, List<T>> list() {
76+
return accumulator( ProjectionAccumulator.list() );
77+
}
78+
79+
/**
80+
* Defines the projection as multivalued, i.e. returning {@code Set<T>} instead of {@code T}.
81+
* @return A new step to define optional parameters.
82+
*/
83+
@Incubating
84+
default FieldProjectionOptionsStep<?, Set<T>> set() {
85+
return accumulator( ProjectionAccumulator.set() );
86+
}
87+
88+
/**
89+
* Defines the projection as multivalued, i.e. returning {@code SortedSet<T>} instead of {@code T}.
90+
* @return A new step to define optional parameters.
91+
*/
92+
@Incubating
93+
default FieldProjectionOptionsStep<?, SortedSet<T>> sortedSet() {
94+
return accumulator( ProjectionAccumulator.sortedSet() );
95+
}
96+
97+
/**
98+
* Defines the projection as multivalued, i.e. returning {@code SortedSet<T>} instead of {@code T}.
99+
* @param comparator The comparator to use for sorting elements within the set.
100+
* @return A new step to define optional parameters.
101+
*/
102+
@Incubating
103+
default FieldProjectionOptionsStep<?, SortedSet<T>> sortedSet(Comparator<T> comparator) {
104+
return accumulator( ProjectionAccumulator.sortedSet( comparator ) );
105+
}
106+
107+
/**
108+
* Defines the projection as multivalued, i.e. returning {@code T[]} instead of {@code T}.
109+
* @param type The type of array elements.
110+
* @return A new step to define optional parameters.
111+
*/
112+
@Incubating
113+
default FieldProjectionOptionsStep<?, T[]> array(Class<T> type) {
114+
return accumulator( ProjectionAccumulator.array( type ) );
115+
}
54116
}

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

+74
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44
*/
55
package org.hibernate.search.engine.search.projection.dsl;
66

7+
import java.util.Comparator;
8+
import java.util.Optional;
9+
import java.util.Set;
10+
import java.util.SortedSet;
711
import java.util.function.Function;
812

913
import org.hibernate.search.engine.search.highlighter.dsl.HighlighterOptionsStep;
1014
import org.hibernate.search.engine.search.projection.ProjectionAccumulator;
15+
import org.hibernate.search.util.common.annotation.Incubating;
1116

1217
/**
1318
* The initial and final step in a highlight definition, where optional parameters can be set.
@@ -59,4 +64,73 @@ public interface HighlightProjectionOptionsStep extends HighlightProjectionFinal
5964
* @param <R> The type of the final result.
6065
*/
6166
<R> ProjectionFinalStep<R> accumulator(ProjectionAccumulator.Provider<String, R> accumulator);
67+
68+
/**
69+
* Defines the projection as single-valued, i.e. returning {@code String} instead of {@code List<String>}.
70+
* <p>
71+
* Can only be used when the highlighter that creates highlighted fragments for this projection is configured
72+
* to return a single fragment at most, i.e. when {@link HighlighterOptionsStep#numberOfFragments(int) .numberOfFragments(1)}
73+
* is applied to the highlighter.
74+
* Otherwise, it will lead to an exception being thrown when the query is created.
75+
*
76+
* @return A final step in the highlight projection definition.
77+
* @see HighlighterOptionsStep#numberOfFragments(int)
78+
*/
79+
@Incubating
80+
default ProjectionFinalStep<String> nullable() {
81+
return accumulator( ProjectionAccumulator.nullable() );
82+
}
83+
84+
/**
85+
* Defines the projection as single-valued wrapped in an {@link Optional}, i.e. returning {@code Optional<String>} instead of {@code List<String>}.
86+
* <p>
87+
* Can only be used when the highlighter that creates highlighted fragments for this projection is configured
88+
* to return a single fragment at most, i.e. when {@link HighlighterOptionsStep#numberOfFragments(int) .numberOfFragments(1)}
89+
* is applied to the highlighter.
90+
* Otherwise, it will lead to an exception being thrown when the query is created.
91+
*
92+
* @return A final step in the highlight projection definition.
93+
* @see HighlighterOptionsStep#numberOfFragments(int)
94+
*/
95+
@Incubating
96+
default ProjectionFinalStep<Optional<String>> optional() {
97+
return accumulator( ProjectionAccumulator.optional() );
98+
}
99+
100+
/**
101+
* Changes the collection accumulating the values to {@link Set} instead of {@link java.util.List}.
102+
* @return A final step in the highlight projection definition.
103+
*/
104+
@Incubating
105+
default ProjectionFinalStep<Set<String>> set() {
106+
return accumulator( ProjectionAccumulator.set() );
107+
}
108+
109+
/**
110+
* Changes the collection accumulating the values to {@link SortedSet} instead of {@link java.util.List}.
111+
* @return A final step in the highlight projection definition.
112+
*/
113+
@Incubating
114+
default ProjectionFinalStep<SortedSet<String>> sortedSet() {
115+
return accumulator( ProjectionAccumulator.sortedSet() );
116+
}
117+
118+
/**
119+
* Changes the collection accumulating the values to {@link SortedSet} instead of {@link java.util.List}.
120+
* @param comparator The comparator to use for sorting strings within the set.
121+
* @return A final step in the highlight projection definition.
122+
*/
123+
@Incubating
124+
default ProjectionFinalStep<SortedSet<String>> sortedSet(Comparator<String> comparator) {
125+
return accumulator( ProjectionAccumulator.sortedSet( comparator ) );
126+
}
127+
128+
/**
129+
* Changes the collection accumulating the values to {@code String[]} instead of {@link java.util.List}.
130+
* @return A final step in the highlight projection definition.
131+
*/
132+
@Incubating
133+
default ProjectionFinalStep<String[]> array() {
134+
return accumulator( ProjectionAccumulator.array( String.class ) );
135+
}
62136
}

integrationtest/backend/elasticsearch/src/test/java/org/hibernate/search/integrationtest/backend/elasticsearch/testsupport/util/ElasticsearchTckBackendFeatures.java

+13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.time.ZoneOffset;
2323
import java.time.ZonedDateTime;
2424
import java.time.temporal.TemporalAccessor;
25+
import java.util.ArrayList;
2526
import java.util.Comparator;
2627
import java.util.LinkedHashMap;
2728
import java.util.Locale;
@@ -31,6 +32,7 @@
3132
import org.hibernate.search.backend.elasticsearch.types.format.impl.ElasticsearchDefaultFieldFormatProvider;
3233
import org.hibernate.search.engine.backend.types.VectorSimilarity;
3334
import org.hibernate.search.engine.cfg.spi.FormatUtils;
35+
import org.hibernate.search.engine.search.projection.ProjectionAccumulator;
3436
import org.hibernate.search.engine.spatial.GeoPoint;
3537
import org.hibernate.search.integrationtest.backend.tck.testsupport.types.BigDecimalFieldTypeDescriptor;
3638
import org.hibernate.search.integrationtest.backend.tck.testsupport.types.FieldTypeDescriptor;
@@ -514,4 +516,15 @@ public <F> boolean rawAggregationProduceSensibleDoubleValue(FieldTypeDescriptor<
514516
}
515517
return super.rawAggregationProduceSensibleDoubleValue( fFieldTypeDescriptor );
516518
}
519+
520+
@Override
521+
public <U, R> R accumulatedNullValue(ProjectionAccumulator.Provider<U, R> accumulator) {
522+
return accumulatedNullValue( accumulator.get() );
523+
}
524+
525+
private <U, R, A> R accumulatedNullValue(ProjectionAccumulator<Object, U, A, R> accumulator) {
526+
ArrayList<Object> values = new ArrayList<>();
527+
values.add( null );
528+
return accumulator.finish( accumulator.accumulateAll( accumulator.createInitial(), values ) );
529+
}
517530
}

0 commit comments

Comments
 (0)