Selaa lähdekoodia

feature #I9H6GN 支持 kotlin 脚本语言

Dale Lee 1 vuosi sitten
vanhempi
säilyke
33f05eb7cc
16 muutettua tiedostoa jossa 452 lisäystä ja 1 poistoa
  1. 2 1
      liteflow-core/src/main/java/com/yomahub/liteflow/enums/ScriptTypeEnum.java
  2. 29 0
      liteflow-script-plugin/liteflow-script-kotlin/pom.xml
  3. 15 0
      liteflow-script-plugin/liteflow-script-kotlin/src/main/java/com/yomahub/liteflow/script/kotlin/KotlinScriptExecutor.java
  4. 2 0
      liteflow-script-plugin/liteflow-script-kotlin/src/main/resources/META-INF/services/com.yomahub.liteflow.script.ScriptExecutor
  5. 1 0
      liteflow-script-plugin/pom.xml
  6. 32 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/pom.xml
  7. 24 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/BaseTest.java
  8. 93 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/T2.java
  9. 49 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/TestKotlin.java
  10. 68 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/common/LiteFlowKotlinScriptCommonELTest.java
  11. 21 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/common/cmp/ACmp.java
  12. 21 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/common/cmp/BCmp.java
  13. 21 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/common/cmp/CCmp.java
  14. 1 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/resources/common/application.properties
  15. 72 0
      liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/resources/common/flow.xml
  16. 1 0
      liteflow-testcase-el/pom.xml

+ 2 - 1
liteflow-core/src/main/java/com/yomahub/liteflow/enums/ScriptTypeEnum.java

