/*
 * Copyright (C) 2005 NTT DATA Corporation
 * 
 */
package org.postgresforest.tool.db;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;

import org.postgresforest.tool.bean.ColumnInfo;
import org.postgresforest.tool.util.StringReplaceUtil;
import org.postgresql.jdbc3.Jdbc3Connection;

/**
 *
 * UserDataCheck
 * @version $Revision: 1.1.1.1 $
 * @since 
 */
public class UserDataCheck extends UserData {

    /**
     * @param dbName
     * @param user
     * @param password
     */
    public UserDataCheck(String dbName, String user, String password) {
        super(dbName, user, password);
        // TODO 自動生成されたコンストラクター・スタブ
    }

    /**
     * @param userPassword
     */
    public UserDataCheck(Properties userPassword) {
        super(userPassword);
        // TODO 自動生成されたコンストラクター・スタブ
    }

    /**
     * カラム情報確認
     * 
     * 指定されたテーブル、カラム情報と
     * メタデータから取得したカラム情報を比較して相違があれば、接続先のリストを返す
     * 
     * @param tableName	テーブル名
     * @param columnInfo	カラム情報
     * @return	相違があるサーバのコネクションのリスト
     * @throws SQLException
     */
    public ArrayList checkColumn(String tableName, ColumnInfo columnInfo) throws SQLException {
    
    	ArrayList errConnectionList = new ArrayList();
    
    	for (Iterator iter = m_Connection.iterator(); iter.hasNext();) {
    
    		Connection con = (Connection) iter.next();
    		int objIndex = m_Connection.indexOf(con);
    		try {
    
    			DatabaseMetaData dataMeta = con.getMetaData();
    
    			//テーブル、属性名を指定して、メタデータ取得
    			ResultSet rs =
    				dataMeta.getColumns(
    					m_dbName,
    					"public",
    					tableName.toLowerCase(),
    					columnInfo.getName().toLowerCase());
    
    			if (rs.next()) {
    				//属性の型をJDBCの型に変換
    				int clmType =
    					((Jdbc3Connection) con).getSQLType(
    						rs.getString("TYPE_NAME").toLowerCase());
    				int gscclmType =
    					((Jdbc3Connection) con).getSQLType(
    						columnInfo.getType().toLowerCase());
    
    				//型と項目番号を比較
    				if ((columnInfo.getNumber()
    					!= rs.getInt("ORDINAL_POSITION"))
    					|| (clmType != gscclmType)) {
    					errConnectionList.add(getURL(objIndex));
    				}
    			} else {
    				errConnectionList.add(getURL(objIndex));
    			}
    
    		} catch (SQLException e) {
    			errConnectionList.add(getURL(objIndex));
    		}
    
    	}
    	return errConnectionList;
    }

    /**
     * データ数チェック処理
     * 
     * 指定されたテーブルのデータ数を各インスタンス毎に比較しチェックする
     * 
     * @param tableName　テーブル名
     * @return	true:正常.false:異常
     * @since 2.0
     */
    public boolean checkDataCount(String tableName) {
    	boolean ret = true;
    	String connectUrl = "";
    	long recordCount = 0;
    	ArrayList recCountList = new ArrayList();
    
    	//テーブルのレコード数をインスタンス毎に取得する
    	for (Iterator iter = m_Connection.iterator(); iter.hasNext();) {
    		Connection con = (Connection) iter.next();
    		
    		try {
    			connectUrl = ((Jdbc3Connection) con).getURL();
    
    			Statement smt = con.createStatement();
    
    			StringReplaceUtil strUtil =
    				new StringReplaceUtil(
    					m_sqlResource.getString("select.record.count"));
    			strUtil.set(1, tableName);
    			
    			ResultSet rs = smt.executeQuery(strUtil.get());
    			while (rs.next()) {
    				recordCount = rs.getLong("RECORD_COUNT");
    				recCountList.add(new Long(recordCount));
    			}
    			rs.close();
    			smt.close();
    
    		} catch (SQLException e) {
    			setErrInfo(connectUrl, e);
    			ret = false;
    		}
    	}
    	
    	//レコード数を比較
    	for (int i = 0; i < recCountList.size() - 1; i++) {
    		Long count1 = (Long) recCountList.get(i);
    		Long count2 = (Long) recCountList.get(i + 1);
    		
    		if (count1.compareTo(count2) != 0) {
    			ret = false;
    			break;
    		}
    	}
    	
    	return ret;
    }
    /**
     * データ数チェック処理
     * 
     * 指定されたテーブルのデータ数を各インスタンス毎に比較しチェックする
     * 
     * @param tableName　テーブル名
     * @return	true:正常.false:異常
     * @since 2.0
     */
    public boolean checkDataCount(String tableName, HashMap urlMap) {
    	boolean ret = true;
    	String connectUrl = "";
    	long recordCount = 0;
    	ArrayList recCountList = new ArrayList();
    
    	//テーブルのレコード数をインスタンス毎に取得する
    	for (Iterator iter = m_Connection.iterator(); iter.hasNext();) {
    		Connection con = (Connection) iter.next();
    		String url = getURL(m_Connection.indexOf(con));
    		
    		if( urlMap.get(url) == null){
    		
    		    continue;
    		}
    		
    		try {
    			connectUrl = ((Jdbc3Connection) con).getURL();
    
    			Statement smt = con.createStatement();
    
    			StringReplaceUtil strUtil =
    				new StringReplaceUtil(
    					m_sqlResource.getString("select.record.count"));
    			strUtil.set(1, tableName);
    			
    			ResultSet rs = smt.executeQuery(strUtil.get());
    			while (rs.next()) {
    				recordCount = rs.getLong("RECORD_COUNT");
    				recCountList.add(new Long(recordCount));
    			}
    			rs.close();
    			smt.close();
    
    		} catch (SQLException e) {
    			setErrInfo(connectUrl, e);
    			ret = false;
    		}
    	}
    	
    	//レコード数を比較
    	for (int i = 0; i < recCountList.size() - 1; i++) {
    		Long count1 = (Long) recCountList.get(i);
    		Long count2 = (Long) recCountList.get(i + 1);
    		
    		if (count1.compareTo(count2) != 0) {
    			ret = false;
    			break;
    		}
    	}
    	
    	return ret;
    }

}
