fn output_struct_or_variant_container()

in serde-generate/src/java.rs [600:767]


    fn output_struct_or_variant_container(
        &mut self,
        variant_base: Option<&str>,
        variant_index: Option<u32>,
        name: &str,
        fields: &[Named<Format>],
    ) -> Result<()> {
        // Beginning of class
        writeln!(self.out)?;
        if let Some(base) = variant_base {
            self.output_comment(name)?;
            writeln!(
                self.out,
                "public static final class {} extends {} {{",
                name, base
            )?;
        } else {
            self.output_comment(name)?;
            writeln!(self.out, "public final class {} {{", name)?;
        }
        let reserved_names = &["Builder"];
        self.enter_class(name, reserved_names);
        // Fields
        for field in fields {
            self.output_comment(&field.name)?;
            writeln!(
                self.out,
                "public final {} {};",
                self.quote_type(&field.value),
                field.name
            )?;
        }
        if !fields.is_empty() {
            writeln!(self.out)?;
        }
        // Constructor.
        writeln!(
            self.out,
            "public {}({}) {{",
            name,
            fields
                .iter()
                .map(|f| format!("{} {}", self.quote_type(&f.value), &f.name))
                .collect::<Vec<_>>()
                .join(", ")
        )?;
        self.out.indent();
        for field in fields {
            writeln!(
                self.out,
                "java.util.Objects.requireNonNull({0}, \"{0} must not be null\");",
                &field.name
            )?;
        }
        for field in fields {
            writeln!(self.out, "this.{} = {};", &field.name, &field.name)?;
        }
        self.out.unindent();
        writeln!(self.out, "}}")?;
        // Serialize
        if self.generator.config.serialization {
            writeln!(
                self.out,
                "\npublic void serialize(com.novi.serde.Serializer serializer) throws com.novi.serde.SerializationError {{",
            )?;
            self.out.indent();
            writeln!(self.out, "serializer.increase_container_depth();")?;
            if let Some(index) = variant_index {
                writeln!(self.out, "serializer.serialize_variant_index({});", index)?;
            }
            for field in fields {
                writeln!(
                    self.out,
                    "{}",
                    self.quote_serialize_value(&field.name, &field.value)
                )?;
            }
            writeln!(self.out, "serializer.decrease_container_depth();")?;
            self.out.unindent();
            writeln!(self.out, "}}")?;

            if variant_index.is_none() {
                for encoding in &self.generator.config.encodings {
                    self.output_class_serialize_for_encoding(*encoding)?;
                }
            }
        }
        // Deserialize (struct) or Load (variant)
        if self.generator.config.serialization {
            if variant_index.is_none() {
                writeln!(
                    self.out,
                    "\npublic static {} deserialize(com.novi.serde.Deserializer deserializer) throws com.novi.serde.DeserializationError {{",
                    name,
                )?;
            } else {
                writeln!(
                    self.out,
                    "\nstatic {} load(com.novi.serde.Deserializer deserializer) throws com.novi.serde.DeserializationError {{",
                    name,
                )?;
            }
            self.out.indent();
            writeln!(self.out, "deserializer.increase_container_depth();")?;
            writeln!(self.out, "Builder builder = new Builder();")?;
            for field in fields {
                writeln!(
                    self.out,
                    "builder.{} = {};",
                    field.name,
                    self.quote_deserialize(&field.value)
                )?;
            }
            writeln!(self.out, "deserializer.decrease_container_depth();")?;
            writeln!(self.out, "return builder.build();")?;
            self.out.unindent();
            writeln!(self.out, "}}")?;

            if variant_index.is_none() {
                for encoding in &self.generator.config.encodings {
                    self.output_class_deserialize_for_encoding(name, *encoding)?;
                }
            }
        }
        // Equality
        write!(self.out, "\npublic boolean equals(Object obj) {{")?;
        self.out.indent();
        writeln!(
            self.out,
            r#"
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
{0} other = ({0}) obj;"#,
            name,
        )?;
        for field in fields {
            writeln!(
                self.out,
                "if (!java.util.Objects.equals(this.{0}, other.{0})) {{ return false; }}",
                &field.name,
            )?;
        }
        writeln!(self.out, "return true;")?;
        self.out.unindent();
        writeln!(self.out, "}}")?;
        // Hashing
        writeln!(self.out, "\npublic int hashCode() {{")?;
        self.out.indent();
        writeln!(self.out, "int value = 7;",)?;
        for field in fields {
            writeln!(
                self.out,
                "value = 31 * value + (this.{0} != null ? this.{0}.hashCode() : 0);",
                &field.name
            )?;
        }
        writeln!(self.out, "return value;")?;
        self.out.unindent();
        writeln!(self.out, "}}")?;
        // Builder
        self.output_struct_or_variant_container_builder(name, fields)?;
        // Custom code
        self.output_custom_code()?;
        // End of class
        self.leave_class(reserved_names);
        writeln!(self.out, "}}")
    }