001/* 002 * Copyright (c) 2003-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-08-17 01:21:47 +0000 (Mon, 17 Aug 2015) $' 007 * '$Revision: 33574 $' 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.moml; 031 032import java.util.Collection; 033import java.util.Iterator; 034import java.util.List; 035import java.util.Vector; 036 037import org.apache.commons.logging.Log; 038import org.apache.commons.logging.LogFactory; 039import org.kepler.objectmanager.lsid.KeplerLSID; 040import org.kepler.objectmanager.lsid.LSIDGenerator; 041 042import ptolemy.actor.gui.RenameConfigurer; 043import ptolemy.kernel.undo.RedoChangeRequest; 044import ptolemy.kernel.undo.UndoChangeRequest; 045import ptolemy.kernel.util.Attribute; 046import ptolemy.kernel.util.ChangeListener; 047import ptolemy.kernel.util.ChangeRequest; 048import ptolemy.kernel.util.IllegalActionException; 049import ptolemy.kernel.util.NameDuplicationException; 050import ptolemy.kernel.util.NamedObj; 051import ptolemy.kernel.util.Settable; 052import ptolemy.kernel.util.StringAttribute; 053import ptolemy.kernel.util.ValueListener; 054import ptolemy.kernel.util.Workspace; 055import ptolemy.moml.MoMLChangeRequest; 056import ptolemy.util.MessageHandler; 057import ptolemy.vergil.actor.ActorGraphModel; 058import ptolemy.vergil.basic.LocatableNodeDragInteractor; 059 060/** 061 * The NamedObjId is a StringAttribute to be used for identifying a NamedObj by 062 * a KeplerLSID. A NamedObj that contains this Attribute is considered to be 063 * uniquely identified by the KeplerLSID that this NamedObjId stores. This class 064 * also handles the updating of KeplerLSIDs based on the ptolemy change listener 065 * system. Static methods in org.kepler.objectmanager.ObjectManager can be used 066 * to access NamedObjId attributes contained by NamedObjs. 067 * 068 *@author berkley, schultz 069 *@created March 1, 2005 070 */ 071public class NamedObjId extends StringAttribute implements ChangeListener { 072 private static final long serialVersionUID = 3665319359405551002L; 073 private static final Log log = LogFactory 074 .getLog(NamedObjId.class.getName()); 075 private static final boolean isDebugging = log.isDebugEnabled(); 076 077 /** If true, new NamedObjId objects will increment the LSID when changes 078 * to the workflow occur. 079 */ 080 private static boolean _incrementLSIDOnWorkflowChange = true; 081 082 /** container for valueListeners assigned to this attribute */ 083 private Vector<ValueListener> valueListeners = new Vector<ValueListener>(); 084 085 private KeplerLSID _id = null; 086 087 public static final String NAME = "entityId"; 088 089 /* A parent NamedObjId for this NamedObjId 090 * The parent will always be updated when this one is. 091 */ 092 private NamedObjId _parentId = null; 093 094 public NamedObjId getParentId() { 095 return _parentId; 096 } 097 098 public void setParentId(NamedObjId parent) { 099 _parentId = parent; 100 } 101 102 /** Constructor */ 103 public NamedObjId() { 104 super(); 105 if(_incrementLSIDOnWorkflowChange) { 106 addChangeListener(this); 107 } 108 } 109 110 /** 111 * Constructor 112 * 113 *@param container 114 * Description of the Parameter 115 *@param name 116 * Description of the Parameter 117 *@exception IllegalActionException 118 * Description of the Exception 119 *@exception NameDuplicationException 120 * Description of the Exception 121 */ 122 public NamedObjId(NamedObj container, String name) 123 throws IllegalActionException, NameDuplicationException { 124 super(container, name); 125 if(_incrementLSIDOnWorkflowChange) { 126 addChangeListener(this); 127 } 128 } 129 130 /** 131 * Constructor 132 * 133 *@param workspace 134 * Description of the Parameter 135 */ 136 public NamedObjId(Workspace workspace) { 137 super(workspace); 138 if(_incrementLSIDOnWorkflowChange) { 139 addChangeListener(this); 140 } 141 } 142 143 /** 144 * Generate a new KeplerLSID and assign it to this NamedObj. 145 * 146 * @param no 147 * the NamedObj. 148 * @throws Exception 149 */ 150 public static void assignIdTo(NamedObj no) throws Exception { 151 assignIdTo(no, LSIDGenerator.getInstance().getNewLSID(), true); 152 } 153 154 /** 155 * Assign the given KeplerLSID to this NamedObj. If the NamedObj already has 156 * this LSID assigned to it do nothing. If the NamedObj has a different 157 * LSID, assign the new LSID to the NamedObj and move the old LSID into the 158 * referral list. 159 * 160 * @param no 161 * @param lsid 162 * @throws Exception 163 */ 164 public static void assignIdTo(NamedObj no, KeplerLSID lsid) 165 throws Exception { 166 assignIdTo(no, lsid, true); 167 } 168 169 /** 170 * Assign the given KeplerLSID to this NamedObj. If the NamedObj already has 171 * this LSID assigned to it do nothing. If the NamedObj has a different 172 * LSID, assign the new LSID to the NamedObj and optionally move the old 173 * LSID into the referral list. 174 * 175 * @param no 176 * the NamedObj 177 * @param lsid 178 * the new LSID to assign. 179 * @param updateReferrals 180 * if true, update the referrals list. 181 * @throws Exception 182 */ 183 public static void assignIdTo(NamedObj no, KeplerLSID lsid, 184 boolean updateReferrals) throws Exception { 185 if (isDebugging) 186 log.debug("assignIdTo(" + no.getName() + ", " + lsid + ")"); 187 188 NamedObjIdReferralList referrals = null; 189 190 if (updateReferrals) { 191 // make sure there is a referral list 192 Attribute referralListAttribute = no 193 .getAttribute(NamedObjIdReferralList.NAME); 194 // if it does not exist, create one 195 if (referralListAttribute == null) { 196 referrals = new NamedObjIdReferralList(no, 197 NamedObjIdReferralList.NAME); 198 // make sure the attribute is a NamedObjIdReferralList 199 } else if(referralListAttribute instanceof NamedObjIdReferralList) { 200 referrals = (NamedObjIdReferralList) referralListAttribute; 201 } else if(referralListAttribute instanceof Settable) { 202 // the attribute is not a NamedObjIdReferralList 203 // this can happen if a Kepler workflow is opened in Ptolemy, saved, 204 // then opened in Kepler. (Ptolemy does not have NamedObjIdReferralList, 205 // so converts to StringAttribute). 206 207 // copy the contents, remove it, and replace with a NamedObjIdReferralList. 208 String expression = ((Settable) referralListAttribute).getExpression(); 209 no.removeAttribute(referralListAttribute); 210 referrals = new NamedObjIdReferralList(no, 211 NamedObjIdReferralList.NAME); 212 referrals.setExpression(expression); 213 } 214 } 215 216 // find the entityId attribute 217 NamedObjId lsidAtt = null; 218 try { 219 // If the user opens a Kepler-2.2 model in Ptolemy and then 220 // saves it, the org.kepler.moml.NamedObjId 221 // will be replaced with a StringAttribute. Then, if the user 222 // tries to reopen the model in Kepler, there will be a cast 223 // exception. So, we get rid of the offending attribute and 224 // create another. 225 lsidAtt = (NamedObjId) no.getAttribute(NamedObjId.NAME); 226 } catch (ClassCastException ex) { 227 no.getAttribute(NamedObjId.NAME).setContainer(null); 228 lsidAtt = null; 229 } 230 if (lsidAtt == null) { 231 if (isDebugging) 232 log.debug("lsidAtt is null"); 233 234 lsidAtt = new NamedObjId(no, NamedObjId.NAME); 235 lsidAtt.setExpression(lsid.toString()); 236 237 // look for the ID in the Annotation attribute. (for backwards 238 // compatibility) 239 Attribute a = no.getAttribute("Annotation"); 240 if (a != null) { 241 if (isDebugging) 242 log.debug("a not null"); 243 NamedObjId annoLsid = (NamedObjId) a 244 .getAttribute(NamedObjId.NAME); 245 if (annoLsid != null) { 246 if (isDebugging) 247 log.debug("found lsidAtt in Annotation"); 248 lsidAtt.setExpression(annoLsid.getExpression()); 249 annoLsid.setContainer(null); 250 } 251 } 252 } 253 254 // Add the old lsid to the derivedFrom list if it is a different 255 // object, namespace, or authority 256 if (lsidAtt.getId() != null) { 257 if (!lsidAtt.getId().equalsWithoutRevision(lsid) && updateReferrals) { 258 if (isDebugging) 259 log.debug("add referral"); 260 referrals.addReferral(lsidAtt.getId()); 261 } 262 } 263 lsidAtt.setExpression(lsid.toString()); 264 } 265 266 /** Clone the object into the specified workspace. */ 267 @Override 268 public Object clone(Workspace workspace) throws CloneNotSupportedException { 269 NamedObjId newObject = (NamedObjId) super.clone(workspace); 270 newObject._id = null; 271 newObject._parentId = null; 272 newObject.valueListeners = new Vector<ValueListener>(); 273 return newObject; 274 } 275 276 /** 277 * returns the default expression which is null 278 * 279 *@return The defaultExpression value 280 */ 281 @Override 282 public String getDefaultExpression() { 283 return null; 284 } 285 286 public KeplerLSID getId() { 287 return _id; 288 } 289 290 /** 291 * Return the LSID for the given NamedObj. If an LSID has not already been 292 * assigned then assign the NamedObj a new LSID. 293 * 294 * @param no 295 * */ 296 public static KeplerLSID getIdFor(NamedObj no) { 297 NamedObjId lsidAtt = NamedObjId.getIdAttributeFor(no); 298 if (lsidAtt == null) { 299 try { 300 NamedObjId.assignIdTo(no); 301 lsidAtt = NamedObjId.getIdAttributeFor(no); 302 } catch (Exception e) { 303 e.printStackTrace(); 304 } 305 } 306 String lsidStr = lsidAtt.getExpression(); 307 if (lsidStr == null) { 308 return null; 309 } 310 try { 311 return new KeplerLSID(lsidStr); 312 } catch (Exception e) { 313 return null; 314 } 315 } 316 317 /** 318 * Return the KeplerIDListAttribute associated with the given NamedObj or 319 * null if no KeplerIDListAttribute exists. 320 * 321 * @param no 322 * * @throws NameDuplicationException 323 * @throws IllegalActionException 324 */ 325 public static NamedObjIdReferralList getIDListAttributeFor(NamedObj no) 326 throws IllegalActionException, NameDuplicationException { 327 328 NamedObjIdReferralList theAtt = null; 329 330 // check the attributes of this obj 331 // FIXME: why iterate over all the attributes instead of 332 // getting the attribute named NamedObjIdReferralList.NAME? 333 List<Attribute> theAtts = no.attributeList(); 334 for (Iterator<Attribute> atit = theAtts.iterator(); atit.hasNext();) { 335 Attribute anAtt = atit.next(); 336 if (isDebugging) 337 log.debug(anAtt.getName() + " " + anAtt); 338 log.debug(anAtt.getClass().getName()); 339 if (anAtt instanceof NamedObjIdReferralList) { 340 theAtt = (NamedObjIdReferralList) anAtt; 341 if (isDebugging) 342 log.debug("FOUND IT"); 343 return theAtt; 344 } 345 } 346 347 if (theAtt == null) { 348 theAtt = new NamedObjIdReferralList(no, NamedObjIdReferralList.NAME); 349 } 350 351 return theAtt; 352 353 } 354 355 /** 356 * Return the NamedObjId associated with the given NamedObj or null if no 357 * associated NamedObjId. 358 * 359 * @param no 360 * */ 361 public static NamedObjId getIdAttributeFor(NamedObj no) { 362 if (no == null) return null; 363 364 Attribute idAtt = no.getAttribute(NAME); 365 if (idAtt == null) { 366 return null; 367 } 368 if (idAtt instanceof NamedObjId) { 369 NamedObjId theAtt = (NamedObjId) idAtt; 370 return theAtt; 371 } 372 return null; 373 } 374 375 /** 376 * set the value of this id. 377 * 378 * If you want a NamedObjIdChangeRequest sent out in response to this 379 * setExpression you must call requestNamedObjIdChange(). updateRevision 380 * does this for you. 381 * 382 * @see #requestNamedObjIdChange() 383 * 384 *@param expression 385 * The new expression value 386 */ 387 @Override 388 public void setExpression(String expression) throws IllegalActionException { 389 super.setExpression(expression); 390 391 try { 392 _id = new KeplerLSID(expression); 393 } catch (Exception e) { 394 _id = null; 395 throw new IllegalActionException("KeplerID format is incorrect. " 396 + e.toString()); 397 } 398 399 /* 400 * It seems like requestNamedObjIdChange() should be private and 401 * called here, but unfortunately this kicks off an infinite 402 * during startup. 403 * NamedObj => MoMLParser => NamedObj => ChangeRequest => NamedObj 404 * => StringAttribute => NamedObjId. 405 * 406 *requestNamedObjIdChange(); 407 */ 408 409 for (int i = 0; i < valueListeners.size(); i++) { 410 // notify any listeners of the change 411 ValueListener listener = valueListeners 412 .elementAt(i); 413 listener.valueChanged(this); 414 } 415 416 // Update the parent 417 NamedObjId parentId = getParentId(); 418 if (parentId != null) { 419 NamedObj parentsContainer = parentId.getContainer(); 420 if (parentsContainer != null) { 421 try { 422 NamedObjId.assignIdTo(parentsContainer,getId()); 423 } catch (Exception e) { 424 e.printStackTrace(); 425 } 426 } 427 } 428 429 } 430 431 /** 432 * Helper method for setting the expression directly with a KeplerLSID 433 * object. 434 * 435 * @param lsid 436 * @throws IllegalActionException 437 */ 438 public void setExpression(KeplerLSID lsid) throws IllegalActionException { 439 this.setExpression(lsid.toString()); 440 } 441 442 /** 443 * add a valueListener 444 * 445 *@param listener 446 * The feature to be added to the ValueListener attribute 447 */ 448 @Override 449 public void addValueListener(ValueListener listener) { 450 valueListeners.add(listener); 451 } 452 453 /** 454 * NamedObjIds should be invisible to the user 455 * 456 *@return The visibility value 457 */ 458 @Override 459 public Settable.Visibility getVisibility() { 460 return NONE; 461 } 462 463 /** 464 * this method does not change the visibility. NamedObjId should only be 465 * invisible 466 * 467 *@param visibility 468 * The new visibility value 469 */ 470 @Override 471 public void setVisibility(Settable.Visibility visibility) { 472 // do nothing....we don't want the visibility getting changed 473 } 474 475 /** 476 * remove the indicated listener 477 * 478 *@param listener 479 * Description of the Parameter 480 */ 481 @Override 482 public void removeValueListener(ValueListener listener) { 483 valueListeners.remove(listener); 484 } 485 486 /** 487 * @param change 488 * @throws Exception 489 */ 490 private void handleNamedObjIdChangeRequest(NamedObjIdChangeRequest change) 491 throws Exception { 492 493 Object source = change.getSource(); 494 495 if (source instanceof NamedObjId) { 496 497 NamedObj context = change.getContext(); 498 NamedObj container = getContainer(); 499 if (container == null) 500 throw new Exception( 501 "NamedObjId.getContainer() is null on NamedObjIdChangeRequest"); 502 503 if (container.deepContains(context)) { 504 updateRevision(); 505 } 506 507 } 508 } 509 510 /** 511 * @param change 512 * @throws Exception 513 */ 514 private void handleMoMLChangeRequest(MoMLChangeRequest change) 515 throws Exception { 516 517 Object source = change.getSource(); 518 NamedObj context = change.getContext(); 519 NamedObj container = this.getContainer(); 520 521 if (isDebugging) { 522 if (context != null) { 523 log.debug("MoMLChangeRequest.context " + context.getName() 524 + " " + context.getClass().getName()); 525 } else { 526 log.debug("MoMLChangeRequest.context is null"); 527 } 528 log.debug("context: " + context); 529 log.debug("container: " + container); 530 } 531 532 if (source instanceof LocatableNodeDragInteractor) { 533 if (isDebugging) 534 log.debug("Handle LocatableNodeDragInteractor"); 535 536 NamedObj containerContainer = container.getContainer(); 537 if (containerContainer == null) { 538 // This is a change in the location of a component on the 539 // canvas and we are in the NamedObjId for the top level object 540 // So roll the revision on the top level object since it's 541 // xml has changed 542 updateRevision(); 543 } 544 545 } else if (source instanceof ActorGraphModel) { 546 if (isDebugging) { 547 log.debug("Handle ActorGraphModel"); 548 log.debug(change.getClass().getName()); 549 } 550 if (context == container) { 551 552 // Because we cannot tell if the relation is being 553 // started or ended here the lsid revision gets updated 554 // both when the user starts the relation and when they 555 // end it which is not ideal. Would prefer to only update 556 // the revision once after a relation has been created. 557 // perhaps there is a way to do this by inspecting the 558 // ActorGraphModel? 559 // ActorGraphModel agm = (ActorGraphModel) source; 560 // agm.getLinkModel().tellMeIfThisIsTheBeginningOrEndOfARelationCreation() 561 // For Now... 562 563 // Set the id on the object directly 564 KeplerLSID lsid = getId(); 565 if (isDebugging) 566 log.debug(lsid.toString()); 567 LSIDGenerator gen = LSIDGenerator.getInstance(); 568 KeplerLSID newLSID = gen.updateLsidRevision(lsid); 569 setExpression(newLSID); 570 if (isDebugging) 571 log.debug(newLSID.toString()); 572 573 // NOTE 574 // Would prefer to update the revision by using a ChangeRequest 575 // as is done in the updateRevision() method but this fouls up 576 // the LinkModel for some reason and causes the linking to fail 577 // completely 578 // so the kludge fix for now is to not use a ChangeRequest to 579 // update the lsid 580 // updateRevision(); 581 } 582 } else if (source instanceof RenameConfigurer) { 583 RenameConfigurer rc = (RenameConfigurer) source; 584 NamedObj sourceObj = rc.getObject(); 585 if (isDebugging) 586 log.debug("RenameConfigurer object is " + sourceObj.getName() ); 587 if (container == sourceObj) { 588 updateRevision(); 589 } 590 } else { 591 if (isDebugging) 592 log.debug("Handle MoMLChangeRequest from " 593 + source.getClass().getName()); 594 595 if (context == container) { 596 updateRevision(); 597 598 } else { 599 if (isDebugging) 600 log.debug("Ignore: MoMLChangeRequest outside of context"); 601 } 602 } 603 604 } 605 606 /** 607 * @param change 608 * @throws Exception 609 */ 610 private void handleUndoChangeRequest(UndoChangeRequest change) 611 throws Exception { 612 613 NamedObj context = change.getContext(); 614 NamedObj container = this.getContainer(); 615 616 if (isDebugging) { 617 if (context != null) { 618 log.debug("UndoChangeRequest.context " + context.getName() 619 + " " + context.getClass().getName()); 620 } else { 621 log.debug("UndoChangeRequest.context is null"); 622 } 623 log.debug("context: " + context); 624 log.debug("container: " + container); 625 } 626 627 if (context == container) { 628 updateRevision(); 629 630 } else { 631 if (isDebugging) 632 log.debug("Ignore: UndoChangeRequest outside of context"); 633 } 634 635 } 636 637 /** 638 * @param change 639 * @throws Exception 640 */ 641 private void handleRedoChangeRequest(RedoChangeRequest change) 642 throws Exception { 643 644 NamedObj context = change.getContext(); 645 NamedObj container = this.getContainer(); 646 647 if (isDebugging) { 648 if (context != null) { 649 log.debug("RedoChangeRequest.context " + context.getName() 650 + " " + context.getClass().getName()); 651 } else { 652 log.debug("RedoChangeRequest.context is null"); 653 } 654 log.debug("context: " + context); 655 log.debug("container: " + container); 656 } 657 658 if (context == container) { 659 updateRevision(); 660 661 } else { 662 if (isDebugging) 663 log.debug("Ignore: RedoChangeRequest outside of context"); 664 } 665 } 666 667 /** 668 * Check the given NamedObj to see if it matches the search ID. 669 * 670 * @param no 671 * @return true if the given NamedObj has an attached NamedObjId that 672 * matches the KeplerLSID that we are searching for 673 * @throws Exception 674 */ 675 public static boolean idMatches(KeplerLSID lsid, NamedObj no, 676 boolean matchRevision) { 677 if (isDebugging) 678 log.debug("idMatches(" + no.getName() + ") " 679 + no.getClass().getName()); 680 681 NamedObjId theID = NamedObjId.getIdAttributeFor(no); 682 if (theID != null) { 683 if (matchRevision) { 684 if (theID.getId().equals(lsid)) { 685 return true; 686 } 687 } else { 688 if (theID.getId().equalsWithoutRevision(lsid)) { 689 return true; 690 } 691 } 692 } 693 return false; 694 } 695 696 /* 697 * (non-Javadoc) 698 * 699 * @see 700 * ptolemy.kernel.util.ChangeListener#changeExecuted(ptolemy.kernel.util 701 * .ChangeRequest) 702 */ 703 @Override 704 public void changeExecuted(ChangeRequest change) { 705 706 if (isDebugging) { 707 System.out.println(); 708 log.debug("******** NamedObjId.changeExecuted(" 709 + change.getClass().getName() + ")"); 710 log.debug("ID: " + getId().toString()); 711 log.debug("change executed being run in " + this.getName() + " " 712 + this.getClass().getName()); 713 NamedObj c1 = this.getContainer(); 714 if (c1 != null) { 715 log.debug(" with container " + c1.getName() + " " 716 + c1.getClass().getName()); 717 NamedObj c2 = c1.getContainer(); 718 if (c2 != null) { 719 log.debug(" which is inside of " + c2.getName() + " " 720 + c2.getClass().getName()); 721 } 722 } 723 if (change.getSource() instanceof NamedObj) { 724 log.debug("Source: " 725 + ((NamedObj) change.getSource()).getName() + " " 726 + change.getSource().getClass().getName()); 727 } else { 728 log.debug("Source is not a named object but is a " 729 + change.getSource().getClass().getName()); 730 } 731 } 732 733 try { 734 735 // The container of a NamedObjId should never be null 736 NamedObj container = this.getContainer(); 737 if (container == null) { 738 throw new Exception( 739 "NamedObjId.getContainer() is null on ChangeRequest"); 740 } 741 if (change instanceof NamedObjIdChangeRequest) { 742 handleNamedObjIdChangeRequest((NamedObjIdChangeRequest) change); 743 744 } else if (change instanceof MoMLChangeRequest) { 745 handleMoMLChangeRequest((MoMLChangeRequest) change); 746 747 } else if (change instanceof UndoChangeRequest) { 748 handleUndoChangeRequest((UndoChangeRequest) change); 749 750 } else if (change instanceof RedoChangeRequest) { 751 handleRedoChangeRequest((RedoChangeRequest) change); 752 753 } 754 755 } catch (Exception e) { 756 log.error("Failed to update revision: " + e.getMessage()); 757 } 758 } 759 760 /** 761 * The updateRevision() method is used to retrieve the next available 762 * revision from the LSIDGenerator and updates the revision accordingly. 763 * 764 * @throws Exception 765 */ 766 public void updateRevision() throws Exception { 767 if (isDebugging) 768 log.debug("updateRevision()"); 769 770 final NamedObj container = getContainer(); 771 772 // update the LSID 773 if (getId().isLocalToInstance()) { 774 775 KeplerLSID lsidCheck = LSIDGenerator.getInstance() 776 .updateLsidRevision(getId()); 777 if (!lsidCheck.equals(getId())) { 778 try { 779 setExpression(lsidCheck.toString()); 780 } catch (IllegalActionException e) { 781 MessageHandler.error("Error setting LSID.", e); 782 return; 783 } 784 } 785 786 } else { 787 788 NamedObjIdReferralList noirl; 789 try { 790 noirl = NamedObjId 791 .getIDListAttributeFor(container); 792 } catch (Exception e) { 793 MessageHandler.error("Error get referral list.", e); 794 return; 795 } 796 try { 797 noirl.addReferral(getId()); 798 } catch (Exception e) { 799 MessageHandler.error("Error adding referral.", e); 800 return; 801 } 802 String updateReferralsMoml = "<property name=\"" 803 + NamedObjIdReferralList.NAME + "\" class=\"" 804 + noirl.getClass().getName() + "\" value=\"" 805 + noirl.getExpression() + "\"/>"; 806 if (isDebugging) 807 log.debug(updateReferralsMoml); 808 NamedObjIdChangeRequest updateReferralRequest = new NamedObjIdChangeRequest( 809 this, getContainer(), updateReferralsMoml); 810 getContainer().requestChange(updateReferralRequest); 811 812 try { 813 _id = LSIDGenerator.getInstance().getNewLSID(); 814 } catch (Exception e) { 815 MessageHandler.error("Error getting new LSID.", e); 816 return; 817 } 818 819 } 820 821 if (isDebugging) 822 log.debug("The new revision: " + getId().toString()); 823 824 requestNamedObjIdChange(); 825 826 for (int i = 0; i < valueListeners.size(); i++) { 827 // notify any listeners of the change 828 ValueListener listener = valueListeners 829 .elementAt(i); 830 listener.valueChanged(this); 831 } 832 833 834 } 835 836 837 public void requestNamedObjIdChange(){ 838 839 String updateEntityIdMoml = "<property name=\"" + NamedObjId.NAME 840 + "\" class=\"" + getClass().getName() + "\" value=\"" 841 + getId() + "\"/>"; 842 if (isDebugging) 843 log.debug(updateEntityIdMoml); 844 NamedObjIdChangeRequest updateIdRequest = new NamedObjIdChangeRequest( 845 this, getContainer(), updateEntityIdMoml); 846 getContainer().requestChange(updateIdRequest); 847 848 } 849 850 /* 851 * (non-Javadoc) 852 * 853 * @seeptolemy.kernel.util.ChangeListener#changeFailed(ptolemy.kernel.util. 854 * ChangeRequest, java.lang.Exception) 855 */ 856 @Override 857 public void changeFailed(ChangeRequest change, Exception exception) { 858 if (isDebugging) 859 log.debug("changeFailed()"); 860 861 } 862 863 /** validate the expression. */ 864 @Override 865 public Collection validate() { 866 // don't need to do anything here 867 return null; 868 } 869 870 /** 871 * Override setContainer method to handle adding and removing the listener 872 * based on whether or not there is a container. 873 */ 874 @Override 875 public void setContainer(NamedObj container) throws IllegalActionException, 876 NameDuplicationException { 877 if (container == null) { 878 removeChangeListener(this); 879 } else { 880 addChangeListener(this); 881 } 882 super.setContainer(container); 883 } 884 885 /** 886 * Add a change listener, if the container is null the listener 887 * is not added. 888 */ 889 @Override 890 public void addChangeListener(ChangeListener listener) { 891 NamedObj container = this.getContainer(); 892 if (container != null) { 893 super.addChangeListener(listener); 894 } 895 } 896 897 /** 898 * Description of the Method 899 * 900 *@param obj 901 * Description of the Parameter 902 *@return Description of the Return Value 903 */ 904 @Override 905 public boolean equals(Object obj) { 906 if (!(obj instanceof NamedObjId)) { 907 return false; 908 } 909 NamedObjId objId = (NamedObjId) obj; 910 String str = objId.getExpression(); 911 if (this.getExpression() == null) { 912 if (str != null) { 913 return false; 914 } 915 return true; 916 } 917 return this.getExpression().equals(objId.getExpression()); 918 } 919 920 /** Set if workflow changes should increment LSIDs. NOTE: this setting 921 * only affects NamedObjId objects created after this method is called; 922 * it does not change existing NamedObjIds. 923 */ 924 public static void incrementLSIDOnWorkflowChange(boolean listen) { 925 _incrementLSIDOnWorkflowChange = listen; 926 } 927}