1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package jgroup.experiment.gui.views.helpers;
20
21 import java.awt.Color;
22 import java.awt.GridBagConstraints;
23 import java.awt.GridBagLayout;
24 import java.awt.event.ActionEvent;
25 import java.awt.event.ActionListener;
26 import java.text.ParseException;
27 import java.util.Enumeration;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.TreeMap;
31 import java.util.TreeSet;
32
33 import javax.swing.BorderFactory;
34 import javax.swing.Box;
35 import javax.swing.BoxLayout;
36 import javax.swing.JButton;
37 import javax.swing.JFormattedTextField;
38 import javax.swing.JLabel;
39 import javax.swing.JOptionPane;
40 import javax.swing.JPanel;
41 import javax.swing.JScrollPane;
42 import javax.swing.JTabbedPane;
43 import javax.swing.JTextField;
44 import javax.swing.JTree;
45 import javax.swing.ScrollPaneConstants;
46 import javax.swing.event.TreeSelectionEvent;
47 import javax.swing.event.TreeSelectionListener;
48 import javax.swing.text.MaskFormatter;
49 import javax.swing.text.NumberFormatter;
50 import javax.swing.tree.DefaultMutableTreeNode;
51 import javax.swing.tree.DefaultTreeModel;
52 import javax.swing.tree.TreePath;
53 import javax.swing.tree.TreeSelectionModel;
54
55 import jgroup.relacs.config.Domain;
56 import jgroup.relacs.config.ExperimentConfig;
57 import jgroup.relacs.config.Host;
58
59 import org.w3c.dom.Document;
60 import org.w3c.dom.Element;
61
62
63
64
65 public class HostPanelManager
66 implements PanelManager
67 {
68
69
70
71
72 private static final String SERVER_TYPE = "Servers";
73 private static final String CLIENT_TYPE = "Clients";
74
75
76
77
78
79
80
81 private JPanel hostPanel = null;
82
83 private JLabel domainNameLabel;
84 private JLabel domainAddressLabel;
85 private JLabel domainPortLabel;
86 private JLabel hostNameLabel;
87 private JLabel hostPortLabel;
88 private JTextField domainNameField;
89 private JFormattedTextField domainAddressField;
90 private JFormattedTextField domainPortField;
91 private JTextField hostNameField;
92 private JFormattedTextField hostPortField;
93 private JPanel settingsPanel;
94
95 private JTree hostsTree;
96 private DefaultMutableTreeNode rootNode;
97 private DefaultTreeModel treeModel;
98 private JButton changeButton;
99 private JButton addButton;
100 private JButton removeButton;
101 private JButton clearButton;
102 private JPanel buttonPanel;
103
104
105
106
107
108
109 private String hostType;
110
111
112
113
114
115
116 public HostPanelManager(JPanel parentPanel)
117 {
118 hostPanel = parentPanel;
119 }
120
121
122
123
124
125
126 public void makePanel()
127 {
128
129
130 JTabbedPane tabs = (JTabbedPane) hostPanel.getParent();
131 int index = tabs.indexOfComponent(hostPanel);
132 hostType = tabs.getTitleAt(index);
133
134
135
136 domainNameLabel = new JLabel("Domain name:");
137 domainAddressLabel = new JLabel("Domain address:");
138 domainPortLabel = new JLabel("Domain port:");
139 hostNameLabel = new JLabel(hostType + " name:");
140 hostPortLabel = new JLabel(hostType + " port:");
141
142 domainNameField = new JTextField();
143
144
145 try {
146 domainAddressField = new JFormattedTextField(new MaskFormatter("###.###.###.###"));
147 } catch (ParseException e) {
148 e.printStackTrace();
149 }
150 NumberFormatter domainPortFormatter = new NumberFormatter();
151 NumberFormatter hostPortFormatter = new NumberFormatter();
152 domainPortFormatter.setMinimum(new Integer(0));
153 domainPortFormatter.setMaximum(new Integer(65535));
154 hostPortFormatter.setMinimum(new Integer(0));
155 hostPortFormatter.setMaximum(new Integer(65535));
156 domainPortField = new JFormattedTextField(domainPortFormatter);
157 hostNameField = new JTextField();
158 hostPortField = new JFormattedTextField(hostPortFormatter);
159
160 domainNameField.setColumns(40);
161 domainPortField.setColumns(40);
162 hostNameField.setColumns(40);
163 hostPortField.setColumns(40);
164
165
166 ChangeTracker.addListener(domainNameField, domainNameLabel, hostPanel);
167 ChangeTracker.addListener(domainAddressField, domainAddressLabel, hostPanel);
168 ChangeTracker.addListener(domainPortField, domainPortLabel, hostPanel);
169 ChangeTracker.addListener(hostNameField, hostNameLabel, hostPanel);
170 ChangeTracker.addListener(hostPortField, hostPortLabel, hostPanel);
171
172 settingsPanel = new JPanel(new GridBagLayout());
173 settingsPanel.setBorder(BorderFactory.createCompoundBorder(
174 BorderFactory.createEmptyBorder(5,5,5,5),
175 BorderFactory.createEmptyBorder(5,5,5,5)));
176
177
178
179 changeButton = new JButton("Change");
180 addButton = new JButton("Add");
181 removeButton = new JButton("Remove");
182 clearButton = new JButton("Clear");
183 buttonPanel = new JPanel(new GridBagLayout());
184
185
186 GridBagConstraints gbc = new GridBagConstraints();
187 gbc.fill = GridBagConstraints.BOTH;
188 gbc.gridwidth = GridBagConstraints.REMAINDER;
189 buttonPanel.add(changeButton, gbc);
190 buttonPanel.add(removeButton, gbc);
191 buttonPanel.add(clearButton, gbc);
192 buttonPanel.add(addButton, gbc);
193 buttonPanel.setBorder(BorderFactory.createCompoundBorder(
194 BorderFactory.createEmptyBorder(5,5,5,5),
195 BorderFactory.createEmptyBorder(5,5,5,5)));
196 addButtonListeners();
197
198
199
200 rootNode = new DefaultMutableTreeNode("Domains");
201 treeModel = new DefaultTreeModel(rootNode);
202 treeModel.setAsksAllowsChildren(true);
203 hostsTree = new JTree(treeModel);
204 hostsTree.getSelectionModel().setSelectionMode
205 (TreeSelectionModel.SINGLE_TREE_SELECTION);
206 addTreeListener();
207
208 hostsTree.setSelectionPath(new TreePath(rootNode));
209 JScrollPane hostsScroller = new JScrollPane(hostsTree);
210 hostsScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
211 hostsScroller.setBorder(BorderFactory.createCompoundBorder(
212 BorderFactory.createTitledBorder(
213 BorderFactory.createEmptyBorder(),
214 hostType + " list:"),
215 BorderFactory.createCompoundBorder(
216 BorderFactory.createLineBorder(Color.BLACK,2),
217 BorderFactory.createEtchedBorder())));
218 Box hostsBox = new Box(BoxLayout.Y_AXIS);
219 hostsBox.add(hostsScroller);
220
221
222
223 gbc.fill = GridBagConstraints.BOTH;
224 gbc.gridx = 0;
225 gbc.gridy = 0;
226 gbc.gridheight = 3;
227 gbc.gridwidth = 1;
228 gbc.weightx = 0.1;
229 hostPanel.add(settingsPanel, gbc);
230
231 gbc.fill = GridBagConstraints.NONE;
232 gbc.gridx = 1;
233 gbc.gridy = 2;
234 gbc.gridheight = 1;
235 hostPanel.add(buttonPanel, gbc);
236
237 gbc.fill = GridBagConstraints.BOTH;
238 gbc.gridx = 2;
239 gbc.gridy = 0;
240 gbc.gridheight = 3;
241 gbc.weighty = 0.1;
242 gbc.weightx = 0.9;
243 hostPanel.add(hostsBox, gbc);
244
245 hostPanel.setBorder(BorderFactory.createCompoundBorder(
246 BorderFactory.createEtchedBorder(),
247 BorderFactory.createEmptyBorder(5,5,5,5)));
248 }
249
250
251
252
253
254 public void updatePanel(ExperimentConfig expConfig)
255 {
256 if( (hostPanel.getParent() instanceof JTabbedPane) == false )
257 throw new IllegalArgumentException("The parent of hostPanel must be a JTabbedPane");
258
259 JTabbedPane tabs = (JTabbedPane) hostPanel.getParent();
260 int index = tabs.indexOfComponent(hostPanel);
261
262
263 Host[] hosts = null;
264 if(hostType.equals(SERVER_TYPE))
265 hosts = expConfig.getServerConfig().getAllHosts().toArray();
266 else if(hostType.equals(CLIENT_TYPE))
267 hosts = expConfig.getClientConfig().getAllHosts().toArray();
268
269
270
271 TreeMap domainMap = sortHosts(hosts);
272
273
274 int domainIndex = 0;
275 for (Iterator domainIter = domainMap.entrySet().iterator(); domainIter.hasNext();) {
276 Map.Entry domainEntry = (Map.Entry) domainIter.next();
277 DefaultMutableTreeNode domainNode
278 = new DefaultMutableTreeNode(domainEntry.getKey(), true);
279 treeModel.insertNodeInto(domainNode, rootNode, domainIndex++);
280
281 TreeSet hostSet = (TreeSet) domainEntry.getValue();
282 int hostIndex = 0;
283 for (Iterator hostIter = hostSet.iterator(); hostIter.hasNext();) {
284 DefaultMutableTreeNode hostNode = new DefaultMutableTreeNode(hostIter.next(), false);
285 treeModel.insertNodeInto(hostNode, domainNode, hostIndex++);
286 }
287 }
288
289 hostsTree.expandRow(0);
290 hostsTree.setSelectionPath(new TreePath(rootNode));
291 }
292
293
294
295
296
297 public void setParentPanel(JPanel parentPanel)
298 {
299 if(hostPanel == null)
300 throw new IllegalArgumentException("JPanel hostPanel has already been set");
301
302 hostPanel = parentPanel;
303 }
304
305
306
307
308
309 public void clear() {
310 domainNameField.setText("");
311 domainAddressField.setValue(null);
312 domainPortField.setValue(null);
313 hostNameField.setText("");
314 hostPortField.setValue(null);
315 rootNode.removeAllChildren();
316 treeModel.reload();
317 }
318
319
320 public void save(Element parentElement, Document document)
321 {
322 Element hostTypeElement = document.createElement(hostType);
323 parentElement.appendChild(hostTypeElement);
324
325 DefaultMutableTreeNode rootNode
326 = (DefaultMutableTreeNode) treeModel.getRoot();
327
328
329 for (Enumeration e = rootNode.children(); e.hasMoreElements();) {
330 DefaultMutableTreeNode currentNode
331 = (DefaultMutableTreeNode) e.nextElement();
332 appendDomain(currentNode, hostTypeElement, document);
333 }
334 }
335
336
337
338
339
340
341 private void addButtonListeners()
342 {
343 addChangeButtonListener();
344 addAddButtonListener();
345 addRemoveButtonListener();
346 addClearButtonListener();
347 }
348
349
350 private void addTreeListener()
351 {
352 hostsTree.addTreeSelectionListener(new TreeSelectionListener() {
353 public void valueChanged(TreeSelectionEvent e) {
354 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
355 hostsTree.getLastSelectedPathComponent();
356 displayNodeInfo(selectedNode);
357 }
358 });
359 }
360
361
362
363
364
365
366 private TreeMap sortHosts(Host[] hosts)
367 {
368 TreeMap domainMap = new TreeMap();
369
370 for (int i = 0; i < hosts.length; i++) {
371 Domain domain = hosts[i].getDomain();
372 String domainNodeText = domain.getName() + " : " + domain.getPort();
373
374
375 TreeSet hostSet = new TreeSet();
376
377 if(!domainMap.containsKey(domainNodeText)){
378 String hostNodeText = hosts[i].getHostName() + " : " + hosts[i].getPort();
379 hostSet.add(hostNodeText);
380
381 for (int j = i+1; j < hosts.length; j++) {
382 if(hosts[j].getDomainName().equalsIgnoreCase(domain.getName()))
383 hostNodeText = hosts[j].getHostName() + " : " + hosts[j].getPort();
384 hostSet.add(hostNodeText);
385 }
386
387 domainMap.put(domainNodeText, hostSet);
388 }
389 }
390
391 return domainMap;
392 }
393
394
395 private void displayNodeInfo(DefaultMutableTreeNode selectedNode)
396 {
397 if(selectedNode == null) {
398
399
400 changeButton.setEnabled(false);
401 addButton.setEnabled(false);
402 removeButton.setEnabled(false);
403 clearButton.setEnabled(false);
404 return;
405 }
406
407 String nodeValue = (String) selectedNode.getUserObject();
408 GridBagConstraints gbc = new GridBagConstraints();
409 gbc.gridx = 0;
410 gbc.fill = GridBagConstraints.BOTH;
411
412 settingsPanel.removeAll();
413
414 if(selectedNode.getChildCount() == 0)
415 clearButton.setEnabled(false);
416 else
417 clearButton.setEnabled(true);
418
419 switch(selectedNode.getLevel()) {
420
421 case 0:
422 changeButton.setEnabled(false);
423 addButton.setEnabled(true);
424 removeButton.setEnabled(false);
425 domainNameField.setText("");
426 domainPortField.setText("");
427
428 settingsPanel.add(domainNameLabel, gbc);
429 settingsPanel.add(domainNameField, gbc);
430
431
432 settingsPanel.add(domainPortLabel, gbc);
433 settingsPanel.add(domainPortField, gbc);
434 break;
435
436
437 case 1:
438 changeButton.setEnabled(true);
439 addButton.setEnabled(true);
440 removeButton.setEnabled(true);
441 int domainIndex = nodeValue.indexOf(':');
442 domainNameField.setText(nodeValue.substring(0, domainIndex));
443 domainPortField.setText(nodeValue.substring(domainIndex + 1, nodeValue.length()));
444
445 settingsPanel.add(domainNameLabel, gbc);
446 settingsPanel.add(domainNameField, gbc);
447
448
449 settingsPanel.add(domainPortLabel, gbc);
450 settingsPanel.add(domainPortField, gbc);
451 settingsPanel.add(hostNameLabel, gbc);
452 settingsPanel.add(hostNameField, gbc);
453 settingsPanel.add(hostPortLabel, gbc);
454 settingsPanel.add(hostPortField, gbc);
455 break;
456
457
458 case 2:
459 changeButton.setEnabled(true);
460 addButton.setEnabled(false);
461 removeButton.setEnabled(true);
462 int hostIndex = nodeValue.indexOf(':');
463 hostNameField.setText(nodeValue.substring(0, hostIndex));
464 hostPortField.setText(nodeValue.substring(hostIndex + 1, nodeValue.length()));
465 settingsPanel.add(hostNameLabel, gbc);
466 settingsPanel.add(hostNameField, gbc);
467 settingsPanel.add(hostPortLabel, gbc);
468 settingsPanel.add(hostPortField, gbc);
469 break;
470 }
471
472 settingsPanel.revalidate();
473 }
474
475
476 private void addChangeButtonListener() {
477 changeButton.addActionListener(new ActionListener() {
478 public void actionPerformed(ActionEvent e) {
479 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
480 hostsTree.getLastSelectedPathComponent();
481 String nodeText = null;
482
483 switch(selectedNode.getLevel()) {
484
485 case 1:
486 String domainName = domainNameField.getText();
487 String domainPort = domainPortField.getText();
488
489 if(domainName.length() == 0) {
490 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
491 "You must provide a\n"
492 +"name for the domain.",
493 "Missing parameter",
494 JOptionPane.INFORMATION_MESSAGE);
495 return;
496 } else if(domainPort.length() == 0) {
497 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
498 "You must provide a port\n"
499 +"number for the domain.",
500 "Missing parameter",
501 JOptionPane.INFORMATION_MESSAGE);
502 return;
503 }
504
505 nodeText = domainName + " : " + domainPort;
506 selectedNode.setUserObject(nodeText);
507 treeModel.reload(selectedNode);
508 ChangeTracker.performedChange(selectedNode);
509 break;
510
511
512 case 2:
513 String hostName = hostNameField.getText();
514 String hostPort = hostPortField.getText();
515
516 if(hostName.length() == 0) {
517 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
518 "You must provide a\n"
519 +"name for the host.",
520 "Missing parameter",
521 JOptionPane.INFORMATION_MESSAGE);
522 return;
523 } else if(hostPort.length() == 0) {
524 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
525 "You must provide a port\n"
526 +"number for the host.",
527 "Missing parameter",
528 JOptionPane.INFORMATION_MESSAGE);
529 return;
530 }
531
532 nodeText = hostName + " : " + hostPort;
533 selectedNode.setUserObject(nodeText);
534 treeModel.reload(selectedNode);
535 ChangeTracker.performedChange(selectedNode);
536 break;
537 }
538 }
539 });
540 }
541
542 private void addAddButtonListener() {
543 addButton.addActionListener(new ActionListener() {
544 public void actionPerformed(ActionEvent e) {
545 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
546 hostsTree.getLastSelectedPathComponent();
547
548 String nodeText = null;
549 DefaultMutableTreeNode newNode = null;
550
551 switch(selectedNode.getLevel()) {
552
553 case 0:
554 String domainName = domainNameField.getText();
555 String domainPort = domainPortField.getText();
556
557 if(domainName.length() == 0) {
558 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
559 "You must provide a\n"
560 +"name for the domain.",
561 "Missing parameter",
562 JOptionPane.INFORMATION_MESSAGE);
563 return;
564 } else if(domainPort.length() == 0) {
565 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
566 "You must provide a port\n"
567 +"number for the domain.",
568 "Missing parameter",
569 JOptionPane.INFORMATION_MESSAGE);
570 return;
571 }
572
573 nodeText = domainName + " : " + domainPort;
574 newNode = new DefaultMutableTreeNode(nodeText);
575 selectedNode.add(newNode);
576 treeModel.reload();
577 ChangeTracker.performedChange(newNode.getParent());
578 break;
579
580
581
582 case 1:
583 String hostName = hostNameField.getText();
584 String hostPort = hostPortField.getText();
585
586 if(hostName.length() == 0) {
587 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
588 "You must provide a\n"
589 +"name for the host.",
590 "Missing parameter",
591 JOptionPane.INFORMATION_MESSAGE);
592 return;
593 } else if(hostPort.length() == 0) {
594 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
595 "You must provide a port\n"
596 +"number for the host.",
597 "Missing parameter",
598 JOptionPane.INFORMATION_MESSAGE);
599 return;
600 }
601
602 nodeText = hostName + " : " + hostPort;
603 newNode = new DefaultMutableTreeNode(nodeText);
604 newNode.setAllowsChildren(false);
605 selectedNode.add(newNode);
606 treeModel.reload();
607 ChangeTracker.performedChange(newNode.getParent());
608 break;
609 }
610
611 hostsTree.expandPath(new TreePath(newNode.getPath()));
612 }
613 });
614 }
615
616
617 private void addRemoveButtonListener() {
618 removeButton.addActionListener(new ActionListener() {
619 public void actionPerformed(ActionEvent e) {
620 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
621 hostsTree.getLastSelectedPathComponent();
622 DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode)
623 selectedNode.getParent();
624
625 if(selectedNode.getChildCount() > 0)
626 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
627 "You have unsaved changes,\n"
628 +"but SAVE is not yet implemented :(",
629 "Would you like to save?",
630 JOptionPane.WARNING_MESSAGE);
631
632 ChangeTracker.performedChange(selectedNode.getParent());
633 selectedNode.removeFromParent();
634 treeModel.reload();
635
636 if(parentNode.getChildCount() > 0) {
637 hostsTree.expandPath(new TreePath(parentNode.getPath()));
638 }
639 }
640 });
641 }
642
643
644 private void addClearButtonListener() {
645 clearButton.addActionListener(new ActionListener() {
646 public void actionPerformed(ActionEvent e) {
647 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode)
648 hostsTree.getLastSelectedPathComponent();
649
650 if(ChangeTracker.hasNodeChanges())
651 JOptionPane.showMessageDialog(clearButton.getTopLevelAncestor(),
652 "You have unsaved changes,\n"
653 +"but SAVE is not yet implemented :(",
654 "Would you like to save?",
655 JOptionPane.WARNING_MESSAGE);
656
657 if(selectedNode == null)
658 rootNode.removeAllChildren();
659 else
660 selectedNode.removeAllChildren();
661
662 treeModel.reload(selectedNode);
663 }
664 });
665 }
666
667
668 private void appendDomain(DefaultMutableTreeNode domainNode, Element parentElement, Document document)
669 {
670 String nodeTitle = (String) domainNode.getUserObject();
671 int index = nodeTitle.indexOf(" : ");
672 String nodeName = "";
673 String port = "";
674
675 if(index != -1) {
676 nodeName = nodeTitle.substring(0, index);
677 port = nodeTitle.substring(index + 3, nodeTitle.length());
678 } else {
679 nodeName = nodeTitle;
680 }
681
682
683 Element domainElement = document.createElement("Domain");
684 domainElement.setAttribute("name", nodeName);
685 if(port != null && port.length() > 0)
686 domainElement.setAttribute("port", port);
687 parentElement.appendChild(domainElement);
688
689
690 for (Enumeration e = domainNode.children(); e.hasMoreElements();) {
691 DefaultMutableTreeNode hostNode
692 = (DefaultMutableTreeNode) e.nextElement();
693 appendHost(hostNode, domainElement, document);
694 }
695 }
696
697
698 private void appendHost(DefaultMutableTreeNode hostNode, Element domainElement, Document document)
699 {
700 String nodeTitle = (String) hostNode.getUserObject();
701 int index = nodeTitle.indexOf(" : ");
702 String nodeName = "";
703 String port = "";
704
705 if(index != -1) {
706 nodeName = nodeTitle.substring(0, index);
707 port = nodeTitle.substring(index + 3, nodeTitle.length());
708 } else {
709 nodeName = nodeTitle;
710 }
711
712
713 Element hostElement = document.createElement("Host");
714 hostElement.setAttribute("name", nodeName);
715 if(port != null && port.length() > 0)
716 hostElement.setAttribute("port", port);
717 domainElement.appendChild(hostElement);
718 }
719 }