<%- @schemas.each do |key, schema| -%>
<%= class_name(key) %>.java
package io.cucumber.messages.types;

import java.util.ArrayList;
import java.util.Objects;
import java.util.Optional;

import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;

/**
 * Represents the <%= class_name(key) %> message in Cucumber's message protocol
 * @see <a href=https://github.com/cucumber/messages>Github - Cucumber - Messages</a>
 <%- if not (schema['description'] || []).empty? -%>
 *
<%= format_description(schema['description'], indent_string: '') %>
<%- end -%>
 */
// Generated code
@SuppressWarnings("unused")
public final class <%= class_name(key) %> {
  <%- schema['properties'].each do |property_name, property| -%>
    private final <%= type_for(class_name(key), property_name, property) -%> <%= property_name %>;
  <%- end -%>
  <%- if (schema['required'] || []).empty? -%>
  <%- schema['properties'].each_with_index do |(property_name, property), index| -%>

    public static <%= class_name(key) %> of(<%= type_for(class_name(key), property_name, property) -%> <%= property_name %>) {
        return new <%= class_name(key) %>(
        <%- schema['properties'].each_with_index do |(property_name_2, property_2), index_2| -%>
          <%- if property_name_2 == property_name -%>
            <%- if property['items'] -%>
            unmodifiableList(new ArrayList<>(requireNonNull(<%= property_name %>, "<%= class_name(key) %>.<%= property_name %> cannot be null")))<%= index_2 < schema['properties'].length-1 ? ',' : '' %>
            <%- else -%>
            requireNonNull(<%= property_name %>, "<%= class_name(key) %>.<%= property_name %> cannot be null")<%= index_2 < schema['properties'].length-1 ? ',' : '' %>
            <%- end -%>
          <%- else -%>
            null<%= index_2 < schema['properties'].length-1 ? ',' : '' %>
          <%- end -%>
        <%- end -%>
        );
    }
  <%- end -%>
  <%- end -%>

    public <%= class_name(key) %>(
    <%- schema['properties'].each_with_index do |(property_name, property), index| -%>
        <%= type_for(class_name(key), property_name, property) -%> <%= property_name %><%= index < schema['properties'].length-1 ? ',' : ''%>
    <%- end -%>
    ) {
      <%- schema['properties'].each_with_index do |(property_name, property), index|
      required = (schema['required'] || []).index(property_name)
      -%>
      <%- if required -%>
       <%- if property['items'] -%>
        this.<%= property_name %> = unmodifiableList(new ArrayList<>(requireNonNull(<%= property_name %>, "<%= class_name(key) %>.<%= property_name %> cannot be null")));
       <%- else -%>
        this.<%= property_name %> = requireNonNull(<%= property_name %>, "<%= class_name(key) %>.<%= property_name %> cannot be null");
       <%- end -%>
      <%- else -%>
       <%- if property['items'] -%>
        this.<%= property_name %> = <%= property_name %> == null ? null : unmodifiableList(new ArrayList<>(<%= property_name %>));
       <%- else -%>
        this.<%= property_name %> = <%= property_name %>;
       <%- end -%>
      <%- end -%>
      <%- end -%>
    }
  <%- schema['properties'].each do |property_name, property| -%>
    <%- if (schema['required'] || []).index(property_name) -%>

    <%- if not (property['description'] || []).empty? -%>
    /**
    <%= format_description(property['description'], indent_string: '    ') %>
     */
    <%- end -%>
    public <%= type_for(class_name(key), property_name, property) -%> get<%= capitalize(property_name) %>() {
        return <%= property_name %>;
    }
    <%- else -%>

    <%- if not (property['description'] || []).empty? -%>
    /**
     <%= format_description(property['description'], indent_string: '    ') %>
     */
    <%- end -%>
    public Optional<<%= type_for(class_name(key), property_name, property) -%>> get<%= capitalize(property_name) %>() {
        return Optional.ofNullable(<%= property_name %>);
    }
    <%- end -%>
  <%- end -%>

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        <%= class_name(key) %> that = (<%= class_name(key) %>) o;
        return <%- schema['properties'].each_with_index do |(property_name, property), index| %>
            <%- if (schema['required'] || []).index(property_name) -%>
            <%= property_name -%>.equals(that.<%= property_name -%>)<%= index < schema['properties'].length-1 ? ' && ' : ';' -%>
            <%- else -%>
            Objects.equals(<%= property_name -%>, that.<%= property_name -%>)<%= index < schema['properties'].length-1 ? ' && ' : ';' -%>
            <%- end -%>
        <% end -%>

    }

    @Override
    public int hashCode() {
        return Objects.hash(
        <%- schema['properties'].each_with_index do |(property_name, property), index| -%>
            <%= property_name %><%= index < schema['properties'].length-1 ? ',' : ''%>
        <%- end -%>
        );
    }

    @Override
    public String toString() {
        return "<%= class_name(key) %>{" +
        <%- schema['properties'].each_with_index do |(property_name, property), index| -%>
            "<%= index == 0 ? '' : ', '%><%= property_name %>=" + <%= property_name %> +
        <%- end -%>
            '}';
    }
}
<% end -%>
