001/* 002 * Copyright (c) 2004-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2014-08-13 22:56:02 +0000 (Wed, 13 Aug 2014) $' 007 * '$Revision: 32876 $' 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.objectmanager.library; 031 032import java.io.File; 033import java.io.IOException; 034import java.lang.ref.WeakReference; 035import java.sql.Connection; 036import java.sql.PreparedStatement; 037import java.sql.ResultSet; 038import java.sql.SQLException; 039import java.sql.Statement; 040import java.util.Hashtable; 041import java.util.LinkedList; 042import java.util.List; 043import java.util.Map; 044import java.util.Vector; 045import java.util.WeakHashMap; 046 047import javax.swing.JTree; 048import javax.swing.event.TreeExpansionEvent; 049import javax.swing.event.TreeExpansionListener; 050import javax.swing.tree.TreePath; 051 052import org.apache.commons.logging.Log; 053import org.apache.commons.logging.LogFactory; 054import org.kepler.gui.FilteredVisibleTreeModel; 055import org.kepler.icon.ComponentEntityConfig; 056import org.kepler.kar.KARCacheContent; 057import org.kepler.kar.KARCacheManager; 058import org.kepler.kar.KARFile; 059import org.kepler.moml.FolderEntityLibrary; 060import org.kepler.moml.KAREntityLibrary; 061import org.kepler.moml.KARErrorEntityLibrary; 062import org.kepler.moml.NamedObjId; 063import org.kepler.moml.OntologyEntityLibrary; 064import org.kepler.objectmanager.cache.CacheManager; 065import org.kepler.objectmanager.lsid.KeplerLSID; 066import org.kepler.util.StatusNotifier; 067import org.kepler.util.sql.DatabaseFactory; 068 069import ptolemy.actor.gui.TableauFrame; 070import ptolemy.data.expr.Parameter; 071import ptolemy.kernel.ComponentEntity; 072import ptolemy.kernel.CompositeEntity; 073import ptolemy.kernel.util.Attribute; 074import ptolemy.kernel.util.IllegalActionException; 075import ptolemy.kernel.util.NameDuplicationException; 076import ptolemy.kernel.util.StringAttribute; 077import ptolemy.kernel.util.Workspace; 078import ptolemy.moml.EntityLibrary; 079import ptolemy.vergil.tree.EntityTreeModel; 080import ptolemy.vergil.tree.VisibleTreeModel; 081 082/** 083 * The LibraryManager is used for managing the Actor Library. It maintains an 084 * index for increased performance. Any code that adds, updates, or removes 085 * items in the library should use the LibraryManager class directly. 086 * 087 *@author Aaron Schultz 088 */ 089public class LibraryManager implements TreeExpansionListener { 090 private static class LibraryManagerHolder { 091 private static final LibraryManager INSTANCE = new LibraryManager(); 092 } 093 094 private static final Log log = LogFactory.getLog(LibraryManager.class 095 .getName()); 096 private static final boolean isDebugging = log.isDebugEnabled(); 097 098 /** 099 * The LIID_LABEL is used as the name of the String Attribute that is 100 * attached to Tree Items to keep track of their Library Index ID. 101 */ 102 public static final String LIID_LABEL = "_LIID"; 103 104 /** A mapping of tree to a list of tree paths that are expanded in it. */ 105 private static final Map<JTree,List<TreePath>> _treeExpansionMap = new WeakHashMap<JTree,List<TreePath>>(); 106 107 /** 108 * Method for getting an instance of this singleton class. 109 */ 110 public static LibraryManager getInstance() { 111 return LibraryManagerHolder.INSTANCE; 112 } 113 114 /** 115 * Return the Library Index ID for the given NamedObj or -1 if an ID cannot 116 * be found. 117 * 118 * @param obj 119 * a NamedObj from the Library tree. 120 * @return int Library Index ID or 121 */ 122 public static int getLiidFor(ComponentEntity obj) { 123 if (isDebugging) 124 log.debug("getLiidFor(" + obj.getName() + ")"); 125 int liid = -1; 126 try { 127 Attribute liidAttribute = obj 128 .getAttribute(LibraryManager.LIID_LABEL); 129 if (liidAttribute == null) { 130 return -1; 131 } 132 if (liidAttribute instanceof StringAttribute) { 133 StringAttribute liidSA = (StringAttribute) liidAttribute; 134 liid = Integer.parseInt(liidSA.getExpression()); 135 } else { 136 liid = -1; 137 } 138 } catch (Exception e) { 139 liid = -1; 140 } 141 return liid; 142 } 143 144 /** 145 * This is the composite entity version of the library. 146 */ 147 private CompositeEntity _actorLibrary; 148 149 /** 150 * This is the workspace passed to us from 151 * ptolemy.actor.gui.UserActorLibrary It is the top level workspace. 152 */ 153 private Workspace _actorLibraryWorkspace = null; 154 155 /** 156 * The LibIndex is used to build the Actor Library. 157 */ 158 private LibIndex _libIndex; 159 160 /** 161 * This is the EntityTreeModel version of the library, used in 162 * AnnotatedPTree. 163 */ 164 private VisibleTreeModel _libraryModel; 165 166 /** 167 * Convenience reference 168 */ 169 private Connection _conn; 170 171 /** 172 * Convenience reference. Make sure to close your ResultSets since we're 173 * reusing the Statement. 174 */ 175 private Statement _stmt; 176 177 /** 178 * JTrees that contain the library can be added to the library manager so 179 * they can be refreshed whenever the library changes. 180 */ 181// private Vector<JTree> _trees = new Vector<JTree>(); 182 private Vector<WeakReference<JTree>> _trees = new Vector<WeakReference<JTree>>(); 183 184 // PreparedStatements 185 private PreparedStatement _getPopulateInfoForLIIDPrepStmt; 186 private PreparedStatement _getLSIDForLIIDPrepStmt; 187 private PreparedStatement _getNameValueForLIIDPrepStmt; 188 189 /** 190 * constructor called from getInstance() 191 */ 192 public LibraryManager() { 193 if (isDebugging) 194 log.debug("Instantiate LibraryManager"); 195 196 try { 197 _conn = DatabaseFactory.getDBConnection(); 198 _stmt = _conn.createStatement(); 199 200 _getPopulateInfoForLIIDPrepStmt = _conn.prepareStatement( 201 "SELECT PARENT,LFT,RGT,LEVEL,LSID,TYPE,NAME FROM " 202 + LibIndex.LIBRARY_INDEX_TABLE_NAME + " WHERE LIID = ?"); 203 204 _getLSIDForLIIDPrepStmt = _conn.prepareStatement("SELECT LSID FROM " 205 + LibIndex.LIBRARY_LSIDS_TABLE_NAME + " WHERE LIID = ?"); 206 207 _getNameValueForLIIDPrepStmt = _conn.prepareStatement("SELECT NAME,VALUE FROM " 208 + LibIndex.LIBRARY_ATTRIBUTES_TABLE_NAME + " WHERE LIID = ?"); 209 210 } catch (Exception e) { 211 e.printStackTrace(); 212 } 213 214 } 215 216 /** 217 * Given the LSID of a KAR that has been successfully cached this method 218 * will add all of the contents of that KAR into the Library by first 219 * updating the LibIndex and then updating the tree model. 220 * 221 * @param f 222 * @throws SQLException 223 */ 224 public void addKAR(File karFile) throws SQLException { 225 226 KARCacheManager kcm = KARCacheManager.getInstance(); 227 Vector<KARCacheContent> contents = kcm.getKARCacheContents(karFile); 228 getIndex().setOrderedInsert(true); 229 for (KARCacheContent content : contents) { 230 231 // Update the ontologies in the library index 232 Vector<LibItem> ontItems = getIndex().assureOntologyComponent( 233 content); 234 // update the ontologies in the library tree model 235 for (LibItem ontLI : ontItems) { 236 ComponentEntity ce = assureTreeItem(ontLI); 237 if (ce == null) { 238 // Problem adding item to the tree 239 // Here we could rebuild the library completely... 240 log.error("Component not added to the library properly"); 241 } 242 } 243 244 // Update the folders in the library index 245 LibItem folderLI = getIndex().assureKarEntry(content); 246 // Update the folders in the library tree model 247 assureTreeItem(folderLI); 248 } 249 250 getIndex().setOrderedInsert(false); 251 } 252 253 /** 254 * Update the LibIndex and tree model for a XML file. 255 * 256 * @param f 257 * @throws SQLException 258 */ 259 public void addXML(File xmlFile) throws SQLException { 260 261 LibIndex index = getIndex(); 262 index.setOrderedInsert(true); 263 264 LibItem xmlLI = index.assureXML(xmlFile); 265 assureTreeItem(xmlLI); 266 267 index.setOrderedInsert(false); 268 } 269 270 /** 271 * Add a reference to a JTree that is using the Library Tree Model so that 272 * it can be updated when the tree model changes. Whenever getTreeModel() is 273 * used in a gui component, the JTree reference should be added using this 274 * method so that it can get refreshed when the library model changes using 275 * the refreshJTrees() method. 276 * 277 *@param ptree 278 * The feature to be added to the LibraryComponent attribute 279 */ 280 public void addLibraryJTree(JTree ptree) { 281 if (isDebugging) { 282 log.debug("addLibraryComponent(" + ptree.getName() + ")"); 283 } 284 if (isDebugging) 285 log.debug("addLibraryComponent(" + ptree + ")"); 286 WeakReference<JTree> ptreeWR = new WeakReference<JTree>(ptree); 287 _trees.addElement(ptreeWR); 288 if (isDebugging) 289 log.debug("_trees size:" + _trees.size()); 290 291 // add this tree to the map and register for expansion events 292 _treeExpansionMap.put(ptree, new LinkedList<TreePath>()); 293 ptree.addTreeExpansionListener(this); 294 } 295 296 /** 297 * Passing a LibItem that has been populated from the database will assure 298 * that the appropriate object is represented in the Library Tree. If the 299 * item already exists it will be returned. If it does not exist then it 300 * will be created along with any parent path components that do not already 301 * exist. The newly created ComponentEntity will then be returned. 302 * 303 * This method is private because API users should only be using addKAR and 304 * deleteKAR methods to modify the Library. 305 * 306 * @param li 307 * @return 308 */ 309 private ComponentEntity assureTreeItem(LibItem li) { 310 if (isDebugging) 311 log.debug("assureTreeItem(" + li.getName() + ")"); 312 ComponentEntity ce = null; 313 try { 314 CompositeEntity current = (CompositeEntity) getTreeModel() 315 .getRoot(); 316 Vector<LibItem> pathItems = _libIndex.getPath(li); 317 for (int i = 0; i < pathItems.size(); i++) { 318 LibItem pathItem = pathItems.elementAt(i); 319 320 int pathLiid = pathItem.getLiid(); 321 if (isDebugging) { 322 log.debug(pathItem.getName()); 323 log.debug(current.getName()); 324 } 325 326 ComponentEntity existingCE = null; 327 List children = current.entityList(ComponentEntity.class); 328 for (Object child : children) { 329 if (child instanceof ComponentEntity) { 330 ComponentEntity childCE = (ComponentEntity) child; 331 int childLiid = LibraryManager.getLiidFor(childCE); 332 if (childLiid == pathLiid) { 333 existingCE = childCE; 334 break; 335 } 336 } else { 337 log.error("Child was not a ComponentEntity!"); 338 } 339 } 340 if (existingCE == null) { 341 // add this puppy to the tree 342 ComponentEntity newCE = createAndAddTreeItem(current, 343 pathItem); 344 if (newCE != null) { 345 if (newCE instanceof CompositeEntity) { 346 current = (CompositeEntity) newCE; 347 ce = current; 348 } else { 349 // ComponentEntity leaf node 350 ce = newCE; 351 break; 352 } 353 } else { 354 log.debug("fail"); 355 ce = null; 356 } 357 } else if (existingCE instanceof CompositeEntity) { 358 current = (CompositeEntity) existingCE; 359 ce = current; 360 } 361 } // end for loop 362 } catch (Exception e) { 363 e.printStackTrace(); 364 } 365 return ce; 366 } 367 368 /** Create an empty library. When KeplerGraphFrame starts, it initializes 369 * ComponentLibraryTab, which in turn requires a library. Building the 370 * library with buildLibrary() can take a long time, so this method can 371 * be used to open a KeplerGraphFrame quickly. 372 */ 373 public void buildEmptyLibrary() { 374 375 EntityLibrary el = new EntityLibrary(_actorLibraryWorkspace); 376 377 LibItem li = new LibItem(); 378 li.setName("Empty Library"); 379 li.setType(LibIndex.TYPE_CONCEPT); 380 381 try { 382 createAndAddTreeItem(el, li); 383 } catch (Exception e) { 384 // TODO Auto-generated catch block 385 e.printStackTrace(); 386 } 387 388 this.setActorLibrary(el); 389 390 } 391 392 /** 393 * This method will synchronize the cache with local repositories. Then it 394 * will rebuild the LibIndex if needed. Then it will generate the Actor 395 * Library from the LibIndex. To force the rebuilding of the LibIndex before 396 * calling this method call getIndex().clear() 397 */ 398 public void buildLibrary() { 399 if (isDebugging) 400 log.debug("buildLibrary()"); 401 402 StatusNotifier.log("Building Library."); 403 404 try { 405 406 KARCacheManager kcm = KARCacheManager.getInstance(); 407 408 // Synchronize the Cache with Local Repositories 409 boolean changed = kcm.synchronizeKARCacheWithLocalRepositories(); 410 411 // Rebuild the Library Index if needed 412 _libIndex = new LibIndex(_conn); 413 414 long start = System.currentTimeMillis(); 415 if (_libIndex.countItems() <= 0) { 416 // rebuild the index if it is empty 417 _libIndex.rebuild(); 418 } else if (!_libIndex.verifyPreorderValues()) { 419 // rebuild the index if the preorder values don't add up 420 // correctly 421 log 422 .error("\n\nPreorder values are corrupt! Rebuilding index.\n\n"); 423 _libIndex.rebuild(); 424 } else if (changed) { 425 // rebuild the index if the KARs in the local repositories have 426 // changed 427 _libIndex.rebuild(); 428 } 429 if (isDebugging) 430 log.debug("\n\nTIME " + (System.currentTimeMillis() - start) 431 + "\n\n"); 432 433 // Generate the actor library using the library index 434 LibraryGenerator lg = new LibraryGenerator(); 435 436 // we're using the same workspace so we need to remove the entities 437 clearActorLibrary(); 438 439 CompositeEntity newLibrary = lg.generate(_actorLibraryWorkspace, 440 _libIndex); 441 this.setActorLibrary(newLibrary); 442 443 } catch (Exception e) { 444 e.printStackTrace(); 445 } 446 447 } 448 449 public void removeAllFrameTabs(TableauFrame parent) { 450 if (isDebugging) 451 { 452 log.debug("parent in _trees is:" + parent); 453 for (int i = 0; i < _trees.size(); i++) { 454 JTree treeEle = _trees.elementAt(i).get(); 455 log.debug("treeEle in _trees element at " + i + " is:" + treeEle); 456 } 457 log.debug("_libraryModel:" + _libraryModel); 458 } 459 } 460 461 /** 462 * Create and add the appropriate type of placeholder object to the parent 463 * CompositeEntity that is in the tree model. Return the object when 464 * finished. 465 * 466 * Only subtypes of ComponentEntity may be returned. However, the tree item 467 * can represent any type of object, depending on what the type is in the 468 * LibIndex. 469 * 470 * @param li 471 * @return 472 * @throws NameDuplicationException 473 * @throws IllegalActionException 474 * @throws IOException 475 * @throws IllegalArgumentException 476 */ 477 public ComponentEntity createAndAddTreeItem(CompositeEntity parent, 478 LibItem li) throws IllegalActionException, 479 NameDuplicationException, IllegalArgumentException, IOException { 480 ComponentEntity ce = null; 481 482 // EditorDropTarget in ptolemy requires an entityId so we set one here 483 // even though we don't ever use it for anything, the LSID should 484 // always be gotten from the LibItem 485 NamedObjId lsidSA = null; 486 487 int type = li.getType(); 488 String displayName = li.getName(); 489 490 String name = displayName; 491 // remove periods from the name since they are not allowed 492 if(name.contains(".")) { 493 name = name.replaceAll("\\.", ","); 494 } 495 li.setName(name); 496 497 switch (type) { 498 case LibIndex.TYPE_COMPONENT: 499 ce = new ComponentEntity(parent, li.getName()); 500 ce.setDisplayName(displayName); 501 // This is needed for ptolemy at the moment 502 KeplerLSID lsid = li.getLsid(); 503 if(lsid != null) { 504 lsidSA = new NamedObjId(ce, NamedObjId.NAME); 505 lsidSA.setExpression(li.getLsid()); 506 } 507 // disable drag and drop for MoML files 508 if(li.getAttributeValue(LibIndex.ATT_XMLFILE) != null) { 509 Parameter parameter = new Parameter(ce, "_notDraggable"); 510 parameter.setExpression("true"); 511 } 512 ce.setClassName(li.getAttributeValue(LibIndex.ATT_CLASSNAME)); 513 ComponentEntityConfig.addSVGIconTo(ce); 514 copyAttributes(li, ce); 515 break; 516 case LibIndex.TYPE_NAMED_OBJ: 517 ce = new ComponentEntity(parent, li.getName()); 518 ce.setDisplayName(displayName); 519 lsidSA = new NamedObjId(ce, NamedObjId.NAME); 520 lsidSA.setExpression(li.getLsid()); 521 // ce.setClassName(li.getAttributeValue(LibIndex.ATT_CLASSNAME)); 522 ComponentEntityConfig.addSVGIconTo(ce); 523 // To catch WorkflowRuns 524 StringAttribute notDraggableAttribute = new StringAttribute(ce, "_notDraggable"); 525 notDraggableAttribute.setExpression("true"); 526 copyAttributes(li, ce); 527 break; 528 case LibIndex.TYPE_ONTOLOGY: 529 ce = new OntologyEntityLibrary(parent, li.getName()); 530 ce.setDisplayName(displayName); 531 break; 532 case LibIndex.TYPE_CONCEPT: 533 ce = new EntityLibrary(parent, li.getName()); 534 ce.setDisplayName(displayName); 535 break; 536 case LibIndex.TYPE_FOLDER: 537 ce = new FolderEntityLibrary(parent, li.getName()); 538 ce.setDisplayName(displayName); 539 break; 540 case LibIndex.TYPE_LOCALREPO: 541 ce = new FolderEntityLibrary(parent, li.getName()); 542 ce.setDisplayName(displayName); 543 break; 544 case LibIndex.TYPE_KAR: 545 ce = new KAREntityLibrary(parent, li.getName()); 546 ce.setDisplayName(displayName); 547 lsidSA = new NamedObjId(ce, NamedObjId.NAME); 548 lsidSA.setExpression(li.getLsid()); 549 break; 550 case LibIndex.TYPE_KAR_ERROR: 551 ce = new KARErrorEntityLibrary(parent, li.getName()); 552 ce.setDisplayName(displayName); 553 lsidSA = new NamedObjId(ce, NamedObjId.NAME); 554 lsidSA.setExpression(li.getLsid()); 555 break; 556 case LibIndex.TYPE_KARFOLDER: 557 ce = new FolderEntityLibrary(parent, li.getName()); 558 ce.setDisplayName(displayName); 559 break; 560 case LibIndex.TYPE_OBJECT: 561 ce = new ComponentEntity(parent, li.getName()); 562 ce.setDisplayName(displayName); 563 lsidSA = new NamedObjId(ce, NamedObjId.NAME); 564 lsidSA.setExpression(li.getLsid()); 565 // ce.setClassName(li.getAttributeValue(LibIndex.ATT_CLASSNAME)); 566 ComponentEntityConfig.addSVGIconTo(ce); 567 notDraggableAttribute = new StringAttribute(ce, "_notDraggable"); 568 notDraggableAttribute.setExpression("true"); 569 } 570 if (ce != null) { 571 StringAttribute liidSA = new StringAttribute(ce, 572 LibraryManager.LIID_LABEL); 573 liidSA.setExpression("" + li.getLiid()); 574 } 575 return ce; 576 } 577 578 private void copyAttributes(LibItem li, ComponentEntity ce) { 579 Hashtable<String,String> attributes = li.getAttributes(); 580 for (String key : attributes.keySet()) { 581 String value = attributes.get(key); 582 try { 583 StringAttribute sa = new StringAttribute(ce, key); 584 sa.setExpression(value); 585 } 586 catch(IllegalActionException e) { 587 e.printStackTrace(); 588 } 589 catch(NameDuplicationException e) { 590 e.printStackTrace(); 591 } 592 } 593 } 594 595 /** 596 * Remove a KAR file from the Component Library and from the user's Disk. 597 * 598 * @param File 599 * aKarFile 600 */ 601 public void deleteKAR(File aKarFile) { 602 603 KARCacheManager kcm = KARCacheManager.getInstance(); 604 if (!kcm.isCached(aKarFile)) { 605 // this file is not in the cache. 606 return; 607 } 608 609 KARFile karf; 610 try { 611 612 karf = new KARFile(aKarFile); 613 File karFileLocation = karf.getFileLocation(); 614 karf.close(); // free up the file pointer 615 616 // remember what was in the kar file before we remove it all 617 Vector<KARCacheContent> entries = kcm 618 .getKARCacheContents(karFileLocation); 619 620 // Remove it from the Index 621 LibItem karItem = getIndex().findKar(karFileLocation); 622 // make sure KAR is in library 623 if(karItem != null) { 624 getIndex().removeItem(karItem.getLiid()); 625 626 // Remove it from the Library 627 ComponentEntity item = findTreeItem(karItem.getLiid()); 628 if (item == null) 629 return; 630 item.setContainer(null); 631 } 632 633 // Remove it from the cache 634 kcm.removeKARFromCache(karFileLocation); 635 636 // verify that it is gone before doing the rest 637 if (!kcm.isCached(karFileLocation)) { 638 639 // Remove the kar file from the file system 640 boolean success = karFileLocation.delete(); 641 if (success) { 642 log.info(karFileLocation.toString() + " was deleted."); 643 } else { 644 System.out.println("Unable to delete " 645 + karFileLocation.toString()); 646 } 647 648 // Update the Ontologies if no other KARs contain the entries 649 Vector<KeplerLSID> lsidsToRemoveFromOntologies = new Vector<KeplerLSID>(); 650 CacheManager cache = CacheManager.getInstance(); 651 for (KARCacheContent entry : entries) { 652 if (isDebugging) 653 log.debug(entry.getLsid()); 654 if (cache.isContained(entry.getLsid())) { 655 // Some other KAR has this object in it too 656 // Don't remove it from the ontologies 657 } else { 658 // This LSID is no longer in the cache 659 lsidsToRemoveFromOntologies.add(entry.getLsid()); 660 } 661 } 662 // remove ontology ComponentEntities that are no longer in the 663 // cache 664 for (KeplerLSID lsid : lsidsToRemoveFromOntologies) { 665 // now we check each Liid to make sure there are no other 666 // LSIDs 667 // that exist for it 668 669 // Remove it from the Index 670 Vector<Integer> liidsRemovedFromIndex = getIndex() 671 .removeItemsByLsid(lsid); 672 673 // Remove them from the Library too 674 for (Integer removedLiid : liidsRemovedFromIndex) { 675 ComponentEntity ontItem = findTreeItem(removedLiid 676 .intValue()); 677 if (ontItem != null) { 678 ontItem.setContainer(null); 679 } else { 680 log.warn("ontItem not found for " + removedLiid); 681 } 682 } 683 } 684 } 685 686 // update the JTrees 687 refreshJTrees(); 688 689 } catch (Exception e) { 690 e.printStackTrace(); 691 } 692 } 693 694 /** 695 * Look only at the children of the given parent to match the given LIID. Do 696 * not recurse the children here, use findTreeItemDeep() for that. 697 * 698 * @param parent 699 * @param liid 700 * @return 701 */ 702 public ComponentEntity findTreeItem(CompositeEntity parent, int liid) { 703 if (isDebugging) 704 log.debug("findTreeItem(" + parent.getName() + "," + liid + ")"); 705 ComponentEntity ce = null; 706 List<ComponentEntity> children = parent 707 .entityList(ComponentEntity.class); 708 for (ComponentEntity child : children) { 709 int childLiid = LibraryManager.getLiidFor(child); 710 if (isDebugging) 711 log.debug(" " + childLiid + " " + child.getName()); 712 if (childLiid == liid) { 713 ce = child; 714 // break; 715 } 716 } 717 return ce; 718 } 719 720 /** 721 * Look in the entire tree and return the ComponentEntity that matches the 722 * given LIID. 723 * 724 * @param liid 725 * @return 726 */ 727 public ComponentEntity findTreeItem(int liid) { 728 if (isDebugging) 729 log.debug("findTreeItem(" + liid + ")"); 730 CompositeEntity root = (CompositeEntity) getTreeModel().getRoot(); 731 ComponentEntity ce = findTreeItemDeep(root, liid); 732 if (ce == null) { 733 log.debug("Unable to find item " + liid + " in Library Tree"); 734 } 735 return ce; 736 } 737 738 /** 739 * Recurse all children under parent to match the given LIID. 740 * 741 * @param parent 742 * @param liid 743 * @return 744 */ 745 public ComponentEntity findTreeItemDeep(CompositeEntity parent, int liid) { 746 if (isDebugging) 747 log 748 .debug("findTreeItemDeep(" + parent.getName() + "," + liid 749 + ")"); 750 // check the children of this parent to see if any of them match the 751 // liid 752 ComponentEntity ce = findTreeItem(parent, liid); 753 if (ce == null) { 754 // recurse the children if we don't find it 755 List<CompositeEntity> children = parent 756 .entityList(CompositeEntity.class); 757 for (CompositeEntity child : children) { 758 ce = findTreeItemDeep(child, liid); 759 if (ce != null) { 760 break; 761 } 762 } 763 } 764 return ce; 765 } 766 767 /** 768 * generate the EntityTreeModel version of the library 769 * 770 *@return Description of the Return Value 771 *@exception IllegalActionException 772 * Description of the Exception 773 */ 774 private void generateTreeModel() { 775 if (isDebugging) { 776 log.debug("generateTreeModel()"); 777 } 778 779 _libraryModel = new VisibleTreeModel(_actorLibrary); 780 } 781 782 private FilteredVisibleTreeModel generateTreeModel(File filterFile) { 783 FilteredVisibleTreeModel treeModel = new FilteredVisibleTreeModel(_libraryModel, filterFile); 784 return treeModel; 785 } 786 787 /** 788 * Get the CompositeEntity version of the library. 789 * 790 * */ 791 public CompositeEntity getActorLibrary() { 792 793 return _actorLibrary; 794 } 795 796 private void setActorLibrary(CompositeEntity ce) { 797 _actorLibrary = ce; 798 generateTreeModel(); 799 } 800 801 /** 802 * @return LibIndex object that the manager is using 803 */ 804 public LibIndex getIndex() { 805 return _libIndex; 806 } 807 808 /** 809 * Return the LIIDs for the given set of LSIDs. 810 * 811 * @param lsids 812 * @return 813 */ 814 public Vector<Integer> getLiidsFor(Vector<KeplerLSID> lsids) { 815 Vector<Integer> liids = new Vector<Integer>(); 816 817 for (KeplerLSID lsid : lsids) { 818 try { 819 String query = "SELECT LIID FROM " 820 + LibIndex.LIBRARY_LSIDS_TABLE_NAME + " WHERE LSID = '" 821 + lsid + "'"; 822 ResultSet rs = _stmt.executeQuery(query); 823 if (rs == null) 824 throw new SQLException("Query Failed: " + query); 825 while (rs.next()) { 826 int liid = rs.getInt(1); 827 liids.add(new Integer(liid)); 828 } 829 rs.close(); 830 } catch (SQLException sqle) { 831 sqle.printStackTrace(); 832 } 833 } 834 return liids; 835 } 836 837 /** 838 * Return a populated LibItem for the given liid. 839 * 840 * @param liid 841 * @return LibItem 842 */ 843 public LibItem getTreeItemIndexInformation(int liid) { 844 LibItem li = null; 845 try { 846 li = getPopulatedLibItem(liid); 847 } catch (Exception e) { 848 e.printStackTrace(); 849 } 850 return li; 851 } 852 853 private void clearActorLibrary() { 854 CompositeEntity root = getActorLibrary(); 855 if (root != null) { 856 List childen = root.entityList(); 857 for (Object child : childen) { 858 if (child instanceof ComponentEntity) { 859 try { 860 ((ComponentEntity) child).setContainer(null); 861 } catch (IllegalActionException e) { 862 e.printStackTrace(); 863 } catch (NameDuplicationException e) { 864 e.printStackTrace(); 865 } 866 } 867 } 868 } 869 } 870 871 872 /** 873 * @return the TreeModel version of the library. 874 */ 875 public EntityTreeModel getTreeModel() { 876 if (_libraryModel == null) { 877 generateTreeModel(); 878 } 879 return _libraryModel; 880 } 881 882 public EntityTreeModel getTreeModel(File filterFile) { 883 return generateTreeModel(filterFile); 884 } 885 886 /** 887 * Refresh and redraw any JTrees that the LibraryManager is keeping track 888 * of. 889 * 890 *@exception IllegalActionException 891 * Description of the Exception 892 */ 893 public void refreshJTrees() throws IllegalActionException { 894 if (isDebugging) { 895 log.debug("refresh"); 896 } 897 898 // Iterate over all the registered JTrees and reset their models. 899 //Iterator<WeakReference> treeItt = _trees.iterator(); 900 901 int size = _trees.size(); 902 int i = 0; 903 while (i < size){ 904 WeakReference<JTree> wf = _trees.elementAt(i); 905 JTree ptree = (JTree)wf.get(); 906 if (ptree == null) 907 { 908 _trees.remove(wf); 909 size--; 910 } 911 else { 912 ptree.setModel(getTreeModel()); 913 914 // stop listening for expansion events since we are going to 915 // expand the paths and do not want to modify the list 916 ptree.removeTreeExpansionListener(this); 917 918 // expand all the paths that were previously expanded 919 final List<TreePath> expansions = _treeExpansionMap.get(ptree); 920 for(TreePath path : expansions) { 921 //System.out.println("expanding " + path); 922 ptree.expandPath(path); 923 } 924 925 // start listening again for expansion events 926 ptree.addTreeExpansionListener(this); 927 928 /* 929 EntityTreeModel etm = (EntityTreeModel) ptree.getModel(); 930 931 // Of course this would be easier if 932 // ptolemy.vergil.tree.EntityTreeModel 933 // had a reload method similar to DefaultTreeModel 934 // that did this for us 935 // TODO etm.reload() 936 937 ArrayList<NamedObj> path = new ArrayList<NamedObj>(); 938 path.add(0, (NamedObj) etm.getRoot()); 939 TreePath tp = new TreePath(path); 940 etm.valueForPathChanged(tp, etm.getRoot()); 941 */ 942 i++; 943 } 944 } 945 } 946 947 /** 948 * Set the workspace for the actor library and regenerate 949 * 950 * @param ws 951 */ 952 public void setActorLibraryWorkspace(Workspace ws) { 953 if (isDebugging) 954 log.debug("setActorLibraryWorkspace(" + ws.getName() + ")"); 955 _actorLibraryWorkspace = ws; 956 } 957 958 /** 959 * Populate this LibItem Object from the database using the given Library 960 * Index ID. 961 * 962 * @param liid 963 * @throws SQLException 964 */ 965 public LibItem getPopulatedLibItem(int liid) throws SQLException { 966 967 LibItem li = new LibItem(); 968 _getPopulateInfoForLIIDPrepStmt.setInt(1, liid); 969 ResultSet rs = _getPopulateInfoForLIIDPrepStmt.executeQuery(); 970 if (rs == null) throw new SQLException("Query Failed: " + _getPopulateInfoForLIIDPrepStmt); 971 if (rs.next()) { 972 973 li.setLiid(liid); 974 975 int parent = rs.getInt(1); 976 if (rs.wasNull()) { 977 li.setParent(null); 978 } else { 979 li.setParent(new Integer(parent)); 980 } 981 982 li.setLeft(rs.getInt(2)); 983 li.setRight(rs.getInt(3)); 984 li.setLevel(rs.getInt(4)); 985 986 String lsid = rs.getString(5); 987 if (rs.wasNull()) { 988 li.setLsid(null); 989 } else { 990 try { 991 li.setLsid(new KeplerLSID(lsid)); 992 } catch (Exception e) { 993 e.printStackTrace(); 994 } 995 } 996 li.setType(rs.getInt(6)); 997 li.setName(rs.getString(7)); 998 999 // double check there is only one row returned for this liid 1000 if (rs.next()) { 1001 throw new SQLException(LibIndex.LIBRARY_INDEX_TABLE_NAME 1002 + " is corrupt" 1003 + " more than one row returned for primary key " 1004 + li.getLiid()); 1005 } 1006 } 1007 rs.close(); 1008 1009 populateAttributes(li, liid); 1010 populateLsids(li, liid); 1011 1012 return li; 1013 1014 } 1015 1016 /** 1017 * Populate this LibItem with the corresponding Attributes stored in the 1018 * LIBRARY_ATTRIBUTES table for the given LIID. 1019 * 1020 * @param liid 1021 * @param stmt 1022 * @throws SQLException 1023 */ 1024 private void populateAttributes(LibItem li, int liid) 1025 throws SQLException { 1026 1027 _getNameValueForLIIDPrepStmt.setInt(1, liid); 1028 ResultSet rs = _getNameValueForLIIDPrepStmt.executeQuery(); 1029 if (rs != null) { 1030 while (rs.next()) { 1031 String name = rs.getString(1); 1032 String value = rs.getString(2); 1033 if (value == null) { 1034 value = new String(); 1035 } 1036 li.addAttribute(name, value); 1037 } 1038 } 1039 rs.close(); 1040 1041 } 1042 1043 /** 1044 * Populate this LibItem with the corresponding LSID values stored in the 1045 * LIBRARY_LSIDS table for the given LIID. 1046 * 1047 * @param liid 1048 * @param stmt 1049 * @throws SQLException 1050 */ 1051 private void populateLsids(LibItem li, int liid) throws SQLException { 1052 1053 _getLSIDForLIIDPrepStmt.setInt(1, liid); 1054 ResultSet rs = _getLSIDForLIIDPrepStmt.executeQuery(); 1055 if (rs != null) { 1056 while (rs.next()) { 1057 String lsidStr = rs.getString(1); 1058 KeplerLSID lsid; 1059 try { 1060 lsid = new KeplerLSID(lsidStr); 1061 li.addLsid(lsid); 1062 } catch (Exception e) { 1063 e.printStackTrace(); 1064 } 1065 } 1066 } 1067 rs.close(); 1068 1069 } 1070 1071 /** Called whenever an item in the tree is expanded. */ 1072 @Override 1073 public void treeExpanded(TreeExpansionEvent event) { 1074 final Object tree = event.getSource(); 1075 final List<TreePath> expansions = _treeExpansionMap.get(tree); 1076 if(expansions != null) { 1077 //System.out.println("expanded " + event.getPath()); 1078 expansions.add(event.getPath()); 1079 } 1080 } 1081 1082 1083 /** Called whenever an item in the tree is collapsed. */ 1084 @Override 1085 public void treeCollapsed(TreeExpansionEvent event) { 1086 final Object tree = event.getSource(); 1087 final List<TreePath> expansions = _treeExpansionMap.get(tree); 1088 if(expansions != null) { 1089 //System.out.println("collapsed " + event.getPath()); 1090 expansions.remove(event.getPath()); 1091 } 1092 } 1093 1094 1095}