package com.constellio.app.modules.rm.extensions;
import static com.constellio.model.services.search.query.logical.LogicalSearchQuery.query;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.from;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.where;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.constellio.app.api.extensions.SystemCheckExtension;
import com.constellio.app.api.extensions.params.CollectionSystemCheckParams;
import com.constellio.app.api.extensions.params.TryRepairAutomaticValueParams;
import com.constellio.app.modules.rm.RMConfigs;
import com.constellio.app.modules.rm.services.RMSchemasRecordsServices;
import com.constellio.app.modules.rm.wrappers.AdministrativeUnit;
import com.constellio.app.modules.rm.wrappers.Category;
import com.constellio.app.modules.rm.wrappers.DecommissioningList;
import com.constellio.app.modules.rm.wrappers.Folder;
import com.constellio.app.services.factories.AppLayerFactory;
import com.constellio.data.dao.services.contents.ContentDao;
import com.constellio.data.io.services.facades.IOServices;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.records.wrappers.User;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.services.contents.ContentManager;
import com.constellio.model.services.records.RecordServices;
import com.constellio.model.services.records.RecordServicesException;
import com.constellio.model.services.records.RecordServicesRuntimeException.NoSuchRecordWithId;
import com.constellio.model.services.search.SearchServices;
public class RMSystemCheckExtension extends SystemCheckExtension {
private static final String DEPOSIT_DATE_BEFORE_TRANSFER_DATE = "depositDateBeforeTransferDate";
private static final String DESTRUCTION_DATE_BEFORE_TRANSFER_DATE = "destructionDateBeforeTransferDate";
private static Logger LOGGER = LoggerFactory.getLogger(RMSystemCheckExtension.class);
String collection;
AppLayerFactory appLayerFactory;
ContentDao contentDao;
ContentManager contentManager;
SearchServices searchServices;
RecordServices recordServices;
IOServices ioServices;
public final String METRIC_LOGICALLY_DELETED_ADM_UNITS = "rm.admUnits.logicallyDeleted";
public final String METRIC_LOGICALLY_DELETED_CATEGORIES = "rm.categories.logicallyDeleted";
public final String DELETED_ADM_UNITS = "rm.admUnit.deleted";
public final String RESTORED_ADM_UNITS = "rm.admUnit.restored";
public final String DELETED_CATEGORIES = "rm.category.deleted";
public final String RESTORED_CATEGORIES = "rm.category.restored";
RMSchemasRecordsServices rm;
RMConfigs configs;
public RMSystemCheckExtension(String collection, AppLayerFactory appLayerFactory) {
this.collection = collection;
this.appLayerFactory = appLayerFactory;
this.recordServices = appLayerFactory.getModelLayerFactory().newRecordServices();
this.searchServices = appLayerFactory.getModelLayerFactory().newSearchServices();
this.contentDao = appLayerFactory.getModelLayerFactory().getDataLayerFactory().getContentsDao();
this.rm = new RMSchemasRecordsServices(collection, appLayerFactory);
this.ioServices = appLayerFactory.getModelLayerFactory().getIOServicesFactory().newIOServices();
this.contentManager = appLayerFactory.getModelLayerFactory().getContentManager();
this.configs = new RMConfigs(appLayerFactory.getModelLayerFactory().getSystemConfigurationsManager());
}
@Override
public boolean tryRepairAutomaticValue(TryRepairAutomaticValueParams params) {
if (params.isMetadata(DecommissioningList.SCHEMA_TYPE, DecommissioningList.FOLDERS)) {
DecommissioningList list = rm.wrapDecommissioningList(params.getRecord());
for (String folderToRemove : params.getValuesToRemove()) {
list.removeFolderDetail(folderToRemove);
}
return true;
}
return false;
}
@Override
public void checkCollection(CollectionSystemCheckParams params) {
boolean markedForReindexing = false;
RMSchemasRecordsServices rm = new RMSchemasRecordsServices(collection, appLayerFactory);
for (AdministrativeUnit unit : rm.searchAdministrativeUnits(where(Schemas.LOGICALLY_DELETED_STATUS).isTrue())) {
String label = unit.getCode() + " - " + unit.getTitle();
params.getResultsBuilder().incrementMetric(METRIC_LOGICALLY_DELETED_ADM_UNITS);
params.getResultsBuilder().markLogicallyDeletedRecordAsError(unit);
if (params.isRepair()) {
params.getResultsBuilder().markAsRepaired(unit.getId());
try {
recordServices.refresh(unit);
if (!unit.getWrappedRecord().isDisconnected()) {
recordServices.add(unit.set(Schemas.LOGICALLY_DELETED_STATUS.getLocalCode(), false));
if (recordServices.isLogicallyThenPhysicallyDeletable(unit.getWrappedRecord(), User.GOD)) {
recordServices.logicallyDelete(unit.getWrappedRecord(), User.GOD);
recordServices.physicallyDelete(unit.getWrappedRecord(), User.GOD);
params.getResultsBuilder().addListItem(DELETED_ADM_UNITS, label);
} else {
params.getResultsBuilder().addListItem(RESTORED_ADM_UNITS, label);
}
} else {
params.getResultsBuilder().addListItem(DELETED_ADM_UNITS, label);
}
} catch (RecordServicesException e) {
throw new RuntimeException(e);
} catch (NoSuchRecordWithId e) {
//OK
}
markedForReindexing = true;
}
}
List<Category> categories = rm.searchCategorys(where(Schemas.LOGICALLY_DELETED_STATUS).isTrue());
for (Category category : categories) {
String label = category.getCode() + " - " + category.getTitle();
params.getResultsBuilder().incrementMetric(METRIC_LOGICALLY_DELETED_CATEGORIES);
params.getResultsBuilder().markLogicallyDeletedRecordAsError(category);
if (params.isRepair()) {
params.getResultsBuilder().markAsRepaired(category.getId());
try {
recordServices.refresh(category);
if (!category.getWrappedRecord().isDisconnected()) {
recordServices.add(category.set(Schemas.LOGICALLY_DELETED_STATUS.getLocalCode(), false));
if (recordServices.isLogicallyThenPhysicallyDeletable(category.getWrappedRecord(), User.GOD)) {
recordServices.logicallyDelete(category.getWrappedRecord(), User.GOD);
recordServices.physicallyDelete(category.getWrappedRecord(), User.GOD);
params.getResultsBuilder().addListItem(DELETED_CATEGORIES, label);
} else {
params.getResultsBuilder().addListItem(RESTORED_CATEGORIES, label);
}
} else {
params.getResultsBuilder().addListItem(DELETED_CATEGORIES, label);
}
} catch (RecordServicesException e) {
throw new RuntimeException(e);
} catch (NoSuchRecordWithId e) {
//OK
}
markedForReindexing = true;
}
}
if (configs.allowModificationOfArchivisticStatusAndExpectedDates().isAlwaysEnabledOrDuringImportOnly()) {
Iterator<Record> foldersIterator = searchServices.recordsIterator(query(from(rm.folder.schemaType())
.where(rm.folder.manualExpectedDepositDate()).isNotNull()
.orWhere(rm.folder.manualExpectedDesctructionDate()).isNotNull()));
while (foldersIterator.hasNext()) {
Folder folder = rm.wrapFolder(foldersIterator.next());
LocalDate manualExpectedDeposit = folder.getManualExpectedDepositDate();
LocalDate manualExpectedDestruction = folder.getManualExpectedDestructionDate();
LocalDate actualTransfer = folder.getActualTransferDate();
LocalDate manualExpectedTransfer = folder.getExpectedTransferDate();
boolean fixDeposit = false;
boolean fixDestruction = false;
Map<String, Object> errorParams = new HashMap<>();
errorParams.put("idTitle", folder.getId() + "-" + folder.getTitle());
if (manualExpectedDeposit != null && actualTransfer != null && manualExpectedDeposit.isBefore(actualTransfer)) {
params.getResultsBuilder().addNewValidationError(RMSystemCheckExtension.class,
DEPOSIT_DATE_BEFORE_TRANSFER_DATE, errorParams);
fixDeposit = params.isRepair();
}
if (manualExpectedDeposit != null && manualExpectedTransfer != null
&& manualExpectedDeposit.isBefore(manualExpectedTransfer)) {
params.getResultsBuilder().addNewValidationError(RMSystemCheckExtension.class,
DEPOSIT_DATE_BEFORE_TRANSFER_DATE, errorParams);
fixDeposit = params.isRepair();
}
if (manualExpectedDestruction != null && actualTransfer != null
&& manualExpectedDestruction.isBefore(actualTransfer)) {
params.getResultsBuilder().addNewValidationError(RMSystemCheckExtension.class,
DESTRUCTION_DATE_BEFORE_TRANSFER_DATE, errorParams);
fixDestruction = params.isRepair();
}
if (manualExpectedDestruction != null && manualExpectedTransfer != null
&& manualExpectedDestruction.isBefore(manualExpectedTransfer)) {
params.getResultsBuilder().addNewValidationError(RMSystemCheckExtension.class,
DESTRUCTION_DATE_BEFORE_TRANSFER_DATE, errorParams);
fixDestruction = params.isRepair();
}
if (fixDeposit || fixDestruction) {
if (fixDeposit) {
folder.setManualExpectedDepositDate(null);
}
if (fixDestruction) {
folder.setManualExpectedDestructionDate(null);
}
try {
recordServices.update(folder);
} catch (RecordServicesException e) {
throw new RuntimeException(e);
}
}
}
}
if (markedForReindexing) {
appLayerFactory.getSystemGlobalConfigsManager().setReindexingRequired(true);
}
}
}