private String copyMethodBody()

in codegen/src/main/java/software/amazon/awssdk/codegen/poet/model/MemberCopierSpec.java [218:341]


    private String copyMethodBody(CodeBlock.Builder code, BuilderTransform builderTransform, UniqueVariableSource variableSource,
                                  EnumTransform enumTransform, String inputVariableName, MemberModel inputMember) {
        if (inputMember.getEnumType() != null) {
            String outputVariableName = variableSource.getNew("result");
            ClassName enumType = poetExtensions.getModelClass(inputMember.getEnumType());
            switch (enumTransform) {
                case NONE:
                    return inputVariableName;
                case ENUM_TO_STRING:
                    code.add("$T $N = $N.toString();", String.class, outputVariableName, inputVariableName);
                    return outputVariableName;
                case STRING_TO_ENUM:
                    code.add("$1T $2N = $1T.fromValue($3N);", enumType, outputVariableName, inputVariableName);
                    return outputVariableName;
                default:
                    throw new IllegalStateException();
            }
        }

        if (inputMember.isSimple()) {
            return inputVariableName;
        }

        if (inputMember.hasBuilder()) {
            switch (builderTransform) {
                case NONE:
                    return inputVariableName;
                case BUILDER_TO_BUILDABLE:
                    String buildableOutput = variableSource.getNew("member");
                    TypeName buildableOutputType = typeName(inputMember, false, false, builderTransform, enumTransform);
                    code.add("$T $N = $N == null ? null : $N.build();", buildableOutputType, buildableOutput, inputVariableName,
                             inputVariableName);
                    return buildableOutput;
                case BUILDABLE_TO_BUILDER:
                    String builderOutput = variableSource.getNew("member");
                    TypeName builderOutputType = typeName(inputMember, false, false, builderTransform, enumTransform);
                    code.add("$T $N = $N == null ? null : $N.toBuilder();", builderOutputType, builderOutput, inputVariableName,
                             inputVariableName);
                    return builderOutput;
                default:
                    throw new IllegalStateException();
            }
        }

        if (inputMember.isList()) {
            String outputVariableName = variableSource.getNew("list");
            String modifiableVariableName = variableSource.getNew("modifiableList");

            MemberModel listEntryModel = inputMember.getListModel().getListMemberModel();
            TypeName listType = typeName(inputMember, false, false, builderTransform, enumTransform);

            code.add("$T $N;", listType, outputVariableName)
                .add("if ($1N == null || $1N instanceof $2T) {", inputVariableName, SdkAutoConstructList.class)
                .add("$N = $T.getInstance();", outputVariableName, DefaultSdkAutoConstructList.class)
                .add("} else {");


            String entryInputVariable = variableSource.getNew("entry");

            // Short-circuit, if the member is simple then we can directly use the constructor
            // that takes a collection which should have a better performance characteristics.
            boolean isMemberSimple = listEntryModel.isSimple() && listEntryModel.getEnumType() == null;
            if (isMemberSimple) {
                code.add("$T $N = new $T<>($N);", listType, modifiableVariableName, ArrayList.class, inputVariableName);
            } else {
                code.add("$T $N = new $T<>($N.size());", listType, modifiableVariableName, ArrayList.class, inputVariableName);
                code.add("$N.forEach($N -> {", inputVariableName, entryInputVariable);

                String entryOutputVariable =
                    copyMethodBody(code, builderTransform, variableSource, enumTransform, entryInputVariable, listEntryModel);

                code.add("$N.add($N);", modifiableVariableName, entryOutputVariable)
                    .add("});");
            }
            code.add("$N = $T.unmodifiableList($N);", outputVariableName, Collections.class, modifiableVariableName)
                .add("}");

            return outputVariableName;
        }

        if (inputMember.isMap()) {
            String outputVariableName = variableSource.getNew("map");
            String modifiableVariableName = variableSource.getNew("modifiableMap");

            MemberModel keyModel = inputMember.getMapModel().getKeyModel();
            MemberModel valueModel = inputMember.getMapModel().getValueModel();
            TypeName keyType = typeName(keyModel, false, false, builderTransform, enumTransform);
            TypeName outputMapType = typeName(inputMember, false, false, builderTransform, enumTransform);

            code.add("$T $N;", outputMapType, outputVariableName)
                .add("if ($1N == null || $1N instanceof $2T) {", inputVariableName, SdkAutoConstructMap.class)
                .add("$N = $T.getInstance();", outputVariableName, DefaultSdkAutoConstructMap.class)
                .add("} else {")
                .add("$T $N = new $T<>($N.size());",
                     outputMapType, modifiableVariableName, LinkedHashMap.class, inputVariableName);

            String keyInputVariable = variableSource.getNew("key");
            String valueInputVariable = variableSource.getNew("value");
            code.add("$N.forEach(($N, $N) -> {", inputVariableName, keyInputVariable, valueInputVariable);

            String keyOutputVariable =
                copyMethodBody(code, builderTransform, variableSource, enumTransform, keyInputVariable, keyModel);

            String valueOutputVariable =
                copyMethodBody(code, builderTransform, variableSource, enumTransform, valueInputVariable, valueModel);

            if (keyModel.getEnumType() != null && !keyType.toString().equals("java.lang.String")) {
                // When enums are used as keys, drop any entries with unknown keys
                code.add("if ($N != $T.UNKNOWN_TO_SDK_VERSION) {", keyOutputVariable, keyType)
                    .add("$N.put($N, $N);", modifiableVariableName, keyOutputVariable, valueOutputVariable)
                    .add("}");
            } else {
                code.add("$N.put($N, $N);", modifiableVariableName, keyOutputVariable, valueOutputVariable);
            }

            code.add("});")
                .add("$N = $T.unmodifiableMap($N);", outputVariableName, Collections.class, modifiableVariableName)
                .add("}");

            return outputVariableName;
        }

        throw new UnsupportedOperationException("Unable to generate copier for member '" + inputMember + "'");
    }