package io.sphere.sdk.facets; import io.sphere.sdk.search.*; import javax.annotation.Nullable; import java.util.List; import java.util.Optional; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; abstract class BaseSelectFacet<T> extends BaseFacet<T> implements SelectFacet<T> { private final boolean multiSelect; private final boolean matchingAll; private final List<String> selectedValues; private final Optional<TermFacetResult> facetResult; private final Optional<Long> threshold; private final Optional<Long> limit; protected BaseSelectFacet(final String key, final String label, final boolean countHidden, final FacetType type, final UntypedSearchModel<T> searchModel, final boolean multiSelect, final boolean matchingAll, final List<String> selectedValues, @Nullable final TermFacetResult facetResult, @Nullable final Long threshold, @Nullable final Long limit) { super(key, label, countHidden, type, searchModel); if (threshold != null && limit != null && threshold > limit) { throw new InvalidSelectFacetConstraintsException(threshold, limit); } this.multiSelect = multiSelect; this.matchingAll = matchingAll; this.selectedValues = selectedValues; this.facetResult = Optional.ofNullable(facetResult); this.threshold = Optional.ofNullable(threshold); this.limit = Optional.ofNullable(limit); } /** * Generates the facet options according to the facet result and selected values provided. * @return the generated facet options */ protected List<FacetOption> getOptions() { return facetResult .map(result -> result.getTerms().stream() .map(termStats -> FacetOption.ofTermStats(termStats, selectedValues)) .collect(toList())) .orElse(emptyList()); } @Override public boolean isAvailable() { return threshold.map(threshold -> getOptions().size() >= threshold).orElse(true); } @Override public List<FacetOption> getAllOptions() { return getOptions(); } @Override public List<FacetOption> getLimitedOptions() { return limit.map(limit -> getOptions().stream().limit(limit).collect(toList())) .orElse(getOptions()); } @Override public boolean isMultiSelect() { return multiSelect; } @Override public boolean isMatchingAll() { return matchingAll; } @Override public List<String> getSelectedValues() { return selectedValues; } @Override public Optional<TermFacetResult> getFacetResult() { return facetResult; } @Override public Optional<Long> getThreshold() { return threshold; } @Override public Optional<Long> getLimit() { return limit; } @Override public List<FilterExpression<T>> getFilterExpressions() { final List<FilterExpression<T>> filterExpressions; if (selectedValues.isEmpty()) { filterExpressions = emptyList(); } else { if (matchingAll) { filterExpressions = selectedValues.stream() .map(selectedValue -> searchModel.filtered().by(selectedValue)) .collect(toList()); } else { filterExpressions = singletonList(searchModel.filtered().by(selectedValues)); } } return filterExpressions; } @Override public FacetExpression<T> getFacetExpression() { return searchModel.faceted().byAllTerms(); } }