CodeConfig.java

/*
 * Copyright (C) 2019 sw4j.org
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.sw4j.tool.barcode.random.config;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * <p>
 * This class configures a concrete code to generate. A code is determined by the encoding (e.g. hex), the file type
 * (e.g. png), the url (or text) with {@code {code}} as placeholder for the random code, and the barcode parameters
 * (type, width, height and error correction).
 * </p>
 * <p>
 * To create a new instance programmatically use the
 * {@link org.sw4j.tool.barcode.random.config.CodeConfig.Builder Builder} which can be obtained with the method
 * {@link #builder()}.
 * </p>
 * <p>
 * Supported barcode types:
 * <ul>
 * <li>qrcode</li>
 * </ul>
 * </p>
 * <p>
 * Supported file types: All types supported by Image IO.
 * </p>
 * <p>
 * This class is immutable.
 * </p>
 * @author Uwe Plonus &lt;u.plonus@gmail.com&gt;
 */
public class CodeConfig {

    /**
     * <p>
     * The default width of a barcode.
     * </p>
     */
    private static final int DEFAULT_WIDTH = 200;

    /**
     * <p>
     * The default height of a barcode.
     * </p>
     */
    private static final int DEFAULT_HEIGHT = 200;

    /**
     * <p>
     * The barcode type to create (e.g. qrcode).
     * </p>
     */
    private final CodeType type;

    /**
     * <p>
     * The width of the barcode. Defaults to 200.
     * </p>
     */
    private final int width;

    /**
     * <p>
     * The height of the barcode. Defaults to 200.
     * </p>
     */
    private final int height;

    /**
     * <p>
     * The error correction parameter of the barcode (if applicable) (e.g. M for QRCode).
     * </p>
     */
    private final String errorCorrection;

    /**
     * <p>
     * The file type of the barcode to generate. Defaults to png.
     * </p>
     */
    private final String filetype;

    /**
     * <p>
     * The encoding of the random number (e.g. hex).
     * </p>
     */
    private final EncodingConfig encoding;

    /**
     * <p>
     * The URL (or text) that should be encoded in the barcode. The random number is placed at the {@code {code}}
     * placeholder.
     * </p>
     */
    private final String url;

    /**
     * <p>
     * Create a new {@code CodeConfig} object with the given parameters.
     * </p>
     * <p>
     * If the size cannot be parsed then the default size will be used.
     * </p>
     * <p>
     * This constructor is annotated so that a YAML or JSON parsed with jackson fasterxml can create an instance
     * directly.
     * </p>
     * @param type the type of the barcode to create (e.g. qrcode). May not be null.
     * @param size the size of the barcode, given in the format "(width)x(height)", e.g. 120x150 for with 120 and height
     *   150. If only a single number is given a square with the given number as width and height is configured.
     * @param errorCorrection the error correction of the barcode (if applicable), e.g. "M" for QRCode.
     * @param filetype the file type for the final barcode image.
     * @param encoding the encoding to use for encoding the random number. May not be null.
     * @param url the URL (or text) to encode in the barcode.
     * @throws IllegalArgumentException if either {@code type} or {@code encoding} is {@code null} or the {@code type}
     *   is unknown.
     */
    public CodeConfig(
            @JsonProperty("type") final String type,
            @JsonProperty("size") final String size,
            @JsonProperty("errorcorrection") final String errorCorrection,
            @JsonProperty("filetype") final String filetype,
            @JsonProperty("encoding") final EncodingConfig encoding,
            @JsonProperty("url") final String url) {
        if (type == null) {
            throw new IllegalArgumentException(String.format("%s: Missing type", getClass().getSimpleName()));
        }
        if (encoding == null) {
            throw new IllegalArgumentException(String.format("%s: Missing encoding", getClass().getSimpleName()));
        }
        this.type = CodeType.lookup(type);
        if (this.type == null) {
            throw new IllegalArgumentException(
                    String.format("%s: Unknown type '%s'", getClass().getSimpleName(), type));
        }
        if (size == null || !size.matches("\\d+(x\\d+)?")) {
            width = DEFAULT_WIDTH;
            height = DEFAULT_HEIGHT;
        } else {
            Pattern p = Pattern.compile("(\\d+)(x(\\d+))?");
            Matcher m = p.matcher(size);
            m.matches();
            width = Integer.parseInt(m.group(1));
            if (m.group(2) == null) {
                height = width;
            } else {
                height = Integer.parseInt(m.group(3));
            }
        }
        this.errorCorrection = errorCorrection;
        this.filetype = filetype == null ? "png" : filetype;
        this.encoding = encoding;
        this.url = url;
    }

    /**
     * <p>
     * Return the type of the barcode (e.g. qrcode).
     * </p>
     * @return the type of the barcode. Is never {@code null}.
     */
    public CodeType getType() {
        return type;
    }

    /**
     * <p>
     * Return the width of the barcode. Defaults to 200.
     * </p>
     * @return the width of the barcode.
     */
    public int getWidth() {
        return width;
    }

    /**
     * <p>
     * Return the height of the barcode. Defaults to 200.
     * </p>
     * @return the width of the barcode.
     */
    public int getHeight() {
        return height;
    }

