package com.constellio.app.modules.rm.extensions; import static com.constellio.app.modules.rm.model.enums.CompleteDatesWhenAddingFolderWithManualStatusChoice.ENABLED; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import com.constellio.app.modules.rm.RMConfigs; import com.constellio.app.modules.rm.constants.RMPermissionsTo; import com.constellio.app.modules.rm.model.enums.CopyType; import com.constellio.app.modules.rm.model.enums.FolderStatus; import com.constellio.app.modules.rm.services.RMSchemasRecordsServices; import com.constellio.app.modules.rm.wrappers.Folder; import com.constellio.app.modules.rm.wrappers.RetentionRule; import com.constellio.data.frameworks.extensions.ExtensionBooleanResult; 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.extensions.behaviors.RecordExtension; import com.constellio.model.extensions.events.records.RecordInCreationBeforeSaveEvent; import com.constellio.model.extensions.events.records.RecordInCreationBeforeValidationAndAutomaticValuesCalculationEvent; import com.constellio.model.extensions.events.records.RecordInModificationBeforeSaveEvent; import com.constellio.model.extensions.events.records.RecordInModificationBeforeValidationAndAutomaticValuesCalculationEvent; import com.constellio.model.services.factories.ModelLayerFactory; import com.constellio.model.services.records.RecordServices; import com.constellio.model.services.search.SearchServices; 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.LogicalSearchQueryOperators; import com.constellio.model.services.search.query.logical.condition.LogicalSearchCondition; import com.constellio.model.services.taxonomies.ConceptNodesTaxonomySearchServices; import com.constellio.model.services.taxonomies.TaxonomiesManager; import com.constellio.model.services.taxonomies.TaxonomiesSearchServices; public class RMFolderExtension extends RecordExtension { private final RMSchemasRecordsServices rmSchema; final String collection; final ModelLayerFactory modelLayerFactory; final RecordServices recordServices; final SearchServices searchServices; final TaxonomiesSearchServices taxonomiesSearchServices; final TaxonomiesManager taxonomyManager; final RMSchemasRecordsServices rm; final RMConfigs configs; public RMFolderExtension(String collection, ModelLayerFactory modelLayerFactory) { this.collection = collection; this.modelLayerFactory = modelLayerFactory; rmSchema = new RMSchemasRecordsServices(collection, modelLayerFactory); recordServices = modelLayerFactory.newRecordServices(); searchServices = modelLayerFactory.newSearchServices(); taxonomiesSearchServices = modelLayerFactory.newTaxonomiesSearchService(); taxonomyManager = modelLayerFactory.getTaxonomiesManager(); this.rm = new RMSchemasRecordsServices(collection, modelLayerFactory); this.configs = new RMConfigs(modelLayerFactory.getSystemConfigurationsManager()); } @Override public void recordInCreationBeforeValidationAndAutomaticValuesCalculation( RecordInCreationBeforeValidationAndAutomaticValuesCalculationEvent event) { if (event.isSchemaType(Folder.SCHEMA_TYPE)) { folderInCreation(rmSchema.wrapFolder(event.getRecord()), event.getTransactionUser()); } if (event.isSchemaType(Folder.SCHEMA_TYPE)) { Folder folder = rmSchema.wrapFolder(event.getRecord()); deleteRootFolderMetadatasIfSubFolder(folder); } } @Override public void recordInCreationBeforeSave(RecordInCreationBeforeSaveEvent event) { if (event.isSchemaType(Folder.SCHEMA_TYPE)) { setFolderPermissionStatus(event.getRecord()); } } @Override public void recordInModificationBeforeSave(RecordInModificationBeforeSaveEvent event) { if (event.isSchemaType(Folder.SCHEMA_TYPE) && event.hasModifiedMetadata(Folder.ARCHIVISTIC_STATUS)) { setFolderPermissionStatus(event.getRecord()); } } @Override public void recordInModificationBeforeValidationAndAutomaticValuesCalculation( RecordInModificationBeforeValidationAndAutomaticValuesCalculationEvent event) { if (event.isSchemaType(Folder.SCHEMA_TYPE)) { Folder folder = rmSchema.wrapFolder(event.getRecord()); deleteRootFolderMetadatasIfSubFolder(folder); } } private void completeMissingActualDates(Folder folder) { if (configs.getAllowModificationOfArchivisticStatusAndExpectedDates().isAlwaysEnabledOrDuringImportOnly() && configs.getCompleteDecommissioningDateWhenCreatingFolderWithManualStatus() == ENABLED) { FolderStatus status = folder.getManualArchivisticStatus(); if (status == FolderStatus.SEMI_ACTIVE && folder.getActualTransferDate() == null) { folder.setManualArchivisticStatus(null); recordServices.recalculate(folder); folder.setActualTransferDate(folder.getExpectedTransferDate()); folder.setManualArchivisticStatus(status); } else if (status == FolderStatus.INACTIVE_DEPOSITED && folder.getActualDepositDate() == null) { folder.setManualArchivisticStatus(null); recordServices.recalculate(folder); if (folder.getActualTransferDate() == null) { folder.setActualTransferDate(folder.getExpectedTransferDate()); } folder.setActualDepositDate(folder.getExpectedDepositDate()); folder.setManualArchivisticStatus(status); } else if (status == FolderStatus.INACTIVE_DESTROYED && folder.getActualDestructionDate() == null) { folder.setManualArchivisticStatus(null); recordServices.recalculate(folder); if (folder.getActualTransferDate() == null) { folder.setActualTransferDate(folder.getExpectedTransferDate()); } folder.setActualDestructionDate(folder.getExpectedDestructionDate()); folder.setManualArchivisticStatus(status); } } } private void setFolderPermissionStatus(Record record) { Folder folder = rmSchema.wrapFolder(record); folder.setPermissionStatus(folder.getArchivisticStatus()); } private void deleteRootFolderMetadatasIfSubFolder(Folder folder) { if (folder.getParentFolder() != null) { folder.setAdministrativeUnitEntered((String) null); folder.setCategoryEntered((String) null); folder.setRetentionRuleEntered((String) null); folder.setCopyStatusEntered(null); } } private void folderInCreation(Folder folder, User user) { Boolean openHolderActivated = modelLayerFactory.getSystemConfigurationsManager().getValue(RMConfigs.OPEN_HOLDER); if (openHolderActivated) { if (folder.getCreatedBy() != null) { User createdBy = rmSchema.getUser(folder.getCreatedBy()); updateStatusCopyIfRequired(folder, createdBy); } else if (user != null) { updateStatusCopyIfRequired(folder, user); } } completeMissingActualDates(folder); } private void updateStatusCopyIfRequired(Folder folder, User user) { String ruleId = folder.getRetentionRuleEntered(); if (StringUtils.isNotBlank(ruleId)) { RetentionRule rule = rmSchema.getRetentionRule(ruleId); if (rule != null) { boolean hasPrincipalCopies = !rule.getPrincipalCopies().isEmpty(); if (hasPrincipalCopies) { List<String> adminUnits = rule.getAdministrativeUnits(); if (!adminUnits.isEmpty() && rule.isResponsibleAdministrativeUnits()) { setFolderStatusAsPrincipalIfUserInRuleAdministrativeUnitsOrSubUnits(folder, user, rule); } } } } } private void setFolderStatusAsPrincipalIfUserInRuleAdministrativeUnitsOrSubUnits(Folder folder, User user, RetentionRule rule) { List<String> creatorAdminUnits = getUserAdminUnits(user); boolean creatorInRuleAdminUnits = !CollectionUtils.intersection(creatorAdminUnits, getRuleHierarchyUnits(rule)) .isEmpty(); if (creatorInRuleAdminUnits) { folder.setCopyStatusEntered(CopyType.PRINCIPAL); } } private Set<String> getRuleHierarchyUnits(RetentionRule rule) { Set<String> returnSet = new HashSet<>(); Taxonomy principalTaxonomy = modelLayerFactory.getTaxonomiesManager().getPrincipalTaxonomy( rule.getCollection()); for (String unit : rule.getAdministrativeUnits()) { List<String> currentUnits = new ConceptNodesTaxonomySearchServices(modelLayerFactory) .getAllConceptIdsHierarchyOf(principalTaxonomy, rmSchema.getAdministrativeUnit(unit).getWrappedRecord()); returnSet.addAll(currentUnits); } return returnSet; } private List<String> getUserAdminUnits(User user) { List<String> returnList = new ArrayList<>(); LogicalSearchCondition condition = LogicalSearchQueryOperators.from(this.rmSchema.administrativeUnit.schema()) .returnAll(); List<Record> results = this.searchServices.search(new LogicalSearchQuery(condition).filteredWithUserWrite(user) .setReturnedMetadatas(ReturnedMetadatasFilter.idVersionSchema())); for (Record record : results) { returnList.add(record.getId()); } return returnList; } @Override public ExtensionBooleanResult isRecordModifiableBy(IsRecordModifiableByParams params) { User user = params.getUser(); if (params.isSchemaType(Folder.SCHEMA_TYPE)) { Folder folder = rm.wrapFolder(params.getRecord()); if (user.hasWriteAccess().on(folder)) { if (folder.getPermissionStatus().isInactive()) { if (folder.getBorrowed() != null && folder.getBorrowed()) { return ExtensionBooleanResult .trueIf((user.has(RMPermissionsTo.MODIFY_INACTIVE_BORROWED_FOLDER).on(folder) && user .has(RMPermissionsTo.MODIFY_INACTIVE_FOLDERS).on(folder))); } return ExtensionBooleanResult.trueIf(user.has(RMPermissionsTo.MODIFY_INACTIVE_FOLDERS).on(folder)); } if (folder.getPermissionStatus().isSemiActive()) { if (folder.getBorrowed() != null && folder.getBorrowed()) { return ExtensionBooleanResult .trueIf(user.has(RMPermissionsTo.MODIFY_SEMIACTIVE_BORROWED_FOLDER).on(folder) && user .has(RMPermissionsTo.MODIFY_SEMIACTIVE_FOLDERS).on(folder)); } return ExtensionBooleanResult.trueIf(user.has(RMPermissionsTo.MODIFY_SEMIACTIVE_FOLDERS).on(folder)); } return ExtensionBooleanResult.TRUE; } return ExtensionBooleanResult.FALSE; } return ExtensionBooleanResult.NOT_APPLICABLE; } }