1 ///////////////////////////////////////////////////////////////////////////////////////////////
2 // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3 // Copyright (C) 2001-2024 the original author or authors.
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ///////////////////////////////////////////////////////////////////////////////////////////////
19
20 package com.puppycrawl.tools.checkstyle.checks.regexp;
21
22 import java.util.Optional;
23 import java.util.regex.Pattern;
24
25 import com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter;
26
27 /**
28 * Options for a detector.
29 */
30 public final class DetectorOptions {
31
32 /**
33 * Flags to compile a regular expression with.
34 * See {@link Pattern#flags()}.
35 */
36 private int compileFlags;
37 /** Used for reporting violations. */
38 private AbstractViolationReporter reporter;
39 /**
40 * Format of the regular expression to check for.
41 */
42 private String format;
43 /** The message to report on detection. If blank, then use the format. */
44 private String message;
45 /** Minimum number of times regular expression should occur in a file. */
46 private int minimum;
47 /** Maximum number of times regular expression should occur in a file. */
48 private int maximum;
49 /** Whether to ignore case when matching. */
50 private boolean ignoreCase;
51 /** Used to determine whether to suppress a detected match. */
52 private MatchSuppressor suppressor;
53 /** Pattern created from format. Lazily initialized. */
54 private Pattern pattern;
55
56 /** Default constructor.*/
57 private DetectorOptions() {
58 }
59
60 /**
61 * Returns new Builder object.
62 *
63 * @return Builder object.
64 */
65 public static Builder newBuilder() {
66 return new DetectorOptions().new Builder();
67 }
68
69 /**
70 * Format of the regular expression.
71 *
72 * @return format of the regular expression.
73 */
74 public String getFormat() {
75 return format;
76 }
77
78 /**
79 * The violation reporter to use.
80 *
81 * @return the violation reporter to use.
82 */
83 public AbstractViolationReporter getReporter() {
84 return reporter;
85 }
86
87 /**
88 * The message to report violations with.
89 *
90 * @return the message to report violations with.
91 */
92 public String getMessage() {
93 return message;
94 }
95
96 /**
97 * The minimum number of allowed detections.
98 *
99 * @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 /**
136 * Specifies the violation reporter and returns Builder object.
137 *
138 * @param val for reporting violations.
139 * @return Builder object.
140 * @noinspection ReturnOfInnerClass
141 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
142 */
143 public Builder reporter(AbstractViolationReporter val) {
144 reporter = val;
145 return this;
146 }
147
148 /**
149 * Specifies the compile-flags to compile a regular expression with
150 * and returns Builder object.
151 *
152 * @param val the format to use when matching lines.
153 * @return Builder object.
154 * @noinspection ReturnOfInnerClass
155 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
156 */
157 public Builder compileFlags(int val) {
158 compileFlags = val;
159 return this;
160 }
161
162 /**
163 * Specifies the format to use when matching lines and returns Builder object.
164 *
165 * @param val the format to use when matching lines.
166 * @return Builder object.
167 * @noinspection ReturnOfInnerClass
168 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
169 */
170 public Builder format(String val) {
171 format = val;
172 return this;
173 }
174
175 /**
176 * Specifies message to use when reporting a match and returns Builder object.
177 *
178 * @param val message to use when reporting a match.
179 * @return Builder object.
180 * @noinspection ReturnOfInnerClass
181 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
182 */
183 public Builder message(String val) {
184 message = val;
185 return this;
186 }
187
188 /**
189 * Specifies the minimum allowed number of detections and returns Builder object.
190 *
191 * @param val the minimum allowed number of detections.
192 * @return Builder object.
193 * @noinspection ReturnOfInnerClass
194 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
195 */
196 public Builder minimum(int val) {
197 minimum = val;
198 return this;
199 }
200
201 /**
202 * Specifies the maximum allowed number of detections and returns Builder object.
203 *
204 * @param val the maximum allowed number of detections.
205 * @return Builder object.
206 * @noinspection ReturnOfInnerClass
207 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
208 */
209 public Builder maximum(int val) {
210 maximum = val;
211 return this;
212 }
213
214 /**
215 * Specifies whether to ignore case when matching and returns Builder object.
216 *
217 * @param val whether to ignore case when matching.
218 * @return Builder object.
219 * @noinspection ReturnOfInnerClass, BooleanParameter
220 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
221 * @noinspectionreason BooleanParameter - check fields are boolean
222 */
223 public Builder ignoreCase(boolean val) {
224 ignoreCase = val;
225 return this;
226 }
227
228 /**
229 * Specifies the suppressor to use and returns Builder object.
230 *
231 * @param val the suppressor to use.
232 * @return current instance
233 * @noinspection ReturnOfInnerClass
234 * @noinspectionreason ReturnOfInnerClass - builder is only used in enclosing class
235 */
236 public Builder suppressor(MatchSuppressor val) {
237 suppressor = val;
238 return this;
239 }
240
241 /**
242 * Returns new DetectorOptions instance.
243 *
244 * @return DetectorOptions instance.
245 */
246 public DetectorOptions build() {
247 message = Optional.ofNullable(message).orElse("");
248 suppressor = Optional.ofNullable(suppressor).orElse(NeverSuppress.INSTANCE);
249 pattern = Optional.ofNullable(format).map(this::createPattern).orElse(null);
250 return DetectorOptions.this;
251 }
252
253 /**
254 * Creates pattern to use by DetectorOptions instance.
255 *
256 * @param formatValue the format to use.
257 * @return Pattern object.
258 */
259 private Pattern createPattern(String formatValue) {
260 int options = compileFlags;
261 if (ignoreCase) {
262 options |= Pattern.CASE_INSENSITIVE;
263 }
264 return Pattern.compile(formatValue, options);
265 }
266
267 }
268
269 }