001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2024 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; 026import java.util.StringTokenizer; 027 028/** 029 * <div> 030 * This filter element is immutable and accepts an integer that matches a CSV value, where 031 * each value is an integer or a range of integers. 032 * </div> 033 */ 034class CsvFilterElement implements IntFilterElement { 035 036 /** Filter set. */ 037 private final Set<IntFilterElement> filters = new HashSet<>(); 038 039 /** 040 * Constructs a {@code CsvFilterElement} from a CSV, Comma-Separated Values, 041 * string. Each value is an integer, or a range of integers. A range of 042 * integers is of the form integer-integer, such as 1-10. 043 * Note: integers must be non-negative. 044 * 045 * @param pattern the CSV string. 046 * @throws NumberFormatException if a component substring does not 047 * contain a parsable integer. 048 */ 049 /* package */ CsvFilterElement(String pattern) { 050 final StringTokenizer tokenizer = new StringTokenizer(pattern, ","); 051 while (tokenizer.hasMoreTokens()) { 052 final String token = tokenizer.nextToken().trim(); 053 final int index = token.indexOf('-'); 054 if (index == -1) { 055 final int matchValue = Integer.parseInt(token); 056 addFilter(new IntMatchFilterElement(matchValue)); 057 } 058 else { 059 final int lowerBound = 060 Integer.parseInt(token.substring(0, index)); 061 final int upperBound = 062 Integer.parseInt(token.substring(index + 1)); 063 addFilter(new IntRangeFilterElement(lowerBound, upperBound)); 064 } 065 } 066 } 067 068 /** 069 * Adds a IntFilterElement to the set. 070 * 071 * @param filter the IntFilterElement to add. 072 */ 073 private void addFilter(IntFilterElement filter) { 074 filters.add(filter); 075 } 076 077 /** 078 * Returns the IntFilters of the filter set. 079 * 080 * @return the IntFilters of the filter set. 081 */ 082 protected Set<IntFilterElement> getFilters() { 083 return Collections.unmodifiableSet(filters); 084 } 085 086 /** 087 * Determines whether an Integer matches a CSV integer value. 088 * 089 * @param intValue the Integer to check. 090 * @return true if intValue is an Integer that matches a CSV value. 091 */ 092 @Override 093 public boolean accept(int intValue) { 094 boolean result = false; 095 for (IntFilterElement filter : getFilters()) { 096 if (filter.accept(intValue)) { 097 result = true; 098 break; 099 } 100 } 101 return result; 102 } 103 104 @Override 105 public boolean equals(Object object) { 106 if (this == object) { 107 return true; 108 } 109 if (object == null || getClass() != object.getClass()) { 110 return false; 111 } 112 final CsvFilterElement csvFilter = (CsvFilterElement) object; 113 return Objects.equals(filters, csvFilter.filters); 114 } 115 116 @Override 117 public int hashCode() { 118 return Objects.hash(filters); 119 } 120 121}