001/* An actor whose execution is specified by a Groovy 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*/
025
026package org.kepler.scriptengine;
027
028import javax.script.ScriptException;
029
030import ptolemy.kernel.CompositeEntity;
031import ptolemy.kernel.util.IllegalActionException;
032import ptolemy.kernel.util.NameDuplicationException;
033import ptolemy.kernel.util.Workspace;
034
035/** An actor whose execution is defined by a Groovy script.
036 *  The script can be edited by double-clicking on the actor.   
037 *  
038 *  <p>The following example defines an actor in Groovy that
039 *  computes factorials:</p>
040<pre>
0411. import ptolemy.data.IntToken
0422. 
0433. // Groovy actor to compute factorials.
0444. 
0455. public class Actor {
0466.     def fire() {
0477.         int val = input.get(0).intValue()
0488.         if(val < 0) {
0499.             actor.error("Input must be non-negative.");
05010.            return
05111.        }
05212.        int total = factorial(val)
05313.        output.broadcast(new IntToken(total))
05414.    }
05515.
05616.    def factorial = { n -> n == 0 ? 1 : n * factorial(n - 1) }
05717.}
058</pre>
059 *
060 *  <p>Line 1 imports the Java class used by the actor. Lines 5-17 define
061 *  the Actor object; the actor object must be named "Actor" in Groovy scripts.
062 *  Lines 6-14 define the fire() method of the actor, which is called each
063 *  time this actor executes in the workflow. Line 7 reads an integer from the
064 *  input port called "input". A port or parameter called "foo" can be accessed
065 *  in the Groovy script by using the same name. Line 12 calls the closure
066 *  defined on line 16 that recursively computes the factorial of the integer
067 *  read from the port. Line 13 writes the result to the output port called
068 *  "output".</p>
069 *  
070 *  @author Daniel Crawl
071 *  @version $Id: Groovy.java 33884 2015-09-11 18:07:23Z crawl $
072 */
073public class Groovy extends ScriptEngineActor {
074
075    /** Construct a new Groovy for a specified workspace. */
076    public Groovy(Workspace workspace) {
077        super(workspace);
078    }
079
080    /** Construct a new Groovy with the given container and name. */
081    public Groovy(CompositeEntity container, String name)
082            throws IllegalActionException, NameDuplicationException {
083        super(container, name);
084        
085        _editorFactory.syntaxStyle.setExpression("text/groovy");
086        
087        language.setToken("groovy");
088        
089        script.setExpression("public class Actor {\n" +
090                "  public void fire() {\n" +
091                "     println(\"in fire\");\n" +
092                "  }\n" +
093                "}\n");
094    }
095
096    /** Put the given object to the actor instance in the script.
097     *  @param name the name of the object to put.
098     *  @param object the object to put.
099     */
100    @Override
101    protected void _putObjectToActorInstance(String name, Object object) throws ScriptException {
102        String globalName = "_yyy_" + name;
103        _engine.put(globalName, object);
104        _engine.eval(_ACTOR_INSTANCE_NAME + ".metaClass." + name + " = " + globalName);
105    }
106}