001/* A configurable attribute that replaces any previous instance. 002 003 Copyright (c) 1998-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.kernel.util; 029 030/////////////////////////////////////////////////////////////////// 031//// SingletonConfigurableAttribute 032 033/** 034 This class is a configurable attribute that replaces any previously 035 existing attribute in the container that has the same name. 036 An important use of this class is to describe icons for visual rendition. 037 The icons are described in an XML schema called SVG, given in the 038 body of a configure XML element. The icon description is named 039 "_iconDescription", and placing such a description into any container 040 replaces any previous description in the container. 041 042 @author Steve Neuendorffer and Edward A. Lee 043 @version $Id$ 044 @since Ptolemy II 1.0 045 @Pt.ProposedRating Green (eal) 046 @Pt.AcceptedRating Green (janneck) 047 */ 048public class SingletonConfigurableAttribute extends ConfigurableAttribute 049 implements Singleton { 050 /** Construct a new attribute with no 051 * container and an empty string as its name. Add the attribute to the 052 * workspace directory. 053 * Increment the version number of the workspace. 054 */ 055 public SingletonConfigurableAttribute() { 056 super(); 057 } 058 059 /** Construct a new attribute with 060 * no container and an empty string as a name. You can then change 061 * the name with setName(). If the workspace argument is null, then 062 * use the default workspace. 063 * Add the attribute to the workspace directory. 064 * Increment the version number of the workspace. 065 * @param workspace The workspace that will list the attribute. 066 */ 067 public SingletonConfigurableAttribute(Workspace workspace) { 068 super(workspace); 069 } 070 071 /** Construct an attribute with the given container and name. 072 * If an attribute already exists with the same name as the one 073 * specified here, that is an instance of class 074 * SingletonConfigurableAttribute (or a derived class), then that 075 * attribute is removed before this one is inserted in the container. 076 * @param container The container. 077 * @param name The name of this attribute. 078 * @exception IllegalActionException If the attribute cannot be contained 079 * by the proposed container. 080 * @exception NameDuplicationException If the container already has an 081 * attribute with this name, and the class of that container is not 082 * SingletonConfigurableAttribute. 083 */ 084 public SingletonConfigurableAttribute(NamedObj container, String name) 085 throws NameDuplicationException, IllegalActionException { 086 super(container, name); 087 } 088 089 /////////////////////////////////////////////////////////////////// 090 //// public methods //// 091 092 /** Remove any previous attribute in the container that has the same 093 * name as this attribute, and then call the base class method to set 094 * the container. If the container is not in the same workspace as 095 * this attribute, throw an exception. 096 * If this attribute is already contained by the NamedObj, do nothing. 097 * If the attribute already has a container, remove 098 * this attribute from its attribute list first. Otherwise, remove 099 * it from the directory of the workspace, if it is there. 100 * If the argument is null, then remove this attribute from its 101 * container. It is not added to the workspace directory, so this 102 * could result in this object being garbage collected. 103 * <p> 104 * Note that since an Attribute is a NamedObj, it can itself have 105 * attributes. However, recursive containment is not allowed, where 106 * an attribute is an attribute of itself, or indirectly of any attribute 107 * it contains. 108 * <p> 109 * This method is write-synchronized on the 110 * workspace and increments its version number. 111 * @param container The container to attach this attribute to. 112 * @exception IllegalActionException If this attribute is not of the 113 * expected class for the container, or it has no name, 114 * or the attribute and container are not in the same workspace, or 115 * the proposed container would result in recursive containment. 116 * @exception NameDuplicationException If the container already has 117 * an attribute with the name of this attribute that is of class 118 * SingletonConfigurableAttribute. 119 */ 120 @Override 121 public void setContainer(NamedObj container) 122 throws IllegalActionException, NameDuplicationException { 123 Attribute previous = null; 124 125 if (container != null) { 126 previous = container.getAttribute(getName()); 127 128 if (previous != null) { 129 previous.setContainer(null); 130 } 131 } 132 133 try { 134 super.setContainer(container); 135 } catch (IllegalActionException ex) { 136 // Restore previous. 137 if (previous != null) { 138 previous.setContainer(container); 139 } 140 141 throw ex; 142 } catch (NameDuplicationException ex) { 143 // Restore previous. 144 if (previous != null) { 145 previous.setContainer(container); 146 } 147 148 throw ex; 149 } 150 } 151}