package com.constellio.model.services.taxonomies;
import static com.constellio.model.entities.schemas.Schemas.ALL_REMOVED_AUTHS;
import static com.constellio.model.entities.schemas.Schemas.ATTACHED_ANCESTORS;
import static com.constellio.model.entities.schemas.Schemas.CODE;
import static com.constellio.model.entities.schemas.Schemas.PATH_PARTS;
import static com.constellio.model.entities.schemas.Schemas.TITLE;
import static com.constellio.model.entities.schemas.Schemas.TOKENS;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.from;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.fromTypesInCollectionOf;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.where;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.constellio.model.entities.Taxonomy;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.records.wrappers.User;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.entities.schemas.MetadataSchema;
import com.constellio.model.entities.schemas.MetadataSchemaType;
import com.constellio.model.entities.schemas.MetadataSchemaTypes;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.services.factories.ModelLayerFactory;
import com.constellio.model.services.schemas.MetadataSchemasManager;
import com.constellio.model.services.schemas.SchemaUtils;
import com.constellio.model.services.search.SPEQueryResponse;
import com.constellio.model.services.search.SearchServices;
import com.constellio.model.services.search.StatusFilter;
import com.constellio.model.services.search.query.ReturnedMetadatasFilter;
import com.constellio.model.services.search.query.logical.LogicalSearchQuery;
import com.constellio.model.services.search.query.logical.condition.DataStoreFieldLogicalSearchCondition;
import com.constellio.model.services.search.query.logical.condition.LogicalSearchCondition;
import com.constellio.model.services.search.query.logical.ongoing.OngoingLogicalSearchCondition;
public class ConceptNodesTaxonomySearchServices {
SearchServices searchServices;
TaxonomiesManager taxonomiesManager;
MetadataSchemasManager metadataSchemasManager;
TaxonomySearchQueryConditionFactory queryFactory;
SchemaUtils schemaUtils = new SchemaUtils();
public ConceptNodesTaxonomySearchServices(ModelLayerFactory modelLayerFactory) {
this.searchServices = modelLayerFactory.newSearchServices();
this.taxonomiesManager = modelLayerFactory.getTaxonomiesManager();
this.metadataSchemasManager = modelLayerFactory.getMetadataSchemasManager();
}
public ConceptNodesTaxonomySearchServices(SearchServices searchServices, TaxonomiesManager taxonomiesManager,
MetadataSchemasManager metadataSchemasManager) {
this.searchServices = searchServices;
this.taxonomiesManager = taxonomiesManager;
this.metadataSchemasManager = metadataSchemasManager;
}
public List<Record> getRootConcept(String collection, String taxonomyCode, TaxonomiesSearchOptions options) {
return getRootConceptResponse(collection, taxonomyCode, options).getRecords();
}
public SPEQueryResponse getRootConceptResponse(String collection, String taxonomyCode, TaxonomiesSearchOptions options) {
return searchServices.query(getRootConceptsQuery(collection, taxonomyCode, options));
}
public LogicalSearchQuery getRootConceptsQuery(String collection, String taxonomyCode, TaxonomiesSearchOptions options) {
Taxonomy taxonomy = taxonomiesManager.getEnabledTaxonomyWithCode(collection, taxonomyCode);
LogicalSearchCondition condition = fromConceptsOf(taxonomy).where(PATH_PARTS).isEqualTo("R");
LogicalSearchQuery query = new LogicalSearchQuery(condition);
query.filteredByStatus(options.getIncludeStatus());
query.setStartRow(options.getStartRow());
query.setNumberOfRows(options.getRows());
query.setReturnedMetadatas(returnedMetadatasForRecordsIn(collection, options));
query.sortAsc(CODE).sortAsc(TITLE);
return query;
}
public ReturnedMetadatasFilter returnedMetadatasForRecordsIn(String collection, TaxonomiesSearchOptions options) {
//TODO Detect which records could possibly be in the taxonomy and only return those essential fields
MetadataSchemaTypes types = metadataSchemasManager.getSchemaTypes(collection);
return returnedMetadatasForRecordsIn(collection, options, types);
}
public static ReturnedMetadatasFilter returnedMetadatasForRecordsIn(String collection,
TaxonomiesSearchOptions options, MetadataSchemaTypes types) {
//TODO Detect which records could possibly be in the taxonomy and only return those essential fields
Set<String> metadatas = new HashSet<>();
metadatas.add(Schemas.CODE.getDataStoreCode());
metadatas.add(Schemas.TITLE.getDataStoreCode());
metadatas.add(Schemas.LINKABLE.getDataStoreCode());
metadatas.add(Schemas.VISIBLE_IN_TREES.getDataStoreCode());
metadatas.add(Schemas.TOKENS.getDataStoreCode());
metadatas.add(Schemas.ATTACHED_ANCESTORS.getDataStoreCode());
metadatas.add(Schemas.ALL_REMOVED_AUTHS.getDataStoreCode());
if (options.getReturnedMetadatasFilter() != null && options.getReturnedMetadatasFilter().getAcceptedFields() != null) {
metadatas.addAll(options.getReturnedMetadatasFilter().getAcceptedFields());
}
for (MetadataSchemaType type : types.getSchemaTypes()) {
for (MetadataSchema schema : type.getAllSchemas()) {
for (Metadata metadata : schema.getMetadatas()) {
if (metadata.getInheritance() == null && metadata.isEssentialInSummary()) {
metadatas.add(metadata.getDataStoreCode());
}
}
}
}
return ReturnedMetadatasFilter.onlyFields(metadatas);
}
public List<Record> getChildConcept(Record record, TaxonomiesSearchOptions options) {
return getChildNodesResponse(record, options).getRecords();
}
public SPEQueryResponse getChildNodesResponse(Record record, TaxonomiesSearchOptions options) {
MetadataSchemaTypes types = metadataSchemasManager.getSchemaTypes(record);
return searchServices.query(childNodesQuery(record, options, types));
}
public static LogicalSearchQuery childNodesQuery(Record record, TaxonomiesSearchOptions options,
MetadataSchemaTypes types) {
LogicalSearchCondition condition = fromTypesInCollectionOf(record).where(directChildOf(record).andWhere(visibleInTrees));
return new LogicalSearchQuery(condition)
.filteredByStatus(options.getIncludeStatus())
.setStartRow(options.getStartRow())
.setNumberOfRows(options.getRows())
.sortAsc(CODE).sortAsc(TITLE)
.setReturnedMetadatas(
returnedMetadatasForRecordsIn(record.getCollection(), options, types));
}
public static LogicalSearchQuery childConceptsQuery(Record record, Taxonomy taxonomy, TaxonomiesSearchOptions options,
MetadataSchemaTypes types) {
LogicalSearchCondition condition = fromTypeIn(taxonomy).where(directChildOf(record)).andWhere(visibleInTrees);
return new LogicalSearchQuery(condition)
.filteredByStatus(options.getIncludeStatus())
.setStartRow(options.getStartRow())
.setNumberOfRows(options.getRows())
.sortAsc(CODE).sortAsc(TITLE)
.setReturnedMetadatas(
returnedMetadatasForRecordsIn(record.getCollection(), options, types));
}
OngoingLogicalSearchCondition fromConceptsOf(Taxonomy taxonomy) {
return from(metadataSchemasManager.getSchemaTypes(taxonomy, taxonomy.getSchemaTypes()));
}
static DataStoreFieldLogicalSearchCondition directChildOf(Record record) {
return (DataStoreFieldLogicalSearchCondition) where(Schemas.PATH_PARTS).isEqualTo("_LAST_" + record.getId());
}
static DataStoreFieldLogicalSearchCondition notDirectChildOf(Record record) {
return (DataStoreFieldLogicalSearchCondition) where(Schemas.PATH_PARTS).isNotEqual("_LAST_" + record.getId());
}
static DataStoreFieldLogicalSearchCondition recordInHierarchyOf(Record record) {
return (DataStoreFieldLogicalSearchCondition) where(Schemas.PATH_PARTS).isEqualTo(record.getId());
}
public static DataStoreFieldLogicalSearchCondition visibleInTrees = (DataStoreFieldLogicalSearchCondition) where(
Schemas.VISIBLE_IN_TREES).isTrueOrNull();
public LogicalSearchQuery getChildNodesQuery(String taxonomyCode, Record record, TaxonomiesSearchOptions options) {
Taxonomy taxonomy = taxonomiesManager.getEnabledTaxonomyWithCode(record.getCollection(), taxonomyCode);
LogicalSearchCondition condition = fromConceptsOf(taxonomy).where(directChildOf(record)).andWhere(visibleInTrees);
return new LogicalSearchQuery(condition)
.filteredByStatus(options.getIncludeStatus())
.setStartRow(options.getStartRow())
.setNumberOfRows(options.getRows())
.sortAsc(CODE).sortAsc(TITLE)
.setReturnedMetadatas(options.getReturnedMetadatasFilter()
.withIncludedMetadatas(TOKENS, ATTACHED_ANCESTORS, ALL_REMOVED_AUTHS));
}
public static OngoingLogicalSearchCondition fromTypeIn(Taxonomy taxonomy) {
return from(taxonomy.getSchemaTypes(), taxonomy.getCollection());
}
public static LogicalSearchCondition childrenCondition(Taxonomy taxonomy, Record inRecord) {
return fromTypeIn(taxonomy).where(directChildOf(inRecord));
}
public List<String> getAllConceptIdsHierarchyOf(Taxonomy taxonomy, Record record) {
List<String> newReponse = new ArrayList<>();
newReponse.add(record.getId());
newReponse.addAll(searchServices.searchRecordIds(fromConceptsOf(taxonomy).where(recordInHierarchyOf(record))));
return newReponse;
}
public List<Record> getAllConceptHierarchyOf(Taxonomy taxonomy, Record record) {
return searchServices.search(new LogicalSearchQuery(fromConceptsOf(taxonomy).where(directChildOf(record))));
}
public List<String> getAllPrincipalConceptIdsAvailableTo(Taxonomy taxonomy, User user, StatusFilter statusFilter) {
return searchServices.searchRecordIds(new LogicalSearchQuery(fromConceptsOf(taxonomy).returnAll())
.sortAsc(CODE).sortAsc(TITLE)
.filteredWithUser(user)
.filteredByStatus(statusFilter));
}
public List<String> getAllPrincipalConceptIdsAvailableTo(Taxonomy taxonomy, User user) {
return getAllPrincipalConceptIdsAvailableTo(taxonomy, user, StatusFilter.ALL);
}
public List<Record> getAllPrincipalConceptsAvailableTo(Taxonomy taxonomy, User user) {
return searchServices.search(new LogicalSearchQuery(fromConceptsOf(taxonomy).returnAll())
.sortAsc(CODE).sortAsc(TITLE)
.filteredWithUser(user));
}
}