001/* 002 * Copyright (c) 2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-08-24 22:44:14 +0000 (Mon, 24 Aug 2015) $' 007 * '$Revision: 33630 $' 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.gui; 031 032import java.awt.BorderLayout; 033import java.awt.Component; 034import java.awt.Cursor; 035import java.awt.event.ActionEvent; 036import java.awt.event.ActionListener; 037import java.awt.event.MouseListener; 038import java.io.File; 039import java.net.URL; 040import java.util.Iterator; 041 042import javax.swing.DefaultListCellRenderer; 043import javax.swing.ImageIcon; 044import javax.swing.JComboBox; 045import javax.swing.JLabel; 046import javax.swing.JList; 047import javax.swing.JOptionPane; 048import javax.swing.JPanel; 049import javax.swing.JTree; 050import javax.swing.event.TreeSelectionListener; 051import javax.swing.tree.TreeSelectionModel; 052 053import org.apache.commons.logging.Log; 054import org.apache.commons.logging.LogFactory; 055import org.kepler.authentication.AuthenticationException; 056import org.kepler.build.modules.Module; 057import org.kepler.build.modules.ModuleTree; 058import org.kepler.gui.popups.LibraryPopupListener; 059import org.kepler.objectmanager.cache.LocalRepositoryManager; 060import org.kepler.objectmanager.library.LibraryManager; 061import org.kepler.objectmanager.repository.RepositoryException; 062import org.kepler.sms.OntologyCatalog; 063import org.kepler.util.StaticResources; 064import org.kepler.util.StatusNotifier; 065 066import ptolemy.actor.gui.TableauFrame; 067import ptolemy.kernel.util.Attribute; 068import ptolemy.kernel.util.IllegalActionException; 069import ptolemy.kernel.util.NameDuplicationException; 070import ptolemy.kernel.util.NamedObj; 071import ptolemy.kernel.util.StringAttribute; 072import ptolemy.moml.EntityLibrary; 073import ptolemy.util.MessageHandler; 074import ptolemy.vergil.tree.EntityTreeModel; 075 076public class ComponentLibraryTab extends JPanel implements TabPane { 077 private static final Log log = LogFactory.getLog(ComponentLibraryTab.class 078 .getName()); 079 private static final boolean isDebugging = log.isDebugEnabled(); 080 081 private String _name; 082 protected EntityTreeModel _libraryModel; 083 // protected LibraryManager _lman = LibraryManager.getInstance(); 084 /** 085 * The configuration for this tableau. 086 */ 087 private TableauFrame _frame; 088 089 protected AnnotatedPTree _library; 090 protected ResultTreeRebuilder _libraryPanel; 091 protected SimpleLibrarySearcher _librarySearcher; // SimpleLibrarySearcher 092 private SimpleSearchUIPane _librarySearchPane; // SimpleSearchUIPane 093 private SearchButtonActionHandler _searchButtonHandler = new SearchButtonActionHandler(); 094 095 private JComboBox _ontSelectBox; 096 private OntSelectActionHandler _ontSelectHandler = new OntSelectActionHandler(); 097 098 private ImageIcon _ontOpenIcon; 099 private ImageIcon _ontClosedIcon; 100 private ImageIcon _folOpenIcon; 101 private ImageIcon _folClosedIcon; 102 103 private MouseListener _mouseListener; 104 private LibraryActionHandler _libraryActionHandler; 105 106 // XXX currently always doing authenticated queries and gets. 107 // The main ramification here is this means the user will be 108 // prompted on their first search to authenticate. Previously 109 // we only ever did non-authenticated search on Components tab. 110 public static final boolean AUTHENTICATE = true; 111 112 public final String allOntologiesName = "All Ontologies and Folders"; 113 114 private LocalRepositoryManager _localRepoManager; 115 116 public ComponentLibraryTab(TableauFrame parent) { 117 super(); 118 this.setBackground(TabManager.BGCOLOR); 119 _frame = parent; 120 121 URL ontOpenURL = ComponentLibraryTab.class.getResource(StaticResources 122 .getSettingsString("ONTOLOGY_TREEICON_OPEN_PATH", "")); 123 if (ontOpenURL != null) { 124 _ontOpenIcon = new ImageIcon(ontOpenURL); 125 } 126 127 URL ontClosedURL = ComponentLibraryTab.class 128 .getResource(StaticResources.getSettingsString( 129 "ONTOLOGY_TREEICON_CLOSED_PATH", "")); 130 if (ontClosedURL != null) { 131 _ontClosedIcon = new ImageIcon(ontClosedURL); 132 } 133 134 URL folOpenURL = ComponentLibraryTab.class.getResource(StaticResources 135 .getSettingsString("FOLDER_TREEICON_OPEN_PATH", "")); 136 if (folOpenURL != null) { 137 _folOpenIcon = new ImageIcon(folOpenURL); 138 } 139 140 URL folClosedURL = ComponentLibraryTab.class 141 .getResource(StaticResources.getSettingsString( 142 "FOLDER_TREEICON_CLOSED_PATH", "")); 143 if (folClosedURL != null) { 144 _folClosedIcon = new ImageIcon(folClosedURL); 145 } 146 147 _localRepoManager = LocalRepositoryManager.getInstance(); 148 149 } 150 151 /** 152 * Implementation of TabPane getName() 153 */ 154 public String getTabName() { 155 return _name; 156 } 157 158 public void setTabName(String name) { 159 _name = name; 160 } 161 162 /** 163 * Implementation of TabPane setParentFrame(TableauFrame) 164 */ 165 public void setParentFrame(TableauFrame parent) { 166 if (parent == null) { 167 //System.out.println("setParentFrame(null)"); 168 closing(); 169 } else { 170 _frame = parent; 171 } 172 } 173 174 private void closing() { 175 // System.out.println("ComponentLibraryTab.closing()"); 176 //_mouseListener.closing(); 177 _library.removeMouseListener(_mouseListener); 178 _mouseListener = null; 179 //_library.removeListener(_libraryActionHandler); 180 _libraryActionHandler = null; 181 if (_librarySearchPane instanceof SimpleSearchUIPane) { 182 SimpleSearchUIPane pane = (SimpleSearchUIPane) _librarySearchPane; 183 pane.closing(); 184 } 185 _frame = null; 186 187 } 188 189 /** 190 * Implementation of getParentFrame getName() 191 */ 192 public TableauFrame getParentFrame() { 193 return _frame; 194 } 195 196 /** 197 * Set true if want not to display remote ontology 198 */ 199 public void setSkipReposiotryOntology(boolean skipRepositoryOntology) { 200 _librarySearcher.setSkipReposiotryOntology(skipRepositoryOntology); 201 } 202 203 /** 204 * Implementation of TabPane getName() 205 */ 206 public void initializeTab() { 207 208 StatusNotifier.log("Initializing Actor Tree."); 209 210 initLibraryTree(); 211 this.setBackground(TabManager.BGCOLOR); 212 213 /* 214 * Getting rid of pluggable Areas. Can get similar results by extending 215 * this class and using the TabPane extension point. 216 */ 217 218 StatusNotifier.log("Initializing Library Search."); 219 initLibrarySearchPane(); 220 initLibrarySearcher(); 221 222 StatusNotifier.log("Initializing Ontology Selector."); 223 initOntSelectBox(); 224 225 StatusNotifier.log("Initializing Library Panel."); 226 initLibraryPanel(); 227 228 JPanel kludgePane = new JPanel(); 229 kludgePane.setLayout(new BorderLayout()); 230 231 // create and add the search panel to the library 232 this.setLayout(new BorderLayout()); 233 this.add(_librarySearchPane, BorderLayout.NORTH); 234 kludgePane.add(_ontSelectBox, BorderLayout.NORTH); 235 kludgePane.add(_libraryPanel, BorderLayout.CENTER); 236 this.add(kludgePane, BorderLayout.CENTER); 237 238 } 239 240 /* 241 * Init the library tree for library panel. 242 */ 243 protected void initLibraryTree() { 244 // get the tree model from the LibraryIndex 245 LibraryManager libraryManager = LibraryManager.getInstance(); 246 247 _libraryModel = libraryManager.getTreeModel(getFilterFile()); 248 _library = new AnnotatedPTree(_libraryModel, this); 249 250 _mouseListener = new LibraryPopupListener(_library); 251 _library.setMouseListener(_mouseListener); 252 253 _library.initAnotatedPTree(); 254 255 libraryManager.addLibraryJTree((JTree) _library); 256 257 _libraryActionHandler = new LibraryActionHandler(); 258 _library.addListener(_libraryActionHandler); 259 _library.setRootVisible(false); 260 } 261 262 /** 263 * Set the selection of the JTree (result) in this panel to single 264 * selection, and add a selection listener to it. 265 * 266 * @param listener 267 */ 268 public void addTreeSingleSelectionListener(TreeSelectionListener listener) { 269 if (_library != null) { 270 _library.getSelectionModel().setSelectionMode( 271 TreeSelectionModel.SINGLE_TREE_SELECTION); 272 _library.addTreeSelectionListener(listener); 273 } 274 if (_libraryPanel != null) { 275 _libraryPanel.setSingleTreeSelectionListener(listener); 276 } 277 } 278 279 /** 280 * Get the result tree after searching. 281 * 282 * @return null if _libraryPanel is null 283 */ 284 public JTree getResultTree() { 285 if (_libraryPanel != null) { 286 JTree tree = _libraryPanel.getResultTree(); 287 if (tree != null) { 288 return tree; 289 } else { 290 return _library; 291 } 292 } else if (_library != null) { 293 return _library; 294 } else { 295 return null; 296 } 297 } 298 299 protected File getFilterFile() { 300 TableauFrame tableauFrame = this._frame; 301 Attribute moduleAttribute = tableauFrame.getTableau().getAttribute( 302 "_filterModule"); 303 Attribute relativePathAttribute = tableauFrame.getTableau() 304 .getAttribute("_filterRelativePath"); 305 if (moduleAttribute == null || relativePathAttribute == null) { 306 return null; 307 } else { 308 try { 309 String moduleName = ((StringAttribute) moduleAttribute) 310 .getExpression(); 311 String relativePath = ((StringAttribute) relativePathAttribute) 312 .getExpression(); 313 // NOTE: Should this be getModuleByStemName? Be sure to test on 314 // installation. Won't matter at the moment because it's only 315 // used in sensor-view module. 316 Module module = ModuleTree.instance().getModule(moduleName); 317 File filterFile = new File(module.getDir(), relativePath); 318 if (filterFile.exists()) { 319 return filterFile; 320 } else { 321 return null; 322 } 323 } catch (ClassCastException ex) { 324 System.err 325 .println("Unable to cast attributes _filterModule and _filterRelativePath to StringAttribute"); 326 return null; 327 } 328 } 329 } 330 331 public void reinitializeTab() { 332 this.removeAll(); 333 this.initializeTab(); 334 this.updateUI(); 335 this.repaint(); 336 } 337 338 /* 339 * org.ecoinformatics.seek.ecogrid.SimpleLibrarySearchGUIPane 340 * org.kepler.gui.SimpleSearchUIPane 341 */ 342 protected void initLibrarySearchPane() { 343 344 _librarySearchPane = new SimpleSearchUIPane(_searchButtonHandler); 345 if (_librarySearchPane == null) { 346 System.out.println("error: _searchPane is null. " + "This " 347 + "problem can be fixed by adding a librarySearchGUIPane " 348 + "property in the configuration.xml file."); 349 } 350 351 } 352 353 /* 354 * org.ecoinformatics.seek.ecogrid.SimpleLibrarySearcher 355 * org.kepler.gui.SimpleChoiceLibrarySearcher 356 * org.kepler.gui.SimpleLibrarySearcher Other possible search techniques can 357 * be substituted here. this would include the ontological lookup scheme 358 * that requires sparrow support 359 */ 360 protected void initLibrarySearcher() { 361 362 _librarySearcher = new SimpleLibrarySearcher(_library, 363 _librarySearchPane); 364 if (_librarySearcher == null) { 365 System.out 366 .println("error: librarySearcher is null. This " 367 + "problem can be fixed by adding a librarySearcherFactory " 368 + "property in the configuration.xml file."); 369 } 370 371 } 372 373 protected void initOntSelectBox() { 374 375 OntologyCatalog oc = OntologyCatalog.instance(); 376 _ontSelectBox = new JComboBox(); 377 _ontSelectBox.addItem(allOntologiesName); 378 Iterator<String> onts = oc.getLibraryOntologyNames(); 379 while (onts.hasNext()) { 380 _ontSelectBox.addItem(onts.next()); 381 } 382 _ontSelectBox.addActionListener(_ontSelectHandler); 383 _ontSelectBox.setRenderer(new IconListRenderer()); 384 385 for (String l : _localRepoManager.getLocalRepositories().values()) { 386 _ontSelectBox.addItem(l); 387 } 388 389 this.add(_ontSelectBox, BorderLayout.NORTH); 390 391 } 392 393 /* 394 * org.kepler.gui.ResultTreeRebuilder 395 * org.ecoinformatics.seek.ecogrid.ResultHighlighter 396 * org.ecoinformatics.seek.ecogrid.ResultsLister 397 */ 398 protected void initLibraryPanel() { 399 400 try { 401 _libraryPanel = new ResultTreeRebuilder(_library, null); 402 if (_libraryPanel == null) { 403 System.out.println("error: _libraryPanel is null. "); 404 } 405 } catch (IllegalActionException iae) { 406 System.out.println("Error displaying search results: " + iae); 407 } 408 409 } 410 411 public JTree getJTree() { 412 return _library; 413 } 414 415 public class IconListRenderer extends DefaultListCellRenderer { 416 417 public Component getListCellRendererComponent(JList list, Object value, 418 int index, boolean isSelected, boolean cellHasFocus) { 419 420 JLabel label = (JLabel) super.getListCellRendererComponent(list, 421 value, index, isSelected, cellHasFocus); 422 423 if (label.getText().equals(allOntologiesName)) { 424 // No Icon 425 } else if (_localRepoManager.isLocalRepositoryName(label.getText())) { 426 label.setIcon(_folClosedIcon); 427 } else { 428 label.setIcon(_ontClosedIcon); 429 } 430 return label; 431 432 } 433 } 434 435 /** 436 * class to handle the search button 437 * 438 * @author berkley 439 * @since February 17, 2005 440 */ 441 public class SearchButtonActionHandler implements ActionListener { 442 /** 443 * Description of the Method 444 * 445 * @param e 446 * Description of the Parameter 447 */ 448 public void actionPerformed(ActionEvent e) { 449 450 if (isDebugging) { 451 log.debug("SearchButtonActionHandler.actionPerformed(ActionEvent)"); 452 } 453 454 Component component = null; 455 456 try { 457 /* 458 * Wait cursor is not set when hitting enter in text field. 459 * http://bugzilla.ecoinformatics.org/show_bug.cgi?id=5581 460 * 461 * However this doesn't help: 462 * 463 if (e.getSource() != null){ 464 component = ((Component)e.getSource()).getParent(); 465 while (component != null){ 466 component = component.getParent(); 467 if (component instanceof ComponentLibraryTab){ 468 component.requestFocus(); 469 component.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 470 break; 471 } 472 } 473 } 474 */ 475 476 setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 477 478 // need to disable the action listener here so update() isn't 479 // called twice 480 _ontSelectBox.removeActionListener(_ontSelectHandler); 481 _ontSelectBox.setSelectedItem(allOntologiesName); 482 _ontSelectBox.addActionListener(_ontSelectHandler); 483 484 String searchTerm = _librarySearchPane.getSearchTerm(); 485 if (isDebugging) 486 log.debug("Search term is '" + searchTerm + "'"); 487 Long totalSearchTime = System.currentTimeMillis(); 488 Long searchTime = System.currentTimeMillis(); 489 LibrarySearchResults searchResults = _librarySearcher.search( 490 searchTerm, AUTHENTICATE); 491 if (isDebugging) 492 log.debug("Library search completed in " 493 + (System.currentTimeMillis() - searchTime) + "ms"); 494 searchTime = System.currentTimeMillis(); 495 _libraryPanel.update(searchResults); 496 if (isDebugging) 497 log.debug("Library updated in " 498 + (System.currentTimeMillis() - searchTime) + "ms"); 499 if (isDebugging) 500 log.debug("Total search time was " 501 + (System.currentTimeMillis() - totalSearchTime) 502 + "ms"); 503 504 } catch (RepositoryException re) { 505 re.printStackTrace(); 506 MessageHandler 507 .error("There was a problem searching the Repository. Please check your network connection.\n", 508 re); 509 } catch (AuthenticationException ae) { 510 if (ae.getType() != AuthenticationException.USER_CANCEL) { 511 MessageHandler 512 .error("Authentication error. Please ensure your username and password were spelled correctly,\nand verify your network connection\n", 513 ae); 514 ae.printStackTrace(); 515 } 516 } catch (Exception exception) { 517 exception.printStackTrace(); 518 MessageHandler.error("Error.\n", exception); 519 } finally { 520 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 521 /* 522 * Wait cursor is not set when hitting enter in text field. 523 * http://bugzilla.ecoinformatics.org/show_bug.cgi?id=5581 524 * 525 * However this doesn't help: 526 * 527 if (component != null){ 528 component.requestFocus(); 529 component.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 530 } 531 */ 532 } 533 } 534 535 } 536 537 /** 538 * Listener used to changes from the NewFolderFrame 539 */ 540 public class LibraryActionHandler implements ActionListener { 541 /** 542 * Description of the Method 543 * 544 * @param event 545 * Description of Parameter 546 */ 547 public void actionPerformed(ActionEvent event) { 548 if (isDebugging) { 549 log.debug("LibraryActionHandler.actionPerformed(ActionEvent)"); 550 } 551 String command = event.getActionCommand(); 552 if (command.equals("new_folder_created") 553 || command.equals("new_actor_created")) { 554 // _library.clearSelection(); //clear the current selections 555 // LibrarySearchResultPane.collapseAll(_library); 556 /* 557 * TreeAction action = (TreeAction)event.getSource(); TreePath 558 * path = action.getPath(); _library.addSelectionPath(path); 559 * System.out.println("path expanded."); 560 * //LibrarySearchResultPane.expandAll(_library); 561 * _library.expandPath(path); 562 */ 563 } 564 } 565 } 566 567 /** 568 * Inner class to handle changes to the Ontology Selection box. 569 * 570 * @author Aaron Schultz 571 */ 572 public class OntSelectActionHandler implements ActionListener { 573 private boolean _actionDisabled = false; 574 575 public void disableAction(boolean actionDisabled) { 576 _actionDisabled = actionDisabled; 577 } 578 579 public void actionPerformed(ActionEvent e) { 580 if (!_actionDisabled) { 581 582 if (e.getSource() == _ontSelectBox) { 583 584 String selectedOntology = (String) _ontSelectBox 585 .getSelectedItem(); 586 587 try { 588 589 if (selectedOntology.equals(allOntologiesName)) { 590 _libraryPanel.update(new LibrarySearchResults()); 591 } else { 592 EntityLibrary selOntLibrary = null; 593 int cnt = _libraryModel.getChildCount(_libraryModel 594 .getRoot()); 595 for (int i = 0; i < cnt; i++) { 596 NamedObj child = (NamedObj) _libraryModel 597 .getChild(_libraryModel.getRoot(), i); 598 if (child.getName().equals(selectedOntology)) { 599 if (child instanceof EntityLibrary) { 600 selOntLibrary = (EntityLibrary) child; 601 } 602 break; 603 } 604 } 605 if (selOntLibrary == null) { 606 String message = "No Components found in " 607 + selectedOntology; 608 JOptionPane.showMessageDialog(getParentFrame(), 609 message); 610 _libraryPanel 611 .update(new LibrarySearchResults()); 612 _ontSelectBox 613 .setSelectedItem(allOntologiesName); 614 } else { 615 ((ResultTreeRebuilder) _libraryPanel) 616 .update(selOntLibrary); 617 _librarySearchPane.clearSearch(); 618 } 619 } 620 } catch (IllegalActionException iae) { 621 // FIXME: handle this exception correctly 622 System.out.println("Error searching: " 623 + iae.getMessage()); 624 // iae.printStackTrace(); 625 } 626 } 627 } 628 } 629 } 630 631 /** 632 * A factory that creates the library panel for the editors. 633 * 634 * @author Aaron Schultz 635 */ 636 public static class Factory extends TabPaneFactory { 637 /** 638 * Create a factory with the given name and container. 639 * 640 * @param container 641 * The container. 642 * @param name 643 * The name of the entity. 644 * @exception IllegalActionException 645 * If the container is incompatible with this attribute. 646 * @exception NameDuplicationException 647 * If the name coincides with an attribute already in the 648 * container. 649 */ 650 public Factory(NamedObj container, String name) 651 throws IllegalActionException, NameDuplicationException { 652 super(container, name); 653 } 654 655 /** 656 * Create a library pane that displays the given library of actors. 657 * 658 * @return A new LibraryPaneTab that displays the library 659 */ 660 public TabPane createTabPane(TableauFrame parent) { 661 ComponentLibraryTab clt = new ComponentLibraryTab(parent); 662 clt.setTabName(this.getName()); 663 return clt; 664 } 665 } 666}