001/* An attribute for instance-specific documentation. 002 003 Copyright (c) 2006-2015 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 */ 028package ptolemy.vergil.basic; 029 030import java.util.Iterator; 031import java.util.LinkedList; 032import java.util.List; 033 034import ptolemy.actor.gui.style.TextStyle; 035import ptolemy.actor.parameters.ParameterPort; 036import ptolemy.actor.parameters.PortParameter; 037import ptolemy.data.BooleanToken; 038import ptolemy.data.expr.SingletonParameter; 039import ptolemy.kernel.Entity; 040import ptolemy.kernel.Port; 041import ptolemy.kernel.util.Attribute; 042import ptolemy.kernel.util.IllegalActionException; 043import ptolemy.kernel.util.InternalErrorException; 044import ptolemy.kernel.util.KernelException; 045import ptolemy.kernel.util.NameDuplicationException; 046import ptolemy.kernel.util.NamedObj; 047import ptolemy.kernel.util.Settable; 048import ptolemy.kernel.util.SingletonAttribute; 049import ptolemy.kernel.util.StringAttribute; 050import ptolemy.kernel.util.Workspace; 051 052/////////////////////////////////////////////////////////////////// 053//// DocAttribute 054 055/** 056 An attribute containing documentation for a Ptolemy II object. 057 058 @author Edward A. Lee 059 @version $Id$ 060 @since Ptolemy II 5.2 061 @Pt.ProposedRating Red (eal) 062 @Pt.AcceptedRating Red (cxh) 063 */ 064public class DocAttribute extends SingletonAttribute { 065 066 /** Construct a documentation attribute with the given name contained 067 * by the specified entity. The container argument must not be null, or a 068 * NullPointerException will be thrown. This attribute will use the 069 * workspace of the container for synchronization and version counts. 070 * If the name argument is null, then the name is set to the empty string. 071 * Increment the version of the workspace. 072 * @param container The container. 073 * @param name The name of this attribute. 074 * @exception IllegalActionException If the attribute is not of an 075 * acceptable class for the container, or if the name contains a period. 076 * @exception NameDuplicationException If the name coincides with 077 * an attribute already in the container. 078 */ 079 public DocAttribute(NamedObj container, String name) 080 throws IllegalActionException, NameDuplicationException { 081 super(container, name); 082 083 description = new StringAttribute(this, "description"); 084 TextStyle style = new TextStyle(description, "_style"); 085 style.height.setExpression("10"); 086 style.width.setExpression("70"); 087 088 author = new StringAttribute(this, "author"); 089 version = new StringAttribute(this, "version"); 090 since = new StringAttribute(this, "since"); 091 092 refreshParametersAndPorts(); 093 094 // Hide the name, if this gets instantiated in Vergil. 095 SingletonParameter hide = new SingletonParameter(this, "_hideName"); 096 hide.setToken(BooleanToken.TRUE); 097 hide.setVisibility(Settable.EXPERT); 098 } 099 100 /** 101 * Construct an empty DocAttribute. 102 */ 103 public DocAttribute() { 104 super(); 105 } 106 107 /** 108 * Construct a DocAttribute in a given workspace. 109 * @param workspace The workspace in which to construct the DocAttribute. 110 */ 111 public DocAttribute(Workspace workspace) { 112 super(workspace); 113 } 114 115 /////////////////////////////////////////////////////////////////// 116 //// parameters //// 117 118 /** The author field. */ 119 public StringAttribute author; 120 121 /** The description. */ 122 public StringAttribute description; 123 124 /** The since field. */ 125 public StringAttribute since; 126 127 /** The version field. */ 128 public StringAttribute version; 129 130 /////////////////////////////////////////////////////////////////// 131 //// public methods //// 132 133 /** Return the documentation for the given parameter, or null if there 134 * none. 135 * @param name The name of the parameter. 136 * @return The documentation for the given parameter, or null if there 137 * is none. 138 */ 139 public String getParameterDoc(String name) { 140 Attribute parameterAttribute = getAttribute(name + " (parameter)"); 141 if (parameterAttribute instanceof Settable) { 142 return ((Settable) parameterAttribute).getExpression(); 143 } 144 // Might be a port-parameter. Try that. 145 parameterAttribute = getAttribute(name + " (port-parameter)"); 146 if (parameterAttribute instanceof Settable) { 147 return ((Settable) parameterAttribute).getExpression(); 148 } 149 // Might be a port-parameter misidentified as a port. Try that. 150 parameterAttribute = getAttribute(name + " (port)"); 151 if (parameterAttribute instanceof Settable) { 152 return ((Settable) parameterAttribute).getExpression(); 153 } 154 return null; 155 } 156 157 /** Return the documentation for the given port, or null if there 158 * none. 159 * @param name The name of the port. 160 * @return The documentation for the given port, or null if there 161 * is none. 162 */ 163 public String getPortDoc(String name) { 164 StringAttribute portAttribute = (StringAttribute) getAttribute( 165 name + " (port)"); 166 if (portAttribute != null) { 167 return portAttribute.getExpression(); 168 } 169 return null; 170 } 171 172 /** For each parameter and port in the container, create a 173 * parameter with the same name appended with either " (port)", 174 * " (port-parameter)", 175 * or " (parameter)". For parameters, only those that are 176 * settable are shown, and only if the visibility is "FULL". 177 * This method also removes any parameters that have no 178 * corresponding parameter or port in the container. 179 * Since this method modifies the model by adding or 180 * removing parameters to this attribute, it should be 181 * called from inside a change request. 182 */ 183 public void refreshParametersAndPorts() { 184 NamedObj container = getContainer(); 185 186 // Remove any parameters that are no longer relevant. 187 // Operate on a copy of the attribute list to avoid 188 // ConcurrentModificationException. 189 List copy = new LinkedList(attributeList()); 190 Iterator parameters = copy.iterator(); 191 while (parameters.hasNext()) { 192 Attribute attribute = (Attribute) parameters.next(); 193 String name = attribute.getName(); 194 int n = name.indexOf(" (parameter)"); 195 if (n >= 0) { 196 // Attribute is a parameter. 197 name = name.substring(0, n); 198 if (container.getAttribute(name) == null) { 199 // Entry is obsolete. Delete it. 200 try { 201 attribute.setContainer(null); 202 } catch (KernelException ex) { 203 // Should not occur. 204 throw new InternalErrorException(ex); 205 } 206 } 207 } else { 208 n = name.indexOf(" (port-parameter)"); 209 if (n >= 0) { 210 // Attribute is a port parameter. 211 name = name.substring(0, n); 212 if (!(container instanceof Entity) 213 || ((Entity) container).getPort(name) == null) { 214 // Entry is obsolete. Delete it. 215 try { 216 attribute.setContainer(null); 217 } catch (KernelException ex) { 218 // Should not occur. 219 throw new InternalErrorException(ex); 220 } 221 } 222 } else { 223 n = name.indexOf(" (port)"); 224 if (n >= 0) { 225 // Attribute is a port parameter. 226 name = name.substring(0, n); 227 if (!(container instanceof Entity) 228 || ((Entity) container).getPort(name) == null) { 229 // Entry is obsolete. Delete it. 230 try { 231 attribute.setContainer(null); 232 } catch (KernelException ex) { 233 // Should not occur. 234 throw new InternalErrorException(ex); 235 } 236 } 237 } 238 } 239 } 240 } 241 242 parameters = container.attributeList(Settable.class).iterator(); 243 while (parameters.hasNext()) { 244 NamedObj attribute = (NamedObj) parameters.next(); 245 if (((Settable) attribute).getVisibility() == Settable.FULL) { 246 String modifier = " (parameter)"; 247 if (attribute instanceof PortParameter) { 248 modifier = " (port-parameter)"; 249 } 250 String name = attribute.getName() + modifier; 251 if (getAttribute(name) == null) { 252 try { 253 // NOTE: Using a StringParameter here is a really poor choice. 254 // It will try to parse anything with a dollar sign. 255 // new StringParameter(this, name); 256 new StringAttribute(this, name); 257 } catch (KernelException e) { 258 throw new InternalErrorException(e); 259 } 260 } 261 } 262 } 263 264 if (container instanceof Entity) { 265 Iterator ports = ((Entity) container).portList().iterator(); 266 while (ports.hasNext()) { 267 Port port = (Port) ports.next(); 268 if (port instanceof ParameterPort) { 269 // Skip this one. 270 continue; 271 } 272 String name = port.getName() + " (port)"; 273 if (getAttribute(name) == null) { 274 try { 275 new StringAttribute(this, name); 276 } catch (KernelException e) { 277 throw new InternalErrorException(e); 278 } 279 } 280 } 281 } 282 } 283}