package com.constellio.app.ui.pages.search; import static com.constellio.app.ui.i18n.i18n.$; import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.from; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.StringUtils; import com.constellio.app.ui.entities.FacetVO; import com.constellio.app.ui.entities.FacetValueVO; import com.constellio.data.dao.dto.records.FacetValue; import com.constellio.data.utils.comparators.AbstractTextComparator; import com.constellio.model.entities.Language; import com.constellio.model.entities.records.Record; import com.constellio.model.entities.records.wrappers.Facet; import com.constellio.model.entities.records.wrappers.structure.FacetOrderType; import com.constellio.model.entities.records.wrappers.structure.FacetType; import com.constellio.model.entities.schemas.Metadata; import com.constellio.model.entities.schemas.MetadataSchemaTypes; import com.constellio.model.entities.schemas.MetadataValueType; import com.constellio.model.entities.schemas.Schemas; import com.constellio.model.services.factories.ModelLayerFactory; import com.constellio.model.services.records.RecordServices; import com.constellio.model.services.records.SchemasRecordsServices; import com.constellio.model.services.schemas.MetadataSchemasManager; import com.constellio.model.services.search.SPEQueryResponse; import com.constellio.model.services.search.SearchServices; import com.constellio.model.services.search.query.logical.LogicalSearchQuery; import com.constellio.model.utils.EnumWithSmallCodeUtils; public class SearchPresenterService { private SchemasRecordsServices schemas; private SearchServices searchServices; private RecordServices recordServices; private MetadataSchemasManager metadataSchemasManager; public SearchPresenterService(final String collection, ModelLayerFactory modelLayerFactory) { this.searchServices = modelLayerFactory.newSearchServices(); this.recordServices = modelLayerFactory.newRecordServices(); this.schemas = new SchemasRecordsServices(collection, modelLayerFactory); this.metadataSchemasManager = modelLayerFactory.getMetadataSchemasManager(); } List<FacetVO> getFacets(LogicalSearchQuery query, Map<String, Boolean> facetStatus) { LogicalSearchQuery facetQuery = prepareFacetQuery(query); return buildFacetVOs(searchServices.query(facetQuery), facetStatus); } private List<FacetVO> buildFacetVOs(SPEQueryResponse response, Map<String, Boolean> facetStatus) { List<FacetVO> result = new ArrayList<>(); for (Facet facet : getActiveFacets()) { List<FacetValueVO> values = new ArrayList<>(); if (facet.getFacetType() == FacetType.FIELD) { buildFieldFacet(response, facet, values); } else { buildQueryFacet(response, facet, values); } if (!values.isEmpty()) { if (facet.getOrderResult() == FacetOrderType.ALPHABETICAL) { Collections.sort(values, new ComparatorByLabel()); } boolean open = Boolean.TRUE.equals(facetStatus.containsKey(facet.getId()) ? facetStatus.get(facet.getId()) : facet.isOpenByDefault()); result.add(new FacetVO(facet.getId(), facet.getTitle(), values, open, facet.getElementPerPage())); } } return result; } private void buildQueryFacet(SPEQueryResponse response, Facet facet, List<FacetValueVO> values) { for (Entry<String, String> queryFacet : facet.getListQueries().entrySet()) { FacetValue facetValue = response.getQueryFacetValue(queryFacet.getKey()); if (facetValue.getQuantity() > 0) { values.add(new FacetValueVO(facet.getId(), facetValue, queryFacet.getValue())); } } } private void buildFieldFacet(SPEQueryResponse response, Facet facet, List<FacetValueVO> values) { for (FacetValue facetValue : response.getFieldFacetValues(facet.getFieldDataStoreCode())) { values.add(new FacetValueVO(facet.getId(), facetValue)); } setFieldFacetValuesLabels(facet, values); } private LogicalSearchQuery prepareFacetQuery(LogicalSearchQuery query) { LogicalSearchQuery facetQuery = new LogicalSearchQuery(query).setNumberOfRows(0); for (Facet facet : getActiveFacets()) { if (facet.getFacetType() == FacetType.FIELD) { facetQuery.addFieldFacet(facet.getFieldDataStoreCode()); } else { for (Entry<String, String> entry : facet.getListQueries().entrySet()) { facetQuery.addQueryFacet(facet.getId(), entry.getKey()); } } } facetQuery.setFieldFacetLimit(100); return facetQuery; } private static class ComparatorByLabel extends AbstractTextComparator<FacetValueVO> { @Override protected String getText(FacetValueVO object) { return object.getLabel(); } } private void setFieldFacetValuesLabels(Facet facet, List<FacetValueVO> facetValueVOs) { Map<String, String> enumMetadatas = findEnumMetadatasLabels(facet.getFieldDataStoreCode()); String datastoreCode = facet.getFieldDataStoreCode(); MetadataSchemaTypes types = metadataSchemasManager.getSchemaTypes(facet.getCollection()); for (FacetValueVO facetValueVO : facetValueVOs) { String value = facetValueVO.getValue(); if (datastoreCode.equals(Schemas.SCHEMA.getDataStoreCode())) { List<Language> languages = metadataSchemasManager.getSchemaTypes(facet.getCollection()).getLanguages(); for (Language language : languages) { facetValueVO.setLabel(types.getSchema(value).getLabel(language)); } } else if (datastoreCode.endsWith("Id_s") || datastoreCode.endsWith("Id_ss")) { Record record = recordServices.getDocumentById(value); facetValueVO.setLabel(record.<String>get(Schemas.TITLE)); } else if (enumMetadatas.containsKey(value)) { facetValueVO.setLabel(enumMetadatas.get(value)); } else { facetValueVO.setLabel(facet.getFieldValueLabel(facetValueVO.getValue())); } if (StringUtils.isBlank(facetValueVO.getLabel())) { facetValueVO.setLabel(facetValueVO.getValue()); } } } private Map<String, String> findEnumMetadatasLabels(String fieldDataStoreCode) { Map<String, String> enumMetadatasLabels = new HashMap<>(); for (Metadata metadata : schemas.getTypes().getAllMetadatas().onlyWithType(MetadataValueType.ENUM)) { if (metadata.getDataStoreCode().equals(fieldDataStoreCode)) { for (String code : EnumWithSmallCodeUtils.toSmallCodeList(metadata.getEnumClass())) { String label = $(metadata.getEnumClass().getSimpleName() + "." + code); enumMetadatasLabels.put(code, label); } } } return enumMetadatasLabels; } List<Facet> getActiveFacets() { LogicalSearchQuery query = new LogicalSearchQuery(from(schemas.facetSchemaType()).where(schemas.facetActive()).isTrue()) .sortAsc(schemas.facetOrder()); return schemas.wrapFacets(searchServices.search(query)); } }