From 8d9e717828d97237754a3fce252566ad7e8a554e Mon Sep 17 00:00:00 2001 From: Pierre Rioux Date: Thu, 27 Sep 2018 09:38:31 -0400 Subject: adding dynamic err message support for violations Change-Id: I80c1a0cade46ef623fce91921449642d8eafb2f6 Issue-ID: LOG-683 Signed-off-by: Pierre Rioux --- .../onap/aai/validation/config/TopicConfig.java | 11 ++- .../validation/ruledriven/RuleDrivenValidator.java | 30 ++++--- .../aai/validation/ruledriven/rule/GroovyRule.java | 13 +-- .../onap/aai/validation/ruledriven/rule/Rule.java | 92 ++++++++++---------- .../aai/validation/ruledriven/rule/RuleResult.java | 98 ++++++++++++++++++++++ 5 files changed, 170 insertions(+), 74 deletions(-) create mode 100644 src/main/java/org/onap/aai/validation/ruledriven/rule/RuleResult.java (limited to 'src/main/java') diff --git a/src/main/java/org/onap/aai/validation/config/TopicConfig.java b/src/main/java/org/onap/aai/validation/config/TopicConfig.java index 99742ac..ccf5d51 100644 --- a/src/main/java/org/onap/aai/validation/config/TopicConfig.java +++ b/src/main/java/org/onap/aai/validation/config/TopicConfig.java @@ -46,13 +46,12 @@ public class TopicConfig { List publisherTopics = new ArrayList<>(); @Autowired - public TopicConfig (@Value("${consumer.topic.names}") final String consumerNames, @Value("${publisher.topic.names}") final String publisherNames){ - - consumerTopicNames = Arrays.asList(consumerNames.split(","));; - publisherTopicNames = Arrays.asList(publisherNames.split(","));; - - + public TopicConfig (@Value("${consumer.topic.names}") final String consumerNames, + @Value("${publisher.topic.names}") final String publisherNames) { + consumerTopicNames = Arrays.asList(consumerNames.split(",")); + publisherTopicNames = Arrays.asList(publisherNames.split(",")); } + /** * Gets the configuration of topics for consumption. * diff --git a/src/main/java/org/onap/aai/validation/ruledriven/RuleDrivenValidator.java b/src/main/java/org/onap/aai/validation/ruledriven/RuleDrivenValidator.java index 476c098..2bc2d90 100644 --- a/src/main/java/org/onap/aai/validation/ruledriven/RuleDrivenValidator.java +++ b/src/main/java/org/onap/aai/validation/ruledriven/RuleDrivenValidator.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -49,6 +50,7 @@ import org.onap.aai.validation.ruledriven.configuration.EntitySection; import org.onap.aai.validation.ruledriven.configuration.GroovyConfigurationException; import org.onap.aai.validation.ruledriven.configuration.RulesConfigurationLoader; import org.onap.aai.validation.ruledriven.rule.Rule; +import org.onap.aai.validation.ruledriven.rule.RuleResult; /** * Validator using explicit rules @@ -159,28 +161,30 @@ public class RuleDrivenValidator implements Validator { AttributeValues attributeValues = entity.getAttributeValues(rule.getAttributePaths()); // Execute the rule for this particular set of attribute values. - boolean valid = false; + RuleResult result = null; try { - valid = rule.execute(attributeValues); + result = rule.execute(attributeValues); } catch (IllegalArgumentException e) { throw new ValidationServiceException(ValidationServiceError.RULE_EXECUTION_ERROR, e, rule, attributeValues); } applicationLogger.debug(String.format("%s|%s|\"%s\"|%s", entity.getType(), entity.getIds(), rule.getName(), - valid ? "pass" : "fail")); + result.getSuccess() ? "pass" : "fail")); + + if (!result.getSuccess()) { + String errorMessage = MessageFormat.format(rule.getErrorMessage(), result.getErrorArguments().toArray()); - if (!valid) { //@formatter:off - Violation violation = builder - .category(rule.getErrorCategory()) - .severity(rule.getSeverity()) - .violationType(ViolationType.RULE) - .validationRule(rule.getName()) - .violationDetails(attributeValues.generateReport()) - .errorMessage(rule.getErrorMessage()) - .build(); - //@formatter:on + Violation violation = builder + .category(rule.getErrorCategory()) + .severity(rule.getSeverity()) + .violationType(ViolationType.RULE) + .validationRule(rule.getName()) + .violationDetails(attributeValues.generateReport()) + .errorMessage(errorMessage) + .build(); + //@formatter:on validationResult.addViolation(violation); } diff --git a/src/main/java/org/onap/aai/validation/ruledriven/rule/GroovyRule.java b/src/main/java/org/onap/aai/validation/ruledriven/rule/GroovyRule.java index b151f6b..df15791 100644 --- a/src/main/java/org/onap/aai/validation/ruledriven/rule/GroovyRule.java +++ b/src/main/java/org/onap/aai/validation/ruledriven/rule/GroovyRule.java @@ -125,7 +125,7 @@ public class GroovyRule implements Rule { * @return */ @Override - public Boolean execute(AttributeValues attributeValues) { + public RuleResult execute(AttributeValues attributeValues) { // Obtain the values of each of the attributes to pass into the rule List valueList = new ArrayList<>(); for (String attrName : this.attributePaths) { @@ -141,10 +141,10 @@ public class GroovyRule implements Rule { * @param values * * @param groovyObject an instance/object of a Groovy class that implements one or more rule methods - * @return the Boolean result of evaluating the expression + * @return the result of evaluating the expression */ @Override - public Boolean execute(Object... values) { + public RuleResult execute(Object... values) { Object result = null; try { result = groovyObject.invokeMethod(getRuleMethod(), values); @@ -153,12 +153,7 @@ public class GroovyRule implements Rule { } catch (NullPointerException e) { throw new IllegalArgumentException("Argument is null", e); } - - if (result instanceof Number) { - return !result.equals(0); - } else { - return (Boolean) result; - } + return new RuleResult(result); } @Override diff --git a/src/main/java/org/onap/aai/validation/ruledriven/rule/Rule.java b/src/main/java/org/onap/aai/validation/ruledriven/rule/Rule.java index 1196db0..60705ea 100644 --- a/src/main/java/org/onap/aai/validation/ruledriven/rule/Rule.java +++ b/src/main/java/org/onap/aai/validation/ruledriven/rule/Rule.java @@ -25,57 +25,57 @@ import org.onap.aai.validation.reader.data.AttributeValues; */ public interface Rule { - /** - * Gets the name of the rule - * - * @return the name - */ - String getName(); + /** + * Gets the name of the rule + * + * @return the name + */ + String getName(); - /** - * Gets the error message. - * - * @return the error message - */ - String getErrorMessage(); + /** + * Gets the error message. + * + * @return the error message + */ + String getErrorMessage(); - /** - * Gets the error category. - * - * @return the error category - */ - String getErrorCategory(); + /** + * Gets the error category. + * + * @return the error category + */ + String getErrorCategory(); - /** - * Gets the severity. - * - * @return the severity - */ - String getSeverity(); + /** + * Gets the severity. + * + * @return the severity + */ + String getSeverity(); - /** - * Gets the paths to the attributes to pass to the rule - * - * @return the attribute paths - */ - List getAttributePaths(); + /** + * Gets the paths to the attributes to pass to the rule + * + * @return the attribute paths + */ + List getAttributePaths(); - /** - * Execute the rule. - * - * @param values - * the attribute values to pass to the rule - * @return a boolean representing the rule evaluation (meaning success/failure) - */ - Boolean execute(AttributeValues values); + /** + * Execute the rule. + * + * @param values + * the attribute values to pass to the rule + * @return a RuleResult instance representing the rule evaluation (meaning success/failure) + */ + RuleResult execute(AttributeValues values); - /** - * Execute the rule. - * - * @param values - * the attribute values to pass to the rule - * @return a boolean representing the rule evaluation (meaning success/failure) - */ - Boolean execute(Object... values); + /** + * Execute the rule. + * + * @param values + * the attribute values to pass to the rule + * @return a RuleResult instance representing the rule evaluation (meaning success/failure) + */ + RuleResult execute(Object... values); } diff --git a/src/main/java/org/onap/aai/validation/ruledriven/rule/RuleResult.java b/src/main/java/org/onap/aai/validation/ruledriven/rule/RuleResult.java new file mode 100644 index 0000000..19f77f7 --- /dev/null +++ b/src/main/java/org/onap/aai/validation/ruledriven/rule/RuleResult.java @@ -0,0 +1,98 @@ +/* + * ============LICENSE_START=================================================== + * Copyright (c) 2018 Amdocs + * ============================================================================ + * 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. + * ============LICENSE_END===================================================== + */ +package org.onap.aai.validation.ruledriven.rule; + +import groovy.lang.Tuple2; +import java.util.Collections; +import java.util.List; + +/** + * Encapsulates the results of rule execution + * + */ +public class RuleResult { + + private Boolean success = true; + private List errorArguments = Collections.emptyList(); + + /** + * Creates an instance of this class using the groovy object returned by rule execution. + * + * Valid object types: + * Boolean: true = success; false = fail + * Number: 0 = success; non-zero = fail + * Tuple2: contains rule result and argument list + * - tuple's "first" contains a boolean representing the results of rule execution + * - tuple's "second" contains a list of strings used to expand rule error text + * + * @param groovyResult + */ + public RuleResult(Object groovyResult) { + if (groovyResult instanceof Number) { + success = !((Number)groovyResult).equals(0); + } else if (groovyResult instanceof Tuple2) { + handleTuple(groovyResult); + } else { + success = (Boolean)groovyResult; + } + } + + @SuppressWarnings("unused") + private RuleResult() { + // intentionally empty + } + + /** + * Returns the results of rule execution, i.e. success or fail + * @return + */ + public Boolean getSuccess() { + return success; + } + + /** + * Returns the list of arguments used to expand rule error text. + * + * For example, this errorText in a rule definition: + * 'Error found with "{0}" in "{1}"; value "{2}" is not a valid MAC address' + * + * used with the following runtime argument list: + * ["macaddr", "tenants.tenant.vservers.vserver.l-interfaces.l-interface", "02:fd:59:3"] + * + * would display: + * Error found with "macaddr" in "tenants.tenant.vservers.vserver.l-interfaces.l-interface"; value "02:fd:59:3" is not a valid MAC address + * + * @return a list of strings; will not return null + */ + public List getErrorArguments() { + return errorArguments; + } + + /** + * Handles a Tuple2 object returned by a groovy rule. + * The tuple's "first" contains a boolean representing the results of rule execution. + * The tuple's "second" contains a list of strings used to expand rule error text. + * @param tupleObject + */ + private void handleTuple(Object tupleObject) { + @SuppressWarnings("unchecked") + Tuple2> tuple = (Tuple2>)tupleObject; + success = tuple.getFirst(); + errorArguments = (tuple.getSecond() == null) ? Collections.emptyList() : tuple.getSecond(); + } +} -- cgit 1.2.3-korg