Config.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.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import java.io.File;
import java.io.IOException;

/**
 * <p>
 * The top level class for configuring the whole application. This class includes the configuration for the input file,
 * the output file(s) and the random number generation and presentation.
 * </p>
 * <p>
 * To create a new instance programmatically use the {@link org.sw4j.tool.barcode.random.config.Config.Builder Builder}
 * which can be obtained by the method {@link #builder()}.
 * </p>
 * <p>
 * This class is immutable.
 * </p>
 * @author Uwe Plonus &lt;u.plonus@gmail.com&gt;
 */
public class Config {

    /**
     * <p>
     * The configuration for the input file.
     * </p>
     */
    private final FileConfig input;

    /**
     * <p>
     * The configuration for the output file(s).
     * </p>
     */
    private final OutputConfig output;

    /**
     * <p>
     * The configuration for the random number generation and presentation.
     * </p>
     */
    private final GenerationConfig random;

    /**
     * <p>
     * The configuration for the predefined presentation.
     * </p>
     */
    private final GenerationConfig predefined;

    /**
     * <p>
     * Create a new {@code Config} with the given part configurations.
     * </p>
     * <p>
     * This constructor is annotated so that a YAML or JSON parsed with jackson fasterxml can create an instance
     * directly.
     * </p>
     * @param input the input file configuration.
     * @param output the output file(s) configuration.
     * @param random the random generation and presentation configuration.
     * @param predefined the predefined presentation configuration.
     * @throws IllegalArgumentException if either {@code input}, {@code output} or {@code random} is {@code null}.
     */
    @JsonCreator
    public Config(
            @JsonProperty("input") final FileConfig input,
            @JsonProperty("output") final OutputConfig output,
            @JsonProperty("random") final GenerationConfig random,
            @JsonProperty("predefined") final GenerationConfig predefined) {
        if (input == null) {
            throw new IllegalArgumentException(String.format("%s: Missing input", getClass().getSimpleName()));
        }
        if (output == null) {
            throw new IllegalArgumentException(String.format("%s: Missing output", getClass().getSimpleName()));
        }
        if (random == null && predefined == null) {
            throw new IllegalArgumentException(String.format("%s: Missing random or predefined",
                    getClass().getSimpleName()));
        }
        this.input = input;
        this.output = output;
        this.random = random;
        this.predefined = predefined;
    }

    /**
     * <p>
     * Return the input file configuration.
     * </p>
     * @return the input file configuration.
     */
    public FileConfig getInput() {
        return input;
    }

    /**
     * <p>
     * Return the output file(s) configuration.
     * </p>
     * @return the output file(s) configuration.
     */
    public OutputConfig getOutput() {
        return output;
    }

    /**
     * <p>
     * Return the random generation and presentation configuration.
     * </p>
     * @return the random generation and presentation configuration.
     */
    public GenerationConfig getRandom() {
        return random;
    }

    /**
     * <p>
     * Return the predefined presentation configuration.
     * </p>
     * @return the predefined presentation configuration.
     */
    public GenerationConfig getPredefined() {
        return predefined;
    }

    /**
     * <p>
     * A factory method to create a configuration from a YAML file.
     * </p>
     * @param configFile the YAML file to read.
     * @return the parsed configuration.
     * @throws IOException if the reading of the file fails.
     */
    public static Config readYamlConfig(final File configFile) throws IOException {
        YAMLMapper mapper = new YAMLMapper();
        return mapper.readValue(configFile, Config.class);
    }

    /**
     * <p>
     * Return a {@link org.sw4j.tool.barcode.random.config.Config.Builder Builder} that can be used to build a config.
     * </p>
     * @return a {@link org.sw4j.tool.barcode.random.config.Config.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.Config Config} 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 input file configuration.
         * </p>
         */
        private FileConfig input;

        /**
         * <p>
         * The output file(s) configuration.
         * </p>
         */
        private OutputConfig output;

        /**
         * <p>
         * The random number generation and presentation configuration.
         * </p>
         */
        private GenerationConfig random;

        /**
         * <p>
         * The predefined presentation configuration.
         * </p>
         */
        private GenerationConfig predefined;

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

        /**
         * <p>
         * Set the input file configuration.
         * </p>
         * @param input the input file configuration.
         * @return the builder for a fluent interface.
         */
        public Builder setInput(final FileConfig input) {
            this.input = input;
            return this;
        }

        /**
         * <p>
         * Set the output file(s) configuration.
         * </p>
         * @param output the output file(s) configuration.
         * @return the builder for a fluent interface.
         */
        public Builder setOutput(final OutputConfig output) {
            this.output = output;
            return this;
        }

        /**
         * <p>
         * Set the random generation and presentation configuration.
         * </p>
         * @param random the random generation and presentation configuration.
         * @return the builder for a fluent interface.
         */
        public Builder setRandom(final GenerationConfig random) {
            this.random = random;
            return this;
        }

        /**
         * <p>
         * Build a new {@link org.sw4j.tool.barcode.random.config.Config Config} with the parameters set.
         * </p>
         * @return the new created {@link org.sw4j.tool.barcode.random.config.Config Config}.
         * @throws IllegalArgumentException if either {@code input}, {@code output} or either {@code random} or
         *  {@code predefined} is {@code null}.
         */
        public Config build() {
            return new Config(input, output, random, predefined);
        }

    }

}