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.checks.regexp;
021
022import java.util.Optional;
023import java.util.regex.Pattern;
024
025import com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter;
026
027/**
028 * Options for a detector.
029 * @author Oliver Burn
030 */
031public final class DetectorOptions {
032    /**
033     * Flags to compile a regular expression with.
034     * See {@link Pattern#flags()}.
035     */
036    private int compileFlags;
037    /** Used for reporting violations. */
038    private AbstractViolationReporter reporter;
039    /**
040     * Format of the regular expression to check for.
041     */
042    private String format;
043    /** The message to report on detection. If blank, then use the format. */
044    private String message = "";
045    /** Minimum number of times regular expression should occur in a file. */
046    private int minimum;
047    /** Maximum number of times regular expression should occur in a file. */
048    private int maximum;
049    /** Whether to ignore case when matching. */
050    private boolean ignoreCase;
051    /** Used to determine whether to suppress a detected match. */
052    private MatchSuppressor suppressor;
053    /** Pattern created from format. Lazily initialized. */
054    private Pattern pattern;
055
056    /** Default constructor.*/
057    private DetectorOptions() { }
058
059    /**
060     * Returns new Builder object.
061     * @return Builder object.
062     */
063    public static Builder newBuilder() {
064        return new DetectorOptions().new Builder();
065    }
066
067    /**
068     * Format of the regular expression.
069     * @return format of the regular expression.
070     */
071    public String getFormat() {
072        return format;
073    }
074
075    /**
076     * The violation reporter to use.
077     * @return the violation reporter to use.
078     */
079    public AbstractViolationReporter getReporter() {
080        return reporter;
081    }
082
083    /**
084     * The message to report errors with.
085     * @return the message to report errors with.
086     */
087    public String getMessage() {
088        return message;
089    }
090
091    /**
092     * The minimum number of allowed detections.
093     * @return the minimum number of allowed detections.
094     */
095    public int getMinimum() {
096        return minimum;
097    }
098
099    /**
100     * The maximum number of allowed detections.
101     * @return the maximum number of allowed detections.
102     */
103    public int getMaximum() {
104        return maximum;
105    }
106
107    /**
108     * The suppressor to use.
109     * @return the suppressor to use.
110     */
111    public MatchSuppressor getSuppressor() {
112        return suppressor;
113    }
114
115    /**
116     * The pattern to use when matching.
117     * @return the pattern to use when matching.
118     */
119    public Pattern getPattern() {
120        if (pattern == null) {
121            int options = compileFlags;
122
123            if (ignoreCase) {
124                options |= Pattern.CASE_INSENSITIVE;
125            }
126            pattern = Pattern.compile(format, options);
127        }
128        return pattern;
129    }
130
131    /** Class which implements Builder pattern to build DetectorOptions instance. */
132    public final class Builder {
133
134        /**
135         * Specifies the violation reporter and returns Builder object.
136         * @param val for reporting violations.
137         * @return Builder object.
138         * @noinspection ReturnOfInnerClass
139         */
140        public Builder reporter(AbstractViolationReporter val) {
141            reporter = val;
142            return this;
143        }
144
145        /**
146         * Specifies the compile flags to compile a regular expression with
147         * and returns Builder object.
148         * @param val the format to use when matching lines.
149         * @return Builder object.
150         * @noinspection ReturnOfInnerClass
151         */
152        public Builder compileFlags(int val) {
153            compileFlags = val;
154            return this;
155        }
156
157        /**
158         * Specifies the format to use when matching lines and returns Builder object.
159         * @param val the format to use when matching lines.
160         * @return Builder object.
161         * @noinspection ReturnOfInnerClass
162         */
163        public Builder format(String val) {
164            format = val;
165            return this;
166        }
167
168        /**
169         * Specifies message to use when reporting a match and returns Builder object.
170         * @param val message to use when reporting a match.
171         * @return Builder object.
172         * @noinspection ReturnOfInnerClass
173         */
174        public Builder message(String val) {
175            message = val;
176            return this;
177        }
178
179        /**
180         * Specifies the minimum allowed number of detections and returns Builder object.
181         * @param val the minimum allowed number of detections.
182         * @return Builder object.
183         * @noinspection ReturnOfInnerClass
184         */
185        public Builder minimum(int val) {
186            minimum = val;
187            return this;
188        }
189
190        /**
191         * Specifies the maximum allowed number of detections and returns Builder object.
192         * @param val the maximum allowed number of detections.
193         * @return Builder object.
194         * @noinspection ReturnOfInnerClass
195         */
196        public Builder maximum(int val) {
197            maximum = val;
198            return this;
199        }
200
201        /**
202         * Specifies whether to ignore case when matching and returns Builder object.
203         * @param val whether to ignore case when matching.
204         * @return Builder object.
205         * @noinspection ReturnOfInnerClass, BooleanParameter
206         */
207        public Builder ignoreCase(boolean val) {
208            ignoreCase = val;
209            return this;
210        }
211
212        /**
213         * Specifies the suppressor to use and returns Builder object.
214         * @param val the suppressor to use.
215         * @return current instance
216         * @noinspection ReturnOfInnerClass
217         */
218        public Builder suppressor(MatchSuppressor val) {
219            suppressor = val;
220            return this;
221        }
222
223        /**
224         * Returns new DetectorOptions instance.
225         * @return DetectorOptions instance.
226         */
227        public DetectorOptions build() {
228            message = Optional.ofNullable(message).orElse("");
229            suppressor = Optional.ofNullable(suppressor).orElse(NeverSuppress.INSTANCE);
230            return DetectorOptions.this;
231        }
232    }
233}