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}