001/* A port that updates a parameter of the container. 002 003 Copyright (c) 2001-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 */ 027package ptolemy.actor.parameters; 028 029import ptolemy.actor.TypedIOPort; 030import ptolemy.data.IntToken; 031import ptolemy.data.expr.Parameter; 032import ptolemy.kernel.ComponentEntity; 033import ptolemy.kernel.Entity; 034import ptolemy.kernel.util.Attribute; 035import ptolemy.kernel.util.IllegalActionException; 036import ptolemy.kernel.util.KernelException; 037import ptolemy.kernel.util.NameDuplicationException; 038import ptolemy.kernel.util.NamedObj; 039import ptolemy.kernel.util.Settable; 040import ptolemy.kernel.util.Workspace; 041 042/////////////////////////////////////////////////////////////////// 043//// ParameterPort 044 045/** 046 A specialized port for use with PortParameter. This port is created 047 by an instance of PortParameter and provides values to a parameter. 048 Data should not be read directly from this port. Instead, the update 049 method of the corresponding PortParameter should be invoked. This 050 port is only useful if the container is opaque, however, this is not 051 checked. 052 053 @see PortParameter 054 @author Edward A. Lee 055 @version $Id$ 056 @since Ptolemy II 3.0 057 @Pt.ProposedRating Green (eal) 058 @Pt.AcceptedRating Yellow (neuendor) 059 */ 060public class ParameterPort extends TypedIOPort { 061 /** Construct a new input port in the specified container with the 062 * specified name. The specified container 063 * must implement the Actor interface, or an exception will be thrown. 064 * @param container The container. 065 * @param name The name of the port. 066 * @exception IllegalActionException If the port is not of an acceptable 067 * class for the container, or if the container does not implement the 068 * Actor interface. 069 * @exception NameDuplicationException If the name coincides with 070 * a port already in the container. 071 */ 072 public ParameterPort(ComponentEntity container, String name) 073 throws IllegalActionException, NameDuplicationException { 074 this(container, name, null); 075 } 076 077 /** Construct a new input port in the specified container with the 078 * specified name. The specified container 079 * must implement the Actor interface, or an exception will be thrown. 080 * @param container The container. 081 * @param name The name of the port. 082 * @param parameter The associate PortParameter, or null to create one. 083 * @exception IllegalActionException If the port is not of an acceptable 084 * class for the container, or if the container does not implement the 085 * Actor interface. 086 * @exception NameDuplicationException If the name coincides with 087 * a port already in the container. 088 */ 089 protected ParameterPort(ComponentEntity container, String name, 090 PortParameter parameter) 091 throws IllegalActionException, NameDuplicationException { 092 super(container, name); 093 setInput(true); 094 setMultiport(false); 095 _parameter = parameter; 096 097 if (_parameter == null) { 098 // This is apparently being created directly, e.g. in MoML, rather than 099 // the preferred way of creating a PortParameter. Create or capture 100 // the corresponding PortParameter. 101 Attribute existingParameter = container.getAttribute(name); 102 if (existingParameter instanceof PortParameter) { 103 _parameter = (PortParameter) existingParameter; 104 _parameter._port = this; 105 } else { 106 _parameter = new PortParameter(container, name, this); 107 } 108 } 109 _setTypeConstraints(); 110 111 // Declare to the SDF scheduler that this port consumes one 112 // token, despite not being connected on the inside. 113 Parameter tokenConsumptionRate = new Parameter(this, 114 "tokenConsumptionRate", new IntToken(1)); 115 tokenConsumptionRate.setVisibility(Settable.NOT_EDITABLE); 116 tokenConsumptionRate.setPersistent(false); 117 118 Parameter notDraggable = new Parameter(this, "_notDraggable"); 119 notDraggable.setPersistent(false); 120 } 121 122 /////////////////////////////////////////////////////////////////// 123 //// public methods //// 124 125 /** Clone the port. This overrides the base class to remove 126 * the current association with a parameter. It is assumed that the 127 * parameter will also be cloned, and when the containers are set of 128 * this port and that parameter, whichever one is set second 129 * will result in re-establishment of the association. 130 * @param workspace The workspace in which to place the cloned port. 131 * @exception CloneNotSupportedException Not thrown in this base class. 132 * @see java.lang.Object#clone() 133 * @return The cloned port. 134 */ 135 @Override 136 public Object clone(Workspace workspace) throws CloneNotSupportedException { 137 ParameterPort newObject = (ParameterPort) super.clone(workspace); 138 139 // Cannot establish an association with the cloned parameter until 140 // that parameter is cloned and the container of both is set. 141 newObject._parameter = null; 142 return newObject; 143 } 144 145 /** Get the associated parameter. 146 * @return The associated parameter. 147 */ 148 public PortParameter getParameter() { 149 if (_parameter == null) { 150 // Attempt to find the parameter. 151 NamedObj container = getContainer(); 152 if (container != null) { 153 Attribute candidate = container.getAttribute(getName()); 154 if (candidate instanceof PortParameter) { 155 _parameter = (PortParameter) candidate; 156 _setTypeConstraints(); 157 } 158 } 159 } 160 return _parameter; 161 } 162 163 /** Set the container of this port. If the container is different 164 * from what it was before and there is an associated parameter, then 165 * also change the container of the parameter. 166 * @see PortParameter 167 * @param entity The new container. 168 * @exception IllegalActionException If the superclass throws it. 169 * @exception NameDuplicationException If the superclass throws it. 170 */ 171 @Override 172 public void setContainer(Entity entity) 173 throws IllegalActionException, NameDuplicationException { 174 if (_settingContainer) { 175 // Recursive call through the parameter. 176 return; 177 } 178 Entity previousContainer = (Entity) getContainer(); 179 if (previousContainer == entity) { 180 // No change. 181 return; 182 } 183 super.setContainer(entity); 184 185 // If there is an associated parameter, and the container has changed, 186 // change that container too. 187 if (_parameter != null) { 188 try { 189 _settingContainer = true; 190 _parameter.setContainer(entity); 191 } catch (KernelException ex) { 192 super.setContainer(previousContainer); 193 throw ex; 194 } finally { 195 _settingContainer = false; 196 } 197 } 198 if (previousContainer == null) { 199 // This may be part of cloning operation, in which case we need to 200 // establish type constraints that are present in the original. 201 // Since ports are normally cloned after parameters, the container should 202 // have the relevant parameter by now. 203 if (getParameter() != null) { 204 _setTypeConstraints(); 205 } 206 } 207 } 208 209 /** Set the display name, and propagate the name change to the 210 * associated parameter. 211 * Increment the version of the workspace. 212 * This method is write-synchronized on the workspace. 213 * @param name The new display name.. 214 */ 215 @Override 216 public void setDisplayName(String name) { 217 if (_settingName) { 218 return; 219 } 220 super.setDisplayName(name); 221 PortParameter parameter = getParameter(); 222 if (parameter != null) { 223 try { 224 _settingName = true; 225 parameter.setDisplayName(name); 226 } finally { 227 _settingName = false; 228 } 229 } 230 } 231 232 /** Set the name, and propagate the name change to the 233 * associated parameter. If a null argument is given, then the 234 * name is set to an empty string. 235 * Increment the version of the workspace. 236 * This method is write-synchronized on the workspace. 237 * @param name The new name. 238 * @exception IllegalActionException If the name contains a period. 239 * @exception NameDuplicationException If the container already 240 * contains an attribute with the proposed name. 241 */ 242 @Override 243 public void setName(String name) 244 throws IllegalActionException, NameDuplicationException { 245 if (_settingName) { 246 return; 247 } 248 super.setName(name); 249 PortParameter parameter = getParameter(); 250 if (parameter != null) { 251 String oldName = getName(); 252 try { 253 _settingName = true; 254 parameter.setName(name); 255 } catch (KernelException ex) { 256 super.setName(oldName); 257 throw ex; 258 } finally { 259 _settingName = false; 260 } 261 } 262 } 263 264 /////////////////////////////////////////////////////////////////// 265 //// protected methods //// 266 267 /** Set the type constraints between the protected member _parameter 268 * and this port. This is a protected method so that subclasses 269 * can define different type constraints. It is assured that when 270 * this is called, _parameter is non-null. However, use caution, 271 * since this method may be called during construction of this 272 * port, and hence the port may not be fully constructed. 273 */ 274 protected void _setTypeConstraints() { 275 PortParameter parameter = getParameter(); 276 if (parameter != null) { 277 parameter.setTypeSameAs(this); 278 } 279 } 280 281 /////////////////////////////////////////////////////////////////// 282 //// protected members //// 283 284 /** The associated parameter. */ 285 protected PortParameter _parameter; 286 287 /////////////////////////////////////////////////////////////////// 288 //// private members //// 289 290 /** Indicator that we are in the midst of setting the container. */ 291 private boolean _settingContainer = false; 292 293 /** Indicator that we are in the midst of setting the name. */ 294 private boolean _settingName = false; 295}