001/* Basic applet that constructs a Ptolemy II model from a MoML file. 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.actor.gui; 029 030import java.net.URL; 031 032import ptolemy.actor.CompositeActor; 033import ptolemy.actor.Manager; 034import ptolemy.kernel.ComponentEntity; 035import ptolemy.kernel.CompositeEntity; 036import ptolemy.kernel.attributes.VersionAttribute; 037import ptolemy.kernel.util.IllegalActionException; 038import ptolemy.kernel.util.NamedObj; 039import ptolemy.kernel.util.Workspace; 040import ptolemy.moml.Documentation; 041import ptolemy.moml.MoMLParser; 042import ptolemy.moml.filter.BackwardCompatibility; 043import ptolemy.moml.filter.RemoveGraphicalClasses; 044 045/////////////////////////////////////////////////////////////////// 046//// MoMLApplet 047 048/** 049 This is an applet that constructs a Ptolemy II model from a MoML file. 050 "MoML" stands for "Modeling Markup Language." It is an XML schema for 051 constructing Ptolemy II models. 052 <p> 053 This class offers a number of alternatives that control the visual 054 appearance of the applet. By default, the applet places on the screen 055 a set of control buttons that can be used to start, stop, pause, and 056 resume the model. Below those buttons, it places the visual elements 057 of any actors in the model that implement the Placeable interface, 058 such as plotters or textual output. 059 <p> 060 The applet parameters are: 061 <ul> 062 <li> 063 <i>background</i>: The background color, typically given as a hex 064 number of the form "#<i>rrggbb</i>" where <i>rr</i> gives the red 065 component, <i>gg</i> gives the green component, and <i>bb</i> gives 066 the blue component. 067 <li> 068 <i>controls</i>: 069 This gives a comma-separated list 070 of any subset of the words "buttons", "topParameters", and 071 "directorParameters" (case insensitive), or the word "none". 072 If this parameter is not given, then it is equivalent to 073 giving "buttons", and only the control buttons mentioned above 074 will be displayed. If the parameter is given, and its value is "none", 075 then no controls are placed on the screen. If the word "topParameters" 076 is included in the comma-separated list, then controls for the 077 top-level parameters of the model are placed on the screen, below 078 the buttons. If the word "directorParameters" is included, 079 then controls for the director parameters are also included. 080 <li> 081 <i>modelURL</i>: The name of a URI (or URL) containing the 082 MoML file that defines the model. 083 <li> 084 <i>orientation</i>: This can have value "horizontal", "vertical", or 085 "controls_only" (case insensitive). If it is "vertical", then the 086 controls are placed above the visual elements of the Placeable actors. 087 This is the default. If it is "horizontal", then the controls 088 are placed to the left of the visual elements. If it is "controls_only" 089 then no visual elements are placed. 090 </ul> 091 <p> 092 To create a model in a different way, say without a <i>modelClass</i> 093 applet parameter, you may extend this class and override the 094 protected method _createModel(). If you wish to alter the way 095 that the model is represented on the screen, you can extend this 096 class an override the _createView() method. The rendition in this class 097 is an instance of ModelPane. 098 099 @author Edward A. Lee, Christopher Hylands 100 @version $Id$ 101 @since Ptolemy II 0.4 102 @Pt.ProposedRating Yellow (eal) 103 @Pt.AcceptedRating Red (eal) 104 */ 105@SuppressWarnings("serial") 106public class MoMLApplet extends PtolemyApplet { 107 /////////////////////////////////////////////////////////////////// 108 //// public methods //// 109 110 /** Return applet information. If the top-level model element 111 * contains a <i>doc</i> element, then the contents of that element 112 * is included in the applet information. 113 * @return A string giving information about the applet. 114 */ 115 @Override 116 public String getAppletInfo() { 117 // Include the release and build number to aid in user support. 118 String version = "Ptolemy II " + VersionAttribute.CURRENT_VERSION; 119 String build = "\n(Build: $Id$)"; 120 121 if (_toplevel != null) { 122 String tip = Documentation.consolidate(_toplevel); 123 124 if (tip != null) { 125 return version + " model given in MoML:\n" + tip + build; 126 } else { 127 return version + " model given in MoML." + build; 128 } 129 } 130 131 return "MoML applet for " + version 132 + "\nPtolemy II comes from UC Berkeley, Department of EECS.\n" 133 + "See http://ptolemy.eecs.berkeley.edu/ptolemyII" + build; 134 } 135 136 /** Describe the applet parameters. 137 * @return An array describing the applet parameters. 138 */ 139 @Override 140 public String[][] getParameterInfo() { 141 String[][] newInfo = { { "modelURL", "", "URL for the MoML file" }, }; 142 return _concatStringArrays(super.getParameterInfo(), newInfo); 143 } 144 145 /////////////////////////////////////////////////////////////////// 146 //// protected methods //// 147 148 /** Read the model from the <i>modelURL</i> applet parameter 149 * and filter out any graphical classes that might require us 150 * to have diva.jar in the classpath. 151 * @param workspace The workspace in which to create the model. 152 * @return A model. 153 * @exception Exception If something goes wrong. 154 */ 155 @Override 156 protected NamedObj _createModel(Workspace workspace) throws Exception { 157 // Filter out graphical classes. 158 return _createModel(workspace, true); 159 } 160 161 /** Read the model from the <i>modelURL</i> applet parameter. 162 * @param workspace The workspace in which to create the model. 163 * @param filterGraphicalClasses If true, then filter out graphical 164 * classes that might require diva.jar to be in the classpath 165 * @return A model. 166 * @exception Exception If something goes wrong. 167 */ 168 protected NamedObj _createModel(Workspace workspace, 169 boolean filterGraphicalClasses) throws Exception { 170 // ptolemy.vergil.MoMLViewerApplet() calls this with 171 // filterGraphicalClasses set to false. 172 _modelURL = _readModelURLParameter(); 173 174 MoMLParser parser = new MoMLParser(); 175 176 // FIXME: if we call _createModel twice, then we will add 177 // this filter twice. We reset the filter list here, 178 // though we will lose any other filters. 179 MoMLParser.setMoMLFilters(null); 180 181 MoMLParser.setMoMLFilters(BackwardCompatibility.allFilters()); 182 183 RemoveGraphicalClasses removeNonAppletClasses = new RemoveGraphicalClasses(); 184 // If filterGraphicalClasses is true, then we filter out 185 // graphical classes so that we do not require diva.jar. If 186 // it is false, then we clear the filter. In both cases we 187 // add some classes that are always filtered. 188 if (!filterGraphicalClasses) { 189 RemoveGraphicalClasses.clear(); 190 } 191 192 // Exclude the code generator 193 removeNonAppletClasses.put( 194 "ptolemy.codegen.kernel.StaticSchedulingCodeGenerator", null); 195 removeNonAppletClasses.put( 196 "ptolemy.vergil.kernel.attributes.DocumentationAttribute", 197 null); 198 MoMLParser.addMoMLFilter(removeNonAppletClasses); 199 200 URL docBase = getDocumentBase(); 201 URL xmlFile = new URL(docBase, _modelURL); 202 _manager = null; 203 204 NamedObj toplevel = parser.parse(docBase, xmlFile); 205 _workspace = toplevel.workspace(); 206 207 if (_fragment != null && !_fragment.trim().equals("")) { 208 // A fragment was specified, so we should look inside. 209 ComponentEntity inside = null; 210 211 if (toplevel instanceof CompositeEntity) { 212 inside = ((CompositeEntity) toplevel).getEntity(_fragment); 213 } 214 215 if (inside == null) { 216 throw new IllegalActionException(toplevel, 217 "No such contained entity: " + _fragment); 218 } 219 220 toplevel = inside; 221 } else if (toplevel instanceof CompositeActor) { 222 CompositeActor result = (CompositeActor) toplevel; 223 _manager = result.getManager(); 224 225 if (_manager == null) { 226 _manager = new Manager(_workspace, "manager"); 227 result.setManager(_manager); 228 } 229 230 _manager.addExecutionListener(this); 231 } 232 233 return toplevel; 234 } 235 236 /** Read the modelURL applet parameter. 237 * If the modelURL applet parameter does not exist, then 238 * read the model applet parameter. As a side effect, 239 * the _fragment field is set with any text after a "#". 240 * @exception Exception Thrown if there is no modelURL or model 241 * applet parameter. 242 * @return the value of the modelURL or model parameter. 243 */ 244 protected String _readModelURLParameter() throws Exception { 245 _modelURL = getParameter("modelURL"); 246 247 if (_modelURL == null) { 248 // For backward compatibility, try name "model". 249 _modelURL = getParameter("model"); 250 251 if (_modelURL == null) { 252 throw new Exception("Applet does not not specify a modelURL."); 253 } 254 } 255 256 // NOTE: Regrettably, Java's URL class is too dumb 257 // to handle a fragment part of a URL. Thus, if 258 // there is one, we have to remove it. Note that 259 // Java calls this a "fragment", a "ref", and 260 // and "reference", all in different parts of the 261 // docs. 262 int sharp = _modelURL.indexOf("#"); 263 264 if (sharp > 0) { 265 _fragment = _modelURL.substring(sharp + 1); 266 _modelURL = _modelURL.substring(0, sharp); 267 } 268 269 return _modelURL; 270 } 271 272 /////////////////////////////////////////////////////////////////// 273 //// protected fields //// 274 275 /** The fragment of the modelURL, if any. This field is set after 276 * _readMoMLAppletParameter() is called. 277 */ 278 protected String _fragment = ""; 279 280 /** The modelURL. This field is set after 281 * _readMoMLAppletParameter() is called. 282 */ 283 protected String _modelURL = ""; 284}