Skip to content

Commit

Permalink
HSEARCH-3290 Simplify the predicate/sort DSL contexts
Browse files Browse the repository at this point in the history
Now that we don't need to support the fluent ("fluid") syntax, we can
have simpler implementations.
  • Loading branch information
yrodiere authored and gsmet committed Nov 2, 2018
1 parent b550c29 commit 3ad0c32
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 137 deletions.
Expand Up @@ -58,7 +58,7 @@ public SearchSort toSearchSort(List<ElasticsearchSearchSortBuilder> builders) {
}

@Override
public void toImplementation(SearchSort sort, Consumer<ElasticsearchSearchSortBuilder> implementationConsumer) {
public void toImplementation(SearchSort sort, Consumer<? super ElasticsearchSearchSortBuilder> implementationConsumer) {
if ( !( sort instanceof ElasticsearchSearchSort ) ) {
throw log.cannotMixElasticsearchSearchSortWithOtherSorts( sort );
}
Expand Down
Expand Up @@ -48,7 +48,7 @@ public SearchSort toSearchSort(List<LuceneSearchSortBuilder> builders) {
}

@Override
public void toImplementation(SearchSort sort, Consumer<LuceneSearchSortBuilder> implementationConsumer) {
public void toImplementation(SearchSort sort, Consumer<? super LuceneSearchSortBuilder> implementationConsumer) {
if ( !( sort instanceof LuceneSearchSort ) ) {
throw log.cannotMixLuceneSearchSortWithOtherSorts( sort );
}
Expand Down
Expand Up @@ -6,14 +6,18 @@
*/
package org.hibernate.search.engine.search.dsl.predicate.impl;

import java.lang.invoke.MethodHandles;
import java.util.function.Consumer;

import org.hibernate.search.engine.backend.index.spi.IndexSearchTarget;
import org.hibernate.search.engine.logging.impl.Log;
import org.hibernate.search.engine.search.SearchPredicate;
import org.hibernate.search.engine.search.dsl.predicate.spi.SearchPredicateContributor;
import org.hibernate.search.engine.search.dsl.predicate.spi.SearchPredicateDslContext;
import org.hibernate.search.engine.search.dsl.query.SearchQueryResultContext;
import org.hibernate.search.engine.search.predicate.spi.SearchPredicateFactory;
import org.hibernate.search.util.AssertionFailure;
import org.hibernate.search.util.impl.common.LoggerFactory;

/**
* A DSL context used when building a {@link SearchPredicate} object,
Expand All @@ -24,10 +28,12 @@
public final class RootSearchPredicateDslContextImpl<B>
implements SearchPredicateDslContext<SearchPredicate, B> {

private final SearchPredicateFactory<?, B> factory;
private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private final SearchPredicateContributorAggregator<B> aggregator = new SearchPredicateContributorAggregator<>();
private final SearchPredicateFactory<?, B> factory;

private SearchPredicateContributor<? extends B> singlePredicateContributor;
private boolean usedContributor = false;
private SearchPredicate predicateResult;

public RootSearchPredicateDslContextImpl(SearchPredicateFactory<?, B> factory) {
Expand All @@ -36,13 +42,26 @@ public RootSearchPredicateDslContextImpl(SearchPredicateFactory<?, B> factory) {

@Override
public void addChild(SearchPredicateContributor<? extends B> child) {
aggregator.add( child );
if ( usedContributor ) {
throw log.cannotAddPredicateToUsedContext();
}
if ( this.singlePredicateContributor != null ) {
throw log.cannotAddMultiplePredicatesToQueryRoot();
}
this.singlePredicateContributor = child;
}

@Override
public SearchPredicate getNextContext() {
if ( predicateResult == null ) {
predicateResult = factory.toSearchPredicate( aggregator.contribute() );
if ( usedContributor ) {
// HSEARCH-3207: we must never call a contribution twice. Contributions may have side-effects.
throw new AssertionFailure(
"A predicate object was requested after the corresponding information was contributed to the DSL." +
" There is a bug in Hibernate Search, please report it."
);
}
predicateResult = factory.toSearchPredicate( getResultingBuilder() );
}
return predicateResult;
}
Expand All @@ -58,12 +77,19 @@ public B getResultingBuilder() {
return factory.toImplementation( predicateResult );
}
else {
if ( usedContributor ) {
// HSEARCH-3207: we must never call a contribution twice. Contributions may have side-effects.
throw new AssertionFailure(
"A predicate contributor was called twice. There is a bug in Hibernate Search, please report it."
);
}
usedContributor = true;
/*
* Optimization: we know the user will not be able to request a SearchPredicate object anymore,
* so we don't need to build a SearchPredicate object in this case,
* we can just use the builder collected by the aggregator directly.
*/
return aggregator.contribute();
return singlePredicateContributor.contribute();
}
}
}

This file was deleted.

Expand Up @@ -6,16 +6,20 @@
*/
package org.hibernate.search.engine.search.dsl.sort.impl;

import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import org.hibernate.search.engine.backend.index.spi.IndexSearchTarget;
import org.hibernate.search.engine.logging.impl.Log;
import org.hibernate.search.engine.search.SearchSort;
import org.hibernate.search.engine.search.dsl.query.SearchQueryContext;
import org.hibernate.search.engine.search.dsl.sort.spi.SearchSortContributor;
import org.hibernate.search.engine.search.dsl.sort.spi.SearchSortDslContext;
import org.hibernate.search.engine.search.sort.spi.SearchSortFactory;
import org.hibernate.search.util.AssertionFailure;
import org.hibernate.search.util.impl.common.LoggerFactory;

/**
* A DSL context used when building a {@link SearchSort} object,
Expand All @@ -26,26 +30,37 @@
public final class RootSearchSortDslContextImpl<B>
implements SearchSortDslContext<SearchSort, B> {

private final SearchSortFactory<?, B> factory;
private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );

private final SearchSortContributorAggregator<B> aggregator = new SearchSortContributorAggregator<>();
protected final SearchSortFactory<?, B> factory;

private final List<SearchSortContributor<? extends B>> sortContributors = new ArrayList<>();
private SearchSort sortResult;
private boolean usedContributors = false;

public RootSearchSortDslContextImpl(SearchSortFactory<?, B> factory) {
this.factory = factory;
}

@Override
public void addChild(SearchSortContributor<? extends B> contributor) {
aggregator.add( contributor );
public void addChild(SearchSortContributor<? extends B> child) {
if ( usedContributors ) {
throw log.cannotAddSortToUsedContext();
}
sortContributors.add( child );
}

@Override
public SearchSort getNextContext() {
if ( sortResult == null ) {
List<B> builderResult = new ArrayList<>();
aggregator.contribute( builderResult::add );
if ( usedContributors ) {
// HSEARCH-3207: we must never call a contribution twice. Contributions may have side-effects.
throw new AssertionFailure(
"A sort object was requested after the corresponding information was contributed to the DSL." +
" There is a bug in Hibernate Search, please report it."
);
}
List<B> builderResult = getResultingBuilders();
sortResult = factory.toSearchSort( builderResult );
}
return sortResult;
Expand All @@ -63,12 +78,21 @@ public List<B> getResultingBuilders() {
factory.toImplementation( sortResult, builderResult::add );
}
else {
if ( usedContributors ) {
// HSEARCH-3207: we must never call a contribution twice. Contributions may have side-effects.
throw new AssertionFailure(
"A sort contributor was called twice. There is a bug in Hibernate Search, please report it."
);
}
usedContributors = true;
/*
* Optimization: we know the user will not be able to request a SearchSort object anymore,
* so we don't need to build a SearchSort object in this case,
* we can just use the builders collected by the aggregator directly.
*/
aggregator.contribute( builderResult::add );
for ( SearchSortContributor<? extends B> sortContributor : sortContributors ) {
sortContributor.contribute( builderResult::add );
}
}
return builderResult;
}
Expand Down
Expand Up @@ -34,16 +34,7 @@ public SearchSortContainerContextImpl(SearchSortFactory<?, B> factory, SearchSor
@Override
public NonEmptySortContext<N> by(SearchSort sort) {
factory.toImplementation( sort, dslContext::addChild );
return new NonEmptySortContext<N>() {
@Override
public SearchSortContainerContext<N> then() {
return SearchSortContainerContextImpl.this;
}
@Override
public N end() {
return dslContext.getNextContext();
}
};
return nonEmptyContext();
}

@Override
Expand Down

This file was deleted.

Expand Up @@ -46,7 +46,7 @@ public interface SearchSortFactory<C, B> {
* @throws SearchException If the {@link SearchSort} object was created
* by a different, incompatible factory.
*/
void toImplementation(SearchSort sort, Consumer<B> implementationConsumer);
void toImplementation(SearchSort sort, Consumer<? super B> implementationConsumer);

/**
* Contribute a sort builder to a collector.
Expand Down
Expand Up @@ -25,7 +25,7 @@ public SearchSort toSearchSort(List<StubSortBuilder> builders) {
}

@Override
public void toImplementation(SearchSort sort, Consumer<StubSortBuilder> implementationConsumer) {
public void toImplementation(SearchSort sort, Consumer<? super StubSortBuilder> implementationConsumer) {
((StubSearchSort) sort).getBuilders().forEach( implementationConsumer );
}

Expand Down

0 comments on commit 3ad0c32

Please sign in to comment.