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.gui; 031 032import java.awt.Color; 033import java.awt.Dimension; 034import java.awt.Frame; 035import java.awt.event.ActionEvent; 036import java.awt.event.ActionListener; 037import java.awt.event.ItemEvent; 038import java.awt.event.ItemListener; 039import java.util.Iterator; 040import java.util.StringTokenizer; 041import java.util.Vector; 042 043import javax.swing.BorderFactory; 044import javax.swing.Box; 045import javax.swing.BoxLayout; 046import javax.swing.JButton; 047import javax.swing.JCheckBox; 048import javax.swing.JDialog; 049import javax.swing.JLabel; 050import javax.swing.JOptionPane; 051import javax.swing.JPanel; 052import javax.swing.JScrollPane; 053import javax.swing.UIManager; 054import javax.swing.border.TitledBorder; 055import javax.swing.event.TableModelEvent; 056import javax.swing.table.AbstractTableModel; 057 058import org.kepler.gui.GraphicalActorMetadata; 059import org.kepler.objectmanager.ActorMetadata; 060import org.kepler.objectmanager.cache.ActorCacheObject; 061import org.kepler.objectmanager.cache.CacheManager; 062import org.kepler.objectmanager.lsid.KeplerLSID; 063import org.kepler.sms.SMSServices; 064import org.kepler.sms.SemanticType; 065 066import ptolemy.actor.IOPort; 067import ptolemy.actor.TypedAtomicActor; 068import ptolemy.actor.TypedCompositeActor; 069import ptolemy.actor.TypedIOPort; 070import ptolemy.kernel.ComponentEntity; 071import ptolemy.kernel.Entity; 072import ptolemy.kernel.util.NamedObj; 073import ptolemy.kernel.util.Workspace; 074import ptolemy.moml.EntityLibrary; 075import ptolemy.vergil.tree.EntityTreeModel; 076import ptolemy.vergil.tree.PTree; 077import ptolemy.vergil.tree.VisibleTreeModel; 078 079 080 081/** 082 * 083 * @author Shawn Bowers 084 */ 085public class SemanticSearchDialog extends JDialog { 086 /** 087 * This is the default constructor 088 */ 089 public SemanticSearchDialog(Frame owner, NamedObj namedObj) { 090 super(owner); 091 092 _namedObj = namedObj; 093 _owner = owner; 094 095 // set title and close behavior 096 this.setTitle("Semantic Search"); 097 this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 098 099 // create the frame's pane 100 JPanel pane = new JPanel(); 101 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 102 pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 103 104 // create the ssearch and result pane 105 JPanel bodyPane = new JPanel(); 106 bodyPane.setLayout(new BoxLayout(bodyPane, BoxLayout.X_AXIS)); 107 bodyPane.add(_createSearchPane()); 108 bodyPane.add(Box.createRigidArea(new Dimension(10, 0))); 109 bodyPane.add(_createResultPane()); 110 111 // add components to pane 112 pane.add(bodyPane); 113 pane.add(Box.createRigidArea(new Dimension(0, 5))); 114 pane.add(_createButtons()); 115 116 // pane.add(Box.createRigidArea(new Dimension(0, 5))); 117 pane.add(_createStatus()); 118 119 // add the pane 120 setContentPane(pane); 121 // set size 122 this.setSize(675, 575); 123 // setResizable(false); 124 125 } 126 127 /** 128 * Initialize the bottom buttons (close) 129 */ 130 private JPanel _createSearchPane() { 131 // initialize "dummy" search objects 132 try { 133 _searchActor = new TypedAtomicActor(); 134 _inSearchPort = new TypedIOPort(_searchActor, "input", true, false); 135 _outSearchPort = new TypedIOPort(_searchActor, "output", false, 136 true); 137 _actorTable = new SemanticTypeTable(_getFrame(), false); 138 _actorTable.addAnnotationObject(_searchActor); 139 _actorTable.setAnnotationObjectVisible(_searchActor); 140 _actorTable.setEnabled(false); 141 _inPortTable = new SemanticTypeTable(_getFrame(), false); 142 _inPortTable.addAnnotationObject(_inSearchPort); 143 _inPortTable.setAnnotationObjectVisible(_inSearchPort); 144 _inPortTable.setEnabled(false); 145 _outPortTable = new SemanticTypeTable(_getFrame(), false); 146 _outPortTable.addAnnotationObject(_outSearchPort); 147 _outPortTable.setAnnotationObjectVisible(_outSearchPort); 148 _outPortTable.setEnabled(false); 149 } catch (Exception e) { 150 e.printStackTrace(); 151 } 152 153 // initialize the checkboxes 154 _chkActorSearch = new JCheckBox("Actor Semantic Types"); 155 _chkActorSearch.setSelected(false); 156 _chkActorSearch.addItemListener(_checkBoxListener); 157 _chkInPortSearch = new JCheckBox("Input Semantic Types"); 158 _chkInPortSearch.setSelected(false); 159 _chkInPortSearch.addItemListener(_checkBoxListener); 160 _chkOutPortSearch = new JCheckBox("Output Semantic Types"); 161 _chkOutPortSearch.setSelected(false); 162 _chkOutPortSearch.addItemListener(_checkBoxListener); 163 164 // initialize the panel 165 JPanel pane = new JPanel(); 166 pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS)); 167 pane.setBorder(_createTitledBorder("Search Criteria")); 168 169 pane.add(_createSearchComponent(_chkActorSearch, _actorTable)); 170 pane.add(Box.createRigidArea(new Dimension(0, 5))); 171 pane.add(_createSearchComponent(_chkInPortSearch, _inPortTable)); 172 pane.add(Box.createRigidArea(new Dimension(0, 5))); 173 pane.add(_createSearchComponent(_chkOutPortSearch, _outPortTable)); 174 175 return pane; 176 } 177 178 /** 179 * 180 */ 181 private JPanel _createResultPane() { 182 JPanel pane = new JPanel(); 183 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 184 pane.setBorder(_createTitledBorder("Search Results")); 185 186 _resultTree = new PTree(new EntityTreeModel(null)); 187 _resultTree.setPreferredSize(new Dimension(280, 100)); 188 JPanel treePane = new JPanel(); 189 treePane.setLayout(new BoxLayout(treePane, BoxLayout.X_AXIS)); 190 treePane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 191 treePane.add(new JScrollPane(_resultTree)); 192 193 pane.add(treePane); 194 195 // return 196 return pane; 197 } 198 199 /** 200 * Combines a check box and semantic type table into a single pane. 201 */ 202 private JPanel _createSearchComponent(JCheckBox chk, SemanticTypeTable tbl) { 203 // set up the main panel 204 JPanel pane = new JPanel(); 205 pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); 206 // construct the check box 207 JPanel chkPane = new JPanel(); 208 chkPane.add(Box.createRigidArea(new Dimension(10, 0))); 209 chkPane.setLayout(new BoxLayout(chkPane, BoxLayout.X_AXIS)); 210 chkPane.add(chk); 211 chkPane.add(Box.createHorizontalGlue()); 212 // add the check box 213 pane.add(chkPane); 214 // add the table 215 pane.add(tbl); 216 // return the pane 217 return pane; 218 } 219 220 /** 221 * Initialize the bottom buttons (close) 222 */ 223 private JPanel _createButtons() { 224 // init buttons 225 _btnSearch = new JButton("Search"); 226 _btnSearch.setActionCommand("search"); 227 _btnSearch.setToolTipText("Search for matching components"); 228 _btnSearch.addActionListener(_buttonListener); 229 _btnClose = new JButton("Close"); 230 _btnClose.setActionCommand("close"); 231 _btnClose.setToolTipText("Close dialog"); 232 _btnClose.addActionListener(_buttonListener); 233 // create the pane 234 JPanel pane = new JPanel(); 235 pane.setLayout(new BoxLayout(pane, BoxLayout.LINE_AXIS)); 236 pane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 237 pane.add(Box.createHorizontalGlue()); 238 pane.add(_btnSearch); 239 pane.add(Box.createRigidArea(new Dimension(10, 0))); 240 pane.add(_btnClose); 241 242 return pane; 243 } 244 245 /** 246 * 247 */ 248 private JPanel _createStatus() { 249 JPanel pane = new JPanel(); 250 pane.setLayout(new BoxLayout(pane, BoxLayout.X_AXIS)); 251 252 _lblQueryStatus = new JLabel("status: "); 253 254 pane.add(Box.createRigidArea(new Dimension(5, 0))); 255 pane.add(_lblQueryStatus); 256 // statusPane.setPreferredSize(new Dimension(100, 25)); 257 pane.add(Box.createHorizontalGlue()); 258 259 return pane; 260 } 261 262 /** 263 * Create a titled border with a blue font 264 */ 265 private TitledBorder _createTitledBorder(String title) { 266 TitledBorder border = BorderFactory.createTitledBorder(" " + title 267 + " "); 268 border.setTitleColor(new Color(0, 10, 230)); 269 return border; 270 } 271 272 /** 273 * @return The frame of the dialog 274 */ 275 private Frame _getFrame() { 276 java.awt.Container c = getParent(); 277 while (!(c instanceof Frame) && c != null) 278 c = c.getParent(); 279 if (c != null) 280 return (Frame) c; 281 return null; 282 } 283 284 /** 285 * Anonymous class to handle check box state changes 286 */ 287 private ItemListener _checkBoxListener = new ItemListener() { 288 public void itemStateChanged(ItemEvent e) { 289 Object source = e.getItemSelectable(); 290 if (source == _chkActorSearch) 291 _actorSearchStateChanged(); 292 else if (source == _chkInPortSearch) 293 _inPortSearchStateChanged(); 294 else if (source == _chkOutPortSearch) 295 _outPortSearchStateChanged(); 296 } 297 }; 298 299 /** 300 * anonymous class to handle button events 301 */ 302 private ActionListener _buttonListener = new ActionListener() { 303 public void actionPerformed(ActionEvent e) { 304 if (e.getActionCommand().equals("search")) 305 _doSearch(); 306 else if (e.getActionCommand().equals("close")) 307 _doClose(); 308 } 309 }; 310 311 /** 312 * Toggles the actor search pane 313 */ 314 private void _actorSearchStateChanged() { 315 if (_chkActorSearch.isSelected()) 316 _actorTable.setEnabled(true); 317 else 318 _actorTable.setEnabled(false); 319 } 320 321 /** 322 * Toggles the input port search pane 323 */ 324 private void _inPortSearchStateChanged() { 325 if (_chkInPortSearch.isSelected()) 326 _inPortTable.setEnabled(true); 327 else 328 _inPortTable.setEnabled(false); 329 } 330 331 /** 332 * Toggles the out port search pane 333 */ 334 private void _outPortSearchStateChanged() { 335 if (_chkOutPortSearch.isSelected()) 336 _outPortTable.setEnabled(true); 337 else 338 _outPortTable.setEnabled(false); 339 } 340 341 /** 342 * Performs the search button operation. 343 */ 344 private void _doSearch() { 345 346 Vector<SemanticType> actorTypes = new Vector<SemanticType>(); 347 Vector<SemanticType> inTypes = new Vector<SemanticType>(); 348 Vector<SemanticType> outTypes = new Vector<SemanticType>(); 349 350 String msg; 351 // check for some search terms; if none then warn 352 // if(_chkOutPortSearch.isSelected()) 353 outTypes = _outPortTable.getSemanticTypes(_outSearchPort); 354 // if(_chkInPortSearch.isSelected()) 355 inTypes = _inPortTable.getSemanticTypes(_inSearchPort); 356 // if(_chkActorSearch.isSelected()) 357 actorTypes = _actorTable.getSemanticTypes(_searchActor); 358 if (outTypes.size() == 0 && inTypes.size() == 0 359 && actorTypes.size() == 0) { 360 msg = "No search criteria specified."; 361 JOptionPane.showMessageDialog(this, msg, "Message", 362 JOptionPane.ERROR_MESSAGE); 363 return; 364 } 365 366 // make sure the sem types are well formed first! 367 if ((msg = _outPortTable.wellFormedSemTypes()) != null) { 368 JOptionPane.showMessageDialog(this, msg, "Message", 369 JOptionPane.ERROR_MESSAGE); 370 return; 371 } else if ((msg = _inPortTable.wellFormedSemTypes()) != null) { 372 JOptionPane.showMessageDialog(this, msg, "Message", 373 JOptionPane.ERROR_MESSAGE); 374 return; 375 } else if ((msg = _actorTable.wellFormedSemTypes()) != null) { 376 JOptionPane.showMessageDialog(this, msg, "Message", 377 JOptionPane.ERROR_MESSAGE); 378 return; 379 } 380 381 // warn about unknown semantic types 382 if (_outPortTable.hasUnknownSemTypes() 383 || _inPortTable.hasUnknownSemTypes() 384 || _actorTable.hasUnknownSemTypes()) { 385 msg = "Unable to find a matching ontology class for at least one semantic type. \n" 386 + "Do you wish to search anyway?"; 387 int n = JOptionPane.showConfirmDialog(this, msg, "Message", 388 JOptionPane.YES_NO_OPTION); 389 if (n == 1) 390 return; 391 } 392 393 // give notice of executing search, and disable search button 394 _lblQueryStatus.setText("status: executing search "); 395 _btnSearch.setEnabled(false); 396 397 // create a search task, add listener and run it 398 _SearchTask task = new _SearchTask(actorTypes, inTypes, outTypes); 399 task.addListener(this); 400 Thread thread = new Thread(task); 401 thread.start(); 402 } 403 404 /** 405 * Callback for thread 406 */ 407 private void _searchCompletedAction(_SearchTask task) { 408 _btnSearch.setEnabled(true); 409 410 Vector<Entity> result = task.getResults(); 411 _lblQueryStatus.setText("status: found " + result.size() + " results"); 412 413 EntityLibrary root = new EntityLibrary(); 414 Workspace workspace = root.workspace(); 415 EntityTreeModel model = new VisibleTreeModel(root); 416 417 for (Iterator<Entity> iter = result.iterator(); iter.hasNext();) { 418 try { 419 NamedObj entity = (NamedObj) iter.next(); 420 // add to the tree 421 NamedObj obj = _clone(entity, workspace); 422 if (obj instanceof ComponentEntity) { 423 ((ComponentEntity) obj).setContainer(root); 424 // ChangeRequest request = new MoMLChangeRequest(obj, 425 // "adding object to search result"); 426 // obj.requestChange(request); 427 // obj.executeChangeRequests(); 428 } 429 } catch (Exception e) { 430 e.printStackTrace(); 431 } 432 } 433 _resultTree.setModel(model); 434 _resultTree.setRootVisible(false); 435 436 } 437 438 private NamedObj _clone(NamedObj obj, Workspace workspace) { 439 NamedObj result = null; 440 try { 441 result = (NamedObj) obj.clone(workspace); 442 } catch (Exception e) { 443 e.printStackTrace(); 444 } 445 return result; 446 } 447 448 /** 449 * A private inner class to execute query as a separate thread. 450 */ 451 private class _SearchTask implements Runnable { 452 private Vector<SemanticType> _actorTypes; 453 private Vector<SemanticType> _inputTypes; 454 private Vector<SemanticType> _outputTypes; 455 private Vector<Entity> _results; 456 private Vector<SemanticSearchDialog> _listeners = new Vector<SemanticSearchDialog>(); 457 458 /** constructor */ 459 public _SearchTask(Vector<SemanticType> actorTypes, Vector<SemanticType> inputTypes, 460 Vector<SemanticType> outputTypes) { 461 _actorTypes = actorTypes; 462 _inputTypes = inputTypes; 463 _outputTypes = outputTypes; 464 } 465 466 /** to notify dialog when results are obtained */ 467 public void addListener(SemanticSearchDialog obj) { 468 _listeners.add(obj); 469 } 470 471 /** executes the query */ 472 public void run() { 473 _results = _doSearch(_actorTypes, _inputTypes, _outputTypes); 474 for (Iterator<SemanticSearchDialog> iter = _listeners.iterator(); iter.hasNext();) { 475 SemanticSearchDialog dialog = (SemanticSearchDialog) iter 476 .next(); 477 dialog._searchCompletedAction(this); 478 } 479 } 480 481 /** retrieve the results */ 482 public Vector<Entity> getResults() { 483 return _results; 484 } 485 486 }; // _SearchTask 487 488 /** 489 * 490 */ 491 private synchronized Vector<Entity> _doSearch(Vector<SemanticType> searchActorTypes, 492 Vector<SemanticType> searchInTypes, 493 Vector<SemanticType> searchOutTypes) { 494 Vector<Entity> result = new Vector<Entity>(); 495 496 Vector<Entity> objects = _getObjectsToSearch(); 497 498 // check if there is a match; we know there is at least one 499 // semantic type, which is checked in _doSearch() above 500 for (Iterator<Entity> iter = objects.iterator(); iter.hasNext();) { 501 boolean compatible = true; 502 Entity entity = iter.next(); 503 504 if (searchActorTypes.size() > 0 && compatible) { 505 Vector entityActorTypes = SMSServices 506 .getActorSemanticTypes(entity); 507 if (SMSServices.compare(entityActorTypes, searchActorTypes) != SMSServices.COMPATIBLE) 508 compatible = false; 509 } 510 511 if (searchInTypes.size() > 0 && compatible) { 512 // iterate through the semantic types while still compatible 513 for (Iterator<SemanticType> types = searchInTypes.iterator(); types.hasNext() 514 && compatible;) { 515 boolean found = false; 516 Vector<SemanticType> searchInType = new Vector<SemanticType>(); 517 searchInType.add(types.next()); 518 // iterator through ports until we find a match 519 for (Iterator ports = entity.portList().iterator(); ports 520 .hasNext() 521 && !found;) { 522 IOPort port = (IOPort) ports.next(); 523 Vector entityInTypes = SMSServices 524 .getPortSemanticTypes(port); 525 if (SMSServices.compare(searchInType, entityInTypes) == SMSServices.COMPATIBLE) 526 found = true; 527 } 528 // if we didn't find a match for a semtype then we're not 529 // compatible 530 if (!found) 531 compatible = false; 532 } 533 } 534 535 if (searchOutTypes.size() > 0 && compatible) { 536 // iterate through the semantic types while still compatible 537 for (Iterator<SemanticType> types = searchOutTypes.iterator(); types 538 .hasNext() 539 && compatible;) { 540 boolean found = false; 541 Vector<SemanticType> searchOutType = new Vector<SemanticType>(); 542 searchOutType.add(types.next()); 543 // iterator through ports until we find a match 544 for (Iterator ports = entity.portList().iterator(); ports 545 .hasNext() 546 && !found;) { 547 IOPort port = (IOPort) ports.next(); 548 Vector entityOutTypes = SMSServices 549 .getPortSemanticTypes(port); 550 if (SMSServices.compare(entityOutTypes, searchOutType) == SMSServices.COMPATIBLE) 551 found = true; 552 } 553 // if we didn't find a match for a semtype then we're not 554 // compatible 555 if (!found) 556 compatible = false; 557 } 558 } 559 560 if (compatible) 561 result.add(entity); 562 } 563 564 return result; 565 } 566 567 /** 568 * 569 */ 570 private Vector<Entity> _getObjectsToSearch() { 571 Vector<Entity> result = new Vector<Entity>(); 572 try { 573 CacheManager manager = CacheManager.getInstance(); 574 Vector<KeplerLSID> cachedLsids = manager.getCachedLsids(); 575 for (KeplerLSID lsid : cachedLsids) { 576 if (manager.getObject(lsid) instanceof ActorCacheObject){ 577 ActorCacheObject aco = (ActorCacheObject) manager 578 .getObject(lsid); 579 ActorMetadata am = aco.getMetadata(); 580 GraphicalActorMetadata gam = new GraphicalActorMetadata(am); 581 NamedObj obj = gam.getActorAsNamedObj(null); 582 // relax to just named obj here? 583 if (obj instanceof Entity){ 584 result.add((Entity)obj); 585 } 586 } 587 } 588 } catch (Exception e) { 589 e.printStackTrace(); 590 } 591 return result; 592 } 593 594 /** 595 * Performs the cancel button operation. 596 */ 597 private void _doClose() { 598 _actorTable.dispose(); 599 _inPortTable.dispose(); 600 _outPortTable.dispose(); 601 dispose(); 602 } 603 604 /** 605 * Really shut the thing down. 606 */ 607 private void _close() { 608 dispose(); 609 } 610 611 private class _ResultTableModel extends AbstractTableModel { 612 // private members 613 private String[] tableHeader = { "Object Name", "Object Type" }; // two 614 // columns 615 private Vector tableData = new Vector(); // vector of NamedObj 616 617 /** 618 * get the column count 619 */ 620 public int getColumnCount() { 621 return tableHeader.length; 622 } 623 624 /** 625 * get the row cound 626 */ 627 public int getRowCount() { 628 return tableData.size(); 629 } 630 631 /** 632 * get the column name 633 */ 634 public String getColumnName(int columnIndex) { 635 return tableHeader[columnIndex]; 636 } 637 638 /** 639 * get the value of a cell 640 */ 641 public Object getValueAt(int rowIndex, int columnIndex) { 642 if (!validRowIndex(rowIndex)) 643 return null; 644 NamedObj obj = (NamedObj) tableData.elementAt(rowIndex); 645 if (rowIndex == 0) 646 return obj.getName(); 647 if (rowIndex == 1) 648 return _getSimpleName(obj.getClass()); 649 return null; 650 } 651 652 /** 653 * results not editable 654 */ 655 public boolean isCellEditable(int rowIndex, int columnIndex) { 656 return false; 657 } 658 659 /** 660 * sets the value in the column. checks that the term is valid? 661 */ 662 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 663 // if(!validRowIndex(rowIndex)) 664 // return; 665 // Object[] row = (Object []) tableData.elementAt(rowIndex); 666 // row[columnIndex] = aValue; 667 // fireTableChanged(new TableModelEvent(this)); // change event 668 } 669 670 /** 671 * Insert a new named ontology class into the model 672 */ 673 public void insertRow(NamedObj obj) { 674 if (rowExists(obj)) 675 return; 676 tableData.add(obj); 677 } 678 679 /** 680 * @return True if the table contains the given class, and false 681 * otherwise. 682 */ 683 public boolean containsRow(NamedObj obj) { 684 return rowExists(obj); 685 } 686 687 /** 688 * @return a list of rows of non-empty Object arrays of arity 2 689 * (Object[2]) 690 */ 691 public Iterator getRows() { 692 return tableData.iterator(); 693 } 694 695 /** 696 * @return the first empty row or -1 if no empties 697 */ 698 public int firstEmptyRow() { 699 int index = 0; 700 for (Iterator iter = tableData.iterator(); iter.hasNext(); index++) { 701 Object[] row = (Object[]) iter.next(); 702 if (row[0] == null && row[1] == null) 703 return index; 704 } 705 return -1; 706 } 707 708 /** 709 * @return true if the row already exists 710 */ 711 private boolean rowExists(NamedObj obj) { 712 return tableData.contains(obj); 713 } 714 715 /** 716 * remove selected row 717 */ 718 public void removeRow(int rowIndex) { 719 if (!validRowIndex(rowIndex)) 720 return; 721 tableData.removeElementAt(rowIndex); 722 fireTableChanged(new TableModelEvent(this)); // change event 723 } 724 725 /** 726 * check that we are at a valid row 727 */ 728 private boolean validRowIndex(int rowIndex) { 729 if (rowIndex >= 0 && rowIndex < getRowCount()) 730 return true; 731 return false; 732 } 733 734 /** 735 * returns the "simple" name of the class 736 */ 737 private String _getSimpleName(Class c) { 738 StringTokenizer st = new StringTokenizer(c.getName(), ".", false); 739 while (st.hasMoreTokens()) { 740 String str = st.nextToken(); 741 if (!st.hasMoreTokens()) 742 return str; 743 } 744 return null; 745 } 746 747 }; 748 749 /** 750 * Main method for testing the dialog. 751 * 752 * @param args 753 * the arguments to the program 754 */ 755 public static void main(String[] args) { 756 try { 757 // a composite "wrapper" 758 TypedCompositeActor swf = new TypedCompositeActor(); 759 760 // windows look and feel 761 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 762 SemanticSearchDialog dialog = new SemanticSearchDialog(null, swf); 763 dialog.setVisible(true); 764 } catch (Exception e) { 765 e.printStackTrace(); 766 } 767 } 768 769 /** Private members */ 770 771 private SemanticTypeTable _actorTable; // the sem types for actor search 772 // criteria 773 private SemanticTypeTable _inPortTable; // the sem types for input 774 private SemanticTypeTable _outPortTable; // the sem types for output 775 private TypedAtomicActor _searchActor; // dummy actor for attaching search 776 // criteria 777 private TypedIOPort _inSearchPort; // dummy port for attaching search 778 // criteria 779 private TypedIOPort _outSearchPort; // dummy port for attaching search 780 // criteria 781 private JCheckBox _chkActorSearch; // check box for using actor search 782 private JCheckBox _chkInPortSearch; // check box for using input search 783 private JCheckBox _chkOutPortSearch; // check box for using output search 784 private PTree _resultTree; // stores results in the tree 785 private JButton _btnSearch; // search btton 786 private JButton _btnClose; // close dialog button 787 private JLabel _lblQueryStatus; // status of query 788 private Frame _owner; // the owner of this dialog 789 private NamedObj _namedObj; // the canvas 790}