    /**
     * <p>
     * Return the error correction of the barcode. May be {@code null} or empty.
     * </p>
     * @return the error correction of the barcode.
     */
    public String getErrorCorrection() {
        return errorCorrection;
    }

    /**
     * <p>
     * Return the file type of the barcode. Defaults to png.
     * </p>
     * @return the file type of the barcode.
     */
    public String getFiletype() {
        return filetype;
    }

    /**
     * <p>
     * Return the encoding of the random number in the barcode. Is never {@code null}.
     * </p>
     * @return the encoding of the random number.
     */
    public EncodingConfig getEncoding() {
        return encoding;
    }

    /**
     * <p>
     * Return the URL (or text) of the barcode with the placeholder {@code {code}} replaced by the encoded random
     * number.
     * </p>
     * @return the URL of the barcode.
     */
    public String getUrl() {
        return url;
    }

    /**
     * <p>
     * Return a {@link org.sw4j.tool.barcode.random.config.CodeConfig.Builder Builder} that can be used to build a
     * config.
     * </p>
     * @return a {@link org.sw4j.tool.barcode.random.config.CodeConfig.Builder Builder}.
     */
    public static Builder builder() {
        return new Builder();
    }


    /**
     * <p>
     * This class is a Builder to build a {@link org.sw4j.tool.barcode.random.config.CodeConfig CodeConfig}
     * programmatically. All methods to set the values are fluent to ease the building of a configuration.
     * </p>
     * <p>
     * This class is not thread save.
     * </p>
     * @author Uwe Plonus &lt;u.plonus@gmail.com&gt;
     */
    public static class Builder {

        /**
         * <p>
         * The type of the barcode.
         * </p>
         */
        private String type;

        /**
         * <p>
         * The width of the barcode.
         * </p>
         */
        private int width;

        /**
         * <p>
         * The height of the barcode.
         * </p>
         */
        private int height;

        /**
         * <p>
         * The error correction of the barcode.
         * </p>
         */
        private String errorCorrection;

        /**
         * <p>
         * The file type of the barcode.
         * </p>
         */
        private String filetype;

        /**
         * <p>
         * The encoding for the random number.
         * </p>
         */
        private EncodingConfig encoding;

        /**
         * <p>
         * The URL (or text) for the barcode.
         * </p>
         */
        private String url;

        /**
         * <p>
         * Create a new {@code Builder}.
         * </p>
         */
        public Builder() {
        }

        /**
         * <p>
         * Set the type of the barcode.
         * </p>
         * @param type the type of the barcode.
         * @return the builder for a fluent interface.
         */
        public Builder setType(final String type) {
            this.type = type;
            return this;
        }

        /**
         * <p>
         * Set the width of the barcode.
         * </p>
         * @param width the width of the barcode.
         * @return the builder for a fluent interface.
         */
        public Builder setWidth(final int width) {
            this.width = width;
            return this;
        }

        /**
         * <p>
         * Set the height of the barcode.
         * </p>
         * @param height the height of the barcode.
         * @return the builder for a fluent interface.
         */
        public Builder setHeight(final int height) {
            this.height = height;
            return this;
        }

        /**
         * <p>
         * Set the error correction of the barcode.
         * </p>
         * @param errorCorrection the error correction of the barcode.
         * @return the builder for a fluent interface.
         */
        public Builder setErrorCorrection(final String errorCorrection) {
            this.errorCorrection = errorCorrection;
            return this;
        }

        /**
         * <p>
         * Set the file type of the barcode.
         * </p>
         * @param filetype the file type of the barcode.
         * @return the builder for a fluent interface.
         */
        public Builder setFiletype(final String filetype) {
            this.filetype = filetype;
            return this;
        }

        /**
         * <p>
         * Set the encoding of the random number in the barcode.
         * </p>
         * @param encoding the encoding of the random number in the barcode.
         * @return the builder for a fluent interface.
         */
        public Builder setEncoding(final EncodingConfig encoding) {
            this.encoding = encoding;
            return this;
        }

        /**
         * <p>
         * Set the URL (or text) of the barcode.
         * </p>
         * @param url the URL (or text) of the barcode.
         * @return the builder for a fluent interface.
         */
        public Builder setUrl(final String url) {
            this.url = url;
            return this;
        }

        /**
         * <p>
         * Build a new {@link org.sw4j.tool.barcode.random.config.CodeConfig CodeConfig} with the parameters set.
         * </p>
         * @return the new created {@link org.sw4j.tool.barcode.random.config.CodeConfig CodeConfig}.
         * @throws IllegalArgumentException if either the type or encoding is {@code null} or the type is unknown.
         */
        public CodeConfig build() {
            String size = null;
            if (width > 0) {
                StringBuilder sb = new StringBuilder();
                sb.append(String.valueOf(width));
                if (height > 0) {
                    sb.append("x");
                    sb.append(String.valueOf(height));
                }
                size = sb.toString();
            }
            return new CodeConfig(type, size, errorCorrection, filetype, encoding, url);
        }

    }

}