package com.constellio.app.ui.pages.management.facet;
import static com.constellio.app.ui.i18n.i18n.$;
import static com.constellio.model.entities.schemas.MetadataValueType.BOOLEAN;
import static com.constellio.model.entities.schemas.MetadataValueType.ENUM;
import static com.constellio.model.entities.schemas.MetadataValueType.INTEGER;
import static com.constellio.model.entities.schemas.MetadataValueType.NUMBER;
import static com.constellio.model.entities.schemas.MetadataValueType.REFERENCE;
import static com.constellio.model.entities.schemas.MetadataValueType.STRING;
import static com.constellio.model.entities.schemas.Schemas.CODE;
import static com.constellio.model.entities.schemas.Schemas.CREATED_BY;
import static com.constellio.model.entities.schemas.Schemas.MODIFIED_BY;
import static com.constellio.model.entities.schemas.Schemas.SCHEMA;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.from;
import static java.util.Arrays.asList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.solr.common.params.ModifiableSolrParams;
import com.constellio.app.services.factories.ConstellioFactories;
import com.constellio.app.services.schemasDisplay.SchemasDisplayManager;
import com.constellio.app.ui.entities.RecordVO;
import com.constellio.app.ui.entities.RecordVO.VIEW_MODE;
import com.constellio.app.ui.framework.builders.RecordToVOBuilder;
import com.constellio.app.ui.pages.base.BasePresenterUtils;
import com.constellio.app.ui.pages.base.SchemaPresenterUtils;
import com.constellio.app.ui.pages.base.SessionContext;
import com.constellio.app.ui.pages.management.facet.AddEditFacetConfigurationPresenter.AvailableFacetFieldMetadata;
import com.constellio.data.dao.dto.records.FacetValue;
import com.constellio.data.dao.services.records.RecordDao;
import com.constellio.data.utils.ImpossibleRuntimeException;
import com.constellio.data.utils.LangUtils;
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.FacetType;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.entities.schemas.MetadataSchemaType;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.entities.structures.MapStringStringStructure;
import com.constellio.model.services.factories.ModelLayerFactory;
import com.constellio.model.services.records.RecordServicesException;
import com.constellio.model.services.records.SchemasRecordsServices;
import com.constellio.model.services.search.SPEQueryResponse;
import com.constellio.model.services.search.query.logical.LogicalSearchQuery;
public class FacetConfigurationPresenterService extends BasePresenterUtils {
private static List<String> FIELD_WITH_AUTOMATIC_LABELS = asList(Schemas.SCHEMA.getDataStoreCode());
private static List<String> ALLOWED_GLOBAL_METADATAS_FOR_FIELD_FACETS = asList(
CREATED_BY.getLocalCode(),
MODIFIED_BY.getLocalCode(),
SCHEMA.getLocalCode(),
CODE.getLocalCode());
private SchemasDisplayManager schemasDisplayManager;
private SchemasRecordsServices schemasRecords;
private String collection;
private ModelLayerFactory modelLayerFactory;
private SessionContext sessionContext;
public FacetConfigurationPresenterService(ConstellioFactories factories, SessionContext sessionContext) {
super(factories, sessionContext);
collection = getCollection();
schemasRecords = new SchemasRecordsServices(collection, appLayerFactory().getModelLayerFactory());
schemasDisplayManager = appLayerFactory().getMetadataSchemasDisplayManager();
modelLayerFactory = factories.getModelLayerFactory();
this.sessionContext = sessionContext;
}
public MapStringStringStructure getStructureValue(Map<Integer, Map<String, String>> values) {
MapStringStringStructure structure = new MapStringStringStructure();
for (Entry<Integer, Map<String, String>> value : values.entrySet()) {
Map<String, String> map = value.getValue();
for (Entry<String, String> labels : map.entrySet()) {
structure.put(labels.getValue(), labels.getKey());
}
}
return structure;
}
public RecordVO getVOForType(FacetType type) {
Facet facet;
switch (type) {
case FIELD:
facet = schemasRecords.newFacetField();
break;
case QUERY:
facet = schemasRecords.newFacetQuery();
break;
default:
throw new ImpossibleRuntimeException("Unknown type");
}
return getVOForRecord(facet.getWrappedRecord());
}
public List<Integer> getInvalidQuery(Map<Integer, Map<String, String>> values) {
List<Integer> invalids = new ArrayList<>();
for (Entry<Integer, Map<String, String>> entry : values.entrySet()) {
Map<String, String> queries = entry.getValue();
for (Entry<String, String> query : queries.entrySet()) {
if (invalidSolrQuery(query.getValue())) {
invalids.add(entry.getKey());
}
}
}
return invalids;
}
private boolean invalidSolrQuery(String query) {
RecordDao recordDao = modelLayerFactory().getDataLayerFactory().newRecordDao();
try {
ModifiableSolrParams solrParams = new ModifiableSolrParams();
solrParams.set("q", "*:*");
solrParams.set("fq", query);
recordDao.searchQuery(solrParams);
} catch (RuntimeException se) {
return true;
}
return false;
}
public RecordVO getVOForRecord(Record record) {
return new RecordToVOBuilder().build(record, VIEW_MODE.FORM, sessionContext);
}
public List<AvailableFacetFieldMetadata> getAvailableDataStoreCodes() {
List<String> codes = new ArrayList<>();
List<AvailableFacetFieldMetadata> availableFacetFieldMetadatas = new ArrayList<>();
for (MetadataSchemaType type : schemasDisplayManager.getAllowedSchemaTypesForSimpleSearch(collection)) {
for (Metadata metadata : type.getAllMetadatas().onlyWithType(BOOLEAN, ENUM, INTEGER, REFERENCE, STRING, NUMBER)) {
String localCode = metadata.getLocalCode();
if (!codes.contains(metadata.getDataStoreCode()) && (!Schemas.isGlobalMetadata(localCode)
|| ALLOWED_GLOBAL_METADATAS_FOR_FIELD_FACETS.contains(localCode))) {
String label = getFieldFacetLabel(metadata);
codes.add(metadata.getDataStoreCode());
availableFacetFieldMetadatas.add(new AvailableFacetFieldMetadata(metadata.getDataStoreCode(), label));
}
}
}
Collections.sort(availableFacetFieldMetadatas, new Comparator<AvailableFacetFieldMetadata>() {
@Override
public int compare(AvailableFacetFieldMetadata o1, AvailableFacetFieldMetadata o2) {
return LangUtils.compareStrings(o1.getLabel(), o2.getLabel());
}
});
return availableFacetFieldMetadatas;
}
private String getFieldFacetLabel(Metadata metadata) {
String label = $("init.allTypes.allSchemas." + metadata.getLocalCode());
if (label.startsWith("init.")) {
label = metadata.getLabel(Language.withCode(sessionContext.getCurrentLocale().getLanguage()));
}
return label;
}
public List<String> getFieldFacetValues(String datastoreCode) {
List<MetadataSchemaType> types = schemasDisplayManager.getAllowedSchemaTypesForSimpleSearch(collection);
for (MetadataSchemaType schemaType : types) {
for (Metadata metadata : schemaType.getAllMetadatas().onlyWithType(BOOLEAN)) {
if (metadata.getDataStoreCode().equals(datastoreCode)) {
return asList("__TRUE__", "__FALSE__");
}
}
}
LogicalSearchQuery query = new LogicalSearchQuery(from(types).returnAll());
query.setNumberOfRows(0);
query.addFieldFacet(datastoreCode);
query.setFieldFacetLimit(1000);
SPEQueryResponse response = searchServices().query(query);
List<String> values = new ArrayList<>();
for (FacetValue facetValue : response.getFieldFacetValues().get(datastoreCode)) {
values.add(facetValue.getValue());
}
values.remove("__NULL__");
return values;
}
public boolean isDataStoreCodeSupportingLabelValues(String datastoreCode) {
for (MetadataSchemaType type : schemasDisplayManager.getAllowedSchemaTypesForSimpleSearch(collection)) {
for (Metadata metadata : type.getAllMetadatas().onlyWithType(BOOLEAN, INTEGER, STRING, NUMBER)) {
if (metadata.getDataStoreCode().equals(datastoreCode) &&
!FIELD_WITH_AUTOMATIC_LABELS.contains(metadata.getDataStoreCode())) {
return true;
}
}
}
return false;
}
public int getNextOrderValue() {
SchemasRecordsServices schemasRecords = new SchemasRecordsServices(collection, modelLayerFactory());
LogicalSearchQuery query = new LogicalSearchQuery();
query.setCondition(from(schemasRecords.facetSchemaType()).returnAll())
.sortDesc(schemasRecords.defaultFacet().get(Facet.ORDER));
List<Record> records = searchServices().search(query);
return schemasRecords.wrapFacet(records.get(records.size() - 1)).getOrder() + 1;
}
public Record toRecord(RecordVO recordVO) {
SchemaPresenterUtils schemaPresenterUtils = new SchemaPresenterUtils(recordVO.getSchema().getCode(),
getConstellioFactories(), sessionContext);
return schemaPresenterUtils.toRecord(recordVO);
}
public void activate(String id) {
toggleActivateDeactivateFacetMetadata(id, true);
}
public void deactivate(String id) {
toggleActivateDeactivateFacetMetadata(id, false);
}
private Metadata getFacetMetadata(Record record, String metadataCode) {
return modelLayerFactory.getMetadataSchemasManager().getSchemaTypes(collection).getSchema(
record.getSchemaCode()).getMetadata(metadataCode);
}
private void toggleActivateDeactivateFacetMetadata(String id, boolean isActivate) {
Record record = recordServices().getDocumentById(id);
Metadata metadata = getFacetMetadata(record, Facet.ACTIVE);
record.set(metadata, isActivate);
try {
recordServices().update(record);
} catch (RecordServicesException e) {
throw new RuntimeException(e);
}
}
public boolean isActive(RecordVO recordVO) {
return recordVO.getMetadataValue(recordVO.getMetadata(Facet.ACTIVE)).getValue() != null ?
(Boolean) recordVO.getMetadataValue(recordVO.getMetadata(Facet.ACTIVE)).getValue() :
false;
}
}