package {{ doc.package }};

{% if cls -%}
{% for f in cls.all_fields -%}
{% if f.range.startswith('BigDecimal') %}
import java.math.BigDecimal;{% endif -%}
{% if f.range.startswith('Instant') %}
import java.time.Instant;{% endif -%}
{% if f.range.startswith('LocalDate') %}
import java.time.LocalDate;{% endif -%}
{% if f.range.startswith('ZonedDateTime') %}
import java.time.ZonedDateTime;{% endif -%}
{% if f.range.startswith('List') %}
import java.util.List;{% endif -%}
{%- endfor %}
{% if not cls.mixin -%}
import java.util.Objects;{%- endif %}

{% if cls.description -%}
/**
 * {{ cls.description }}
 */{% endif %}
{% if cls.mixin -%}
public interface {{ cls.name }} {
{% for f in cls.all_fields %}
    public {{f.range}} {{ f.name }}();

{%- endfor %}
}
{% else -%}
public record {{ cls.name }}({% for f in cls.all_fields -%}
    {{f.range}} {{ f.name }}{{ ", " if not loop.last else "" }}
{%- endfor %}){{ " implements" if cls.mixins else "" }} {% for f in cls.mixins -%}
    {{ f }}{{ ", " if not loop.last else "" }}
{%- endfor %} {

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
{% for f in cls.all_fields %}
        private {{ f.range }} {{ f.name }} = {{ f.default_value }};
{%- endfor %}
{% for f in cls.all_fields %}

        public Builder {{ f.name }}({{ f.range }} {{ f.name }}) {
            this.{{ f.name }} = Objects.requireNonNull({{ f.name }});
            return this;
        }
{%- endfor %}

    public {{ cls.name }} build() {
            return new {{ cls.name }}(
               {%- for f in cls.all_fields -%}
               {{ f.name }}{{ ", " if not loop.last else "" }}
               {%- endfor -%}
            );
        }
    }
}
{% endif -%}
{% elif enum -%}

import java.util.Map;
import java.util.HashMap;
import java.util.Collections;

import com.fasterxml.jackson.annotation.JsonCreator;

{% if enum.description %}/**
 * {{ enum.description }}
 */
{% endif -%}
public enum {{ enum.name }} {
{%- for value in enum.values[0:-1] %}
{% if value.description %}
  /**
   * {{ value.description }}
   */
{%- endif %}
  {{ value.label|upper }}("{{ value.text }}"),
{%- endfor %}
{%- if enum.values %}
{% if enum.values[-1].description %}
  /**
   * {{ enum.values[-1].description }}
   */
{%- endif %}
  {{ enum.values[-1].label|upper }}("{{ enum.values[-1].text }}");
  {%- else %}
  ;{% endif %}

  private final static Map<String, {{ enum.name }}> MAP;

  static {
    Map<String, {{ enum.name }}> map = new HashMap<String, {{ enum.name }}>();
    for ( {{ enum.name }} value : {{ enum.name }}.values() ) {
      map.put(value.toString(), value);
    }

    MAP = Collections.unmodifiableMap(map);
  }

  private final String repr;

  {{ enum.name }}(String repr) {
    this.repr = repr;
  }

  @Override
  public String toString() {
    return repr;
  }

  @JsonCreator
  public static {{ enum.name }} fromString(String v) {
    return MAP.get(v);
  }
}
{% endif -%}
