001/* An actor whose execution is specified by a Javascript script. 002 003Copyright (c) 2013 The Regents of the University of California. 004All rights reserved. 005Permission is hereby granted, without written agreement and without 006license or royalty fees, to use, copy, modify, and distribute this 007software and its documentation for any purpose, provided that the above 008copyright notice and the following two paragraphs appear in all copies 009of this software. 010 011IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015SUCH DAMAGE. 016 017THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022ENHANCEMENTS, OR MODIFICATIONS. 023 024*/ 025package org.kepler.scriptengine; 026 027import ptolemy.kernel.CompositeEntity; 028import ptolemy.kernel.util.IllegalActionException; 029import ptolemy.kernel.util.NameDuplicationException; 030import ptolemy.kernel.util.Workspace; 031 032/** An actor whose execution is defined by a Javascript script. 033 * The script can be edited by double-clicking on the actor. 034 * 035 * <p>The following example defines an actor in Javascript that 036 * computes factorials:</p> 037<pre> 0381. importClass(Packages.ptolemy.data.type.BaseType); 0392. importClass(Packages.ptolemy.data.IntToken); 0403. 0414. function Actor() {}; 0425. 0436. // implement the "fire" function to be called each time the actor executes 0447. Actor.prototype.fire = function() { 0458. 0469. // read from the "input" port 04710. var val = this.input.get(0).intValue(); 04811. 04912. if(val < 0) { 05013. error = "Input must be greater than or equal to 0"; 05114. } else { 05215. var total = 1; 05316. while(val > 1) { 05417. total *= val; 05518. val--; 05619. } 05720. // write the result to the "output" port 05821. this.output.broadcast(new IntToken(total)); 05922. } 06023. }; 06124. 06225. // define the "preinitialize" function to be called once when the workflow starts. 06326. Actor.prototype.preinitialize = function() { 06427. // set the data types for the "input" and "output" ports. 06528. this.input.setTypeEquals(BaseType.INT); 06629. this.output.setTypeAtLeast(this.input); 06730. }; 068</pre> 069 * 070 * <p>Lines 1 and 2 import the Java classes used by the actor. Line 4 defines the 071 * Actor object and is required in every Javascript. Lines 7-23 define the 072 * fire() method of the actor; this method is called each time this actor 073 * executes in the workflow. Line 10 reads an integer from the input port 074 * called "input". A port or parameter called "foo" can be accessed in the 075 * Javascript script by using "this.foo". Lines 12-19 compute the factorial 076 * of the integer read from the port. Line 21 writes the result to the output 077 * port called "output". Lines 26-29 define the preinitialize() method of this 078 * actor, which is executed once when the workflow starts. Lines 28-29 set 079 * the types for the input and output ports.</p> 080 * 081 * @author Daniel Crawl 082 * @version $Id: Javascript.java 33884 2015-09-11 18:07:23Z crawl $ 083 */ 084public class Javascript extends ScriptEngineActor { 085 086 /** Construct a new Javascript for a specified workspace. */ 087 public Javascript(Workspace workspace) { 088 super(workspace); 089 } 090 091 /** Construct a new Javascript with the given container and name. */ 092 public Javascript(CompositeEntity container, String name) 093 throws IllegalActionException, NameDuplicationException { 094 super(container, name); 095 096 _editorFactory.syntaxStyle.setExpression("text/javascript"); 097 098 // use the rhino engine that is not bundled with the JDK 099 // the engine is in actors/lib/jar/script-engine/js-engine.jar, and 100 // uses the RhinoScript jar in Ptolemy $PTII/lib/js.jar. 101 language.setToken("rhino-nonjdk"); 102 103 // create a simple script that prints something when 104 // the actor fires 105 script.setExpression("// this prints each time the actor executes\n" + 106 "function Actor() {};\n" + 107 "\n" + 108 "Actor.prototype.fire = function() {\n" + 109 " println(\"in fire\");\n" + 110 "};"); 111 } 112}