2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.bpmn.core;
23 import java.io.ByteArrayInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.math.BigDecimal;
28 import java.util.Iterator;
30 import javax.xml.transform.stream.StreamSource;
32 import org.camunda.bpm.engine.ProcessEngineException;
33 import org.camunda.bpm.engine.delegate.DelegateExecution;
34 //import java.util.logging.Logger;
35 import org.camunda.bpm.engine.delegate.Expression;
37 import org.openecomp.mso.logger.MessageEnum;
38 import org.openecomp.mso.logger.MsoLogger;
40 import net.sf.saxon.Configuration;
41 import net.sf.saxon.s9api.DocumentBuilder;
42 import net.sf.saxon.s9api.Processor;
43 import net.sf.saxon.s9api.QName;
44 import net.sf.saxon.s9api.XQueryCompiler;
45 import net.sf.saxon.s9api.XQueryEvaluator;
46 import net.sf.saxon.s9api.XQueryExecutable;
47 import net.sf.saxon.s9api.XdmAtomicValue;
48 import net.sf.saxon.s9api.XdmItem;
49 import net.sf.saxon.s9api.XdmNode;
52 * Executes an XQuery script.
54 * Required fields:<br/><br/>
55 * scriptFile: the XQuery script file path<br/>
56 * outputVariable: the output variable name<br/>
58 * Optional fields:<br/><br/>
59 * xmlInputVariables: CSV list of variables containing
60 * XML data to be injected into the script<br/>
61 * atomicInputVariables: CSV list of variables containing
62 * atomic data to be injected into the script<br/>
64 public class XQueryScriptTask extends BaseTask {
66 private static MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL);
68 private Expression scriptFile;
69 private Expression xmlInputVariables;
70 private Expression atomicInputVariables;
71 private Expression outputVariable;
73 public void execute(DelegateExecution execution) throws Exception {
74 if (msoLogger.isDebugEnabled()) {
75 msoLogger.debug("Started Executing " + getTaskName());
78 String theScriptFile =
79 getStringField(scriptFile, execution, "scriptFile");
80 String theXmlInputVariables =
81 getOptionalStringField(xmlInputVariables, execution, "xmlInputVariables");
82 String theAtomicInputVariables =
83 getOptionalStringField(atomicInputVariables, execution, "atomicInputVariables");
84 String theOutputVariable =
85 getStringField(outputVariable, execution, "outputVariable");
87 if (msoLogger.isDebugEnabled()) {
88 System.out.println("scriptFile = " + theScriptFile
89 + " xmlInputVariables = " + theXmlInputVariables
90 + " atomicInputVariables = " + theAtomicInputVariables
91 + "outputVariable = " + theOutputVariable);
94 String[] xmlInputVariableArray = (theXmlInputVariables == null)
95 ? new String[0] : theXmlInputVariables.split(",[ ]*");
97 String[] atomicInputVariableArray = (theAtomicInputVariables == null)
98 ? new String[0] : theAtomicInputVariables.split(",[ ]*");
100 Boolean shouldFail = (Boolean) execution.getVariable("shouldFail");
102 if (shouldFail != null && shouldFail) {
103 throw new ProcessEngineException(getClass().getSimpleName() + " Failed");
106 // The script could be compiled once and reused, but we are reading it
107 // and compiling it every time.
108 Configuration configuration = new Configuration();
109 Processor processor = new Processor(configuration);
110 XQueryCompiler compiler = processor.newXQueryCompiler();
111 XQueryExecutable executable = compile(compiler, theScriptFile);
113 // The evaluator must not be shared by multiple threads. Here is where
114 // the initial context may be set, as well as values of external variables.
115 XQueryEvaluator evaluator = executable.load();
117 // Convert XML string variable content to document-node objects and inject
118 // these into the evaluator. Note: the script must accept the document-node
119 // type. Most MSO scripts today expect element() input, not document-node
120 // input. TODO: figure out how to pass the variable data as element() types.
122 for (String xmlInputVariable : xmlInputVariableArray) {
123 if (msoLogger.isDebugEnabled()) {
124 msoLogger.debug("Injecting XML variable '" + xmlInputVariable + "'");
125 msoLogger.debug("printing the variable content>>'" + execution.getVariable(xmlInputVariable) +"'");
128 String xml = (String) execution.getVariable(xmlInputVariable);
129 DocumentBuilder documentBuilder = processor.newDocumentBuilder();
130 StreamSource source = new StreamSource(new ByteArrayInputStream(xml.getBytes("UTF-8")));
131 XdmNode xdmNode = documentBuilder.build(source);
133 // Inject the document-node object into the XQueryEvaluator.
134 // TODO: transform it to an element()
135 QName variable = new QName(xmlInputVariable);
136 evaluator.setExternalVariable(variable, xdmNode);
139 // Inject atomic variables into the evaluator.
141 for (String atomicInputVariable : atomicInputVariableArray) {
143 if (msoLogger.isDebugEnabled()) {
144 System.out.println("Injecting object variable '"
145 + atomicInputVariable + "'");
148 QName variable = new QName(atomicInputVariable);
149 Object value = execution.getVariable(atomicInputVariable);
152 // The variable value is null, so we have no way to know what
153 // type it is. I don't know how to deal with this, so for
154 // now, just skip it.
156 msoLogger.warn (MessageEnum.BPMN_VARIABLE_NULL, "BPMN", MsoLogger.getServiceName(), MsoLogger.ErrorCode.DataError, atomicInputVariable);
161 // There might be a better way to do this...
162 if (value instanceof BigDecimal) {
163 evaluator.setExternalVariable(variable,
164 new XdmAtomicValue((BigDecimal) value));
165 } else if (value instanceof Boolean) {
166 evaluator.setExternalVariable(variable,
167 new XdmAtomicValue((Boolean) value));
168 } else if (value instanceof Double) {
169 evaluator.setExternalVariable(variable,
170 new XdmAtomicValue((Double) value));
171 } else if (value instanceof Float) {
172 evaluator.setExternalVariable(variable,
173 new XdmAtomicValue((Float) value));
174 } else if (value instanceof Long) {
175 evaluator.setExternalVariable(variable,
176 new XdmAtomicValue((Long) value));
177 } else if (value instanceof String) {
178 evaluator.setExternalVariable(variable,
179 new XdmAtomicValue((String) value));
180 } else if (value instanceof URI) {
181 evaluator.setExternalVariable(variable,
182 new XdmAtomicValue((URI) value));
184 throw new BadInjectedFieldException(
185 "atomicInputVariables", getTaskName(),
186 "'" + atomicInputVariable + "' type is not supported: "
191 // Evaluate the query and collect the output.
192 StringBuilder output = new StringBuilder();
193 Iterator<XdmItem> xdmItems = evaluator.iterator();
194 while (xdmItems.hasNext()) {
195 XdmItem item = xdmItems.next();
197 if (msoLogger.isDebugEnabled()) {
198 msoLogger.debug("XQuery result item = " + item);
201 output.append(item.toString());
204 // Set the output variable.
205 execution.setVariable(theOutputVariable, output.toString());
207 if (msoLogger.isDebugEnabled()) {
208 msoLogger.debug("Done Executing " + getTaskName());
213 * Compiles an XQuery script contained in a resource (file).
214 * @param compiler the XQueryCompiler
215 * @param resource the resource path
216 * @return an XQueryExecutable
217 * @throws Exception on error
219 private XQueryExecutable compile(XQueryCompiler compiler, String resource)
221 InputStream xqStream = null;
223 xqStream = getClass().getResourceAsStream(resource);
225 if (xqStream == null) {
226 throw new IOException("Resource not found: " + resource);
229 XQueryExecutable executable = compiler.compile(xqStream);
234 if (xqStream != null) {
237 } catch (Exception e) {