package com.constellio.app.modules.rm.model.validators; import static com.constellio.app.modules.rm.wrappers.RetentionRule.COPY_RETENTION_RULES; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import com.constellio.app.modules.rm.RMConfigs; import com.constellio.app.modules.rm.model.CopyRetentionRule; import com.constellio.app.modules.rm.model.enums.CopyType; import com.constellio.app.modules.rm.model.enums.DisposalType; import com.constellio.app.modules.rm.model.enums.RetentionRuleScope; import com.constellio.app.modules.rm.wrappers.RetentionRule; import com.constellio.app.modules.rm.wrappers.structures.RetentionRuleDocumentType; import com.constellio.model.entities.schemas.ConfigProvider; import com.constellio.model.entities.schemas.Metadata; import com.constellio.model.entities.schemas.MetadataSchema; import com.constellio.model.entities.schemas.validation.RecordMetadataValidator; import com.constellio.model.entities.schemas.validation.RecordValidator; import com.constellio.model.frameworks.validation.DecoratedValidationsErrors; import com.constellio.model.frameworks.validation.ValidationErrors; import com.constellio.model.services.records.RecordValidatorParams; public class RetentionRuleValidator implements RecordValidator { public static final String MUST_SPECIFY_ADMINISTRATIVE_UNITS_XOR_RESPONSIBLES_FLAG = "mustSpecifyAdministrativeUnitsXORSetResponsibles"; public static final String NO_ADMINISTRATIVE_UNITS_OR_RESPONSIBLES_FLAG = "noAdministrativeUnitsOrResponsibles"; public static final String MUST_SPECIFY_ONE_SECONDARY_COPY_RETENTON_RULE = "mustSpecifyOneSecondaryRetentionRule"; public static final String MUST_SPECIFY_AT_LEAST_ONE_PRINCIPAL_COPY_RETENTON_RULE = "mustSpecifyAtLeastOnePrincipalRetentionRule"; public static final String MUST_NOT_SPECIFY_SECONDARY_DOCUMENT_COPY_RETENTON_RULE = "mustNotSpecifySecondaryDocumentRetentionRule"; public static final String MUST_SPECIFY_AT_LEAST_ONE_PRINCIPAL_DOCUMENT_COPY_RETENTON_RULE = "mustSpecifyAtLeastOnePrincipalDocumentRetentionRule"; public static final String INVALID_COPY_RETENTION_RULE_FIELD = "invalidCopyRuleField"; public static final String INVALID_COPY_RETENTION_RULE_FIELD_INVALID = "invalid"; public static final String INVALID_COPY_RETENTION_RULE_FIELD_REQUIRED = "required"; public static final String INVALID_COPY_RETENTION_RULE_FIELD_NULL_REQUIRED = "nullRequired"; public static final String DOCUMENT_COPY_RETENTION_RULE_FIELD_REQUIRED = "documentCopyRetentionRuleFieldRequired"; public static final String MISSING_DOCUMENT_TYPE_DISPOSAL = "missingDocumentTypeDisposal"; public static final String DOCUMENT_RULE_MUST_HAVE_ONLY_DOCUMENT_COPY_RULES = "documentRuleMustHaveOnlyDocumentCopyRules"; // public static final String PRINCIPAL_DEFAULT_COPY_RETENTION_RULE_IN_FOLDER_RULE = "principalDefaultCopyRetentionRuleInFolderRule"; public static final String SECONDARY_DEFAULT_COPY_RETENTION_RULE_IN_FOLDER_RULE = "secondaryDefaultCopyRetentionRuleInFolderRule"; // public static final String PRINCIPAL_DEFAULT_COPY_RETENTION_RULE_REQUIRED_IN_DOCUMENT_RULE = "principalDefaultCopyRetentionRuleRequiredInDocumentRule"; public static final String SECONDARY_DEFAULT_COPY_RETENTION_RULE_REQUIRED_IN_DOCUMENT_RULE = "secondaryDefaultCopyRetentionRuleRequiredInDocumentRule"; // public static final String DOCUMENT_TYPES_IN_DOCUMENT_RULE = "documentTypesInDocumentRule"; public static final String PRINCIPAL_COPY_WITHOUT_TYPE_REQUIRED = "principalCopyWithoutTypeRequired"; // public static final String PRINCIPAL_COPIES_MUST_HAVE_DIFFERENT_CONTENT_TYPES = "principalCopiesMustHaveDifferentContentTypes"; // public static final String PRINCIPAL_COPIES_MUST_HAVE_DIFFERENT_CONTENT_TYPES_DUPLICATES = "duplicates"; public static final String MISSING_DOCUMENT_TYPE_DISPOSAL_INDEX = "index"; @Override public void validate(RecordValidatorParams params) { RetentionRule retentionRule = new RetentionRule(params.getValidatedRecord(), params.getTypes()); validate(retentionRule, params.getSchema(), params.getConfigProvider(), params.getValidationErrors()); } void validate(RetentionRule retentionRule, MetadataSchema schema, ConfigProvider configProvider, ValidationErrors validationErrors) { if (retentionRule.getScope() != RetentionRuleScope.DOCUMENTS) { validateDocumentTypes(retentionRule, validationErrors); } else { validateNoDocumentTypes(retentionRule, validationErrors); } validateAdministrativeUnits(retentionRule, schema, configProvider, validationErrors); validateCopyRetentionRules(retentionRule, schema, validationErrors, configProvider); validateDocumentCopyRetentionRules(retentionRule, schema, validationErrors); validateDefaultDocumentCopyRetentionRules(retentionRule, schema, validationErrors, configProvider); } private void validateDefaultDocumentCopyRetentionRules(RetentionRule retentionRule, MetadataSchema schema, ValidationErrors validationErrors, ConfigProvider configProvider) { if (!configProvider.<Boolean>get(RMConfigs.DOCUMENT_RETENTION_RULES)) { return; } if (retentionRule.getScope() == RetentionRuleScope.DOCUMENTS) { if (retentionRule.getPrincipalDefaultDocumentCopyRetentionRule() == null) { validationErrors.add(getClass(), PRINCIPAL_DEFAULT_COPY_RETENTION_RULE_REQUIRED_IN_DOCUMENT_RULE); } if (retentionRule.getSecondaryDefaultDocumentCopyRetentionRule() == null) { validationErrors.add(getClass(), SECONDARY_DEFAULT_COPY_RETENTION_RULE_REQUIRED_IN_DOCUMENT_RULE); } } else { if (retentionRule.getPrincipalDefaultDocumentCopyRetentionRule() != null) { validationErrors.add(getClass(), PRINCIPAL_DEFAULT_COPY_RETENTION_RULE_IN_FOLDER_RULE); } if (retentionRule.getSecondaryDefaultDocumentCopyRetentionRule() != null) { validationErrors.add(getClass(), SECONDARY_DEFAULT_COPY_RETENTION_RULE_IN_FOLDER_RULE); } } } private void validateNoDocumentTypes(RetentionRule retentionRule, ValidationErrors validationErrors) { if (!retentionRule.getDocumentTypesDetails().isEmpty()) { validationErrors.add(getClass(), DOCUMENT_TYPES_IN_DOCUMENT_RULE); } } private void validateDocumentTypes(RetentionRule retentionRule, ValidationErrors validationErrors) { List<RetentionRuleDocumentType> documentTypes = retentionRule.getDocumentTypesDetails(); if (retentionRule.hasCopyRetentionRuleWithSortDispositionType()) { for (int i = 0; i < documentTypes.size(); i++) { RetentionRuleDocumentType documentType = documentTypes.get(i); if (documentType.getDisposalType() == null || documentType.getDisposalType() == DisposalType.SORT) { Map<String, Object> parameters = new HashMap<>(); parameters.put(MISSING_DOCUMENT_TYPE_DISPOSAL_INDEX, "" + i); validationErrors.add(getClass(), MISSING_DOCUMENT_TYPE_DISPOSAL, parameters); } } } } private void validateCopyRetentionRules(RetentionRule retentionRule, MetadataSchema schema, ValidationErrors validationErrors, ConfigProvider configProvider) { List<CopyRetentionRule> copyRetentionRules = retentionRule.getCopyRetentionRules(); boolean validIntegrity = true; for (int i = 0; i < copyRetentionRules.size(); i++) { CopyRetentionRule copyRetentionRule = copyRetentionRules.get(i); Map<String, String> parameters = new HashMap<>(); parameters.put("code", copyRetentionRule.getCode()); parameters.put("index", "" + (i + 1)); parameters.put("metadata", RetentionRule.COPY_RETENTION_RULES); DecoratedValidationsErrors copyRuleErrors = new DecoratedValidationsErrors(validationErrors, parameters); validateCopyRuleIntegrity(copyRetentionRule, copyRuleErrors); validIntegrity &= !copyRuleErrors.hasDecoratedErrors(); } if (validIntegrity) { int principalCount = 0; int principalCountWithoutType = 0; int secondaryCount = 0; List<CopyRetentionRule> copyRetentionRules1 = retentionRule.getCopyRetentionRules(); for (int i = 0; i < copyRetentionRules1.size(); i++) { CopyRetentionRule copyRetentionRule = copyRetentionRules1.get(i); if (copyRetentionRule.getCopyType() == CopyType.PRINCIPAL) { principalCount++; if (copyRetentionRule.getTypeId() == null) { principalCountWithoutType++; } } else { secondaryCount++; if (copyRetentionRule.getTypeId() != null) { Map<String, Object> parameters = nullRequired(i, copyRetentionRule, "type", COPY_RETENTION_RULES); validationErrors.add(getClass(), INVALID_COPY_RETENTION_RULE_FIELD, parameters); } } } boolean copyRulePrincipalRequired = configProvider.get(RMConfigs.COPY_RULE_PRINCIPAL_REQUIRED); if (retentionRule.getScope() != RetentionRuleScope.DOCUMENTS && principalCount == 0 && copyRulePrincipalRequired) { addCopyRetentionRuleError(MUST_SPECIFY_AT_LEAST_ONE_PRINCIPAL_COPY_RETENTON_RULE, validationErrors); } if (retentionRule.getScope() == RetentionRuleScope.DOCUMENTS && (principalCount + secondaryCount) != 0) { addCopyRetentionRuleError(DOCUMENT_RULE_MUST_HAVE_ONLY_DOCUMENT_COPY_RULES, validationErrors); } if (retentionRule.getScope() != RetentionRuleScope.DOCUMENTS && secondaryCount != 1) { addCopyRetentionRuleError(MUST_SPECIFY_ONE_SECONDARY_COPY_RETENTON_RULE, validationErrors); } if (principalCount != 0 && principalCountWithoutType == 0) { addCopyRetentionRuleError(PRINCIPAL_COPY_WITHOUT_TYPE_REQUIRED, validationErrors); } } } private Map<String, Object> nullRequired(int i, CopyRetentionRule copyRetentionRule, String type, String metadata) { Map<String, Object> parameters = new HashMap<>(); parameters.put("code", copyRetentionRule.getCode()); parameters.put("index", "" + (i + 1)); parameters.put("field", "type"); parameters.put("errorType", "nullRequired"); parameters.put("metadata", metadata); return parameters; } private void validateDocumentCopyRetentionRules(RetentionRule retentionRule, MetadataSchema schema, ValidationErrors validationErrors) { List<CopyRetentionRule> copyRetentionRules = retentionRule.getDocumentCopyRetentionRules(); boolean validIntegrity = true; for (int i = 0; i < copyRetentionRules.size(); i++) { CopyRetentionRule copyRetentionRule = copyRetentionRules.get(i); Map<String, String> parameters = new HashMap<>(); parameters.put("code", copyRetentionRule.getCode()); parameters.put("index", "" + (i + 1)); parameters.put("metadata", RetentionRule.DOCUMENT_COPY_RETENTION_RULES); DecoratedValidationsErrors copyRuleErrors = new DecoratedValidationsErrors(validationErrors, parameters); validateCopyRuleIntegrity(copyRetentionRule, copyRuleErrors); if (copyRetentionRule.getTypeId() == null) { copyRuleErrors.add(getClass(), INVALID_COPY_RETENTION_RULE_FIELD, requiredField("type")); } validIntegrity &= !copyRuleErrors.hasDecoratedErrors(); } if (validIntegrity) { int principalCount = 0; int secondaryCount = 0; for (CopyRetentionRule copyRetentionRule : retentionRule.getDocumentCopyRetentionRules()) { if (copyRetentionRule.getCopyType() == CopyType.PRINCIPAL) { principalCount++; } else { secondaryCount++; } } if (retentionRule.getScope() == RetentionRuleScope.DOCUMENTS && principalCount == 0) { addCopyRetentionRuleError(MUST_SPECIFY_AT_LEAST_ONE_PRINCIPAL_DOCUMENT_COPY_RETENTON_RULE, validationErrors); } if (secondaryCount != 0) { addCopyRetentionRuleError(MUST_NOT_SPECIFY_SECONDARY_DOCUMENT_COPY_RETENTON_RULE, validationErrors); } } } private Map<String, Object> requiredField(String field) { Map<String, Object> parameters = new HashMap<>(); parameters.put("field", field); parameters.put("errorType", "required"); return parameters; } private void validateCopyRuleIntegrity(CopyRetentionRule copyRetentionRule, ValidationErrors validationErrors) { if (copyRetentionRule.getCopyType() == null) { validationErrors.add(getClass(), INVALID_COPY_RETENTION_RULE_FIELD, requiredField("copyType")); } if (copyRetentionRule.getMediumTypeIds() == null || copyRetentionRule.getMediumTypeIds().isEmpty()) { validationErrors.add(getClass(), INVALID_COPY_RETENTION_RULE_FIELD, requiredField("mediumTypes")); } if (copyRetentionRule.getActiveRetentionPeriod() == null) { validationErrors.add(getClass(), INVALID_COPY_RETENTION_RULE_FIELD, requiredField("active")); } if (copyRetentionRule.getSemiActiveRetentionPeriod() == null) { validationErrors.add(getClass(), INVALID_COPY_RETENTION_RULE_FIELD, requiredField("semiActive")); } if (copyRetentionRule.getInactiveDisposalType() == null) { validationErrors.add(getClass(), INVALID_COPY_RETENTION_RULE_FIELD, requiredField("inactive")); } } private void addCopyRetentionRuleError(String code, ValidationErrors validationErrors) { Map<String, Object> parameters = new HashMap<>(); validationErrors.add(getClass(), code, parameters); } // private void addCopyRetentionRuleIntegrityError(int index, String copyCode, String field, MetadataSchema schema, // ValidationErrors validationErrors) { // Map<String, Object> parameters = new HashMap<>(); // parameters.put("field", field); // parameters.put("index", "" + index); // parameters.put("code", copyCode); // parameters.put(RecordMetadataValidator.METADATA_CODE, COPY_RETENTION_RULES); // parameters.put(RecordMetadataValidator.METADATA_LABEL, // schema.getMetadata(COPY_RETENTION_RULES).getCode()); // String errorCode = StringUtils.isBlank(copyCode) ? // COPY_RETENTION_RULE_FIELD_AT_INDEX_REQUIRED : // COPY_RETENTION_RULE_FIELD_WITH_CODE_REQUIRED; // validationErrors.add(getClass(), errorCode, parameters); // // } // // private void newCopyRetentionRulesParameters(String errorCode, String metadataCode, int index, // CopyRetentionRule copyRetentionRule, ) { // Map<String, Object> parameters = new HashMap<>(); // parameters = new HashMap<>(); // parameters.put("code", null); // parameters.put("index", "3"); // parameters.put("field", "semiActive"); // parameters.put("value", "*"); // parameters.put("errorType", "invalid"); // parameters.put("metadata", RetentionRule.COPY_RETENTION_RULES); // // } private void validateAdministrativeUnits(RetentionRule retentionRule, MetadataSchema schema, ConfigProvider configProvider, ValidationErrors validationErrors) { List<String> administrativeUnits = retentionRule.getAdministrativeUnits(); boolean responsibleAdministrativeUnits = retentionRule.isResponsibleAdministrativeUnits(); if (administrativeUnits.isEmpty() && !responsibleAdministrativeUnits) { validationErrors.add(getClass(), NO_ADMINISTRATIVE_UNITS_OR_RESPONSIBLES_FLAG); } else { if (!administrativeUnits.isEmpty() && responsibleAdministrativeUnits) { Object openHolder = configProvider.get(RMConfigs.OPEN_HOLDER); if (openHolder == null || !(Boolean) openHolder) { validationErrors.add(getClass(), MUST_SPECIFY_ADMINISTRATIVE_UNITS_XOR_RESPONSIBLES_FLAG); } } } } }