package com.constellio.model.services.schemas.validators;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.entities.schemas.MetadataSchema;
import com.constellio.model.entities.schemas.MetadataSchemaTypes;
import com.constellio.model.entities.schemas.MetadataValueType;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.frameworks.validation.ValidationErrors;
import com.constellio.model.frameworks.validation.Validator;
import com.constellio.model.services.records.RecordProvider;
public class CyclicHierarchyValidator implements Validator<Record> {
public static final String CANNOT_REFERENCE_A_DESCENDANT_IN_A_CHILD_OF_REFERENCE = "cannotReferenceADescendantInAChildOfReference";
public static final String UNALLOWED_CODE = "unallowedCode";
private final List<Metadata> metadatas;
private final MetadataSchemaTypes schemaTypes;
private final RecordProvider recordProvider;
public CyclicHierarchyValidator(MetadataSchemaTypes schemaTypes, List<Metadata> metadatas,
RecordProvider recordProvider) {
this.schemaTypes = schemaTypes;
this.metadatas = metadatas;
this.recordProvider = recordProvider;
}
@Override
public void validate(Record record, ValidationErrors validationErrors) {
for (Metadata metadata : metadatas) {
if (metadata.getType() == MetadataValueType.REFERENCE && record.isModified(metadata)
&& record.get(metadata) != null) {
if (!metadata.isMultivalue()) {
String referenceValue = record.get(metadata);
Record referencedRecord = recordProvider.getRecord(referenceValue);
MetadataSchema schema = getSchema(referencedRecord);
if (metadata.isChildOfRelationship()) {
String principalPath = (String) referencedRecord.get(Schemas.PRINCIPAL_PATH);
if (isInPrincipalPath(record.getId(), principalPath)) {
addValidationErrors(validationErrors, CANNOT_REFERENCE_A_DESCENDANT_IN_A_CHILD_OF_REFERENCE,
metadata, schema.getCode());
}
}
}
}
}
}
private boolean isInPrincipalPath(String recordId, String principalPath) {
boolean inPrincipalPath = false;
if (principalPath != null) {
String[] principalPathSplitted = StringUtils.split(principalPath, "/");
for (String principalPathPart : principalPathSplitted) {
if (principalPathPart.equals(recordId)) {
inPrincipalPath = true;
break;
}
}
}
return inPrincipalPath;
}
private MetadataSchema getSchema(Record referencedRecord) {
String referencedSchemaCode = referencedRecord.getSchemaCode();
return schemaTypes.getSchema(referencedSchemaCode);
}
public void addValidationErrors(ValidationErrors validationErrors, String code, Metadata metadata, String unallowedSchema) {
Map<String, Object> parameters = new HashMap<>();
parameters.put(METADATA_CODE, metadata.getCode());
parameters.put(METADATA_LABEL,metadata.getLabelsByLanguageCodes());
parameters.put(UNALLOWED_CODE, unallowedSchema);
validationErrors.add(getClass(), code, parameters);
}
}