/*
 * Copyright (c) 2007, Going Dot Com Inc. All rights reserved.
 */

package jp.co.going.xbrl.sample;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

import jp.co.going.xbrl.common.XbException;
import jp.co.going.xbrl.sample.dao.XbDivideMeasureDao;
import jp.co.going.xbrl.sample.dao.XbMeasureDao;
import jp.co.going.xbrl.sample.dao.XbUnitDao;
import jp.co.going.xbrl.sample.dao.XbUnitDivideDao;
import jp.co.going.xbrl.sample.dao.XbUnitMeasureDao;
import jp.co.going.xbrl.sample.dao.obj.XbDivideMeasureObj;
import jp.co.going.xbrl.sample.dao.obj.XbMeasureObj;
import jp.co.going.xbrl.sample.dao.obj.XbUnitDivideObj;
import jp.co.going.xbrl.sample.dao.obj.XbUnitMeasureObj;
import jp.co.going.xbrl.sample.dao.obj.XbUnitObj;

/**
 * @author Masako Okayasu
 */
@SuppressWarnings("serial")
public class XbUnitInput extends XbTreeDataSet implements ActionListener {

	private Connection conn = null;
	private XbUnitDao unitDao = null;
	private XbUnitMeasureDao unitMeasureDao = null;
	private XbUnitDivideDao unitDivideDao = null;
	private XbDivideMeasureDao divideMeasureDao = null;
	private XbMeasureDao measureDao = null;

	private XbMyTreeNode rootNode = new XbMyTreeNode("（登録済リスト）");
	private JButton expButton = new JButton("展開");
	private JRadioButton[] specRadio = new JRadioButton[2];
	private String[] dataList = null;

	private int sampleCount = 1;
	private boolean childFlag = false;
	private boolean idDoneFlag = false;
	private boolean measureDoneFlag = false;
	private boolean numFlag = false;
	private boolean denFlag = false;
	private int menuFlag = 0;

	private int insertFlag = 0;
	private long unitID = 0;
	private long divideID = 0;

	public XbUnitInput(Connection conn, boolean checked) {
		this.conn = conn;

		setTitle("XBRL Toolkit : Input " + UNIT);
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			e.printStackTrace();
		}

		unitDao = XbUnitDao.getInstance(conn);
		unitMeasureDao = XbUnitMeasureDao.getInstance(conn);
		unitDivideDao = XbUnitDivideDao.getInstance(conn);
		divideMeasureDao = XbDivideMeasureDao.getInstance(conn);
		measureDao = XbMeasureDao.getInstance(conn);


		Container container = getContentPane();
		container.setLayout(new BorderLayout());

		JPanel HeaderPanel = HeaderPanel(checked);
		JPanel MainPanel = MainPanel();
		JPanel SubmitPanel = SubmitPanel();

		submitButton.addActionListener(this);
		submitButton.setEnabled(false);
		closeButton.addActionListener(this);

		container.add(HeaderPanel, BorderLayout.NORTH);
		container.add(MainPanel, BorderLayout.CENTER);
		container.add(SubmitPanel, BorderLayout.SOUTH);

