001package com.github.dkfellows.notabuilder;
002
003/**
004 * A class that has four fields: foo, bar, grill and quux.
005 */
006public class ThingClass {
007    private final int foo;
008    private final int bar;
009    private final double grill;
010    private final String quux;
011
012    /**
013     * Make an instance of the class. 
014     * @param args The labelled non-default arguments to pass.
015     * @see ThingClass.Args#foo(int)
016     * @see ThingClass.Args#bar(int)
017     * @see ThingClass.Args#grill(double)
018     * @see ThingClass.Args#quux(String)
019     */
020    public ThingClass(Args... args) {
021        // Defaults
022        var foo = 0;
023        var bar = 0;
024        var grill = 0.0;
025        var quux = "";
026
027        // Extract the args
028        for (var arg: args) {
029            switch (arg) {
030            case Foo f -> foo = f.foo();
031            case Bar b -> bar = b.bar();
032            case Grill g -> grill = g.grill();
033            case Quux q -> quux = q.quux();
034            }
035        }
036
037        // Assign the fields (once, because final)
038        this.foo = foo;
039        this.bar = bar;
040        this.grill = grill;
041        this.quux = quux;
042    }
043
044    /** Get the foo.
045     * @return The foo value. */
046    public int getFoo() { return foo; }
047    /** Get the bar.
048     * @return The bar value. */
049    public int getBar() { return bar; }
050    /** Get the grill.
051     * @return The grill value. */
052    public double getGrill() { return grill; }
053    /** Get the quux.
054     * @return The quux value. */
055    public String getQuux() { return quux; }
056    /** @return The string rendering of the object. */
057    @Override
058    public String toString() {
059        return String.format("[foo=%s,bar=%s,grill=%s,quux=%s]", foo, bar, grill, quux);
060    }
061
062    /** Argument labeller. */
063    public sealed interface Args permits Foo, Bar, Grill, Quux {
064        /**
065         * Label a value as a {@link ThingClass#getFoo() foo}.
066         * @param value The value to label.
067         * @return The labelled value.
068         */
069        public static Args foo(int value) {
070            return new Foo(value);
071        }
072        /**
073         * Label a value as a {@link ThingClass#getBar() bar}.
074         * @param value The value to label.
075         * @return The labelled value.
076         */
077        public static Args bar(int value) {
078            return new Bar(value);
079        }
080        /**
081         * Label a value as a {@link ThingClass#getGrill() grill}.
082         * @param value The value to label.
083         * @return The labelled value.
084         */
085        public static Args grill(double value) {
086            return new Grill(value);
087        }
088        /**
089         * Label a value as a {@link ThingClass#getQuux() quux}.
090         * @param value The value to label.
091         * @return The labelled value.
092         */
093        public static Args quux(String value) {
094            return new Quux(value);
095        }
096    }
097
098    private record Foo(int foo) implements Args {}
099    private record Bar(int bar) implements Args {}
100    private record Grill(double grill) implements Args {}
101    private record Quux(String quux) implements Args {}
102}