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 030// LibraryIndex.item() 031// LibraryIndexComponentItem.getLSID() 032// CacheManager.getInstance().getObject(lsid) 033// ActorCacheObject.getMetadata().getActorAsNamedObject() 034// ActorCacheObject aco = (ActorCacheObject)cacheMan.getObject(new KeplerLSID(lsidString)); 035// ActorMetadata am = aco.getMetadata(); 036// NamedObj no = am.getActorAsNamedObj(null); 037 038package org.kepler.sms.gui; 039 040import java.awt.Dimension; 041import java.awt.Frame; 042import java.awt.event.ActionEvent; 043import java.awt.event.ActionListener; 044import java.util.Iterator; 045import java.util.Vector; 046 047import javax.swing.BorderFactory; 048import javax.swing.Box; 049import javax.swing.BoxLayout; 050import javax.swing.JButton; 051import javax.swing.JDialog; 052import javax.swing.JLabel; 053import javax.swing.JOptionPane; 054import javax.swing.JPanel; 055import javax.swing.JScrollPane; 056 057import org.kepler.gui.GraphicalActorMetadata; 058import org.kepler.objectmanager.ActorMetadata; 059import org.kepler.objectmanager.cache.ActorCacheObject; 060import org.kepler.objectmanager.cache.CacheManager; 061import org.kepler.objectmanager.lsid.KeplerLSID; 062import org.kepler.sms.SMSServices; 063import org.kepler.sms.SemanticTypeManager; 064 065import ptolemy.kernel.ComponentEntity; 066import ptolemy.kernel.util.NamedObj; 067import ptolemy.kernel.util.Workspace; 068import ptolemy.moml.EntityLibrary; 069import ptolemy.vergil.tree.EntityTreeModel; 070import ptolemy.vergil.tree.PTree; 071import ptolemy.vergil.tree.VisibleTreeModel; 072 073/** 074 */ 075public class SuggestCompatibleOperation { 076 077 // ////////////////////////////////////////////////////////////////////// 078 // PUBLIC MEMBERS 079 080 public static int OUTPUT = 1; 081 public static int INPUT = 2; 082 public static int COMPONENTS = 3; 083 084 // ////////////////////////////////////////////////////////////////////// 085 // PUBLIC CONSTRUCTORS 086 087 /** 088 * Constructor 089 */ 090 public SuggestCompatibleOperation(Frame owner, NamedObj entity, int op) { 091 _owner = owner; 092 _entity = entity; 093 // check for op type 094 if (op == OUTPUT) 095 _suggestOutput(); 096 else if (op == INPUT) 097 _suggestInput(); 098 else if (op == COMPONENTS) 099 _suggestComponents(); 100 } 101 102 // ////////////////////////////////////////////////////////////////////// 103 // PRIVATE METHODS 104 105 /** 106 * Private method for performing output operation 107 */ 108 private void _suggestOutput() { 109 // make sure output types exist 110 if (SMSServices.getAllOutputSemanticTypes(_entity).size() == 0) { 111 String msg = "No output semantic type annotations defined" 112 + " for this component."; 113 JOptionPane.showMessageDialog(_owner, msg, 114 "Suggest Compatible Outputs", JOptionPane.ERROR_MESSAGE); 115 return; 116 } 117 // do the input search 118 _searchForInput(); 119 if (_components.size() == 0) { 120 String msg = "No compatible components found in actor library" 121 + " for output types."; 122 JOptionPane.showMessageDialog(_owner, msg, 123 "Suggest Compatible Outputs", JOptionPane.ERROR_MESSAGE); 124 return; 125 } 126 // display results (if any) 127 _displayResults(); 128 } 129 130 /** 131 * Private method for performing input operation 132 */ 133 private void _suggestInput() { 134 // make sure output types exist 135 if (SMSServices.getAllInputSemanticTypes(_entity).size() == 0) { 136 String msg = "No input semantic type annotations defined for" 137 + " this component."; 138 JOptionPane.showMessageDialog(_owner, msg, 139 "Suggest Compatible Outputs", JOptionPane.ERROR_MESSAGE); 140 return; 141 } 142 // do the input search 143 _searchForOutput(); 144 if (_components.size() == 0) { 145 String msg = "No compatible components found in actor library" 146 + " for output types."; 147 JOptionPane.showMessageDialog(_owner, msg, 148 "Suggest Compatible Outputs", JOptionPane.ERROR_MESSAGE); 149 return; 150 } 151 // display results (if any) 152 _displayResults(); 153 } 154 155 /** 156 * Private method for performing component operation 157 */ 158 private void _suggestComponents() { 159 // make sure the actor has at least a semantic type (category or port) 160 if (SMSServices.getAllInputSemanticTypes(_entity).size() == 0 161 && SMSServices.getAllOutputSemanticTypes(_entity).size() == 0 162 && SMSServices.getActorSemanticTypes(_entity).size() == 0) { 163 String msg = "No semantic type annotations are defined" 164 + " for this component."; 165 JOptionPane.showMessageDialog(_owner, msg, 166 "Suggest Compatible Outputs", JOptionPane.ERROR_MESSAGE); 167 return; 168 } 169 // do the input search 170 _searchForComponents(); 171 if (_components.size() == 0) { 172 String msg = "No compatible components found in actor library."; 173 JOptionPane.showMessageDialog(_owner, msg, 174 "Suggest Compatible Outputs", JOptionPane.ERROR_MESSAGE); 175 return; 176 } 177 // display results (if any) 178 _displayResults(); 179 } 180 181 /** 182 * Private method for performing search for matching input 183 * 184 * @param semTypes 185 * a set of semantic types to search for 186 * @return a set of matching components 187 */ 188 private void _searchForInput() { 189 // build hashtable of port types 190 _buildOutputPortMgr(); 191 // get the list of components 192 _buildInputComponents(); 193 // match component types to those in port manager 194 _filterInputComponents(); 195 } 196 197 /** 198 * Private method for performing search for matching input 199 * 200 * @param semTypes 201 * a set of semantic types to search for 202 * @return a set of matching components 203 */ 204 private void _searchForOutput() { 205 // build hashtable of port types 206 _buildInputPortMgr(); 207 // get the list of components 208 _buildOutputComponents(); 209 // match component types to those in port manager 210 _filterOutputComponents(); 211 } 212 213 private void _searchForComponents() { 214 // find components with compatible semantic type categorizations 215 _buildSimilarComponents(); 216 _filterSimilarComponents(); 217 } 218 219 /** 220 * Private method to build a hash table of ports (keys) and their semantic 221 * types (as named ont classes) 222 */ 223 private void _buildOutputPortMgr() { 224 Iterator portIter = SMSServices.getAllOutputPorts(_entity).iterator(); 225 while (portIter.hasNext()) { 226 Object port = portIter.next(); 227 _portMgr.addObject(port); 228 Iterator typeIter = SMSServices.getPortSemanticTypes(port) 229 .iterator(); 230 while (typeIter.hasNext()) 231 _portMgr.addType(port, typeIter.next()); 232 } 233 _portMgr.pruneUntypedObjects(); 234 } 235 236 /** 237 * Private method to build a hash table of ports (keys) and their semantic 238 * types (as named ont classes) 239 */ 240 private void _buildInputPortMgr() { 241 Iterator portIter = SMSServices.getAllInputPorts(_entity).iterator(); 242 while (portIter.hasNext()) { 243 Object port = portIter.next(); 244 _portMgr.addObject(port); 245 Iterator typeIter = SMSServices.getPortSemanticTypes(port) 246 .iterator(); 247 while (typeIter.hasNext()) 248 _portMgr.addType(port, typeIter.next()); 249 } 250 _portMgr.pruneUntypedObjects(); 251 } 252 253 /** 254 * Private method to build a list of components to search over. Components 255 * are those within the actor library that are not entity libraries and that 256 * have at least one output semantic type. The result is stored in 257 * _components 258 */ 259 private void _buildOutputComponents() { 260 Iterator<NamedObj> nodes = _getComponents().iterator(); 261 while (nodes.hasNext()) { 262 NamedObj node = nodes.next(); 263 // check if it has any input semantic types 264 if (SMSServices.getAllOutputSemanticTypes(node).size() != 0) { 265 if (!_componentExists(node)) 266 _components.add(node); 267 } 268 } 269 } 270 271 /** 272 * Private method to build a list of components to search over. Components 273 * are those within the actor library that are not entity libraries and that 274 * have at least one input semantic type. The result is stored in 275 * _components 276 */ 277 private void _buildInputComponents() { 278 Iterator<NamedObj> nodes = _getComponents().iterator(); 279 while (nodes.hasNext()) { 280 NamedObj node = nodes.next(); 281 // check if it has any input semantic types 282 if (SMSServices.getAllInputSemanticTypes(node).size() != 0) { 283 if (!_componentExists(node)) 284 _components.add(node); 285 } 286 } 287 } 288 289 /** 290 * Private method to build a list of components to search over. Components 291 * are those within the actor library that are not entity libraries and that 292 * have at least one input, output, or category semantic type. The result is 293 * stored in _components 294 */ 295 private void _buildSimilarComponents() { 296 try { 297 Iterator<NamedObj> nodes = _getComponents().iterator(); 298 while (nodes.hasNext()) { 299 NamedObj node = nodes.next(); 300 // check if it has any input semantic types 301 if (SMSServices.getActorSemanticTypes(node).size() != 0 302 || SMSServices.getAllInputSemanticTypes(node).size() != 0 303 || SMSServices.getAllOutputSemanticTypes(node).size() != 0) { 304 if (!_componentExists(node)) 305 _components.add(node); 306 } 307 } 308 } catch (Exception e) { 309 e.printStackTrace(); 310 } 311 312 } 313 314 /** 315 * Private method that retrieves the components in the library as 316 * NamedObj's, i.e., actual, instantiated actors. 317 */ 318 private Vector<NamedObj> _getComponents() { 319 Vector<NamedObj> result = new Vector<NamedObj>(); 320 try { 321 322 CacheManager manager = CacheManager.getInstance(); 323 Vector<KeplerLSID> cachedLsids = manager.getCachedLsids(); 324 for (KeplerLSID lsid : cachedLsids) { 325 try{ 326 ActorCacheObject aco = (ActorCacheObject) CacheManager 327 .getInstance().getObject(lsid); 328 ActorMetadata am = aco.getMetadata(); 329 GraphicalActorMetadata gam = new GraphicalActorMetadata(am); 330 NamedObj node = gam.getActorAsNamedObj(null); 331 result.add(node); 332 } 333 catch(ClassCastException cce){ 334 // can no longer assume all items in library can be cast 335 // to ActorCacheObject. just skip these. 336 } 337 } 338 } catch (Exception e) { 339 e.printStackTrace(); 340 } 341 return result; 342 } 343 344 /** 345 * Checks for like named components 346 */ 347 private boolean _componentExists(NamedObj obj) { 348 String str = obj.getName(); 349 Iterator<NamedObj> compIter = _components.iterator(); 350 while (compIter.hasNext()) { 351 NamedObj comp = compIter.next(); 352 if (str.equals(comp.getName())) 353 return true; 354 } 355 return false; 356 } 357 358 /** 359 * This is the main algorithm for checking. Looks at output ports 360 * individually, and checks if any input ports are supertypes. Note this 361 * could be further generalized to support additional types of checking, 362 * e.g., across output/input ports. 363 */ 364 private void _filterOutputComponents() { 365 Vector<NamedObj> results = new Vector<NamedObj>(); 366 367 // nothing to filter 368 if (_components.size() == 0) 369 return; 370 371 Iterator<NamedObj> compIter = _components.iterator(); 372 while (compIter.hasNext()) { 373 boolean comp_is_match = false; 374 NamedObj comp = compIter.next(); 375 // for each input port, check comp output ports 376 Iterator inPortIter = _portMgr.getObjects().iterator(); 377 while (!comp_is_match && inPortIter.hasNext()) { 378 // get the input sem types 379 Vector inSemTypes = _portMgr.getTypes(inPortIter.next()); 380 // get the output ports 381 Iterator outPortIter = SMSServices.getAllOutputPorts( 382 comp).iterator(); 383 while (!comp_is_match && outPortIter.hasNext()) { 384 // get the input sem types 385 Vector outSemTypes = SMSServices 386 .getPortSemanticTypes(outPortIter.next()); 387 if (SMSServices.compare(outSemTypes, inSemTypes) == SMSServices.COMPATIBLE) { 388 comp_is_match = true; 389 results.add(comp); 390 } 391 } 392 } 393 } 394 _components = results; 395 } 396 397 /** 398 * This is the main algorithm for checking. Looks at output ports 399 * individually, and checks if any input ports are supertypes. Note this 400 * could be further generalized to support additional types of checking, 401 * e.g., across output/input ports. 402 */ 403 private void _filterInputComponents() { 404 Vector<NamedObj> results = new Vector<NamedObj>(); 405 406 // nothing to filter 407 if (_components.size() == 0) 408 return; 409 410 Iterator<NamedObj> compIter = _components.iterator(); 411 while (compIter.hasNext()) { 412 boolean comp_is_match = false; 413 NamedObj comp = compIter.next(); 414 // for each output port, check comp input ports 415 Iterator outPortIter = _portMgr.getObjects().iterator(); 416 while (!comp_is_match && outPortIter.hasNext()) { 417 // get the output sem types 418 Vector outSemTypes = _portMgr.getTypes(outPortIter.next()); 419 // get the input ports 420 Iterator inPortIter = SMSServices.getAllInputPorts( 421 comp).iterator(); 422 while (!comp_is_match && inPortIter.hasNext()) { 423 // get the input sem types 424 Vector inSemTypes = SMSServices 425 .getPortSemanticTypes(inPortIter.next()); 426 if (SMSServices.compare(outSemTypes, inSemTypes) == SMSServices.COMPATIBLE) { 427 comp_is_match = true; 428 results.add(comp); 429 } 430 } 431 } 432 } 433 _components = results; 434 } 435 436 private void _filterSimilarComponents() { 437 if (SMSServices.getActorSemanticTypes(_entity).size() != 0) 438 _filterSimilarComponentType(); 439 if (SMSServices.getAllInputSemanticTypes(_entity).size() != 0) 440 _filterSimilarComponentInput(); 441 if (SMSServices.getAllOutputSemanticTypes(_entity).size() != 0) 442 _filterSimilarComponentOutput(); 443 } 444 445 private void _filterSimilarComponentType() { 446 Vector<NamedObj> results = new Vector<NamedObj>(); 447 // nothing to filter 448 if (_components.size() == 0) 449 return; 450 Iterator<NamedObj> compIter = _components.iterator(); 451 while (compIter.hasNext()) { 452 boolean comp_is_match = false; 453 NamedObj comp = compIter.next(); 454 Vector subTypes = SMSServices.getActorSemanticTypes(comp); 455 Iterator typeIter = SMSServices.getActorSemanticTypes(_entity) 456 .iterator(); 457 while (!comp_is_match && typeIter.hasNext()) { 458 Vector superTypes = new Vector(); 459 superTypes.add(typeIter.next()); 460 if (SMSServices.compare(subTypes, superTypes) == SMSServices.COMPATIBLE) { 461 comp_is_match = true; 462 results.add(comp); 463 } 464 } 465 } 466 _components = results; 467 } 468 469 private void _filterSimilarComponentInput() { 470 Vector<NamedObj> results = new Vector<NamedObj>(); 471 // nothing to filter 472 if (_components.size() == 0) 473 return; 474 SemanticTypeManager manager = _inputPortManager(); 475 Iterator<NamedObj> compIter = _components.iterator(); 476 while (compIter.hasNext()) { 477 boolean comp_is_match = false; 478 NamedObj comp = compIter.next(); 479 // for each output port, check comp input ports 480 Iterator portIter = manager.getObjects().iterator(); 481 while (!comp_is_match && portIter.hasNext()) { 482 // get the search item input sem types 483 Vector superTypes = manager.getTypes(portIter.next()); 484 // get the component input ports 485 Iterator inPortIter = SMSServices.getAllInputPorts( 486 (NamedObj) comp).iterator(); 487 while (!comp_is_match && inPortIter.hasNext()) { 488 // get the input sem types 489 Vector subTypes = SMSServices 490 .getPortSemanticTypes(inPortIter.next()); 491 if (SMSServices.compare(subTypes, superTypes) == SMSServices.COMPATIBLE) { 492 comp_is_match = true; 493 results.add(comp); 494 } 495 } 496 } 497 } 498 _components = results; 499 } 500 501 private void _filterSimilarComponentOutput() { 502 Vector<NamedObj> results = new Vector<NamedObj>(); 503 // nothing to filter 504 if (_components.size() == 0) 505 return; 506 SemanticTypeManager manager = _outputPortManager(); 507 Iterator<NamedObj> compIter = _components.iterator(); 508 while (compIter.hasNext()) { 509 boolean comp_is_match = false; 510 NamedObj comp = compIter.next(); 511 // for each output port, check comp input ports 512 Iterator portIter = manager.getObjects().iterator(); 513 while (!comp_is_match && portIter.hasNext()) { 514 // get the search item input sem types 515 Vector subTypes = manager.getTypes(portIter.next()); 516 // get the component output ports 517 Iterator outPortIter = SMSServices.getAllOutputPorts( 518 (NamedObj) comp).iterator(); 519 while (!comp_is_match && outPortIter.hasNext()) { 520 // get the output sem types 521 Vector superTypes = SMSServices 522 .getPortSemanticTypes(outPortIter.next()); 523 if (SMSServices.compare(subTypes, superTypes) == SMSServices.COMPATIBLE) { 524 comp_is_match = true; 525 results.add(comp); 526 } 527 } 528 } 529 } 530 _components = results; 531 } 532 533 private SemanticTypeManager _inputPortManager() { 534 SemanticTypeManager manager = new SemanticTypeManager(); 535 Iterator portIter = SMSServices.getAllInputPorts(_entity).iterator(); 536 while (portIter.hasNext()) { 537 Object port = portIter.next(); 538 manager.addObject(port); 539 Iterator typeIter = SMSServices.getPortSemanticTypes(port) 540 .iterator(); 541 while (typeIter.hasNext()) 542 manager.addType(port, typeIter.next()); 543 } 544 manager.pruneUntypedObjects(); 545 return manager; 546 } 547 548 private SemanticTypeManager _outputPortManager() { 549 SemanticTypeManager manager = new SemanticTypeManager(); 550 Iterator portIter = SMSServices.getAllOutputPorts(_entity).iterator(); 551 while (portIter.hasNext()) { 552 Object port = portIter.next(); 553 manager.addObject(port); 554 Iterator typeIter = SMSServices.getPortSemanticTypes(port) 555 .iterator(); 556 while (typeIter.hasNext()) 557 manager.addType(port, typeIter.next()); 558 } 559 manager.pruneUntypedObjects(); 560 return manager; 561 } 562 563 /** 564 * Private method to draw a simple dialog of search matches. 565 */ 566 private void _displayResults() { 567 // the dialog for viewing results 568 final JDialog dialog = new JDialog(); 569 dialog.setTitle("Search Results"); 570 571 // overall panel for the dialog 572 JPanel panel = new JPanel(); 573 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 574 panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 575 576 // set up the button 577 JButton closeBtn = new JButton("Close"); 578 closeBtn.setActionCommand("close"); 579 closeBtn.addActionListener(new ActionListener() { 580 public void actionPerformed(ActionEvent e) { 581 if (e.getActionCommand().equals("close")) 582 dialog.dispose(); 583 } 584 }); 585 586 // label 587 JPanel panel1 = new JPanel(); 588 panel1.setLayout(new BoxLayout(panel1, BoxLayout.X_AXIS)); 589 panel1.add(new JLabel("Suggeted Components (drag to canvas):")); 590 panel1.add(Box.createHorizontalGlue()); 591 592 // close button 593 JPanel panel2 = new JPanel(); 594 panel2.setLayout(new BoxLayout(panel2, BoxLayout.X_AXIS)); 595 panel2.add(Box.createHorizontalGlue()); 596 panel2.add(closeBtn); 597 598 // add everything to the main panel 599 panel.add(panel1); 600 panel.add(Box.createRigidArea(new Dimension(0, 5))); 601 panel.add(new JScrollPane(_buildResultTree())); 602 panel.add(Box.createRigidArea(new Dimension(0, 10))); 603 panel.add(panel2); 604 605 // add main panel to the dialog and show it 606 dialog.add(panel); 607 dialog.pack(); 608 dialog.show(); 609 } 610 611 /** 612 * Construct the visual tree widget showing a list of results. 613 */ 614 private PTree _buildResultTree() { 615 EntityLibrary root = new EntityLibrary(); 616 Workspace workspace = root.workspace(); 617 EntityTreeModel model = new VisibleTreeModel(root); 618 619 Iterator<NamedObj> compIter = _components.iterator(); 620 while (compIter.hasNext()) { 621 try { 622 NamedObj entity = compIter.next(); 623 // add to the tree 624 NamedObj obj = (NamedObj) entity.clone(workspace); 625 if (obj instanceof ComponentEntity) 626 ((ComponentEntity) obj).setContainer(root); 627 } catch (Exception e) { 628 e.printStackTrace(); 629 } 630 } 631 632 PTree resultTree = new PTree(model); 633 resultTree.setRootVisible(false); 634 resultTree.setMinimumSize(new Dimension(120, 100)); 635 resultTree.setMaximumSize(new Dimension(120, 100)); 636 637 return resultTree; 638 } 639 640 // ////////////////////////////////////////////////////////////////////////////// 641 // PRIVATE MEMBERS 642 643 private Frame _owner; 644 private NamedObj _entity; 645 private int _op; 646 647 private Vector<NamedObj> _components = new Vector<NamedObj>(); 648 private SemanticTypeManager _portMgr = new SemanticTypeManager(); 649 650}