001////////////////////////////////////////////////////////////////////////////////
002// checkstyle: Checks Java source code for adherence to a set of rules.
003// Copyright (C) 2001-2017 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.Objects;
023import java.util.regex.Pattern;
024
025import com.puppycrawl.tools.checkstyle.api.AuditEvent;
026import com.puppycrawl.tools.checkstyle.api.Filter;
027import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
028
029/**
030 * This filter processes {@link AuditEvent}
031 * objects based on the criteria of file, check, module id, line, and
032 * column. It rejects an AuditEvent if the following match:
033 * <ul>
034 *   <li>the event's file name; and</li>
035 *   <li>the check name or the module identifier; and</li>
036 *   <li>(optionally) the event's line is in the filter's line CSV; and</li>
037 *   <li>(optionally) the check's columns is in the filter's column CSV.</li>
038 * </ul>
039 *
040 * @author Rick Giles
041 */
042public class SuppressElement
043    implements Filter {
044    /** The regexp to match file names against. */
045    private final Pattern fileRegexp;
046
047    /** The pattern for file names. */
048    private final String filePattern;
049
050    /** The regexp to match check names against. */
051    private final Pattern checkRegexp;
052
053    /** The pattern for check class names. */
054    private final String checkPattern;
055
056    /** Module id filter. */
057    private final String moduleId;
058
059    /** Line number filter. */
060    private final CsvFilter lineFilter;
061
062    /** CSV for line number filter. */
063    private final String linesCsv;
064
065    /** Column number filter. */
066    private final CsvFilter columnFilter;
067
068    /** CSV for column number filter. */
069    private final String columnsCsv;
070
071    /**
072     * Constructs a {@code SuppressElement} for a
073     * file name pattern.
074     *
075     * @param files   regular expression for names of filtered files.
076     * @param checks  regular expression for filtered check classes.
077     * @param modId   the id
078     * @param lines   lines CSV values and ranges for line number filtering.
079     * @param columns columns CSV values and ranges for column number filtering.
080     */
081    public SuppressElement(String files, String checks,
082                           String modId, String lines, String columns) {
083        filePattern = files;
084        fileRegexp = Pattern.compile(files);
085        checkPattern = checks;
086        if (checks == null) {
087            checkRegexp = null;
088        }
089        else {
090            checkRegexp = CommonUtils.createPattern(checks);
091        }
092        moduleId = modId;
093        linesCsv = lines;
094        if (lines == null) {
095            lineFilter = null;
096        }
097        else {
098            lineFilter = new CsvFilter(lines);
099        }
100        columnsCsv = columns;
101        if (columns == null) {
102            columnFilter = null;
103        }
104        else {
105            columnFilter = new CsvFilter(columns);
106        }
107    }
108
109    @Override
110    public boolean accept(AuditEvent event) {
111        return isFileNameAndModuleNotMatching(event)
112                || isLineAndColumnMatch(event);
113    }
114
115    /**
116     * Is matching by file name and Check name.
117     * @param event event
118     * @return true is matching
119     */
120    private boolean isFileNameAndModuleNotMatching(AuditEvent event) {
121        return event.getFileName() == null
122                || !fileRegexp.matcher(event.getFileName()).find()
123                || event.getLocalizedMessage() == null
124                || moduleId != null && !moduleId.equals(event.getModuleId())
125                || checkRegexp != null && !checkRegexp.matcher(event.getSourceName()).find();
126    }
127
128    /**
129     * Whether line and column match.
130     * @param event event to process.
131     * @return true if line and column match.
132     */
133    private boolean isLineAndColumnMatch(AuditEvent event) {
134        return (lineFilter != null || columnFilter != null)
135                && (lineFilter == null || !lineFilter.accept(event.getLine()))
136                && (columnFilter == null || !columnFilter.accept(event.getColumn()));
137    }
138
139    @Override
140    public int hashCode() {
141        return Objects.hash(filePattern, checkPattern, moduleId, linesCsv, columnsCsv);
142    }
143
144    @Override
145    public boolean equals(Object other) {
146        if (this == other) {
147            return true;
148        }
149        if (other == null || getClass() != other.getClass()) {
150            return false;
151        }
152        final SuppressElement suppressElement = (SuppressElement) other;
153        return Objects.equals(filePattern, suppressElement.filePattern)
154                && Objects.equals(checkPattern, suppressElement.checkPattern)
155                && Objects.equals(moduleId, suppressElement.moduleId)
156                && Objects.equals(linesCsv, suppressElement.linesCsv)
157                && Objects.equals(columnsCsv, suppressElement.columnsCsv);
158    }
159}