/*************************************************************************** * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration) * and Cosylab 2002, All rights reserved * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package com.cosylab.cdb.browser; import java.awt.Color; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.List; import java.util.Map.Entry; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.swing.JOptionPane; import javax.swing.JTabbedPane; import javax.swing.JTextArea; import javax.swing.JTree; import javax.swing.event.TreeExpansionEvent; import javax.swing.event.TreeExpansionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreePath; import com.cosylab.CDB.DAL; import com.cosylab.CDB.JDAL; import com.cosylab.CDB.JDALHelper; import com.cosylab.CDB.WDAL; import com.cosylab.CDB.WDALHelper; import alma.acs.util.ACSPorts; import alma.cdbErrType.CDBRecordIsReadOnlyEx; class CDBLogic implements TreeSelectionListener, TreeExpansionListener, KeyListener { /** * The CDB tree. */ static JTree CDBTree = null; /** * Instance of the DAL server. */ private static DAL dal; /** * Reference to writable DAL interface if it is implemented by DAL */ private static WDAL wdal = null; /** * Reference to JDAL interface if it is implemented by DAL */ private static JDAL jdal = null; /** * The string is used as a key for the hashMaps used to store the components. * String is the full tree paht of the component. * (set in BrowserJNDIContext & BrowserJNDIXMLContext). */ private static String hashMapKey; /** * Stores the original XML String how it is before the user starts editing */ private static String originalXMLString = null; /** * Boolean that tells if the XML string has been edited. */ public static boolean XMLStringChanged = false; /** * The name of the first table column. */ static final String titleCol1 = "ATTRIBUTE NAME"; /** * The name of the second table column. */ static final String titleCol2 = "ATTRIBUTE VALUE"; /** * The prefix added to each curl */ static final String rootPrefix = "/root"; /** * The index of the tab containing the Table. */ static final int tableIndex = 0; /** * The index of the tab containing the XML String. */ static final int xmlIndex = 1; //private static boolean valueChangedEvent = true; /** * Boolean that tells id the table has been edited. */ static boolean tableChanged = false; /** * Boolean that tells if a tabbed pane has a table tab. * If false -> no table view available. */ private static boolean tableIndexEnabled = false; /** * Boolean that tells if a tabbed pane has a XML tab. * If false -> no XML View. */ static boolean XMLIndexEnabled = false; /** * HashMap that stored the tabbed panes (JTebbedPane). */ static HashMap tabbedPanes = new HashMap(); /** * HashMap that stores the tables (CDBTable). */ static HashMap<String, CDBTable> tables = new HashMap<String, CDBTable>(); /** * HashMap that stores the table models (CDBTableModel) */ static HashMap<String, CDBTableModel> tableModels = new HashMap<String, CDBTableModel>(); /** * HashMap that stores the XML components (JTextArea). */ static HashMap xmls = new HashMap(); /** * The currently selected tabbed pane (can be null). */ static JTabbedPane selectedTabbedPane; /** * The currently selected XML component (can be null). */ static JTextArea selectedXMLArea; /** * The currently selected table component (can be null). */ static CDBTable selectedTable; /** * The currently selected table model (can be null). */ static CDBTableModel selectedTableModel; /** * Create the CDB Tree. */ public static JTree setUpCDBTree(String strIOR){ Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.cosylab.cdb.browser.BrowserJNDIContextFactory"); if(strIOR == null) { env.put(Context.PROVIDER_URL, "corbaloc::" + ACSPorts.getIP() + ":" + ACSPorts.getCDBPort() + "/CDB"); } else env.put(Context.PROVIDER_URL, strIOR); Context context = null; try{ context = new InitialContext(env); }catch(NamingException e) { e.printStackTrace(); } if(context == null) { return null; } // create Tree with the given context CDBTree = new JTree(new com.cosylab.cdb.CDBTreeNode("root",null,context)); CDBTree.addTreeSelectionListener(new CDBLogic()); CDBTree.addTreeExpansionListener(new CDBLogic()); CDBTree.setToggleClickCount(1); return CDBTree; } /** * Set the DAL server. */ public static void setDAL(DAL dal){ CDBLogic.dal = dal; // check if it is writable DAL try { wdal = WDALHelper.narrow(dal); } catch(Exception e) { // no op } // check if it is writable DAL try { jdal = JDALHelper.narrow(dal); } catch(Exception e) { // no op } } /** * Sets the key of all hash maps used to store the data. * @param key the unique key of the next entry to be stored. */ public static void setKey(String key){ hashMapKey = "/root" + key; } /** * Get the current key. * @return the current key. */ public static String getKey(){ return hashMapKey; } /** * Creates a two dimensional array used to create the tables data. * * @param attributes * the data of the table. */ public static Object[][] getData(LinkedHashMap<String, Object> attributes) { if (!attributes.isEmpty()) {// && attributes != null){ // Sort attributes into alphabetical order, see http://jira.alma.cl/browse/COMP-4841 List<Entry<String, Object>> attributesList = new ArrayList<Entry<String, Object>>(attributes.entrySet()); Comparator<Entry<String, Object>> compa = new Comparator<Entry<String, Object>>() { @Override public int compare(Entry<String, Object> e1, Entry<String, Object> e2) { return ( e1.getKey().compareToIgnoreCase(e2.getKey()) ); } }; Collections.sort(attributesList, compa); Object data[][] = new Object[attributesList.size()][2]; int i = 0; for (Entry<String, Object> entry : attributesList) { data[i][0] = entry.getKey(); data[i][1] = entry.getValue(); i++; } return data; } return null; } /** * Called whenever an item in the tree has been expanded. * @param event the event that characterizes the change. */ public void treeExpanded(TreeExpansionEvent event){ TreePath tp = event.getPath(); String path = stringPath(tp); CDBTree.setSelectionPath(tp); } /** * Called whenever an item in the tree has been collapsed. * @param event the event that characterizes the change. */ public void treeCollapsed(TreeExpansionEvent event){ TreePath tp = event.getPath(); String path = stringPath(tp); CDBTree.setSelectionPath(tp); } /** * Called whenever the value of the selection changes. * @param event the event that characterizes the change. */ public void valueChanged(TreeSelectionEvent event){ TreePath tp = event.getPath(); String path = stringPath(tp); Browser.getInstance().setPath(path); //Browser.getInstance().display("MESSAGE: Selected node: " + tp.toString() + ".",true); // check that selected node has a corresponding tabbed pane if(tabbedPanes.containsKey(path)){ // update selected components selectedTable = tables.get(path); selectedTableModel = tableModels.get(path); selectedXMLArea = (JTextArea)xmls.get(path); selectedTabbedPane = (JTabbedPane)tabbedPanes.get(path); // set selected tabbedPane Browser.getInstance().setRightComp(selectedTabbedPane,true); } else{ //Browser.getInstance().display(" No tabbed pane available for this node", false); // set selected components selectedTabbedPane = null; selectedTable = null; selectedTableModel = null; selectedXMLArea = null; // set an emty text area JTextArea empty = new JTextArea(); empty.setBackground(Color.LIGHT_GRAY); empty.setEditable(false); Browser.getInstance().setRightComp(empty,false); } } /** * Send the XML String for validation. */ public static void saveXMLString(boolean ok){ if(XMLStringChanged){ // Get XML String that has to be validated String newXMLString = selectedXMLArea.getText(); // Validation was suesfully. if(ok){ // -> DV if(wdal != null) { String curl = CDBLogic.getKey().substring(rootPrefix.length()); try { Browser.getInstance().display("Invoking set_DAO for " + curl, true); wdal.set_DAO(curl, newXMLString); ok = true; }catch (CDBRecordIsReadOnlyEx e){ e.printStackTrace(); Browser.getInstance().display("==> ERROR MESSAGE: The file or record is read only: " + e, true); }catch (Exception e) { e.printStackTrace(); Browser.getInstance().display("==> ERROR MESSAGE: Exception while saving changes " + e, true); } } // <- // update components?? Browser.getInstance().enableButtons(false); CDBTree.setEnabled(true); if(tableIndexEnabled){ selectedTabbedPane.setEnabledAt(tableIndex,true); tableIndexEnabled = false; } originalXMLString = null; } // Validation failed. if(!ok){ Browser.getInstance().display("==> ERROR MESSAGE: Validation function under development. ",true); // Reset XML String to its original value. selectedXMLArea.setText(originalXMLString); originalXMLString = null; Browser.getInstance().enableButtons(false); CDBTree.setEnabled(true); if(tableIndexEnabled){ selectedTabbedPane.setEnabledAt(tableIndex,true); tableIndexEnabled = false; } Browser.getInstance().display("XML string is reset to its original value.",false); } XMLStringChanged = false; } } /** * Reset the XML String of the selected tabbed pane to its original value * No interaction with jDAL needed. */ public static void resetXMLString(){ if(XMLStringChanged){ Browser.getInstance().display("MESSAGE: Resetting XML string for node " + Browser.getInstance().getPath() + ". ",true); selectedXMLArea.setText(originalXMLString); originalXMLString = null; Browser.getInstance().enableButtons(false); CDBTree.setEnabled(true); if(tableIndexEnabled){ selectedTabbedPane.setEnabledAt(tableIndex,true); tableIndexEnabled = false; } //Browser.getInstance().display("Enable CDBTree & disable buttons.",false); XMLStringChanged = false; } } public static void resetTable(){ if(tableChanged){ Browser.getInstance().display("MESSAGE: Resetting values for table " + Browser.getInstance().getPath() + ". ",true); selectedTableModel.resetValues(); Browser.getInstance().enableButtons(false); CDBTree.setEnabled(true); if(XMLIndexEnabled){ selectedTabbedPane.setEnabledAt(xmlIndex,true); XMLIndexEnabled = false; } tableChanged = false; selectedTable.emptyArray(); } } public static void saveTable(){ if(tableChanged){ Browser.getInstance().display("MESSAGE: Saving values for table " + Browser.getInstance().getPath() + ". ",true); // -> DV added try { // compose short xml of changed fields and send it to the WDAL boolean isNode = XMLIndexEnabled; // we must find node for DAL since we can be inside inner element i.e. MOUNT/current String currentPath = CDBLogic.getKey(); String curl = CDBLogic.getKey(); while(CDBLogic.xmls.get(curl) == null) { curl = curl.substring(0, curl.lastIndexOf('/')); } // TODO find better way for curl finding // TODO BUG CDBLogic.getKey() must be used because maps are filled with it but it is not synchronized // with Browser.getInstance().getPath() String elementName; if(!currentPath.equals(curl)) // in cases when we have element which is not a node i.e. 'current' inside 'TEST_PS_1' then we strip elementName elementName = currentPath.substring(curl.length()+1); else elementName = ""; curl = curl.substring("/root/".length()); System.out.println("curl=" + curl + " elem=" + elementName); // // send changed values to the WDAL StringWriter sw = new StringWriter(); sw.write("<?xml version='1.0' encoding='ISO-8859-1'?>\n"); sw.write("<curl "); if(elementName.length() >0) sw.write("><" + elementName +" "); for (int i = 0; i < selectedTableModel.getRowCount(); i++) { if (selectedTableModel.resetValue.get(new Integer(i)) != null) { System.out.println(XMLIndexEnabled + " " + Browser.getInstance().getPath() + " changed is " + selectedTableModel.getValueAt(i,0) + "=" + selectedTableModel.getValueAt(i,1)); sw.write(selectedTableModel.getValueAt(i,0) + "=\"" + selectedTableModel.getValueAt(i,1) + "\" "); } } if(elementName.length() >0) sw.write("/></curl>"); else sw.write("/>"); if(wdal != null) { Browser.getInstance().display("Invoking set_DAO for " + curl, true); wdal.set_DAO(curl, sw.toString()); } }catch (CDBRecordIsReadOnlyEx e){ e.printStackTrace(); Browser.getInstance().display("==> ERROR MESSAGE: The file or record is read only: " + e, true); } catch (Exception e) { e.printStackTrace(); Browser.getInstance().display("==> ERROR MESSAGE: Exception while saving changes " + e, true); } // <- Browser.getInstance().enableButtons(false); CDBTree.setEnabled(true); if(XMLIndexEnabled){ selectedTabbedPane.setEnabledAt(xmlIndex,true); XMLIndexEnabled = false; } tableChanged = false; selectedTable.emptyArray(); } } /** * Add a key listener to the XML text Area. */ public static void addListener(JTextArea XMLArea){ XMLArea.addKeyListener(new CDBLogic()); } /** * Invoked when a key has been pressed (inside a XML text area). */ public void keyPressed(KeyEvent e){ if(e.getSource() == selectedXMLArea){ if(XMLStringChanged == false){ originalXMLString = selectedXMLArea.getText(); Browser.getInstance().display("MESSAGE: Editing XML string for node: " + Browser.getInstance().getPath() ,true); CDBTree.setEnabled(false); if(selectedTabbedPane.isEnabledAt(tableIndex)){ tableIndexEnabled = true; // disable the table index selectedTabbedPane.setEnabledAt(tableIndex,false); } Browser.getInstance().enableButtons(true); XMLStringChanged = true; Browser.getInstance().display(". To enable CDBTree save or reset changes made.",false); } } } /** * Invoked when a key has been released. */ public void keyReleased(KeyEvent e){} /** * Invoked when a key has been typed. */ public void keyTyped(KeyEvent e){} /** * Checks if any XML tab is selected. * @return true if XML tab is selected, false otherwise */ public static boolean isXMLTabSelected(){ if(selectedTabbedPane == null){ return false; } if(selectedTabbedPane.getSelectedIndex() == xmlIndex){ return true; } else return false; } /** * */ public static void clearCache(){ if(jdal != null){ jdal.clear_cache_all(); Browser.getInstance().display("MESSAGE: Clear Cache executed sucessfully", true); }else{ Browser.getInstance().display("==> ERROR MESSAGE: Clear Cache was not executed.", true); } } /** * Return a String representation of the selected path. * @param tp the selected Tree Path */ public static String stringPath(TreePath tp){ Object [] p = tp.getPath(); String path = ""; for(int i = 0; i < tp.getPathCount(); i ++){ path = path + "/" + (String)p[i].toString(); } return path; } /** * remove all elements inside HashMaps. */ public static void clearHashMaps(){ tabbedPanes.clear(); tables.clear(); tableModels.clear(); xmls.clear(); selectedTabbedPane = null; selectedTable = null; selectedTableModel = null; selectedXMLArea = null; } public static String getCurl() { if(CDBLogic.getKey() == null) return ""; return CDBLogic.getKey().substring(rootPrefix.length()); } /** * */ public static void addNode() { // if we have writable interface if(wdal == null) { Browser.getInstance().display("==> ERROR MESSAGE: Unable to narrow writable DAL server ", true); return; } String curl = getCurl(); CDBAddNodeDlg dlg = new CDBAddNodeDlg(Browser.getInstance()); dlg.setCurl(curl+"/"); dlg.setXML("<?xml version='1.0' encoding='ISO-8859-1'?>\n<Node>\n</Node>"); if(dlg.showModal() != JOptionPane.OK_OPTION) return; System.out.println("Dialog showed " + dlg.getCurl() + " -> " + dlg.getXML()); // try to add node try { wdal.add_node(dlg.getCurl(), dlg.getXML()); } catch(Exception e ) { Browser.getInstance().display("==> ERROR MESSAGE: Error while trying to add node " + curl + " : " + e, true); } } /** * */ public static void deleteNode() { // if we have writable interface if(wdal == null) { Browser.getInstance().display("==> ERROR MESSAGE: Unable to narrow writable DAL server ", true); return; } // ask to be sure String curl = getCurl(); int retVal = JOptionPane.showConfirmDialog(Browser.getInstance(), "Are you sure you want to delete node " + curl + "?", "Delete node", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if(retVal != JOptionPane.YES_OPTION ) return; // try to delete it try { wdal.remove_node(curl); } catch(Exception e ) { Browser.getInstance().display("==> ERROR MESSAGE: Error while trying to delete node " + curl + " : " + e, true); } } }