001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2026 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018/////////////////////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.filters; 021 022import java.util.Collections; 023import java.util.HashSet; 024import java.util.Objects; 025import java.util.Set; 026 027/** 028 * <div> 029 * This filter element is immutable and accepts an integer that matches a CSV value, where 030 * each value is an integer or a range of integers. 031 * </div> 032 */ 033final class CsvFilterElement implements IntFilterElement { 034 035 /** Filter set. */ 036 private final Set<IntFilterElement> filters = new HashSet<>(); 037 038 /** 039 * Constructs a {@code CsvFilterElement} from a CSV, Comma-Separated Values, 040 * string. Each value is an integer, or a range of integers. A range of 041 * integers is of the form integer-integer, such as 1-10. 042 * Note: integers must be non-negative. 043 * 044 * @param pattern the CSV string. 045 * @throws NumberFormatException if a component substring does not 046 * contain a parsable integer. 047 */ 048 /* package */ CsvFilterElement(String pattern) { 049 for (String token : pattern.split(",", -1)) { 050 if (token.isEmpty()) { 051 continue; 052 } 053 final String trimmedToken = token.trim(); 054 final int index = trimmedToken.indexOf('-'); 055 if (index == -1) { 056 final int matchValue = Integer.parseInt(trimmedToken); 057 addFilter(new IntMatchFilterElement(matchValue)); 058 } 059 else { 060 final int lowerBound = 061 Integer.parseInt(trimmedToken.substring(0, index)); 062 final int upperBound = 063 Integer.parseInt(trimmedToken.substring(index + 1)); 064 addFilter(new IntRangeFilterElement(lowerBound, upperBound)); 065 } 066 } 067 } 068 069 /** 070 * Adds a IntFilterElement to the set. 071 * 072 * @param filter the IntFilterElement to add. 073 */ 074 private void addFilter(IntFilterElement filter) { 075 filters.add(filter); 076 } 077 078 /** 079 * Returns the IntFilters of the filter set. 080 * 081 * @return the IntFilters of the filter set. 082 */ 083 private Set<IntFilterElement> getFilters() { 084 return Collections.unmodifiableSet(filters); 085 } 086 087 /** 088 * Determines whether an Integer matches a CSV integer value. 089 * 090 * @param intValue the Integer to check. 091 * @return true if intValue is an Integer that matches a CSV value. 092 */ 093 @Override 094 public boolean accept(int intValue) { 095 boolean result = false; 096 for (IntFilterElement filter : getFilters()) { 097 if (filter.accept(intValue)) { 098 result = true; 099 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}