/*
 * blancoDb Enterprise Edition
 * Copyright (C) 2004-2005 Tosiki Iga
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 */
package blanco.db.expander.query.iterator;

import java.util.Iterator;

import blanco.commons.util.BlancoNameAdjuster;
import blanco.db.definition.QueryField;
import blanco.db.definition.QueryIterator;
import blanco.db.mapping.BlancoDbMappingUtil;
import blanco.db.util.BlancoDbObjectStorage;
import blanco.ig.expander.Scope;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;
import blanco.ig.expander.implementor.Call;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.method.MethodExpander;

/**
 * @author Tosiki Iga
 */
public class GetRowMethod extends MethodExpander {
    private BlancoDbObjectStorage storage = null;

    private QueryIterator _iterator = null;

    private Value _result = null;

    public GetRowMethod(final BlancoDbObjectStorage storage,
            final Type rowObjectType, final QueryIterator iterator) {
        super("getRow");
        this.storage = storage;
        this._iterator = iterator;

        _result = new Value(rowObjectType, "result");
    }

    /**
     * シングル属性が有効である場合には protectedとします。
     */
    protected Scope getScope() {
        if (_iterator.isSingle()) {
            return Scope.PROTECTED;
        } else {
            return Scope.PUBLIC;
        }
    }

    public void setupSignature() {
        setReturnType(_result.getType());

        getJavaDoc().addException(new Type("java.sql.SQLException"),
                "SQL例外が発生した場合。");
        addException(new Type("java.sql.SQLException"));

        getJavaDoc().addLine("現在の行のデータをオブジェクトとして取得します。");
        getJavaDoc().addLine("");

        if (_iterator.isSingle()) {
            getJavaDoc().addLine("シングル属性が有効なのでスコープをprotectedとします。<br>");
            getJavaDoc().addLine("このメソッドの代わりに getSingleRowメソッドを利用してください。<br>");
        } else {
            getJavaDoc().addLine(
                    "このメソッドを呼び出す前に、next()などのカーソルを操作するメソッドを呼び出す必要があります。");
        }

        getJavaDoc().addReturn("行オブジェクト。");
    }

    public void implement() {
        final Implementor implementor = new Implementor(getData());

        if (storage.getSetting().isLogging()) {
            implementor.addLine("if (fLog.isDebugEnabled()) {");
            implementor.addLine("fLog.debug(\"" + getName() + "\");");
            implementor.addLine("}");
            implementor.addLine("");
        }

        implementor.declare(_result, new Call(_result.getType()));
        final Iterator fieldIterator = _iterator.getFieldIterator();
        QueryField field = null;

        int indexCol = 1;
        while (fieldIterator.hasNext()) {
            field = (QueryField) fieldIterator.next();

            implementor.addStatement("result.set"
                    + BlancoNameAdjuster.toClassName(field.getName())
                    + "("
                    + BlancoDbMappingUtil.mapWrapperClassForPrimitive(
                            "fResultSet."
                                    + BlancoDbMappingUtil
                                            .getResultSetGetterMethodName(field
                                                    .getTypeName()) + "("
                                    + indexCol + ")", field.getTypeName())
                    + ")");

            if (field.getObjectMappingForPrimitiveNullSupport()) {
                implementor.openIf("fResultSet.wasNull()");
                implementor.addStatement("result.set"
                        + BlancoNameAdjuster.toClassName(field.getName())
                        + "(null)");
                implementor.closeIf();
            }
            indexCol++;
        }

        implementor.emptyLine();

        implementor.addReturn(_result);
    }
}