fun build()

in smithy-crt/src/main/kotlin/software/amazon/smithy/crt/java/JavaElements.kt [492:589]


    fun build() : Builder<T> {
        if (client.superclass != null && client.superclass!!.packageName() != "java.lang") {
            builderInterface.addInterface(Interface(client.superclass!!.nestedClass("Builder")))
            builderImpl.superclass(client.superclass!!.nestedClass("BuilderImpl"))
        }

        builderImpl.addDefaultConstructor().addModifier(Modifier.PROTECTED)

        // private $Client(BuilderImpl builder)
        client.addConstructor(Constructor(client.className, Field("builder", builderImpl.className))
            .addModifier(Modifier.PROTECTED)
            .java { builder ->
                if (client.superclass != null && client.superclass!!.packageName() != "java.lang") {
                    builder.addStatement("super(builder)")
                }
                client.members.values.forEach { member ->
                    builder.addStatement("this.${'$'}L = builder.${'$'}L",
                        StringUtils.uncapitalize(member.name), StringUtils.uncapitalize(member.name))
                }
            }
        )

        // public Builder toBuilder()
        val toBuilder = Method("toBuilder", builderInterface.className)
            .addModifier(Modifier.PUBLIC)
            .java { builder ->
                builder.addStatement("return new ${'$'}T(this)", builderImpl.className)
            }
        if (client.superclass != null && client.superclass!!.packageName() != "java.lang") {
            toBuilder.addAnnotation(Annotation(ClassName.get(Override::class.javaObjectType)))
        }
        client.addMethod(toBuilder)

        // public static Builder builder()
        client.addMethod(Method("builder", builderInterface.className)
            .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
            .java { builder ->
                builder.addStatement("return new ${'$'}T()", builderImpl.className)
            }
        )

        // public Builder $member(T $member)
        client.members.values.forEach { member ->
            builderInterface.addMethod(
                Method(
                    StringUtils.uncapitalize(member.name),
                    builderInterface.className,
                    Field(StringUtils.uncapitalize(member.name), member.typeName)
                ).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
            )
        }


        builderInterface.addMethod(
                Method(
                        "build",
                        client.className
                ).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
            )
        
        builderImpl
            .addConstructor(Constructor(client.className, Field("model", client.className))
                .addModifier(Modifier.PRIVATE)
                .java { builder ->
                    client.members.values.forEach { member ->
                        builder.addStatement("${'$'}L(model.${'$'}L)",
                            StringUtils.uncapitalize(member.name), StringUtils.uncapitalize(member.name))
                    }
                }
            )
            .addMethod(Method("build", client.className)
                .addModifier(Modifier.PUBLIC)
                .java { builder ->
                    builder.addStatement("return new ${'$'}T(this)", client.className)
                }
            )
        client.members.values.forEach { member ->
            builderImpl.addMethod(
                Method(
                    StringUtils.uncapitalize(member.name),
                    builderInterface.className,
                    Field(StringUtils.uncapitalize(member.name), member.typeName)
                ).addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                    .java {
                        it.addStatement("this.${'$'}L = ${'$'}L",
                            StringUtils.uncapitalize(member.name), StringUtils.uncapitalize(member.name))
                        it.addStatement("return this")
                    }
            )
            builderImpl.addMember(member)
        }

        val builder = client.java() as TypeSpec.Builder
        builder.addType(builderInterface.build().java().build())
        builder.addType(builderImpl.build().java().build())

        return this
    }