001/* Attribute that contains attributes that identify the containing model. 002 003 Copyright (c) 2004-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 */ 028package ptolemy.vergil.kernel.attributes; 029 030import java.text.DateFormat; 031import java.util.Date; 032 033import ptolemy.data.BooleanToken; 034import ptolemy.data.expr.Parameter; 035import ptolemy.data.expr.SingletonParameter; 036import ptolemy.kernel.Entity; 037import ptolemy.kernel.InstantiableNamedObj; 038import ptolemy.kernel.attributes.URIAttribute; 039import ptolemy.kernel.util.Attribute; 040import ptolemy.kernel.util.IllegalActionException; 041import ptolemy.kernel.util.InternalErrorException; 042import ptolemy.kernel.util.NameDuplicationException; 043import ptolemy.kernel.util.Nameable; 044import ptolemy.kernel.util.Settable; 045import ptolemy.kernel.util.SingletonAttribute; 046import ptolemy.kernel.util.StringAttribute; 047import ptolemy.util.StringUtilities; 048import ptolemy.vergil.icon.BoxedValuesIcon; 049 050/////////////////////////////////////////////////////////////////// 051//// IDAttribute 052 053/** 054 This attribute identifies the containing model, showing its name, base 055 class, last modified date, author, and contributors information. 056 Of these, only the contributors information is editable. 057 For the others, they are inferred from either the model itself or the 058 operations on the model. 059 Unfortunately, the changes will not be shown on the display until the 060 model is saved, closed and re-opened. 061 <p> 062 @author Edward A. Lee 063 @version $Id$ 064 @since Ptolemy II 4.1 065 @Pt.ProposedRating Yellow (eal) 066 @Pt.AcceptedRating Red (cxh) 067 */ 068public class IDAttribute extends SingletonAttribute { 069 /** Construct an attribute with the given name contained by the 070 * specified container. The container argument must not be null, or a 071 * NullPointerException will be thrown. This attribute will use the 072 * workspace of the container for synchronization and version counts. 073 * If the name argument is null, then the name is set to the empty 074 * string. Increment the version of the workspace. 075 * @param container The container. 076 * @param name The name of this attribute. 077 * @exception IllegalActionException If the attribute is not of an 078 * acceptable class for the container, or if the name contains a period. 079 * @exception NameDuplicationException If the name coincides with 080 * an attribute already in the container. 081 */ 082 public IDAttribute(Entity container, String name) 083 throws IllegalActionException, NameDuplicationException { 084 super(container, name); 085 086 // name for the model 087 this.name = new StringAttribute(this, "name"); 088 this.name.setExpression(container.getName()); 089 090 // This should not be persistent, in case the name changes outside 091 // of this parameter. 092 this.name.setPersistent(false); 093 094 // This should not be editable, since the name is set by saveAs. 095 this.name.setVisibility(Settable.NOT_EDITABLE); 096 097 // FIXME: Need to listen for changes to the name. 098 // How to do that? 099 // The current design is also a solution in that the name of this 100 // attribute and model must be consistent with the name of the file. 101 // boolean isClass = false; 102 //if (container instanceof InstantiableNamedObj) { 103 /* isClass = */((InstantiableNamedObj) container).isClassDefinition(); 104 //} 105 106 String className = container.getClassName(); 107 108 baseClass = new StringAttribute(this, "baseClass"); 109 baseClass.setExpression(className); 110 111 // This should not be persistent, because the base class 112 // is set already, generally. 113 baseClass.setPersistent(false); 114 115 // Cannot change the base class. 116 baseClass.setVisibility(Settable.NOT_EDITABLE); 117 118 URIAttribute modelURI = (URIAttribute) container.getAttribute("_uri", 119 URIAttribute.class); 120 121 if (modelURI != null) { 122 StringAttribute definedIn = new StringAttribute(this, "definedIn"); 123 definedIn.setExpression(modelURI.getURI().toString()); 124 definedIn.setPersistent(false); 125 definedIn.setVisibility(Settable.NOT_EDITABLE); 126 } 127 128 // The date when this model is created. 129 // Actually, it is the date when this attribute is created. 130 // We assume that when the model is created, this attribute 131 // is also created. 132 // We may force this to happen.:-) Further more, we may force 133 // that only the top level contains an model ID. 134 created = new StringAttribute(this, "created"); 135 created.setExpression( 136 DateFormat.getDateTimeInstance().format(new Date())); 137 created.setVisibility(Settable.NOT_EDITABLE); 138 created.setPersistent(true); 139 140 // The date when this model is modified. 141 // Everytime the model gets modified, the updateContent method 142 // defined below is called and the lastUpdated attribute gets 143 // updated. 144 lastUpdated = new StringAttribute(this, "lastUpdated"); 145 _updateDate(); 146 lastUpdated.setVisibility(Settable.NOT_EDITABLE); 147 lastUpdated.setPersistent(true); 148 149 // The name of the author who creates the model. 150 // This attribute can not be changed so that the 151 // intellectual property (IP) is preserved. 152 author = new StringAttribute(this, "author"); 153 author.setVisibility(Settable.NOT_EDITABLE); 154 155 String userName = null; 156 157 try { 158 userName = StringUtilities.getProperty("user.name"); 159 } catch (Exception ex) { 160 System.out.println("Warning, in IDAttribute, failed to read " 161 + "'user.name' property (-sandbox or applets always cause " 162 + "this)"); 163 } 164 165 if (userName != null) { 166 author.setExpression(userName); 167 } 168 169 author.setPersistent(true); 170 171 // The names of the contributors who modify the model. 172 contributors = new StringAttribute(this, "contributors"); 173 174 String contributorsNames = ""; 175 contributors.setExpression(contributorsNames); 176 author.setPersistent(true); 177 178 // Hide the name of this ID attribute. 179 SingletonParameter hide = new SingletonParameter(this, "_hideName"); 180 hide.setToken(BooleanToken.TRUE); 181 hide.setVisibility(Settable.EXPERT); 182 183 BoxedValuesIcon icon = new BoxedValuesIcon(this, "_icon"); 184 icon.setPersistent(false); 185 186 // No need to display any parameters when the "_showParameters" 187 // preference asks for such display because presumably all the 188 // parameters are reflected in the visual display already. 189 Parameter hideAllParameters = new Parameter(this, "_hideAllParameters"); 190 hideAllParameters.setVisibility(Settable.EXPERT); 191 hideAllParameters.setExpression("true"); 192 } 193 194 /////////////////////////////////////////////////////////////////// 195 //// attributes //// 196 197 /** The author of the model. */ 198 public StringAttribute author; 199 200 /** The contributors of the model. */ 201 public StringAttribute contributors; 202 203 /** The date that this model was created. */ 204 public StringAttribute created; 205 206 /** The base class of the containing class or entity. */ 207 public StringAttribute baseClass; 208 209 /** A boolean indicating whether the container is a class or an 210 * instance. This is a string that must have value "true" or 211 * "false". 212 */ 213 public StringAttribute isClass; 214 215 /** The date that this model was last updated. */ 216 public StringAttribute lastUpdated; 217 218 /** The name of the containing class or entity. */ 219 public StringAttribute name; 220 221 /////////////////////////////////////////////////////////////////// 222 //// public methods //// 223 224 /** React to a change in an attribute. If the attribute is <i>name</i>, 225 * then change the name of the container to match. 226 * @param attribute The attribute that changed. 227 * @exception IllegalActionException If the change is not acceptable 228 * to this container (not thrown in this base class). 229 */ 230 @Override 231 public void attributeChanged(Attribute attribute) 232 throws IllegalActionException { 233 if (attribute == name) { 234 Nameable container = getContainer(); 235 236 try { 237 container.setName(name.getExpression()); 238 } catch (NameDuplicationException e) { 239 throw new IllegalActionException(this, e, 240 "Cannot change the name of the container to match."); 241 } 242 } else { 243 super.attributeChanged(attribute); 244 } 245 } 246 247 /** Update the modification date of this attribute. 248 */ 249 @Override 250 public void updateContent() throws InternalErrorException { 251 super.updateContent(); 252 _updateDate(); 253 } 254 255 /////////////////////////////////////////////////////////////////// 256 //// private methods //// 257 258 /** Set the current date for the <i>lastUpdated</i> parameter. 259 */ 260 private void _updateDate() { 261 try { 262 lastUpdated.setExpression( 263 DateFormat.getDateTimeInstance().format(new Date())); 264 } catch (IllegalActionException e) { 265 throw new InternalErrorException(e); 266 } 267 } 268}