001/* 002 * Copyright (c) 2005-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.sms.actors; 031 032import java.awt.Color; 033import java.awt.Component; 034import java.awt.Dimension; 035import java.awt.Frame; 036import java.awt.event.ActionEvent; 037import java.awt.event.ActionListener; 038import java.awt.event.KeyEvent; 039import java.awt.event.MouseAdapter; 040import java.awt.event.MouseEvent; 041import java.util.Enumeration; 042import java.util.Iterator; 043import java.util.Vector; 044 045import javax.swing.BorderFactory; 046import javax.swing.Box; 047import javax.swing.BoxLayout; 048import javax.swing.DefaultCellEditor; 049import javax.swing.JButton; 050import javax.swing.JComboBox; 051import javax.swing.JDialog; 052import javax.swing.JLabel; 053import javax.swing.JOptionPane; 054import javax.swing.JPanel; 055import javax.swing.JScrollPane; 056import javax.swing.JTable; 057import javax.swing.JTree; 058import javax.swing.ListSelectionModel; 059import javax.swing.SwingConstants; 060import javax.swing.border.TitledBorder; 061import javax.swing.event.TableModelEvent; 062import javax.swing.table.AbstractTableModel; 063import javax.swing.table.TableColumn; 064import javax.swing.tree.DefaultTreeModel; 065import javax.swing.tree.TreeModel; 066import javax.swing.tree.TreeNode; 067import javax.swing.tree.TreePath; 068 069import org.kepler.sms.KeplerVirtualIOPort; 070import org.kepler.sms.SemanticType; 071import org.kepler.sms.gui.SemanticTypeTable; 072 073import ptolemy.actor.IOPort; 074import ptolemy.actor.TypedIOPort; 075import ptolemy.actor.TypedIORelation; 076import ptolemy.kernel.util.NamedObj; 077 078/* 079 FIXME: 080 081 - the conversion table: 082 1). read in while loading mappings (both MergeEditor and MappingRefinement) 083 2). store when changed in editor 084 3). make sure stored as output 085 086 - go back to _computeMerge ... 087 */ 088 089/** 090 * 091 * @author Shawn Bowers 092 */ 093public class MergeEditorDialog extends JDialog { 094 095 /** 096 * Constructor 097 */ 098 public MergeEditorDialog(Frame owner, MergeActor mergeActor) { 099 super(owner); 100 _owner = owner; 101 _mergeActor = mergeActor; 102 103 _loadTargetPorts(); 104 _loadMappings(); 105 106 this.setTitle("Compute Merge Results"); 107 this.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); 108 109 JPanel pane = new JPanel(); 110 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 111 pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 112 113 // add the tree part 114 pane.add(_createPortTrees()); 115 pane.add(Box.createRigidArea(new Dimension(0, 10))); 116 117 // add the conversion part 118 pane.add(_createConversionTable()); 119 pane.add(Box.createRigidArea(new Dimension(0, 10))); 120 121 // add the semantic type table 122 pane.add(_createSemTypeTable(owner)); 123 // pane.setBorder(_createTitledBorder("Output Port Semantic Type")); 124 pane.add(Box.createRigidArea(new Dimension(0, 10))); 125 126 pane.add(_createButtonPane()); 127 128 // add the pane 129 setContentPane(pane); 130 // set size 131 this.setSize(500, 725); 132 this.setResizable(false); 133 } 134 135 /** 136 * Create and initialize the main buttons 137 */ 138 private JPanel _createButtonPane() { 139 JPanel pane = new JPanel(); 140 pane.setLayout(new BoxLayout(pane, BoxLayout.LINE_AXIS)); 141 pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 142 pane.add(Box.createHorizontalGlue()); 143 pane.add(_commitBtn); 144 pane.add(Box.createRigidArea(new Dimension(10, 0))); 145 pane.add(_closeBtn); 146 147 // init buttons 148 _commitBtn.setMnemonic(KeyEvent.VK_C); 149 _commitBtn.setActionCommand("commit"); 150 _commitBtn 151 .setToolTipText("Save changes to annotations and close editor"); 152 _commitBtn.addActionListener(_buttonListener); 153 _closeBtn.setActionCommand("cancel"); 154 _closeBtn.setToolTipText("Close editor without saving"); 155 _closeBtn.addActionListener(_buttonListener); 156 157 return pane; 158 } 159 160 /** 161 * Create and initialize the input and output port trees. 162 */ 163 private JPanel _createPortTrees() { 164 // outer pane 165 JPanel pane = new JPanel(); 166 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 167 pane.setBorder(_createTitledBorder("Input-Output Mapping")); 168 169 // tree pane 170 JPanel treePane = new JPanel(); 171 treePane.setLayout(new BoxLayout(treePane, BoxLayout.X_AXIS)); 172 173 // create the input tree 174 _inputPortTree = new JTree(_createInputModel()); 175 _inputPortTree.setRootVisible(false); 176 _inputPortTree.setEditable(false); 177 _inputPortTree.setExpandsSelectedPaths(true); 178 // listen for mouse clicks 179 _inputPortTree.addMouseListener(new MouseAdapter() { 180 public void mousePressed(MouseEvent e) { 181 int selRow = _inputPortTree.getRowForLocation(e.getX(), e 182 .getY()); 183 if (selRow == -1) 184 return; 185 TreePath selPath = _inputPortTree.getPathForLocation(e.getX(), 186 e.getY()); 187 TreeNode node = (TreeNode) selPath.getLastPathComponent(); 188 if (node == null || e.getClickCount() != 1) 189 return; 190 TreePath[] paths = { selPath }; 191 _inputPortTree.setSelectionPaths(paths); 192 _outputPortTree.setSelectionPaths(null); 193 _conversionTbl.setModel(_emptyConversionModel); 194 // set the model to an empty model instance 195 if (node instanceof _PortTreeNode) { 196 _inputSingleClick((_PortTreeNode) node); 197 _semTypeTable.setEnabled(false); 198 _semTypeTable 199 .setAnnotationObjectVisible(_emptyAnnotationPort); 200 _loadNewConversionTable((IOPort) ((_PortTreeNode) node) 201 .getPort()); 202 } 203 204 } 205 }); 206 JScrollPane inputTreeView = new JScrollPane(_inputPortTree); 207 JPanel inputTreePane = _labelComponent("merge input ports ", 208 inputTreeView, 225, 175); 209 210 // create the output tree 211 _outputPortTree = new JTree(_createOutputModel()); 212 _outputPortTree.setRootVisible(false); 213 _outputPortTree.setEditable(false); 214 _inputPortTree.setExpandsSelectedPaths(true); 215 // listen for mouse clicks 216 _outputPortTree.addMouseListener(new MouseAdapter() { 217 public void mousePressed(MouseEvent e) { 218 int selRow = _outputPortTree.getRowForLocation(e.getX(), e 219 .getY()); 220 if (selRow == -1) 221 return; 222 TreePath selPath = _outputPortTree.getPathForLocation(e.getX(), 223 e.getY()); 224 TreeNode node = (TreeNode) selPath.getLastPathComponent(); 225 if (node == null || e.getClickCount() != 1) 226 return; 227 TreePath[] paths = { selPath }; 228 _outputPortTree.setSelectionPaths(paths); 229 _inputPortTree.setSelectionPaths(null); 230 _conversionTbl.setModel(_emptyConversionModel); 231 if (node instanceof _PortTreeNode) { 232 _outputSingleClick((_PortTreeNode) node); 233 _semTypeTable.setEnabled(true); 234 _semTypeTable 235 .setAnnotationObjectVisible((IOPort) ((_PortTreeNode) node) 236 .getPort()); 237 } 238 } 239 }); 240 JScrollPane outputTreeView = new JScrollPane(_outputPortTree); 241 JPanel outputTreePane = _labelComponent("merge output ports ", 242 outputTreeView, 225, 175); 243 244 // add input and output tree to treepane 245 treePane.add(inputTreePane); 246 treePane.add(Box.createRigidArea(new Dimension(10, 0))); 247 treePane.add(outputTreePane); 248 249 // button pane 250 JPanel buttonPane = new JPanel(); 251 buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS)); 252 buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 253 254 // create the buttons 255 JButton btnEdit = new JButton("Refine Mappings"); 256 btnEdit.setActionCommand("refine"); 257 btnEdit.addActionListener(_buttonListener); 258 btnEdit.setToolTipText("Add or remove input-output port mappings"); 259 JButton btnPrune = new JButton("Prune Output Ports"); 260 btnPrune.setActionCommand("prune"); 261 btnPrune.addActionListener(_buttonListener); 262 btnPrune.setToolTipText("Remove unused output ports"); 263 JButton btnAdd = new JButton("Add Output Port"); 264 btnAdd.setActionCommand("add"); 265 btnAdd.addActionListener(_buttonListener); 266 btnAdd.setToolTipText("Add a new output port"); 267 268 // add buttons 269 buttonPane.add(Box.createHorizontalGlue()); 270 buttonPane.add(btnEdit); 271 buttonPane.add(Box.createRigidArea(new Dimension(5, 0))); 272 buttonPane.add(btnPrune); 273 buttonPane.add(Box.createRigidArea(new Dimension(5, 0))); 274 buttonPane.add(btnAdd); 275 276 // add intermediate panes to outer pane 277 pane.add(treePane); 278 pane.add(Box.createRigidArea(new Dimension(0, 5))); 279 pane.add(buttonPane); 280 // return it 281 return pane; 282 } 283 284 /* 285 * Create and initialize the conversion function combo box 286 */ 287 private JPanel _createConversionTable() { 288 // outer pane 289 JPanel pane = new JPanel(); 290 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 291 pane.setBorder(_createTitledBorder("Conversion Functions")); 292 293 // set up the table 294 _conversionTbl = new JTable(_emptyConversionModel); 295 _conversionTbl 296 .setPreferredScrollableViewportSize(new Dimension(200, 80)); 297 // init 298 _conversionTbl.setColumnSelectionAllowed(false); 299 _conversionTbl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 300 301 // init the combo box view pane 302 JPanel view = new JPanel(); 303 view.setLayout(new BoxLayout(view, BoxLayout.Y_AXIS)); 304 view.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // top,left,bottom,right 305 view.add(new JScrollPane(_conversionTbl)); 306 // add to the pane 307 pane.add(view); 308 // return 309 return pane; 310 } 311 312 /** 313 * Create and initialize the output semantic type table 314 */ 315 private JPanel _createSemTypeTable(Frame owner) { 316 // outer pane 317 JPanel pane = new JPanel(); 318 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 319 pane.setBorder(_createTitledBorder("Output Port Semantic Type")); 320 // init the table 321 _semTypeTable = new SemanticTypeTable(owner, false); // don't show the 322 // label 323 _semTypeTable.setEnabled(false); 324 _initSemTypeTable(); 325 326 // add to the pane 327 pane.add(_semTypeTable); 328 // return 329 return pane; 330 } 331 332 /** 333 * 334 */ 335 private void _setFunctionCombo() { 336 TableColumn functionColumn = _conversionTbl.getColumnModel().getColumn( 337 0); 338 JComboBox comboBox = new JComboBox(); 339 comboBox.setEditable(false); 340 comboBox.addItem(""); 341 comboBox.addItem("gramsToKilograms"); 342 comboBox.addItem("inchesToMeters"); 343 functionColumn.setCellEditor(new DefaultCellEditor(comboBox)); 344 } 345 346 /** 347 * 348 */ 349 private void _loadNewConversionTable(IOPort port) { 350 _ConversionFunctionTableModel model = new _ConversionFunctionTableModel(); 351 _conversionTbl.setModel(model); 352 353 // set up where the column draws functions from 354 _setFunctionCombo(); 355 356 // iteration over mapping targets ... 357 Iterator<SimpleMergeMapping> iter = _mergeActor.getInputPortMappings(port); 358 while (iter.hasNext()) { 359 SimpleMergeMapping m = iter.next(); 360 String function = m.getConversion(); 361 if (function == null) 362 function = ""; 363 model.insertRow(function, m.getTargetPort()); 364 } 365 } 366 367 /** 368 * 369 */ 370 private void _initSemTypeTable() { 371 Vector oldports = _semTypeTable.getAnnotationObjects(); 372 Vector<IOPort> currports = new Vector<IOPort>(); 373 Iterator<IOPort> iter = getTargetPorts().iterator(); 374 375 while (iter.hasNext()) { 376 IOPort p = iter.next(); 377 currports.add(p); 378 if (!oldports.contains(p)) 379 _semTypeTable.addAnnotationObject(p); 380 } 381 382 Iterator oldPortsIter = oldports.iterator(); 383 while (iter.hasNext()) { 384 IOPort p = (IOPort) oldPortsIter.next(); 385 if (!currports.contains(p)) 386 _semTypeTable.removeAnnotationObject(p); 387 } 388 _semTypeTable.addAnnotationObject(_emptyAnnotationPort); 389 } 390 391 /** 392 * Create a titled border with a blue font 393 */ 394 private TitledBorder _createTitledBorder(String title) { 395 TitledBorder border = BorderFactory.createTitledBorder(" " + title 396 + " "); 397 border.setTitleColor(new Color(0, 10, 230)); 398 return border; 399 } 400 401 /** 402 * Call back for input port tree 403 */ 404 private void _inputSingleClick(_PortTreeNode portNode) { 405 // get the output mappings for the port 406 IOPort p = (IOPort) portNode.getPort(); 407 _selectPortNodes(_outputPortTree, getTargetPorts(p)); 408 } 409 410 /** 411 * Call back for output port tree 412 */ 413 private void _outputSingleClick(_PortTreeNode portNode) { 414 IOPort outputPort = (IOPort) portNode.getPort(); 415 Vector<IOPort> inputs = new Vector<IOPort>(); 416 Iterator iter = _mergeActor.connectedPortList().iterator(); 417 while (iter.hasNext()) { 418 IOPort inPort = (IOPort) iter.next(); 419 Iterator<IOPort> targets = getTargetPorts(inPort).iterator(); 420 while (targets.hasNext()) { 421 IOPort target = targets.next(); 422 if (target.equals(outputPort)) 423 inputs.add(inPort); 424 }// end while 425 }// end while 426 _selectPortNodes(_inputPortTree, inputs); 427 } 428 429 /** 430 * Selects the given set of ports in the tree. 431 */ 432 private void _selectPortNodes(JTree tree, Vector<IOPort> ports) { 433 Vector<TreePath> treePaths = new Vector<TreePath>(); 434 Iterator<IOPort> iter = ports.iterator(); 435 while (iter.hasNext()) { 436 TreePath path = _getTreePath(iter.next(), tree); 437 if (path != null && !treePaths.contains(path)) 438 treePaths.add(path); 439 } 440 TreePath[] t = new TreePath[treePaths.size()]; 441 for (int i = 0; i < treePaths.size(); i++) 442 t[i] = treePaths.elementAt(i); 443 tree.setSelectionPaths(t); 444 } 445 446 /** 447 * Gets the tree path for the given port in the given tree 448 */ 449 private TreePath _getTreePath(IOPort port, JTree tree) { 450 TreeModel m = tree.getModel(); 451 TreeNode root = (TreeNode) m.getRoot(); 452 TreePath startpath = new TreePath(root); 453 return _getTreePath(port, root, startpath); 454 } 455 456 /** 457 * Gets the tree path for the given port, a parent node, and a current path. 458 * The parent is the leaf node of the current path. 459 */ 460 private TreePath _getTreePath(IOPort port, TreeNode parent, 461 TreePath currpath) { 462 Enumeration children = parent.children(); 463 while (children.hasMoreElements()) { 464 TreeNode t = (TreeNode) children.nextElement(); 465 TreePath path = currpath.pathByAddingChild(t); 466 if (t instanceof _PortTreeNode 467 && port.equals(((_PortTreeNode) t).getPort())) 468 return path; 469 TreePath portpath = _getTreePath(port, t, path); 470 if (portpath != null) 471 return portpath; 472 }// end while 473 return null; 474 } 475 476 /** 477 * Creates and initializes the default tree model of the input tree 478 */ 479 protected DefaultTreeModel _createInputModel() { 480 _ActorTreeNode root = new _ActorTreeNode(null); 481 _inputTreeModel = new DefaultTreeModel(root); 482 483 Iterator iter = _mergeActor.getActors().iterator(); 484 while (iter.hasNext()) { 485 NamedObj actor = (NamedObj) iter.next(); 486 _ActorTreeNode anode = new _ActorTreeNode(actor); 487 root.addChild(anode); 488 Iterator ports = _mergeActor.getActorPorts(actor).iterator(); 489 while (ports.hasNext()) { 490 IOPort port = (IOPort) ports.next(); 491 _PortTreeNode pnode = new _PortTreeNode(port); 492 anode.addChild(pnode); 493 }// end while 494 }// end while 495 496 return _inputTreeModel; 497 } 498 499 /** 500 * Creates and initializes the default tree model of the output tree 501 */ 502 protected DefaultTreeModel _createOutputModel() { 503 _ActorTreeNode root = new _ActorTreeNode(null); 504 _outputTreeModel = new DefaultTreeModel(root); 505 506 Iterator<IOPort> iter = getTargetPorts().iterator(); 507 while (iter.hasNext()) { 508 IOPort port = iter.next(); 509 _PortTreeNode pnode = new _PortTreeNode(port); 510 root.addChild(pnode); 511 }// end while 512 return _outputTreeModel; 513 } 514 515 private void _resetGUI() { 516 _outputPortTree.setSelectionPaths(null); 517 _inputPortTree.setSelectionPaths(null); 518 _semTypeTable.setAnnotationObjectVisible(_emptyAnnotationPort); 519 _conversionTbl.setModel(_emptyConversionModel); 520 } 521 522 // ////////////////////////////////////////////////////////////////////////// 523 // LOCAL TARGET PORTS 524 525 /** 526 * Load the target ports from the merge actor. This method should be called 527 * only once when the dialog is created. 528 */ 529 private void _loadTargetPorts() { 530 Iterator iter = _mergeActor.outputPortList().iterator(); 531 while (iter.hasNext()) { 532 try { 533 IOPort p = (IOPort) ((IOPort) iter.next()).clone(); 534 p.setContainer(null); 535 _targetPorts.add(p); 536 } catch (Exception e) { 537 e.printStackTrace(); 538 } 539 } 540 } 541 542 /** 543 * @return the set of local target ports 544 */ 545 public Vector<IOPort> getTargetPorts() { 546 return _targetPorts; 547 } 548 549 /** 550 * @return the set of local target ports for the given input port 551 */ 552 public Vector<IOPort> getTargetPorts(IOPort inputPort) { 553 Vector<IOPort> results = new Vector<IOPort>(); 554 NamedObj actorObj = inputPort.getContainer(); 555 String actor = actorObj.getName(); 556 String port = inputPort.getName(); 557 Vector<String> targetNames = new Vector<String>(); 558 Iterator<SimpleMergeMapping> iter = getMappings().iterator(); 559 while (iter.hasNext()) { 560 SimpleMergeMapping m = iter.next(); 561 if (actor.equals(m.getSourceActor()) 562 && port.equals(m.getSourceActorPort())) 563 targetNames.add(m.getTargetPort()); 564 }// end while 565 566 Iterator<IOPort> ioPortIter = getTargetPorts().iterator(); 567 while (ioPortIter.hasNext()) { 568 IOPort p = ioPortIter.next(); 569 if (targetNames.contains(p.getName())) 570 results.add(p); 571 }// end while 572 return results; 573 } 574 575 /** 576 * removes the given target port 577 */ 578 public void removeTargetPort(IOPort port) { 579 _targetPorts.remove(port); 580 } 581 582 /** 583 * adds the given target port 584 */ 585 public void addTargetPort(IOPort port) { 586 if (!_targetPorts.contains(port)) 587 _targetPorts.add(port); 588 } 589 590 // ////////////////////////////////////////////////////////////////////////// 591 // LOCAL MAPPINGS 592 593 private void _loadMappings() { 594 Iterator iter = _mergeActor.getMappings().iterator(); 595 while (iter.hasNext()) { 596 try { 597 SimpleMergeMapping m = (SimpleMergeMapping) iter.next(); 598 SimpleMergeMapping mcopy = new SimpleMergeMapping(m 599 .getSourceActor(), m.getSourceActorPort(), m 600 .getTargetPort()); 601 if (m.getConversion() != null) 602 mcopy.setConversion(m.getConversion()); 603 _mappings.add(mcopy); 604 } catch (Exception e) { 605 e.printStackTrace(); 606 } 607 }// end while 608 } 609 610 private void _printMappings() { 611 Iterator<SimpleMergeMapping> iter = _mappings.iterator(); 612 while (iter.hasNext()) { 613 SimpleMergeMapping m = iter.next(); 614 String actor = m.getSourceActor(); 615 String actorPort = m.getSourceActorPort(); 616 String target = m.getTargetPort(); 617 System.out.println("... mapping: " + actor + ", " + actorPort 618 + ", " + target); 619 } 620 } 621 622 // for commit ... 623 // m.setName(_mergeActor.uniqueName("_merge")); 624 625 public Vector<SimpleMergeMapping> getMappings() { 626 return _mappings; 627 } 628 629 public void removeMapping(SimpleMergeMapping m) { 630 _mappings.remove(m); 631 } 632 633 /** 634 * replace current mappings with the new set 635 */ 636 public void addMapping(SimpleMergeMapping m) { 637 if (!_mappings.contains(m)) 638 _mappings.add(m); 639 } 640 641 private void _doAdd() { 642 String msg = "Please enter a port name"; 643 String portName = null; 644 boolean success = true; 645 646 _resetGUI(); 647 648 try { 649 String title = "Create Merge Output Port"; 650 int type = JOptionPane.PLAIN_MESSAGE; 651 portName = (String) JOptionPane.showInputDialog(this, msg, title, 652 type); 653 } catch (Exception e) { 654 e.printStackTrace(); 655 } 656 if (portName == null) 657 return; 658 if (portName.trim().length() < 1) { 659 msg = "A port name must be provided"; 660 success = false; 661 } 662 if (success) { 663 try { 664 NamedObj o = new NamedObj(); 665 o.setName(portName); 666 } catch (Exception e) { 667 success = false; 668 msg = e.getMessage(); 669 } 670 } 671 Iterator<IOPort> iter = getTargetPorts().iterator(); 672 while (success && iter.hasNext()) { 673 IOPort p = iter.next(); 674 if (portName.equals(p.getName())) { 675 success = false; 676 msg = "A port named '" + portName + "' already exists."; 677 break; 678 } 679 }// end while 680 681 if (!success) { 682 JOptionPane.showMessageDialog(this, msg, "Error", 683 JOptionPane.ERROR_MESSAGE); 684 return; 685 } 686 687 // add the port 688 TypedIOPort out = new TypedIOPort(); 689 try { 690 out.setName(portName); 691 out.setOutput(true); 692 out.setInput(false); 693 addTargetPort(out); 694 } catch (Exception e) { 695 e.printStackTrace(); 696 return; 697 } 698 // update the display 699 _outputPortTree.setModel(_createOutputModel()); 700 // add to the sem port dialog 701 _semTypeTable.addAnnotationObject(out); 702 } 703 704 private void _doPrune() { 705 _resetGUI(); 706 707 Iterator iter = _getDanglingOutputPorts().iterator(); 708 Vector dangling = new Vector(); 709 while (iter.hasNext()) { 710 IOPort p = (IOPort) iter.next(); 711 dangling.add(p); 712 removeTargetPort(p); 713 } 714 // refresh the dialog 715 _outputPortTree.setModel(_createOutputModel()); 716 // remove from semantic type dialog 717 iter = dangling.iterator(); 718 while (iter.hasNext()) 719 _semTypeTable.removeAnnotationObject((IOPort) iter.next()); 720 } 721 722 private Vector<IOPort> _getDanglingOutputPorts() { 723 Vector<IOPort> results = new Vector<IOPort>(); 724 Iterator<SimpleMergeMapping> iter = getMappings().iterator(); 725 Vector<String> targets = new Vector<String>(); 726 while (iter.hasNext()) { 727 SimpleMergeMapping m = iter.next(); 728 targets.add(m.getTargetPort()); 729 } 730 731 Iterator<IOPort> ioIter = getTargetPorts().iterator(); 732 while (iter.hasNext()) { 733 IOPort p = ioIter.next(); 734 if (!targets.contains(p.getName())) 735 results.add(p); 736 }// end while 737 return results; 738 } 739 740 /** 741 * Call back for the commit button 742 */ 743 private void _doCommit() { 744 _resetGUI(); 745 746 String msg = null; 747 int opt = JOptionPane.YES_NO_OPTION; 748 int type = JOptionPane.WARNING_MESSAGE; 749 // if any "dangling" ports output warning message 750 if (_getDanglingOutputPorts().size() > 0) { 751 msg = "Dangling output ports: Some output ports are not mapped to input ports \n" 752 + "Commit anyway?"; 753 if (1 == JOptionPane.showConfirmDialog(this, msg, "Warning", opt, 754 type)) 755 return; // abort 756 } 757 // commit the semantic type changes 758 if ((msg = _semTypeTable.wellFormedSemTypes()) != null) { 759 JOptionPane.showMessageDialog(this, msg, "Message", 760 JOptionPane.ERROR_MESSAGE); 761 return; // abort 762 } 763 if (_semTypeTable.hasUnknownSemTypes()) { 764 msg = "Unable to find a matching ontology class for at least one semantic type. \n" 765 + "Commit anyway?"; 766 if (1 == JOptionPane.showConfirmDialog(this, msg, "Message", opt, 767 type)) 768 return; // abort 769 } 770 _semTypeTable.commitAnnotationObjects(); 771 772 // update the mergeActor mappings and output ports 773 _saveChanges(); 774 775 // System.out.println(_mergeActor.exportMoML()); 776 777 _mergeActor.update(); 778 779 // close the dialog 780 _doClose(); 781 } 782 783 private void _saveChanges() { 784 // remove existing output ports 785 Iterator iter = _mergeActor.outputPortList().iterator(); 786 while (iter.hasNext()) { 787 IOPort p = (IOPort) iter.next(); 788 try { 789 p.setContainer(null); 790 } catch (Exception e) { 791 e.printStackTrace(); 792 } 793 }// end while 794 795 // add the new ports 796 iter = getTargetPorts().iterator(); 797 while (iter.hasNext()) { 798 TypedIOPort p = (TypedIOPort) iter.next(); 799 try { 800 TypedIOPort port = (TypedIOPort) p.clone(_mergeActor 801 .workspace()); 802 port.setContainer(_mergeActor); 803 } catch (Exception e) { 804 e.printStackTrace(); 805 } 806 }// end while 807 _mergeActor.setProductionRate(); 808 809 // remove existing mappings 810 iter = _mergeActor.getMappings().iterator(); 811 while (iter.hasNext()) { 812 try { 813 SimpleMergeMapping m = (SimpleMergeMapping) iter.next(); 814 m.setContainer(null); 815 } catch (Exception e) { 816 e.printStackTrace(); 817 } 818 } 819 820 // for each mapping, set name and clone into workspace 821 iter = getMappings().iterator(); 822 while (iter.hasNext()) { 823 SimpleMergeMapping m = (SimpleMergeMapping) iter.next(); 824 try { 825 m.setName(_mergeActor.uniqueName("_merge")); 826 SimpleMergeMapping map = (SimpleMergeMapping) m 827 .clone(_mergeActor.workspace()); 828 map.setContainer(_mergeActor); 829 } catch (Exception e) { 830 e.printStackTrace(); 831 } 832 } 833 } 834 835 /** 836 * Call back for the close button 837 */ 838 private void _doClose() { 839 dispose(); 840 } 841 842 /** 843 * 844 */ 845 private void _doEdit() { 846 _resetGUI(); 847 MappingRefinementDialog.showDialog(_owner, _mergeActor, this); 848 _outputPortTree.setSelectionPaths(null); 849 _inputPortTree.setSelectionPaths(null); 850 } 851 852 /** 853 * Given a label string, component, height, and width, creates a new panel 854 * with a label and the component of size height and width. The label is 855 * positioned above the component and is left justified. 856 */ 857 private JPanel _labelComponent(String str, Component component, int width, 858 int height) { 859 // output pane 860 JPanel pane = new JPanel(); 861 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 862 // pane for label only 863 JPanel labelPane = new JPanel(); 864 labelPane.setLayout(new BoxLayout(labelPane, BoxLayout.X_AXIS)); 865 labelPane.add(new JLabel(str, SwingConstants.LEFT)); 866 labelPane.add(Box.createHorizontalGlue()); 867 // add label 868 pane.add(labelPane); 869 // add space 870 pane.add(Box.createRigidArea(new Dimension(0, 5))); 871 // add component 872 pane.add(component); 873 // set sizes 874 pane.setMaximumSize(new Dimension(width, height)); 875 pane.setMinimumSize(new Dimension(width, height)); 876 pane.setPreferredSize(new Dimension(width, height)); 877 // return outer pane 878 return pane; 879 } 880 881 /** 882 * Inner class for tree nodes 883 */ 884 private class _ActorTreeNode implements TreeNode { 885 public _ActorTreeNode(NamedObj actor) { 886 _actor = actor; 887 } 888 889 public NamedObj getActor() { 890 return _actor; 891 } 892 893 public void addChild(_ActorTreeNode child) { 894 if (!_children.contains(child)) { 895 _children.add(child); 896 child.removeFromParent(); 897 child.setParent(this); 898 } 899 } 900 901 public void addChild(_PortTreeNode child) { 902 if (!_children.contains(child)) { 903 _children.add(child); 904 child.removeFromParent(); 905 child.setParent(this); 906 } 907 } 908 909 public void setParent(TreeNode parent) { 910 _parent = parent; 911 } 912 913 public void removeFromParent() { 914 _parent = null; 915 } 916 917 public Enumeration children() { 918 return _children.elements(); 919 } 920 921 public boolean getAllowsChildren() { 922 return true; 923 } 924 925 public TreeNode getChildAt(int index) { 926 if (index < _children.size() && index >= 0) 927 return (TreeNode) _children.elementAt(index); 928 return null; 929 } 930 931 public int getIndex(TreeNode node) { 932 return _children.indexOf(node); 933 } 934 935 public int getChildCount() { 936 return _children.size(); 937 } 938 939 public TreeNode getParent() { 940 return _parent; 941 } 942 943 public boolean isLeaf() { 944 return _children.size() == 0; 945 } 946 947 public String toString() { 948 if (_actor != null) 949 return _actor.getName(); 950 return ""; 951 } 952 953 private NamedObj _actor; 954 private Vector _children = new Vector(); 955 private TreeNode _parent; 956 }; 957 958 /** 959 * Inner class for port tree nodes 960 */ 961 private class _PortTreeNode implements TreeNode { 962 public _PortTreeNode(Object port) { 963 _port = port; 964 } 965 966 public Object getPort() { 967 return _port; 968 } 969 970 public void addChild(_PortTreeNode child) { 971 if (!_children.contains(child)) { 972 _children.add(child); 973 child.removeFromParent(); 974 child.setParent(this); 975 } 976 } 977 978 public void setParent(TreeNode parent) { 979 _parent = parent; 980 } 981 982 public void removeFromParent() { 983 _parent = null; 984 } 985 986 public Enumeration children() { 987 return _children.elements(); 988 } 989 990 public boolean getAllowsChildren() { 991 return true; 992 } 993 994 public TreeNode getChildAt(int index) { 995 if (index < _children.size() && index >= 0) 996 return (TreeNode) _children.elementAt(index); 997 return null; 998 } 999 1000 public int getIndex(TreeNode node) { 1001 return _children.indexOf(node); 1002 } 1003 1004 public int getChildCount() { 1005 return _children.size(); 1006 } 1007 1008 public TreeNode getParent() { 1009 return _parent; 1010 } 1011 1012 public boolean isLeaf() { 1013 return _children.size() == 0; 1014 } 1015 1016 public String toString() { 1017 String str = ""; 1018 if (_port instanceof IOPort) 1019 str += ((IOPort) _port).getName(); 1020 else if (_port instanceof KeplerVirtualIOPort) 1021 str += ((KeplerVirtualIOPort) _port).getName(); 1022 return str; 1023 } 1024 1025 private Object _port; 1026 private Vector _children = new Vector(); 1027 private TreeNode _parent; 1028 1029 }; 1030 1031 /** 1032 * anonymous class to handle button events 1033 */ 1034 private ActionListener _buttonListener = new ActionListener() { 1035 public void actionPerformed(ActionEvent e) { 1036 if (e.getActionCommand().equals("commit")) 1037 _doCommit(); 1038 else if (e.getActionCommand().equals("cancel")) 1039 _doClose(); 1040 else if (e.getActionCommand().equals("refine")) { 1041 _doEdit(); // new dialog 1042 } else if (e.getActionCommand().equals("prune")) { 1043 _doPrune(); 1044 } else if (e.getActionCommand().equals("add")) { 1045 _doAdd(); 1046 } 1047 } 1048 }; 1049 1050 public static void main(String[] args) { 1051 try { 1052 javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager 1053 .getSystemLookAndFeelClassName()); 1054 1055 ptolemy.actor.TypedCompositeActor cont = new ptolemy.actor.TypedCompositeActor(); 1056 1057 MergeActor m = new MergeActor(cont, "merge"); 1058 1059 ptolemy.actor.TypedCompositeActor a = new ptolemy.actor.TypedCompositeActor( 1060 cont, "A"); 1061 ptolemy.actor.lib.Const a1_inner = new ptolemy.actor.lib.Const(a, 1062 "A1_inner"); 1063 a1_inner.value.setToken(new ptolemy.data.IntToken(1)); 1064 ptolemy.actor.lib.Const a2_inner = new ptolemy.actor.lib.Const(a, 1065 "A2_inner"); 1066 a2_inner.value.setToken(new ptolemy.data.IntToken(4)); 1067 TypedIOPort a_output1 = new TypedIOPort(a, "output1", false, true); 1068 TypedIOPort a_output2 = new TypedIOPort(a, "output2", false, true); 1069 TypedIORelation a1rel = new TypedIORelation(a, "a1rel"); 1070 a1_inner.output.link(a1rel); 1071 a_output1.link(a1rel); 1072 TypedIORelation a2rel = new TypedIORelation(a, "a2rel"); 1073 a2_inner.output.link(a2rel); 1074 a_output2.link(a1rel); 1075 1076 ptolemy.actor.lib.Const b = new ptolemy.actor.lib.Const(cont, "B"); 1077 b.value.setToken(new ptolemy.data.IntToken(2)); 1078 1079 ptolemy.actor.lib.Const c = new ptolemy.actor.lib.Const(cont, "C"); 1080 c.value.setToken(new ptolemy.data.IntToken(3)); 1081 1082 TypedIORelation arel11 = new TypedIORelation(cont, "rel11"); 1083 a_output1.link(arel11); 1084 m.mergeInputPort.link(arel11); 1085 1086 TypedIORelation arel12 = new TypedIORelation(cont, "rel12"); 1087 a_output2.link(arel12); 1088 m.mergeInputPort.link(arel12); 1089 1090 TypedIORelation brel = new TypedIORelation(cont, "rel2"); 1091 b.output.link(brel); 1092 m.mergeInputPort.link(brel); 1093 1094 TypedIORelation crel = new TypedIORelation(cont, "rel3"); 1095 c.output.link(crel); 1096 m.mergeInputPort.link(crel); 1097 1098 // semantic port annotations 1099 SemanticType t1 = new SemanticType(b.output, b.output 1100 .uniqueName("_semanticType")); 1101 t1 1102 .setConceptId("urn:lsid:lsid.ecoinformatics.org:onto:4:1#BiomassMeasurement"); 1103 SemanticType t2 = new SemanticType(c.output, c.output 1104 .uniqueName("_semanticType")); 1105 t2 1106 .setConceptId("urn:lsid:lsid.ecoinformatics.org:onto:4:1#BiomassMeasurement"); 1107 1108 m.computeMerge(); 1109 m.editMerge(); 1110 1111 } catch (Exception e) { 1112 e.printStackTrace(); 1113 } 1114 } 1115 1116 // a table for the conversion functions: t(function, output port) 1117 /** 1118 * inner class for managing the table data 1119 */ 1120 private class _ConversionFunctionTableModel extends AbstractTableModel { 1121 // private members 1122 private String[] tableHeader = { "Function", "Output Port" }; // two 1123 // columns 1124 private Vector tableData = new Vector(); // vector of arrays 1125 1126 public int getColumnCount() { 1127 return 2; 1128 } 1129 1130 public int getRowCount() { 1131 return tableData.size(); 1132 } 1133 1134 public String getColumnName(int columnIndex) { 1135 return tableHeader[columnIndex]; 1136 } 1137 1138 public Object getValueAt(int rowIndex, int columnIndex) { 1139 Object[] row = (Object[]) tableData.elementAt(rowIndex); 1140 return row[columnIndex]; 1141 } 1142 1143 public boolean isCellEditable(int rowIndex, int columnIndex) { 1144 if (columnIndex == 0) 1145 return true; 1146 return false; 1147 } 1148 1149 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 1150 if (!validRowIndex(rowIndex)) 1151 return; 1152 Object[] row = (Object[]) tableData.elementAt(rowIndex); 1153 row[columnIndex] = aValue; 1154 fireTableChanged(new TableModelEvent(this)); // change event 1155 } 1156 1157 public void insertRow(String function, String portName) { 1158 Object[] row = new Object[2]; 1159 row[0] = function; 1160 row[1] = portName; 1161 if (rowExists(row)) // if exists, return 1162 return; 1163 // make sure there are no empty rows (if so, to first one) 1164 int index = firstEmptyRow(); 1165 if (index != -1) 1166 tableData.setElementAt(row, index); 1167 else 1168 tableData.add(row); 1169 fireTableChanged(new TableModelEvent(this)); 1170 } 1171 1172 public boolean containsRow(String function, String portName) { 1173 Object[] tmpRow = new Object[2]; 1174 tmpRow[0] = function; 1175 tmpRow[1] = portName; 1176 return rowExists(tmpRow); 1177 } 1178 1179 /** 1180 * @return a list of rows of non-empty Object arrays of arity 2 1181 * (Object[2]) 1182 */ 1183 public Iterator getRows() { 1184 Vector results = new Vector(); 1185 for (Iterator iter = tableData.iterator(); iter.hasNext();) { 1186 Object[] row = (Object[]) iter.next(); 1187 if (row[0] != null || row[1] != null) 1188 results.add(row); 1189 } 1190 return results.iterator(); 1191 } 1192 1193 public void insertEmptyRow() { 1194 tableData.addElement(new Object[2]); 1195 fireTableChanged(new TableModelEvent(this)); // change event 1196 } 1197 1198 public int firstEmptyRow() { 1199 int index = 0; 1200 for (Iterator iter = tableData.iterator(); iter.hasNext(); index++) { 1201 Object[] row = (Object[]) iter.next(); 1202 if (row[0] == null && row[1] == null) 1203 return index; 1204 } 1205 return -1; 1206 } 1207 1208 private boolean rowExists(Object[] newrow) { 1209 for (Iterator iter = tableData.iterator(); iter.hasNext();) { 1210 Object[] row = (Object[]) iter.next(); 1211 if (newrow[0].equals(row[0]) && newrow[1].equals(row[1])) 1212 return true; 1213 } 1214 return false; 1215 } 1216 1217 public void removeRow(int rowIndex) { 1218 if (!validRowIndex(rowIndex)) 1219 return; 1220 tableData.removeElementAt(rowIndex); 1221 fireTableChanged(new TableModelEvent(this)); // change event 1222 } 1223 1224 private boolean validRowIndex(int rowIndex) { 1225 if (rowIndex >= 0 && rowIndex < getRowCount()) 1226 return true; 1227 return false; 1228 } 1229 }; 1230 1231 private Frame _owner; 1232 private MergeActor _mergeActor; 1233 private JButton _commitBtn = new JButton("Commit"); 1234 private JButton _closeBtn = new JButton("Cancel"); 1235 private DefaultTreeModel _outputTreeModel; 1236 private DefaultTreeModel _inputTreeModel; 1237 private JTree _outputPortTree; 1238 private JTree _inputPortTree; 1239 private SemanticTypeTable _semTypeTable; 1240 private IOPort _emptyAnnotationPort = new IOPort(); 1241 private JTable _conversionTbl; 1242 private _ConversionFunctionTableModel _emptyConversionModel = new _ConversionFunctionTableModel(); 1243 // a local copy of the merge actor mappings 1244 private Vector<SimpleMergeMapping> _mappings = new Vector<SimpleMergeMapping>(); 1245 // a local copy of the target output ports 1246 private Vector<IOPort> _targetPorts = new Vector<IOPort>(); 1247 1248}// MergeEditorDialog