/*
 * 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.implementor;

import java.util.Iterator;

import blanco.ig.expander.Type;
import blanco.ig.expander.Value;
import blanco.ig.expander.implementor.Call;
import blanco.ig.expander.implementor.ImplementData;
import blanco.ig.expander.implementor.Implementor;
import blanco.ig.expander.implementor.Receiver;
import blanco.ig.expander.implementor.Statement;
import blanco.ig.expander.implementor.StringLiteral;

/**
 * @author Yasuo Nakanishi
 */
public class BlancoDbImplementor extends Implementor {

    public BlancoDbImplementor(ImplementData data) {
        super(data);
    }

    public void close(Value target) {
        Statement s = new Statement(target);
        s.join("!=", new Statement(Value.NULL));
        openIf(s);

        Receiver r = new Receiver(target);
        r.call("close");
        addStatement(r);
        assign(target, new Statement(Value.NULL));
        closeIf();
    }

    public void throwIntegrityConstraintException(Value sqlException,
            Type exceptionType) {

        Call c = new Call("BlancoDbUtil.isIntegrityConstraintException");
        c.addArgument(sqlException);
        openIf(c);

        c = new Call("BlancoDbUtil.throwIntegrityConstraintException");
        c.addArgument(sqlException);
        addStatement(c);

        closeIf();
        addThrow(sqlException);
    }

    public void checkSingleRowUpdated(Value result, Type noModifiedType,
            Type tooMenyType) {
        Statement s = new Statement(result);
        s.join("==", new Statement(int.class, "0"));
        openIf(s);

        Call c = new Call(noModifiedType);
        c.addArgument(new StringLiteral("行が一件も変更されませんでした。"));
        addThrow(c);

        s = new Statement(result);
        s.join(">", new Statement(int.class, "1"));
        addElseIf(s);

        Value message = new Value(String.class, "message");
        s = new StringLiteral("一件を超える行が変更されてしまいました。影響のあった件数:");
        s.join("+", new Statement(result));
        declare(message, s);

        c = new Call(tooMenyType);
        c.addArgument(message);
        addThrow(c);

        closeIf();
    }

    public void closeResultSetAndStatement(Value resultSet, Value satement) {
        Statement expression = new Statement(resultSet);
        expression.join("!=", new Statement(Value.NULL));
        openTry();
        openIf(expression);
        addStatement(new Receiver(resultSet, "close"));
        assign(resultSet, new Statement(Value.NULL));
        closeIf();

        addFinally();
        close(satement);
        closeTry();
    }

    public void checkRowNotFound(Value resultSet, Type exceptionType) {
        openIf("next() == false");
        Call c = new Call(exceptionType);
        c.addArgument(new StringLiteral("行が検索できませんでした。"));
        addThrow(c);
        closeIf();
    }

    public void checkTooManyRowsFound(Value resultSet, Type exeptionType) {
        openIf("next()");
        Call c = new Call(exeptionType);
        c.addArgument(new StringLiteral("1件以上の行が検索されました。"));
        addThrow(c);
        closeIf();
    }

    public void outLog(Value statement) {
        Call c = new Call("outLog");
        c.addArgument(new Receiver(statement, "getOperationLog"));
        addStatement(c);
    }

    public void setupOperationQuery(Value statement, String queryName) {
        Receiver r = new Receiver(statement, "prepareStatement");
        addStatement(r);
    }

    public void declareIterator(Value iterator) {
        Call c = new Call(iterator.getType());
        c.addArgument("_connection");
        declare(iterator, c);
    }

    public void callSetInputParameter(Value invoker, Iterator parameters) {
        Receiver r = new Receiver(invoker);
        Call c = r.call("setInputParameter");
        while (parameters.hasNext()) {
            Value value = (Value) parameters.next();
            c.addArgument(value);
            if (value.getType().getName().equals("InputStream")
                    || value.getType().getName().equals("Reader")) {
                c.addArgument("10000");
            }

        }
        addStatement(r);
    }

    public void callExecuteQuery(Value invoker) {
        Receiver r = new Receiver(invoker);
        Call c = r.call("executeQuery");
        addStatement(r);
    }

    // 2005.04.08 t.iga パラメータを除去しました。一方で事前にバインドください。
    public Statement createCallExecute(Value invoker) {
        Receiver r = new Receiver(invoker);
        Call c = r.call("executeUpdate");
        return r;
    }
}