package com.constellio.app.ui.framework.data; import static com.constellio.app.ui.i18n.i18n.$; import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.from; import static com.constellio.model.services.search.query.logical.valueCondition.ConditionTemplateFactory.autocompleteFieldMatchingInMetadatas; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang3.StringUtils; import com.constellio.app.services.factories.ConstellioFactories; import com.constellio.app.ui.entities.UserVO; import com.constellio.app.ui.framework.components.fields.lookup.LookupField.TextInputDataProvider; import com.constellio.app.ui.pages.base.SessionContext; 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.SchemaUtils; import com.constellio.model.services.search.SPEQueryResponse; import com.constellio.model.services.search.StatusFilter; import com.constellio.model.services.search.query.logical.LogicalSearchQuery; import com.constellio.model.services.search.query.logical.condition.LogicalSearchCondition; import com.constellio.model.services.users.UserServices; public class RecordTextInputDataProvider extends TextInputDataProvider<String> { private transient int lastStartIndex; private transient String lastQuery; private transient SPEQueryResponse response; private transient ModelLayerFactory modelLayerFactory; protected SessionContext sessionContext; protected String schemaTypeCode; protected String schemaCode; protected boolean security; protected boolean onlyLinkables = false; protected boolean writeAccess; public RecordTextInputDataProvider(ConstellioFactories constellioFactories, SessionContext sessionContext, String schemaTypeCode, boolean writeAccess) { this(constellioFactories, sessionContext, schemaTypeCode, null, writeAccess); } public RecordTextInputDataProvider(ConstellioFactories constellioFactories, SessionContext sessionContext, String schemaTypeCode, String schemaCode, boolean writeAccess) { this.writeAccess = writeAccess; this.sessionContext = sessionContext; this.schemaTypeCode = schemaTypeCode; this.schemaCode = schemaCode; this.modelLayerFactory = constellioFactories.getModelLayerFactory(); this.security = determineIfSecurity(); } private boolean determineIfSecurity() { boolean security = false; MetadataSchemaTypes types = modelLayerFactory.getMetadataSchemasManager().getSchemaTypes(getCurrentCollection()); List<MetadataSchemaType> typesByCode = new ArrayList<MetadataSchemaType>(); if (schemaTypeCode != null) { MetadataSchemaType type = types.getSchemaType(schemaTypeCode); typesByCode.add(type); } else { String schemaTypeCodeFromSchema = SchemaUtils.getSchemaTypeCode(schemaCode); MetadataSchemaType type = types.getSchemaType(schemaTypeCodeFromSchema); typesByCode.add(type); } for (MetadataSchemaType type : typesByCode) { if (type.hasSecurity() || modelLayerFactory.getTaxonomiesManager().isTypeInPrincipalTaxonomy(type)) { security = true; break; } } return security; } private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); init(); } private void init() { ConstellioFactories constellioFactories = ConstellioFactories.getInstance(); modelLayerFactory = constellioFactories.getModelLayerFactory(); } @Override public List<String> getData(String text, int startIndex, int count) { User user = getCurrentUser(); if (lastQuery == null || !lastQuery.equals(text) || lastStartIndex != startIndex) { lastQuery = text; lastStartIndex = startIndex; response = searchAutocompleteField(user, text, startIndex, count); } return toRecordIds(response.getRecords()); } @Override public int size(String text) { User user = getCurrentUser(); if (lastQuery == null || !lastQuery.equals(text)) { lastQuery = text; lastStartIndex = -1; response = searchAutocompleteField(user, text, 0, 1); } return (int) response.getNumFound(); } protected List<String> toRecordIds(List<Record> matches) { List<String> recordIds = new ArrayList<>(); for (Record match : matches) { recordIds.add(match.getId()); } return recordIds; } public SPEQueryResponse searchAutocompleteField(User user, String text, int startIndex, int count) { LogicalSearchCondition condition; Metadata sort = null; if (schemaTypeCode != null) { MetadataSchemaType type = modelLayerFactory.getMetadataSchemasManager() .getSchemaTypes(getCurrentCollection()).getSchemaType(schemaTypeCode); List<Metadata> extraMetadatas = type.getDefaultSchema().getMetadatas().onlySearchable().onlySchemaAutocomplete(); if (StringUtils.isNotBlank(text)) { condition = from(type).where(autocompleteFieldMatchingInMetadatas(text, extraMetadatas)); } else { String caption = $("caption." + type.getCode() + ".record"); condition = from(type).returnAll(); if (caption != null && caption.startsWith("{code}")) { sort = Schemas.CODE; } else { sort = Schemas.TITLE; } } } else { MetadataSchema schema = modelLayerFactory.getMetadataSchemasManager() .getSchemaTypes(getCurrentCollection()).getSchema(schemaCode); List<Metadata> extraMetadatas = schema.getMetadatas().onlySearchable().onlySchemaAutocomplete(); if (StringUtils.isNotBlank(text)) { condition = from(schema).where(autocompleteFieldMatchingInMetadatas(text, extraMetadatas)); } else { condition = from(schema).returnAll(); } } if (onlyLinkables) { condition = condition.andWhere(Schemas.LINKABLE).isTrueOrNull(); } LogicalSearchQuery query = new LogicalSearchQuery(condition) .setPreferAnalyzedFields(true) .filteredByStatus(StatusFilter.ACTIVES) .setStartRow(startIndex) .setNumberOfRows(count); if (sort != null) { query.sortAsc(sort); } if (security) { if (writeAccess) { query.filteredWithUserWrite(user); } else { query.filteredWithUser(user); } } return modelLayerFactory.newSearchServices().query(query); } protected String getCurrentCollection() { return sessionContext.getCurrentCollection(); } public User getCurrentUser() { String currentCollection = sessionContext.getCurrentCollection(); UserVO currentUserVO = sessionContext.getCurrentUser(); UserServices userServices = modelLayerFactory.newUserServices(); return userServices.getUserInCollection(currentUserVO.getUsername(), currentCollection); } @Override public void setOnlyLinkables(boolean onlyLinkables) { this.onlyLinkables = onlyLinkables; } public ModelLayerFactory getModelLayerFactory() { return modelLayerFactory; } }