001/* A documentation attribute for Kepler. 002 003 Copyright (c) 2007-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028 029package ptolemy.vergil.basic; 030 031import java.io.IOException; 032import java.io.Writer; 033import java.util.Enumeration; 034import java.util.Hashtable; 035import java.util.Iterator; 036 037import ptolemy.data.expr.StringParameter; 038import ptolemy.kernel.Entity; 039import ptolemy.kernel.Port; 040import ptolemy.kernel.util.Attribute; 041import ptolemy.kernel.util.Configurable; 042import ptolemy.kernel.util.ConfigurableAttribute; 043import ptolemy.kernel.util.IllegalActionException; 044import ptolemy.kernel.util.InternalErrorException; 045import ptolemy.kernel.util.NameDuplicationException; 046import ptolemy.kernel.util.NamedObj; 047import ptolemy.kernel.util.StringAttribute; 048import ptolemy.kernel.util.Workspace; 049import ptolemy.moml.MoMLChangeRequest; 050import ptolemy.util.StringUtilities; 051 052/** 053 A Documentation attribute for actors. 054 This class is used by Kepler so that the DocViewer can access kepler 055 specific actor metadata based documentation. 056 @author Chad Berkley 057 @version $Id$ 058 @since Ptolemy II 6.1 059 @Pt.ProposedRating Red (cxh) 060 @Pt.AcceptedRating Red (cxh) 061 */ 062public class KeplerDocumentationAttribute extends Attribute 063 implements Configurable { 064 065 /** Construct a Kepler documentation attribute. */ 066 public KeplerDocumentationAttribute() { 067 super(); 068 } 069 070 /** 071 * Construct a Kepler documentation attribute. 072 * 073 *@param container The container. 074 *@param name The name of the Kepler documentation attribute. 075 *@exception IllegalActionException If thrown by the superclass. 076 *@exception NameDuplicationException If thrown by the superclass. 077 */ 078 public KeplerDocumentationAttribute(NamedObj container, String name) 079 throws IllegalActionException, NameDuplicationException { 080 super(container, name); 081 } 082 083 /** 084 * Construct a Kepler documentation attribute. 085 * 086 *@param workspace The workspace in which the object is created. 087 */ 088 public KeplerDocumentationAttribute(Workspace workspace) { 089 super(workspace); 090 } 091 092 /////////////////////////////////////////////////////////////////// 093 //// public methods //// 094 095 /** Add port to the port hashtable. 096 * @param name The name of the port. 097 * @param value A String representing the port. 098 * @exception NameDuplicationException If thrown while creating the port. 099 * @exception Exception If thrown while configuring the port 100 */ 101 public void addPort(String name, String value) 102 throws NameDuplicationException, Exception { 103 104 _portHash.put(name, value); 105 ConfigurableAttribute port = new ConfigurableAttribute(this, 106 "port:" + name); 107 port.configure(null, null, value); 108 } 109 110 /** Add a property to the property hashtable. 111 * @param name The name of the property. 112 * @param value A string representing the property. 113 * @exception NameDuplicationException If thrown while creating the property 114 * @exception Exception If thrown while configuring the attribute 115 * @see #getProperty(String) 116 */ 117 public void addProperty(String name, String value) 118 throws NameDuplicationException, Exception { 119 _propertyHash.put(name, value); 120 ConfigurableAttribute attribute = new ConfigurableAttribute(this, 121 "prop:" + name); 122 attribute.configure(null, null, value); 123 } 124 125 /** Configure this documentation attribute. 126 * @param base Currently ignored. 127 * @param source The source of this configuration. 128 * @param text The configuration text. 129 */ 130 @Override 131 public void configure(java.net.URL base, String source, String text) { 132 this.source = source; 133 this.text = text; 134 } 135 136 /** 137 * Create empty fields for the main attribute as well as any 138 * params or ports that exist in the target. 139 * @param target the namedobj to create the empty attributes for 140 */ 141 public void createEmptyFields(NamedObj target) { 142 try { 143 /*ConfigurableAttribute authorAtt =*/new ConfigurableAttribute(this, 144 "author"); 145 /*ConfigurableAttribute versionAtt =*/new ConfigurableAttribute( 146 this, "version"); 147 /*ConfigurableAttribute descriptionAtt =*/new ConfigurableAttribute( 148 this, "description"); 149 /*ConfigurableAttribute uldAtt =*/new ConfigurableAttribute(this, 150 "userLevelDocumentation"); 151 152 _author = ""; 153 _version = ""; 154 _description = ""; 155 _userLevelDocumentation = ""; 156 157 Iterator attributes = target.attributeList().iterator(); 158 while (attributes.hasNext()) { 159 Attribute attribute = (Attribute) attributes.next(); 160 String attributeName = attribute.getName(); 161 if (!attributeName.substring(0, 1).equals("_") 162 && !attributeName.equals("KeplerDocumentation")) { 163 _propertyHash.put(attribute.getName(), ""); 164 } 165 } 166 167 if (target instanceof Entity) { 168 Iterator ports = ((Entity) target).portList().iterator(); 169 while (ports.hasNext()) { 170 Port p = (Port) ports.next(); 171 _portHash.put(p.getName(), ""); 172 } 173 } 174 175 // Generate a generic change request so the KeplerLSID is updated 176 String caStr = "ptolemy.kernel.util.ConfigurableAttribute"; 177 178 String updateMoml = "<property name=\"author\" " + "class=\"" 179 + caStr + "\" value=\"\"/>"; 180 MoMLChangeRequest updateRequest = new MoMLChangeRequest(this, 181 target, updateMoml); 182 this.requestChange(updateRequest); 183 } catch (Exception ex) { 184 throw new InternalErrorException(this, ex, 185 "Could not add KeplerDocumentation internal attributes."); 186 } 187 } 188 189 /** 190 * Populate the members of KeplerDocumentationAttribute from 191 * another given KeplerDocumentationAttribute. 192 * @param documentationAttribute The DocumentationAttribute from which to copy attributes. 193 */ 194 public void createInstanceFromExisting( 195 KeplerDocumentationAttribute documentationAttribute) { 196 if (documentationAttribute != null 197 && documentationAttribute.attributeList() != null) { 198 Iterator attributes = documentationAttribute.attributeList() 199 .iterator(); 200 while (attributes.hasNext()) { 201 ConfigurableAttribute attribute = (ConfigurableAttribute) attributes 202 .next(); 203 String attributeName = attribute.getName(); 204 if (attributeName.equals("description")) { 205 _description = attribute.getConfigureText(); 206 } else if (attributeName.equals("author")) { 207 _author = attribute.getConfigureText(); 208 } else if (attributeName.equals("version")) { 209 _version = attribute.getConfigureText(); 210 } else if (attributeName.equals("userLevelDocumentation")) { 211 _userLevelDocumentation = attribute.getConfigureText(); 212 } else if (attributeName.indexOf("port:") != -1) { //add to the port hash 213 String portName = attributeName.substring( 214 attributeName.indexOf(":") + 1, 215 attributeName.length()); 216 String portDescription = attribute.getConfigureText(); 217 if (portName != null) { 218 if (portDescription == null) { 219 portDescription = ""; 220 } 221 _portHash.put(portName, portDescription); 222 } 223 224 } else if (attributeName.indexOf("prop:") != -1) { //add to the prop hash 225 String propertyName = attributeName.substring( 226 attributeName.indexOf(":") + 1, 227 attributeName.length()); 228 String propertyDescription = attribute.getConfigureText(); 229 if (propertyName != null) { 230 if (propertyDescription == null) { 231 propertyDescription = ""; 232 } 233 _propertyHash.put(propertyName, propertyDescription); 234 } 235 } 236 } 237 } 238 } 239 240 /** Write a MoML description of this object with the specified 241 * indentation depth and with the specified name substituting 242 * for the name of this object. 243 * @param output The output stream to write to. 244 * @param depth The depth in the hierarchy, to determine indenting. 245 * @param name The name to use in the exported MoML. 246 * @exception IOException If an I/O error occurs. 247 */ 248 @Override 249 public void exportMoML(Writer output, int depth, String name) 250 throws IOException { 251 createInstanceFromExisting(this); 252 StringBuffer results = new StringBuffer("<property name=\"" + name 253 + "\" class=\"" + getClassName() + "\">\n" 254 + "<property name=\"description\" class=\"ptolemy.kernel.util.ConfigurableAttribute\">" 255 + "<configure>" + StringUtilities.escapeForXML(_description) 256 + "</configure>" + "</property>\n" 257 + "<property name=\"author\" class=\"ptolemy.kernel.util.ConfigurableAttribute\">" 258 + "<configure>" + StringUtilities.escapeForXML(_author) 259 + "</configure>" + "</property>\n" 260 + "<property name=\"version\" class=\"ptolemy.kernel.util.ConfigurableAttribute\">" 261 + "<configure>" + StringUtilities.escapeForXML(_version) 262 + "</configure>" + "</property>\n" 263 + "<property name=\"userLevelDocumentation\" class=\"ptolemy.kernel.util.ConfigurableAttribute\">" 264 + "<configure>" 265 + StringUtilities.escapeForXML(_userLevelDocumentation) 266 + "</configure>" + "</property>\n"); 267 268 Enumeration portKeys = _portHash.keys(); 269 while (portKeys.hasMoreElements()) { 270 String key = (String) portKeys.nextElement(); 271 String val = (String) _portHash.get(key); 272 results.append("<property name=\"port:" + key 273 + "\" class=\"ptolemy.kernel.util.ConfigurableAttribute\">" 274 + "<configure>" + StringUtilities.escapeForXML(val) 275 + "</configure>" + "</property>\n"); 276 } 277 278 Enumeration propKeys = _propertyHash.keys(); 279 while (propKeys.hasMoreElements()) { 280 String key = (String) propKeys.nextElement(); 281 String val = (String) _propertyHash.get(key); 282 results.append("<property name=\"prop:" + key 283 + "\" class=\"ptolemy.kernel.util.ConfigurableAttribute\">" 284 + "<configure>" + StringUtilities.escapeForXML(val) 285 + "</configure>" + "</property>\n"); 286 } 287 288 results.append("</property>"); 289 output.write(results.toString()); 290 } 291 292 /** Return the author. 293 * @return the author 294 * @see #setAuthor(String) 295 */ 296 public String getAuthor() { 297 if (_author == null) { 298 return ""; 299 } 300 301 if (!_author.equals("null")) { 302 return _author; 303 } else { 304 return ""; 305 } 306 } 307 308 /** Get the configuration source. 309 * @return The configuration source. 310 */ 311 @Override 312 public String getConfigureSource() { 313 return source; 314 } 315 316 /** Get the configuration text. 317 * @return The configuration text 318 */ 319 @Override 320 public String getConfigureText() { 321 return text; 322 } 323 324 /** Return the description. 325 * @return the description 326 * @see #setDescription(String) 327 */ 328 public String getDescription() { 329 if (_description == null) { 330 return ""; 331 } 332 333 if (!_description.equals("null")) { 334 return _description; 335 } else { 336 return ""; 337 } 338 } 339 340 /** 341 * Return a docAttribute with the available kepler documentation. 342 * Returns null if an error prevents the doc attribute from being 343 * created. 344 * @param target The container for the DocAttribute 345 * @return The DocAttribute. 346 */ 347 public DocAttribute getDocAttribute(NamedObj target) { 348 createInstanceFromExisting(this); 349 try { 350 DocAttribute documentationAttribute = new DocAttribute( 351 target.workspace()); 352 documentationAttribute.setContainer(target); 353 //documentationAttribute.setName("keplerFormattedPTIIDocumentation"); 354 documentationAttribute.author = new StringAttribute( 355 documentationAttribute, "author"); 356 documentationAttribute.author.setExpression(_author); 357 documentationAttribute.version = new StringAttribute( 358 documentationAttribute, "version"); 359 documentationAttribute.version.setExpression(_version); 360 documentationAttribute.since = new StringAttribute( 361 documentationAttribute, "since"); 362 documentationAttribute.since.setExpression(""); 363 documentationAttribute.description = new StringAttribute( 364 documentationAttribute, "description"); 365 documentationAttribute.description 366 .setExpression(_userLevelDocumentation); 367 368 //add ports and params 369 Enumeration ports = _portHash.keys(); 370 while (ports.hasMoreElements()) { 371 String name = (String) ports.nextElement(); 372 String description = (String) _portHash.get(name); 373 StringAttribute attribute = new StringAttribute( 374 documentationAttribute, name + " (port)"); 375 attribute.setExpression(description); 376 } 377 378 Enumeration propItt = _propertyHash.keys(); 379 while (propItt.hasMoreElements()) { 380 String name = (String) propItt.nextElement(); 381 String description = (String) _propertyHash.get(name); 382 StringParameter parameter = new StringParameter( 383 documentationAttribute, name + " (parameter)"); 384 parameter.setExpression(description); 385 } 386 387 return documentationAttribute; 388 } catch (Exception ex) { 389 throw new InternalErrorException(this, ex, 390 "Error creating docAttribute."); 391 } 392 393 } 394 395 /** Return the document class. 396 * @return the document class or the empty string. 397 * @see #setDocClass(String) 398 */ 399 public String getDocClass() { 400 if (!_docClass.equals("null")) { 401 return _docClass; 402 } else { 403 return ""; 404 } 405 } 406 407 /** Return the document name. 408 * @return the document name 409 * @see #setDocName(String) 410 */ 411 public String getDocName() { 412 if (!_docName.equals("null")) { 413 return _docName; 414 } else { 415 return ""; 416 } 417 } 418 419 /** Return the port documentation. 420 * @param name The name of the port. 421 * @return the port documentation. 422 */ 423 public String getPort(String name) { 424 return (String) _portHash.get(name); 425 } 426 427 /** Return the port hash. 428 * @return the port hash 429 * @see #setPortHash(Hashtable) 430 */ 431 public Hashtable getPortHash() { 432 return _portHash; 433 } 434 435 /** Return the property documentation. 436 * @param name The name of the property. 437 * @return the property docs 438 * @see #addProperty(String, String) 439 */ 440 public String getProperty(String name) { 441 return (String) _propertyHash.get(name); 442 } 443 444 /** Return the property hash. 445 * @return the property hash 446 * @see #setPropertyHash(Hashtable) 447 */ 448 public Hashtable getPropertyHash() { 449 return _propertyHash; 450 } 451 452 /** Return the user level documentation. 453 * @return the user level documentation 454 * @see #setUserLevelDocumentation(String) 455 */ 456 public String getUserLevelDocumentation() { 457 if (_userLevelDocumentation == null) { 458 return ""; 459 } 460 461 if (!_userLevelDocumentation.equals("null")) { 462 return _userLevelDocumentation; 463 } else { 464 return ""; 465 } 466 } 467 468 /** Return the version. 469 * @return the version 470 * @see #setVersion(String) 471 */ 472 public String getVersion() { 473 if (_version == null) { 474 return ""; 475 } 476 477 if (!_version.equals("null")) { 478 return _version; 479 } else { 480 return ""; 481 } 482 } 483 484 /** Remove a port from the port hashtable. 485 * @param name The name of the port. 486 * @return The value of the port. 487 * @exception IllegalActionException If an error occurs removing the 488 * ConfigurableAttribute. 489 * @exception NameDuplicationException If an error occurs removing the 490 * ConfigurableAttribute. 491 * @see #addPort(String, String) 492 */ 493 public String removePort(String name) 494 throws IllegalActionException, NameDuplicationException { 495 String retval = (String) _portHash.remove(name); 496 if (retval != null) { 497 Attribute attribute = getAttribute("port:" + name); 498 attribute.setContainer(null); 499 } 500 return retval; 501 } 502 503 /** Remove a property from the property hashtable. 504 * @param name The name of the property. 505 * @return The value of the property. 506 * @exception IllegalActionException If an error occurs removing the 507 * ConfigurableAttribute. 508 * @exception NameDuplicationException If an error occurs removing the 509 * ConfigurableAttribute. 510 * @see #addProperty(String, String) 511 */ 512 public String removeProperty(String name) 513 throws IllegalActionException, NameDuplicationException { 514 String retval = (String) _propertyHash.remove(name); 515 if (retval != null) { 516 Attribute attribute = getAttribute("prop:" + name); 517 attribute.setContainer(null); 518 } 519 return retval; 520 } 521 522 /** Set the author. 523 * @param author The author. 524 * @see #getAuthor() 525 */ 526 public void setAuthor(String author) { 527 _author = author; 528 } 529 530 /** Set the description. 531 * @param description The description. 532 * @see #getDescription() 533 */ 534 public void setDescription(String description) { 535 _description = description; 536 } 537 538 /** Set the name of this docClass. 539 * @param className The name of this docClass. 540 * @see #getDocClass() 541 */ 542 public void setDocClass(String className) { 543 _docClass = className; 544 } 545 546 /** Set the name of this document. 547 * @param name The name of this document. 548 * @see #getDocName() 549 */ 550 public void setDocName(String name) { 551 _docName = name; 552 } 553 554 /** Set the port hash. 555 * @param portHash The port hash. 556 * @see #getPortHash() 557 */ 558 public void setPortHash(Hashtable portHash) { 559 _portHash = portHash; 560 } 561 562 /** Set the property hashtable. 563 * @param propertyHash The property hashtable. 564 * @see #getPropertyHash() 565 * 566 * FIXME: need to remove all existing ConfigurableAttributes 567 * for properties and add new ones for new hash table. 568 */ 569 public void setPropertyHash(Hashtable propertyHash) { 570 _propertyHash = propertyHash; 571 } 572 573 /** Set the user level documentation. 574 * @param userLevelDocumentation The user level documentation. 575 * @see #getUserLevelDocumentation() 576 */ 577 public void setUserLevelDocumentation(String userLevelDocumentation) { 578 _userLevelDocumentation = userLevelDocumentation; 579 } 580 581 /** Set the version. 582 * @param version The version. 583 * @see #getVersion() 584 */ 585 public void setVersion(String version) { 586 _version = version; 587 } 588 589 /** 590 * Exports this documentation attribute as docML. 591 * @return The docML 592 */ 593 public String toDocML() { 594 createInstanceFromExisting(this); 595 StringBuffer results = new StringBuffer( 596 "<?xml version=\"1.0\" standalone=\"yes\"?>\n" 597 + "<!DOCTYPE doc PUBLIC \"-//UC Berkeley//DTD DocML 1//EN\"" 598 + "\"http://ptolemy.eecs.berkeley.edu/xml/dtd/DocML_1.dtd\">\n" 599 + "<doc name=\"" + _docName + "\" class=\"" + _docClass 600 + "\">\n" + "<description>\n" + _userLevelDocumentation 601 + "\n</description>\n" + "<author>" + _author 602 + "</author>\n"); 603 604 Enumeration ports = _portHash.keys(); 605 while (ports.hasMoreElements()) { 606 String name = (String) ports.nextElement(); 607 String desc = (String) _portHash.get(name); 608 results.append("<port name=\"" + name + "\">" + desc + "</port>\n"); 609 } 610 611 Enumeration propItt = _propertyHash.keys(); 612 while (propItt.hasMoreElements()) { 613 String name = (String) propItt.nextElement(); 614 String desc = (String) _propertyHash.get(name); 615 results.append("<property name=\"" + name + "\">" + desc 616 + "</property>\n"); 617 } 618 619 results.append("</doc>\n"); 620 return results.toString(); 621 } 622 623 /** 624 * Method for configurable. 625 * In this class, we do nothing. 626 */ 627 @Override 628 public void updateContent() throws InternalErrorException { 629 //do nothing 630 } 631 632 /** Update the documentation fields of this object from another 633 * KeplerDocumentationAttribute. A documentation field in 634 * this object is updated if it is empty and the corresponding field 635 * in the given object is not empty. However, if a field does not 636 * exist in this object, but is present in the given object, the 637 * field is *not* created in this object. 638 * 639 * @param oldDoc 640 * The KeplerDocumentationAttribute from which to copy 641 * attributes. 642 * @param printWhenReplacing 643 * If true, print when the values are overwritten. 644 * 645 * @exception Exception 646 * if there is an error updating the fields. 647 */ 648 public void updateFromExisting(KeplerDocumentationAttribute oldDoc, 649 boolean printWhenReplacing) throws Exception { 650 651 if (oldDoc != null && oldDoc.attributeList() != null) { 652 Iterator<?> attributes = oldDoc.attributeList().iterator(); 653 while (attributes.hasNext()) { 654 ConfigurableAttribute attribute = (ConfigurableAttribute) attributes 655 .next(); 656 String attributeName = attribute.getName(); 657 boolean replaced = false; 658 if (attributeName.equals("description")) { 659 String oldDescription = attribute.getConfigureText(); 660 if (_isEmpty(_description) && !_isEmpty(oldDescription)) { 661 _description = oldDescription; 662 replaced = true; 663 } 664 } else if (attributeName.equals("author")) { 665 String oldAuthor = attribute.getConfigureText(); 666 if (_isEmpty(_author) && !_isEmpty(oldAuthor)) { 667 _author = oldAuthor; 668 replaced = true; 669 } 670 } else if (attributeName.equals("version")) { 671 String oldVersion = attribute.getConfigureText(); 672 if (_isEmpty(_version) && !_isEmpty(oldVersion)) { 673 _version = oldVersion; 674 replaced = true; 675 } 676 } else if (attributeName.equals("userLevelDocumentation")) { 677 String oldUserLevelDocumentation = attribute 678 .getConfigureText(); 679 if (_isEmpty(_userLevelDocumentation) 680 && !_isEmpty(oldUserLevelDocumentation)) { 681 _userLevelDocumentation = oldUserLevelDocumentation; 682 replaced = true; 683 } 684 } else if (attributeName.indexOf("port:") != -1) { // add to the 685 // port hash 686 String portName = attributeName.substring( 687 attributeName.indexOf(":") + 1, 688 attributeName.length()); 689 String portDescription = attribute.getConfigureText(); 690 if (portName != null) { 691 if (portDescription == null) { 692 portDescription = ""; 693 } 694 String newPortDoc = (String) _portHash.get(portName); 695 if (newPortDoc != null && _isEmpty(newPortDoc) 696 && !_isEmpty(portDescription)) { 697 // Attribute clonedAttribute = (Attribute) 698 // attribute.clone(); 699 _portHash.put(portName, portDescription); 700 replaced = true; 701 } 702 } 703 704 } else if (attributeName.indexOf("prop:") != -1) { // add to the 705 // prop hash 706 String propertyName = attributeName.substring( 707 attributeName.indexOf(":") + 1, 708 attributeName.length()); 709 String propertyDescription = attribute.getConfigureText(); 710 if (propertyName != null) { 711 if (propertyDescription == null) { 712 propertyDescription = ""; 713 } 714 String newPropDoc = (String) _propertyHash 715 .get(propertyName); 716 if (newPropDoc != null && _isEmpty(newPropDoc) 717 && !_isEmpty(propertyDescription)) { 718 _propertyHash.put(propertyName, 719 propertyDescription); 720 replaced = true; 721 } 722 } 723 } 724 725 if (replaced) { 726 727 if (printWhenReplacing) { 728 System.out.println( 729 "WARNING: using old docs for " + attributeName 730 + " since the new ones appear empty."); 731 } 732 // Update the attribute too, creating one if it does not exist. 733 ConfigurableAttribute myAttribute = (ConfigurableAttribute) getAttribute( 734 attributeName); 735 if (myAttribute == null) { 736 myAttribute = new ConfigurableAttribute(this, 737 attributeName); 738 } 739 myAttribute.configure(attribute.getBase(), 740 attribute.getConfigureSource(), 741 attribute.getConfigureText()); 742 } 743 } 744 } 745 } 746 747 /////////////////////////////////////////////////////////////////// 748 //// private methods //// 749 750 /** A utility method to determine if a field's string is empty. 751 * @return Returns true if the field is null or the content appears to be 752 * empty. 753 */ 754 private static boolean _isEmpty(String string) { 755 756 if (string == null) { 757 return true; 758 } 759 String trimmed = string.trim(); 760 if (trimmed.isEmpty() || trimmed.equalsIgnoreCase("null")) { 761 return true; 762 } 763 764 return false; 765 } 766 767 /////////////////////////////////////////////////////////////////// 768 //// private fields //// 769 770 //members for Configurable 771 private String source; 772 773 private String text; 774 775 //members for DocumenationAttribute 776 private String _docName; 777 778 private String _docClass; 779 780 private String _description; 781 782 private String _author; 783 784 private String _version; 785 786 private String _userLevelDocumentation; 787 788 private Hashtable _portHash = new Hashtable(); 789 790 private Hashtable _propertyHash = new Hashtable(); 791}