ConverterColumnNative.java

/*
 * SPDX-FileCopyrightText: 2025 kaumei.io
 * SPDX-License-Identifier: Apache-2.0
 */
package io.kaumei.jdbc.anno.jdbc2java;

import com.palantir.javapoet.CodeBlock;
import io.kaumei.jdbc.anno.gen.TargetMethod;
import io.kaumei.jdbc.anno.model.OptionalFlag;
import io.kaumei.jdbc.anno.model.SQLNameDV;
import io.kaumei.jdbc.anno.store.SourceDV;
import org.jspecify.annotations.Nullable;

import javax.lang.model.type.TypeMirror;
import java.sql.ResultSet;
import java.util.Optional;

import static java.util.Objects.requireNonNull;

final class ConverterColumnNative extends Jdbc2JavaConverter {

    private final @Nullable Class<?> cls;
    private final String methodName;
    private final boolean isPrimitive;

    ConverterColumnNative(TypeMirror type, SourceDV source, Class<?> cls, String methodName) {
        super(type, source);
        this.cls = cls == ResultSet.class ? null : cls;
        this.methodName = requireNonNull(methodName);
        this.isPrimitive = this.type().getKind().isPrimitive();
    }

    // ------------------------------------------------------------------------

    @Override
    public boolean isColumn() {
        return true;
    }

    @Override
    public CodeBlock nullCheck(String varName) {
        return this.isPrimitive
                ? CodeBlock.of("rs.wasNull()")
                : CodeBlock.of("($L == null || rs.wasNull())", varName);
    }

    @Override
    public void addColumnByIndex(TargetMethod builder, String localVarName, ColumnIndex index, OptionalFlag optional) {
        builder.addComment("ConverterColumnNative.addColumnByIndex", "type", type(), "optional", optional);
        if (cls == null) {
            setLocalVar(builder, localVarName, optional, CodeBlock.of("rs.$N($L)", methodName, index.columnIndexVar()));
        } else {
            setLocalVar(builder, localVarName, optional, CodeBlock.of("$T.$N(rs, $L)", cls, methodName, index.columnIndexVar()));
        }
        if (optional.isNonNull()) {
            builder.beginControlFlow("if($L)", nullCheck(localVarName));
            builder.addThrowColumnWasNull(index);
            builder.endControlFlow();
        }
    }

    @Override
    public void addColumnByName(TargetMethod builder, String localVarName, SQLNameDV columnName, OptionalFlag optional) {
        builder.addComment("ConverterColumnNative.addColumnByName", "type", type(), "optional", optional);
        if (cls == null) {
            setLocalVar(builder, localVarName, optional, CodeBlock.of("rs.$N($S)", methodName, columnName.value()));
        } else {
            setLocalVar(builder, localVarName, optional, CodeBlock.of("$T.$N(rs, $S)", cls, methodName, columnName.value()));
        }
        if (optional.isNonNull()) {
            builder.beginControlFlow("if($L)", nullCheck(localVarName));
            builder.addStatement("throw new $T($S)", NullPointerException.class, "JDBC column was null on name: " + columnName.value());
            builder.endControlFlow();
        }
    }

    private void setLocalVar(TargetMethod builder, String localVarName, OptionalFlag optional, CodeBlock code) {
        if (optional.isOptionalType()) {
            builder.addStatement("var $L = $T.ofNullable($L)", localVarName, Optional.class, code);
        } else {
            builder.addStatement("var $L = $L", localVarName, code);
        }
    }
}