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

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

import org.postgresforest.tool.bean.AddDbInfo;
import org.postgresforest.tool.bean.DbLinkInfo;
import org.postgresforest.tool.bean.ServerDumpDataInfo;
import org.postgresforest.tool.bean.ServerInfo;
import org.postgresforest.tool.db.DbBase;
import org.postgresforest.tool.db.GSCdata;
import org.postgresforest.tool.db.UserData;
import org.postgresforest.tool.util.MessagesCommandLine;
import org.postgresforest.tool.util.StringReplaceUtil;

/**
 * DB作成処理アクション
 * 
 * <pre>
 * 入力情報"AddDbForm"から、以下の処理を行う。
 * ・GSC更新
 *   forestservdbへレコード挿入
 * ・データベース作成
 *   CREATE DATABASE コマンド実行
 * </pre>
 *
 */
public class DbAction extends ActionBase {
	/** 作成モード定数  */
	
	/**
	 * @param gsc
	 */
	public DbAction(GSCdata gsc) {
		super(gsc);
		// TODO 自動生成されたコンストラクター・スタブ
	}
	/**
	 * DB作成メイン処理
	 * 
	 * @see org.postgresforest.tool.action.DbAction#addDb()
	 */
	public boolean add(AddDbInfo addForm) {


		String dbName = addForm.getDb();
		String option = addForm.getOption();
		int makeMode = addForm.getMakeMode();
		ArrayList serverDumpDataList = addForm.getServer();
		
		//サーバIDリストを作成
		Integer[] idList = new Integer[serverDumpDataList.size()];
		for(int i = 0; i < serverDumpDataList.size(); i++){
			ServerDumpDataInfo info = (ServerDumpDataInfo)serverDumpDataList.get(i);
			if(info.isChkFlag() == true){
				idList[i] = new Integer(info.getId());
			}
			else{
				idList[i] = null;
			}
		}
		
		//ダンプファイルリストを作成
		String[] dumpList = new String[serverDumpDataList.size()];
		for(int i = 0; i < serverDumpDataList.size(); i++){
			ServerDumpDataInfo info = (ServerDumpDataInfo)serverDumpDataList.get(i);
			dumpList[i] = info.getDumpData();
		}
		
		//ユーザDBクラス生成
		UserData userData = new UserData(m_gsc.getUserPassword());

		try {

			//GSCへ接続
			if (!connect(m_gsc)) {
				return false; 
			}
			
			//--------------
			// データベース登録チェック　
			//--------------
			ArrayList dbList = m_gsc.getDbList();
			boolean dbCheck = false;
			for (int i = 0; i < dbList.size(); i++) {
				String checkDbName = (String)dbList.get(i);
				if (dbName.compareTo(checkDbName) == 0) {
					dbCheck = true;
					break;
				}
			}
			//作成モード毎にデータベース登録チェック結果を判断する
			if (makeMode == DbBase.DB_ADD && 
				dbCheck == false) {					//データベース追加
				StringReplaceUtil strUtil =
					new StringReplaceUtil(MessagesCommandLine.getString("errors.db.notadd"));
				strUtil.set(1, dbName);
				
				System.out.println(strUtil.get());

				return false; 
			}
			else if (makeMode == DbBase.DB_SHIFT && 
				dbCheck == true) {						//データベース移行
				StringReplaceUtil strUtil =
					new StringReplaceUtil(MessagesCommandLine.getString("errors.db.notshift"));
				strUtil.set(1, dbName);
				
				System.out.println(strUtil.get());
				return false; 
			}

			//--------------
			// GSC　更新
			//--------------

			//サーバIDでインスタンス情報取得
			ArrayList serverList;
			try {
				serverList = m_gsc.getServerList(idList);
			} catch (SQLException e) {
				setAccessErrs(m_gsc);
				return false; 
			}
			//forest_servdb更新
			if (!m_gsc.addServDb(dbName, idList)) {
				m_gsc.rollback();
				setAccessErrs(m_gsc);
				return false; 
			}
				
			if (makeMode == DbBase.DB_ADD) {	//データベース追加
				//forest_tablepartdtl更新
				if (!m_gsc.setDbAdd(dbName, idList)) {
					m_gsc.rollback();
					setAccessErrs(m_gsc);
					return false; 
				}
			}
						
			//--------------
			// ユーザデータベース情報生成
			//--------------
			//接続情報をセット
			for (Iterator iter = serverList.iterator(); iter.hasNext();) {
				ServerInfo serverInfo = (ServerInfo) iter.next();
				String host = serverInfo.getHost();
				String port = serverInfo.getPort();

				//ユーザDBクラスに追加
				userData.addUrl(host, port, dbName);
				
				int serverId = serverInfo.getId();
				for (int i = 0; i < idList.length; i++) {
					if (idList[i] != null) {
						if (idList[i].intValue() == serverId) {
							userData.addDumpData(dumpList[i]);
							break;
						}
					}
				}
			}

			//--------------
			// ユーザデータベース作成
			//--------------
			//template1DBに接続
			if (connectTemlate(userData)) {
				//--------------
				// データベース存在チェック　
				//--------------
				ArrayList dbMapList = userData.getDbMapList();
				String[] urls = userData.getURL();
				ArrayList servers = new ArrayList();
				for (int i = 0; i < urls.length ; i++) {
					HashMap dbNameMap = (HashMap) dbMapList.get(i);
					if (dbNameMap.containsKey(dbName)) {
						servers.add(urls[i]);
					}
				}
				userData.rollback();
				
				//ユーザデータベース作成
				if (!userData.makeDB(option, makeMode)) {
					//データベース削除
					userData.delDB();
					m_gsc.rollback();
					userData.rollback();
					setAccessErrs("errors.db.create", userData);
					
					System.out.println("errors.db.create");
					return false; 
				}
				else{
					//リストア実行
					if (makeMode == DbBase.DB_ADD || makeMode == DbBase.DB_SHIFT) {	//データベース追加・移行
						if (!userData.execRestore(dbName)) {
							//データベース削除
							userData.delDB();
							m_gsc.rollback();
							userData.rollback();
							setAccessErrs("errors.db.restore", userData);

//							System.out.println("errors.db.restore");
							
							return false; 
						}
					}
					
					//forest_tablepart,forest_tablepartdtl更新
					if (makeMode == DbBase.DB_SHIFT) {	//データベース移行
						userData.close();
						
						//ユーザデータベースに接続
						boolean ret = true;
 						if (connect(userData)) {
							//テーブル名を取得
							ArrayList tableList = userData.getTableList();
							
							//forest_tablepartdtl更新
							if (!m_gsc.setDbShift(dbName, tableList, serverList)) {
								ret = false;
							}
						}
						else{
							ret = false;
						}
						
						//forest_tablepartdtl更新に失敗
						if (!ret){
							//template1DBに接続
							if (connectTemlate(userData)) {
								//データベース削除
								userData.delDB();
							}
							m_gsc.rollback();
							userData.rollback();
							setAccessErrs(m_gsc);
							return false; 
						}
					}
				}
				
				m_gsc.commit();
			}

		} finally {
			m_gsc.close();
			userData.close();
		}

		return true; 
	}
	/**
	 * データベース削除メイン処理
	 * 
	 * @see org.postgresforest.tool.action.AdminActionBase#executeMain(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, javax.servlet.http.HttpSession, org.postgresforest.tool.db.GSCdata)
	 */
	public boolean del(ArrayList dbLinkList)  {


		UserData userData = new UserData(m_gsc.getUserPassword());

		try {

			//--------------
			// GSC　更新
			//--------------

			if (!connect(m_gsc)) {
				return false; 
			}

			Iterator iter = dbLinkList.iterator();
			while (iter.hasNext()) {
				DbLinkInfo dnLinkInfo = (DbLinkInfo) iter.next();
				String dbName = dnLinkInfo.getName();

				ArrayList serveList = dnLinkInfo.getServer();
				Iterator serverIter = serveList.iterator();
				while (serverIter.hasNext()) {
					ServerInfo serverInfo = (ServerInfo) serverIter.next();
					if (serverInfo.isChkFlag()) {
						int serverId = serverInfo.getId();

						String host = serverInfo.getHost();
						String port = serverInfo.getPort();

						//テーブルが存在するユーザーDBを削除できないようにする
						//テーブルリストを取得
						ArrayList tableList;
						try {
							tableList = m_gsc.getTableList(dbName);
						} catch (SQLException e) {
							m_gsc.rollback();
							setAccessErrs(m_gsc);
							return false; 
						}
						//テーブルがあればデータベース登録を中止
						if (tableList.size() > 0) {
							m_gsc.rollback();
							System.out.println(MessagesCommandLine.getString("errors.gsc.table.exist"));
							return false; 
						}

						//ユーザDBクラスに追加
						userData.addUrl(host, port, dbName);

						//forest_servdb更新
						if (!m_gsc.delServDb(dbName, serverId)) {
							m_gsc.rollback();
							setAccessErrs(m_gsc);
							return false; 

						}

					}

				}
			}
			m_gsc.commit();

			//--------------
			// ユーザデータベース削除
			//--------------
			//接続
			if (!connectTemlate(userData)) {
				return false; 
			}
			//ユーザデータベース削除
			if (!userData.delDB()) {
				setAccessErrs("errors.db.drop", userData);
				return false; 
			}
			
		} finally {
			m_gsc.close();
			userData.close();
		}

		return true; 

	}
	/**
	 * データベース一覧情報作成処理
	 * 
	 */
	public ArrayList getList() throws Exception {

 
		//データ作成
		ArrayList dbList = null;
		try {
			//接続
			if (!connect(m_gsc)) {
				throw new Exception();
			}
			
			//データベース一覧情報作成
			dbList = m_gsc.getDbList();

		} finally {
			m_gsc.close();
		}

		return dbList;
	}	
}
