package com.ftinc.si.assist.test.web;

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;

import org.openqa.selenium.By;
import org.openqa.selenium.NotFoundException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import com.ftinc.si.assist.run.Messages;
import com.ftinc.si.assist.test.Fson;
import com.ftinc.si.assist.test.Tool;

public class PageAction {
	//自動スクロール用：xpathから要素を取得する。
	protected static String s_elmGetter = "function _elementAtXpath(path){return document.evaluate(path,document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;}"; //$NON-NLS-1$

	protected static int s_defaultTimeout = -1;//目標の要素が表示されるまで待つ時間（秒）
	protected static int s_localTimeout = 20; //invisible判定などの待ち時間。既に存在している要素が対象。
	protected HashMap<String, Object> arg_map = new HashMap<String, Object>(); //要素のID、JavaScriptの記述など
	protected String options = "";//同じActionがoptionsにより複数の振る舞いを行うための属性。CheckFor、Alert、ToWindowの切り替えなど。 //$NON-NLS-1$
	protected static String s_win_id = null; //最初のブラウザ起動時のID

	protected PageAction refer_to;//delegateする元のaction。ほとんど同じ属性を持つ場合に参照delegateが便利な時がある。
	protected void setReferTo(PageAction act) {
		refer_to = act;
	}

	//xpathの位置取りのあいまいさの存在する可能性がなくなったらtrue
	private boolean m_fixed;

	protected int getTimeout() {
		if (getArg("timeout") != null) { //$NON-NLS-1$
			return Integer.valueOf(getArg("timeout").toString()); //$NON-NLS-1$
		}
		return s_defaultTimeout;
	}

	//コンストラクタ
	protected PageAction() {
		//TestCaseで指定がなければSystemから取得する。
		if (s_defaultTimeout < 0) {
			String str_n = PagePlayer.getProperty("webtest.timeout"); //$NON-NLS-1$
			if (str_n.length() > 0 && str_n.matches("^[0-9]+$")) { //$NON-NLS-1$
				s_defaultTimeout = Integer.valueOf(str_n);
			}
		}
		//何も指定されていなかったら20秒を採用
		if (s_defaultTimeout < 0) {
			s_defaultTimeout = s_localTimeout;
		}
		m_fixed = false;
	}

	//必要なものだけが、初期化する。
	public void initAction() {
	}

	//通常のPageActionは全自動。
	public boolean isAutomatic() {
		return true;
	}

