package ru.hflabs.rcd.service.document.recodeRuleSet; import com.google.common.collect.ImmutableMap; import org.springframework.util.StringUtils; import org.springframework.validation.Errors; import ru.hflabs.rcd.accessor.RuleFieldAccessor; import ru.hflabs.rcd.exception.constraint.DuplicateNameException; import ru.hflabs.rcd.exception.constraint.IllegalPrimaryKeyException; import ru.hflabs.rcd.exception.constraint.document.IllegalFieldException; import ru.hflabs.rcd.exception.constraint.rule.IllegalChangeMetaFieldException; import ru.hflabs.rcd.exception.constraint.rule.IllegalRecodeRuleSetException; import ru.hflabs.rcd.exception.constraint.rule.SelfMappingException; import ru.hflabs.rcd.exception.search.document.UnknownDictionaryException; import ru.hflabs.rcd.exception.search.document.UnknownGroupException; import ru.hflabs.rcd.exception.search.document.UnknownMetaFieldException; import ru.hflabs.rcd.model.ModelUtils; import ru.hflabs.rcd.model.criteria.FilterCriteriaValue; import ru.hflabs.rcd.model.document.Field; import ru.hflabs.rcd.model.document.MetaField; import ru.hflabs.rcd.model.path.MetaFieldNamedPath; import ru.hflabs.rcd.model.rule.RecodeRuleSet; import ru.hflabs.rcd.service.IFilterService; import ru.hflabs.rcd.service.ServiceUtils; import ru.hflabs.rcd.service.document.IMetaFieldService; import ru.hflabs.rcd.service.document.RuleChangeValidator; import ru.hflabs.rcd.service.rule.IRecodeRuleSetService; import ru.hflabs.util.core.EqualsUtil; import ru.hflabs.util.core.FormatUtil; import javax.validation.constraints.NotNull; import static org.springframework.validation.ValidationUtils.rejectIfEmptyOrWhitespace; import static ru.hflabs.rcd.accessor.Accessors.FROM_SET_INJECTOR; import static ru.hflabs.rcd.accessor.Accessors.TO_SET_INJECTOR; /** * Класс <class>RecodeRuleSetValidator</class> реализует базовый валидатор для набора правил перекодирования * * @author Nazin Alexander */ public abstract class RecodeRuleSetChangeValidator extends RuleChangeValidator<MetaFieldNamedPath, MetaField, RecodeRuleSet, IMetaFieldService> { /** Сервис работы со значениями полей */ private IFilterService<Field> fieldService; /** Сервис работы с наборами правил перекодирования */ protected IRecodeRuleSetService recodeRuleSetService; public RecodeRuleSetChangeValidator(boolean mustExist) { super(mustExist, RecodeRuleSet.class, FROM_SET_INJECTOR, TO_SET_INJECTOR, IllegalRecodeRuleSetException.class); } public void setFieldService(IFilterService<Field> fieldService) { this.fieldService = fieldService; } public void setRecodeRuleSetService(IRecodeRuleSetService recodeRuleSetService) { this.recodeRuleSetService = recodeRuleSetService; } @Override protected RecodeRuleSet formatValue(RecodeRuleSet target) { target.setName(FormatUtil.parseString(target.getName())); return super.formatValue(target); } @Override protected void doValidateField(Errors errors, RecodeRuleSet target, RuleFieldAccessor<MetaFieldNamedPath, MetaField, RecodeRuleSet> accessor) { MetaFieldNamedPath path = accessor.applyNamedPath(target); try { accessor.inject(target, recodeFieldService.findUniqueByNamedPath(path, false)); } catch (UnknownGroupException ex) { rejectValue(errors, MetaFieldNamedPath.GROUP_NAME, ex, path.getGroupName()); } catch (UnknownDictionaryException ex) { rejectValue(errors, MetaFieldNamedPath.DICTIONARY_NAME, ex, path.getDictionaryName()); } catch (UnknownMetaFieldException ex) { rejectValue(errors, MetaFieldNamedPath.FIELD_NAME, ex, path.getFieldName()); } } @Override protected void doValidateFields(Errors errors, RecodeRuleSet target) { // Выполняем валидацию МЕТА-полей super.doValidateFields(errors, target); // Проверяем, что поля источника и назначения не равны if (!errors.hasErrors() && EqualsUtil.equals(target.getFromDictionaryId(), target.getToDictionaryId())) { reject(errors, new SelfMappingException(target.getFromNamedPath()), target.getFromNamedPath()); } } /** * Выполняет валидацию значения поля по умолчанию * * @param errors контейнер ошибок * @param target проверяемый набор */ private void doValidateDefaultField(Errors errors, RecodeRuleSet target) { try { // Получаем значение поля по умолчанию по его идентификатору Field defaultField = fieldService.findByID(target.getDefaultFieldId(), false, false); // Проверяем, что значение поля относится к МЕТА-полю назначения if (!EqualsUtil.equals(defaultField.getMetaFieldId(), target.getToFieldId())) { rejectValue( errors, RecodeRuleSet.DEFAULT_FIELD_ID, new IllegalFieldException(String.format("Default field '%s' does not belong to meta field %s", defaultField.getValue(), target.getToNamedPath())), defaultField.getValue(), target.getToNamedPath() ); } } catch (IllegalPrimaryKeyException ex) { reject(errors, ex, target.getDefaultFieldId()); } } /** * Выполняет валидацию уникальности названия набора правил * * @param errors контейнер ошибок * @param target проверяемый набор */ private void doValidateName(Errors errors, RecodeRuleSet target) { // Если набор правил должен существовать, то его имя должно быть задано if (mustExist) { rejectIfEmptyOrWhitespace( errors, RecodeRuleSet.NAME, NotNull.class.getSimpleName(), String.format("Name for %s must not be empty", retrieveTargetClass().getSimpleName()) ); } // Выполняем поиск существующего набора с таким же именем if (StringUtils.hasText(target.getName())) { String targetName = target.getName(); // Выполняем поиск существующего набора с таким же именем RecodeRuleSet existedRuleSet = recodeRuleSetService.findUniqueByNamedPath(targetName, true); // Если существует набор с таким же именем, то проверяем, что это тот же самый, что и проверяемый if (existedRuleSet != null && !EqualsUtil.equals(target.getId(), existedRuleSet.getId())) { rejectValue( errors, RecodeRuleSet.NAME, new DuplicateNameException(String.format("%s with name '%s' already exist", retrieveTargetClass().getSimpleName(), targetName)), targetName ); } } } @Override protected void doValidateCommon(Errors errors, RecodeRuleSet target) { // Проверяем название набора doValidateName(errors, target); // Проверяем МЕТА-поля super.doValidateCommon(errors, target); // Проверяем значение перекодирования по умолчанию if (!errors.hasErrors() && target.getDefaultFieldId() != null) { doValidateDefaultField(errors, target); } } /** * Класс <class>Create</class> реализует сервис валидации набора правил перекодирования при создании * * @author Nazin Alexander */ public static class Create extends RecodeRuleSetChangeValidator { public Create() { super(false); } @Override protected RecodeRuleSet findExisted(RecodeRuleSet target, boolean exist) { return ServiceUtils.findUniqueDocumentBy( recodeRuleSetService, ImmutableMap.<String, FilterCriteriaValue<?>>of( RecodeRuleSet.FROM_DICTIONARY_ID, new FilterCriteriaValue.StringValue(target.getFromDictionaryId()), RecodeRuleSet.TO_DICTIONARY_ID, new FilterCriteriaValue.StringValue(target.getToDictionaryId()) ), false ); } } /** * Класс <class>Update</class> реализует сервис валидации набора правил перекодирования при обновлении * * @author Nazin Alexander */ public static class Update extends RecodeRuleSetChangeValidator { public Update() { super(true); } @Override protected RecodeRuleSet findExisted(RecodeRuleSet target, boolean exist) { return recodeRuleSetService.findByID(target.getId(), true, true); } /** * Выполняет валидацию смены МЕТА-поля * * @param errors контейнер ошибок * @param newField новое поле * @param oldField текущее поле */ private void doValidateChangeMetaField(Errors errors, MetaField newField, MetaField oldField) { if (!EqualsUtil.equals(newField.getDictionaryId(), oldField.getDictionaryId())) { MetaFieldNamedPath oldPath = ModelUtils.createMetaFieldNamedPath(oldField); MetaFieldNamedPath newPath = ModelUtils.createMetaFieldNamedPath(newField); reject(errors, new IllegalChangeMetaFieldException(oldPath, newPath), oldPath, newPath); } } @Override protected void validateNewToOld(Errors errors, RecodeRuleSet newObject, RecodeRuleSet oldObject) { doValidateChangeMetaField(errors, newObject.getFrom(), oldObject.getFrom()); doValidateChangeMetaField(errors, newObject.getTo(), oldObject.getTo()); } } }