1 ///////////////////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3 // Copyright (C) 2001-2026 the original author or authors.
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ///////////////////////////////////////////////////////////////////////////////////////////////
19
20 package com.puppycrawl.tools.checkstyle.filters;
21
22 import java.util.Collections;
23 import java.util.HashSet;
24 import java.util.Objects;
25 import java.util.Set;
26
27 /**
28 * <div>
29 * This filter element is immutable and accepts an integer that matches a CSV value, where
30 * each value is an integer or a range of integers.
31 * </div>
32 */
33 final class CsvFilterElement implements IntFilterElement {
34
35 /** Filter set. */
36 private final Set<IntFilterElement> filters = new HashSet<>();
37
38 /**
39 * Constructs a {@code CsvFilterElement} from a CSV, Comma-Separated Values,
40 * string. Each value is an integer, or a range of integers. A range of
41 * integers is of the form integer-integer, such as 1-10.
42 * Note: integers must be non-negative.
43 *
44 * @param pattern the CSV string.
45 * @throws NumberFormatException if a component substring does not
46 * contain a parsable integer.
47 */
48 /* package */ CsvFilterElement(String pattern) {
49 for (String token : pattern.split(",", -1)) {
50 if (token.isEmpty()) {
51 continue;
52 }
53 final String trimmedToken = token.trim();
54 final int index = trimmedToken.indexOf('-');
55 if (index == -1) {
56 final int matchValue = Integer.parseInt(trimmedToken);
57 addFilter(new IntMatchFilterElement(matchValue));
58 }
59 else {
60 final int lowerBound =
61 Integer.parseInt(trimmedToken.substring(0, index));
62 final int upperBound =
63 Integer.parseInt(trimmedToken.substring(index + 1));
64 addFilter(new IntRangeFilterElement(lowerBound, upperBound));
65 }
66 }
67 }
68
69 /**
70 * Adds a IntFilterElement to the set.
71 *
72 * @param filter the IntFilterElement to add.
73 */
74 private void addFilter(IntFilterElement filter) {
75 filters.add(filter);
76 }
77
78 /**
79 * Returns the IntFilters of the filter set.
80 *
81 * @return the IntFilters of the filter set.
82 */
83 private Set<IntFilterElement> getFilters() {
84 return Collections.unmodifiableSet(filters);
85 }
86
87 /**
88 * Determines whether an Integer matches a CSV integer value.
89 *
90 * @param intValue the Integer to check.
91 * @return true if intValue is an Integer that matches a CSV value.
92 */
93 @Override
94 public boolean accept(int intValue) {
95 boolean result = false;
96 for (IntFilterElement filter : getFilters()) {
97 if (filter.accept(intValue)) {
98 result = true;
99 break;
100 }
101 }
102 return result;
103 }
104
105 @Override
106 public boolean equals(Object object) {
107 if (this == object) {
108 return true;
109 }
110 if (object == null || getClass() != object.getClass()) {
111 return false;
112 }
113 final CsvFilterElement csvFilter = (CsvFilterElement) object;
114 return Objects.equals(filters, csvFilter.filters);
115 }
116
117 @Override
118 public int hashCode() {
119 return Objects.hash(filters);
120 }
121
122 }