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.common;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.fail;
26 import java.io.IOException;
27 import java.io.StringReader;
28 import java.lang.management.ManagementFactory;
29 import java.lang.management.RuntimeMXBean;
30 import java.lang.reflect.Field;
31 import java.lang.reflect.Modifier;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.Comparator;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
39 import java.util.UUID;
41 import javax.ws.rs.core.Response;
42 import javax.xml.bind.JAXBException;
43 import javax.xml.namespace.NamespaceContext;
44 import javax.xml.namespace.QName;
45 import javax.xml.parsers.DocumentBuilder;
46 import javax.xml.parsers.DocumentBuilderFactory;
47 import javax.xml.parsers.ParserConfigurationException;
48 import javax.xml.xpath.XPath;
49 import javax.xml.xpath.XPathConstants;
50 import javax.xml.xpath.XPathExpression;
51 import javax.xml.xpath.XPathExpressionException;
52 import javax.xml.xpath.XPathFactory;
54 import org.camunda.bpm.engine.RuntimeService;
55 import org.camunda.bpm.engine.history.HistoricProcessInstance;
56 import org.camunda.bpm.engine.history.HistoricVariableInstance;
57 import org.camunda.bpm.engine.runtime.ProcessInstance;
58 import org.camunda.bpm.engine.test.ProcessEngineRule;
59 import org.camunda.bpm.engine.variable.impl.VariableMapImpl;
60 import org.custommonkey.xmlunit.DetailedDiff;
61 import org.custommonkey.xmlunit.XMLUnit;
62 import org.jboss.resteasy.spi.AsynchronousResponse;
63 import org.junit.Before;
64 import org.junit.Rule;
65 import org.openecomp.mso.bpmn.common.adapter.sdnc.CallbackHeader;
66 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCAdapterCallbackRequest;
67 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCAdapterResponse;
68 import org.openecomp.mso.bpmn.common.adapter.vnf.CreateVnfNotification;
69 import org.openecomp.mso.bpmn.common.adapter.vnf.DeleteVnfNotification;
70 import org.openecomp.mso.bpmn.common.adapter.vnf.MsoExceptionCategory;
71 import org.openecomp.mso.bpmn.common.adapter.vnf.MsoRequest;
72 import org.openecomp.mso.bpmn.common.adapter.vnf.UpdateVnfNotification;
73 import org.openecomp.mso.bpmn.common.adapter.vnf.VnfRollback;
74 import org.openecomp.mso.bpmn.common.workflow.service.SDNCAdapterCallbackServiceImpl;
75 import org.openecomp.mso.bpmn.common.workflow.service.VnfAdapterNotifyServiceImpl;
76 import org.openecomp.mso.bpmn.common.workflow.service.WorkflowAsyncCommonResource;
77 import org.openecomp.mso.bpmn.common.workflow.service.WorkflowMessageResource;
78 import org.openecomp.mso.bpmn.common.workflow.service.WorkflowResponse;
79 import org.openecomp.mso.bpmn.core.CamundaDBSetup;
80 import org.openecomp.mso.bpmn.core.PropertyConfigurationSetup;
81 import org.w3c.dom.Document;
82 import org.w3c.dom.Element;
83 import org.w3c.dom.Node;
84 import org.w3c.dom.NodeList;
85 import org.xml.sax.InputSource;
86 import org.xml.sax.SAXException;
88 import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
89 import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
90 import com.github.tomakehurst.wiremock.junit.WireMockRule;
95 * A base class for Workflow tests.
97 * WireMock response transformers may be specified by declaring public
98 * static fields with the @WorkflowTestTransformer annotation. For example:
100 * @WorkflowTestTransformer
101 * public static final ResponseTransformer sdncAdapterMockTransformer =
102 * new SDNCAdapterMockTransformer();
105 public class WorkflowTest {
107 public final ProcessEngineRule processEngineRule = new ProcessEngineRule();
110 public final WireMockRule wireMockRule;
115 public WorkflowTest() throws RuntimeException {
116 // Process WorkflowTestTransformer annotations
117 List<ResponseTransformer> transformerList = new ArrayList<ResponseTransformer>();
119 for (Field field : getClass().getFields()) {
120 WorkflowTestTransformer annotation = (WorkflowTestTransformer)
121 field.getAnnotation(WorkflowTestTransformer.class);
123 if (annotation == null) {
127 if (!Modifier.isStatic(field.getModifiers())) {
128 throw new RuntimeException(field.getDeclaringClass().getName()
129 + "#" + field.getName() + " has a @WorkflowTestTransformer "
130 + " annotation but it is not declared static");
133 ResponseTransformer transformer;
136 transformer = (ResponseTransformer) field.get(null);
137 } catch (IllegalAccessException e) {
138 throw new RuntimeException(field.getDeclaringClass().getName()
139 + "#" + field.getName() + " is not accessible", e);
140 } catch (ClassCastException e) {
141 throw new RuntimeException(field.getDeclaringClass().getName()
142 + "#" + field.getName() + " is not a ResponseTransformer", e);
145 if (transformer == null) {
149 transformerList.add(transformer);
152 ResponseTransformer[] transformerArray =
153 transformerList.toArray(new ResponseTransformer[transformerList.size()]);
155 wireMockRule = new WireMockRule(WireMockConfiguration.wireMockConfig()
156 .port(28090).extensions(transformerArray));
160 public void testSetup() throws Exception {
161 CamundaDBSetup.configure();
162 PropertyConfigurationSetup.init();
166 * The current request ID. Normally set when an "invoke" method is called.
168 protected volatile String msoRequestId = null;
171 * The current service instance ID. Normally set when an "invoke" method
174 protected volatile String msoServiceInstanceId = null;
177 * Logs a test start method.
179 protected void logStart() {
180 StackTraceElement[] st = Thread.currentThread().getStackTrace();
181 String method = st[2].getMethodName();
182 System.out.println("STARTED TEST: " + method);
186 * Logs a test end method.
188 protected void logEnd() {
189 StackTraceElement[] st = Thread.currentThread().getStackTrace();
190 String method = st[2].getMethodName();
191 System.out.println("ENDED TEST: " + method);
195 * Invokes a subprocess.
196 * @param processKey the process key
197 * @param businessKey a unique key that will identify the process instance
198 * @param injectedVariables variables to inject into the process
200 protected void invokeSubProcess(String processKey, String businessKey,
201 Map<String, Object> injectedVariables) {
202 RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
203 List<String> arguments = runtimeMxBean.getInputArguments();
204 System.out.println("JVM args = " + arguments);
206 msoRequestId = (String) injectedVariables.get("mso-request-id");
208 if (msoRequestId == null) {
209 String msg = "mso-request-id variable was not provided";
210 System.out.println(msg);
214 // Note: some scenarios don't have a service-instance-id, may be null
215 msoServiceInstanceId = (String) injectedVariables.get("mso-service-instance-id");
217 RuntimeService runtimeService = processEngineRule.getRuntimeService();
218 runtimeService.startProcessInstanceByKey(processKey, businessKey, injectedVariables);
222 * Invokes an asynchronous process.
223 * Errors are handled with junit assertions and will cause the test to fail.
224 * @param processKey the process key
225 * @param schemaVersion the API schema version, e.g. "v1"
226 * @param businessKey a unique key that will identify the process instance
227 * @param request the request
228 * @return a TestAsyncResponse object associated with the test
230 protected TestAsyncResponse invokeAsyncProcess(String processKey,
231 String schemaVersion, String businessKey, String request) {
232 return invokeAsyncProcess(processKey, schemaVersion, businessKey, request, null);
236 * Invokes an asynchronous process.
237 * Errors are handled with junit assertions and will cause the test to fail.
238 * @param processKey the process key
239 * @param schemaVersion the API schema version, e.g. "v1"
240 * @param businessKey a unique key that will identify the process instance
241 * @param request the request
242 * @param injectedVariables optional variables to inject into the process
243 * @return a TestAsyncResponse object associated with the test
245 public TestAsyncResponse invokeAsyncProcess(String processKey,
246 String schemaVersion, String businessKey, String request,
247 Map<String, Object> injectedVariables) {
249 RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
250 List<String> arguments = runtimeMxBean.getInputArguments();
251 System.out.println("JVM args = " + arguments);
253 Map<String, Object> variables = createVariables(schemaVersion, businessKey,
254 request, injectedVariables, false);
255 VariableMapImpl variableMapImpl = createVariableMapImpl(variables);
257 System.out.println("Sending " + request + " to " + processKey + " process");
258 WorkflowAsyncCommonResource workflowResource = new WorkflowAsyncCommonResource();
259 workflowResource.setProcessEngineServices4junit(processEngineRule);
261 TestAsyncResponse asyncResponse = new TestAsyncResponse();
262 workflowResource.startProcessInstanceByKey(asyncResponse, processKey, variableMapImpl);
263 return asyncResponse;
267 * Invokes an asynchronous process.
268 * Errors are handled with junit assertions and will cause the test to fail.
269 * @param processKey the process key
270 * @param schemaVersion the API schema version, e.g. "v1"
271 * @param businessKey a unique key that will identify the process instance
272 * @param request the request
273 * @param injectedVariables optional variables to inject into the process
274 * @param serviceInstantiationModel indicates whether this method is being
275 * invoked for a flow that is designed using the service instantiation model
276 * @return a TestAsyncResponse object associated with the test
278 protected TestAsyncResponse invokeAsyncProcess(String processKey,
279 String schemaVersion, String businessKey, String request,
280 Map<String, Object> injectedVariables, boolean serviceInstantiationModel) {
282 RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
283 List<String> arguments = runtimeMxBean.getInputArguments();
284 System.out.println("JVM args = " + arguments);
286 Map<String, Object> variables = createVariables(schemaVersion, businessKey,
287 request, injectedVariables, serviceInstantiationModel);
288 VariableMapImpl variableMapImpl = createVariableMapImpl(variables);
290 System.out.println("Sending " + request + " to " + processKey + " process");
291 WorkflowAsyncCommonResource workflowResource = new WorkflowAsyncCommonResource();
292 workflowResource.setProcessEngineServices4junit(processEngineRule);
294 TestAsyncResponse asyncResponse = new TestAsyncResponse();
295 workflowResource.startProcessInstanceByKey(asyncResponse, processKey, variableMapImpl);
296 return asyncResponse;
300 * Private helper method that creates a variable map for a request.
301 * Errors are handled with junit assertions and will cause the test to fail.
302 * @param schemaVersion the API schema version, e.g. "v1"
303 * @param businessKey a unique key that will identify the process instance
304 * @param request the request
305 * @param injectedVariables optional variables to inject into the process
306 * @param serviceInstantiationModel indicates whether this method is being
307 * invoked for a flow that is designed using the service instantiation model
308 * @return a variable map
310 private Map<String, Object> createVariables(String schemaVersion,
311 String businessKey, String request, Map<String, Object> injectedVariables,
312 boolean serviceInstantiationModel) {
314 Map<String, Object> variables = new HashMap<String, Object>();
316 // These variables may be overridded by injected variables.
317 variables.put("mso-service-request-timeout", "180");
318 variables.put("isDebugLogEnabled", "true");
320 // These variables may not be overridded by injected variables.
321 String[] notAllowed = new String[] {
322 "mso-schema-version",
326 "mso-service-instance-id"
329 if (injectedVariables != null) {
330 for (String key : injectedVariables.keySet()) {
331 for (String var : notAllowed) {
332 if (var.equals(key)) {
333 String msg = "Cannot specify " + var + " in injected variables";
334 System.out.println(msg);
339 variables.put(key, injectedVariables.get(key));
343 variables.put("mso-schema-version", schemaVersion);
344 variables.put("mso-business-key", businessKey);
345 variables.put("bpmnRequest", request);
347 if (serviceInstantiationModel) {
350 * The request ID and the service instance ID are generated for flows
351 * that follow the service instantiation model unless "requestId" and
352 * "serviceInstanceId" are injected variables.
356 msoRequestId = (String) injectedVariables.get("requestId");
357 variables.put("mso-request-id", msoRequestId);
358 msoServiceInstanceId = (String) injectedVariables.get("serviceInstanceId");
359 variables.put("mso-service-instance-id", msoServiceInstanceId);
363 if (msoRequestId == null || msoRequestId.trim().equals("")) {
364 System.out.println("No requestId element in injectedVariables");
365 variables.put("mso-request-id", UUID.randomUUID().toString());
367 if (msoServiceInstanceId == null || msoServiceInstanceId.trim().equals("")) {
368 System.out.println("No seviceInstanceId element in injectedVariables");
369 variables.put("mso-service-instance-id", UUID.randomUUID().toString());
373 msoRequestId = getXMLTextElement(request, "request-id");
375 if (msoRequestId == null) {
376 //check in injected variables
378 msoRequestId = (String) injectedVariables.get("requestId");
382 if (msoRequestId == null || msoRequestId.trim().equals("")) {
383 String msg = "No request-id element in " + request;
384 System.out.println(msg);
389 variables.put("mso-request-id", msoRequestId);
391 // Note: some request types don't have a service-instance-id
392 msoServiceInstanceId = getXMLTextElement(request, "service-instance-id");
394 if (msoServiceInstanceId != null) {
395 variables.put("mso-service-instance-id", msoServiceInstanceId);
403 * Private helper method that creates a camunda VariableMapImpl from a simple
405 * @param variables the simple variable map
406 * @return a VariableMap
408 private VariableMapImpl createVariableMapImpl(Map<String, Object> variables) {
409 Map<String, Object> wrappedVariables = new HashMap<String, Object>();
411 for (String key : variables.keySet()) {
412 Object value = variables.get(key);
413 wrappedVariables.put(key, wrapVariableValue(value));
416 VariableMapImpl variableMapImpl = new VariableMapImpl();
417 variableMapImpl.put("variables", wrappedVariables);
418 return variableMapImpl;
422 * Private helper method that wraps a variable value for inclusion in a
423 * camunda VariableMapImpl.
424 * @param value the variable value
425 * @return the wrapped variable
427 private Map<String, Object> wrapVariableValue(Object value) {
428 HashMap<String, Object> valueMap = new HashMap<String, Object>();
429 valueMap.put("value", value);
434 * Receives a response from an asynchronous process.
435 * Errors are handled with junit assertions and will cause the test to fail.
436 * @param businessKey the process business key
437 * @param asyncResponse the TestAsyncResponse object associated with the test
438 * @param timeout the timeout in milliseconds
439 * @return the WorkflowResponse
441 public WorkflowResponse receiveResponse(String businessKey,
442 TestAsyncResponse asyncResponse, long timeout) {
443 System.out.println("Waiting " + timeout + "ms for process with business key " + businessKey
444 + " to send a response");
446 long now = System.currentTimeMillis() + timeout;
447 long endTime = now + timeout;
449 while (now <= endTime) {
450 Response response = asyncResponse.getResponse();
452 if (response != null) {
453 System.out.println("Received a response from process with business key " + businessKey);
455 Object entity = response.getEntity();
457 if (!(entity instanceof WorkflowResponse)) {
458 String msg = "Response entity is " +
459 (entity == null ? "null" : entity.getClass().getName()) +
460 ", expected WorkflowResponse";
461 System.out.println(msg);
463 return null; // unreachable
466 return (WorkflowResponse) entity;
471 } catch (InterruptedException e) {
472 String msg = "Interrupted waiting for a response from process with business key " +
474 System.out.println(msg);
476 return null; // unreachable
479 now = System.currentTimeMillis();
482 String msg = "No response received from process with business key " + businessKey +
483 " within " + timeout + "ms";
484 System.out.println(msg);
485 fail("Process with business key " + businessKey + " did not end within 10000ms");
486 return null; // unreachable
490 * Runs a program to inject SDNC callback data into the test environment.
491 * A program is essentially just a list of keys that identify callback data
492 * to be injected, in sequence. An example program:
494 * reserve, assign, delete:ERR
496 * Errors are handled with junit assertions and will cause the test to fail.
497 * @param callbacks an object containing callback data for the program
498 * @param program the program to execute
500 protected void injectSDNCRestCallbacks(CallbackSet callbacks, String program) {
502 String[] cmds = program.replaceAll("\\s+", "").split(",");
504 for (String cmd : cmds) {
506 String modifier = "STD";
508 if (cmd.contains(":")) {
509 String[] parts = cmd.split(":");
514 String content = null;
516 if ("STD".equals(modifier)) {
517 content = callbacks.get(action);
519 if (content == null) {
520 String msg = "No callback defined for '" + action + "' SDNC request";
521 System.out.println(msg);
524 } else if ("ERR".equals(modifier)) {
525 content = "{\"SDNCServiceError\":{\"sdncRequestId\":\"((REQUEST-ID))\",\"responseCode\":\"500\",\"responseMessage\":\"SIMULATED ERROR FROM SDNC ADAPTER\",\"ackFinalIndicator\":\"Y\"}}";
527 String msg = "Invalid SDNC program modifier: '" + modifier + "'";
528 System.out.println(msg);
532 if (!injectSDNCRestCallback(content, 10000)) {
533 fail("Failed to inject SDNC '" + action + "' callback");
538 } catch (InterruptedException e) {
539 fail("Interrupted after injection of SDNC '" + action + "' callback");
545 * Runs a program to inject SDNC events into the test environment.
546 * A program is essentially just a list of keys that identify event data
547 * to be injected, in sequence. An example program:
551 * Errors are handled with junit assertions and will cause the test to fail.
552 * Defaults the Event Type to "SDNCAEvent" for backward compatibility.
553 * @param callbacks an object containing event data for the program
554 * @param program the program to execute
556 protected void injectSDNCEvents(CallbackSet callbacks, String program) {
557 injectSDNCEvents(callbacks, program, "SDNCAEvent");
561 * Runs a program to inject SDNC events into the test environment.
562 * A program is essentially just a list of keys that identify event data
563 * to be injected, in sequence. An example program:
567 * Errors are handled with junit assertions and will cause the test to fail.
568 * @param callbacks an object containing event data for the program
569 * @param program the program to execute
570 * @param eventType (i.e. "SDNCAEvent", "SNIROResponse", etc.)
572 protected void injectSDNCEvents(CallbackSet callbacks, String program, String eventType) {
574 String[] cmds = program.replaceAll("\\s+", "").split(",");
576 for (String cmd : cmds) {
578 String modifier = "STD";
580 if (cmd.contains(":")) {
581 String[] parts = cmd.split(":");
586 String content = null;
588 if ("STD".equals(modifier)) {
589 content = callbacks.get(action);
591 if (content == null) {
592 String msg = "No SDNC event callback defined for '" + action + "'";
593 System.out.println(msg);
597 String msg = "Invalid SDNC program modifier: '" + modifier + "'";
598 System.out.println(msg);
602 if (!injectWorkflowMessage(eventType, content, 10000)) {
603 fail("Failed to inject SDNC '" + action + "' event");
608 } catch (InterruptedException e) {
609 fail("Interrupted after injection of SDNC '" + action + "' event");
615 * Runs a program to inject SDNC callback data into the test environment.
616 * A program is essentially just a list of keys that identify callback data
617 * to be injected, in sequence. An example program:
619 * reserve, assign, delete:ERR
621 * Errors are handled with junit assertions and will cause the test to fail.
622 * @param callbacks an object containing callback data for the program
623 * @param program the program to execute
625 public void injectSDNCCallbacks(CallbackSet callbacks, String program) {
627 String[] cmds = program.replaceAll("\\s+", "").split(",");
629 for (String cmd : cmds) {
631 String modifier = "STD";
633 if (cmd.contains(":")) {
634 String[] parts = cmd.split(":");
639 String content = null;
641 String respMsg = "OK";
643 if ("STD".equals(modifier)) {
644 content = callbacks.get(action);
646 if (content == null) {
647 String msg = "No callback defined for '" + action + "' SDNC request";
648 System.out.println(msg);
654 } else if ("ERR".equals(modifier)) {
655 content = "<svc-request-id>((REQUEST-ID))</svc-request-id><response-code>500</response-code><response-message>SIMULATED ERROR FROM SDNC ADAPTER</response-message>";
657 respMsg = "SERVER ERROR";
659 String msg = "Invalid SDNC program modifier: '" + modifier + "'";
660 System.out.println(msg);
664 if (!injectSDNCCallback(respCode, respMsg, content, 10000)) {
665 fail("Failed to inject SDNC '" + action + "' callback");
670 } catch (InterruptedException e) {
671 fail("Interrupted after injection of SDNC '" + action + "' callback");
677 * Runs a program to inject VNF adapter REST callback data into the test environment.
678 * A program is essentially just a list of keys that identify callback data
679 * to be injected, in sequence. An example program:
683 * Errors are handled with junit assertions and will cause the test to fail.
684 * @param callbacks an object containing callback data for the program
685 * @param program the program to execute
687 public void injectVNFRestCallbacks(CallbackSet callbacks, String program) {
689 String[] cmds = program.replaceAll("\\s+", "").split(",");
691 for (String cmd : cmds) {
693 String modifier = "STD";
695 if (cmd.contains(":")) {
696 String[] parts = cmd.split(":");
701 String content = null;
703 if ("STD".equals(modifier)) {
704 content = callbacks.get(action);
706 if (content == null) {
707 String msg = "No callback defined for '" + action + "' VNF REST request";
708 System.out.println(msg);
711 } else if ("ERR".equals(modifier)) {
712 content = "SIMULATED ERROR FROM VNF ADAPTER";
714 String msg = "Invalid VNF REST program modifier: '" + modifier + "'";
715 System.out.println(msg);
719 if (!injectVnfAdapterRestCallback(content, 10000)) {
720 fail("Failed to inject VNF REST '" + action + "' callback");
725 } catch (InterruptedException e) {
726 fail("Interrupted after injection of VNF REST '" + action + "' callback");
732 * Runs a program to inject VNF callback data into the test environment.
733 * A program is essentially just a list of keys that identify callback data
734 * to be injected, in sequence. An example program:
736 * createVnf, deleteVnf
738 * Errors are handled with junit assertions and will cause the test to fail.
739 * @param callbacks an object containing callback data for the program
740 * @param program the program to execute
742 protected void injectVNFCallbacks(CallbackSet callbacks, String program) {
744 String[] cmds = program.replaceAll("\\s+", "").split(",");
746 for (String cmd : cmds) {
748 String modifier = "STD";
750 if (cmd.contains(":")) {
751 String[] parts = cmd.split(":");
756 String content = null;
758 if ("STD".equals(modifier)) {
759 content = callbacks.get(action);
761 if (content == null) {
762 String msg = "No callback defined for '" + action + "' VNF request";
763 System.out.println(msg);
767 } else if ("ERR".equals(modifier)) {
768 String msg = "Currently unsupported VNF program modifier: '" + modifier + "'";
769 System.out.println(msg);
772 String msg = "Invalid VNF program modifier: '" + modifier + "'";
773 System.out.println(msg);
777 boolean injected = false;
779 if (content.contains("createVnfNotification")) {
780 injected = injectCreateVNFCallback(content, 10000);
781 } else if (content.contains("deleteVnfNotification")) {
782 injected = injectDeleteVNFCallback(content, 10000);
783 } else if (content.contains("updateVnfNotification")) {
784 injected = injectUpdateVNFCallback(content, 10000);
788 String msg = "Failed to inject VNF '" + action + "' callback";
789 System.out.println(msg);
795 } catch (InterruptedException e) {
796 fail("Interrupted after injection of VNF '" + action + "' callback");
802 * Waits for the number of running processes with the specified process
803 * definition key to equal a particular count.
804 * @param processKey the process definition key
805 * @param count the desired count
806 * @param timeout the timeout in milliseconds
808 public void waitForRunningProcessCount(String processKey, int count, long timeout) {
809 System.out.println("Waiting " + timeout + "ms for there to be " + count + " "
810 + processKey + " instances");
812 long now = System.currentTimeMillis() + timeout;
813 long endTime = now + timeout;
816 while (now <= endTime) {
817 int actual = processEngineRule.getRuntimeService()
818 .createProcessInstanceQuery()
819 .processDefinitionKey(processKey)
822 if (actual != last) {
823 System.out.println("There are now " + actual + " "
824 + processKey + " instances");
828 if (actual == count) {
834 } catch (InterruptedException e) {
835 String msg = "Interrupted waiting for there to be " + count + " "
836 + processKey + " instances";
837 System.out.println(msg);
841 now = System.currentTimeMillis();
844 String msg = "Timed out waiting for there to be " + count + " "
845 + processKey + " instances";
846 System.out.println(msg);
851 * Waits for the specified process variable to be set.
852 * @param processKey the process definition key
853 * @param variable the variable name
854 * @param timeout the timeout in milliseconds
855 * @return the variable value, or null if it cannot be obtained
856 * in the specified time
858 protected Object getProcessVariable(String processKey, String variable,
861 System.out.println("Waiting " + timeout + "ms for "
862 + processKey + "." + variable + " to be set");
864 long now = System.currentTimeMillis() + timeout;
865 long endTime = now + timeout;
867 ProcessInstance processInstance = null;
870 while (value == null) {
872 if (processInstance == null) {
873 System.out.println("Timed out waiting for "
874 + processKey + " to start");
876 System.out.println("Timed out waiting for "
877 + processKey + "[" + processInstance.getId()
878 + "]." + variable + " to be set");
884 if (processInstance == null) {
885 processInstance = processEngineRule.getRuntimeService()
886 .createProcessInstanceQuery()
887 .processDefinitionKey(processKey)
891 if (processInstance != null) {
892 value = processEngineRule.getRuntimeService()
893 .getVariable(processInstance.getId(), variable);
898 } catch (InterruptedException e) {
899 System.out.println("Interrupted waiting for "
900 + processKey + "." + variable + " to be set");
904 now = System.currentTimeMillis();
907 System.out.println(processKey + "["
908 + processInstance.getId() + "]." + variable + "="
915 * Injects a single SDNC adapter callback request. The specified callback data
916 * may contain the placeholder string ((REQUEST-ID)) which is replaced with
917 * the actual SDNC request ID. Note: this is not the requestId in the original
919 * @param content the content of the callback
920 * @param timeout the timeout in milliseconds
921 * @return true if the callback could be injected, false otherwise
923 protected boolean injectSDNCRestCallback(String content, long timeout) {
924 String sdncRequestId = (String) getProcessVariable("SDNCAdapterRestV1",
925 "SDNCAResponse_CORRELATOR", timeout);
927 if (sdncRequestId == null) {
931 content = content.replace("((REQUEST-ID))", sdncRequestId);
932 // Deprecated usage. All test code should switch to the (( ... )) syntax.
933 content = content.replace("{{REQUEST-ID}}", sdncRequestId);
935 System.out.println("Injecting SDNC adapter callback");
936 WorkflowMessageResource workflowMessageResource = new WorkflowMessageResource();
937 workflowMessageResource.setProcessEngineServices4junit(processEngineRule);
938 Response response = workflowMessageResource.deliver("SDNCAResponse", sdncRequestId, content);
939 System.out.println("Workflow response to SDNC adapter callback: " + response);
944 * Injects a single SDNC adapter callback request. The specified callback data
945 * may contain the placeholder string ((REQUEST-ID)) which is replaced with
946 * the actual SDNC request ID. Note: this is not the requestId in the original
948 * @param content the content of the callback
949 * @param respCode the response code (normally 200)
950 * @param respMsg the response message (normally "OK")
951 * @param timeout the timeout in milliseconds
952 * @return true if the callback could be injected, false otherwise
954 protected boolean injectSDNCCallback(int respCode, String respMsg,
955 String content, long timeout) {
957 String sdncRequestId = (String) getProcessVariable("sdncAdapter",
958 "SDNCA_requestId", timeout);
960 if (sdncRequestId == null) {
964 content = content.replace("((REQUEST-ID))", sdncRequestId);
965 // Deprecated usage. All test code should switch to the (( ... )) syntax.
966 content = content.replace("{{REQUEST-ID}}", sdncRequestId);
968 System.out.println("Injecting SDNC adapter callback");
969 CallbackHeader callbackHeader = new CallbackHeader();
970 callbackHeader.setRequestId(sdncRequestId);
971 callbackHeader.setResponseCode(String.valueOf(respCode));
972 callbackHeader.setResponseMessage(respMsg);
973 SDNCAdapterCallbackRequest sdncAdapterCallbackRequest = new SDNCAdapterCallbackRequest();
974 sdncAdapterCallbackRequest.setCallbackHeader(callbackHeader);
975 sdncAdapterCallbackRequest.setRequestData(content);
976 SDNCAdapterCallbackServiceImpl callbackService = new SDNCAdapterCallbackServiceImpl();
977 callbackService.setProcessEngineServices4junit(processEngineRule);
978 SDNCAdapterResponse sdncAdapterResponse = callbackService.sdncAdapterCallback(sdncAdapterCallbackRequest);
979 System.out.println("Workflow response to SDNC adapter callback: " + sdncAdapterResponse);
985 * Injects a single VNF adapter callback request. The specified callback data
986 * may contain the placeholder string ((MESSAGE-ID)) which is replaced with
987 * the actual message ID. Note: this is not the requestId in the original
989 * @param content the content of the callback
990 * @param timeout the timeout in milliseconds
991 * @return true if the callback could be injected, false otherwise
993 protected boolean injectVnfAdapterRestCallback(String content, long timeout) {
994 String messageId = (String) getProcessVariable("vnfAdapterRestV1",
995 "VNFAResponse_CORRELATOR", timeout);
997 if (messageId == null) {
1001 content = content.replace("((MESSAGE-ID))", messageId);
1002 // Deprecated usage. All test code should switch to the (( ... )) syntax.
1003 content = content.replace("{{MESSAGE-ID}}", messageId);
1005 System.out.println("Injecting VNF adapter callback");
1006 WorkflowMessageResource workflowMessageResource = new WorkflowMessageResource();
1007 workflowMessageResource.setProcessEngineServices4junit(processEngineRule);
1008 Response response = workflowMessageResource.deliver("VNFAResponse", messageId, content);
1009 System.out.println("Workflow response to VNF adapter callback: " + response);
1014 * Injects a Create VNF adapter callback request. The specified callback data
1015 * may contain the placeholder string ((MESSAGE-ID)) which is replaced with
1016 * the actual message ID. It may also contain the placeholder string
1017 * ((REQUEST-ID)) which is replaced request ID of the original MSO request.
1018 * @param content the content of the callback
1019 * @param timeout the timeout in milliseconds
1020 * @return true if the callback could be injected, false otherwise
1021 * @throws JAXBException if the content does not adhere to the schema
1023 protected boolean injectCreateVNFCallback(String content, long timeout) {
1025 String messageId = (String) getProcessVariable("vnfAdapterCreateV1",
1026 "VNFC_messageId", timeout);
1028 if (messageId == null) {
1032 content = content.replace("((MESSAGE-ID))", messageId);
1033 // Deprecated usage. All test code should switch to the (( ... )) syntax.
1034 content = content.replace("{{MESSAGE-ID}}", messageId);
1036 if(content.contains("((REQUEST-ID))")){
1037 content = content.replace("((REQUEST-ID))", msoRequestId);
1038 // Deprecated usage. All test code should switch to the (( ... )) syntax.
1039 content = content.replace("{{REQUEST-ID}}", msoRequestId);
1042 System.out.println("Injecting VNF adapter callback");
1044 // Is it possible to unmarshal this with JAXB? I couldn't.
1046 CreateVnfNotification createVnfNotification = new CreateVnfNotification();
1047 XPathTool xpathTool = new VnfNotifyXPathTool();
1048 xpathTool.setXML(content);
1051 String completed = xpathTool.evaluate(
1052 "/tns:createVnfNotification/tns:completed/text()");
1053 createVnfNotification.setCompleted("true".equals(completed));
1055 String vnfId = xpathTool.evaluate(
1056 "/tns:createVnfNotification/tns:vnfId/text()");
1057 createVnfNotification.setVnfId(vnfId);
1059 NodeList entries = (NodeList) xpathTool.evaluate(
1060 "/tns:createVnfNotification/tns:outputs/tns:entry",
1061 XPathConstants.NODESET);
1063 CreateVnfNotificationOutputs outputs = new CreateVnfNotificationOutputs();
1065 for (int i = 0; i < entries.getLength(); i++) {
1066 Node node = entries.item(i);
1068 if (node.getNodeType() == Node.ELEMENT_NODE) {
1069 Element entry = (Element) node;
1070 String key = entry.getElementsByTagNameNS("*", "key").item(0).getTextContent();
1071 String value = entry.getElementsByTagNameNS("*", "value").item(0).getTextContent();
1072 outputs.add(key, value);
1076 createVnfNotification.setOutputs(outputs);
1078 VnfRollback rollback = new VnfRollback();
1080 String cloudSiteId = xpathTool.evaluate(
1081 "/tns:createVnfNotification/tns:rollback/tns:cloudSiteId/text()");
1082 rollback.setCloudSiteId(cloudSiteId);
1084 String requestId = xpathTool.evaluate(
1085 "/tns:createVnfNotification/tns:rollback/tns:msoRequest/tns:requestId/text()");
1086 String serviceInstanceId = xpathTool.evaluate(
1087 "/tns:createVnfNotification/tns:rollback/tns:msoRequest/tns:serviceInstanceId/text()");
1089 if (requestId != null || serviceInstanceId != null) {
1090 MsoRequest msoRequest = new MsoRequest();
1091 msoRequest.setRequestId(requestId);
1092 msoRequest.setServiceInstanceId(serviceInstanceId);
1093 rollback.setMsoRequest(msoRequest);
1096 String tenantCreated = xpathTool.evaluate(
1097 "/tns:createVnfNotification/tns:rollback/tns:tenantCreated/text()");
1098 rollback.setTenantCreated("true".equals(tenantCreated));
1100 String tenantId = xpathTool.evaluate(
1101 "/tns:createVnfNotification/tns:rollback/tns:tenantId/text()");
1102 rollback.setTenantId(tenantId);
1104 String vnfCreated = xpathTool.evaluate(
1105 "/tns:createVnfNotification/tns:rollback/tns:vnfCreated/text()");
1106 rollback.setVnfCreated("true".equals(vnfCreated));
1108 String rollbackVnfId = xpathTool.evaluate(
1109 "/tns:createVnfNotification/tns:rollback/tns:vnfId/text()");
1110 rollback.setVnfId(rollbackVnfId);
1112 createVnfNotification.setRollback(rollback);
1114 } catch (Exception e) {
1115 System.out.println("Failed to unmarshal VNF callback content:");
1116 System.out.println(content);
1120 VnfAdapterNotifyServiceImpl notifyService = new VnfAdapterNotifyServiceImpl();
1121 notifyService.setProcessEngineServices4junit(processEngineRule);
1123 notifyService.createVnfNotification(
1125 createVnfNotification.isCompleted(),
1126 createVnfNotification.getException(),
1127 createVnfNotification.getErrorMessage(),
1128 createVnfNotification.getVnfId(),
1129 createVnfNotification.getOutputs(),
1130 createVnfNotification.getRollback());
1136 * Injects a Delete VNF adapter callback request. The specified callback data
1137 * may contain the placeholder string ((MESSAGE-ID)) which is replaced with
1138 * the actual message ID. It may also contain the placeholder string
1139 * ((REQUEST-ID)) which is replaced request ID of the original MSO request.
1140 * @param content the content of the callback
1141 * @param timeout the timeout in milliseconds
1142 * @return true if the callback could be injected, false otherwise
1143 * @throws JAXBException if the content does not adhere to the schema
1145 protected boolean injectDeleteVNFCallback(String content, long timeout) {
1147 String messageId = (String) getProcessVariable("vnfAdapterDeleteV1",
1148 "VNFDEL_uuid", timeout);
1150 if (messageId == null) {
1154 content = content.replace("((MESSAGE-ID))", messageId);
1155 // Deprecated usage. All test code should switch to the (( ... )) syntax.
1156 content = content.replace("{{MESSAGE-ID}}", messageId);
1158 System.out.println("Injecting VNF adapter delete callback");
1160 // Is it possible to unmarshal this with JAXB? I couldn't.
1162 DeleteVnfNotification deleteVnfNotification = new DeleteVnfNotification();
1163 XPathTool xpathTool = new VnfNotifyXPathTool();
1164 xpathTool.setXML(content);
1167 String completed = xpathTool.evaluate(
1168 "/tns:deleteVnfNotification/tns:completed/text()");
1169 deleteVnfNotification.setCompleted("true".equals(completed));
1170 // if notification failure, set the exception and error message
1171 if (deleteVnfNotification.isCompleted() == false) {
1172 deleteVnfNotification.setException(MsoExceptionCategory.INTERNAL);
1173 deleteVnfNotification.setErrorMessage(xpathTool.evaluate(
1174 "/tns:deleteVnfNotification/tns:errorMessage/text()")) ;
1177 } catch (Exception e) {
1178 System.out.println("Failed to unmarshal VNF Delete callback content:");
1179 System.out.println(content);
1183 VnfAdapterNotifyServiceImpl notifyService = new VnfAdapterNotifyServiceImpl();
1184 notifyService.setProcessEngineServices4junit(processEngineRule);
1186 notifyService.deleteVnfNotification(
1188 deleteVnfNotification.isCompleted(),
1189 deleteVnfNotification.getException(),
1190 deleteVnfNotification.getErrorMessage());
1196 * Injects a Update VNF adapter callback request. The specified callback data
1197 * may contain the placeholder string ((MESSAGE-ID)) which is replaced with
1198 * the actual message ID. It may also contain the placeholder string
1199 * ((REQUEST-ID)) which is replaced request ID of the original MSO request.
1200 * @param content the content of the callback
1201 * @param timeout the timeout in milliseconds
1202 * @return true if the callback could be injected, false otherwise
1203 * @throws JAXBException if the content does not adhere to the schema
1205 protected boolean injectUpdateVNFCallback(String content, long timeout) {
1207 String messageId = (String) getProcessVariable("vnfAdapterUpdate",
1208 "VNFU_messageId", timeout);
1210 if (messageId == null) {
1214 content = content.replace("((MESSAGE-ID))", messageId);
1215 // Deprecated usage. All test code should switch to the (( ... )) syntax.
1216 content = content.replace("{{MESSAGE-ID}}", messageId);
1218 content = content.replace("((REQUEST-ID))", msoRequestId);
1219 // Deprecated usage. All test code should switch to the (( ... )) syntax.
1220 content = content.replace("{{REQUEST-ID}}", msoRequestId);
1222 System.out.println("Injecting VNF adapter callback");
1224 // Is it possible to unmarshal this with JAXB? I couldn't.
1226 UpdateVnfNotification updateVnfNotification = new UpdateVnfNotification();
1227 XPathTool xpathTool = new VnfNotifyXPathTool();
1228 xpathTool.setXML(content);
1231 String completed = xpathTool.evaluate(
1232 "/tns:updateVnfNotification/tns:completed/text()");
1233 updateVnfNotification.setCompleted("true".equals(completed));
1235 NodeList entries = (NodeList) xpathTool.evaluate(
1236 "/tns:updateVnfNotification/tns:outputs/tns:entry",
1237 XPathConstants.NODESET);
1239 UpdateVnfNotificationOutputs outputs = new UpdateVnfNotificationOutputs();
1241 for (int i = 0; i < entries.getLength(); i++) {
1242 Node node = entries.item(i);
1244 if (node.getNodeType() == Node.ELEMENT_NODE) {
1245 Element entry = (Element) node;
1246 String key = entry.getElementsByTagNameNS("*", "key").item(0).getTextContent();
1247 String value = entry.getElementsByTagNameNS("*", "value").item(0).getTextContent();
1248 outputs.add(key, value);
1252 updateVnfNotification.setOutputs(outputs);
1254 VnfRollback rollback = new VnfRollback();
1256 String cloudSiteId = xpathTool.evaluate(
1257 "/tns:updateVnfNotification/tns:rollback/tns:cloudSiteId/text()");
1258 rollback.setCloudSiteId(cloudSiteId);
1260 String requestId = xpathTool.evaluate(
1261 "/tns:updateVnfNotification/tns:rollback/tns:msoRequest/tns:requestId/text()");
1262 String serviceInstanceId = xpathTool.evaluate(
1263 "/tns:updateVnfNotification/tns:rollback/tns:msoRequest/tns:serviceInstanceId/text()");
1265 if (requestId != null || serviceInstanceId != null) {
1266 MsoRequest msoRequest = new MsoRequest();
1267 msoRequest.setRequestId(requestId);
1268 msoRequest.setServiceInstanceId(serviceInstanceId);
1269 rollback.setMsoRequest(msoRequest);
1272 String tenantCreated = xpathTool.evaluate(
1273 "/tns:updateVnfNotification/tns:rollback/tns:tenantCreated/text()");
1274 rollback.setTenantCreated("true".equals(tenantCreated));
1276 String tenantId = xpathTool.evaluate(
1277 "/tns:updateVnfNotification/tns:rollback/tns:tenantId/text()");
1278 rollback.setTenantId(tenantId);
1280 String vnfCreated = xpathTool.evaluate(
1281 "/tns:updateVnfNotification/tns:rollback/tns:vnfCreated/text()");
1282 rollback.setVnfCreated("true".equals(vnfCreated));
1284 String rollbackVnfId = xpathTool.evaluate(
1285 "/tns:updateVnfNotification/tns:rollback/tns:vnfId/text()");
1286 rollback.setVnfId(rollbackVnfId);
1288 updateVnfNotification.setRollback(rollback);
1290 } catch (Exception e) {
1291 System.out.println("Failed to unmarshal VNF callback content:");
1292 System.out.println(content);
1296 VnfAdapterNotifyServiceImpl notifyService = new VnfAdapterNotifyServiceImpl();
1297 notifyService.setProcessEngineServices4junit(processEngineRule);
1299 notifyService.updateVnfNotification(
1301 updateVnfNotification.isCompleted(),
1302 updateVnfNotification.getException(),
1303 updateVnfNotification.getErrorMessage(),
1304 updateVnfNotification.getOutputs(),
1305 updateVnfNotification.getRollback());
1311 * Injects a workflow message. The specified callback data may contain the
1312 * placeholder string ((CORRELATOR)) which is replaced with the actual
1314 * @param content the message type
1315 * @param content the message content
1316 * @param timeout the timeout in milliseconds
1317 * @return true if the event could be injected, false otherwise
1319 protected boolean injectWorkflowMessage(String messageType, String content, long timeout) {
1320 String correlator = (String) getProcessVariable("ReceiveWorkflowMessage",
1321 messageType + "_CORRELATOR", timeout);
1323 if (correlator == null) {
1327 content = content.replace("((CORRELATOR))", correlator);
1329 System.out.println("Injecting " + messageType + " message");
1330 WorkflowMessageResource workflowMessageResource = new WorkflowMessageResource();
1331 workflowMessageResource.setProcessEngineServices4junit(processEngineRule);
1332 Response response = workflowMessageResource.deliver(messageType, correlator, content);
1333 System.out.println("Workflow response to " + messageType + " message: " + response);
1338 * Wait for the process to end.
1339 * @param businessKey the process business key
1340 * @param timeout the amount of time to wait, in milliseconds
1342 public void waitForProcessEnd(String businessKey, long timeout) {
1343 System.out.println("Waiting " + timeout + "ms for process with business key " +
1344 businessKey + " to end");
1346 long now = System.currentTimeMillis() + timeout;
1347 long endTime = now + timeout;
1349 while (now <= endTime) {
1350 if (isProcessEnded(businessKey)) {
1351 System.out.println("Process with business key " + businessKey + " has ended");
1357 } catch (InterruptedException e) {
1358 String msg = "Interrupted waiting for process with business key " +
1359 businessKey + " to end";
1360 System.out.println(msg);
1364 now = System.currentTimeMillis();
1367 String msg = "Process with business key " + businessKey +
1368 " did not end within " + timeout + "ms";
1369 System.out.println(msg);
1374 * Verifies that the specified historic process variable has the specified value.
1375 * If the variable does not have the specified value, the test is failed.
1376 * @param businessKey the process business key
1377 * @param variable the variable name
1378 * @param value the expected variable value
1380 public void checkVariable(String businessKey, String variable, Object value) {
1381 if (!isProcessEnded(businessKey)) {
1382 fail("Cannot get historic variable " + variable + " because process with business key " +
1383 businessKey + " has not ended");
1386 Object variableValue = getVariableFromHistory(businessKey, variable);
1387 assertEquals(value, variableValue);
1391 * Checks to see if the specified process is ended.
1392 * @param businessKey the process business Key
1393 * @return true if the process is ended
1395 protected boolean isProcessEnded(String businessKey) {
1396 HistoricProcessInstance processInstance = processEngineRule.getHistoryService()
1397 .createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
1398 return processInstance != null && processInstance.getEndTime() != null;
1402 * Gets a variable value from a historical process instance.
1403 * @param businessKey the process business key
1404 * @param variableName the variable name
1405 * @return the variable value, or null if the variable could not be
1408 public Object getVariableFromHistory(String businessKey, String variableName) {
1410 HistoricProcessInstance processInstance = processEngineRule.getHistoryService()
1411 .createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
1413 if (processInstance == null) {
1417 HistoricVariableInstance v = processEngineRule.getHistoryService()
1418 .createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId())
1419 .variableName(variableName).singleResult();
1420 return v == null ? null : v.getValue();
1421 } catch (Exception e) {
1422 System.out.println("Error retrieving variable " + variableName +
1423 " from historical process with business key " + businessKey + ": " + e);
1429 * Gets the value of a subflow variable from the specified subflow's
1430 * historical process instance.
1432 * @param subflowName - the name of the subflow that contains the variable
1433 * @param variableName the variable name
1435 * @return the variable value, or null if the variable could not be obtained
1438 protected Object getVariableFromSubflowHistory(String subflowName, String variableName) {
1440 List<HistoricProcessInstance> processInstanceList = processEngineRule.getHistoryService()
1441 .createHistoricProcessInstanceQuery().processDefinitionName(subflowName).list();
1443 Collections.sort(processInstanceList, new Comparator<HistoricProcessInstance>() {
1444 public int compare(HistoricProcessInstance m1, HistoricProcessInstance m2) {
1445 return m1.getStartTime().compareTo(m2.getStartTime());
1449 HistoricProcessInstance processInstance = processInstanceList.get(0);
1451 if (processInstanceList == null) {
1455 HistoricVariableInstance v = processEngineRule.getHistoryService()
1456 .createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId())
1457 .variableName(variableName).singleResult();
1458 return v == null ? null : v.getValue();
1459 } catch (Exception e) {
1460 System.out.println("Error retrieving variable " + variableName +
1461 " from sub flow: " + subflowName + ", Exception is: " + e);
1467 * Gets the value of a subflow variable from the subflow's
1468 * historical process x instance.
1470 * @param subflowName - the name of the subflow that contains the variable
1471 * @param variableName the variable name
1472 * @param subflowInstanceIndex - the instance of the subflow (use when same subflow is called more than once from mainflow)
1474 * @return the variable value, or null if the variable could not be obtained
1476 protected Object getVariableFromSubflowHistory(int subflowInstanceIndex, String subflowName, String variableName) {
1478 List<HistoricProcessInstance> processInstanceList = processEngineRule.getHistoryService()
1479 .createHistoricProcessInstanceQuery().processDefinitionName(subflowName).list();
1481 Collections.sort(processInstanceList, new Comparator<HistoricProcessInstance>() {
1482 public int compare(HistoricProcessInstance m1, HistoricProcessInstance m2) {
1483 return m1.getStartTime().compareTo(m2.getStartTime());
1487 HistoricProcessInstance processInstance = processInstanceList.get(subflowInstanceIndex);
1489 if (processInstanceList == null) {
1493 HistoricVariableInstance v = processEngineRule.getHistoryService()
1494 .createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId())
1495 .variableName(variableName).singleResult();
1496 return v == null ? null : v.getValue();
1497 } catch (Exception e) {
1498 System.out.println("Error retrieving variable " + variableName +
1499 " from " + subflowInstanceIndex + " instance index of sub flow: " + subflowName + ", Exception is: " + e);
1506 * Extracts text from an XML element. This method is not namespace aware
1507 * (namespaces are ignored). The first matching element is selected.
1508 * @param xml the XML document or fragment
1509 * @param tag the desired element, e.g. "<name>"
1510 * @return the element text, or null if the element was not found
1512 protected String getXMLTextElement(String xml, String tag) {
1513 xml = removeXMLNamespaces(xml);
1515 if (!tag.startsWith("<")) {
1516 tag = "<" + tag + ">";
1519 int start = xml.indexOf(tag);
1525 int end = xml.indexOf('<', start + tag.length());
1531 return xml.substring(start + tag.length(), end);
1535 * Removes namespace definitions and prefixes from XML, if any.
1537 private String removeXMLNamespaces(String xml) {
1538 // remove xmlns declaration
1539 xml = xml.replaceAll("xmlns.*?(\"|\').*?(\"|\')", "");
1541 // remove opening tag prefix
1542 xml = xml.replaceAll("(<)(\\w+:)(.*?>)", "$1$3");
1544 // remove closing tags prefix
1545 xml = xml.replaceAll("(</)(\\w+:)(.*?>)", "$1$3");
1547 // remove extra spaces left when xmlns declarations are removed
1548 xml = xml.replaceAll("\\s+>", ">");
1554 * Asserts that two XML documents are semantically equivalent. Differences
1555 * in whitespace or in namespace usage do not affect the comparison.
1556 * @param expected the expected XML
1557 * @param actual the XML to test
1558 * @throws SAXException
1559 * @throws IOException
1561 public static void assertXMLEquals(String expected, String actual)
1562 throws SAXException, IOException {
1563 XMLUnit.setIgnoreWhitespace(true);
1564 XMLUnit.setIgnoreAttributeOrder(true);
1565 DetailedDiff diff = new DetailedDiff(XMLUnit.compareXML(expected, actual));
1566 List<?> allDifferences = diff.getAllDifferences();
1567 assertEquals("Differences found: " + diff.toString(), 0, allDifferences.size());
1571 * A test implementation of AsynchronousResponse.
1573 public class TestAsyncResponse implements AsynchronousResponse {
1574 Response response = null;
1580 public synchronized void setResponse(Response response) {
1581 this.response = response;
1585 * Gets the response.
1586 * @return the response, or null if none has been produced yet
1588 public synchronized Response getResponse() {
1594 * An object that contains callback data for a "program".
1596 public class CallbackSet {
1597 private final Map<String, String> map = new HashMap<String, String>();
1600 * Add callback data to the set.
1601 * @param action the action with which the data is associated
1602 * @param content the callback data
1604 public void put(String action, String content) {
1605 map.put(action, content);
1609 * Retrieve callback data from the set.
1610 * @param action the action with which the data is associated
1611 * @return the callback data, or null if there is none for the specified operation
1613 public String get(String action) {
1614 return map.get(action);
1619 * A tool for evaluating XPath expressions.
1621 protected class XPathTool {
1622 private final DocumentBuilderFactory factory;
1623 private final SimpleNamespaceContext context = new SimpleNamespaceContext();
1624 private final XPath xpath = XPathFactory.newInstance().newXPath();
1625 private String xml = null;
1626 private Document doc = null;
1631 public XPathTool() {
1632 factory = DocumentBuilderFactory.newInstance();
1633 factory.setNamespaceAware(true);
1634 xpath.setNamespaceContext(context);
1639 * @param prefix the namespace prefix
1640 * @param uri the namespace uri
1642 public synchronized void addNamespace(String prefix, String uri) {
1643 context.add(prefix, uri);
1647 * Sets the XML content to be operated on.
1648 * @param xml the XML content
1650 public synchronized void setXML(String xml) {
1656 * Returns the document object.
1657 * @return the document object, or null if XML has not been set
1658 * @throws SAXException
1659 * @throws IOException
1660 * @throws ParserConfigurationException
1662 public synchronized Document getDocument()
1663 throws ParserConfigurationException, IOException, SAXException {
1673 * Evaluates the specified XPath expression and returns a string result.
1674 * This method throws exceptions on error.
1675 * @param expression the expression
1676 * @return the result object
1677 * @throws ParserConfigurationException
1678 * @throws IOException
1679 * @throws SAXException
1680 * @throws XPathExpressionException on error
1682 public synchronized String evaluate(String expression)
1683 throws ParserConfigurationException, SAXException,
1684 IOException, XPathExpressionException {
1685 return (String) evaluate(expression, XPathConstants.STRING);
1689 * Evaluates the specified XPath expression.
1690 * This method throws exceptions on error.
1691 * @param expression the expression
1692 * @param returnType the return type
1693 * @return the result object
1694 * @throws ParserConfigurationException
1695 * @throws IOException
1696 * @throws SAXException
1697 * @throws XPathExpressionException on error
1699 public synchronized Object evaluate(String expression, QName returnType)
1700 throws ParserConfigurationException, SAXException,
1701 IOException, XPathExpressionException {
1704 XPathExpression expr = xpath.compile(expression);
1705 return expr.evaluate(doc, returnType);
1709 * Private helper method that builds the document object.
1710 * Assumes the calling method is synchronized.
1711 * @throws ParserConfigurationException
1712 * @throws IOException
1713 * @throws SAXException
1715 private void buildDocument() throws ParserConfigurationException,
1716 IOException, SAXException {
1719 throw new IOException("XML input is null");
1722 DocumentBuilder builder = factory.newDocumentBuilder();
1723 InputSource source = new InputSource(new StringReader(xml));
1724 doc = builder.parse(source);
1730 * A NamespaceContext class based on a Map.
1732 private class SimpleNamespaceContext implements NamespaceContext {
1733 private Map<String, String> prefixMap = new HashMap<String, String>();
1734 private Map<String, String> uriMap = new HashMap<String, String>();
1736 public synchronized void add(String prefix, String uri) {
1737 prefixMap.put(prefix, uri);
1738 uriMap.put(uri, prefix);
1742 public synchronized String getNamespaceURI(String prefix) {
1743 return prefixMap.get(prefix);
1747 public Iterator<String> getPrefixes(String uri) {
1748 List<String> list = new ArrayList<String>();
1749 String prefix = uriMap.get(uri);
1750 if (prefix != null) {
1753 return list.iterator();
1757 public String getPrefix(String uri) {
1758 return uriMap.get(uri);
1763 * A VnfNotify XPathTool.
1765 protected class VnfNotifyXPathTool extends XPathTool {
1766 public VnfNotifyXPathTool() {
1767 addNamespace("tns", "http://org.openecomp.mso/vnfNotify");
1772 * Helper class to make it easier to create this type.
1774 private static class CreateVnfNotificationOutputs
1775 extends org.openecomp.mso.bpmn.common.adapter.vnf.CreateVnfNotification.Outputs {
1776 public void add(String key, String value) {
1777 Entry entry = new Entry();
1779 entry.setValue(value);
1780 getEntry().add(entry);
1785 * Helper class to make it easier to create this type.
1787 private static class UpdateVnfNotificationOutputs
1788 extends org.openecomp.mso.bpmn.common.adapter.vnf.UpdateVnfNotification.Outputs {
1789 public void add(String key, String value) {
1790 Entry entry = new Entry();
1792 entry.setValue(value);
1793 getEntry().add(entry);