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