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 }