/*
 * blancoDb
 * Copyright (C) 2004-2005 Yasuo Nakanishi
 * 
 * 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.table.gateway;

import java.sql.SQLException;
import java.util.Iterator;

import blanco.db.conf.BlancoDbSetting;
import blanco.db.definition.TableField;
import blanco.db.definition.TableGateway;
import blanco.db.expander.implementor.BlancoDbImplementor;
import blanco.db.generator.TypeFactory;
import blanco.db.properties.GenerationProperties;
import blanco.db.util.BlancoDbObjectStorage;
import blanco.ig.expander.NameAdjuster;
import blanco.ig.expander.Type;
import blanco.ig.expander.Value;

/**
 * @author Yasuo Nakanishi
 */
public class SelectMethod extends TableGatewayMethod {
    private Type _rowObjectType = null;

    private TypeFactory _typeFactory = null;

    private BlancoDbSetting _setting = null;

    private String _query = "";

    private GenerationProperties _properties = null;

    public SelectMethod(Type rowObjectType, TableGateway gateway, String query) {
        super("select", gateway);

        _rowObjectType = rowObjectType;
        _query = query;

        BlancoDbObjectStorage storage = BlancoDbObjectStorage.getInstance();
        _setting = storage.getSetting();
        _typeFactory = storage.getTypeFactory();
        _properties = storage.getGenerationProperties();
    }

    public void setupSignature() {
        setReturnType(_rowObjectType);

        TableField field = null;
        Iterator i = getGateway().getPrimaryKeyFieldIterator();
        while (i.hasNext()) {
            field = (TableField) i.next();
            addArgument(createPrimaryKeyArgument(field));
        }

        addException(new Type(SQLException.class));

        if (_properties.isGenerateJavaDoc()) {
            getJavaDoc().addLine("キーとなる列の値を使って行を取得します。");

            i = getGateway().getPrimaryKeyFieldIterator();
            boolean isFirst = true;
            while (i.hasNext()) {
                if (isFirst) {
                    isFirst = false;
                    //getJavaDoc().addLine("");
                }
                field = (TableField) i.next();
                String name = field.getName();
                getJavaDoc().addParameter(getNameAdjuster().toValueName(name),
                        "'" + name + "'列の値");
            }

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

    public void implement() {
        NameAdjuster adjuster = new NameAdjuster();
        BlancoDbImplementor implementor = getImplementor();

        Value result = new Value(_rowObjectType, "result");
        implementor.declareByDefault(result);

        String simpleClassName = "Simple" + getGateway().getClassName()
                + "SelectIterator";
        implementor.addUsingType(new Type(_setting.getRootNameSpace()
                + ".query." + simpleClassName));
        implementor.addStatement(simpleClassName + " iterator = new "
                + simpleClassName + "(_connection)");
        implementor.openTry();

        TableField field = null;
        Iterator i = getGateway().getPrimaryKeyFieldIterator();
        String strInputParameter = "";
        while (i.hasNext()) {
            field = (TableField) i.next();
            if (field.getTypeName().equals("InputStream")
                    || field.getTypeName().equals("Reader")) {
                continue;
            }
            if (field.isPrimaryKey()) {
                if (strInputParameter.length() > 0) {
                    strInputParameter += ", ";
                }
                strInputParameter += adjuster.toValueName(field.getName());
            }
        }

        String rowClassName = "Simple" + getGateway().getClassName()
                + "SelectRow";
        implementor.addUsingType(new Type(_setting.getRootNameSpace() + ".row."
                + rowClassName));
        implementor.addStatement(rowClassName + " work = new " + rowClassName
                + "()");

        implementor.addStatement("iterator.setInputParameter("
                + strInputParameter + ")");
        implementor.addStatement("work = iterator.getSingleRow()");

        i = getGateway().getFieldIterator();
        while (i.hasNext()) {
            field = (TableField) i.next();
            if (field.getTypeName().equals("InputStream")
                    || field.getTypeName().equals("Reader")) {
                continue;
            }
            implementor.addStatement("result.set"
                    + adjuster.toClassName(field.getName()) + "(work.get"
                    + adjuster.toClassName(field.getName()) + "())");
        }

        implementor.addFinally();
        implementor.addStatement("iterator.close()");
        implementor.closeTry();

        implementor.addLine("return result;");
    }
}