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}