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

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * blancoDbが利用するQueryパース・ユーティリティクラス <br>
 * SQLの解釈および変換などを目的とします。 <br>
 * 
 * @author Tosiki Iga
 */
public class BlancoDbQueryParserUtil {
    /**
     * SQL入力パラメータとして判定するための正規表現文字列。
     */
    private static final String SZ_PARAMETER_FOR_SQL_INPUT_PARAMETER = "#[a-zA-Z0-9.\\-_\\P{InBasicLatin}]*\\b|#.*$";

    /**
     * SQL入力パラメータのマップ <br>
     * TODO マップはマズイです。
     */
    private final Map _mapForSqlInputParameters = new Hashtable();

    /**
     * オリジナルのSQL文字列
     */
    private String _originalSqlQueryString = "";

    public BlancoDbQueryParserUtil(final String sqlQueryString) {
        // パラメータを記憶します。
        _originalSqlQueryString = sqlQueryString;

        // 正規表現文字列インスタンスを生成します。
        // TODO 正規表現による処理は不適切。
        final Matcher matcher = Pattern.compile(
                SZ_PARAMETER_FOR_SQL_INPUT_PARAMETER).matcher(
                _originalSqlQueryString);

        for (int index = 1; matcher.find(); index++) {
            String name = matcher.group();
            // 先頭の＃を除去します。
            name = name.substring(1, name.length());
            if (_mapForSqlInputParameters.containsKey(name) == false) {
                _mapForSqlInputParameters.put(name, new ArrayList());
            }
            ((ArrayList) _mapForSqlInputParameters.get(name)).add(new Integer(
                    index));
        }

        for (Iterator ite = _mapForSqlInputParameters.keySet().iterator(); ite
                .hasNext();) {
            final String key = (String) ite.next();
            final List list = (List) _mapForSqlInputParameters.get(key);
            _mapForSqlInputParameters.put(key, convertListToArray(list));
        }
    }

    /**
     * 入力されたSQL入力パラメータをint配列に変換します。
     * 
     * @param sqlInputParameterFoundList
     * @return
     */
    private int[] convertListToArray(final List sqlInputParameterFoundList) {
        final int[] convertedIntArray = new int[sqlInputParameterFoundList
                .size()];
        final Iterator ite = sqlInputParameterFoundList.iterator();
        for (int index = 0; ite.hasNext(); index++) {
            convertedIntArray[index] = ((Integer) ite.next()).intValue();
        }
        return convertedIntArray;
    }

    /**
     * Iteratorに実際に張り込まれるナチュラルなSQL文
     * 
     * @return
     */
    public String getNaturalSqlString() {
        return _originalSqlQueryString.replaceAll(
                SZ_PARAMETER_FOR_SQL_INPUT_PARAMETER, "?");
    }

    /**
     * 試作：キーを元に、intをゲットします。
     * 
     * @param key
     * @return
     */
    public int[] getSqlParameters(final String key) {
        // TODO マップからIteratorを起こしているのが問題。
        return (int[]) _mapForSqlInputParameters.get(key);
    }
}