001/* An abstract base class for initializable attributes. 002 003 Copyright (c) 1997-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 */ 028 029package ptolemy.data.expr; 030 031import java.util.LinkedHashSet; 032import java.util.Set; 033 034import ptolemy.actor.CompositeActor; 035import ptolemy.actor.Initializable; 036import ptolemy.kernel.util.HierarchyListener; 037import ptolemy.kernel.util.IllegalActionException; 038import ptolemy.kernel.util.NameDuplicationException; 039import ptolemy.kernel.util.NamedObj; 040import ptolemy.kernel.util.Workspace; 041 042/////////////////////////////////////////////////////////////////// 043//// AbstractInitializableParameter 044 045/** An abstract base class for parameters that are preinitialized, 046 * initialized, and wrapped up during execution of a model. 047 * This takes care of the rather complex adjustments that must 048 * be made when the hierarchy changes and also provides default 049 * methods. 050 * 051 * @author Edward A. Lee 052 * @version $Id$ 053 * @since Ptolemy II 10.0 054 * @Pt.ProposedRating Yellow (eal ) 055 * @Pt.AcceptedRating Red (eal) 056 */ 057public abstract class AbstractInitializableParameter extends Parameter 058 implements HierarchyListener, Initializable { 059 060 /** Construct an instance of the attribute. 061 * @param container The container. 062 * @param name The name. 063 * @exception IllegalActionException If the superclass throws it. 064 * @exception NameDuplicationException If the superclass throws it. 065 */ 066 public AbstractInitializableParameter(NamedObj container, String name) 067 throws IllegalActionException, NameDuplicationException { 068 super(container, name); 069 } 070 071 /////////////////////////////////////////////////////////////////// 072 //// public methods //// 073 074 /** Add the specified object to the set of objects whose 075 * preinitialize(), initialize(), and wrapup() 076 * methods should be invoked upon invocation of the corresponding 077 * methods of this object. 078 * @param initializable The object whose methods should be invoked. 079 * @see #removeInitializable(Initializable) 080 */ 081 @Override 082 public void addInitializable(Initializable initializable) { 083 if (_initializables == null) { 084 _initializables = new LinkedHashSet<Initializable>(); 085 } 086 _initializables.add(initializable); 087 } 088 089 /** Clone the attribute. This clears the list of initializable objects. 090 * @param workspace The workspace in which to place the cloned attribute. 091 * @exception CloneNotSupportedException Not thrown in this base class. 092 * @see java.lang.Object#clone() 093 * @return The cloned variable. 094 */ 095 @Override 096 public Object clone(Workspace workspace) throws CloneNotSupportedException { 097 AbstractInitializableParameter newObject = (AbstractInitializableParameter) super.clone( 098 workspace); 099 newObject._initializables = null; 100 return newObject; 101 } 102 103 /** Notify this object that the containment hierarchy above it has 104 * changed. This method does nothing because instead we use 105 * {@link #preinitialize()} to handle re-establishing the connections. 106 * @exception IllegalActionException If the change is not 107 * acceptable. 108 */ 109 @Override 110 public void hierarchyChanged() throws IllegalActionException { 111 // Make sure we are registered as to be initialized 112 // with the container. 113 Initializable container = _getInitializableContainer(); 114 if (container != null) { 115 container.addInitializable(this); 116 } 117 } 118 119 /** Notify this object that the containment hierarchy above it will be 120 * changed, which results in 121 * @exception IllegalActionException If unlinking to a published port fails. 122 */ 123 @Override 124 public void hierarchyWillChange() throws IllegalActionException { 125 // Unregister to be initialized with the initializable container. 126 // We will be re-registered when hierarchyChanged() is called. 127 Initializable container = _getInitializableContainer(); 128 if (container != null) { 129 container.removeInitializable(this); 130 } 131 } 132 133 /** Invoke initialize() on registered initializables. 134 * @exception IllegalActionException If thrown by a subclass. 135 */ 136 @Override 137 public void initialize() throws IllegalActionException { 138 // Invoke initializable methods. 139 if (_initializables != null) { 140 for (Initializable initializable : _initializables) { 141 initializable.initialize(); 142 } 143 } 144 } 145 146 /** Invoke preinitialize() on registered initializables. 147 * @exception IllegalActionException If thrown by a subclass. 148 */ 149 @Override 150 public void preinitialize() throws IllegalActionException { 151 // Invoke initializable methods. 152 if (_initializables != null) { 153 for (Initializable initializable : _initializables) { 154 initializable.preinitialize(); 155 } 156 } 157 } 158 159 /** Remove the specified object from the list of objects whose 160 * preinitialize(), initialize(), and wrapup() 161 * methods should be invoked upon invocation of the corresponding 162 * methods of this object. If the specified object is not 163 * on the list, do nothing. 164 * @param initializable The object whose methods should no longer be invoked. 165 * @see #addInitializable(Initializable) 166 */ 167 @Override 168 public void removeInitializable(Initializable initializable) { 169 if (_initializables != null) { 170 _initializables.remove(initializable); 171 if (_initializables.size() == 0) { 172 _initializables = null; 173 } 174 } 175 } 176 177 /** Override the base class to register as an 178 * {@link Initializable} 179 * so that preinitialize() is invoked, and as a 180 * {@link HierarchyListener}, so that we are notified of 181 * changes in the hiearchy above. 182 * @param container The proposed container. 183 * @exception IllegalActionException If the action would result in a 184 * recursive containment structure, or if 185 * this entity and container are not in the same workspace. 186 * @exception NameDuplicationException If the container already has 187 * an entity with the name of this entity. 188 */ 189 @Override 190 public void setContainer(NamedObj container) 191 throws IllegalActionException, NameDuplicationException { 192 Initializable previousInitializableContainer = _getInitializableContainer(); 193 NamedObj previousContainer = getContainer(); 194 super.setContainer(container); 195 Initializable newInitializableContainer = _getInitializableContainer(); 196 if (previousInitializableContainer != newInitializableContainer) { 197 if (previousInitializableContainer != null) { 198 previousInitializableContainer.removeInitializable(this); 199 } 200 if (newInitializableContainer != null) { 201 newInitializableContainer.addInitializable(this); 202 } 203 } 204 if (previousContainer != container) { 205 if (previousContainer != null) { 206 previousContainer.removeHierarchyListener(this); 207 } 208 if (container != null) { 209 container.addHierarchyListener(this); 210 } 211 } 212 } 213 214 /** Invoke wrapup() on registered initializables. 215 * @exception IllegalActionException If thrown by a subclass. 216 */ 217 @Override 218 public void wrapup() throws IllegalActionException { 219 // Invoke initializable methods. 220 if (_initializables != null) { 221 for (Initializable initializable : _initializables) { 222 initializable.wrapup(); 223 } 224 } 225 } 226 227 /////////////////////////////////////////////////////////////////// 228 //// protected methods //// 229 230 /** Return the first Initializable encountered above this 231 * in the hierarchy that will be initialized (i.e., it is either 232 * an atomic actor or an opaque composite actor). 233 * @return The first Initializable above this in the hierarchy, 234 * or null if there is none. 235 */ 236 protected Initializable _getInitializableContainer() { 237 NamedObj container = getContainer(); 238 while (container != null) { 239 if (container instanceof Initializable) { 240 if (container instanceof CompositeActor) { 241 if (((CompositeActor) container).isOpaque()) { 242 return (Initializable) container; 243 } 244 } else { 245 return (Initializable) container; 246 } 247 } 248 container = container.getContainer(); 249 } 250 return null; 251 } 252 253 /////////////////////////////////////////////////////////////////// 254 //// private variables //// 255 256 /** List of objects whose (pre)initialize() and wrapup() methods should be 257 * slaved to these. 258 */ 259 private transient Set<Initializable> _initializables; 260}