{%- macro enum_value(enum, field, index) -%}
{%- if field.value -%}
(int) ({{field.value|expression_to_text('i32')}})
{%- elif index == 0 -%}
0
{%- else -%}
{{enum.fields[index - 1]|name}} + 1
{%- endif -%}
{%- endmacro -%}

{%- macro enum_def(enum, top_level) -%}
public {{ 'static ' if not top_level }}final class {{enum|name}} {

{% for field in enum.fields %}
    public static final int {{field|name}} = {{enum_value(enum, field, loop.index0)}};
{% endfor %}

    private static final boolean IS_EXTENSIBLE = {% if enum.extensible %}true{% else %}false{% endif %};

    public static boolean isKnownValue(int value) {
{%- if enum.fields %}
        switch (value) {
{%-   for enum_field in enum.fields|groupby('numeric_value') %}
            case {{enum_field[0]}}:
{%-   endfor %}
                return true;
        }
{%- endif %}
        return false;
    }

    public static void validate(int value) {
        if (IS_EXTENSIBLE || isKnownValue(value))
            return;

        throw new DeserializationException("Invalid enum value.");
    }

    private {{enum|name}}() {}

}
{%- endmacro -%}
