001/* An attribute that references a library to use with the container. 002 003 Copyright (c) 1998-2013 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.moml; 029 030import ptolemy.kernel.CompositeEntity; 031import ptolemy.kernel.util.Attribute; 032import ptolemy.kernel.util.ConfigurableAttribute; 033import ptolemy.kernel.util.IllegalActionException; 034import ptolemy.kernel.util.InternalErrorException; 035import ptolemy.kernel.util.KernelException; 036import ptolemy.kernel.util.NameDuplicationException; 037import ptolemy.kernel.util.NamedObj; 038import ptolemy.kernel.util.SingletonAttribute; 039import ptolemy.kernel.util.Workspace; 040 041/////////////////////////////////////////////////////////////////// 042//// LibraryAttribute 043 044/** 045 This class is a configurable singleton attribute that associates a 046 component library with a model. By convention, it is typically named 047 "_library". A visual editor that opens a model containing this attribute 048 will offer the contents of its library as the component library for editing 049 the model. "Singleton" means that if this attribute is placed in a model, 050 it will replace any previous singleton attribute that has the same name. 051 "Configurable" means that the contents of the library can be set in 052 a configure element in MoML, or via the configure() method. 053 The library can also be set by calling setLibrary(); this will override 054 any library specified by configure. 055 <p> 056 When creating a library to associate with this attribute, the 057 library should be created in the same workspace as this attribute 058 (as returned by the workspace() method). Normally, it will have no 059 container. The text specified in the configure element (or a call 060 to the configure() method) is not parsed until the getLibrary() 061 method is called. Thus, the overhead of creating the library is 062 avoided if the library is not used. 063 064 @author Edward A. Lee 065 @version $Id$ 066 @since Ptolemy II 1.0 067 @Pt.ProposedRating Yellow (eal) 068 @Pt.AcceptedRating Red (janneck) 069 */ 070public class LibraryAttribute extends ConfigurableAttribute { 071 /** Construct a new attribute with no 072 * container and an empty string as its name. Add the attribute to the 073 * workspace directory. 074 * Increment the version number of the workspace. 075 */ 076 public LibraryAttribute() { 077 super(); 078 } 079 080 /** Construct a new attribute with 081 * no container and an empty string as a name. You can then change 082 * the name with setName(). If the workspace argument is null, then 083 * use the default workspace. 084 * Add the attribute to the workspace directory. 085 * Increment the version number of the workspace. 086 * @param workspace The workspace that will list the attribute. 087 */ 088 public LibraryAttribute(Workspace workspace) { 089 super(workspace); 090 } 091 092 /** Construct an attribute with the given container and name. 093 * If an attribute already exists with the same name as the one 094 * specified here, that is an instance of class 095 * LibraryAttribute (or a derived class), then that 096 * attribute is removed before this one is inserted in the container. 097 * @param container The container. 098 * @param name The name of this attribute. 099 * @exception IllegalActionException If the attribute cannot be contained 100 * by the proposed container. 101 * @exception NameDuplicationException If the container already has an 102 * attribute with this name, and the class of that container is not 103 * LibraryAttribute. 104 */ 105 public LibraryAttribute(NamedObj container, String name) 106 throws NameDuplicationException, IllegalActionException { 107 super(container, name); 108 } 109 110 /////////////////////////////////////////////////////////////////// 111 //// public methods //// 112 113 /** Return the library specified by the configure() method or the 114 * setLibrary() method, or null if it has not been set. If the 115 * configure() method has defined the library, then calling this 116 * method will parse the MoML in specified in the configure() call 117 * to create the library. The parser for the top-level container 118 * of this attribute will be used, if there is one. Otherwise, 119 * a new parser will be used. Note that the library will be 120 * reparsed each time this is called. This method ensures that 121 * the library that is returned contains an attribute called 122 * "_libraryMarker" so that a user interface recognizes it as 123 * a library. 124 * @return The library, or null if none. 125 * @exception Exception If the library specification 126 * is invalid, for example because the MoML cannot be parsed, or 127 * because it does not define an instance of CompositeEntity. 128 * @see #setLibrary(CompositeEntity) 129 */ 130 public CompositeEntity getLibrary() throws Exception { 131 if (_librarySet) { 132 return _library; 133 } 134 135 MoMLParser parser = ParserAttribute.getParser(this); 136 parser.reset(); 137 138 String value = value(); 139 140 NamedObj library = null; 141 if (!value.trim().equals("")) { 142 library = parser.parse(value); 143 if (!(library instanceof CompositeEntity)) { 144 throw new IllegalActionException(this, 145 "Expected library to be in an instance of CompositeEntity," 146 + " but it is: " 147 + library.getClass().getName()); 148 } 149 // Ensure that the library is marked as a library. 150 Attribute marker = library.getAttribute("_libraryMarker"); 151 152 if (marker == null) { 153 new SingletonAttribute(library, "_libraryMarker"); 154 } 155 } 156 157 return (CompositeEntity) library; 158 } 159 160 /** Specify the library, overriding any library that might have been 161 * or might later be specified by a call to configure(). This method 162 * ensures that the library contains an attribute named "_libraryMarker" 163 * by creating one if it is not there. 164 * @param library The library. 165 * @see #getLibrary() 166 */ 167 public void setLibrary(CompositeEntity library) { 168 _library = library; 169 _librarySet = true; 170 171 if (_library != null) { 172 Attribute marker = _library.getAttribute("_libraryMarker"); 173 174 if (marker == null) { 175 try { 176 new SingletonAttribute(_library, "_libraryMarker"); 177 } catch (KernelException ex) { 178 throw new InternalErrorException( 179 "Can't add library marker: " + ex); 180 } 181 } 182 } 183 } 184 185 /////////////////////////////////////////////////////////////////// 186 //// private variables //// 187 // The library. 188 private CompositeEntity _library; 189 190 // Flag indicating that the library was set by setLibrary(). 191 private boolean _librarySet = false; 192}