		// Measure初期値
		try {
			ArrayList<XbMeasureObj> list = measureDao.selectAll();
			dataList = new String[list.size()];
			for(int i=0; i<list.size(); i++) {
				XbMeasureObj obj = list.get(i);
				dataList[i] = String.valueOf(obj.getMeasure_id()) + ". " + obj.getMeasure_name();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		pack();
	}

	/**
	 * 画面Header欄の生成
	 */
	private JPanel HeaderPanel(boolean checked) {
		JPanel HeaderPanel = new JPanel();
		HeaderPanel.setLayout(new BorderLayout());

		HeaderPanel.add(new JLabel("　【 " + nameList.get(UNIT) + "定義 】　　"), BorderLayout.WEST);

		expButton.addActionListener(this);
		HeaderPanel.add(setPanel(expButton), BorderLayout.CENTER);

		JPanel specPanel = new JPanel();
		specPanel.setLayout(new FlowLayout());

		specRadio[0] = new JRadioButton("Spec2.0", !checked);
		specRadio[0].addActionListener(this);
		specRadio[1] = new JRadioButton("Spec2.1", checked);
		specRadio[1].addActionListener(this);

		ButtonGroup group = new ButtonGroup();
		group.add(specRadio[0]);
		group.add(specRadio[1]);

		specPanel.add(new JLabel("スペック："));
		specPanel.add(specRadio[0]);
		specPanel.add(specRadio[1]);
		HeaderPanel.add(specPanel, BorderLayout.EAST);

		return HeaderPanel;
	}

	/**
	 * Unit入力欄の生成
	 */
	private JPanel MainPanel() {
		JPanel MainPanel = new JPanel();
		MainPanel.setLayout(new BorderLayout());

		if(specRadio[0].isSelected()==true) {
			makeTreeSpec20();
		}
		else if(specRadio[1].isSelected()==true) {
			makeTreeSpec21();
		}

		treeModel = new DefaultTreeModel(rootNode);
		tree = new JTree(treeModel);
		tree.setToggleClickCount(1);
		tree.setSelectionRow(0);
		selectNode = rootNode;

		JScrollPane scroll = new JScrollPane();
		scroll.getViewport().setView(tree);
		scroll.setPreferredSize(new Dimension(400, 300));
		MainPanel.add(scroll, BorderLayout.NORTH);

		JLabel tooltip = new JLabel(TOOLTIP1);
		tooltip.setFont(setFont(11));
		tooltip.setPreferredSize(new Dimension(400, 26));
		MainPanel.add(tooltip, BorderLayout.SOUTH);

		popMenu();
		setMouseAdapter();

		return MainPanel;
	}

	/**
	 * スペック 2.0 仕様で Tree の生成
	 */
	private void makeTreeSpec20() {
		try {
			ArrayList<XbUnitObj> tableData = unitDao.selectAll();
			for(int i=0; i<tableData.size(); i++) {
				XbUnitObj unitObj = tableData.get(i);

				// スペック共通部分
				XbMyTreeNode unitNode = makeTree(unitObj, 20);

				// operator
				ArrayList<XbUnitDivideObj> list2 = unitDivideDao.selectAll(unitObj.getUnit_id());
				for(int j=0; j<list2.size(); j++) {
					XbUnitDivideObj unitDivideObj = list2.get(j);

					String temp = "";
					if(unitDivideObj.getOperator_type()==1) {
						temp = DIVIDE;
					} else {
						temp = MULTIPLY;
					}

					XbMyTreeNode unitDivideNode = new XbMyTreeNode("<" + temp + ">");
					unitNode.add(unitDivideNode);

					XbMyTreeNode tempMeasureNode = new XbMyTreeNode("<" + MEASURE + ">");
					unitDivideNode.add(tempMeasureNode);

					ArrayList<XbDivideMeasureObj> list3 = divideMeasureDao.selectAll(unitDivideObj.getDivide_id());
					for(int k=0; k<list3.size(); k++) {
						XbDivideMeasureObj divideMeasureObj = list3.get(k);

						XbMyTreeNode measureValue = new XbMyTreeNode(divideMeasureObj.getMeasure_name());
						measureValue.setType(MEASURE);
						measureValue.setID(divideMeasureObj.getMeasure_id());
						tempMeasureNode.add(measureValue);
			}	}	}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * スペック 2.1 仕様で Tree の生成
	 */
	private void makeTreeSpec21() {
		try {
			ArrayList<XbUnitObj> tableData = unitDao.selectAll();
			for(int i=0; i<tableData.size(); i++) {
				XbUnitObj unitObj = tableData.get(i);

				// スペック共通部分
				XbMyTreeNode unitNode = makeTree(unitObj, 21);

				// divide
				ArrayList<XbUnitDivideObj> list2 = unitDivideDao.selectAll(unitObj.getUnit_id());
				for(int j=0; j<list2.size(); j++) {
					XbUnitDivideObj unitDivideObj = list2.get(j);
					XbMyTreeNode unitDivideNode = new XbMyTreeNode("<" + DIVIDE + ">");
					unitNode.add(unitDivideNode);

					ArrayList<XbDivideMeasureObj> list3 = divideMeasureDao.selectAll(unitDivideObj.getDivide_id());
					for(int k=0; k<list3.size(); k++) {
						XbDivideMeasureObj divideMeasureObj = list3.get(k);

						String temp = "";
						if(divideMeasureObj.getDivide_type()==1) {
							temp = NUMERATOR;
						} else {
							temp = DENOMINATOR;
						}

						XbMyTreeNode divideMeasureNode = new XbMyTreeNode("<" + temp + ">");
						unitDivideNode.setID(unitDivideObj.getDivide_id());
						unitDivideNode.add(divideMeasureNode);

						XbMyTreeNode tempMeasureNode = new XbMyTreeNode("<" + MEASURE + ">");
						divideMeasureNode.add(tempMeasureNode);

						XbMyTreeNode measureValue = new XbMyTreeNode(divideMeasureObj.getMeasure_name());
						measureValue.setType(MEASURE);
						measureValue.setID(divideMeasureObj.getMeasure_id());
						tempMeasureNode.add(measureValue);
			}	}	}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * スペック共通 Tree の生成
	 */
	private XbMyTreeNode makeTree(XbUnitObj unitObj, int spec) {
		XbMyTreeNode unitNode = null;

		try {
			// ユニット
			unitNode = new XbMyTreeNode("<" + UNIT + ">： " + unitObj.getUnit_name());
			unitNode.setID(unitObj.getUnit_id());
			rootNode.add(unitNode);

			// ユニットID
			if(spec==21 && unitObj.getName() != null && !unitObj.getName().equals("")) {
				XbMyTreeNode unitID = new XbMyTreeNode(UNIT + " ID： " + unitObj.getName());
				unitID.setType(UNIT);
				unitNode.add(unitID);
			}

			// 単位
			ArrayList<XbUnitMeasureObj> list1 = unitMeasureDao.selectAll(unitObj.getUnit_id());
			for(int j=0; j<list1.size(); j++) {
				XbUnitMeasureObj unitMeasureObj = list1.get(j);

				XbMyTreeNode unitMeasureNode = new XbMyTreeNode("<" + MEASURE + ">");
				unitNode.add(unitMeasureNode);

				XbMyTreeNode measureValue = new XbMyTreeNode(unitMeasureObj.getMeasure_name());
				measureValue.setType(MEASURE);
				measureValue.setID(unitMeasureObj.getMeasure_id());
				unitMeasureNode.add(measureValue);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return unitNode;
	}

	/**
	 * 右クリックメニューの生成
	 */
	private void popMenu() {
		popMenu = new JPopupMenu();

		if(menuFlag==0) {
			popMenuItem[0] = new JMenuItem(UNIT + "追加");
			popMenuItem[0].addActionListener(this);
			popMenu.add(popMenuItem[0]);
		}

		if((menuFlag==1 && measureDoneFlag==false)
				|| (specRadio[0].isSelected()==true && menuFlag==3)
				|| menuFlag==4 || menuFlag==5) {
			popMenuItem[1] = new JMenuItem(MEASURE + "追加");
			popMenuItem[1].addActionListener(this);
			popMenu.add(popMenuItem[1]);
		}

		if(menuFlag==1 && measureDoneFlag==false) {
			popMenuItem[2] = new JMenuItem(DIVIDE + "追加");
			popMenuItem[2].addActionListener(this);
			popMenu.add(popMenuItem[2]);
		}

		if(specRadio[0].isSelected()==true) {
			if(menuFlag==1 && measureDoneFlag==false) {
				popMenuItem[3] = new JMenuItem(MULTIPLY + "追加");
				popMenuItem[3].addActionListener(this);
				popMenu.add(popMenuItem[3]);
		}	}

		if(specRadio[1].isSelected()==true) {
			if(menuFlag==3 && numFlag==false) {
				popMenuItem[4] = new JMenuItem(NUMERATOR + "追加");
				popMenuItem[4].addActionListener(this);
				popMenu.add(popMenuItem[4]);
			}

			if(menuFlag==3 && denFlag==false) {
				popMenuItem[5] = new JMenuItem(DENOMINATOR + "追加");
				popMenuItem[5].addActionListener(this);
				popMenu.add(popMenuItem[5]);
			}

			if((menuFlag==1 && idDoneFlag==false) || menuFlag==6) {
				popMenuItem[6] = new JMenuItem(UNIT + " ID名指定");
				popMenuItem[6].addActionListener(this);
				popMenu.add(popMenuItem[6]);
		}	}

		if(menuFlag==2) {
			popMenuItem[7] = new JMenuItem("アイテム指定");
			popMenuItem[7].addActionListener(this);
			popMenu.add(popMenuItem[7]);
		}

		if(menuFlag==1 || menuFlag==9) {
			popMenuItem[8] = new JMenuItem("名前変更");
			popMenuItem[8].addActionListener(this);
			popMenu.add(popMenuItem[8]);
		}

		if(menuFlag != 0) {
			popMenuItem[9] = new JMenuItem("削除");
			popMenuItem[9].addActionListener(this);
			popMenu.add(popMenuItem[9]);
		}
	}

	/**
	 * MouseAdapterの登録
	 */
	private void setMouseAdapter() {
		tree.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				int selectRow = tree.getRowForLocation(e.getX(), e.getY());
				if(selectRow != -1) {
					tree.setSelectionRow(selectRow);
					selectNode = (XbMyTreeNode)tree.getLastSelectedPathComponent();
					selectNodeName = selectNode.getUserObject().toString();

					if(SwingUtilities.isRightMouseButton(e)) {
						if(selectNode == rootNode) {
							menuFlag = 0;
						} else if(selectNodeName.indexOf(" sample") != -1) {
							menuFlag = 9;
						} else if(selectNodeName.indexOf("<" + UNIT + ">： ") != -1) {
							menuFlag = 1;
							for(int i=0; i<selectNode.getChildCount(); i++) {
								String childNodeName = ((XbMyTreeNode)selectNode.getChildAt(i)).getUserObject().toString();
								if(childNodeName.indexOf(UNIT + " ID： ") != -1) {
									idDoneFlag = true;
								} else if(childNodeName.indexOf("<" + MEASURE + ">") != -1
										|| childNodeName.indexOf("<" + DIVIDE + ">") != -1
										|| childNodeName.indexOf("<" + MULTIPLY + ">") != -1) {
									measureDoneFlag = true;
							}	}
						} else if(selectNodeName.indexOf("<" + MEASURE + ">") != -1) {
							menuFlag = 2;
						} else if(selectNodeName.indexOf("<" + DIVIDE + ">") != -1) {
							menuFlag = 3;
							for(int i=0; i<selectNode.getChildCount(); i++) {
								String childNodeName = ((XbMyTreeNode)selectNode.getChildAt(i)).getUserObject().toString();
								if(childNodeName.indexOf("<" + NUMERATOR + ">") != -1) {
									numFlag = true;
								}
								if(childNodeName.indexOf("<" + DENOMINATOR + ">") != -1) {
									denFlag = true;
							}	}
						} else if(selectNodeName.indexOf("<" + MULTIPLY) != -1) {
							menuFlag = 4;
						} else if(selectNodeName.indexOf("<" + NUMERATOR + ">") != -1
								|| selectNodeName.indexOf("<" + DENOMINATOR + ">") != -1) {
							menuFlag = 5;
						} else {
							childFlag = true;
							if(selectNode.getType().equals(MEASURE)) {
								menuFlag = 2;
							} else if(selectNode.getType().equals(UNIT)) {
								menuFlag = 6;
							}
						}
						popMenu();
						popMenu.show(e.getComponent(), e.getX(), e.getY());
		}	}	}	});
	}

	/**
	 * Button, MenuItem のイベントを取得
	 */
	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();

		if(source == specRadio[0]) {
			try {
				if(getNodeValue(rootNode)) {
					if(JOptionPane.showConfirmDialog(this, "更新してよろしいですか？") == JOptionPane.YES_OPTION) {
						conn.commit();
					} else {
						conn.rollback();
				}	}
				rootNode.removeAllChildren();
				makeTreeSpec20();

			} catch (Exception ex) { 
				ex.printStackTrace();
		}	}
		else if(source == specRadio[1]) {
			try {
				if(getNodeValue(rootNode)) {
					if(JOptionPane.showConfirmDialog(this, "更新してよろしいですか？") == JOptionPane.YES_OPTION) {
						conn.commit();
					} else {
						conn.rollback();
				}	}
				rootNode.removeAllChildren();
				makeTreeSpec21();

			} catch (Exception ex) { 
				ex.printStackTrace();
		}	}
		else if(source == popMenuItem[0]) {
			addNode("<" + UNIT + ">： ( sample" + sampleCount + " )");
			sampleCount++;
		}
		else if(source == popMenuItem[1]) {
			addNode("<" + MEASURE + ">");
		}
		else if(source == popMenuItem[2]) {
			addNode("<" + DIVIDE + ">");
		}
		else if(source == popMenuItem[3]) {
			addNode("<" + MULTIPLY + ">");
		}
		else if(source == popMenuItem[4]) {
			addNode("<" + NUMERATOR + ">");
		}
		else if(source == popMenuItem[5]) {
			addNode("<" + DENOMINATOR + ">");
		}
		else if(source == popMenuItem[6]) {
			String defaultdata = "";
			if(childFlag==true)  defaultdata = selectNodeName.substring(selectNodeName.indexOf("： ") + 2);

			Object field = JOptionPane.showInputDialog(this, UNIT + " ID名指定：", "入力", JOptionPane.INFORMATION_MESSAGE, null, null, defaultdata);
			if(field != null && !field.equals("")) {
				String unitID = UNIT + " ID： " + field.toString().trim();

				if(childFlag==true) {
					selectNode.setUserObject(unitID);
				}
				else {
					XbMyTreeNode unitNode = new XbMyTreeNode(unitID);
					unitNode.setType(UNIT);
					selectNode.insert(unitNode, 0);
		}	}	}
		else if(source == popMenuItem[7]) {
			if(setNodeValue(childFlag, dataList, dataList.length>0 ? dataList[0] : null, MEASURE)) {
				submitButton.setEnabled(true);
		}	}
		else if(source == popMenuItem[8]) {
			setNewNodeName();
		}
		else if(source == popMenuItem[9]) {
			if(delNode()) {
				submitButton.setEnabled(true);
		}	}
		else if(source == submitButton) {
			try {
				getNodeValue(rootNode);
				conn.commit();

				JOptionPane.showMessageDialog(this, "データを登録しました。");
				submitButton.setEnabled(false);

			} catch (Exception ex) { 
				ex.printStackTrace();
		}	}
		else if(source == closeButton){
			this.setVisible(false);
		}

		childFlag = false;
		idDoneFlag = false;
		measureDoneFlag = false;
		numFlag = false;
		denFlag = false;

		treeModel.reload();
		tree.expandPath(new TreePath(selectNode));
		tree.setSelectionPath(new TreePath(selectNode.getPath()));
		selectNode = (XbMyTreeNode)tree.getLastSelectedPathComponent();

		if(source == expButton || source == specRadio[0] || source == specRadio[1]) {
			for(int i=0; i<tree.getRowCount(); i++) {
				tree.expandRow(i);
			}
		}
	}

	/**
	 * ノードの値を取得
	 */
	private boolean getNodeValue(XbMyTreeNode Node) {
		boolean rc = false;
		try {
			for(int i=0; i<Node.getChildCount(); i++) {
				XbMyTreeNode childNode = (XbMyTreeNode)Node.getChildAt(i);
				String childNodeName = childNode.getUserObject().toString();

				// Unit登録
				if(childNodeName.indexOf("<" + UNIT + ">： ") != -1) {
					if(childNode.getID() != 0) {
						unitID = 0;
					} else {
						unitID = unitDao.getNextId();
						String unitName = "";

						XbMyTreeNode obj = (XbMyTreeNode)childNode.getChildAt(0);
						if(obj != null && obj.getUserObject().toString().indexOf(UNIT + " ID： ") != -1) {
							String temp = obj.getUserObject().toString();
							unitName = temp.substring(temp.indexOf("： ")+2);
						}

						XbUnitObj unitObj = new XbUnitObj();
						unitObj.setUnit_id(unitID);
						unitObj.setName(unitName);
						unitObj.setUnit_name(childNodeName.substring(childNodeName.indexOf("： ")+2));
						unitObj.setCreation_date(new Date());
						unitDao.insert(unitObj);
						insertFlag = 1;
				}	}

				if(unitID != 0) {
					// Unit - divide 登録
					if(insertFlag==2 || insertFlag==3) {
						XbUnitDivideObj unitDivideObj = new XbUnitDivideObj();
						unitDivideObj.setUnit_id(unitID);
						unitDivideObj.setDivide_id(divideID);
						unitDivideObj.setCreation_date(new Date());

						if(insertFlag==2) {
							unitDivideObj.setOperator_type(operatorType.get(DIVIDE));
						}
						else if(insertFlag==3) {
							unitDivideObj.setOperator_type(operatorType.get(MULTIPLY));
						}
						unitDivideDao.insert(unitDivideObj);
					}

					// measure 登録
					if(insertFlag==6) {
						XbUnitMeasureObj unitMeasureObj = new XbUnitMeasureObj();
						unitMeasureObj.setUnit_id(unitID);
						unitMeasureObj.setMeasure_id(childNode.getID());
						unitMeasureObj.setCreation_date(new Date());
						unitMeasureDao.insert(unitMeasureObj);
						rc = true;
					}

					if((insertFlag >= 7 && insertFlag <= 9) && childNode.getID() != 0) {
						XbDivideMeasureObj divideMeasureObj = new XbDivideMeasureObj();
						divideMeasureObj.setDivide_id(divideID);
						divideMeasureObj.setMeasure_id(childNode.getID());
						divideMeasureObj.setCreation_date(new Date());

						if(insertFlag==7) {
							divideMeasureObj.setDivide_type(0);
						} else if(insertFlag==8) {
							divideMeasureObj.setDivide_type(divideType.get(NUMERATOR));
						} else if(insertFlag==9) {
							divideMeasureObj.setDivide_type(divideType.get(DENOMINATOR));
						}
						divideMeasureDao.insert(divideMeasureObj);
						rc = true;
					}

					// Unit - divide 登録
					if(childNodeName.indexOf("<" + DIVIDE + ">") != -1) {
						divideID = unitDivideDao.getNextId();
						insertFlag = 2;
					}
					if(childNodeName.indexOf("<" + MULTIPLY + ">") != -1) {
						divideID = unitDivideDao.getNextId();
						insertFlag = 3;
					}

					// divide - measure 登録
					if(childNodeName.indexOf("<" + NUMERATOR + ">") != -1) {
						insertFlag = 4;
					}
					if(childNodeName.indexOf("<" + DENOMINATOR + ">") != -1) {
						insertFlag = 5;
					}

					// measure 登録
					if(childNodeName.indexOf("<" + MEASURE + ">") != -1) {
						if(insertFlag==1) {
							insertFlag = 6;		// Unit - measure
						}
						else if(insertFlag==2 || insertFlag==3) {
							insertFlag = 7;		// divide - measure（0:タイプなし）
						}
						else if(insertFlag==4) {
							insertFlag = 8;		// divide - measure（1:Numerator）
						}
						else if(insertFlag==5) {
							insertFlag = 9;		// divide - measure（2:Denominator）
					}	}

					// さらに深部へ
					if(childNode.getChildCount() > 0) {
						rc = getNodeValue(childNode);
					}
			}	}
		} catch (XbException err) {
			try {
				err.printStackTrace();
				conn.rollback();
			}
			catch (Exception ex) {
				ex.printStackTrace();
			}
		} catch (Exception ex) { 
			ex.printStackTrace();
		}
		return rc;
	}
}