/****************************************************************************** * Copyright 2009-2018 Exactpro (Exactpro Systems Limited) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.exactpro.sf.configuration.dictionary.impl; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.lang.model.SourceVersion; import org.apache.commons.lang3.StringUtils; import com.exactpro.sf.common.messages.structures.IAttributeStructure; import com.exactpro.sf.common.messages.structures.IDictionaryStructure; import com.exactpro.sf.common.messages.structures.IFieldStructure; import com.exactpro.sf.common.messages.structures.IMessageStructure; import com.exactpro.sf.configuration.dictionary.DictionaryValidationError; import com.exactpro.sf.configuration.dictionary.DictionaryValidationErrorLevel; import com.exactpro.sf.configuration.dictionary.DictionaryValidationErrorType; import com.exactpro.sf.configuration.dictionary.ValidationHelper; import com.exactpro.sf.configuration.dictionary.interfaces.IDictionaryValidator; @SuppressWarnings("serial") public class DefaultDictionaryValidator extends AbstractDictionaryValidator { private static final Set<String> prohibitedNames = new HashSet<>(); static { prohibitedNames.add("_"); } public DefaultDictionaryValidator() { } public DefaultDictionaryValidator(IDictionaryValidator parentValidator) { super(parentValidator); } @Override public List<DictionaryValidationError> validate(IDictionaryStructure dictionary, boolean full, Boolean fieldsOnly) { List<DictionaryValidationError> errors = super.validate(dictionary, full, fieldsOnly); checkDictionaryNamespace(errors, dictionary); if (fieldsOnly == null || fieldsOnly) { ValidationHelper.checkDuplicates(null, dictionary.getFields().values(), errors, false, DictionaryValidationErrorLevel.DICTIONARY); } if (fieldsOnly == null || !fieldsOnly) { ValidationHelper.checkDuplicates(null, dictionary.getMessages().values(), errors, true, DictionaryValidationErrorLevel.DICTIONARY); } return errors; } @Override public List<DictionaryValidationError> validate(IMessageStructure message, IFieldStructure field) { List<DictionaryValidationError> errors = super.validate(message, field); if (field.isEnum()) { checkFieldName(errors, message, field); } if (!field.isComplex()) { // Check default value type boolean isError = ValidationHelper.checkTypeError(errors, message, field, field.getJavaType(), field.getDefaultValue(), DictionaryValidationErrorType.ERR_DEFAULT_VALUE); if (!isError) { checkContainsError(errors, message, field, field.getDefaultValue(), field.getValues(), DictionaryValidationErrorType.ERR_DEFAULT_VALUE); } // Check values types if(field.getValues() != null) { for (IAttributeStructure value : field.getValues().values()) { ValidationHelper.checkTypeError(errors, null, field, field.getJavaType(), value.getValue(), DictionaryValidationErrorType.ERR_VALUES); checkValueName(errors, message, field, value); } } } // Check attributes types for (IAttributeStructure attr : field.getAttributes().values()) { ValidationHelper.checkTypeError(errors, message, field, attr.getType(), attr.getValue(), DictionaryValidationErrorType.ERR_ATTRIBUTES); checkAttributeName(errors, message, field, attr); } return errors; } @Override public List<DictionaryValidationError> validate(IDictionaryStructure dictionary, IMessageStructure message, boolean full) { List<DictionaryValidationError> errors = super.validate(dictionary, message, full); checkMessageName(errors, message); // Check duplicates ValidationHelper.checkDuplicates(message, message.getFields().values(), errors, false, DictionaryValidationErrorLevel.MESSAGE); // Check attributes types for (IAttributeStructure attr : message.getAttributes().values()) { ValidationHelper.checkTypeError(errors, message, null, attr.getType(), attr.getValue(), DictionaryValidationErrorType.ERR_ATTRIBUTES); checkAttributeName(errors, message, null, attr); } return errors; } /** * Check the presence of value in values table */ private void checkContainsError(List<DictionaryValidationError> errors, IMessageStructure message, IFieldStructure field, Object value, Map<String, IAttributeStructure> values, DictionaryValidationErrorType errType) { if(value == null) { return; } if(value instanceof String && StringUtils.isEmpty((String)value)) { return; } if(values == null || values.isEmpty()) { return; } boolean found = false; for (IAttributeStructure attr : values.values()) { if (value.toString().equals(attr.getValue())) { found = true; } } if (!found) { errors.add(new DictionaryValidationError(message == null ? null : message.getName(), field.getName(), "Value <strong>\"" + value + "\"</strong> wasn't found in values table", DictionaryValidationErrorLevel.FIELD, errType)); logger.error("[{}{}] Value \"{}\" wasn't found in values table", message != null ? message.getName() + "/" : "", field.getName(), value); } } private void checkFieldName(List<DictionaryValidationError> errors, IMessageStructure message, IFieldStructure field) { checkStructureName(errors, message, field, field.getName(), Structure.Field); } private void checkMessageName(List<DictionaryValidationError> errors, IMessageStructure message) { checkStructureName(errors, message, null, message.getName(), Structure.Message); } private void checkAttributeName(List<DictionaryValidationError> errors, IMessageStructure message, IFieldStructure field, IAttributeStructure attr) { checkStructureName(errors, message, field, attr.getName(), Structure.Attribute); } private void checkValueName(List<DictionaryValidationError> errors, IMessageStructure message, IFieldStructure field, IAttributeStructure value) { checkStructureName(errors, message, field, value.getName(), Structure.Value); } private void checkDictionaryNamespace(List<DictionaryValidationError> errors, IDictionaryStructure dictionary) { checkStructureName(errors, null, null, dictionary.getNamespace(), Structure.Dictionary); } private void checkStructureName(List<DictionaryValidationError> errors, IMessageStructure message, IFieldStructure field, String structureName, Structure structure) { if (structure.isProhibited(structureName)) { DictionaryValidationErrorLevel level; if (field != null) { level = DictionaryValidationErrorLevel.FIELD; } else if (message != null) { level = DictionaryValidationErrorLevel.MESSAGE; } else { level = DictionaryValidationErrorLevel.DICTIONARY; } DictionaryValidationErrorType type; switch (structure) { case Attribute: type = DictionaryValidationErrorType.ERR_ATTRIBUTES; break; case Value: type = DictionaryValidationErrorType.ERR_VALUES; break; default: type = DictionaryValidationErrorType.ERR_NAME; break; } errors.add(new DictionaryValidationError(message != null ? message.getName() : null, field != null ? field.getName() : null, String.format("Prohibited name <strong>%s</strong> for %s. Name can't be Java keyword or have value that presents in this list [%s]", structureName, structure, StringUtils.join(structure.getProhibitedNames(), ",")), level, type)); } } private enum Structure { Message, Field, Dictionary, Attribute, Value { final Set<String> prohibit = new HashSet<>(prohibitedNames); { prohibit.add("Missed"); prohibit.add("Present"); } @Override boolean isProhibited(String name) { return super.isProhibited(name) || prohibit.contains(name); } @Override Set<String> getProhibitedNames() { return prohibit; } }; boolean isProhibited(String name) { return prohibitedNames.contains(name) || SourceVersion.isKeyword(name) || !SourceVersion.isIdentifier(name); } Set<String> getProhibitedNames() { return prohibitedNames; } } }