001/* 002 * Copyright (c) 2003-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-07-02 19:21:28 +0000 (Thu, 02 Jul 2015) $' 007 * '$Revision: 33522 $' 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; 031 032import java.io.File; 033import java.io.FileInputStream; 034import java.io.FileNotFoundException; 035import java.io.FileWriter; 036import java.io.IOException; 037import java.io.InputStream; 038import java.io.Serializable; 039import java.io.StringWriter; 040import java.lang.reflect.Constructor; 041import java.util.Hashtable; 042import java.util.Iterator; 043import java.util.List; 044import java.util.StringTokenizer; 045import java.util.Vector; 046import java.util.jar.JarEntry; 047import java.util.jar.JarFile; 048import java.util.zip.ZipEntry; 049 050import org.apache.commons.logging.Log; 051import org.apache.commons.logging.LogFactory; 052import org.kepler.moml.CompositeClassEntity; 053import org.kepler.moml.NamedObjId; 054import org.kepler.moml.PortAttribute; 055import org.kepler.moml.PropertyAttribute; 056import org.kepler.objectmanager.lsid.KeplerLSID; 057import org.kepler.sms.SemanticType; 058import org.kepler.util.DotKeplerManager; 059import org.kepler.util.FileUtil; 060import org.kepler.util.TransientStringAttribute; 061 062import ptolemy.actor.Director; 063import ptolemy.actor.IOPort; 064import ptolemy.actor.TypedAtomicActor; 065import ptolemy.actor.TypedCompositeActor; 066import ptolemy.actor.TypedIOPort; 067import ptolemy.data.expr.Parameter; 068import ptolemy.data.expr.StringParameter; 069import ptolemy.data.expr.Variable; 070import ptolemy.kernel.ComponentEntity; 071import ptolemy.kernel.ComponentRelation; 072import ptolemy.kernel.CompositeEntity; 073import ptolemy.kernel.Entity; 074import ptolemy.kernel.InstantiableNamedObj; 075import ptolemy.kernel.Port; 076import ptolemy.kernel.util.Attribute; 077import ptolemy.kernel.util.IllegalActionException; 078import ptolemy.kernel.util.NameDuplicationException; 079import ptolemy.kernel.util.NamedObj; 080import ptolemy.kernel.util.SingletonConfigurableAttribute; 081import ptolemy.kernel.util.StringAttribute; 082import ptolemy.kernel.util.Workspace; 083import ptolemy.moml.MoMLParser; 084import ptolemy.moml.unit.UnitAttribute; 085import ptolemy.util.StringUtilities; 086import ptolemy.vergil.basic.KeplerDocumentationAttribute; 087 088/** 089 * This class parses and contains metadata for an actor. this creates an entity 090 * of the form: 091 * 092 * <pre> 093 * <entity name="Constant"> 094 * <property name="documentation" class="ptolemy.vergil.basic.KeplerDocumentationAttribute"> 095 * actor to provide constant input 096 * </property> 097 * <property name="entityId" class="org.kepler.moml.NamedObjId" 098 * value="urn:lsid:lsid.ecoinformatics.org:actor:101:1"/> 099 * <property name="class" value="org.kepler.actor.TestActor" 100 * class="ptolemy.kernel.util.StringAttribute"> 101 * <property name="id" value="urn:lsid:lsid.ecoinformatics.org:actor:1001:1" 102 * class="ptolemy.kernel.util.StringAttribute"/> 103 * </property> 104 * <property name="output" class="org.kepler.moml.PortProperty> 105 * <property name="direction" value="output" class="ptolemy.kernel.util.StringAttribute"/> 106 * <property name="dataType" value="unknown" class="ptolemy.kernel.util.StringAttribute"/> 107 * <property name="isMultiport" value="false" class="ptolemy.kernel.util.StringAttribute"/> 108 * </property> 109 * <property name="trigger" class="org.kepler.moml.PortProperty> 110 * <property name="direction" value="input" class="ptolemy.kernel.util.StringAttribute"/> 111 * <property name="dataType" value="unknown" class="ptolemy.kernel.util.StringAttribute"/> 112 * <property name="isMultiport" value="true" class="ptolemy.kernel.util.StringAttribute"/> 113 * </property> 114 * <property class="org.kepler.sms.SemanticType" name="semanticType" value="urn:lsid:lsid.ecoinformatics.org:onto:1:1#ConstantActor"/> 115 * <property class="org.kepler.moml.Dependency" name="dependency" value="urn:lsid:lsid.ecoinformatics.org:nativeLib:1:1"/> 116 * </entity> 117 * </pre> 118 * 119 * Note: As of 8/18/09, this class no longer includes graphical ammentities, 120 * such as icons in the moml. If you want graphical widgets for your actor, you 121 * must use org.kepler.gui.GraphicalActorMetadata. 122 * 123 * @author Chad Berkley 124 *@created April 07, 2005 125 */ 126public class ActorMetadata implements Serializable { 127 128 private static final Log log = LogFactory.getLog(ActorMetadata.class 129 .getName()); 130 private static final boolean isDebugging = log.isDebugEnabled(); 131 132 /** 133 * The id of the class that implements this actor. 134 */ 135 private String _classId; 136 137 /** 138 * The java class name. For composites, this is the name of the xml file 139 * like org.kepler.actor.MyCompositeActor 140 */ 141 private String _className; 142 143 /** 144 * The class name as represented in ptII. For composites, this is always 145 * ptolemy.actor.TypedCompositeActor. For java classes, this is the name of 146 * the java class. 147 */ 148 private String _internalClassName; 149 150 /** 151 * The id of the actor. 152 */ 153 private String _actorId; 154 155 /** 156 * The name of the actor 157 */ 158 private String _actorName; 159 160 /** 161 * The instantiation of the actor. TODO describe more about how/when this is 162 * populated, etc. 163 */ 164 private NamedObj _actor; 165 166 /** 167 * True if the actor described by this ActorMetadata is a class description. 168 */ 169 private boolean _isClass; 170 171 /** 172 * dependency ids 173 */ 174 private Vector<ClassedProperty> _dependencyVector; 175 176 /** 177 * semantic types 178 */ 179 private Vector<ClassedProperty> _semanticTypeVector; 180 181 /** 182 * ports 183 */ 184 private Vector<PortMetadata> _portVector; 185 186 /** 187 * changed flag 188 */ 189 private boolean _changed = false; 190 191 /** 192 * attribute vector for generic attributes 193 */ 194 private Vector<Attribute> _attributeVector; 195 196 /** 197 * vector for relations in a composite 198 */ 199 private Vector<ComponentRelation> _relationVector; 200 201 /** 202 * 203 */ 204 private String _links = null; 205 206 /** 207 * 208 */ 209 private Vector<MetadataHandler> _metadataHandlerVector; 210 211 /** 212 * default constructor. this is for serialization only. do not use this. 213 */ 214 public ActorMetadata() { 215 initialize(); 216 // nothing here. 217 } 218 219 private void initialize() { 220 _dependencyVector = new Vector<ClassedProperty>(); 221 _semanticTypeVector = new Vector<ClassedProperty>(); 222 _portVector = new Vector<PortMetadata>(); 223 _attributeVector = new Vector<Attribute>(); 224 _relationVector = new Vector<ComponentRelation>(); 225 _metadataHandlerVector = new Vector<MetadataHandler>(); 226 _isClass = false; 227 } 228 229 /** 230 * Constructor. Takes in xml metadata. This should be a moml entity with the 231 * kepler additional metadata properties. The entity is parsed and an 232 * ActorMetadata object is created with appropriate fields. 233 * 234 * @param moml 235 * the xml metadata 236 */ 237 public ActorMetadata(InputStream moml) throws InvalidMetadataException { 238 if (isDebugging && moml != null) 239 log.debug("ActorMetadata(" + moml.toString() + ")"); 240 241 initialize(); 242 243 try { 244 String momlStr = FileUtil.convertStreamToString(moml); 245 246 if (isDebugging) { 247 // log.debug("\n********************************"); 248 // log.debug(momlStr); 249 // log.debug("********************************\n"); 250 log.debug("**** MoMLParser ****"); 251 } 252 253 /** 254 * The MoMLParser cannot be the first thing to be called on Kepler 255 * generated MoML files. Because TypedIOPorts are converted to 256 * PortAttributes, an error is thrown when trying to parse Kepler 257 * generated MoMLs that have any added ports. TODO: How to fix this? 258 */ 259 MoMLParser parser = new MoMLParser(new Workspace()); 260 parser.reset(); 261 262 if (isDebugging) 263 log.debug("got moml parser outputing moml"); 264 265 NamedObj obj = null; 266 try { 267 obj = parser.parse(null, momlStr); 268 } catch (Exception e) { 269 log.error(e.getMessage()); 270 } 271 if (obj == null) 272 return; 273 274 if (isDebugging) { 275 String filename = "parsed-actor_" + obj.getName() + ".moml"; 276 writeDebugMomlFor(obj, filename); 277 } 278 279 if (obj instanceof TypedCompositeActor) { 280 _links = ((TypedCompositeActor) obj).exportLinks(1, null); 281 } 282 _actorName = obj.getName(); 283 284 StringAttribute classAttribute = (StringAttribute) obj.getAttribute("class"); 285 286 if(classAttribute == null) { 287 throw new InvalidMetadataException("Missing 'class' attribute for " + 288 obj.getFullName()); 289 } 290 291 Attribute idAtt = classAttribute.getAttribute("id"); 292 293 if(idAtt == null) { 294 throw new InvalidMetadataException("Missing 'id' attribute for " + 295 obj.getFullName()); 296 } 297 298 _classId = ((StringAttribute) idAtt).getExpression(); 299 300 _className = classAttribute.getExpression(); 301 _internalClassName = obj.getClassName(); 302 303 Attribute actIdAtt = obj.getAttribute(NamedObjId.NAME); 304 305 if(actIdAtt == null) { 306 throw new InvalidMetadataException("Missing '" + 307 NamedObjId.NAME + "' attribute for " + obj.getFullName()); 308 } 309 310 _actorId = ((NamedObjId) actIdAtt).getExpression(); 311 312 NamedObj actor = getActorClass(_className, _actorName, obj); 313 314 // Handle class definitions 315 if (actor instanceof InstantiableNamedObj) { 316 InstantiableNamedObj ino = (InstantiableNamedObj) actor; 317 if (ino.isClassDefinition()) { 318 _isClass = true; 319 //_internalClassName = _className; 320 } 321 } 322 this.setActor(actor); 323 324 if (isDebugging) { 325 String filename = "instantiated-actor-before_" 326 + getActor().getName() + ".moml"; 327 writeDebugMomlFor(obj, filename); 328 } 329 330 // get the semantic type and dependency lsids and any general 331 // properties 332 for (Object o : obj.attributeList()) { 333 334 Attribute a = null; 335 if (o instanceof Attribute) { 336 a = (Attribute) o; 337 } else { 338 log.error("Object is not an Attribute"); 339 continue; 340 } 341 342 getSemanticTypesAndDependencyLsids(a); 343 344 } 345 346 // get the ports 347 348 // NOTE: we parse obj instead of actor since actor does not have 349 // the PortAttributes 350 parseNamedObj(obj); 351 addAllRelations(); 352 353 if (isDebugging) { 354 String filename = "instantiated-actor-after_" 355 + getActor().getName() + ".moml"; 356 writeDebugMomlFor(obj, filename); 357 } 358 359 } catch (IOException ioe) { 360 throw new InvalidMetadataException("Error reading data from lsid " 361 + _actorId + ": " + ioe.getMessage(), ioe); 362 } catch (Exception e) { 363 if (isDebugging) 364 log.debug(e.getStackTrace()); 365 throw new InvalidMetadataException( 366 "Error in parsing actor metadata: " + e.getMessage(), e); 367 } 368 } 369 370 /** 371 * TODO: What is this doing? 372 * 373 * @param a 374 * @return 375 */ 376 private boolean checkAtt(Attribute a) { 377 String attName = a.getName(); 378 String acn = a.getClassName(); 379 if (!attName.equals(NamedObjId.NAME) && !attName.equals("class") 380 && !acn.equals("org.kepler.moml.PropertyEntity") 381 && !acn.equals("org.kepler.moml.PropertyAttribute") 382 && !acn.equals("org.kepler.moml.CompositeClassEntity") 383 && !acn.equals("org.kepler.moml.PortAttribute")) { 384 return true; 385 } 386 return false; 387 } 388 389 /** 390 * TODO: What is this doing? 391 * 392 * @param a 393 * @throws IllegalActionException 394 * @throws NameDuplicationException 395 * @throws CloneNotSupportedException 396 */ 397 private void getSemanticTypesAndDependencyLsids(Attribute a) 398 throws IllegalActionException, NameDuplicationException, 399 CloneNotSupportedException { 400 401 String attName = a.getName(); 402 String attClassName = a.getClassName(); 403 String aClassName = a.getClass().getName(); 404 String kd = "ptolemy.vergil.basic.KeplerDocumentationAttribute"; 405 406 if (attClassName.equals(kd)) { 407 // parse the documentation 408 409 setDocumentationAttribute((KeplerDocumentationAttribute) a); 410 } else if (checkAtt(a)) { 411 412 String attValue = null; 413 if (a instanceof StringAttribute) { 414 attValue = ((StringAttribute) a).getExpression(); 415 416 } else if (a instanceof UnitAttribute) { 417 attValue = ((UnitAttribute) a).getExpression(); 418 419 } else if (a instanceof Variable) { 420 attValue = ((Variable) a).getExpression(); 421 } 422 423 if (attName.indexOf("semanticType") != -1) { 424 addSemanticType(a.getName(), attValue); 425 426 } else if (attName.indexOf("dependency") != -1) { 427 ClassedProperty prop = new ClassedProperty(attName, attValue, 428 aClassName); 429 _dependencyVector.add(prop); 430 431 } else if (attName.indexOf("_iconDescription") != -1) { 432 NamedObj act = getActor(); 433 Attribute iconAtt = act.getAttribute("_iconDescription"); 434 435 if (act != null && iconAtt != null) { 436 handleIconDescription(a); 437 438 } else { 439 addAttribute(a); 440 } 441 } else { 442 // add generic attributes 443 addAttribute(a); 444 } 445 } 446 } 447 448 /** 449 * TODO: What is this doing? 450 * 451 * @param a 452 */ 453 private void handleIconDescription(Attribute a) { 454 boolean objIsDefault = false; 455 boolean actorIsDefault = false; 456 457 String objIconStr = ((SingletonConfigurableAttribute) a) 458 .getExpression(); 459 String actorIconStr = ((SingletonConfigurableAttribute) getActor() 460 .getAttribute("_iconDescription")).getExpression(); 461 462 // Should this come from somewhere else? 463 String pp = "<polygon" + " points=\"-20,-10 20,0 -20,10\"" 464 + " style=\"fill:blue\"/>"; 465 466 if (objIconStr.indexOf(pp) != -1) { 467 objIsDefault = true; 468 } 469 470 if (actorIconStr.indexOf(pp) != -1) { 471 actorIsDefault = true; 472 } 473 474 if ((objIsDefault && actorIsDefault) 475 || (objIsDefault && actorIsDefault) 476 || (!objIsDefault && !actorIsDefault)) { 477 addAttribute(a); 478 } else if (objIsDefault && !actorIsDefault) { 479 // do nothing. leave the attribute in the actor 480 } 481 } 482 483 /** 484 * builds a new ActorMetadata object from an existing NamedObj 485 * 486 * @param am 487 * the ActorMetadata to build this object from. 488 */ 489 public ActorMetadata(NamedObj obj) { 490 491 //System.out.println(obj.exportMoML()); 492 493 initialize(); 494 495 if (obj instanceof InstantiableNamedObj) { 496 InstantiableNamedObj ino = (InstantiableNamedObj) obj; 497 if (ino.isClassDefinition()) { 498 _isClass = true; 499 } 500 } 501 502 this.setActor(obj); 503 504 if (obj.getAttribute(NamedObjId.NAME) != null) { 505 _actorId = ((NamedObjId) obj.getAttribute(NamedObjId.NAME)) 506 .getExpression(); 507 } 508 _actorName = obj.getName(); 509 510 if (_isClass) { 511 512 Attribute classAtt = obj.getAttribute("tempClassName"); 513 if (classAtt != null) { 514 TransientStringAttribute classAttribute = (TransientStringAttribute) classAtt; 515 String className = classAttribute.getExpression(); 516 _className = className; 517 _internalClassName = className; 518 } 519 520 _links = null; 521 522 addAllAttributes(); 523 addAllRelations(); 524 removeLinks(); 525 526 } else { 527 _className = obj.getClassName(); 528 _internalClassName = obj.getClassName(); 529 try { 530 if (obj instanceof TypedCompositeActor) { 531 _links = ((TypedCompositeActor) obj).exportLinks(1, null); 532 } 533 } catch (Exception e) { 534 System.out.println("Error looking at links: " + e.getMessage()); 535 } 536 537 // set the internalClassname 538 if (obj instanceof TypedAtomicActor) { 539 _internalClassName = "ptolemy.actor.TypedAtomicActor"; 540 } else if (obj instanceof Attribute) { 541 _internalClassName = "org.kepler.moml.PropertyEntity"; 542 } else if (obj instanceof TypedCompositeActor 543 || obj instanceof CompositeEntity) { 544 _internalClassName = "org.kepler.moml.CompositeClassEntity"; 545 } 546 547 addAllAttributes(); 548 addAllRelations(); 549 } 550 parseActor(); 551 } 552 553 /** 554 * return the actor this object was built from. 555 */ 556 public NamedObj getActor() { 557 return _actor; 558 } 559 560 public void setActor(NamedObj actor) { 561 _actor = actor; 562 } 563 564 /** 565 * return the name of the actor 566 */ 567 public String getName() { 568 return _actorName; 569 } 570 571 /** 572 * set the name 573 */ 574 public void setName(String name) { 575 _actorName = name; 576 } 577 578 /** 579 * return the lsid of the actor class object 580 */ 581 public String getId() { 582 return _actorId; 583 } 584 585 /** 586 * returns the id of this object as a KeplerLSID 587 */ 588 public KeplerLSID getLSID() throws Exception { 589 return new KeplerLSID(_actorId); 590 } 591 592 /** 593 * 594 */ 595 public KeplerDocumentationAttribute getDocumentationAttribute() { 596 KeplerDocumentationAttribute da = (KeplerDocumentationAttribute) getActor() 597 .getAttribute("KeplerDocumentation"); 598 return da; 599 } 600 601 /** 602 * 603 */ 604 public void setDocumentationAttribute(KeplerDocumentationAttribute newda) 605 throws IllegalActionException, NameDuplicationException, 606 CloneNotSupportedException { 607 608 NamedObj a = getActor(); 609 if (a == null) 610 return; 611 612 Attribute da = a.getAttribute("documentation"); 613 614 // if the actor already has a da, then get rid of it and set this one 615 // instead 616 if (da != null) 617 da.setContainer(null); 618 619 da = a.getAttribute("KeplerDocumentation"); 620 if (da != null) 621 da.setContainer(null); 622 623 Workspace w = a.workspace(); 624 KeplerDocumentationAttribute n = (KeplerDocumentationAttribute) newda 625 .clone(w); 626 n.setContainer(a); 627 } 628 629 /** 630 * set the id 631 */ 632 public void setId(String id) { 633 _actorId = id; 634 } 635 636 /** 637 * return the classname of the actor object. this will be the java type 638 * classname no matter what kind of actor we are describing. for instance if 639 * it is a java class, it will be a.b.c.ClassName where the file is stored 640 * in a/b/c/ClassName.class. If it is a MoML class, it will be 641 * a.b.c.MomlClassName where the file is a/b/c/MomlClassName.xml 642 */ 643 public String getClassName() { 644 return _className; 645 } 646 647 /** 648 * return the internal class name of the actor object. for composites this 649 * will be ptolemy.actor.TypedCompositeActor. For atomics, it will be the 650 * full java class name. 651 */ 652 public String getInternalClassName() { 653 return _internalClassName; 654 } 655 656 /** 657 * return the id of the class 658 */ 659 public String getClassId() { 660 return _classId; 661 } 662 663 public void setClassId(String id) { 664 _classId = id; 665 } 666 667 /** 668 * add the id of a dependency to the metadata 669 * 670 * @param id 671 * the id of the dependency to add 672 */ 673 public void addDependency(String id) { 674 ClassedProperty cp = new ClassedProperty("dependency", id, 675 "org.kepler.moml.Dependency"); 676 _dependencyVector.addElement(cp); 677 } 678 679 /** 680 * add the id of a semantic type to the metadata 681 * 682 * @param id 683 * the id of the semantic type to add 684 */ 685 public void addSemanticType(String name, String id) { 686 ClassedProperty cp = new ClassedProperty(name, id, 687 "org.kepler.sms.SemanticType"); 688 _semanticTypeVector.addElement(cp); 689 } 690 691 /** 692 * return a vector of the ids of the semantic type reference 693 */ 694 public Vector<String> getSemanticTypes() { 695 Vector<String> v = new Vector<String>(); 696 for (int i = 0; i < _semanticTypeVector.size(); i++) { 697 v 698 .addElement(((ClassedProperty) _semanticTypeVector 699 .elementAt(i)).value); 700 } 701 return v; 702 } 703 704 public Hashtable<String, String> getSemanticTypeHash() { 705 Hashtable<String, String> h = new Hashtable<String, String>(); 706 for (int i = 0; i < _semanticTypeVector.size(); i++) { 707 ClassedProperty cp = (ClassedProperty) _semanticTypeVector 708 .elementAt(i); 709 h.put(cp.name, cp.value); 710 } 711 return h; 712 } 713 714 public void removeSemanticType(String id) { 715 for (int i = 0; i < _semanticTypeVector.size(); i++) { 716 ClassedProperty cp = (ClassedProperty) _semanticTypeVector 717 .elementAt(i); 718 if (cp.name.equals(id)) { 719 _semanticTypeVector.remove(i); 720 break; 721 } 722 } 723 } 724 725 /** 726 * return a vector of the ids of the semantic type reference 727 */ 728 public Vector<String> getDependencies() { 729 Vector<String> v = new Vector<String>(); 730 for (int i = 0; i < _dependencyVector.size(); i++) { 731 v 732 .addElement(((ClassedProperty) _dependencyVector 733 .elementAt(i)).value); 734 } 735 return v; 736 } 737 738 /** 739 * get the changed flag. this is useful for keeping track of the state of 740 * the actor metadata. this flag does not affect this class in any internal 741 * way except for setting the flag. 742 */ 743 public boolean getChanged() { 744 return _changed; 745 } 746 747 /** 748 * set the changed flag. this is useful for keeping track of the state of 749 * the actor metadata. this flag does not affect this class in any internal 750 * way except for setting the flag. 751 * 752 * @param b 753 */ 754 public void setChanged(boolean b) { 755 _changed = b; 756 } 757 758 /** 759 * add a generic attribute to this actorMetadata object. 760 * 761 * @param a 762 * the attribute to add 763 */ 764 public void addAttribute(Attribute a) { 765 // why did we intentionally skip PortParameters? 766 // if 767 // (a.getClassName().equals("ptolemy.actor.parameters.PortParameter")) { 768 // return; 769 // } 770 _attributeVector.add(a); 771 } 772 773 /** 774 * add a relation 775 */ 776 public void addRelation(ComponentRelation r) { 777 _relationVector.add(r); 778 } 779 780 /** 781 * return this actor as a ComponentEntity 782 * 783 * @param container 784 * the new ComponentEntity's container 785 */ 786 public NamedObj getActorAsNamedObj(CompositeEntity container) 787 throws Exception { 788 789 NamedObj obj = null; 790 791 // Throw a NullPointerException here with a good message. 792 // If actor is null, clone() will fail anyway. 793 if (getActor() == null) { 794 throw new NullPointerException( 795 "Could not clone '" 796 + _actorName 797 + "' from the '" 798 + _className 799 + "' class; the object is null, possibly meaning it was not " 800 + "found. Perhaps there is a classpath problem and/or the " 801 + "karlib needs to be flushed?"); 802 803 } else if (getActor() instanceof TypedCompositeActor) { 804 805 /* 806 * if we are dealing with a composite entity, do stuff a bit 807 * differently we need to instantiate the composite or else it will 808 * show up in the library as a class instead of an entity. this 809 * causes kepler to think that the user wants to drag a class to the 810 * canvas and it requires the user to instantiate the actor before 811 * using it. by calling instantiate here, we bypass that. 812 */ 813 if (_internalClassName 814 .equals("org.kepler.moml.CompositeClassEntity")) { 815 obj = getActor(); 816 obj = addPorts(obj, _portVector); 817 818 if (container == null) { 819 try { 820 NamedObj newobj = (NamedObj) getActor().clone( 821 new Workspace()); 822 // this kinda works 823 return newobj; 824 } catch (java.lang.CloneNotSupportedException cnse) { 825 System.out 826 .println("trying to clone " 827 + getActor().getName() 828 + " but " 829 + "you can't clone this object for some reason: " 830 + cnse.getMessage()); 831 } 832 } else { 833 return (NamedObj) getActor().clone(container.workspace()); 834 // this kinda works 835 } 836 // return 837 // (NamedObj)((TypedCompositeActor)actor).instantiate(container, 838 // actor.getName()); 839 // obj = 840 // (NamedObj)((TypedCompositeActor)actor).instantiate(container, 841 // actor.getName()); 842 // obj.setClassName(className); 843 // return obj; 844 } else { 845 846 // see if the internal class name is a subclass of composite actor 847 Class<?> clazz = Class.forName(_internalClassName); 848 Class<?> compositeActorClass = Class.forName("ptolemy.actor.TypedCompositeActor"); 849 if(compositeActorClass.isAssignableFrom(clazz)) { 850 // clone it 851 if(container == null) { 852 return (NamedObj) getActor().clone(new Workspace()); 853 } else { 854 return (NamedObj) getActor().clone(container.workspace()); 855 } 856 } else { 857 obj = (NamedObj) ((TypedCompositeActor) getActor()) 858 .instantiate(container, getActor().getName()); 859 obj.setClassName(_className); 860 } 861 } 862 863 } else if (getActor() instanceof Director 864 || getActor() instanceof Attribute) { 865 // this is a director or other Attribute derived class 866 867 // obj = new Director(container, actorName); 868 // obj.setClassName(className); 869 if (container == null) { 870 obj = (NamedObj) getActor().clone(new Workspace()); 871 } else { 872 obj = (NamedObj) getActor().clone(container.workspace()); 873 } 874 875 } else { 876 // this is an atomic actor 877 if (container != null) { 878 obj = (NamedObj) getActor().clone(container.workspace()); 879 ((TypedAtomicActor) obj).setContainer(container); 880 } else { 881 obj = (NamedObj) getActor().clone(null); 882 } 883 } 884 885 // call the metadata handlers 886 for (int i = 0; i < _metadataHandlerVector.size(); i++) { 887 MetadataHandler handler = (MetadataHandler) _metadataHandlerVector 888 .elementAt(i); 889 handler.handleMetadata(obj); 890 } 891 892 NamedObjId objId; 893 StringAttribute classObj; 894 StringAttribute classIdObj; 895 896 try { 897 objId = new NamedObjId(obj, NamedObjId.NAME); 898 } catch (ptolemy.kernel.util.IllegalActionException iee) { 899 objId = (NamedObjId) obj.getAttribute(NamedObjId.NAME); 900 } catch (ptolemy.kernel.util.NameDuplicationException nde) { 901 objId = (NamedObjId) obj.getAttribute(NamedObjId.NAME); 902 } 903 904 try { 905 classObj = new StringAttribute(obj, "class"); 906 classIdObj = new StringAttribute(classObj, "id"); 907 } catch (ptolemy.kernel.util.InternalErrorException iee) { 908 classObj = (StringAttribute) obj.getAttribute("class"); 909 classIdObj = (StringAttribute) classObj.getAttribute("id"); 910 } catch (ptolemy.kernel.util.NameDuplicationException nde) { 911 classObj = (StringAttribute) obj.getAttribute("class"); 912 classIdObj = (StringAttribute) classObj.getAttribute("id"); 913 } 914 915 if (objId != null) { 916 objId.setExpression(_actorId); 917 } 918 919 classObj.setExpression(_className); 920 classIdObj.setExpression(_classId); 921 for (int i = 0; i < _semanticTypeVector.size(); i++) { 922 ClassedProperty cp = (ClassedProperty) _semanticTypeVector 923 .elementAt(i); 924 Attribute attribute = obj.getAttribute(cp.name); 925 if (attribute == null) { 926 SemanticType semType = new SemanticType(obj, cp.name); 927 semType.setExpression(cp.value); 928 } 929 else if (!(attribute instanceof SemanticType)) { 930 log.warn("Attribute is not a SemanticType as expected"); 931 } 932 } 933 /* 934 * FIXME: TODO: add dependencies and other info to the NamedObj 935 */ 936 937 // add the general attributes to the object 938 for (int i = 0; i < _attributeVector.size(); i++) { 939 Attribute a = (Attribute) _attributeVector.elementAt(i); 940 Attribute aClone = (Attribute) a.clone(obj.workspace()); 941 try { 942 aClone.setContainer(obj); 943 } catch (NameDuplicationException nde) { 944 // System.out.println("obj already has attribute " + 945 // a.getName()); 946 // ignore this, it shouldn't matter. 947 // Specialized versions of some actors (e.g. RExpression actor 948 // require that parameters be reset to new values 949 // without the following code, these will not be reset 950 // Dan Higgins - 1/20/2006 951 String attValue; 952 String attName; 953 attName = aClone.getName(); 954 if (aClone instanceof StringAttribute) { 955 attValue = ((StringAttribute) aClone).getExpression(); 956 StringAttribute sa = (StringAttribute) obj 957 .getAttribute(attName); 958 sa.setExpression(attValue); 959 } else if (aClone instanceof StringParameter) { 960 attValue = ((StringParameter) aClone).getExpression(); 961 StringParameter sp = (StringParameter) obj 962 .getAttribute(attName); 963 sp.setExpression(attValue); 964 } else if (aClone instanceof Parameter) { 965 attValue = ((Parameter) aClone).getExpression(); 966 Parameter pp = (Parameter) obj.getAttribute(attName); 967 pp.setExpression(attValue); 968 } 969 970 } 971 } 972 973 // copy any extra moml ports over 974 if (!(getActor() instanceof Director)) { 975 obj = addPorts(obj, _portVector); 976 } 977 978 return obj; 979 } 980 981 /** 982 * return the moml xml representation of the actor. 983 */ 984 public String toString() { 985 if (isDebugging) { 986 log.debug("toString()"); 987 } 988 return toString(true, true, true); 989 } 990 991 /** 992 * return the moml xml representation of the actor. 993 * @param incSemanticTypeNames if true, add a suffix to property names 994 * for semantic types, e.g. semanticType00 -> semanticType000 995 * @param includeAttributes if true, add the attributes and parameters 996 * to the xml representation. this flag does not affect semantic types 997 * or documentation attributes. 998 * @param includePorts if true, add the ports to the xml representation. 999 */ 1000 public String toString(boolean addSuffixToSemanticTypeNames, 1001 boolean includeAttributes, boolean includePorts) { 1002 1003 StringBuffer sb = new StringBuffer(); 1004 1005 sb.append("<?xml version=\"1.0\"?>\n"); 1006 1007 sb.append("<!DOCTYPE entity PUBLIC " 1008 + "\"-//UC Berkeley//DTD MoML 1//EN\"\n" 1009 + " \"http://ptolemy.eecs.berkeley.edu" 1010 + "/xml/dtd/MoML_1.dtd\">\n"); 1011 NamedObj actor = getActor(); 1012 if (actor instanceof PropertyAttribute) { 1013 1014 sb.append("<property name=\"" + _actorName 1015 + "\" class=\"org.kepler.moml.PropertyAttribute\">\n"); 1016 1017 } else if (actor instanceof Attribute) { 1018 1019 sb.append("<property name=\"" + _actorName 1020 + "\" class=\"org.kepler.moml.PropertyEntity\">\n"); 1021 1022 } else if (_internalClassName 1023 .equals("org.kepler.moml.CompositeClassEntity")) { 1024 1025 sb.append("<entity name=\"" + _actorName 1026 + "\" class=\"org.kepler.moml.CompositeClassEntity\">\n"); 1027 1028 } else { 1029 1030 if (_isClass) { 1031 //System.out.println("isClass: " + _internalClassName); 1032 sb.append("<entity name=\"" + _actorName 1033 + "\" class=\"" + _internalClassName + "\">\n"); 1034 } else if(actor instanceof TypedAtomicActor) { 1035 sb.append("<entity name=\"" + _actorName 1036 + "\" class=\"ptolemy.actor.TypedAtomicActor\">\n"); 1037 } else { 1038 // FIXME what about composites? 1039 sb.append("<entity name=\"" + _actorName 1040 + "\" class=\"ptolemy.kernel.ComponentEntity\">\n"); 1041 } 1042 1043 } 1044 1045 sb.append("<property name=\"" + NamedObjId.NAME + "\" value=\"" 1046 + _actorId + "\" class=\"org.kepler.moml.NamedObjId\"/>\n"); 1047 1048 if (_internalClassName.equals("ptolemy.actor.Director") 1049 || _internalClassName 1050 .equals("ptolemy.actor.TypedCompositeActor") 1051 || _internalClassName.equals("ptolemy.kernel.ComponentEntity") 1052 || _internalClassName.equals("ptolemy.actor.TypedAtomicActor") 1053 || _internalClassName.equals("org.kepler.moml.PropertyEntity") 1054 || _internalClassName 1055 .equals("org.kepler.moml.CompositeClassEntity")) { 1056 sb.append("<property name=\"class\" value=\"" + _className 1057 + "\" class=\"ptolemy.kernel.util.StringAttribute\">\n"); 1058 } else { 1059 sb.append("<property name=\"class\" value=\"" + _internalClassName 1060 + "\" class=\"ptolemy.kernel.util.StringAttribute\">\n"); 1061 } 1062 1063 // add another property to tell what the moml class is 1064 if (_internalClassName.equals("ptolemy.actor.TypedCompositeActor")) { 1065 sb.append(" <property name=\"momlClass\" value=\"" + _className 1066 + "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 1067 } 1068 sb.append(" <property name=\"id\" value=\"" + _classId 1069 + "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 1070 sb.append("</property>\n"); 1071 1072 // print the dependencies 1073 if (_dependencyVector.size() != 0) { 1074 for (int i = 0; i < _dependencyVector.size(); i++) { 1075 ClassedProperty cp = (ClassedProperty) _dependencyVector.get(i); 1076 cp.addNameIterator(i); 1077 sb.append(cp.toString() + "\n"); 1078 } 1079 } 1080 1081 // print the semantic types 1082 if (_semanticTypeVector.size() != 0) { 1083 for (int i = 0; i < _semanticTypeVector.size(); i++) { 1084 ClassedProperty cp = (ClassedProperty) _semanticTypeVector 1085 .get(i); 1086 if(addSuffixToSemanticTypeNames) { 1087 cp.addNameIterator(i); 1088 } 1089 sb.append(cp.toString() + "\n"); 1090 } 1091 } 1092 1093 // add general attributes 1094 if (_attributeVector.size() != 0) { 1095 for (int i = 0; i < _attributeVector.size(); i++) { 1096 Attribute a = (Attribute) _attributeVector.elementAt(i); 1097 if(includeAttributes || (a instanceof SemanticType)) { 1098 sb.append(a.exportMoML() + "\n"); 1099 } 1100 } 1101 } 1102 1103 // print the ports 1104 // NOTE: the ports must come after attributes since ParameterPorts 1105 // must come after the PortParameters. otherwise parsing the xml 1106 // results in a NameDuplicatonException. 1107 // see http://bugzilla.ecoinformatics.org/show_bug.cgi?id=4580 1108 1109 if (includePorts && _portVector.size() != 0) { 1110 for (int i = 0; i < _portVector.size(); i++) { 1111 if (getActor() instanceof TypedCompositeActor 1112 && getActor() instanceof InstantiableNamedObj 1113 && !((InstantiableNamedObj) getActor()) 1114 .isClassDefinition()) { 1115 sb.append(((PortMetadata) _portVector.get(i)) 1116 .toMoMLString()); 1117 } else { 1118 sb.append(((PortMetadata) _portVector.get(i)).toString()); 1119 } 1120 } 1121 } 1122 1123 // add relations 1124 if (_relationVector.size() != 0) { 1125 for (int i = 0; i < _relationVector.size(); i++) { 1126 ComponentRelation r = (ComponentRelation) _relationVector 1127 .elementAt(i); 1128 sb.append(r.exportMoML() + "\n"); 1129 } 1130 1131 } 1132 1133 // add documentation 1134 KeplerDocumentationAttribute da = getDocumentationAttribute(); 1135 if (da != null) { 1136 sb.append(da.exportMoML()); 1137 } 1138 1139 String cce = "org.kepler.moml.CompositeClassEntity"; 1140 if (_internalClassName.equals(cce)) { 1141 CompositeEntity ce = (CompositeEntity) getActor(); 1142 1143 // add any class definitions 1144 // NOTE: these must be added before the entities since the 1145 // MoMLParser needs to read them first. 1146 List<?> classDefinitions = ce.classDefinitionList(); 1147 for(Object obj : classDefinitions) { 1148 String classDefinitionMoml = ((NamedObj)obj).exportMoML(); 1149 sb.append(classDefinitionMoml); 1150 } 1151 1152 List<?> entList = ce.entityList(); 1153 Iterator<?> entityItt = entList.iterator(); 1154 1155 while (entityItt.hasNext()) { 1156 Entity ent = (Entity) entityItt.next(); 1157 String entMoml = ent.exportMoML(); 1158 sb.append(entMoml); 1159 } 1160 1161 } 1162 1163 if (_links != null) { 1164 sb.append(_links); 1165 } 1166 1167 if (getActor() instanceof Attribute 1168 || getActor() instanceof PropertyAttribute) { 1169 sb.append("</property>"); 1170 } else { 1171 sb.append("</entity>\n"); 1172 } 1173 1174 return sb.toString(); 1175 } 1176 1177 /** 1178 * this method allows other classes to add handlers to further process the 1179 * metadata produced by this class. The handlers will be called in the 1180 * getActorAsNamedObj() and getActorClass() methods. 1181 * 1182 * @param handler 1183 * the handler to add 1184 */ 1185 public void addMetadataHandler(MetadataHandler handler) { 1186 _metadataHandlerVector.add(handler); 1187 } 1188 1189 /** 1190 * remove a metadata handler 1191 * 1192 * @param handler 1193 * the handler to remove 1194 */ 1195 public void removeMetadataHandler(MetadataHandler handler) { 1196 _metadataHandlerVector.remove(handler); 1197 } 1198 1199 private boolean addPort(TypedIOPort p, PortMetadata pm) 1200 throws IllegalActionException { 1201 if (isDebugging) 1202 log.debug("*************p: " + p.exportMoML()); 1203 boolean found = false; 1204 1205 String pName = p.getName(); 1206 String cpName = cleansePortName(pm.name); 1207 if (pName.equals(cpName)) { 1208 1209 if (isDebugging) 1210 log.debug("adding port " + pm.name); 1211 1212 Vector<NamedObj> pAtts = pm.attributes; 1213 for (int j = 0; j < pAtts.size(); j++) { 1214 try { 1215 if (isDebugging) 1216 log.debug("cloning port " + pm.name); 1217 1218 NamedObj noAtt = pAtts.elementAt(j); 1219 1220 Attribute pm_att = (Attribute) noAtt; 1221 if (isDebugging) 1222 log.debug("processing attribute: " + pm_att.getName()); 1223 if (pm_att instanceof SemanticType) { 1224 ((Attribute) ((Attribute) pAtts.elementAt(j)).clone(p 1225 .workspace())).setContainer(p); 1226 // System.out.println("added attribute " + 1227 // ((Attribute)pm.attributes.elementAt(j)).getName() 1228 // + " to port " + p.getName()); 1229 } 1230 // System.out.println("cloned port " + pm.name); 1231 // System.out.println("<port> is now: " + 1232 // p.exportMoML()); 1233 } catch (NameDuplicationException nde) { 1234 // System.out.println("tried to duplicate " + 1235 // pm.attributes.elementAt(j).toString()); 1236 } catch (java.lang.CloneNotSupportedException cnse) { 1237 } 1238 } 1239 found = true; 1240 } 1241 return found; 1242 } 1243 1244 /** 1245 * adds any kepler ports to the actor 1246 */ 1247 private NamedObj addPorts(NamedObj obj, Vector<PortMetadata> portVector) 1248 throws IllegalActionException, NameDuplicationException { 1249 boolean found = false; 1250 1251 for (int i = 0; i < portVector.size(); i++) { 1252 1253 // if there are any ports in the port vector that are not in the 1254 // port iterator, add them 1255 1256 Entity ent = (Entity) obj; 1257 List<?> pList = ent.portList(); 1258 Iterator<?> portIterator = pList.iterator(); 1259 PortMetadata pm = (PortMetadata) portVector.elementAt(i); 1260 Vector<NamedObj> pmAtts = pm.attributes; 1261 1262 if (isDebugging) 1263 log.debug("**********pm: " + pm.toString()); 1264 1265 while (portIterator.hasNext()) { 1266 1267 TypedIOPort p = (TypedIOPort) portIterator.next(); 1268 found = addPort(p, pm); 1269 if (found) 1270 break; 1271 1272 } 1273 1274 if (!found) { 1275 TypedIOPort port = null; 1276 1277 if (obj instanceof TypedAtomicActor) { 1278 TypedAtomicActor taa = (TypedAtomicActor) obj; 1279 List<?> taaPL = taa.portList(); 1280 Iterator<?> portList = taaPL.iterator(); 1281 1282 boolean flag = true; 1283 while (portList.hasNext()) { 1284 1285 TypedIOPort oldport = (TypedIOPort) portList.next(); 1286 String oldportName = oldport.getName(); 1287 1288 if (oldportName.equals(pm.name)) 1289 flag = false; 1290 1291 List<?> opAttList = oldport.attributeList(); 1292 1293 if (isDebugging) { 1294 log.debug("old port atts: " + opAttList.size()); 1295 log.debug("pm att size: " + pmAtts.size()); 1296 } 1297 1298 if (opAttList.size() != pmAtts.size()) 1299 flag = true; 1300 } 1301 1302 if (flag) { 1303 1304 if (isDebugging) 1305 log.debug("adding port " + pm.name + " to obj"); 1306 1307 String cpName = cleansePortName(pm.name); 1308 port = new TypedIOPort(taa, cpName); 1309 1310 } else { 1311 1312 if (isDebugging) { 1313 log.debug("not adding port " + pm.name + " to obj"); 1314 } 1315 1316 } 1317 } else { 1318 1319 TypedCompositeActor tca = (TypedCompositeActor) obj; 1320 List<?> tcaPList = tca.portList(); 1321 Iterator<?> portList = tcaPList.iterator(); 1322 1323 boolean flag = true; 1324 while (portList.hasNext()) { 1325 1326 TypedIOPort oldport = (TypedIOPort) portList.next(); 1327 String oldportName = oldport.getName(); 1328 1329 if (oldportName.equals(pm.name)) 1330 flag = false; 1331 } 1332 1333 if (flag) { 1334 String cpName = cleansePortName(pm.name); 1335 port = new TypedIOPort(tca, cpName); 1336 } 1337 } 1338 1339 if (port == null) { 1340 continue; 1341 } 1342 1343 if (pm.direction.equals("input")) { 1344 port.setInput(true); 1345 } else if (pm.direction.equals("output")) { 1346 port.setOutput(true); 1347 } else if (pm.direction.equals("inputoutput")) { 1348 port.setInput(true); 1349 port.setOutput(true); 1350 } 1351 1352 if (pm.multiport) { 1353 port.setMultiport(true); 1354 } 1355 1356 Iterator<?> attItt = pmAtts.iterator(); 1357 while (attItt.hasNext()) { 1358 1359 Attribute a = (Attribute) attItt.next(); 1360 try { 1361 Workspace pws = port.workspace(); 1362 Attribute attClone = (Attribute) a.clone(pws); 1363 attClone.setContainer(port); 1364 1365 } catch (CloneNotSupportedException cnse) { 1366 System.out.println("Cloning the attribute " 1367 + a.getName() + " is not supported: " 1368 + cnse.getMessage()); 1369 } 1370 } 1371 } else { 1372 found = false; 1373 } 1374 } 1375 1376 return obj; 1377 } 1378 1379 /** 1380 * removes the 'kepler:' from the port names. this tag is used to keep ptii 1381 * from throwing name duplication exceptions becuase our port metadata 1382 * Parameter has the same name as the port it describes 1383 */ 1384 private String cleansePortName(String portName) { 1385 if (portName.indexOf("kepler:") != -1) { 1386 // strip the kepler: off of the name. kepler: is there to 1387 // prevent namedup exceptions in the moml parser 1388 return portName.substring(7, portName.length()); 1389 } 1390 return portName; 1391 } 1392 1393 /** 1394 * parse an actor to create the actorMetadata object 1395 * 1396 *@param actor 1397 */ 1398 private void parseActor() { 1399 NamedObj actor = getActor(); 1400 if (actor instanceof ComponentEntity /* 1401 * && !(actor instanceof 1402 * TypedCompositeActor) 1403 */) { 1404 List<?> list = ((ComponentEntity) actor).portList(); 1405 Iterator<?> portIterator = list.iterator(); 1406 while (portIterator.hasNext()) { 1407 Port p = (Port) portIterator.next(); 1408 PortMetadata pm = new PortMetadata(); 1409 1410 pm.name = p.getName(); 1411 1412 if(p instanceof TypedIOPort) 1413 { 1414 pm.type = ((TypedIOPort)p).getType().toString(); 1415 } 1416 1417 if(p instanceof IOPort) 1418 { 1419 IOPort iop = (IOPort)p; 1420 1421 pm.multiport = iop.isMultiport(); 1422 1423 if (iop.isInput() && iop.isOutput()) { 1424 pm.direction = "inputoutput"; 1425 1426 } else if (iop.isInput()) { 1427 pm.direction = "input"; 1428 1429 } else if (iop.isOutput()) { 1430 pm.direction = "output"; 1431 } 1432 } 1433 1434 pm.portClassName = p.getClassName(); 1435 1436 // get any other port attributes and copy them 1437 List<?> portAttList = p.attributeList(); 1438 Iterator<?> portAttsIt = portAttList.iterator(); 1439 1440 while (portAttsIt.hasNext()) { 1441 1442 NamedObj att = (NamedObj) portAttsIt.next(); 1443 pm.addAttribute(att); 1444 1445 if (isDebugging) 1446 log.debug("adding att: " + att.exportMoML()); 1447 } 1448 1449 _portVector.addElement(pm); 1450 } 1451 } 1452 } 1453 1454 /** 1455 * parse a named obj and get it's port info 1456 */ 1457 private void parseNamedObj(NamedObj obj) throws InvalidMetadataException { 1458 1459 if (obj instanceof CompositeClassEntity) { 1460 1461 // if it's a composite, look for the <port> objects instead of the 1462 // PortProperties 1463 Entity ent = (Entity) obj; 1464 List<?> pList = ent.portList(); 1465 Iterator<?> portIterator = pList.iterator(); 1466 1467 while (portIterator.hasNext()) { 1468 1469 TypedIOPort port = (TypedIOPort) portIterator.next(); 1470 PortMetadata pm = new PortMetadata(); 1471 1472 pm.name = port.getName(); 1473 pm.type = port.getType().toString(); 1474 pm.multiport = port.isMultiport(); 1475 1476 if (port.isInput()) { 1477 pm.direction = "input"; 1478 } 1479 1480 if (port.isOutput()) { 1481 pm.direction = "output"; 1482 } 1483 1484 if (port.isOutput() && port.isInput()) { 1485 pm.direction = "inputoutput"; 1486 } 1487 1488 pm.portClassName = port.getClassName(); 1489 1490 List<?> attList = port.attributeList(); 1491 Iterator<?> listIt = attList.iterator(); 1492 1493 while (listIt.hasNext()) { 1494 NamedObj att = (NamedObj) listIt.next(); 1495 pm.addAttribute(att); 1496 } 1497 1498 _portVector.addElement(pm); 1499 1500 } 1501 1502 } else if (obj instanceof ComponentEntity) { 1503 1504 List<?> list = null; 1505 try { 1506 1507 Class<?> cls = Class.forName("org.kepler.moml.PortAttribute"); 1508 ComponentEntity ce = (ComponentEntity) obj; 1509 list = ce.attributeList(cls); 1510 1511 } catch (ClassNotFoundException cnfe) { 1512 } 1513 1514 Iterator<?> portIterator = list.iterator(); 1515 1516 while (portIterator.hasNext()) { 1517 PortAttribute pa = (PortAttribute) portIterator.next(); 1518 PortMetadata pm = new PortMetadata(); 1519 1520 pm.name = pa.getName(); 1521 if(pm.name == null) { 1522 throw new InvalidMetadataException("Port is missing name."); 1523 } 1524 1525 StringAttribute attribute = (StringAttribute) pa.getAttribute("dataType"); 1526 if(attribute == null) { 1527 throw new InvalidMetadataException("Port " + pm.name + " is missing dataType attribute."); 1528 } 1529 pm.type = attribute.getExpression(); 1530 1531 attribute = (StringAttribute) pa.getAttribute("isMultiport"); 1532 if(attribute == null) { 1533 throw new InvalidMetadataException("Port " + pm.name + " is missing isMultiport attribute."); 1534 } 1535 1536 // try parsing the boolean string 1537 try { 1538 pm.multiport = Boolean.valueOf(attribute.getExpression()).booleanValue(); 1539 } catch(Throwable t) { 1540 throw new InvalidMetadataException("Invalid isMultiport value for port " 1541 + pm.name + ": " + attribute.getExpression()); 1542 } 1543 1544 attribute = (StringAttribute) pa.getAttribute("direction"); 1545 if(attribute == null) { 1546 throw new InvalidMetadataException("Port " + pm.name + " is missing direction attribute."); 1547 } 1548 pm.direction = attribute.getExpression(); 1549 1550 List<?> attList = pa.attributeList(); 1551 Iterator<?> listIt = attList.iterator(); 1552 1553 while (listIt.hasNext()) { 1554 NamedObj att = (NamedObj) listIt.next(); 1555 1556 if (!att.getName().equals("dataType") 1557 && !att.getName().equals("isMultiport") 1558 && !att.getName().equals("direction")) { 1559 1560 if (isDebugging) 1561 log.debug("adding att: " + att.exportMoML()); 1562 pm.addAttribute(att); 1563 } 1564 } 1565 1566 _portVector.addElement(pm); 1567 } 1568 } 1569 } 1570 1571 /** 1572 * look for a moml class and try to instantiate it 1573 * 1574 * @param actorName 1575 * @param className 1576 * @param actorMetadataMoml 1577 * @return 1578 */ 1579 private NamedObj lookForMoml(String actorName, String className, 1580 NamedObj actorMetadataMoml) throws Exception { 1581 if (isDebugging) log.debug("lookForMoml"); 1582 1583 if (_internalClassName.equals("org.kepler.moml.CompositeClassEntity")) { 1584 // This is a total hack, but I cannot get the 1585 // CompositeActors to clone correctly, so this try statement 1586 // basically clones them manually. It works so i'm leaving 1587 // it for now. 1588 try { 1589 StringBuffer sb = new StringBuffer(); 1590 // sb.append("<class name=\"" + actorName + 1591 // "\" extends=\"" + className + "\">"); 1592 sb.append("<entity name=\"" + actorName + "\" class=\"" 1593 + className + "\">"); 1594 1595 // get attributes and clone them over to the new obj 1596 CompositeClassEntity cce = (CompositeClassEntity) actorMetadataMoml; 1597 Iterator<?> attItt = cce.attributeList().iterator(); 1598 1599 while (attItt.hasNext()) { 1600 Attribute a = (Attribute) attItt.next(); 1601 sb.append(a.exportMoML()); 1602 } 1603 1604 // get entities and clone them over to the new obj 1605 1606 Iterator<?> entItt = cce.entityList().iterator(); 1607 while (entItt.hasNext()) { 1608 ComponentEntity ent = (ComponentEntity) entItt.next(); 1609 sb.append(ent.exportMoML()); 1610 } 1611 1612 // get ports and clone them over to the new obj 1613 Iterator<?> portItt = cce.portList().iterator(); 1614 while (portItt.hasNext()) { 1615 Port p = (Port) portItt.next(); 1616 sb.append(p.exportMoML()); 1617 } 1618 1619 // get relations and clone them over to the new obj 1620 TypedCompositeActor tca = (TypedCompositeActor) actorMetadataMoml; 1621 Iterator<?> relationItt = tca.relationList().iterator(); 1622 while (relationItt.hasNext()) { 1623 ComponentRelation r = (ComponentRelation) relationItt 1624 .next(); 1625 sb.append(r.exportMoML()); 1626 } 1627 1628 sb.append(_links); 1629 // sb.append("</class>"); 1630 sb.append("</entity>"); 1631 1632 Workspace w = actorMetadataMoml.workspace(); 1633 1634 if (isDebugging) 1635 log.debug("**** MoMLParser ****"); 1636 1637 MoMLParser parser = new MoMLParser(w); 1638 parser.reset(); 1639 NamedObj obj = parser.parse(sb.toString()); 1640 return obj; 1641 } catch (Exception exc) { 1642 System.out.println("error creating compositeClassEntity: " 1643 + exc.getMessage()); 1644 exc.printStackTrace(); 1645 throw exc; 1646 } 1647 } else { 1648 1649 // see if the internal class name is a subclass of composite actor 1650 Class<?> clazz = Class.forName(_internalClassName); 1651 Class<?> compositeActorClass = Class.forName("ptolemy.actor.TypedCompositeActor"); 1652 if(compositeActorClass.isAssignableFrom(clazz)) { 1653 1654 // parse the moml in the actor metadata 1655 MoMLParser parser = new MoMLParser(actorMetadataMoml.workspace()); 1656 parser.reset(); 1657 NamedObj obj = parser.parse(actorMetadataMoml.exportMoML()); 1658 return obj; 1659 1660 } else { 1661 // ptolemy.kernel.ComponentEntity 1662 ComponentEntity actor = parseMoMLFile(className); 1663 if (isDebugging) { 1664 log.debug("returning " + actor.getName()); 1665 } 1666 return (TypedCompositeActor) actor; 1667 } 1668 } 1669 1670 } 1671 1672 /** 1673 * get the actor class and instantiate it to a NamedObj and return it 1674 */ 1675 private NamedObj getActorClass(String className, String actorName, 1676 NamedObj actorMetadataMoml) { 1677 1678 if (isDebugging && actorMetadataMoml != null) { 1679 log.debug("getActorClass(" + className + "," + actorName + "," 1680 + actorMetadataMoml.getName() + ")"); 1681 } 1682 1683 // try to get the actor class and instantiate it 1684 try { 1685 1686 TypedAtomicActor actor; 1687 Class<?> actorClass = Class.forName(className); 1688 CompositeEntity ce = new CompositeEntity(); 1689 Object[] args = { ce, actorName }; 1690 actor = (TypedAtomicActor) createInstance(actorClass, args); 1691 1692 // call the metadata handlers 1693 for (int i = 0; i < _metadataHandlerVector.size(); i++) { 1694 1695 Object o = _metadataHandlerVector.elementAt(i); 1696 MetadataHandler handler = (MetadataHandler) o; 1697 handler.handleMetadata(actor); 1698 } 1699 1700 return actor; 1701 1702 } catch (Exception e) { 1703 if (isDebugging) { 1704 log.debug(e.toString()); 1705 log.debug(_internalClassName); 1706 } 1707 1708 NamedObj secTry; 1709 try { 1710 1711 secTry = lookForMoml(actorName, className, actorMetadataMoml); 1712 return secTry; 1713 1714 } catch (Exception ee) { 1715 if (isDebugging) 1716 log.debug(ee.toString()); 1717 1718 NamedObj thirdTry; 1719 try { 1720 1721 thirdTry = handleNonEntityDirectors(actorName, className, 1722 actorMetadataMoml); 1723 return thirdTry; 1724 1725 } catch (Exception eee) { 1726 1727 if (isDebugging) 1728 log.debug(eee.toString()); 1729 1730 NamedObj fourthTry; 1731 try { 1732 1733 fourthTry = handleMiscAtt(actorName, className, 1734 actorMetadataMoml); 1735 return fourthTry; 1736 1737 } catch (Exception eeee) { 1738 1739 printFinalException(eeee,className); 1740 return null; 1741 } 1742 } 1743 } 1744 } 1745 } 1746 1747 /** 1748 * Helper method. 1749 * @param eeee 1750 * @param className 1751 */ 1752 private void printFinalException(Exception eeee,String className) { 1753 System.out.println("The class name you entered was either not " 1754 + "found in classpath or could not be instantiated:"); 1755 System.out.println(className); 1756 System.out.println("Note that this class must be in the " 1757 + "classpath from which you launched this program."); 1758 String msg = eeee.getMessage(); 1759 if (msg != null) { 1760 System.out.println(msg); 1761 } 1762 1763 } 1764 1765 /** 1766 * Todo: What is this doing? 1767 * @param className 1768 * @param actorName 1769 * @param actorMetadataMoml 1770 * @return 1771 * @throws Exception 1772 */ 1773 private NamedObj handleMiscAtt(String actorName, String className, 1774 NamedObj actorMetadataMoml) throws Exception { 1775 1776 Attribute att; 1777 Class<?> attClass = Class.forName(className); 1778 // NOTE: place the attribute inside a TypedCompositeActor instead 1779 // of a CompositeEntity since PortParameter requires the container 1780 // to implement TypedActor. 1781 Object[] args = { new TypedCompositeActor(), actorName }; 1782 att = (Attribute) createInstance(attClass, args); 1783 return att; 1784 } 1785 1786 /** 1787 * This handles directors which are not entities, but attributes 1788 * 1789 * @param className 1790 * @param actorName 1791 * @param actorMetadataMoml 1792 * @return 1793 * @throws Exception 1794 */ 1795 private NamedObj handleNonEntityDirectors(String actorName, 1796 String className, NamedObj actorMetadataMoml) throws Exception { 1797 1798 Director director; 1799 Class<?> directorClass = Class.forName(className); 1800 Object[] args = { new CompositeEntity(), actorName }; 1801 director = (Director) createInstance(directorClass, args); 1802 return director; 1803 } 1804 1805 /** 1806 * add all of the attributes with the exception of the kepler attributes 1807 * (which should already be in the metadata) to the AM object. 1808 * 1809 * @param obj 1810 * the NamedObj to get the attributes from. 1811 */ 1812 private void addAllAttributes() { 1813 NamedObj obj = getActor(); 1814 if (obj != null && obj.attributeList() != null) { 1815 1816 List<?> attList = obj.attributeList(); 1817 Iterator<?> i = attList.iterator(); 1818 1819 while (i.hasNext()) { 1820 Attribute a = (Attribute) i.next(); 1821 String name = a.getName(); 1822 if (!name.equals(NamedObjId.NAME) && !name.equals("class") 1823 && !name.equals("KeplerDocumentation") 1824 && name.indexOf("dependency") == -1) { 1825 addAttribute(a); 1826 } 1827 1828 } 1829 } 1830 } 1831 1832 private void removeLinks() { 1833 NamedObj obj = getActor(); 1834 if (obj == null) return; 1835 } 1836 1837 /** 1838 * add all of the relations 1839 * 1840 * @param obj 1841 * the NamedObj to get the attributes from. 1842 */ 1843 private void addAllRelations() { 1844 NamedObj obj = getActor(); 1845 if (obj == null) return; 1846 1847 if (obj instanceof TypedCompositeActor) { 1848 TypedCompositeActor tca = (TypedCompositeActor) obj; 1849 List<?> relList = tca.relationList(); 1850 if (relList != null) { 1851 1852 Iterator<?> i = relList.iterator(); 1853 while (i.hasNext()) { 1854 ComponentRelation r = (ComponentRelation) i.next(); 1855 addRelation(r); 1856 } 1857 } 1858 } 1859 } 1860 1861 /** 1862 * search the classpath for a specific class and return the file. In the 1863 * tradition of ptolemy, this will also search for moml files with a class 1864 * definition. this is required for composite actors. 1865 * 1866 * @param className 1867 * the name of the class to search for 1868 * @param workDir 1869 * the directory where temp files can be created 1870 */ 1871 protected File searchClasspath(String className) 1872 throws FileNotFoundException { 1873 1874 // separate the class name from the package path 1875 String actualClassName = className.substring( 1876 className.lastIndexOf(".") + 1, className.length()); 1877 String packagePath = className.substring(0, className.lastIndexOf(".")); 1878 String[] packagePathStruct = packagePath.split("\\."); 1879 1880 // get the classpath so we can search for the class files 1881 String classpath = System.getProperty("java.class.path"); 1882 String sep = System.getProperty("path.separator"); 1883 StringTokenizer st = new StringTokenizer(classpath, sep); 1884 1885 while (st.hasMoreTokens()) { 1886 String path = st.nextToken(); 1887 File pathDir = new File(path); 1888 1889 if (pathDir.isDirectory()) { 1890 // search the directory for the file 1891 1892 if (matchDirectoryPath(pathDir, packagePathStruct, 0)) { 1893 // now we found a candidate...see if the class is in there 1894 File classDir = new File(pathDir.getAbsolutePath() 1895 + File.separator 1896 + packagePath.replace('.', File.separator 1897 .toCharArray()[0])); 1898 File[] classDirFiles = classDir.listFiles(); 1899 for (int i = 0; i < classDirFiles.length; i++) { 1900 1901 String dirFileName = classDirFiles[i].getName(); 1902 1903 if (dirFileName.indexOf(".") != -1) { 1904 String extension = dirFileName.substring( 1905 dirFileName.lastIndexOf("."), dirFileName 1906 .length()); 1907 String prefix = dirFileName.substring(0, 1908 dirFileName.lastIndexOf(".")); 1909 if (actualClassName.equals(prefix) 1910 && (extension.equals(".class") || extension 1911 .equals(".xml"))) { 1912 // search for xml or class files 1913 return classDirFiles[i]; 1914 } 1915 } 1916 } 1917 } 1918 } else if (pathDir.isFile()) { 1919 // search a jar file for the file. if it's not a jar file, 1920 // ignore it 1921 try { 1922 String entryName = className.replace('.', '/') + ".class"; 1923 JarFile jarFile = null; 1924 try { 1925 jarFile = new JarFile(pathDir); 1926 // this looks for a class file 1927 JarEntry entry = jarFile.getJarEntry(entryName); 1928 if (entry != null) { 1929 // get the class file from the jar and return it 1930 return pathDir; 1931 } else { 1932 // look for the xml file instead 1933 entryName = className.replace('.', '/') + ".xml"; 1934 entry = jarFile.getJarEntry(entryName); 1935 if (entry != null) { 1936 return pathDir; 1937 } 1938 } 1939 } finally { 1940 if(jarFile != null) { 1941 jarFile.close(); 1942 } 1943 } 1944 } catch (Exception e) { 1945 // keep going if this isn't a jar file 1946 continue; 1947 } 1948 } 1949 } 1950 throw new FileNotFoundException("Cannot find the specified class " 1951 + "file in the classpath."); 1952 } 1953 1954 /** 1955 * locates a directory based on an array of paths to look for. for instance, 1956 * if you are searching for org/kepler/kar searchForMe would be {org, 1957 * kepler, kar}. dir is where the search starts. Index should start out as 1958 * 0. 1959 */ 1960 private boolean matchDirectoryPath(File dir, String[] searchForMe, int index) { 1961 File[] dirContents = dir.listFiles(); 1962 for (int i = 0; i < dirContents.length; i++) { 1963 if (dirContents[i].getName().equals(searchForMe[index])) { 1964 if (index < searchForMe.length - 1) { 1965 if (index < searchForMe.length) { 1966 return matchDirectoryPath(dirContents[i], searchForMe, 1967 ++index); 1968 } else { 1969 return false; 1970 } 1971 } else { 1972 return true; 1973 } 1974 } 1975 } 1976 return false; 1977 } 1978 1979 /** 1980 * try to locate and parse a moml file as a class 1981 */ 1982 protected ComponentEntity parseMoMLFile(String className) throws Exception { 1983 if (isDebugging) 1984 log.debug("parseMoMLFile(" + className + ")"); 1985 1986 JarFile jarFile = null; 1987 InputStream xmlStream = null; 1988 try { 1989 // first we need to find the file and read it 1990 File classFile = searchClasspath(className); 1991 StringWriter sw = new StringWriter(); 1992 if (classFile.getName().endsWith(".jar")) { 1993 jarFile = new JarFile(classFile); 1994 ZipEntry entry = jarFile.getEntry(className.replace('.', '/') 1995 + ".xml"); 1996 xmlStream = jarFile.getInputStream(entry); 1997 } else { 1998 xmlStream = new FileInputStream(classFile); 1999 } 2000 2001 byte[] b = new byte[1024]; 2002 int numread = xmlStream.read(b, 0, 1024); 2003 while (numread != -1) { 2004 String s = new String(b, 0, numread); 2005 sw.write(s); 2006 numread = xmlStream.read(b, 0, 1024); 2007 } 2008 sw.flush(); 2009 // get the moml document 2010 String xmlDoc = sw.toString(); 2011 sw.close(); 2012 2013 if (isDebugging) 2014 log.debug("**** MoMLParser ****"); 2015 2016 // use the moml parser to parse the doc 2017 MoMLParser parser = new MoMLParser(); 2018 parser.reset(); 2019 2020 // System.out.println("processing " + className); 2021 NamedObj obj = parser.parse(xmlDoc); 2022 return (ComponentEntity) obj; 2023 } finally { 2024 if(jarFile != null) { 2025 jarFile.close(); 2026 } 2027 if(xmlStream != null) { 2028 xmlStream.close(); 2029 } 2030 } 2031 } 2032 2033 /** 2034 * createInstance. creates an instance of a class object. taken from 2035 * ptolemy's MomlParser class. modified for this application. 2036 * 2037 * @param newClass 2038 *@param arguments 2039 *@return TypedAtomicActor 2040 *@exception Exception 2041 */ 2042 public static NamedObj createInstance(Class<?> newClass, Object[] arguments) 2043 throws Exception { 2044 if (isDebugging) 2045 log.debug("createInstance(" + newClass + "," + arguments + ")"); 2046 Constructor<?>[] constructors = newClass.getConstructors(); 2047 for (int i = 0; i < constructors.length; i++) { 2048 Constructor<?> constructor = constructors[i]; 2049 Class<?>[] parameterTypes = constructor.getParameterTypes(); 2050 2051 for (int j = 0; j < parameterTypes.length; j++) { 2052 Class<?> c = parameterTypes[j]; 2053 if (isDebugging) 2054 log.debug(c.getName()); 2055 } 2056 2057 if (parameterTypes.length != arguments.length) { 2058 continue; 2059 } 2060 2061 boolean match = true; 2062 2063 for (int j = 0; j < parameterTypes.length; j++) { 2064 if (!(parameterTypes[j].isInstance(arguments[j]))) { 2065 match = false; 2066 break; 2067 } 2068 } 2069 2070 if (match) { 2071 NamedObj newEntity = (NamedObj) constructor 2072 .newInstance(arguments); 2073 return newEntity; 2074 } 2075 } 2076 2077 // If we get here, then there is no matching constructor. 2078 // Generate a StringBuffer containing what we were looking for. 2079 StringBuffer argumentBuffer = new StringBuffer(); 2080 2081 for (int i = 0; i < arguments.length; i++) { 2082 argumentBuffer.append(arguments[i].getClass() + " = \"" 2083 + arguments[i].toString() + "\""); 2084 2085 if (i < (arguments.length - 1)) { 2086 argumentBuffer.append(", "); 2087 } 2088 } 2089 2090 throw new Exception("Cannot find a suitable constructor (" 2091 + arguments.length + " args) (" + argumentBuffer + ") for '" 2092 + newClass.getName() + "'"); 2093 } 2094 2095 /** 2096 * This method is just a helper debugging method to write out the object 2097 * moml to a file in a specified location on disk, the cache dir. 2098 * 2099 * @param obj 2100 * @param filename 2101 */ 2102 private void writeDebugMomlFor(NamedObj obj, String filename) { 2103 String momlExport = obj.exportMoML(); 2104 2105 DotKeplerManager dkm = DotKeplerManager.getInstance(); 2106 File f = new File(dkm.getCacheDir(), filename); 2107 FileWriter fw; 2108 try { 2109 fw = new FileWriter(f); 2110 fw.write(momlExport, 0, momlExport.length()); 2111 fw.flush(); 2112 fw.close(); 2113 System.out.println("done exporting debug moml: " + f.toString()); 2114 } catch (IOException e) { 2115 e.printStackTrace(); 2116 } 2117 } 2118 2119 /** 2120 * metadata object for a classed property 2121 */ 2122 private static class ClassedProperty implements Serializable { 2123 public String name = ""; 2124 public String value = ""; 2125 public String className = ""; 2126 public Integer iterator = null; 2127 2128 /** 2129 * constructor 2130 */ 2131 public ClassedProperty(String name, String value, String className) { 2132 this.name = name; 2133 this.value = value; 2134 this.className = className; 2135 } 2136 2137 /** 2138 * adds an integer to the end of the name of the property if there is 2139 * more than one of these properties. for instance: semanticType0, 2140 * semanticType1, etc. 2141 * 2142 * @param int i the number to add to the name. 2143 */ 2144 public void addNameIterator(int i) { 2145 iterator = Integer.valueOf(i); 2146 } 2147 2148 /** 2149 * create the xml rep of the ClassedProperty 2150 */ 2151 public String toString() { 2152 if (iterator == null) { 2153 return "<property name=\"" + name + "\" value=\"" + value 2154 + "\" class=\"" + className + "\"/>"; 2155 } else { 2156 int itt = iterator.intValue(); 2157 return "<property name=\"" + name + itt + "\" value=\"" + value 2158 + "\" class=\"" + className + "\"/>"; 2159 } 2160 } 2161 } 2162 2163 /** 2164 * metadata object that represents a port 2165 */ 2166 private static class PortMetadata implements Serializable { 2167 public String name = ""; 2168 public String direction = ""; 2169 public String type = ""; 2170 public boolean multiport = false; 2171 public Vector<NamedObj> attributes = new Vector<NamedObj>(); 2172 2173 /** The class name of the port, e.g., ptolemy.actor.TypedIOPort */ 2174 public String portClassName; 2175 2176 public void addAttribute(NamedObj att) { 2177 attributes.addElement(att); 2178 } 2179 2180 /** 2181 * return the moml xml rep of the port 2182 * 2183 * */ 2184 public String toString() { 2185 StringBuffer sb = new StringBuffer(); 2186 2187 if (name.indexOf("kepler:") != -1) { 2188 sb.append("<property name=\"" + name 2189 + "\" class=\"org.kepler.moml.PortAttribute\">\n"); 2190 } else { 2191 sb.append("<property name=\"kepler:" + name 2192 + "\" class=\"org.kepler.moml.PortAttribute\">\n"); 2193 } 2194 sb.append(" <property name=\"direction\" value=\"" + direction 2195 + "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 2196 sb.append(" <property name=\"dataType\" value=\"" + type 2197 + "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 2198 sb.append(" <property name=\"isMultiport\" value=\"" + multiport 2199 + "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 2200 for (int i = 0; i < attributes.size(); i++) { 2201 // System.out.println("appending port attribute: " + 2202 // ((NamedObj)attributes.elementAt(i)).exportMoML()); 2203 sb.append(" " 2204 + ((NamedObj) attributes.elementAt(i)).exportMoML()); 2205 } 2206 sb.append("</property>\n"); 2207 /* 2208 * sb.append("<port name=\"" + name + 2209 * "\" class=\"ptolemy.actor.IOPort\">\n"); 2210 * sb.append(" <property name=\"direction\" value=\"" + direction + 2211 * "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 2212 * sb.append(" <property name=\"dataType\" value=\"" + type + 2213 * "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 2214 * sb.append(" <property name=\"isMultiport\" value=\"" + multiport 2215 * + "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 2216 * sb.append("</port>\n"); 2217 */ 2218 return sb.toString(); 2219 } 2220 2221 public String toMoMLString() { 2222 StringBuffer sb = new StringBuffer(); 2223 String dispName = name; 2224 if (name.indexOf("kepler:") != -1) { 2225 dispName = name.substring(8, name.length()); 2226 } 2227 2228 String escapedDispName = StringUtilities.escapeForXML(dispName); 2229 2230 sb.append("<port name=\"" + escapedDispName + "\" class=\"" 2231 + portClassName + "\">\n"); 2232 2233 if (direction.equals("input")) { 2234 sb.append(" <property name=\"input\"/>\n"); 2235 } 2236 if (direction.equals("output")) { 2237 sb.append(" <property name=\"output\"/>\n"); 2238 } 2239 if (direction.equals("inputoutput")) { 2240 sb.append(" <property name=\"output\"/>\n"); 2241 sb.append(" <property name=\"input\"/>\n"); 2242 } 2243 // added by Dan Higgins April 2007 2244 sb.append(" <property name=\"dataType\" value=\"" + type 2245 + "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 2246 sb.append(" <property name=\"isMultiport\" value=\"" + multiport 2247 + "\" class=\"ptolemy.kernel.util.StringAttribute\"/>\n"); 2248 for (int i = 0; i < attributes.size(); i++) { 2249 // System.out.println("appending port attribute: " + 2250 // ((NamedObj)attributes.elementAt(i)).exportMoML()); 2251 sb.append(" " 2252 + ((NamedObj) attributes.elementAt(i)).exportMoML()); 2253 } 2254 // end addition by Dan Higgins April 2007 2255 sb.append("</port>\n"); 2256 return sb.toString(); 2257 } 2258 } 2259}