001package com.github.dkfellows.notabuilder;
002
003/**
004 * A record that has four fields.
005 * @param foo The foo field.
006 * @param bar The bar field.
007 * @param grill The grill field.
008 * @param quux The quux field.
009 */
010public record ThingRecord(int foo, int bar, double grill, String quux) {
011    /**
012     * Make an instance of the record.
013     * @param args The labelled non-default arguments to pass.
014     * @see ThingRecord.Args#foo(int)
015     * @see ThingRecord.Args#bar(int)
016     * @see ThingRecord.Args#grill(double)
017     * @see ThingRecord.Args#quux(String)
018     */
019    public ThingRecord(Args... args) {
020        // Defaults
021        var foo = 0;
022        var bar = 0;
023        var grill = 0.0;
024        var quux = "";
025
026        // Extract the args by pattern matching
027        for (var arg: args) {
028            switch (arg) {
029            case Foo(var val) -> foo = val;
030            case Bar(var val) -> bar = val;
031            case Grill(var val) -> grill = val;
032            case Quux(var val) -> quux = val;
033            }
034        }
035
036        // Pass to the primary, auto-generated constructor
037        this(foo, bar, grill, quux);
038    }
039
040    /** @deprecated Use the other constructor instead. */
041    @Deprecated(since = "0.1")
042    public ThingRecord {}
043
044    /** Argument labeller. */
045    public sealed interface Args permits Foo, Bar, Grill, Quux {
046        /**
047         * Label a value as a {@link ThingRecord#foo()}.
048         * @param value The value to label.
049         * @return The labelled value.
050         */
051        public static Args foo(int value) {
052            return new Foo(value);
053        }
054
055        /**
056         * Label a value as a {@link ThingRecord#bar()}.
057         * @param value The value to label.
058         * @return The labelled value.
059         */
060        public static Args bar(int value) {
061            return new Bar(value);
062        }
063
064        /**
065         * Label a value as a {@link ThingRecord#grill()}.
066         * @param value The value to label.
067         * @return The labelled value.
068         */
069        public static Args grill(double value) {
070            return new Grill(value);
071        }
072
073        /**
074         * Label a value as a {@link ThingRecord#quux()}.
075         * @param value The value to label.
076         * @return The labelled value.
077         */
078        public static Args quux(String value) {
079            return new Quux(value);
080        }
081    }
082
083    private record Foo(int foo) implements Args {}
084    private record Bar(int bar) implements Args {}
085    private record Grill(double grill) implements Args {}
086    private record Quux(String quux) implements Args {}
087}