如何通过Java脚本API

时间:2015-07-03 10:02:34

标签: java xml

我正在写一些可称为工作流引擎的东西。为此,我已根据特定的XML Schema将工作流的数据模型创建为XML。

以下是表示此数据模型的XML示例:

<dm:agentModel xmlns:dm="ProcessObjects" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="ProcessObjects agentModel.xsd">
    <dm:cfp isList="false" objName="myCFP"></dm:cfp>
    <dm:proposal isList="true" objName="receivedProposals"></dm:proposal>
    <dm:feedbackList objName="cfpFeedbacks">
      <dm:item>
        <dm:to>Andrew</dm:to>
        <dm:from>Paul</dm:from>
        <dm:heading>That is bad</dm:heading>
        <dm:body>Fix points a, b and c, please.</dm:body>
      </dm:item>  
      <dm:item>
        <dm:to>Frank</dm:to>
        <dm:from>Paul</dm:from>
        <dm:heading>Very good!</dm:heading>
        <dm:body>I see no drawbacks. You can also ask Matthew for additional feedback.</dm:body>
      </dm:item>  
    </dm:feedbackList>
</dm:agentModel>

工作流定义由用户通过Web编辑器定义,是BPMN XML标准。为了不深入细节,我需要让用户定义一些脚本界面。用户需要能够写出如下内容:

/*JavaScript code*/
for(var i=0; i<agentModel.cfpFeedbacks.length; i++) {
    if(agentModel.cfpFeedbacks[i].to == "Frank") {
        agentModel.cfpFeedbacks[i].to += " Sinatra";
    }
}

到目前为止,我编写了Java类(DataModel),可以访问上面给出的XML构建的数据。因为XML可能包含许多不同的对象,所以getter和setter看起来像:

/*Java code*/
DataModel agentModel = new DataModel(xmlString);
agentModel.getValue("cfpFeedbacks[1].to");
//returns String "Frank"
agentModel.setValue("cfpFeedbacks[0].from", "Paul Anka");
//obvious

要运行用户编写的脚本,我尝试使用Java Scripting API

/*Java code*/
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");

//binding object 
engine.put("agentModel", agentModel);
String script =   "var i = 0;"
                + "println(agentModel.getValue(\"cfpFeedbacks[\" + i + \"].from\"));";
engine.eval(script);

哪个或多或少有效。我想要的就是这样的工作:

/*Java code*/
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");

//binding object 
engine.put("agentModel", agentModel);
String script =   "var i = 0;"
                + "println(agentModel.cfpFeedbacks[i].from);";
/**
* any magic operations here
*/
engine.eval(script);

目标是为最终用户提供最简单的界面来编写脚本。

我有点失落,我会感激任何灵感。就个人而言,我确实考虑了三种情况:

  • 创建Java-Bean样式类,并编译它们而不是处理XML
  • 从第二种形式解析脚本字符串到第一种形式(这似乎是最简单的,但时间很长,绝对不是'干净')
  • 为调用object.field的同义词调用object.getValue("field")
  • 的对象开发某种魔术界面

也许我看不到有一些明显的解决方法。

提前感谢您的回复,

PS。如果我的描述不清楚,或者您发现提供更多源代码是值得的,我会立即澄清问题。完成任务现在是我的首要任务。

1 个答案:

答案 0 :(得分:0)

最好的方法是将xml反序列化为java对象,然后将结果放入引擎。

您可以直接操作通过engine.put(..)方法

投放的对象
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
engine.put("a", 1);
engine.put("b", 5);
engine.eval("a = 2;");
Object result = engine.eval("c = a + b;");
System.out.println("a + b = " + result);

最后从脚本引擎获取对象并将对象序列化为xml,jackson 将非常有用