package ExV; import javax.swing.*; import javax.swing.event.*; import javax.swing.tree.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.net.*; import java.io.*; public class ExpertPanel extends javax.swing.JPanel implements ActionListener, TreeSelectionListener, TreeExpansionListener, TreeWillExpandListener{ /** Creates new form ExpertPanel */ public ExpertPanel() { initComponents (); } // Variables declaration - do not modify public ExV applet; boolean debug = false; String hostname = null; DatagramSocket socket = null; InetAddress remoteA = null; int remotePort = 9999; Object lastWidget=null; JTree tree, treeOrg; Experts tr; DefaultListModel model, modelORG, orgsModel; MyJList testersList, developersList, orgsList; LoginDetail ld; ModuleDetail md; boolean ignoreEvent = false; PersonChanged personChanged = new PersonChanged (this); OrgChanged orgChanged = new OrgChanged (this); private void initComponents () { setLayout (new java.awt.BorderLayout ()); } public void empty (){ removeNotify(); removeAll(); tr=null; tree=null; treeOrg=null; model.clear(); modelORG.clear(); orgsModel.clear(); testersList=null; developersList=null; orgsList=null; ld=null; md=null; applet=null; } public void actionPerformed (ActionEvent e){ if (ignoreEvent) return; if (e.getSource() instanceof JButton){ String email=((JButton)(e.getSource())) .getText (); if (email .startsWith ("Supervisor: ")){ email = email .substring (12); } String ss [] = new String [1]; ss [0] = email; if (applet != null){ if (email .indexOf ("@") > 0) applet .run ("mailto", ss); else applet .run ("post", ss); } } else { String type = ((MyJComboBox)e.getSource()) .type; String login = (String)(((MyJComboBox)e.getSource()) .getSelectedItem ()); System.out.println (type + ":" + login); ListSelectionEvent el = new ListSelectionEvent (e.getSource(), 0, 0, false); lastWidget = e .getSource (); if (type .equals ("login")){ personChanged (login); } if (type .equals ("org")){ orgChanged (login); } if (type .equals ("module")){ moduleChanged (login); } } } public void record (String type){ if (!debug) return; // send time, action type, widget, and version String res = System .currentTimeMillis() +";"+ type +";"+ lastWidget .getClass () +";"+ 1; System .out .println (res); byte dpbuf [] = res .getBytes (); //for (in i = 0; i < dpbuf1 .length; i++) dpbuf [i] = dpbuf1 [i]; DatagramPacket dp = new DatagramPacket (dpbuf, dpbuf .length, remoteA, remotePort); try { //socket .setSendBufferSize (dp.getLength()); //System .out .println ("buffer size:"+socket .getSendBufferSize()); socket .send (dp); System .out .println ("Sent:"+dp.getLength()); }catch (Exception e){ System.err.println ("Exception:" + e); } } public void orgChanged (String org){ ignoreEvent=true; record ("O;"+org); unselectNodes (); Enumeration en = null; // if org list generated the event select appropriate developers // and testers in dev and test lists ///////////////////////////////////////// //need to get a root node for any data!!! // ModInfo mi = (ModInfo) ((DefaultMutableTreeNode) tr .nodes .get ("/bcfn:0")) .getUserObject(); ModInfo mi = (ModInfo) ((DefaultMutableTreeNode) tr .bcf .getRoot ()) .getUserObject(); ///////////////////////////////////////// //set selections for dev list developersList .clearSelection (); testersList .clearSelection (); int i = 0; Vector v = new Vector (); for (Enumeration ee = model .elements (); ee .hasMoreElements() ; i++){ String hrid = mi .hridForLogin ((new StringTokenizer ((String)(ee .nextElement()), ":")) .nextToken ()); if (hrid != null && tr .hrid2org .get (hrid) != null && ((String) tr .hrid2org .get (hrid)) .compareTo (org) == 0) v .addElement (new Integer (i)); } int sel [] = new int [v .size ()]; for (i =0; i < sel .length; i++) sel [i] = ((Integer)v .elementAt (i)) .intValue (); developersList .setSelectedIndices (sel); //set selections for tester list i = 0; v = new Vector (); for (Enumeration ee = modelORG .elements (); ee .hasMoreElements() ; i++){ String hrid = mi .hridForLogin ((new StringTokenizer ((String)(ee .nextElement()), ":")) .nextToken ()); if (hrid != null && tr .hrid2org .get (hrid) != null && ((String) tr .hrid2org .get (hrid)) .compareTo (org) == 0) v .addElement (new Integer (i)); } sel = new int [v .size ()]; for (i =0; i < sel .length; i++) sel [i] = ((Integer)v .elementAt (i)) .intValue (); testersList .setSelectedIndices (sel); // finally highlight modules based on which org was selected Object oo = tr .org2node .get (org); if(oo != null) for (en = ((Hashtable)oo) .keys (); en .hasMoreElements ();){ Object o = en .nextElement (); if (o != null){ //System.err.println (o); DefaultMutableTreeNode n = (DefaultMutableTreeNode) o; ModInfo mi1 = (ModInfo) n .getUserObject(); mi1 .orgIsSelected = true; mi1 .orgSelected = org; } } // update the org field in the details ld .org .setText (org); repaint (); ignoreEvent=false; return; } private void unselectNodes (){ Enumeration it = null; for (it = tr .nodes .elements ();it .hasMoreElements ();){ ModInfo mi = (ModInfo) ((DefaultMutableTreeNode) it .nextElement ()) .getUserObject(); mi .isSelected = false; mi .orgIsSelected = false; } for (it = tr .nodesOrg .elements ();it .hasMoreElements ();){ ModInfo mi = (ModInfo) ((DefaultMutableTreeNode) it .nextElement ()) .getUserObject(); mi .isSelected = false; mi .orgIsSelected = false; } } public void personChanged (String name){ if (ignoreEvent) return; ignoreEvent=true; record ("P;"+name); // first always unselect all developer or testing nodes unselectNodes (); developersList .selectItem (name); testersList .selectItem (name); //System.err.println ("personChanged1:"+ignoreEvent); ld .login .setText (name + ""); String hrid = (String) tr .login2hrid .get (name); if (hrid != null && hrid .compareTo ("") != 0 && hrid .compareTo ("null") != 0){ if (tr .hrid2name .get (hrid) != null){ StringTokenizer st1 = new StringTokenizer ((String) (tr .hrid2name .get (hrid)), ":"); ld .name .setText (st1.nextToken()); ld .email .setText (st1.nextToken()); ld .org .setText (st1.nextToken()); ld .phone .setText ("ph: " + st1.nextToken()); ld .sid .setText ("Supervisor: "+st1.nextToken()); String desc = st1.nextToken(); //ld .summary .setText (desc .replace ('&','\n')); ld .summary .setText (desc); ld .location .setText (st1.nextToken()); } } { // suspiciously complex Enumeration it = tr .nodes .elements (); for (;it .hasMoreElements ();){ ModInfo mi = (ModInfo) ((DefaultMutableTreeNode) it .nextElement ()) .getUserObject(); if (mi .level == 0){ //ld .ndelta .setText (mi .ndeltaForLogin (name) + ""); ld .login .setText (name + ""); } // if (mi .hridForLogin (name) == null || mi .hridForLogin (name) .compareTo ("null") == 0){ // ld .name .setText ("null"); // ld .email .setText ("null"); // ld .org .setText ("null"); // } else { // if (mi .hridForLogin (name) == null || tr .hrid2name .get (mi .hridForLogin (name)) == null){ // ld .name .setText ("unknown"); // ld .email .setText ("unknown"); // ld .org .setText ("unknown"); // } else { // StringTokenizer st1 = new StringTokenizer ((String)tr .hrid2name .get (mi .hridForLogin (name)), ":"); // ld .name .setText (st1.nextToken()); // ld .email .setText (st1.nextToken()); // ld .org .setText (st1.nextToken()); // } // } } } //System.err.println ("personChanged2:"+ignoreEvent);ignoreEvent=true;// the org selection sets it to false!!! orgsList .selectItem (ld .org .getText ()); //System.err.println ("personChanged3:"+ignoreEvent);ignoreEvent=true;// the org selection sets it to false!!! //select all modules that the developer worked on for the tree nodes Enumeration en = null; // see if the org or developer list was clicked if (lastWidget == testersList){ en = ((Hashtable) (tr .login2nodeOrg .get (name))) .keys (); } else { Hashtable hh= (Hashtable) tr.login2node .get (name); if (hh == null) en = null; else en = hh .keys (); } if (en != null){ for (;en .hasMoreElements ();){ DefaultMutableTreeNode n = (DefaultMutableTreeNode) en .nextElement (); ModInfo mi = ((ModInfo) ((DefaultMutableTreeNode)n) .getUserObject()); mi .isSelected = true; mi .loginSelected = name; } } //System .out. println ("repaint"); repaint (); ignoreEvent=false; } public void moduleChanged (String module){ ignoreEvent=true; String modid = module; record ("M;"+modid); DefaultMutableTreeNode n = (DefaultMutableTreeNode) (tr .nodes .get (modid)); //System.out.println (modid+":"+ n + ":" + tree .getSelectionPath ()); if (n != null) { tree .setSelectionPath (new TreePath (n .getPath ())); ModInfo mi = (ModInfo) ((DefaultMutableTreeNode)n) .getUserObject(); md .ndelta .setText (mi .ndelta +""); md .nLogin .setText (mi .people .length +""); md .level .setText (mi .level +""); md .module .setText (mi .name ()); // first select developers for that module model .clear (); for (int i = 0; i < Math .min(mi .people .length, 700); i++) model .addElement (mi .people[i] .login + ":"+ mi .people[i] .location +":"+ ((mi .people[i] .loginDelta*100/mi .ndelta)/100.)); // now select testers mi = (ModInfo) ((DefaultMutableTreeNode)tr .nodesOrg .get(mi .name ())).getUserObject (); md .nOrgLogin .setText (mi .people .length +""); modelORG .clear (); for (int i = 0; i < mi .people .length; i++) modelORG .addElement (mi .people[i] .login + ":"+ mi .people[i] .location +":"+ ((mi .people[i] .loginDelta*100/mi .ndelta)/100.)); // finally select right organizations orgsModel .clear (); Hashtable tmp = new Hashtable (); Hashtable tmp1 = new Hashtable (); Hashtable tmp2 = new Hashtable (){ public synchronized Object put (Object o, Object a){ if (get (o) == null) return super .put (o, a); else return super .put (o, new Integer (((Integer) a) .intValue ()+ ((Integer)get(o)) .intValue())); } }; // use developers to represent an organizxation mi = (ModInfo) ((DefaultMutableTreeNode)n) .getUserObject(); //System.out.println (mi .name () + ":" + mi .people .length); for (int i = 0; i < mi .people .length; i++){ String org = (String) tr .hrid2org .get (mi .people[i] .hrid); //System.out.println (org + ":" + mi .people[i] .login + ":" + mi .people[i] .hrid); if (org != null){ tmp .put (org, org); int ndel=mi .people [i] .loginDelta; //System.err.println(org+":"+1 +":"+ndel+":"+mi .people[i] .login); if (tmp1 .containsKey (org)) ndel += ((Integer) tmp1 .get (org)) .intValue (); tmp1 .put (org, new Integer (ndel)); } } String organizations [] = new String [tmp .size ()]; int ii = 0; for (Enumeration en = tmp .keys (); en .hasMoreElements ();){ Object o = en .nextElement (); organizations [ii++] = (String) o; } QSort .sort (organizations); for (int i = 0; i < organizations .length; i++){ String o = organizations [i]; double d = ((Integer)tmp1 .get (o)) .doubleValue (); d = d/mi .ndelta; d = d < .01 ? 0 : d; //System.err.println(o+":"+d +":"+mi .ndelta); String dd = d + " "; orgsModel .addElement (o + ":" + dd .substring (0,4)); //System.out.println (o); } } ignoreEvent=false; } /** show developers, testers, and organizations associated with particular module*/ public void valueChanged(TreeSelectionEvent e) { if (e .getPath() .getPathComponent(0) == tr .bcf){ //select right developers TreeNode n = (TreeNode) (e .getPath() .getLastPathComponent()); ModInfo mi = (ModInfo) ((DefaultMutableTreeNode)n) .getUserObject(); md .level .setText (mi .level +""); lastWidget = e .getSource (); if (!ignoreEvent) moduleChanged (mi .name ()); } } public void treeWillExpand (TreeExpansionEvent e){ System.out.println ("wille:"+e); } public void treeWillCollapse (TreeExpansionEvent e){ System.out.println ("willc:"+e); } public void treeExpanded (TreeExpansionEvent e){ //System.out.println (e); //System.out.println ("a:"+e.getPath()); //System.out.println ("b:"+e .getPath() .getLastPathComponent()); TreePath p = e .getPath(); TreeNode n = (TreeNode) p .getLastPathComponent(); TreeNode p0 = n .getParent (); if (p0 == null) return; //System.out.println ("nchildren="+p0 .getChildCount ()); for (int i = 0; i < p0 .getChildCount (); i++){ TreeNode n1 = p0 .getChildAt (i); //System.out.println (i+":"+n1+":"+n+":"+(n1 != n)); if (n1 != n){ TreeNode tpa [] = new TreeNode [2];tpa[0]=p0;tpa[1]=n1; tree .expandPath (new TreePath (tpa)); } } //tree .expandPath ((javax.swing.tree.TreePath) (e .getPath())); } public void treeCollapsed (TreeExpansionEvent e){ //System.out.println (e); //System.out.println ("a1:"+e.getPath()); //System.out.println ("b1:"+e .getPath() .getLastPathComponent()); //tree .collapsePath ((javax.swing.tree.TreePath) (e .getPath())); TreePath p = e .getPath(); TreeNode n = (TreeNode) p .getLastPathComponent(); TreeNode p0 = n .getParent (); if (p0 == null) return; //System.out.println ("nchildren="+p0 .getChildCount ()); for (int i = 0; i < p0 .getChildCount (); i++){ TreeNode n1 = p0 .getChildAt (i); //System.out.println (i+":"+n1+":"+n+":"+(n1 != n)); if (n1 != n){ TreeNode tpa [] = new TreeNode [2]; tpa[0]=p0; tpa[1]=n1; tree .collapsePath (new TreePath (tpa)); } } } public ExpertPanel (TreeCellRenderer renderer, Experts tr, String hostname, boolean debug) { this .debug = debug; this .hostname = hostname; this .tr = tr; GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); //setLayout (gridbag); //setLayout (new BorderLayout ()); setLayout (new GridLayout (1,2)); //sp = new JScrollPane(treeOrg, JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane .HORIZONTAL_SCROLLBAR_AS_NEEDED ); //add(sp, BorderLayout.EAST); // Put list views in a separate pane model = new DefaultListModel (); modelORG = new DefaultListModel (); orgsModel = new DefaultListModel (); JPanel leftContainer = new JPanel (); leftContainer .setLayout (new GridLayout (2, 1)); JPanel listContainer = new JPanel (); listContainer .setLayout (new GridLayout (1, 3)); JScrollPane a = new JScrollPane(testersList = new MyJList (modelORG, true), JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane .HORIZONTAL_SCROLLBAR_AS_NEEDED); a .setColumnHeaderView (new JLabel ("Supervisors")); a .setToolTipText ("Click on a login to see related code and contact detail"); c.fill = GridBagConstraints.BOTH; c.gridheight = 1; c.gridwidth = 1; c.weightx = 1.0; c.weighty = 1.0; c.gridx = 1; gridbag .setConstraints(a, c); //add(a); listContainer .add (a); testersList .addMouseListener (new MyJListMouseAdapter(testersList, this)); testersList .addListSelectionListener (personChanged); a = new JScrollPane(developersList = new MyJList (model, true), JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane .HORIZONTAL_SCROLLBAR_AS_NEEDED); a .setColumnHeaderView (new JLabel ("Developers")); a .setToolTipText ("Click on a login to see changed code and contact detail"); developersList .addListSelectionListener (personChanged); developersList .addMouseListener (new MyJListMouseAdapter(developersList, this)); c.gridx = 2; gridbag .setConstraints(a, c); //add(a); listContainer .add (a); a = new JScrollPane(orgsList = new MyJList (orgsModel, true), JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane .HORIZONTAL_SCROLLBAR_AS_NEEDED); a .setColumnHeaderView (new JLabel ("Organizations")); orgsList .addListSelectionListener (orgChanged); a .setToolTipText ("Click on an org number to see members and changed code."); c.gridx = 3; gridbag .setConstraints(a, c); //add(a); listContainer .add (a); leftContainer .add (listContainer); c.gridwidth = 3; c.gridheight = 1; c.gridx = 1; c.weightx = 1.0; c.weighty = 0.0; md = new ModuleDetail (this); gridbag .setConstraints(md, c); //add (md); ld = new LoginDetail (this); c.gridx = 1; c.gridwidth = 3; gridbag .setConstraints(ld, c); leftContainer .add(ld); //add (leftContainer, "West"); add (leftContainer); // Create tree tree = new JTree(tr .bcf); //treeOrg = new JTree(tr .bcfOrg); //tree .addTreeWillExpandListener (this); //tree .addTreeExpansionListener (this); tree .addTreeSelectionListener (this); // Set line style tree .putClientProperty("JTree.lineStyle", "Angled"); //treeOrg.putClientProperty("JTree.lineStyle", "Angled"); // Change the cell renderer tree .setCellRenderer(renderer); tree .setRowHeight (-1); //treeOrg.setCellRenderer(renderer); ToolTipManager.sharedInstance().registerComponent(tree); tree .addMouseListener(new MyMouseAdapter(this)); // Put tree in a scrollable pane JScrollPane sp = new JScrollPane (); sp .setPreferredSize (new Dimension(300, 400)); sp .getViewport() .add(tree); //JScrollPane sp = new JScrollPane(tree, JScrollPane .VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane .HORIZONTAL_SCROLLBAR_AS_NEEDED ); sp .setColumnHeaderView (new JLabel ("Modules")); sp .setToolTipText ("Click on a module to see organizations, developers, and MR raisers involved"); c.fill = GridBagConstraints.BOTH; c.weightx = 10000; c.weighty = 1.0; c.gridx = 4; c.gridheight = 3; c.gridwidth = GridBagConstraints.REMAINDER; c.gridwidth = 1; gridbag .setConstraints(sp, c); add(sp); //add(sp, "Center"); // now create udp connection to notmafia if (debug && socket == null){ //this is for listening locally //DummyThread dt = new DummyThread (this); //dt .start (); try{ socket = new DatagramSocket (); remoteA = InetAddress .getByName (hostname); } catch (Exception e){ System.err.println (e); } try { byte ss [] = ("init:" + System .currentTimeMillis()) .getBytes (); DatagramPacket dp = new DatagramPacket (ss, ss .length, remoteA, remotePort); socket .send (dp); } catch (IOException e){ System.err.println (e); } } } public void start (String s){ if (!debug) return; try { byte ss [] = ("start:" + System .currentTimeMillis() + ":" + s) .getBytes (); DatagramPacket dp = new DatagramPacket (ss, ss .length, remoteA, remotePort); socket .send (dp); } catch (IOException e){ System.err.println (e); } //for (int i = tree .getRowCount () - 1; i > 0; i--){ tree .expandRow (i);} //tree .collapseRow (0); } public void stop (){ if (!debug) return; try { byte ss [] = ("stop:" + System .currentTimeMillis()) .getBytes (); DatagramPacket dp = new DatagramPacket (ss, ss .length, remoteA, remotePort); socket .send (dp); } catch (IOException e){ System.err.println (e); } } public void destroy (){ if (!debug) return; try { byte ss [] = ("destroy:" + System .currentTimeMillis()) .getBytes (); DatagramPacket dp = new DatagramPacket (ss, ss .length, remoteA, remotePort); socket .send (dp); } catch (IOException e){ System.err.println (e); } } } class MyJListMouseAdapter extends MouseAdapter { public MyJList list; public ExpertPanel ep; MyJListMouseAdapter (MyJList list, ExpertPanel ep){ this .list = list; this .ep = ep; } public void mouseClicked(MouseEvent e) { int index = list .locationToIndex(e.getPoint()); if ((e .getModifiers () & MouseEvent .BUTTON1_MASK) > 0) { System.out.println("left clicked on Item " + index); } else { System.out.println("right clicked on Item " + index); String ss [] = new String [1]; StringTokenizer st = new StringTokenizer ((String)(list .getModel () .getElementAt (index)), ":"); if (st != null){ ss [0] = st .nextToken (); ep .applet .run ("mrs", ss); ep .record ("MR;"+ss[0]); } } } } class MyMouseAdapter extends MouseAdapter { public ExpertPanel ep; MyMouseAdapter (ExpertPanel ep){ this .ep = ep; } public void mouseClicked(MouseEvent e) { int selRow = ep .tree .getRowForLocation(e.getX(), e.getY()); TreePath selPath = ep .tree .getPathForLocation(e.getX(), e.getY()); if(selRow != -1) { if ((e .getModifiers () & MouseEvent .BUTTON1_MASK) > 0) { } else { DefaultMutableTreeNode n = (DefaultMutableTreeNode) (selPath .getLastPathComponent()); //if (n.getChildCount () == 0){ if (ep .applet != null){ ModInfo mi = (ModInfo) n .getUserObject(); System.out.println ("show files:"+mi.getModule ()); String ss [] = new String [1]; ss [0] = mi.getModule (); ep .applet .run ("files", ss); ep .record ("MF;"+ss[0]); } //} } } } } class PersonChanged implements ListSelectionListener { public ExpertPanel ep; PersonChanged (ExpertPanel ep){ this .ep = ep; } public void valueChanged (ListSelectionEvent e) { if (e .getValueIsAdjusting() || ep .ignoreEvent) { //System.err.println (e .getValueIsAdjusting() + ":" + ignoreEvent); return; } //System.err.println ("personChanged:"+e .getSource ()); StringTokenizer st = null; //from developrt and tester list if (e .getSource () instanceof JList){ JList l = (JList) e .getSource (); st = new StringTokenizer ((String)(l .getModel () .getElementAt (l .getSelectedIndex ())), ":"); } // //from login combo box // if (e .getSource () instanceof JComboBox){ // JComboBox l = (JComboBox) e .getSource (); // st = new StringTokenizer ((String)(l .getSelectedItem ()), ":"); // } ep .lastWidget = e .getSource (); System.err.println ("personChanged:"+e .getSource ()); if (st != null) ep .personChanged (st .nextToken ()); } } class OrgChanged implements ListSelectionListener { public ExpertPanel ep; OrgChanged (ExpertPanel ep){ this .ep = ep; } public void valueChanged (ListSelectionEvent e) { if (e .getValueIsAdjusting() || ep .ignoreEvent) { //System.err.println (e .getValueIsAdjusting() + ":" + ignoreEvent); return; } //System.err.println ("orgChanged:"+e .getSource ()); StringTokenizer st = null; //from org list if (e .getSource () instanceof JList){ JList l = (JList) e .getSource (); st = new StringTokenizer ((String)(l .getModel () .getElementAt (l .getSelectedIndex ())), ":"); } // //from login combo box // if (e .getSource () instanceof JComboBox){ // JComboBox l = (JComboBox) e .getSource (); // st = new StringTokenizer ((String)(l .getSelectedItem ()), ":"); // } ep .lastWidget = e .getSource (); if (st != null) ep .orgChanged (st .nextToken ()); } }