2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2024 Ericsson
4 * Modifications Copyright (C) 2024 OpenInfra Foundation Europe
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
21 package org.oran.smo.yangtools.parser.findings;
23 import java.util.ArrayList;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Objects;
28 import java.util.regex.Pattern;
30 import org.oran.smo.yangtools.parser.model.ModuleIdentity;
33 * A predicate that takes one or more modules, and one or more severities.
35 * @Author Mark Hollmann
37 public class ModuleAndSeverityFilterPredicate implements FindingFilterPredicate {
40 * Parses the supplied string into an instance of ModuleAndSeverityFilterPredicate.
42 * Module names are separated from severities by the ";" character.
44 * Module names are separated by the "," character. Severities are likewise separated by
45 * the "," character. A value must be supplied for both module names and severities.
47 * The only allowable wildcard character is a "*", denoting any "character sequence".
49 * Example: The following will suppress all findings of severity INFO and WARNING in any IETF
50 * and IANA modules: "ietf-*,iana-*;INFO,WARNING"
52 public static ModuleAndSeverityFilterPredicate fromString(final String s,
53 final FindingSeverityCalculator findingSeverityCalculator) {
55 final String[] split = s.split(";");
56 if (split.length != 2) {
57 throw new RuntimeException("Invalid string format for ModuleAndSeverityFilterPredicate.");
60 final List<Pattern> moduleNames = new ArrayList<>();
61 if (!split[0].equals("*")) {
62 final String[] moduleNamesSplit = split[0].contains(",") ? split[0].split(",") : new String[] { split[0] };
63 for (final String stringPattern : moduleNamesSplit) {
64 moduleNames.add(Pattern.compile(stringPattern.trim().replace(".", "[.]").replace("*", ".*")));
68 final Set<FindingSeverity> severities = new HashSet<>();
69 if (!split[1].equals("*")) {
70 final String[] severitiesSplit = split[1].contains(",") ? split[1].split(",") : new String[] { split[1] };
71 for (final String severity : severitiesSplit) {
72 severities.add(FindingSeverity.valueOf(severity.trim().toUpperCase()));
76 return new ModuleAndSeverityFilterPredicate(moduleNames, severities, findingSeverityCalculator);
79 private final List<Pattern> moduleNames;
80 private final Set<FindingSeverity> severities;
81 private final FindingSeverityCalculator findingSeverityCalculator;
84 * A finding will be filtered if the statement is part of any of the supplied modules,
85 * and has any of the supplied severities.
87 * More formally, the name of the module in which the offending statement sits must be
88 * matchable against any of the module name patterns, and the severity of the finding must
89 * be part of the supplied set of severities.
91 * Supplying an empty list for module names, or empty set for severities, will match-all
94 public ModuleAndSeverityFilterPredicate(final List<Pattern> moduleNames, final Set<FindingSeverity> severities,
95 final FindingSeverityCalculator findingSeverityCalculator) {
96 this.moduleNames = Objects.requireNonNull(moduleNames);
97 this.severities = Objects.requireNonNull(severities);
98 this.findingSeverityCalculator = Objects.requireNonNull(findingSeverityCalculator);
102 public boolean test(final Finding f) {
103 return matchOnModule(f) && matchOnSeverity(f);
106 private boolean matchOnModule(final Finding finding) {
108 if (moduleNames.isEmpty()) {
113 * If the finding does not relate to a YAM then obviously we cannot match.
115 if (finding.getYangModel() == null) {
120 * It can happen that we don't have a module identity yet, because a finding was found
121 * before we actually got a chance to extract the module name. In this case we use the
122 * name of the input. This is not foolproof, of course.
124 final ModuleIdentity moduleIdentity = finding.getYangModel().getModuleIdentity();
125 final String moduleOrSubModuleName = moduleIdentity == null ?
126 finding.getYangModel().getYangInput().getName() :
127 moduleIdentity.getModuleName();
129 for (final Pattern pattern : moduleNames) {
130 if (pattern.matcher(moduleOrSubModuleName).matches()) {
138 private boolean matchOnSeverity(final Finding finding) {
140 if (severities.isEmpty()) {
144 return severities.contains(findingSeverityCalculator.calculateSeverity(finding.getFindingType()));