	//操作の実行。返却値はScript実行や要素取得などのアクションの場合には結果文字列、通常のアクションはnullが返る。
	public ArrayList<String> doAction(WebDriver drv) {
		WebElement elm = null;
		try {
			elm = waitUntil(drv);
			doCore(drv, elm);
		} catch (TimeoutException e) {
			//実際はタイムアウトではなく見つからなかった。
			throw new NotFoundException("\t\ttimeout at " + this.getClass().getSimpleName() + " [" + e.getMessage() + "] ,where location = " + getTarget()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		return null;
	}

	//$POSITIONが与えられた場合、ヒットした数を一時的に保持。
	private Integer num_prev = null; //前回検出した要素数。
	private Integer num_hit = null; //順番の条件を外して検出した要素数。
	private WebElement pre_hit = null;
	private Integer req_pos = 0;//指定された位置。指定されていなければ0.

	//画面の準備ができるまで待つ。Actionごとに待ち方が異なる。
	protected WebElement waitUntil(WebDriver drv) {
		By t_loc = getLocator();
		if (t_loc != null) {
			int t_sec = getTimeout();
			WebDriverWait wait = new WebDriverWait(drv, t_sec);

			//読込が完了していることを確認する。
			try {
				//positionが設定されている時は、(...)[1]ではない。...である。
				//DOMはできている。onloadで順序の入れ替えをしている可能性があるので、さらにwait2を行う。
				wait.until(ExpectedConditions.presenceOfElementLocated(t_loc));

				if (!m_fixed) {
					String t_path = getXpath();
					//あいまいさが残っている可能性がある。
					String position = (String)getArg("$POSITION"); //$NON-NLS-1$
					if (position != null && position.length() > 0 && !position.equals("[1]")) { //$NON-NLS-1$
						//ここに来る段階で、位置は２以上と推定される。
						if (position.matches("^\\[\\d+\\]$")) { //$NON-NLS-1$
							//中に数字がある。
							req_pos = Integer.valueOf(position.replaceFirst("^\\[(\\d+)\\]$", "$1")); //$NON-NLS-1$ //$NON-NLS-2$
						}
						//複数現れるまで２秒待つ。★★固定でよいのか????
						WebDriverWait wait2 = new WebDriverWait(drv, 2, 500);
						try {
							//ここに入ってきた時点で、複数個ヒットすることを期待している。
							final ExpectedCondition<Boolean> t_ec = new ExpectedCondition<Boolean>() {
								public Boolean apply(WebDriver drv) {
									List<WebElement> t_list = drv.findElements(getLocator());
									if (req_pos > 0 && t_list.size() >= req_pos) {
										//位置が指定されている。
										if (pre_hit == null) {
											pre_hit = t_list.get(req_pos - 1);
											try {
												Thread.sleep(200);
											} catch (InterruptedException e) {
												e.printStackTrace();
											}
										} else if (pre_hit.equals(t_list.get(req_pos - 1))) {
											num_hit = req_pos;
											return true;
										} else {
											pre_hit = t_list.get(req_pos - 1);
											try {
												Thread.sleep(200);
											} catch (InterruptedException e) {
												e.printStackTrace();
											}
										}
									} else if (t_list.size() > 1) {
										if (num_prev == null) {
											num_prev = t_list.size();
										} else if (num_prev == t_list.size()) {
											//要素数が安定した。
											//last()で指定。
											num_hit = t_list.size();
											return true;
										} else {
											//まだ安定していない。
											num_prev = t_list.size();
										}
									} else {
										try {
											//様子を見る。
											Thread.sleep(500);
										} catch (InterruptedException e) {
											e.printStackTrace();
										}
									}
									return false;
								}
							};
							//HTML高速化のためにダミーで一つ最初につくる実装方法もある。その作りに騙されないようにする。
							wait2.until(t_ec);
						} catch (Exception e) {
							//有効化操作が必要なコントロール（有効化後、１要素しか表示しない実装方法がある）
							//	そのためthroughするが、有効化を実装した画面のテストは少し遅くなる。
							num_hit = 1;
						}

						if (num_hit > 1 && position.equals("[last()]")) { //$NON-NLS-1$
							position = "[" + num_hit.toString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
						} else if (num_hit > 1 && position.indexOf("last()") > 0) { //$NON-NLS-1$
							//[]の中のlast()を実際の位置に置き換える。加減算にする。
							String exp = position.replaceFirst("\\[(.*)\\]", "$1"); //$NON-NLS-1$ //$NON-NLS-2$
							exp = exp.replace("last()", num_hit.toString()); //$NON-NLS-1$

							//式を評価する。
							Integer t_n = Fson.numberByExpression(exp);
							if (t_n != null) {
								position = "[" + t_n.toString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
							} else {
								position = "[" + num_hit.toString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
							}
						} else if (num_hit < 2) {
							//有効化操作が必要なコントロール（有効化後、実体含めて２要素以下しか表示しない実装方法がある）
							if (!"[1]".equals("[" + num_hit.toString() + "]")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
								//有効化でない場合、気づけるようにデバッグモードのログに出力。
								Tool.logIfDebug(null, t_path + Messages.getString("PageAction.9") + position); //$NON-NLS-1$
							}
							position = "[" + num_hit.toString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
						} else if (num_hit >= req_pos && req_pos > 0) {
							position = "[" + req_pos.toString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
						}
						if (!t_path.matches("^\\(.*\\)\\[\\d+\\]$")) { //$NON-NLS-1$
							//()付でない場合、付ける。
							t_path = "(" + t_path + ")"; //$NON-NLS-1$ //$NON-NLS-2$
						}
						t_path = t_path + position;
						setArg("xpath", t_path); //$NON-NLS-1$
					}
				}
				//あいまいさがなくなった。はずである。
				m_fixed = true;

				//要素が表示されるまでスクロールする。
				return scrollToView(drv);
			} catch (Exception e) {
				String target = "xpath=" + getXpath(); //$NON-NLS-1$
				if (arg_map.containsKey("itemID")) { //$NON-NLS-1$
					target += " itemID=" + arg_map.get("itemID").toString(); //$NON-NLS-1$ //$NON-NLS-2$
				}
				throw new NotFoundException("\t\tPageAction msg=" + e.getMessage() + target); //$NON-NLS-1$
			}
		}
		return null;
	}

	//Action実行の本体
	protected void doCore(WebDriver drv, WebElement elm) {
	}

	//xpathのWebElementがあれば、見えるようにスクロールする。
	protected WebElement scrollToView(WebDriver drv) {
		//要素が表示されるまでスクロールする。
		return scrollToViewByXpath(drv, getXpath());
	}

	//xpathのWebElementがあれば、見えるようにスクロールする。
	private WebElement scrollToViewByXpath(WebDriver drv, String xpath) {
		if (xpath != null) {
			//xpathが変わっている可能性もあるのでもう一回確認。
			int t_sec = getTimeout();
			WebDriverWait wait = new WebDriverWait(drv, t_sec);

			//xpathが変わっている可能性もあるのでもう一回確認。
			WebElement elm = drv.findElement(getLocator());
//			if (ExpectedConditions.elementToBeClickable(elm).apply(drv) == elm) {
			//clickable判定ではiggridのテストを通過できなかった。識別子の指定で見えていないのに成功することがあるようだ。

			if (ExpectedConditions.visibilityOf(elm).apply(drv) == elm) {
				//見えていたらスクロールする必要なし。
				//※　但しz-indexで上層に要素があり、イベントが遮られる可能性あり。

				//ブラウザの表示範囲外に隠れているかどうか、現時点では判別できないので、コメントアウト。
//				if (isCovered(drv, elm)) {
//					//とりあえずやっつけでのイベント発火なのでログに書いておく。
//					TestLogger.err("Warning:" + getXpath() + Messages.getString("PageAction.10"));  //$NON-NLS-1$ //$NON-NLS-2$
//				}
				return elm;
			}
			Actions t_acts = new Actions(drv);
			t_acts.moveToElement(elm).perform();

			elm =  wait.until(ExpectedConditions.elementToBeClickable(elm));
			return elm;
		}
		return null;
	}

	//何かしらLocation情報が指定されていたらByを返す。
	protected final By getLocator() {
		if (arg_map.containsKey("id")) { //$NON-NLS-1$
			//決定表から指定する際にはIDの方が楽の場合がある。
			return By.id((String)arg_map.get("id")); //$NON-NLS-1$
		} else if (arg_map.containsKey("xpath")) { //$NON-NLS-1$
//			if (getXpath() != null) {
				return By.xpath(getXpath()); //$NON-NLS-1$
//			}
		}
		return null;
	}

	//最終的なxpathを返す。$KEY,$VARに代入済みの状態にする。
	protected String getXpath() {
		String t_path = (String)getArg("xpath");//$NON-NLS-1$
		if (t_path != null) {
			if (t_path.contains("$KEY")) { //$NON-NLS-1$
				String t_key = (String)getArg("$KEY");//$NON-NLS-1$
				if (t_key != null && t_key.length() > 0) {
					//xpathに＄KEYが含まれているときに備えて、変換する。
					t_path = t_path.replaceAll(Pattern.quote("$KEY"), Matcher.quoteReplacement(t_key)); //$NON-NLS-1$

				} else {
					Tool.logForTesting(null, Messages.getString("PageAction.7") + t_path + "."); //$NON-NLS-1$ //$NON-NLS-2$
				}
			} else {
				//$KEYがない場合、あいまいさの可能性が排除された状況と見ることができる。
				m_fixed = true;
			}
			if (t_path.indexOf("$)[1]") > 0) { //$NON-NLS-1$
				//入力部品のインスタンスが一つしかない場合、コントロール辞書の孫コントロールの末尾には「$」がある。
				m_fixed = true;
				t_path = t_path.replace("$)[1]", ")[1]"); //$NON-NLS-1$ //$NON-NLS-2$
				setArg("xpath", t_path);//$VARがない場合、ここで一旦確定とする。 //$NON-NLS-1$
			}

			if (!m_fixed) {
				//位置取りのあいまいさが存在する場合の処理。このインスタンスの初回呼び出しのみ行われる。
				String position = (String)getArg("$POSITION"); //$NON-NLS-1$
				if (position != null && !position.equals("[1]") && t_path.endsWith("[1]")) { //$NON-NLS-1$ //$NON-NLS-2$
					//最後に位置が指定されているがpositionを優先すべき。とりあえず外側の()と末尾の[1]を外す。
					t_path = t_path.replaceFirst("^\\((.*)\\)\\[1\\]$", "$1"); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
			if (t_path.contains("$VAR")) { //$NON-NLS-1$
				Object t_var = getArg("$VAR");//$NON-NLS-1$
				if (t_var != null && t_var.toString().length() > 0) { //$NON-NLS-1$
					//xpathに＄VARが含まれているときに備えて、変換する。
					t_path = t_path.replaceAll(Pattern.quote("$VAR"), Matcher.quoteReplacement(t_var.toString())); //$NON-NLS-1$ //$NON-NLS-2$
				} else {
					Tool.logForTesting(null, Messages.getString("PageAction.13") + t_path + "."); //$NON-NLS-1$ //$NON-NLS-2$
				}
				if (m_fixed) {
					//$VAR代入後には確定したxpathとする。
					setArg("xpath", t_path); //$NON-NLS-1$
				}
			}
			return t_path;
		}
		String t_id = (String)getArg("id"); //$NON-NLS-1$
		if (t_id != null) {
			return "//*[@id='" + t_id + "']"; //$NON-NLS-1$ //$NON-NLS-2$
		}
		return null;
	}

	//arg_mapに設定した値を返す。なければ、delegateを試みる。$KEYなどの共通属性をMacroAction内で共有するため。
	protected Object getArg(String key) {
		if (arg_map.containsKey(key)) {
			return arg_map.get(key);
		} else if (key.equals("$VAR") && arg_map.containsKey("value")) {
			//最後のよりどころはvalue
			return arg_map.get("value");
		} else if (refer_to != null) {
			//下から上への一方通行である。
			return refer_to.getArg(key);
		}
		return null;
	}

	//委任されたPageActionが委任元を見ながら値を設定する。$付のキーは共有される。
	protected void setArg(String key, Object value) {
		arg_map.put(key, value);
		if (key.startsWith("$") && refer_to != null) { //$NON-NLS-1$
			refer_to.setArg(key, value);
		}
	}


	//WebElementGetterのTarget欄の値を拾い上げる。
	//また、例外処理の際に、Locatorの指定情報を取得する。
	protected String getTarget() {
		if (arg_map.containsKey("xpath")) { //$NON-NLS-1$
			return "\"xpath\":\"" + getXpath() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		} else if (arg_map.containsKey("id")) { //$NON-NLS-1$
			return "\"id\":\"" + (String)arg_map.get("id") + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		} else if (arg_map.containsKey("title")) { //$NON-NLS-1$
			return "\"title\":\"" + (String)arg_map.get("title") + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		return null;
	}

	//////////////////////////以下、編集用メソッド

	//WebElementGetterから呼ばれる。
	//path情報を持つアクションかどうか。falseならgetTargetはpath以外のものを返すべきなので上書きすること。
	protected boolean hasPath() {
		return true;
	}

	//PageActionEditorに転記する際に第二列に書き込む内容を合成する。
	protected String getJsonElement(String target, String arg) {
		String t_result = ""; //$NON-NLS-1$
		if (target == null && arg == null) {
			//指定がないときは、自分自身からJSON文字列を作る。
			t_result = Tool.getJSONfromObject(this, "^(?!s_).+"); //$NON-NLS-1$
			t_result = t_result.replaceAll("(\\A\\s*\\{|\\}\\s*\\z)", "");	//前後の{}を取る。 //$NON-NLS-1$ //$NON-NLS-2$
			t_result = t_result.replaceAll(",", ",\n"); //$NON-NLS-1$ //$NON-NLS-2$
		} else if (target != null && target.matches("^\\s*\".+\":\".+\"\\s*[\\s\\S]*$")) { //$NON-NLS-1$
			//json形式である。デフォルトではargは使わない。使う場合はoverrideすること。
			t_result = target;
		}
		return t_result;
	}

	//Assert判定するActionかどうか
	protected boolean assertable() {
		return false;
	}


	//WebElementGetterの正規表現欄の値を指定する。
	//最初の項目はラベル、最後の項目は現在の状態であり、必ず選択されている。
	protected ArrayList<String> getLabelAndParams() {
		ArrayList<String> t_list = new ArrayList<String>();
		if (assertable()) {
			t_list.add(Messages.getString("PageAction.6")); //$NON-NLS-1$
			t_list.add("visible=true"); //$NON-NLS-1$
			t_list.add("visible=false"); //$NON-NLS-1$
			t_list.add("enabled=true"); //$NON-NLS-1$
			t_list.add("enabled=false"); //$NON-NLS-1$
			t_list.add(":SKIP"); //$NON-NLS-1$
		}
		return t_list;
	}

	//<|>|<=|>=|==|=~つきを拡張正規表現に変換する。
	protected String convertReg(String str) {
		if (str != null) {
			str = str.replaceFirst("=~", "").trim(); //$NON-NLS-1$ //$NON-NLS-2$
			str = str.replaceFirst("==", "=").trim(); //$NON-NLS-1$ //$NON-NLS-2$
			if ("|>|<|=|".contains(str.substring(0, 1))) { //$NON-NLS-1$
				return "$" + str; //$NON-NLS-1$
			}
		} else {
			str = ""; //$NON-NLS-1$
		}
		return str;
	}

	//正規表現などの評価式があれば返す。
	protected ArrayList<String> getRegs() {
		//評価アクションであり、かつvalueが指定されている時、判定のための評価式を返す。
		if (assertable() && arg_map.get("value") != null) { //$NON-NLS-1$
			ArrayList<String> t_list = new ArrayList<String>();
			t_list.add(convertReg(arg_map.get("value").toString())); //$NON-NLS-1$
			return t_list;
		}
		return null;
	}


	//このPageActionが対象とするXPathの配列を返す。Actionの種類によってターゲットとなるNodeが異なる。
	protected String[] getFocussingXPaths(String xpath) {
		if (xpath != null && xpath.length() > 0) {
			if (!xpath.startsWith("(") && !xpath.startsWith("//")) { //$NON-NLS-1$ //$NON-NLS-2$
				xpath = "//" + xpath; //$NON-NLS-1$
			}
			//指定の文字を含む。
			return new String[] {xpath};
		}
		return null;
	}

	//このPageActionが対象とするWebElementとそのXpathを取得する。WebElementGetterで要素を選択するためである。
	//返却値はWebElementgetterを開くかどうか。
	protected boolean getFocussingElements(WebDriver drv, ArrayList<WebElement> el_list, ArrayList<String> xp_list, String xpath) {
		if (drv != null) {
			//検索用xpathが明に指定されていなければ、自分の関心のあるnodeを検索する。
			String[] t_xpaths = getFocussingXPaths(xpath);
			if (t_xpaths != null) {
				for (int i = 0; i < t_xpaths.length; i++) {
					List<WebElement> t_elms1 = drv.findElements(By.xpath(t_xpaths[i]));
					if (t_elms1.size() > 1) {
						for (int j = 0; j < t_elms1.size(); j++) {
							el_list.add(t_elms1.get(j));

							String str_num = ""; //$NON-NLS-1$
							if (t_xpaths.length > 0) {
								str_num = "[" + Integer.toString(j + 1) +"]"; //$NON-NLS-1$ //$NON-NLS-2$
							}
							//()はdescendantを付けなくても済むように。
							xp_list.add("(" + t_xpaths[i] + ")" + str_num); //$NON-NLS-1$ //$NON-NLS-2$
						}
					} else if (t_elms1.size() == 1) {
						el_list.add(t_elms1.get(0));
						xp_list.add(t_xpaths[i]);
					}
				}
			}
		}

		return true;//WebElementGetterを開くサイン
	}


	//必要に応じて、WebElementGetterに対してJsonテンプレートを返す。
	protected String getTemplateString() {
		return null;
	}


	//WebElementGetterから呼ばれる。
	protected JPopupMenu getPopup(WebElementGetter wg, String cur_str) {
		if (hasPath()) {
			JPopupMenu t_pop = new JPopupMenu();
			t_pop.add(new JMenuItem(new InsertAction("\"id\":\"\"", "AddID", wg, cur_str))); //$NON-NLS-1$ //$NON-NLS-2$
			t_pop.add(new JMenuItem(new InsertAction("\"xpath\":\"//*[@id='']\"", "AddXpath", wg, cur_str))); //$NON-NLS-1$ //$NON-NLS-2$

			JMenu t_menu = new JMenu(Messages.getString("PageAction.21")); //$NON-NLS-1$
			t_menu.add(new JMenuItem(new InsertAction(Messages.getString("PageAction.22"), "EqualsText", wg, cur_str))); //$NON-NLS-1$ //$NON-NLS-2$
			t_menu.add(new JMenuItem(new InsertAction(Messages.getString("PageAction.24"), "ContainsText", wg, cur_str))); //$NON-NLS-1$ //$NON-NLS-2$
			t_menu.add(new JMenuItem(new InsertAction(Messages.getString("PageAction.26"), "HasTag", wg, cur_str))); //$NON-NLS-1$ //$NON-NLS-2$
			t_pop.add(t_menu);

			return t_pop;
		}
		return null;
	}

	//popupのコマンド文字列を受けて、このメソッドに中継する。
	//中継だけなので、アクションはこのクラスのみ。
	class InsertAction extends AbstractAction {
		String m_string;
		String act_name;
		String m_target;
		WebElementGetter m_master;
		HashMap<String, String> m_dic = new HashMap<String, String>();

		InsertAction(String str, String a_name, WebElementGetter master, String cstr) {
			putValue(Action.NAME, str);
			m_string = str;
			act_name = a_name;
			m_master = master;
			m_target = cstr;

			if (m_dic.size() == 0) {
				m_dic.put("ContainsText", "[contains(.,'$')]"); //$NON-NLS-1$ //$NON-NLS-2$
				m_dic.put("EqualsText", "[.='$']"); //$NON-NLS-1$ //$NON-NLS-2$
				m_dic.put("HasTag", "[.//$]"); //$NON-NLS-1$ //$NON-NLS-2$
				m_dic.put("ContainsText@", "[contains(@value,'$')]"); //$NON-NLS-1$ //$NON-NLS-2$
				m_dic.put("EqualsText@", "[@value='$']"); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			switch (act_name) {
				case "EqualsText": //$NON-NLS-1$
				case "HasTag": //$NON-NLS-1$
				case "ContainsText": //$NON-NLS-1$
				case "EqualsText@": //$NON-NLS-1$
				case "ContainsText@": //$NON-NLS-1$
					m_master.setTargetFromPopup(addingStringToTarget());
					break;
				case "SelectFile": //$NON-NLS-1$
					//fileを選択し、パスをセットする。
					JFileChooser t_fc = new JFileChooser(Tool.getPrevPath());
					if (t_fc.showOpenDialog(m_master) == JFileChooser.APPROVE_OPTION) {
						File t_file = t_fc.getSelectedFile();
						String jf_name = t_file.getAbsolutePath();  //クラスのパス
						m_master.setTargetFromPopup(jf_name);

						Tool.setPrevPath(t_file.getAbsolutePath());
					}
					break;
				default:
					m_master.setTargetFromPopup(m_string);
					break;
			}
		}


		//m_targetに文字を追加する。
		private String addingStringToTarget() {
			String t_data = JOptionPane.showInputDialog(m_master, m_string, ""); //$NON-NLS-1$

			String t_result = m_target;
			if (t_data.length() > 0) {
				String tail = m_dic.get(act_name);
				tail = tail.replaceAll("\\$", Matcher.quoteReplacement(t_data)); //$NON-NLS-1$
				if (t_result.matches("\\A[\\s\\S]*\"xpath\":\"[^\"]+\\[[0-9]+\\]\"[\\s\\S]*\\z")) { //$NON-NLS-1$
					//xpathになっている場合:xpathの最後が数字配列である。条件追加で絞りたいので配列を取る。
					tail = Matcher.quoteReplacement(tail + "\"");//"ごと置き換えるため末尾に追加。 //$NON-NLS-1$
					t_result = t_result.replaceFirst("^([\\s\\S]*\"xpath\":\"[^\"]+)\\[[0-9]+\\]\"([\\s\\S]*)\\z", "$1" + tail + "$2"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				} else if (t_result.matches("\\A[\\s\\S]*\"xpath\":\"[^\"]+\"[\\s\\S]*\\z")) { //$NON-NLS-1$
					//xpathになっている場合:xpathの最後が数字配列ではない。
					tail = Matcher.quoteReplacement(tail + "\"");//"ごと置き換えるため末尾に追加。 //$NON-NLS-1$
					t_result = t_result.replaceFirst("^([\\s\\S]*\"xpath\":\"[^\"]+)\"([\\s\\S]*)\\z", "$1" + tail + "$2"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				} else if (t_result.matches("\\A[\\s\\S]*\\(xpath=\"[^\"]+\\[[0-9]+\\][\\s\\S]*\\z")) { //$NON-NLS-1$
					//xpathになっている場合
					tail = Matcher.quoteReplacement(tail + "\"");//"ごと置き換えるため末尾に追加。 //$NON-NLS-1$
					t_result = t_result.replaceFirst("\\A([\\s\\S]*\\(xpath=\"[^\"]+)\\[[0-9]+\\]\"([\\s\\S]*)\\z", "$1" + tail + "$2"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				} else if (t_result.matches("\\A[\\s\\S]*\\(xpath=\"[^\"]+\"[\\s\\S]*\\z")) { //$NON-NLS-1$
					//xpathになっている場合
					tail = Matcher.quoteReplacement(tail + "\"");//"ごと置き換えるため末尾に追加。 //$NON-NLS-1$
					t_result = t_result.replaceFirst("\\A([\\s\\S]*\\(xpath=\"[^\"]+)\"([\\s\\S]*)\\z", "$1" + tail + "$2"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				} else {
					t_result += tail;
				}
			}
			return t_result;
		}
	}

	//キー入力結果（strb）により、WebElementGetterの入力欄を自動指定する場合に上書きする。
	protected boolean modifyByKeyInput(KeyEvent e, StringBuilder strb) {
		return false;
	}

}
