All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bboss.org.jgroups.demos.ReplicatedTreeDemo Maven / Gradle / Ivy

The newest version!
// $Id: ReplicatedTreeDemo.java,v 1.9 2008/01/22 10:44:34 belaban Exp $

package bboss.org.jgroups.demos;


import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import bboss.org.jgroups.View;
import bboss.org.jgroups.blocks.ReplicatedTree;


/**
 * Graphical view of a ReplicatedTree
 *
 * @author Bela Ban
 */
public class ReplicatedTreeDemo {


    /**
     * Graphical view of a ReplicatedTree (using the MVC paradigm). An instance of this class needs to be given a
     * reference to the underlying model (ReplicatedTree) and needs to registers as a ReplicatedTreeListener. Changes
     * to the tree structure are propagated from the model to the view (via ReplicatedTreeListener), changes from the
     * GUI (e.g. by a user) are executed on the tree model (which will broadcast the changes to all replicas).

* The view itself caches only the nodes, but doesn't cache any of the data (HashMap) associated with it. When * data needs to be displayed, the underlying tree will be accessed directly. * * @author Bela Ban */ static class ReplicatedTreeView extends JFrame implements WindowListener, ReplicatedTree.ReplicatedTreeListener, TreeSelectionListener, TableModelListener { DefaultTreeModel tree_model=null; JTree jtree=null; final DefaultTableModel table_model=new DefaultTableModel(); final JTable table=new JTable(table_model); final MyNode root=new MyNode(SEP); final String props=null; String selected_node=null; ReplicatedTree tree=null; // the underlying model JPanel tablePanel=null; JMenu operationsMenu=null; JPopupMenu operationsPopup=null; JMenuBar menubar=null; static final String SEP=ReplicatedTree.SEPARATOR; private static final int KEY_COL_WIDTH=20; private static final int VAL_COL_WIDTH=300; public ReplicatedTreeView(ReplicatedTree tree, Object title) throws Exception { this.tree=tree; tree.addReplicatedTreeListener(this); addNotify(); setTitle("ReplicatedTreeDemo: mbr=" + title); tree_model=new DefaultTreeModel(root); jtree=new JTree(tree_model); jtree.setDoubleBuffered(true); jtree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); JScrollPane scroll_pane=new JScrollPane(jtree); populateTree(); getContentPane().add(scroll_pane, BorderLayout.CENTER); addWindowListener(this); table_model.setColumnIdentifiers(new String[]{"Name", "Value"}); table_model.addTableModelListener(this); setTableColumnWidths(); tablePanel=new JPanel(); tablePanel.setLayout(new BorderLayout()); tablePanel.add(table.getTableHeader(), BorderLayout.NORTH); tablePanel.add(table, BorderLayout.CENTER); getContentPane().add(tablePanel, BorderLayout.SOUTH); jtree.addTreeSelectionListener(this);//REVISIT MouseListener ml=new MouseAdapter() { public void mouseClicked(MouseEvent e) { int selRow=jtree.getRowForLocation(e.getX(), e.getY()); TreePath selPath=jtree.getPathForLocation(e.getX(), e.getY()); if(selRow != -1) { selected_node=makeFQN(selPath.getPath()); jtree.setSelectionPath(selPath); if(e.getModifiers() == java.awt.event.InputEvent.BUTTON3_MASK) { operationsPopup.show(e.getComponent(), e.getX(), e.getY()); } } } }; jtree.addMouseListener(ml); createMenus(); setLocation(50, 50); setSize(getInsets().left + getInsets().right + 485, getInsets().top + getInsets().bottom + 367); init(); setVisible(true); } public void windowClosed(WindowEvent event) { } public void windowDeiconified(WindowEvent event) { } public void windowIconified(WindowEvent event) { } public void windowActivated(WindowEvent event) { } public void windowDeactivated(WindowEvent event) { } public void windowOpened(WindowEvent event) { } public void windowClosing(WindowEvent event) { System.exit(0); } public void tableChanged(TableModelEvent evt) { int row, col; String key, val; if(evt.getType() == TableModelEvent.UPDATE) { row=evt.getFirstRow(); col=evt.getColumn(); if(col == 0) { // set() key=(String)table_model.getValueAt(row, col); val=(String)table_model.getValueAt(row, col + 1); if(key != null && val != null) { tree.put(selected_node, key, val); } } else { // add() key=(String)table_model.getValueAt(row, col - 1); val=(String)table.getValueAt(row, col); if(key != null && val != null) { tree.put(selected_node, key, val); } } } } public void valueChanged(TreeSelectionEvent evt) { TreePath path=evt.getPath(); String fqn=SEP; String component_name; HashMap data=null; for(int i=0; i < path.getPathCount(); i++) { component_name=((MyNode)path.getPathComponent(i)).name; if(component_name.equals(SEP)) continue; if(fqn.equals(SEP)) fqn+=component_name; else fqn=fqn + SEP + component_name; } data=getData(tree, fqn); if(data != null) { getContentPane().add(tablePanel, BorderLayout.SOUTH); populateTable(data); validate(); } else { clearTable(); getContentPane().remove(tablePanel); validate(); } } /* ------------------ ReplicatedTree.ReplicatedTreeListener interface ------------ */ public void nodeAdded(String fqn) { MyNode n, p; n=root.add(fqn); if(n != null) { p=(MyNode)n.getParent(); tree_model.reload(p); jtree.scrollPathToVisible(new TreePath(n.getPath())); } } public void nodeRemoved(String fqn) { MyNode n; TreeNode par; n=root.findNode(fqn); if(n != null) { n.removeAllChildren(); par=n.getParent(); n.removeFromParent(); tree_model.reload(par); } } public void nodeModified(String fqn) { // HashMap data; // data=getData(tree, fqn); //populateTable(data); REVISIT /* poulateTable is the current table being shown is the info of the node. that is modified. */ } public void viewChange(View new_view) { Vector mbrship; if(new_view != null && (mbrship=new_view.getMembers()) != null) { tree._put(SEP, "members", mbrship); tree._put(SEP, "coordinator", mbrship.firstElement()); } } /* ---------------- End of ReplicatedTree.ReplicatedTreeListener interface -------- */ /*----------------- Runnable implementation to make View change calles in AWT Thread ---*/ public void run() { } /* ----------------------------- Private Methods ---------------------------------- */ /** * Fetches all data from underlying tree model and display it graphically */ void init() { Vector mbrship=null; addGuiNode(SEP); mbrship=tree != null && tree.getMembers() != null ? (Vector)tree.getMembers().clone() : null; if(mbrship != null) { tree._put(SEP, "members", mbrship); tree._put(SEP, "coordinator", mbrship.firstElement()); } } /** * Fetches all data from underlying tree model and display it graphically */ private void populateTree() { addGuiNode(SEP); } /** * Recursively adds GUI nodes starting from fqn */ void addGuiNode(String fqn) { Set children; String child_name; if(fqn == null) return; // 1 . Add myself root.add(fqn); // 2. Then add my children children=tree.getChildrenNames(fqn); if(children != null) { for(Iterator it=children.iterator(); it.hasNext();) { child_name=(String)it.next(); addGuiNode(fqn + SEP + child_name); } } } String makeFQN(Object[] path) { StringBuilder sb=new StringBuilder(""); String tmp_name; if(path == null) return null; for(int i=0; i < path.length; i++) { tmp_name=((MyNode)path[i]).name; if(tmp_name.equals(SEP)) continue; else sb.append(SEP + tmp_name); } tmp_name=sb.toString(); if(tmp_name.length() == 0) return SEP; else return tmp_name; } void clearTable() { int num_rows=table.getRowCount(); if(num_rows > 0) { for(int i=0; i < num_rows; i++) table_model.removeRow(0); table_model.fireTableRowsDeleted(0, num_rows - 1); repaint(); } } void populateTable(HashMap data) { String key, strval=""; Object val; int num_rows=0; Map.Entry entry; if(data == null) return; num_rows=data.size(); clearTable(); if(num_rows > 0) { for(Iterator it=data.entrySet().iterator(); it.hasNext();) { entry=(Map.Entry)it.next(); key=(String)entry.getKey(); val=entry.getValue(); if(val != null) strval=val.toString(); table_model.addRow(new Object[]{key, strval}); } table_model.fireTableRowsInserted(0, num_rows - 1); validate(); } } private void setTableColumnWidths() { table.sizeColumnsToFit(JTable.AUTO_RESIZE_NEXT_COLUMN); TableColumn column=null; column=table.getColumnModel().getColumn(0); column.setMinWidth(KEY_COL_WIDTH); column.setPreferredWidth(KEY_COL_WIDTH); column=table.getColumnModel().getColumn(1); column.setPreferredWidth(VAL_COL_WIDTH); } private void createMenus() { menubar=new JMenuBar(); operationsMenu=new JMenu("Operations"); AddNodeAction addNode=new AddNodeAction(); addNode.putValue(AbstractAction.NAME, "Add to this node"); RemoveNodeAction removeNode=new RemoveNodeAction(); removeNode.putValue(AbstractAction.NAME, "Remove this node"); AddModifyDataForNodeAction addModAction=new AddModifyDataForNodeAction(); addModAction.putValue(AbstractAction.NAME, "Add/Modify data"); ExitAction exitAction=new ExitAction(); exitAction.putValue(AbstractAction.NAME, "Exit"); operationsMenu.add(addNode); operationsMenu.add(removeNode); operationsMenu.add(addModAction); operationsMenu.add(exitAction); menubar.add(operationsMenu); setJMenuBar(menubar); operationsPopup=new JPopupMenu(); operationsPopup.add(addNode); operationsPopup.add(removeNode); operationsPopup.add(addModAction); } HashMap getData(ReplicatedTree tree, String fqn) { HashMap data; Set keys; String key; Object value; if(tree == null || fqn == null) return null; keys=tree.getKeys(fqn); if(keys == null) return null; data=new HashMap(); for(Iterator it=keys.iterator(); it.hasNext();) { key=(String)it.next(); value=tree.get(fqn, key); if(value != null) data.put(key, value); } return data; } /* -------------------------- End of Private Methods ------------------------------ */ /*----------------------- Actions ---------------------------*/ class ExitAction extends AbstractAction { public void actionPerformed(ActionEvent e) { System.exit(0); } } class AddNodeAction extends AbstractAction { public void actionPerformed(ActionEvent e) { JTextField fqnTextField=new JTextField(); if(selected_node != null) fqnTextField.setText(selected_node); Object[] information={"Enter fully qualified name", fqnTextField}; final String btnString1="OK"; final String btnString2="Cancel"; Object[] options={btnString1, btnString2}; int userChoice=JOptionPane.showOptionDialog(null, information, "Add Node", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]); if(userChoice == 0) { String userInput=fqnTextField.getText(); tree.put(userInput, null); } } } class RemoveNodeAction extends AbstractAction { public void actionPerformed(ActionEvent e) { tree.remove(selected_node); } } class AddModifyDataForNodeAction extends AbstractAction { public void actionPerformed(ActionEvent e) { HashMap data=getData(tree, selected_node); if(data != null) { } else { clearTable(); data=new HashMap(); data.put("Add Key", "Add Value"); } populateTable(data); getContentPane().add(tablePanel, BorderLayout.SOUTH); validate(); } } // public static void main(String args[]) { // ReplicatedTree tree; // // for(int i=0; i < args.length; i++) { // if(args[i].equals("-help")) { // System.out.println("ReplicatedTreeView [-help]"); // return; // } // } // // try { // tree=new ReplicatedTree(null); // tree.setRemoteCalls(false); // HashMap map=new HashMap(); // map.put("name", "Framework"); // map.put("pid", new Integer(322649)); // tree.put("/federations/fed1/servers/Framework", map); // tree.put("/federations/fed1/servers/Security", null); // // // demo.setVisible(true); // new ReplicatedTreeView(tree, ""); // // tree.put("/federations/fed1/servers/Security/components/RuntimeMonitor", null); // tree.put("/federations/fed1/servers/fenics", null); // // // } // catch(Exception ex) { // ex.printStackTrace(System.err); // } // } class MyNode extends DefaultMutableTreeNode { String name=""; MyNode(String name) { this.name=name; } /** * Adds a new node to the view. Intermediary nodes will be created if they don't yet exist. * Returns the first node that was created or null if node already existed */ public MyNode add(String fqn) { MyNode curr, n, ret=null; StringTokenizer tok; String child_name; if(fqn == null) return null; curr=this; tok=new StringTokenizer(fqn, ReplicatedTreeView.SEP); while(tok.hasMoreTokens()) { child_name=tok.nextToken(); n=curr.findChild(child_name); if(n == null) { n=new MyNode(child_name); if(ret == null) ret=n; curr.add(n); } curr=n; } return ret; } /** * Removes a node from the view. Child nodes will be removed as well */ public void remove(String fqn) { removeFromParent(); } MyNode findNode(String fqn) { MyNode curr, n; StringTokenizer tok; String child_name; if(fqn == null) return null; curr=this; tok=new StringTokenizer(fqn, ReplicatedTreeView.SEP); while(tok.hasMoreTokens()) { child_name=tok.nextToken(); n=curr.findChild(child_name); if(n == null) return null; curr=n; } return curr; } MyNode findChild(String relative_name) { MyNode child; if(relative_name == null || getChildCount() == 0) return null; for(int i=0; i < getChildCount(); i++) { child=(MyNode)getChildAt(i); if(child.name == null) { continue; } if(child.name.equals(relative_name)) return child; } return null; } String print(int indent) { StringBuilder sb=new StringBuilder(); for(int i=0; i < indent; i++) sb.append(' '); if(!isRoot()) { if(name == null) sb.append("/"); else { sb.append(ReplicatedTreeView.SEP + name); } } sb.append('\n'); if(getChildCount() > 0) { if(isRoot()) indent=0; else indent+=4; for(int i=0; i < getChildCount(); i++) sb.append(((MyNode)getChildAt(i)).print(indent)); } return sb.toString(); } public String toString() { return name; } } } public static void main(String args[]) { ReplicatedTree tree; String start_directory=null; boolean jmx=false; String props="udp.xml"; for(int i=0; i < args.length; i++) { if("-props".equals(args[i])) { props=args[++i]; continue; } if("-start_directory".equals(args[i])) { start_directory=args[++i]; continue; } if("-jmx".equals(args[i])) { jmx=true; continue; } help(); return; } try { tree=new ReplicatedTree("ReplicatedTreeDemo-Group", props, 10000, jmx); new ReplicatedTreeView(tree, tree.getLocalAddress()); // demo.setVisible(true); if(start_directory != null && start_directory.length() > 0) { populateTree(tree, start_directory); } else { /* HashMap map=new HashMap(); map.put("name", "Framework"); map.put("pid", new Integer(322649)); tree.put("/federations/fed1/servers/Framework", map); tree.put("/federations/fed1/servers/Security", null); tree.put("/federations/fed1/servers/Security/components/RuntimeMonitor", null); tree.put("/federations/fed1/servers/fenics", null); */ } } catch(Exception ex) { ex.printStackTrace(System.err); } } static void help() { System.out.println("ReplicatedTreeView [-help] " + "[-props ] [-start_directory ] [-jmx]"); } static void populateTree(ReplicatedTree tree, String dir) { File file=new File(dir); if(!file.exists()) return; tree.put(dir, null); if(file.isDirectory()) { String[] children=file.list(); if(children != null && children.length > 0) { for(int i=0; i < children.length; i++) populateTree(tree, dir + '/' + children[i]); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy