package com.constellio.model.services.schemas;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.constellio.data.utils.LangUtils;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.records.Transaction;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.entities.schemas.MetadataSchemaType;
import com.constellio.model.entities.schemas.MetadataSchemaTypes;
import com.constellio.model.services.records.RecordImpl;
import com.constellio.model.services.records.RecordServices;
import com.constellio.model.services.records.RecordUtils;
public class RecordsModificationBuilder {
private RecordServices recordServices;
public RecordsModificationBuilder(RecordServices recordServices) {
this.recordServices = recordServices;
}
public List<RecordsModification> build(Transaction transaction, MetadataSchemaTypes metadataSchemaTypes) {
List<RecordsModification> recordsModifications = new ArrayList<>();
Map<String, List<Record>> recordsSplittedByTypes = newRecordUtils().splitRecordsBySchemaTypes(
transaction.getSavedRecordWithModification());
for (String schemaTypeCode : metadataSchemaTypes.getSchemaTypesSortedByDependency()) {
if (recordsSplittedByTypes.containsKey(schemaTypeCode)) {
MetadataSchemaType schemaType = metadataSchemaTypes.getSchemaType(schemaTypeCode);
List<Record> records = recordsSplittedByTypes.get(schemaTypeCode);
recordsModifications.add(getSchemaTypeRecordsModifications(schemaType, records));
}
}
return recordsModifications;
}
private RecordsModification getSchemaTypeRecordsModifications(MetadataSchemaType schemaType, List<Record> records) {
List<Metadata> modifiedMetadatas = getModifiedMetadatas(schemaType, records);
return new RecordsModification(records, modifiedMetadatas, schemaType);
}
private List<Metadata> getModifiedMetadatas(MetadataSchemaType schemaType, List<Record> records) {
List<Metadata> modifiedMetadatas = new ArrayList<>();
List<String> modifiedMetadatasCodes = getModifiedMetadatasDataStoreCodes(records, schemaType);
for (String metadataDataStoreCode : modifiedMetadatasCodes) {
modifiedMetadatas.add(schemaType.getMetadataWithDataStoreCode(metadataDataStoreCode));
}
return modifiedMetadatas;
}
public RecordUtils newRecordUtils() {
return new RecordUtils();
}
public List<String> getModifiedMetadatasDataStoreCodes(List<Record> records, MetadataSchemaType schemaType) {
Set<String> modifiedMetadatasCodes = new HashSet<>();
for (Record record : records) {
RecordImpl recordImpl = (RecordImpl) record;
RecordImpl originalRecord = (RecordImpl) record.getCopyOfOriginalRecord();
Map<String, Object> modifiedValues = recordImpl.getModifiedValues();
modifiedMetadatasCodes.addAll(modifiedValues.keySet());
recordServices.reloadEagerTransientMetadatas(recordImpl);
recordServices.reloadEagerTransientMetadatas(originalRecord);
recordServices.loadLazyTransientMetadatas(recordImpl);
recordServices.loadLazyTransientMetadatas(originalRecord);
for (Metadata automaticMetadata : schemaType.getSchema(record.getSchemaCode()).getEagerTransientMetadatas()) {
Object before = originalRecord.get(automaticMetadata);
Object after = recordImpl.get(automaticMetadata);
if (!LangUtils.isEqual(before, after)) {
modifiedMetadatasCodes.add(automaticMetadata.getDataStoreCode());
}
}
for (Metadata automaticMetadata : schemaType.getSchema(record.getSchemaCode()).getLazyTransientMetadatas()) {
Object before = originalRecord.get(automaticMetadata);
Object after = recordImpl.get(automaticMetadata);
if (!LangUtils.isEqual(before, after)) {
modifiedMetadatasCodes.add(automaticMetadata.getDataStoreCode());
}
}
}
return new ArrayList<>(modifiedMetadatasCodes);
}
}