/*
 * 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.ArrayList;
import java.util.Iterator;
import java.util.List;

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;
import blanco.ig.expander.implementor.Call;

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

    private TypeFactory _typeFactory = null;

    private BlancoDbSetting _setting = null;

    private String _query = "";

    private GenerationProperties _properties = null;

    public SelectAllMethod(Type rowObjectType, TableGateway gateway,
            String query) {
        super("selectAll", gateway);

        _rowObjectType = rowObjectType;
        _query = query;

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

    public void setupSignature() {
        setReturnType(new Type(List.class));
        addException(new Type(SQLException.class));

        if (_properties.isGenerateJavaDoc()) {
            getJavaDoc().addLine("テーブルの全ての行のリストで取得します。<br>");
            getJavaDoc().addLine(
                    "リストには " + getGateway().getClassName() + "クラスが格納されます。<br>");
            getJavaDoc().addLine("注意: 全てのデータが一旦メモリ上に展開されることに注意。");
            getJavaDoc()
                    .addReturn(
                            getGateway().getClassName()
                                    + "クラスのList。検索結果が0件の場合には空のリスト。");
        }
    }

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

        Value result = new Value(List.class, "result");
        implementor.declare(result, new Call(ArrayList.class));

        String simpleClassName = "Simple" + getGateway().getClassName()
                + "SelectAllIterator";
        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 rowClassName = "Simple" + getGateway().getClassName()
                + "SelectAllRow";
        implementor.addUsingType(new Type(_setting.getRootNameSpace() + ".row."
                + rowClassName));
        implementor.addStatement(rowClassName + " work = new " + rowClassName
                + "()");

        implementor.addLine("while(iterator.next()) {");
        implementor.addStatement("work = iterator.getRow()");

        implementor.addStatement(_rowObjectType.getName() + " row = new "
                + _rowObjectType.getName() + "()");

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

        implementor.addLine("}");

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

        implementor.addReturn(result);
    }
}