1 /*
2 * Copyright (C) 2019 sw4j.org
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 package org.sw4j.tool.barcode.random.config;
18
19 import com.fasterxml.jackson.annotation.JsonProperty;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 /**
24 * <p>
25 * This class configures a concrete code to generate. A code is determined by the encoding (e.g. hex), the file type
26 * (e.g. png), the url (or text) with {@code {code}} as placeholder for the random code, and the barcode parameters
27 * (type, width, height and error correction).
28 * </p>
29 * <p>
30 * To create a new instance programmatically use the
31 * {@link org.sw4j.tool.barcode.random.config.CodeConfig.Builder Builder} which can be obtained with the method
32 * {@link #builder()}.
33 * </p>
34 * <p>
35 * Supported barcode types:
36 * <ul>
37 * <li>qrcode</li>
38 * </ul>
39 * </p>
40 * <p>
41 * Supported file types: All types supported by Image IO.
42 * </p>
43 * <p>
44 * This class is immutable.
45 * </p>
46 * @author Uwe Plonus <u.plonus@gmail.com>
47 */
48 public class CodeConfig {
49
50 /**
51 * <p>
52 * The default width of a barcode.
53 * </p>
54 */
55 private static final int DEFAULT_WIDTH = 200;
56
57 /**
58 * <p>
59 * The default height of a barcode.
60 * </p>
61 */
62 private static final int DEFAULT_HEIGHT = 200;
63
64 /**
65 * <p>
66 * The barcode type to create (e.g. qrcode).
67 * </p>
68 */
69 private final CodeType type;
70
71 /**
72 * <p>
73 * The width of the barcode. Defaults to 200.
74 * </p>
75 */
76 private final int width;
77
78 /**
79 * <p>
80 * The height of the barcode. Defaults to 200.
81 * </p>
82 */
83 private final int height;
84
85 /**
86 * <p>
87 * The error correction parameter of the barcode (if applicable) (e.g. M for QRCode).
88 * </p>
89 */
90 private final String errorCorrection;
91
92 /**
93 * <p>
94 * The file type of the barcode to generate. Defaults to png.
95 * </p>
96 */
97 private final String filetype;
98
99 /**
100 * <p>
101 * The encoding of the random number (e.g. hex).
102 * </p>
103 */
104 private final EncodingConfig encoding;
105
106 /**
107 * <p>
108 * The URL (or text) that should be encoded in the barcode. The random number is placed at the {@code {code}}
109 * placeholder.
110 * </p>
111 */
112 private final String url;
113
114 /**
115 * <p>
116 * Create a new {@code CodeConfig} object with the given parameters.
117 * </p>
118 * <p>
119 * If the size cannot be parsed then the default size will be used.
120 * </p>
121 * <p>
122 * This constructor is annotated so that a YAML or JSON parsed with jackson fasterxml can create an instance
123 * directly.
124 * </p>
125 * @param type the type of the barcode to create (e.g. qrcode). May not be null.
126 * @param size the size of the barcode, given in the format "(width)x(height)", e.g. 120x150 for with 120 and height
127 * 150. If only a single number is given a square with the given number as width and height is configured.
128 * @param errorCorrection the error correction of the barcode (if applicable), e.g. "M" for QRCode.
129 * @param filetype the file type for the final barcode image.
130 * @param encoding the encoding to use for encoding the random number. May not be null.
131 * @param url the URL (or text) to encode in the barcode.
132 * @throws IllegalArgumentException if either {@code type} or {@code encoding} is {@code null} or the {@code type}
133 * is unknown.
134 */
135 public CodeConfig(
136 @JsonProperty("type") final String type,
137 @JsonProperty("size") final String size,
138 @JsonProperty("errorcorrection") final String errorCorrection,
139 @JsonProperty("filetype") final String filetype,
140 @JsonProperty("encoding") final EncodingConfig encoding,
141 @JsonProperty("url") final String url) {
142 if (type == null) {
143 throw new IllegalArgumentException(String.format("%s: Missing type", getClass().getSimpleName()));
144 }
145 if (encoding == null) {
146 throw new IllegalArgumentException(String.format("%s: Missing encoding", getClass().getSimpleName()));
147 }
148 this.type = CodeType.lookup(type);
149 if (this.type == null) {
150 throw new IllegalArgumentException(
151 String.format("%s: Unknown type '%s'", getClass().getSimpleName(), type));
152 }
153 if (size == null || !size.matches("\\d+(x\\d+)?")) {
154 width = DEFAULT_WIDTH;
155 height = DEFAULT_HEIGHT;
156 } else {
157 Pattern p = Pattern.compile("(\\d+)(x(\\d+))?");
158 Matcher m = p.matcher(size);
159 m.matches();
160 width = Integer.parseInt(m.group(1));
161 if (m.group(2) == null) {
162 height = width;
163 } else {
164 height = Integer.parseInt(m.group(3));
165 }
166 }
167 this.errorCorrection = errorCorrection;
168 this.filetype = filetype == null ? "png" : filetype;
169 this.encoding = encoding;
170 this.url = url;
171 }
172
173 /**
174 * <p>
175 * Return the type of the barcode (e.g. qrcode).
176 * </p>
177 * @return the type of the barcode. Is never {@code null}.
178 */
179 public CodeType getType() {
180 return type;
181 }
182
183 /**
184 * <p>
185 * Return the width of the barcode. Defaults to 200.
186 * </p>
187 * @return the width of the barcode.
188 */
189 public int getWidth() {
190 return width;
191 }
192
193 /**
194 * <p>
195 * Return the height of the barcode. Defaults to 200.
196 * </p>
197 * @return the width of the barcode.
198 */
199 public int getHeight() {
200 return height;
201 }
202
203 /**
204 * <p>
205 * Return the error correction of the barcode. May be {@code null} or empty.
206 * </p>
207 * @return the error correction of the barcode.
208 */
209 public String getErrorCorrection() {
210 return errorCorrection;
211 }
212
213 /**
214 * <p>
215 * Return the file type of the barcode. Defaults to png.
216 * </p>
217 * @return the file type of the barcode.
218 */
219 public String getFiletype() {
220 return filetype;
221 }
222
223 /**
224 * <p>
225 * Return the encoding of the random number in the barcode. Is never {@code null}.
226 * </p>
227 * @return the encoding of the random number.
228 */
229 public EncodingConfig getEncoding() {
230 return encoding;
231 }
232
233 /**
234 * <p>
235 * Return the URL (or text) of the barcode with the placeholder {@code {code}} replaced by the encoded random
236 * number.
237 * </p>
238 * @return the URL of the barcode.
239 */
240 public String getUrl() {
241 return url;
242 }
243
244 /**
245 * <p>
246 * Return a {@link org.sw4j.tool.barcode.random.config.CodeConfig.Builder Builder} that can be used to build a
247 * config.
248 * </p>
249 * @return a {@link org.sw4j.tool.barcode.random.config.CodeConfig.Builder Builder}.
250 */
251 public static Builder builder() {
252 return new Builder();
253 }
254
255
256 /**
257 * <p>
258 * This class is a Builder to build a {@link org.sw4j.tool.barcode.random.config.CodeConfig CodeConfig}
259 * programmatically. All methods to set the values are fluent to ease the building of a configuration.
260 * </p>
261 * <p>
262 * This class is not thread save.
263 * </p>
264 * @author Uwe Plonus <u.plonus@gmail.com>
265 */
266 public static class Builder {
267
268 /**
269 * <p>
270 * The type of the barcode.
271 * </p>
272 */
273 private String type;
274
275 /**
276 * <p>
277 * The width of the barcode.
278 * </p>
279 */
280 private int width;
281
282 /**
283 * <p>
284 * The height of the barcode.
285 * </p>
286 */
287 private int height;
288
289 /**
290 * <p>
291 * The error correction of the barcode.
292 * </p>
293 */
294 private String errorCorrection;
295
296 /**
297 * <p>
298 * The file type of the barcode.
299 * </p>
300 */
301 private String filetype;
302
303 /**
304 * <p>
305 * The encoding for the random number.
306 * </p>
307 */
308 private EncodingConfig encoding;
309
310 /**
311 * <p>
312 * The URL (or text) for the barcode.
313 * </p>
314 */
315 private String url;
316
317 /**
318 * <p>
319 * Create a new {@code Builder}.
320 * </p>
321 */
322 public Builder() {
323 }
324
325 /**
326 * <p>
327 * Set the type of the barcode.
328 * </p>
329 * @param type the type of the barcode.
330 * @return the builder for a fluent interface.
331 */
332 public Builder setType(final String type) {
333 this.type = type;
334 return this;
335 }
336
337 /**
338 * <p>
339 * Set the width of the barcode.
340 * </p>
341 * @param width the width of the barcode.
342 * @return the builder for a fluent interface.
343 */
344 public Builder setWidth(final int width) {
345 this.width = width;
346 return this;
347 }
348
349 /**
350 * <p>
351 * Set the height of the barcode.
352 * </p>
353 * @param height the height of the barcode.
354 * @return the builder for a fluent interface.
355 */
356 public Builder setHeight(final int height) {
357 this.height = height;
358 return this;
359 }
360
361 /**
362 * <p>
363 * Set the error correction of the barcode.
364 * </p>
365 * @param errorCorrection the error correction of the barcode.
366 * @return the builder for a fluent interface.
367 */
368 public Builder setErrorCorrection(final String errorCorrection) {
369 this.errorCorrection = errorCorrection;
370 return this;
371 }
372
373 /**
374 * <p>
375 * Set the file type of the barcode.
376 * </p>
377 * @param filetype the file type of the barcode.
378 * @return the builder for a fluent interface.
379 */
380 public Builder setFiletype(final String filetype) {
381 this.filetype = filetype;
382 return this;
383 }
384
385 /**
386 * <p>
387 * Set the encoding of the random number in the barcode.
388 * </p>
389 * @param encoding the encoding of the random number in the barcode.
390 * @return the builder for a fluent interface.
391 */
392 public Builder setEncoding(final EncodingConfig encoding) {
393 this.encoding = encoding;
394 return this;
395 }
396
397 /**
398 * <p>
399 * Set the URL (or text) of the barcode.
400 * </p>
401 * @param url the URL (or text) of the barcode.
402 * @return the builder for a fluent interface.
403 */
404 public Builder setUrl(final String url) {
405 this.url = url;
406 return this;
407 }
408
409 /**
410 * <p>
411 * Build a new {@link org.sw4j.tool.barcode.random.config.CodeConfig CodeConfig} with the parameters set.
412 * </p>
413 * @return the new created {@link org.sw4j.tool.barcode.random.config.CodeConfig CodeConfig}.
414 * @throws IllegalArgumentException if either the type or encoding is {@code null} or the type is unknown.
415 */
416 public CodeConfig build() {
417 String size = null;
418 if (width > 0) {
419 StringBuilder sb = new StringBuilder();
420 sb.append(String.valueOf(width));
421 if (height > 0) {
422 sb.append("x");
423 sb.append(String.valueOf(height));
424 }
425 size = sb.toString();
426 }
427 return new CodeConfig(type, size, errorCorrection, filetype, encoding, url);
428 }
429
430 }
431
432 }