View Javadoc
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 &lt;u.plonus@gmail.com&gt;
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 &lt;u.plonus@gmail.com&gt;
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 }