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.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 */
030public final class DetectorOptions {
031
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    /**
061     * Returns new Builder object.
062     *
063     * @return Builder object.
064     */
065    public static Builder newBuilder() {
066        return new DetectorOptions().new Builder();
067    }
068
069    /**
070     * Format of the regular expression.
071     *
072     * @return format of the regular expression.
073     */
074    public String getFormat() {
075        return format;
076    }
077
078    /**
079     * The violation reporter to use.
080     *
081     * @return the violation reporter to use.
082     */
083    public AbstractViolationReporter getReporter() {
084        return reporter;
085    }
086
087    /**
088     * The message to report violations with.
089     *
090     * @return the message to report violations with.
091     */
092    public String getMessage() {
093        return message;
094    }
095
096    /**
097     * The minimum number of allowed detections.
098     *
099     * @return the minimum number of allowed detections.
100     */
101    public int getMinimum() {
102        return minimum;
103    }
104
105    /**
106     * The maximum number of allowed detections.
107     *
108     * @return the maximum number of allowed detections.
109     */
110    public int getMaximum() {
111        return maximum;
112    }
113
114    /**
115     * The suppressor to use.
116     *
117     * @return the suppressor to use.
118     */
119    public MatchSuppressor getSuppressor() {
120        return suppressor;
121    }
122
123    /**
124     * The pattern to use when matching.
125     *
126     * @return the pattern to use when matching.
127     */
128    public Pattern getPattern() {
129        return pattern;
130    }
131
132    /** Class which implements Builder pattern to build DetectorOptions instance. */
133    public final class Builder {
134        /**
135         * Creates a new {@code Builder} instance.
136         */
137        public Builder() {
138            // no code by default
139        }
140
141        /**
142         * Specifies the violation reporter and returns Builder object.
143         *
144         * @param val for reporting violations.
145         * @return Builder object.
146         * @noinspection ReturnOfInnerClass
147         * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
148         */
149        public Builder reporter(AbstractViolationReporter val) {
150            reporter = val;
151            return this;
152        }
153
154        /**
155         * Specifies the compile-flags to compile a regular expression with
156         * and returns Builder object.
157         *
158         * @param val the format to use when matching lines.
159         * @return Builder object.
160         * @noinspection ReturnOfInnerClass
161         * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
162         */
163        public Builder compileFlags(int val) {
164            compileFlags = val;
165            return this;
166        }
167
168        /**
169         * Specifies the format to use when matching lines and returns Builder object.
170         *
171         * @param val the format to use when matching lines.
172         * @return Builder object.
173         * @noinspection ReturnOfInnerClass
174         * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
175         */
176        public Builder format(String val) {
177            format = val;
178            return this;
179        }
180
181        /**
182         * Specifies message to use when reporting a match and returns Builder object.
183         *
184         * @param val message to use when reporting a match.
185         * @return Builder object.
186         * @noinspection ReturnOfInnerClass
187         * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
188         */
189        public Builder message(String val) {
190            message = val;
191            return this;
192        }
193
194        /**
195         * Specifies the minimum allowed number of detections and returns Builder object.
196         *
197         * @param val the minimum allowed number of detections.
198         * @return Builder object.
199         * @noinspection ReturnOfInnerClass
200         * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
201         */
202        public Builder minimum(int val) {
203            minimum = val;
204            return this;
205        }
206
207        /**
208         * Specifies the maximum allowed number of detections and returns Builder object.
209         *
210         * @param val the maximum allowed number of detections.
211         * @return Builder object.
212         * @noinspection ReturnOfInnerClass
213         * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
214         */
215        public Builder maximum(int val) {
216            maximum = val;
217            return this;
218        }
219
220        /**
221         * Specifies whether to ignore case when matching and returns Builder object.
222         *
223         * @param val whether to ignore case when matching.
224         * @return Builder object.
225         * @noinspection ReturnOfInnerClass, BooleanParameter
226         * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
227         * @noinspectionreason BooleanParameter - check fields are boolean
228         */
229        public Builder ignoreCase(boolean val) {
230            ignoreCase = val;
231            return this;
232        }
233
234        /**
235         * Specifies the suppressor to use and returns Builder object.
236         *
237         * @param val the suppressor to use.
238         * @return current instance
239         * @noinspection ReturnOfInnerClass
240         * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
241         */
242        public Builder suppressor(MatchSuppressor val) {
243            suppressor = val;
244            return this;
245        }
246
247        /**
248         * Returns new DetectorOptions instance.
249         *
250         * @return DetectorOptions instance.
251         */
252        public DetectorOptions build() {
253            message = Optional.ofNullable(message).orElse("");
254            suppressor = Optional.ofNullable(suppressor).orElse(NeverSuppress.INSTANCE);
255            pattern = Optional.ofNullable(format).map(this::createPattern).orElse(null);
256            return DetectorOptions.this;
257        }
258
259        /**
260         * Creates pattern to use by DetectorOptions instance.
261         *
262         * @param formatValue the format to use.
263         * @return Pattern object.
264         */
265        private Pattern createPattern(String formatValue) {
266            int options = compileFlags;
267            if (ignoreCase) {
268                options |= Pattern.CASE_INSENSITIVE;
269            }
270            return Pattern.compile(formatValue, options);
271        }
272
273    }
274
275}