@@ -8,7 +8,8 @@ public enum ScriptTypeEnum {
 	PYTHON("python", "python"),
 	LUA("luaj", "lua"),
 	AVIATOR("AviatorScript", "aviator"),
-	JAVA("java", "java");
+	JAVA("java", "java"),
+	KOTLIN("kotlin", "kotlin");
 
 	private String engineName;
 

+ 29 - 0
liteflow-script-plugin/liteflow-script-kotlin/pom.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>liteflow-script-plugin</artifactId>
+        <groupId>com.yomahub</groupId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>liteflow-script-kotlin</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>liteflow-core</artifactId>
+            <version>${revision}</version>
+            <optional>true</optional>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains.kotlin</groupId>
+            <artifactId>kotlin-scripting-jsr223</artifactId>
+            <version>1.9.23</version>
+        </dependency>
+    </dependencies>
+</project>

+ 15 - 0
liteflow-script-plugin/liteflow-script-kotlin/src/main/java/com/yomahub/liteflow/script/kotlin/KotlinScriptExecutor.java

@@ -0,0 +1,15 @@
+package com.yomahub.liteflow.script.kotlin;
+
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
+import com.yomahub.liteflow.script.jsr223.JSR223ScriptExecutor;
+
+/**
+ * Kotlin脚本执行器
+ * @author DaleLee
+ */
+public class KotlinScriptExecutor extends JSR223ScriptExecutor {
+    @Override
+    public ScriptTypeEnum scriptType() {
+        return ScriptTypeEnum.KOTLIN;
+    }
+}

+ 2 - 0
liteflow-script-plugin/liteflow-script-kotlin/src/main/resources/META-INF/services/com.yomahub.liteflow.script.ScriptExecutor

@@ -0,0 +1,2 @@
+# Kotlin的实现
+com.yomahub.liteflow.script.kotlin.KotlinScriptExecutor

+ 1 - 0
liteflow-script-plugin/pom.xml

@@ -23,6 +23,7 @@
         <module>liteflow-script-lua</module>
         <module>liteflow-script-aviator</module>
         <module>liteflow-script-java</module>
+        <module>liteflow-script-kotlin</module>
     </modules>
 
 </project>

+ 32 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/pom.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>liteflow-testcase-el</artifactId>
+        <groupId>com.yomahub</groupId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>liteflow-testcase-el-script-kotlin-springboot</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>liteflow-spring-boot-starter</artifactId>
+            <version>${revision}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.yomahub</groupId>
+            <artifactId>liteflow-script-kotlin</artifactId>
+            <version>2.12.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </dependency>
+    </dependencies>
+</project>

+ 24 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/BaseTest.java

@@ -0,0 +1,24 @@
+package com.yomahub.liteflow.test.script;
+
+import com.yomahub.liteflow.core.FlowInitHook;
+import com.yomahub.liteflow.flow.FlowBus;
+import com.yomahub.liteflow.property.LiteflowConfigGetter;
+import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner;
+import com.yomahub.liteflow.spring.ComponentScanner;
+import com.yomahub.liteflow.thread.ExecutorHelper;
+import org.junit.jupiter.api.AfterAll;
+
+public class BaseTest {
+
+	@AfterAll
+	public static void cleanScanCache() {
+		ComponentScanner.cleanCache();
+		FlowBus.cleanCache();
+		ExecutorHelper.loadInstance().clearExecutorServiceMap();
+		SpiFactoryCleaner.clean();
+		LiteflowConfigGetter.clean();
+		FlowInitHook.cleanHook();
+		FlowBus.clearStat();
+	}
+
+}

+ 93 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/T2.java

@@ -0,0 +1,93 @@
+package com.yomahub.liteflow.test.script.kotlin;
+
+import com.yomahub.liteflow.slot.DefaultContext;
+import org.junit.jupiter.api.Test;
+
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+
+public class T2 {
+    @Test
+    public  void test1() throws ScriptException {
+        // 初始化 ScriptEngineManager 和 Kotlin 脚本引擎
+        ScriptEngineManager manager = new ScriptEngineManager();
+        ScriptEngine engine = manager.getEngineByName("kotlin");
+
+        if (engine == null) {
+            throw new IllegalStateException("Kotlin script engine not found");
+        }
+
+        // 假设我们有以下Kotlin脚本,它期望一个名为'message'的外部参数
+        String script = "fun greet(name: String) {\n" +
+                "                println(\"Hello, $name!\")\n" +
+                "            }\n" +
+                "            println(bindings[\"message\"])";
+
+
+        // 编译脚本为CompiledScript对象
+        Compilable compilable = (Compilable) engine;
+        CompiledScript compiledScript = compilable.compile(script);
+
+        // 准备脚本上下文,用于传递外部参数
+        Bindings bindings = engine.createBindings();
+        // 设置外部参数
+        bindings.put("message", "User");
+
+        // 使用相同的上下文多次执行已编译的脚本
+        for (int i = 0; i < 2; i++) {
+            compiledScript.eval(bindings);
+        }
+//        engine.put("message","User");
+//        engine.eval(script);
+        //engine.eval(script,bindings);
+    }
+
+    @Test
+    public  void test2() throws ScriptException {
+        ScriptEngineManager manager = new ScriptEngineManager();
+        ScriptEngine engine = manager.getEngineByName("kotlin");
+        String script = "" +
+                "var defaultContext = bindings[\"defaultContext\"]\n" +
+                "println(defaultContext.getData(\"key\"))";
+        // 编译脚本为CompiledScript对象
+        Compilable compilable = (Compilable) engine;
+        CompiledScript compiledScript = compilable.compile(script);
+
+        // 准备脚本上下文,用于传递外部参数
+        Bindings bindings = new SimpleBindings();
+        DefaultContext context = new DefaultContext();
+        context.setData("key", "value");
+        // 设置外部参数
+        bindings.put("defaultContext", context);
+        compiledScript.eval(bindings);
+    }
+
+    @Test
+    public  void test3() throws ScriptException {
+        ScriptEngineManager manager = new ScriptEngineManager();
+        ScriptEngine engine = manager.getEngineByName("kotlin");
+        String script =
+                "fun  getNum() = 15\n" +
+                        "getNum()";
+
+        // 编译脚本为CompiledScript对象
+        Compilable compilable = (Compilable) engine;
+        CompiledScript compiledScript = compilable.compile(script);
+
+        // 准备脚本上下文,用于传递外部参数
+//        Bindings bindings = new SimpleBindings();
+//        DefaultContext context = new DefaultContext();
+//        context.setData("key", "value");
+//        // 设置外部参数
+//        bindings.put("defaultContext", context);
+  /*      Object res = compiledScript.eval();
+        System.out.println(res);*/
+        Object eval = engine.eval(script);
+        System.out.println(eval);
+    }
+}

+ 49 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/TestKotlin.java

@@ -0,0 +1,49 @@
+package com.yomahub.liteflow.test.script.kotlin;
+
+import com.yomahub.liteflow.enums.ScriptTypeEnum;
+
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+
+public class TestKotlin {
+    public static void main(String[] args) throws ScriptException, NoSuchMethodException {
+        // 获取脚本引擎管理器
+        ScriptEngineManager manager = new ScriptEngineManager();
+
+        // 获取Kotlin脚本引擎
+        ScriptEngine engine = manager.getEngineByName(ScriptTypeEnum.KOTLIN.getEngineName()); // ".kts" 是Kotlin脚本文件的扩展名
+
+        // 检查是否找到了Kotlin脚本引擎
+        if (engine == null) {
+            System.out.println("No Kotlin script engine found.");
+            return;
+        }
+
+        System.out.println(engine instanceof Compilable);
+
+        // 定义一个Kotlin脚本
+        String script = "println(\"Hello, Kotlin JSR 223!\")";
+
+        Compilable compilable = (Compilable) engine;
+        CompiledScript compile = compilable.compile(script);
+        compile.eval();
+
+
+        // 编译并执行脚本
+        engine.eval(script);
+
+        // 如果ScriptEngine也实现了Invocable接口,我们可以调用脚本中的函数
+//        if (engine instanceof Invocable) {
+//            Invocable inv = (Invocable) engine;
+//
+//            // 调用脚本中的greet函数
+//            String greeting = (String) inv.invokeFunction("greet", "World");
+//            System.out.println(greeting); // 输出: Hello, World!
+//        } else {
+//            System.out.println("The script engine does not support Invocable interface.");
+//        }
+    }
+}

+ 68 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/common/LiteFlowKotlinScriptCommonELTest.java

@@ -0,0 +1,68 @@
+package com.yomahub.liteflow.test.script.kotlin.common;
+
+import com.yomahub.liteflow.core.FlowExecutor;
+import com.yomahub.liteflow.flow.LiteflowResponse;
+import com.yomahub.liteflow.slot.DefaultContext;
+import com.yomahub.liteflow.test.script.BaseTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.annotation.Resource;
+
+@ExtendWith(SpringExtension.class)
+@TestPropertySource(value = "classpath:/common/application.properties")
+@SpringBootTest(classes = LiteFlowKotlinScriptCommonELTest.class)
+@EnableAutoConfiguration
+@ComponentScan({"com.yomahub.liteflow.test.script.kotlin.common.cmp"})
+public class LiteFlowKotlinScriptCommonELTest extends BaseTest {
+
+    @Resource
+    private FlowExecutor flowExecutor;
+
+    @Test
+    public void testCommon1() {
+        LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
+        Assertions.assertTrue(response.isSuccess());
+        DefaultContext context = response.getFirstContextBean();
+        Assertions.assertEquals(Integer.valueOf(5), context.getData("s1"));
+    }
+
+    @Test
+    public void testFor1() {
+        DefaultContext context = new DefaultContext();
+        context.setData("k1", 1);
+        context.setData("k2", 2);
+        LiteflowResponse response = flowExecutor.execute2Resp("chain2", "arg", context);
+        Assertions.assertTrue(response.isSuccess());
+        Assertions.assertEquals("s2==>a==>a==>a",response.getExecuteStepStr());
+    }
+
+    @Test
+    public void testIf1() {
+        LiteflowResponse response = flowExecutor.execute2Resp("chain3", "arg");
+        Assertions.assertTrue(response.isSuccess());
+        Assertions.assertEquals("s3==>b",response.getExecuteStepStr());
+    }
+
+    @Test
+    public void testIf2() {
+        LiteflowResponse response = flowExecutor.execute2Resp("chain4", "arg");
+        Assertions.assertTrue(response.isSuccess());
+        Assertions.assertEquals("s4",response.getExecuteStepStr());
+    }
+
+    @Test
+    public void testSwitch1() {
+        DefaultContext context = new DefaultContext();
+        context.setData("id", "c");
+        LiteflowResponse response = flowExecutor.execute2Resp("chain5", "arg", context);
+        Assertions.assertTrue(response.isSuccess());
+        Assertions.assertEquals("s5==>c",response.getExecuteStepStr());
+    }
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/common/cmp/ACmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.script.kotlin.common.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent("a")
+public class ACmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("ACmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/common/cmp/BCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.script.kotlin.common.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent("b")
+public class BCmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("BCmp executed!");
+	}
+
+}

+ 21 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/java/com/yomahub/liteflow/test/script/kotlin/common/cmp/CCmp.java

@@ -0,0 +1,21 @@
+/**
+ * <p>Title: liteflow</p>
+ * <p>Description: 轻量级的组件式流程框架</p>
+ * @author Bryan.Zhang
+ * @email weenyc31@163.com
+ * @Date 2020/4/1
+ */
+package com.yomahub.liteflow.test.script.kotlin.common.cmp;
+
+import com.yomahub.liteflow.annotation.LiteflowComponent;
+import com.yomahub.liteflow.core.NodeComponent;
+
+@LiteflowComponent("c")
+public class CCmp extends NodeComponent {
+
+	@Override
+	public void process() {
+		System.out.println("CCmp executed!");
+	}
+
+}

+ 1 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/resources/common/application.properties

@@ -0,0 +1 @@
+liteflow.rule-source=common/flow.xml

+ 72 - 0
liteflow-testcase-el/liteflow-testcase-el-script-kotlin-springboot/src/test/resources/common/flow.xml

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<flow>
+    <nodes>
+        <node id="s1" type="script" language="kotlin">
+            <![CDATA[
+                import com.yomahub.liteflow.slot.DefaultContext
+
+                fun sum(a: Int, b: Int) = a + b
+                var a = 2
+                var b = 3
+                val defaultContext = bindings["defaultContext"] as DefaultContext
+                defaultContext.setData("s1", sum(a, b))
+                println("Hello Kotlin!")
+            ]]>
+        </node>
+        <node id="s2" type="for_script" language="kotlin">
+            <![CDATA[
+                import com.yomahub.liteflow.slot.DefaultContext
+
+                fun getCount(): Int {
+                    val ctx = bindings["defaultContext"] as DefaultContext
+                    var n1 = ctx.getData("k1") as Int;
+                    var n2 = ctx.getData("k2") as Int;
+                    return n1 + n2;
+                }
+                getCount()
+            ]]>
+        </node>
+        <node id="s3" type="boolean_script" language="kotlin">
+            <![CDATA[
+                fun getBoolean1() = 2 > 1
+                getBoolean1()
+            ]]>
+        </node>
+        <node id="s4" type="boolean_script" language="kotlin">
+            <![CDATA[
+                fun getBoolean2() = 2 < 1
+                getBoolean2()
+            ]]>
+        </node>
+        <node id="s5" type="switch_script" language="kotlin">
+            <![CDATA[
+                import com.yomahub.liteflow.slot.DefaultContext
+
+                fun getId(ctx: DefaultContext) : String {
+                    return ctx.getData("id") as String
+                }
+                getId(bindings["defaultContext"] as DefaultContext)
+            ]]>
+        </node>
+    </nodes>
+
+    <chain name="chain1">
+        THEN(a, b, c, s1);
+    </chain>
+
+    <chain name="chain2">
+        FOR(s2).DO(a);
+    </chain>
+
+    <chain name="chain3">
+        IF(s3, b);
+    </chain>
+
+    <chain name="chain4">
+        IF(s4, b);
+    </chain>
+
+    <chain name="chain5">
+        SWITCH(s5).TO(a, b, c);
+    </chain>
+</flow>

+ 1 - 0
liteflow-testcase-el/pom.xml

@@ -39,6 +39,7 @@
         <module>liteflow-testcase-el-script-java-springboot</module>
         <module>liteflow-testcase-el-builder</module>
         <module>liteflow-testcase-el-routechain</module>
+        <module>liteflow-testcase-el-script-kotlin-springboot</module>
     </modules>
 
     <build>