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

import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;

import com.ftinc.si.assist.run.Messages;
import com.ftinc.si.assist.test.AssertRecord;
import com.ftinc.si.assist.test.Fson;
import com.ftinc.si.assist.test.ObjectRecord;
import com.ftinc.si.assist.test.Tool;
import com.ftinc.si.assist.test.gui.ArgumentEditor;
import com.ftinc.si.assist.test.gui.SimpleTextEditor;
import com.ftinc.si.assist.test.gui.TestCaseEditor;

//PagePlayerの$0を編集する。
//preCaseもしくはURLを指定する。
//アクション指定：①操作の種類③要素指定および引数
public class PageActionEditor extends JDialog {
	private HashMap<String, String> m_cmap = new HashMap<String, String>();

	private JTable m_table;
	private DefaultTableModel m_table_model;
	private JScrollPane m_tableScrollPane;
	private JRadioButton m_rdbtnParentHide;
	private ObjectRecord m_rec;
	private AssertRecord m_asrec;

	private WebElementGetter m_elmgetter = null;
	private SimpleTextEditor m_editor = null;
	private ArrayList<String> m_assertings = null;

	public PageActionEditor(JDialog owner, ObjectRecord rec, AssertRecord ast, String[] regs) {
		super(owner, true);
		setResizable(false);
		addComponentListener(new ComponentAdapter() {
			@Override
			public void componentMoved(ComponentEvent e) {
				if (m_elmgetter != null) {
					//もし開いているなら、追従させる。
					if (m_table.isShowing()) {
						Point op = m_table.getLocationOnScreen();
						m_elmgetter.setLocation(op.x + m_table.getWidth(), op.y);
						m_editor.setLocation(op.x + m_table.getWidth(), op.y);
					}
				}
			}
		});

		//画面を閉じるときの処理
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				if (m_elmgetter != null)  {
					m_elmgetter.closing();
				}
				if (m_rdbtnParentHide.isSelected()) {
					resoreParent();
				}
			}
		});

		m_rec = rec;
		m_asrec = ast;
		m_elmgetter = new WebElementGetter(this);
		m_editor = new SimpleTextEditor(this, "", false); //$NON-NLS-1$
		m_assertings = new ArrayList<String>();
		if (regs != null) {
			//正規表現を読み込む
			for (int i = 0; i < regs.length; i++) {
				m_assertings.add(regs[i]);
			}
		}

		setTitle(Messages.getString("PageActionEditor.0")); //$NON-NLS-1$
		getContentPane().setLayout(null);
		setBounds(owner.getX() + 50, owner.getY() + 50, 590, 265);

		JLabel lblActions = new JLabel(Messages.getString("PageActionEditor.2")); //$NON-NLS-1$
		lblActions.setBounds(12, 10, 60, 13);
		getContentPane().add(lblActions);

		m_tableScrollPane = new JScrollPane();
		m_tableScrollPane.setBounds(12, 33, 549, 156);
		getContentPane().add(m_tableScrollPane);

		final String[] colNames = {Messages.getString("PageActionEditor.1"), Messages.getString("PageActionEditor.6"), ""}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		m_table_model = new DefaultTableModel(colNames, 0);
		m_table = new JTable(m_table_model);

		m_table.setColumnSelectionAllowed(false);
		m_table.setRowSelectionAllowed(true);
		m_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

		TableColumn col0 = m_table.getColumnModel().getColumn(0);
		col0.setMinWidth(100);
		col0.setMaxWidth(100);

		TableColumn col2 = m_table.getColumnModel().getColumn(2);
		col2.setMinWidth(1);
		col2.setMaxWidth(1);

		m_table.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				Point t_pt = e.getPoint();
				int ir = m_table.rowAtPoint(t_pt);
				int ic = m_table.columnAtPoint(t_pt);

				//ダブルクリックはセルエディタが捕まえるので、シングルクリックしか感知できない。
				if (e.getClickCount() == 1 && ic == 1) {
					//行の選択状態に変化があれば、追従するelmgetterの状態を初期化する。
					//但し、入力列であること。先頭列はComboがイベントを優先的にとるため。

					if (m_elmgetter.m_selectedRow != ir) {
						//cellの内容を、初期化のためにm_elmgetterに転記する。
						String val = (String)m_table_model.getValueAt(ir, 1);
						String assertAndIndex = (String)m_table_model.getValueAt(ir, 2);

						//Assert対象の場合は、最初から""以上は入っている。
						if (assertAndIndex != null && assertAndIndex.length() < 2) {
							assertAndIndex = null;
						}

						PageAction t_act = getPageAction(ir, val);
						if (t_act != null) {
							//PageActionが指定できるなら、WebElementGetterを開く。
							//m_elmgetterの引数欄に文字を転記する。
							m_elmgetter.initParams(ir, t_act, assertAndIndex);

							//ブラウザから状態を読み込めるなら、現在の行のアクションを元に読み込む。
							if (m_elmgetter.initTags()) {
								m_editor.setVisible(false);//開いていたら閉じる。

								Point op = m_table.getLocationOnScreen();
								m_elmgetter.setLocation(op.x + m_table.getWidth(), op.y);
								m_elmgetter.setVisible(true);
							} else {
								//modalでないので、明に閉じる。
								m_elmgetter.setVisible(false);

								//テキストエディタを開く
								m_editor.setText(val);//trueはモーダル
								m_editor.setVisible(true);
								String t_result = m_editor.getText();
								if (t_result != null && t_result.length() > 0) {
									m_table_model.setValueAt(t_result, ir, 1);
								}
							}
						}
					}
				} else {
					//他のセルなら直接入力なので補助画面は閉じる。
					m_elmgetter.setVisible(false);
				}
			}
		});

		m_tableScrollPane.setViewportView(m_table);

		final JButton btnOk = new JButton(Messages.getString("PageActionEditor.9")); //$NON-NLS-1$
		btnOk.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (!btnOk.isEnabled()) {
					return;
				}

				//JSONを作成し、m_recに入れる。
				setJson();

				//Assert情報も必要なら更新される。
				setAssertStrings();

				if (m_elmgetter != null) {
					m_elmgetter.setVisible(false);
					m_elmgetter.closing();
					m_elmgetter = null;
				}
				if (m_rdbtnParentHide.isSelected()) {
					resoreParent();
				}
				setVisible(false);
			}
		});
		btnOk.setBounds(372, 205, 91, 21);
		btnOk.setEnabled(!TestCaseEditor.unableMode);
		getContentPane().add(btnOk);

		JButton btnCancel = new JButton(Messages.getString("PageActionEditor.10")); //$NON-NLS-1$
		btnCancel.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (m_elmgetter != null) {
					m_elmgetter.setVisible(false);
					m_elmgetter.closing();
					m_elmgetter = null;
				}
				if (m_rdbtnParentHide.isSelected()) {
					resoreParent();
				}
				setVisible(false);
			}
		});
		btnCancel.setBounds(470, 205, 91, 21);
		getContentPane().add(btnCancel);

		JButton btnAdd = new JButton(Messages.getString("PageActionEditor.btnAdd.text")); //$NON-NLS-1$
		btnAdd.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				//行を末尾に追加する
				int i = m_table.getSelectedRow();
				addRow(i);

				//WebElementGetterを閉じる
				if (m_elmgetter != null) {
					m_elmgetter.setVisible(false);
				}
			}
		});
		btnAdd.setBounds(84, 6, 92, 21);
		getContentPane().add(btnAdd);

		JButton btnDelete = new JButton(Messages.getString("PageActionEditor.btnNewButton.text")); //$NON-NLS-1$
		btnDelete.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				//WebElementGetterを閉じる
				if (m_elmgetter != null) {
					m_elmgetter.setVisible(false);
				}

				int i = m_table.getSelectedRow();
				if (i >= 0) {
					//行が選択されていれば削除する。
					int t_option = JOptionPane.showConfirmDialog(null, Messages.getString("PageActionEditor.8"), Messages.getString("PageActionEditor.12"), JOptionPane.YES_NO_OPTION); //$NON-NLS-1$ //$NON-NLS-2$
					if (t_option == JOptionPane.YES_OPTION){
						m_table_model.removeRow(i);
					}
				}
			}
		});

		btnDelete.setBounds(188, 6, 73, 21);
		getContentPane().add(btnDelete);

		JButton btnUp = new JButton(Messages.getString("PageActionEditor.btnUp.text")); //$NON-NLS-1$
		btnUp.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				//WebElementGetterを閉じる
				if (m_elmgetter != null) {
					m_elmgetter.setVisible(false);
				}

				int i = m_table.getSelectedRow();
				if (i > 0) {
					//選択行を上に移動する
					m_table_model.moveRow(i, i, i - 1);
					m_table.changeSelection(i - 1, 1, false, false);
					if (m_elmgetter != null) {
						m_elmgetter.m_selectedRow--;
					}
				}
			}
		});
		btnUp.setBounds(405, 6, 73, 21);
		getContentPane().add(btnUp);

		JButton btnDown = new JButton(Messages.getString("PageActionEditor.btnDown.text")); //$NON-NLS-1$
		btnDown.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				//WebElementGetterを閉じる
				if (m_elmgetter != null) {
					m_elmgetter.setVisible(false);
				}

				int i = m_table.getSelectedRow();
				String nextAction = getAction(i + 1);
				if (nextAction != null && nextAction.length() > 0) {
					//選択行を下に移動する。従ない場合は何もしない。
					m_table_model.moveRow(i, i, i + 1);
					m_table.changeSelection(i + 1, 1, false, false);
					if (m_elmgetter != null) {
						m_elmgetter.m_selectedRow++;
					}
				}
			}
		});
		btnDown.setBounds(482, 6, 79, 21);
		getContentPane().add(btnDown);

		JLabel lblMove = new JLabel(Messages.getString("PageActionEditor.lblMove.text")); //$NON-NLS-1$
		lblMove.setBounds(361, 10, 50, 13);
		getContentPane().add(lblMove);

		m_rdbtnParentHide = new JRadioButton(Messages.getString("PageActionEditor.phideRadioButton.text")); //$NON-NLS-1$
		m_rdbtnParentHide.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JDialog t_owner =ArgumentEditor.s_owner;
				Window t_frame = t_owner.getOwner();

				if (m_rdbtnParentHide.isSelected()) {
					m_browser_y = t_frame.getY();
					m_caseeditor_y = t_owner.getY();

					t_frame.setLocation(t_frame.getX(), m_screenOY + 1- t_frame.getHeight());
					t_owner.setLocation(t_owner.getX(), m_screenOY + 1- t_owner.getHeight());
				} else {
					t_frame.setLocation(t_frame.getX(), m_browser_y);
					t_owner.setLocation(t_owner.getX(), m_caseeditor_y);
				}
			}
		});
		m_rdbtnParentHide.setBounds(12, 205, 113, 21);
		getContentPane().add(m_rdbtnParentHide);

		JButton btnAddTemplate = new JButton(Messages.getString("PageActionEditor.btnNewButton.text_2")); //$NON-NLS-1$
		btnAddTemplate.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				setJson();
				if (m_rec.jSON.length() > 0) {
					m_elmgetter.registerTargetFromPopup("com.ftinc.si.assist.test.web.PagePlayer", m_rec.jSON); //$NON-NLS-1$
				}
			}
		});
		btnAddTemplate.setBounds(137, 205, 159, 21);
		getContentPane().add(btnAddTemplate);

		//全スクリーン座標の範囲を取得。マルチディスプレイでも隠せるようにする。
		getScreenRange();

		//テーブルにコンボボックスを設定する。
		initModel();
	}

	private int m_browser_y;
	private int m_caseeditor_y;

	private int m_screenOY;

	//全スクリーン座標の範囲を取得。マルチディスプレイでも隠せるようにする。
	private void getScreenRange() {
		Rectangle vBounds = new Rectangle();
		GraphicsEnvironment g_env = GraphicsEnvironment.getLocalGraphicsEnvironment();
		GraphicsDevice[] gdlist =g_env.getScreenDevices();
		for (int j = 0; j < gdlist.length; j++) {
			GraphicsDevice g_d = gdlist[j];
			GraphicsConfiguration[] g_conf =g_d.getConfigurations();
			for (int i=0; i < g_conf.length; i++) {
				vBounds =vBounds.union(g_conf[i].getBounds());
			}
		}
		m_screenOY = vBounds.y;
	}

	//隠していた親を元に戻す。
	private void resoreParent() {
		JDialog t_owner =ArgumentEditor.s_owner;
		Window t_frame = t_owner.getOwner();

		t_frame.setLocation(t_frame.getX(), m_browser_y);
		t_owner.setLocation(t_owner.getX(), m_caseeditor_y);
	}

	//アクション定義用テーブルの行を追加する
	private void addRow(int r) {
		final Object[] t_data = {"", "", ""}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
		int n = -1;
		if (r < 0 || r == m_table_model.getRowCount() - 1) {
			m_table_model.addRow(t_data);
			n = m_table_model.getRowCount() - 1;
		} else {
			m_table_model.insertRow(r + 1, t_data);
			n = r + 1;
		}
		//アクションの種別が選択されると、いったん、WebElementGetterを閉じるようにする。
		@SuppressWarnings("unchecked")
		JComboBox<String> t_combo = (JComboBox<String>)((DefaultCellEditor)(m_table.getCellEditor(n, 0))).getComponent();
		t_combo.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//WebElementGetterは第二列選択時にのみ表示させたい。
				//そのため、第0列を選択し直したらリセットする。
				m_elmgetter.m_selectedRow = -1;
				m_elmgetter.setVisible(false);
			}
		});

		//自動スクロール。タイミングはイベント処理後
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				final JScrollBar t_scrollBar = m_tableScrollPane.getVerticalScrollBar();
				t_scrollBar.setValue(t_scrollBar.getMaximum());
			}
		});
	}

	//コンボボックスの設定、および、ObjectRecordから情報を読み込んで、Tableを埋める。
	private void initModel() {
		//Actionを選択するコンボボックスを設置
		JComboBox<String> t_actions = new JComboBox<String>();

		t_actions.addItem("LoadURL"); //$NON-NLS-1$
		m_cmap.put("LoadURL", "com.ftinc.si.assist.test.web.LoadURL"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("SendKeys"); //$NON-NLS-1$
		m_cmap.put("SendKeys", "com.ftinc.si.assist.test.web.SendKeys"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("Click"); //$NON-NLS-1$
		m_cmap.put("Click", "com.ftinc.si.assist.test.web.Click"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("Snap"); //$NON-NLS-1$
		m_cmap.put("Snap", "com.ftinc.si.assist.test.web.Snap"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("Reset"); //$NON-NLS-1$
		m_cmap.put("Reset", "com.ftinc.si.assist.test.web.ResetBrowser"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("JQExec"); //$NON-NLS-1$
		m_cmap.put("JQExec", "com.ftinc.si.assist.test.web.JQExec"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("ByHand"); //$NON-NLS-1$
		m_cmap.put("ByHand", "com.ftinc.si.assist.test.web.UseHand"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("ToFrame"); //$NON-NLS-1$
		m_cmap.put("ToFrame", "com.ftinc.si.assist.test.web.ToFrame"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("CheckFor"); //$NON-NLS-1$
		m_cmap.put("CheckFor", "com.ftinc.si.assist.test.web.CheckFor/CheckFor"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("ToWindow"); //$NON-NLS-1$
		m_cmap.put("ToWindow", "com.ftinc.si.assist.test.web.CheckFor/ToWindow"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("Alert"); //$NON-NLS-1$
		m_cmap.put("Alert", "com.ftinc.si.assist.test.web.CheckFor/Alert"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("Prompt"); //$NON-NLS-1$
		m_cmap.put("Prompt", "com.ftinc.si.assist.test.web.Prompt"); //$NON-NLS-1$ //$NON-NLS-2$

		t_actions.addItem("FileUpload"); //$NON-NLS-1$
		m_cmap.put("Prompt", "com.ftinc.si.assist.test.web.FileUpload"); //$NON-NLS-1$ //$NON-NLS-2$

//編集用なのでメニューから追加しないが編集は可能にする。
//		m_cmap.put("SetDB", "com.ftinc.si.assist.test.web.DBSetter"); //$NON-NLS-1$ //$NON-NLS-2$
//		m_cmap.put("TestDB", "com.ftinc.si.assist.test.web.DBGetter"); //$NON-NLS-1$ //$NON-NLS-2$
//		m_cmap.put("Before", "com.ftinc.si.assist.test.web.BeforeAction/Before"); //$NON-NLS-1$ //$NON-NLS-2$
//		m_cmap.put("After", "com.ftinc.si.assist.test.web.AfterAction/After"); //$NON-NLS-1$ //$NON-NLS-2$
		t_actions.addItem("Macro"); //$NON-NLS-1$
		m_cmap.put("Macro", "com.ftinc.si.assist.test.web.MacroActions"); //$NON-NLS-1$ //$NON-NLS-2$

		TableCellEditor cell_combo1 = new DefaultCellEditor(t_actions);
		m_table.getColumnModel().getColumn(0).setCellEditor(cell_combo1);

		//m_rec.jSONからテーブルの状態を復元する。
		if (m_rec.jSON != null && m_rec.jSON.length() > 0) {
			PagePlayer t_play = (PagePlayer)Tool.getObjectfromJSON(PagePlayer.class, m_rec.jSON);

			//★★★★★★Before用ここから★★★★★★★★★
			//事前実行を大域設定から拾い出し、Beforeを復元してActionとして前段に加える。
			HashMap<String, Object> f_map = Tool.getCommentMapFromJson(true, m_rec.jSON);
			int n = 0;
			for (Map.Entry<String, Object> entry: f_map.entrySet()) {
				if (entry.getKey().startsWith("dbset")) { //$NON-NLS-1$
					BeforeAction t_act1 = new BeforeAction();
					//jpathに$/dbset.は不要
					String t_jpath = entry.getKey().replaceFirst("dbset.*?\\$\\.",""); //$NON-NLS-1$ //$NON-NLS-2$
					t_act1.arg_map.put("jpath", t_jpath); //$NON-NLS-1$
					t_act1.arg_map.put("key_value", entry.getValue()); //$NON-NLS-1$
					t_act1.options = "SetDB";
					t_play.actions.add(n, t_act1);
					n++;
				} else if (entry.getKey().matches(("^exec\\sbefore.*$"))) { //$NON-NLS-1$
					//外部プロセス呼び出し
					BeforeAction t_act1 = new BeforeAction();
					t_act1.arg_map.put("jpath", entry.getKey()); //$NON-NLS-1$
					t_act1.arg_map.put("key_value", entry.getValue()); //$NON-NLS-1$
					t_act1.options = "Before";
					t_play.actions.add(n, t_act1);
					n++;
				}
			}
			//★★★★★★Before用ここまで★★★★★★★★★

			//★★★★★★After用ここから★★★★★★★★★
			//DBの事前設定を大域設定から拾い出し、TestDBを復元してActionとして最後尾に加える。
			f_map = Tool.getCommentMapFromJson(true,  m_rec.jSON);
			for (Map.Entry<String, Object> entry: f_map.entrySet()) {
				if (entry.getKey().startsWith("dbtest")) { //$NON-NLS-1$
					AfterAction t_act2 = new AfterAction();
					t_act2.arg_map.put("jpath", entry.getKey().replaceFirst("dbtest.*?\\$\\.","")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						//jpathはカラム指定付でなければならない。
					t_act2.arg_map.put("value", entry.getValue()); //$NON-NLS-1$
					t_act2.options = "TestDB";
					t_play.actions.add(t_act2);
				} else if (entry.getKey().matches(("^exec\\safter.*$"))) { //$NON-NLS-1$
					//外部プロセス呼び出し
					AfterAction t_act1 = new AfterAction();
					t_act1.arg_map.put("jpath", entry.getKey()); //$NON-NLS-1$
					t_act1.arg_map.put("key_value", entry.getValue()); //$NON-NLS-1$
					t_act1.options = "After";
					t_play.actions.add(n, t_act1);
					n++;
				}
			}
			//★★★★★★After用ここまで★★★★★★★★★

			int n_asserting = 0;//現在処理しているAssertingの位置
			for (int i = 0; i < t_play.actions.size(); i++) {
				PageAction t_pact = t_play.actions.get(i);

				//1行追加する。
				addRow(-1);

				//第一列を記入
				String cname = t_pact.options;//初期値としてオプションを入れる。checkforとほとんどの場合は空文字。
				//3番目の条件は、optionsを使っているMacroActionsのアクション名を正しく取得するため。
				if (cname != null && cname.length() > 0 && !cname.startsWith("_")) {
					cname = t_pact.getClass().getName() + "/" + t_pact.options; //$NON-NLS-1$
				} else {
					cname = t_pact.getClass().getName();
				}
				//アクション名をm_cmapから取得する。
				String act_name = getActionFromClass(cname);
				m_table_model.setValueAt(act_name, i, 0);

				//第二列を記入
				String t_targets = t_pact.getJsonElement(null, null);
				m_table_model.setValueAt(t_targets, i, 1);

				//第三列を記入:正規表現
				//　WebTestCommandRecordでWebAssertRecordにアクションの結果を渡すために、アクションと組にしておく。
				if (n_asserting > m_assertings.size()) {
					Tool.alertMSG(null, "# of regular exps not match to assertables."); //$NON-NLS-1$
				} else {
					if (t_pact.assertable() && m_assertings.size() > 0) {
						String str_assert = null;
						if (m_assertings.size() > n_asserting) {
							str_assert = m_assertings.get(n_asserting);
						}
						if (str_assert != null && str_assert.length() > 0) {
							m_table_model.setValueAt(str_assert, i, 2); //$NON-NLS-1$
						}
						n_asserting++;
					}
				}
			}

		} else {
			//とりあえず1行追加する。
			addRow(-1);
		}
	}

	//クラス名からアクション名への逆引き
	private String getActionFromClass(String cname) {
		for(Entry<String, String> e : m_cmap.entrySet()) {
			if (e.getValue().equals(cname)) {
				return e.getKey();
			}
		}
		return null;
	}


	//指定行のPageActionを生成する。テーブルに埋め込む場合、WebElementGetterに引き渡す場合がある。
	protected PageAction getPageAction(int r, String val) {
		//アクションを作る。
		String cname = m_cmap.get(m_table_model.getValueAt(r, 0));
		if (cname == null) {
			return null;
		}
		String[] temp = cname.split("/"); //$NON-NLS-1$
		String t_option = ""; //$NON-NLS-1$
		if (temp.length > 1) {
			cname = temp[0];
			t_option = temp[1];
		}

		try {
			PageAction t_act = (PageAction)Tool.newObject(Tool.forName(cname), new Class[]{}, new Object[]{});
			t_act.options = t_option;

			//テーブルからJsonを作り、t_act内部のmapに移す。
			Fson.updateFromJson(t_act, "{\"arg_map\":{" + val + "}}"); //$NON-NLS-1$ //$NON-NLS-2$
			return t_act;
		} catch (ClassNotFoundException | InvocationTargetException | IllegalAccessException |
				SecurityException | IllegalArgumentException | NoSuchMethodException | InstantiationException e) {
			Tool.alertMSG(null, e.getMessage() + "@getPageAction"); //$NON-NLS-1$
		}
		return null;
	}

	//判定用の正規表現を返す。+別名情報をタブキーの後に追加する。後はWebDriverPluginで処理する。
	protected void setAssertStrings() {
		if (m_assertings != null && m_assertings.size() > 0) {
			String t_regs = "["; //$NON-NLS-1$
			for (int i = 0; m_assertings.size() > i; i++) {
				String t_str = m_assertings.get(i);

				//""が囲んでいるかどうかにかかわらず、結果を同じにする。
				if (t_str.matches("^\".*\"$")) { //$NON-NLS-1$
					t_str = t_str.replaceFirst("^\"(.*)\"$", "$1"); //$NON-NLS-1$ //$NON-NLS-2$
				}
				if (t_regs.length() > 1) {
					t_regs += ","; //$NON-NLS-1$
				}
				t_regs += "\"" + t_str + "\""; //$NON-NLS-1$ //$NON-NLS-2$
			}
			t_regs += "]"; //$NON-NLS-1$
			m_asrec.criteriaRex = t_regs;
			m_asrec.changed();
		}
	}

	//このページに関するアクションの組をJsonにする。
	//WebDriverPluginがAssertRecordにindexNames,AssertNamesを仕込むために、準備をする。
	protected void setJson() {
		String part1_json = "{"; //$NON-NLS-1$
		String part2_json = ""; //$NON-NLS-1$

		m_assertings.clear();
		if (m_table_model.getRowCount() > 0) {
			part2_json += "\"actions\":["; //$NON-NLS-1$
			for (int i = 0; i < m_table_model.getRowCount(); i++) {
				//Assertableであることを確認し、正規表現を集める.
				PageAction t_act = getPageAction(i, ""); //$NON-NLS-1$

				//SetDB,TestDB,Before,Afterは特別扱い。VCentralに格納する。
				if ("SetDB".equals(m_table_model.getValueAt(i, 0))) { //$NON-NLS-1$
					part1_json += "//?dbset \"$." + t_act.arg_map.get("jpath") + "\":{" + t_act.arg_map.get("key_value") + "},\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
				} else if ("TestDB".equals(m_table_model.getValueAt(i, 0))) { //$NON-NLS-1$
					part1_json += "//?dbtest \"$." + t_act.arg_map.get("jpath") + "\":" + Tool.getJSONfromObject(t_act.arg_map.get("value")) + ",\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
				} else if ("Before".equals(m_table_model.getValueAt(i, 0)) || "After".equals(m_table_model.getValueAt(i, 0))) {
					//jpathには特殊コマンドが入っている。key_valueには、実際に起動するコマンドやオプションが入っている。
					part1_json += "//?" + t_act.arg_map.get("jpath") + "\":" + t_act.arg_map.get("key_value") + ",\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
				} else {
					if (i > 0) {
						part2_json += ","; //$NON-NLS-1$
					}

					String t_reg = m_table_model.getValueAt(i, 2).toString();//正規表現
					if (t_reg != null && t_reg.length() > 0) {
						//正規表現を蓄積する。
						if (t_act.assertable()) {
							m_assertings.add(t_reg);
						} else {
							//空の場合、「何でもあり」とする。
							m_assertings.add(".*"); //$NON-NLS-1$
						}
					}
					//行をJSONにする。
					part2_json += makeJsonAt(i, m_table_model.getValueAt(i, 1).toString());
				}
			}
			part2_json += "]"; //$NON-NLS-1$
		}
		part2_json += "}"; //$NON-NLS-1$

		//JSONはこのメソッドを通じるべし。
		m_rec.setJSON(part1_json + part2_json);
	}

	//1行ごとのJSONを作成する。第二引数に実行する文字列を指定するのは、WebElementGetterのpreview機能からも使うため。。
	protected String makeJsonAt(int i, String str) {
		String t_json = ""; //$NON-NLS-1$

		String action_name = (String)m_table_model.getValueAt(i, 0);
		if (action_name != null && action_name.length() > 0) {
			String c_name = m_cmap.get(action_name);
			String[] temp = c_name.split("/"); //$NON-NLS-1$
			String t_option = "";//alert,towindow,checkforの指定（あれば） //$NON-NLS-1$
			if (temp.length > 1) {
				c_name = temp[0];
				t_option = temp[1];
			}

			t_json += "(" + c_name + ")"; //$NON-NLS-1$ //$NON-NLS-2$
			t_json += "{"; //$NON-NLS-1$
			if (str.length() > 0) {
				if (t_option.length() > 0) {
					//ToWindow/Alertの時、optionsが指定される。
					t_json += "\"options\":\"" + t_option + "\","; //$NON-NLS-1$ //$NON-NLS-2$
				}

				//""に囲まれている文字列の中にダブルクォートがある場合に備えてエスケープ処理をする。
				if (str.matches("^.*?\"arg_map\"\\s*:\\s*\\{[\\s\\S]*\\}.*$")) {
					t_json += str; //既に{}なしのJson形式である。
				} else if ("ByHand".equals(action_name) || "Snap".equals(action_name)) { //$NON-NLS-1$
					String t_attr = Fson.escape(str);
					t_json += "\"arg_map\":{\"message\":\"" + t_attr + "\"}"; //$NON-NLS-1$ //$NON-NLS-2$
				} else {
					//ここにくるケースは、エスケープ済み
					t_json += "\"arg_map\":{" + str + "}"; //$NON-NLS-1$ //$NON-NLS-2$
				}

			} else {
				//close,snapは中身が空っぽである。
				t_json += "\"arg_map\":{}"; //$NON-NLS-1$ //$NON-NLS-2$
			}
			t_json += "}"; //$NON-NLS-1$
		} else if (str.length() == 0) {
			Tool.alertMSG(null, Integer.toString(i) + "th row not specified.");; //$NON-NLS-1$
		}
		return t_json;
	}


	/////////////以下、要素取得ダイアログからのみアクセスするメソッドである。
	//引数定義用セルに値を入れる。
	void setArgumentAt(int r, String value, String assertAndIndex) {
		if (m_table.getValueAt(r, 0) != null) {
			m_table_model.setValueAt(value, r, 1);

			if (assertAndIndex != null) {
				m_table_model.setValueAt(assertAndIndex, r, 2);
			}
		}
	}

	int numArgument() {
		int max = 1000;
		int n = 0;
		while (m_table_model.getValueAt(n, 0) != null || max > n) {
			n++;
		}
		return n - 1;
	}

	//引数情報を取得する
	String getArgument(int r) {
		if (m_table.getValueAt(r, 0) != null) {
			return m_table_model.getValueAt(r, 1).toString();
		}
		return null;
	}

	String getAction(int r) {
		return m_table.getValueAt(r, 0).toString();
	}
}
