2 * ============LICENSE_START=======================================================
\r
4 * ================================================================================
\r
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * ================================================================================
\r
7 * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * you may not use this file except in compliance with the License.
\r
9 * You may obtain a copy of the License at
\r
11 * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * Unless required by applicable law or agreed to in writing, software
\r
14 * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * See the License for the specific language governing permissions and
\r
17 * limitations under the License.
\r
18 * ============LICENSE_END=========================================================
\r
21 package org.openecomp.mso.bpmn.common;
\r
23 import static org.junit.Assert.assertEquals;
\r
24 import static org.junit.Assert.fail;
\r
25 import static org.openecomp.mso.bpmn.core.json.JsonUtils.getJsonValue;
\r
26 import static org.openecomp.mso.bpmn.core.json.JsonUtils.updJsonValue;
\r
28 import java.io.IOException;
\r
29 import java.io.StringReader;
\r
30 import java.lang.management.ManagementFactory;
\r
31 import java.lang.management.RuntimeMXBean;
\r
32 import java.lang.reflect.Field;
\r
33 import java.lang.reflect.Modifier;
\r
34 import java.util.ArrayList;
\r
35 import java.util.HashMap;
\r
36 import java.util.Iterator;
\r
37 import java.util.List;
\r
38 import java.util.Map;
\r
39 import java.util.UUID;
\r
41 import javax.ws.rs.core.Response;
\r
42 import javax.xml.bind.JAXBException;
\r
43 import javax.xml.namespace.NamespaceContext;
\r
44 import javax.xml.namespace.QName;
\r
45 import javax.xml.parsers.DocumentBuilder;
\r
46 import javax.xml.parsers.DocumentBuilderFactory;
\r
47 import javax.xml.parsers.ParserConfigurationException;
\r
48 import javax.xml.xpath.XPath;
\r
49 import javax.xml.xpath.XPathConstants;
\r
50 import javax.xml.xpath.XPathExpression;
\r
51 import javax.xml.xpath.XPathExpressionException;
\r
52 import javax.xml.xpath.XPathFactory;
\r
54 import org.camunda.bpm.engine.RuntimeService;
\r
55 import org.camunda.bpm.engine.history.HistoricProcessInstance;
\r
56 import org.camunda.bpm.engine.history.HistoricVariableInstance;
\r
57 import org.camunda.bpm.engine.runtime.ProcessInstance;
\r
58 import org.camunda.bpm.engine.test.ProcessEngineRule;
\r
59 import org.camunda.bpm.engine.variable.impl.VariableMapImpl;
\r
60 import org.custommonkey.xmlunit.DetailedDiff;
\r
61 import org.custommonkey.xmlunit.XMLUnit;
\r
62 import org.jboss.resteasy.spi.AsynchronousResponse;
\r
63 import org.json.JSONArray;
\r
64 import org.json.JSONObject;
\r
65 import org.junit.Before;
\r
66 import org.junit.Rule;
\r
67 import org.openecomp.mso.bpmn.common.adapter.sdnc.CallbackHeader;
\r
68 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCAdapterCallbackRequest;
\r
69 import org.openecomp.mso.bpmn.common.adapter.sdnc.SDNCAdapterResponse;
\r
70 import org.openecomp.mso.bpmn.common.adapter.vnf.CreateVnfNotification;
\r
71 import org.openecomp.mso.bpmn.common.adapter.vnf.DeleteVnfNotification;
\r
72 import org.openecomp.mso.bpmn.common.adapter.vnf.MsoExceptionCategory;
\r
73 import org.openecomp.mso.bpmn.common.adapter.vnf.MsoRequest;
\r
74 import org.openecomp.mso.bpmn.common.adapter.vnf.UpdateVnfNotification;
\r
75 import org.openecomp.mso.bpmn.common.adapter.vnf.VnfRollback;
\r
76 import org.openecomp.mso.bpmn.common.workflow.service.SDNCAdapterCallbackServiceImpl;
\r
77 import org.openecomp.mso.bpmn.common.workflow.service.VnfAdapterNotifyServiceImpl;
\r
78 import org.openecomp.mso.bpmn.common.workflow.service.WorkflowAsyncResource;
\r
79 import org.openecomp.mso.bpmn.common.workflow.service.WorkflowMessageResource;
\r
80 import org.openecomp.mso.bpmn.common.workflow.service.WorkflowResponse;
\r
81 import org.openecomp.mso.bpmn.core.PropertyConfigurationSetup;
\r
82 import org.openecomp.mso.bpmn.core.domain.Resource;
\r
83 import org.openecomp.mso.bpmn.core.domain.ServiceDecomposition;
\r
84 import org.openecomp.mso.bpmn.core.utils.CamundaDBSetup;
\r
85 import org.w3c.dom.Document;
\r
86 import org.w3c.dom.Element;
\r
87 import org.w3c.dom.Node;
\r
88 import org.w3c.dom.NodeList;
\r
89 import org.xml.sax.InputSource;
\r
90 import org.xml.sax.SAXException;
\r
92 import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
\r
93 import com.github.tomakehurst.wiremock.extension.ResponseTransformer;
\r
94 import com.github.tomakehurst.wiremock.junit.WireMockRule;
\r
99 * A base class for Workflow tests.
\r
101 * WireMock response transformers may be specified by declaring public
\r
102 * static fields with the @WorkflowTestTransformer annotation. For example:
\r
104 * @WorkflowTestTransformer
\r
105 * public static final ResponseTransformer sdncAdapterMockTransformer =
\r
106 * new SDNCAdapterMockTransformer();
\r
109 public class WorkflowTest {
\r
111 public final ProcessEngineRule processEngineRule = new ProcessEngineRule();
\r
114 public final WireMockRule wireMockRule;
\r
117 * Content-Type for XML.
\r
119 protected static final String XML = "application/xml";
\r
122 * Content-Type for JSON.
\r
124 protected static final String JSON = "application/json; charset=UTF-8";
\r
130 public WorkflowTest() throws RuntimeException {
\r
131 // Process WorkflowTestTransformer annotations
\r
132 List<ResponseTransformer> transformerList = new ArrayList<ResponseTransformer>();
\r
134 for (Field field : getClass().getFields()) {
\r
135 WorkflowTestTransformer annotation = field.getAnnotation(WorkflowTestTransformer.class);
\r
137 if (annotation == null) {
\r
141 if (!Modifier.isStatic(field.getModifiers())) {
\r
142 throw new RuntimeException(field.getDeclaringClass().getName()
\r
143 + "#" + field.getName() + " has a @WorkflowTestTransformer "
\r
144 + " annotation but it is not declared static");
\r
147 ResponseTransformer transformer;
\r
150 transformer = (ResponseTransformer) field.get(null);
\r
151 } catch (IllegalAccessException e) {
\r
152 throw new RuntimeException(field.getDeclaringClass().getName()
\r
153 + "#" + field.getName() + " is not accessible", e);
\r
154 } catch (ClassCastException e) {
\r
155 throw new RuntimeException(field.getDeclaringClass().getName()
\r
156 + "#" + field.getName() + " is not a ResponseTransformer", e);
\r
159 if (transformer == null) {
\r
163 transformerList.add(transformer);
\r
166 ResponseTransformer[] transformerArray =
\r
167 transformerList.toArray(new ResponseTransformer[transformerList.size()]);
\r
169 wireMockRule = new WireMockRule(WireMockConfiguration.wireMockConfig()
\r
170 .port(28090).extensions(transformerArray));
\r
174 public void testSetup() throws Exception {
\r
175 CamundaDBSetup.configure();
\r
176 PropertyConfigurationSetup.init();
\r
180 * The current request ID. Normally set when an "invoke" method is called.
\r
182 protected volatile String msoRequestId = null;
\r
185 * The current service instance ID. Normally set when an "invoke" method
\r
188 protected volatile String msoServiceInstanceId = null;
\r
191 * Logs a test start method.
\r
193 protected void logStart() {
\r
194 StackTraceElement[] st = Thread.currentThread().getStackTrace();
\r
195 String method = st[2].getMethodName();
\r
196 System.out.println("STARTED TEST: " + method);
\r
200 * Logs a test end method.
\r
202 protected void logEnd() {
\r
203 StackTraceElement[] st = Thread.currentThread().getStackTrace();
\r
204 String method = st[2].getMethodName();
\r
205 System.out.println("ENDED TEST: " + method);
\r
209 * Invokes a subprocess.
\r
210 * @param processKey the process key
\r
211 * @param businessKey a unique key that will identify the process instance
\r
212 * @param injectedVariables variables to inject into the process
\r
214 protected void invokeSubProcess(String processKey, String businessKey, Map<String, Object> injectedVariables) {
\r
215 RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
\r
216 List<String> arguments = runtimeMxBean.getInputArguments();
\r
217 System.out.println("JVM args = " + arguments);
\r
219 msoRequestId = (String) injectedVariables.get("mso-request-id");
\r
220 String requestId = (String) injectedVariables.get("msoRequestId");
\r
222 if (msoRequestId == null && requestId == null) {
\r
223 String msg = "mso-request-id variable was not provided";
\r
224 System.out.println(msg);
\r
228 // Note: some scenarios don't have a service-instance-id, may be null
\r
229 msoServiceInstanceId = (String) injectedVariables.get("mso-service-instance-id");
\r
231 RuntimeService runtimeService = processEngineRule.getRuntimeService();
\r
232 runtimeService.startProcessInstanceByKey(processKey, businessKey, injectedVariables);
\r
236 * Invokes an asynchronous process.
\r
237 * Errors are handled with junit assertions and will cause the test to fail.
\r
238 * @param processKey the process key
\r
239 * @param schemaVersion the API schema version, e.g. "v1"
\r
240 * @param businessKey a unique key that will identify the process instance
\r
241 * @param request the request
\r
242 * @return a TestAsyncResponse object associated with the test
\r
244 protected TestAsyncResponse invokeAsyncProcess(String processKey,
\r
245 String schemaVersion, String businessKey, String request) {
\r
246 return invokeAsyncProcess(processKey, schemaVersion, businessKey, request, null);
\r
250 * Invokes an asynchronous process.
\r
251 * Errors are handled with junit assertions and will cause the test to fail.
\r
252 * @param processKey the process key
\r
253 * @param schemaVersion the API schema version, e.g. "v1"
\r
254 * @param businessKey a unique key that will identify the process instance
\r
255 * @param request the request
\r
256 * @param injectedVariables optional variables to inject into the process
\r
257 * @return a TestAsyncResponse object associated with the test
\r
259 protected TestAsyncResponse invokeAsyncProcess(String processKey,
\r
260 String schemaVersion, String businessKey, String request,
\r
261 Map<String, Object> injectedVariables) {
\r
263 RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
\r
264 List<String> arguments = runtimeMxBean.getInputArguments();
\r
265 System.out.println("JVM args = " + arguments);
\r
267 Map<String, Object> variables = createVariables(schemaVersion, businessKey,
\r
268 request, injectedVariables, false);
\r
269 VariableMapImpl variableMapImpl = createVariableMapImpl(variables);
\r
271 System.out.println("Sending " + request + " to " + processKey + " process");
\r
272 WorkflowAsyncResource workflowResource = new WorkflowAsyncResource();
\r
273 workflowResource.setProcessEngineServices4junit(processEngineRule);
\r
275 TestAsyncResponse asyncResponse = new TestAsyncResponse();
\r
276 workflowResource.startProcessInstanceByKey(asyncResponse, processKey, variableMapImpl);
\r
277 return asyncResponse;
\r
281 * Invokes an asynchronous process.
\r
282 * Errors are handled with junit assertions and will cause the test to fail.
\r
283 * @param processKey the process key
\r
284 * @param schemaVersion the API schema version, e.g. "v1"
\r
285 * @param businessKey a unique key that will identify the process instance
\r
286 * @param request the request
\r
287 * @param injectedVariables optional variables to inject into the process
\r
288 * @param serviceInstantiationModel indicates whether this method is being
\r
289 * invoked for a flow that is designed using the service instantiation model
\r
290 * @return a TestAsyncResponse object associated with the test
\r
292 protected TestAsyncResponse invokeAsyncProcess(String processKey,
\r
293 String schemaVersion, String businessKey, String request,
\r
294 Map<String, Object> injectedVariables, boolean serviceInstantiationModel) {
\r
296 RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
\r
297 List<String> arguments = runtimeMxBean.getInputArguments();
\r
298 System.out.println("JVM args = " + arguments);
\r
300 Map<String, Object> variables = createVariables(schemaVersion, businessKey,
\r
301 request, injectedVariables, serviceInstantiationModel);
\r
302 VariableMapImpl variableMapImpl = createVariableMapImpl(variables);
\r
304 System.out.println("Sending " + request + " to " + processKey + " process");
\r
305 WorkflowAsyncResource workflowResource = new WorkflowAsyncResource();
\r
306 workflowResource.setProcessEngineServices4junit(processEngineRule);
\r
308 TestAsyncResponse asyncResponse = new TestAsyncResponse();
\r
309 workflowResource.startProcessInstanceByKey(asyncResponse, processKey, variableMapImpl);
\r
310 return asyncResponse;
\r
314 * Private helper method that creates a variable map for a request.
\r
315 * Errors are handled with junit assertions and will cause the test to fail.
\r
316 * @param schemaVersion the API schema version, e.g. "v1"
\r
317 * @param businessKey a unique key that will identify the process instance
\r
318 * @param request the request
\r
319 * @param injectedVariables optional variables to inject into the process
\r
320 * @param serviceInstantiationModel indicates whether this method is being
\r
321 * invoked for a flow that is designed using the service instantiation model
\r
322 * @return a variable map
\r
324 private Map<String, Object> createVariables(String schemaVersion,
\r
325 String businessKey, String request, Map<String, Object> injectedVariables,
\r
326 boolean serviceInstantiationModel) {
\r
328 Map<String, Object> variables = new HashMap<>();
\r
330 // These variables may be overridded by injected variables.
\r
331 variables.put("mso-service-request-timeout", "180");
\r
332 variables.put("isDebugLogEnabled", "true");
\r
334 // These variables may not be overridded by injected variables.
\r
335 String[] notAllowed = new String[] {
\r
336 "mso-schema-version",
\r
337 "mso-business-key",
\r
340 "mso-service-instance-id"
\r
343 if (injectedVariables != null) {
\r
344 for (String key : injectedVariables.keySet()) {
\r
345 for (String var : notAllowed) {
\r
346 if (var.equals(key)) {
\r
347 String msg = "Cannot specify " + var + " in injected variables";
\r
348 System.out.println(msg);
\r
353 variables.put(key, injectedVariables.get(key));
\r
357 variables.put("mso-schema-version", schemaVersion);
\r
358 variables.put("mso-business-key", businessKey);
\r
359 variables.put("bpmnRequest", request);
\r
361 if (serviceInstantiationModel) {
\r
364 * The request ID and the service instance ID are generated for flows
\r
365 * that follow the service instantiation model unless "requestId" and
\r
366 * "serviceInstanceId" are injected variables.
\r
370 msoRequestId = (String) injectedVariables.get("requestId");
\r
371 variables.put("mso-request-id", msoRequestId);
\r
372 msoServiceInstanceId = (String) injectedVariables.get("serviceInstanceId");
\r
373 variables.put("mso-service-instance-id", msoServiceInstanceId);
\r
375 catch(Exception e) {
\r
377 if (msoRequestId == null || msoRequestId.trim().equals("")) {
\r
378 System.out.println("No requestId element in injectedVariables");
\r
379 variables.put("mso-request-id", UUID.randomUUID().toString());
\r
381 if (msoServiceInstanceId == null || msoServiceInstanceId.trim().equals("")) {
\r
382 System.out.println("No seviceInstanceId element in injectedVariables");
\r
383 variables.put("mso-service-instance-id", UUID.randomUUID().toString());
\r
387 msoRequestId = getXMLTextElement(request, "request-id");
\r
389 if (msoRequestId == null) {
\r
390 //check in injected variables
\r
392 msoRequestId = (String) injectedVariables.get("requestId");
\r
394 catch(Exception e) {
\r
396 if (msoRequestId == null || msoRequestId.trim().equals("")) {
\r
397 String msg = "No request-id element in " + request;
\r
398 System.out.println(msg);
\r
403 variables.put("mso-request-id", msoRequestId);
\r
405 // Note: some request types don't have a service-instance-id
\r
406 msoServiceInstanceId = getXMLTextElement(request, "service-instance-id");
\r
408 if (msoServiceInstanceId != null) {
\r
409 variables.put("mso-service-instance-id", msoServiceInstanceId);
\r
417 * Private helper method that creates a camunda VariableMapImpl from a simple
\r
419 * @param variables the simple variable map
\r
420 * @return a VariableMap
\r
422 private VariableMapImpl createVariableMapImpl(Map<String, Object> variables) {
\r
423 Map<String, Object> wrappedVariables = new HashMap<>();
\r
425 for (String key : variables.keySet()) {
\r
426 Object value = variables.get(key);
\r
427 wrappedVariables.put(key, wrapVariableValue(value));
\r
430 VariableMapImpl variableMapImpl = new VariableMapImpl();
\r
431 variableMapImpl.put("variables", wrappedVariables);
\r
432 return variableMapImpl;
\r
436 * Private helper method that wraps a variable value for inclusion in a
\r
437 * camunda VariableMapImpl.
\r
438 * @param value the variable value
\r
439 * @return the wrapped variable
\r
441 private Map<String, Object> wrapVariableValue(Object value) {
\r
442 HashMap<String, Object> valueMap = new HashMap<>();
\r
443 valueMap.put("value", value);
\r
448 * Receives a response from an asynchronous process.
\r
449 * Errors are handled with junit assertions and will cause the test to fail.
\r
450 * @param businessKey the process business key
\r
451 * @param asyncResponse the TestAsyncResponse object associated with the test
\r
452 * @param timeout the timeout in milliseconds
\r
453 * @return the WorkflowResponse
\r
455 protected WorkflowResponse receiveResponse(String businessKey,
\r
456 TestAsyncResponse asyncResponse, long timeout) {
\r
457 System.out.println("Waiting " + timeout + "ms for process with business key " + businessKey
\r
458 + " to send a response");
\r
460 long now = System.currentTimeMillis() + timeout;
\r
461 long endTime = now + timeout;
\r
463 while (now <= endTime) {
\r
464 Response response = asyncResponse.getResponse();
\r
466 if (response != null) {
\r
467 System.out.println("Received a response from process with business key " + businessKey);
\r
469 Object entity = response.getEntity();
\r
471 if (!(entity instanceof WorkflowResponse)) {
\r
472 String msg = "Response entity is " +
\r
473 (entity == null ? "null" : entity.getClass().getName()) +
\r
474 ", expected WorkflowResponse";
\r
475 System.out.println(msg);
\r
477 return null; // unreachable
\r
480 return (WorkflowResponse) entity;
\r
485 } catch (InterruptedException e) {
\r
486 String msg = "Interrupted waiting for a response from process with business key " +
\r
488 System.out.println(msg);
\r
490 return null; // unreachable
\r
493 now = System.currentTimeMillis();
\r
496 String msg = "No response received from process with business key " + businessKey +
\r
497 " within " + timeout + "ms";
\r
498 System.out.println(msg);
\r
499 fail("Process with business key " + businessKey + " did not end within 10000ms");
\r
500 return null; // unreachable
\r
504 * Runs a program to inject SDNC callback data into the test environment.
\r
505 * A program is essentially just a list of keys that identify callback data
\r
506 * to be injected, in sequence. An example program:
\r
508 * reserve, assign, delete:ERR
\r
510 * Errors are handled with junit assertions and will cause the test to fail.
\r
511 * @param callbacks an object containing callback data for the program
\r
512 * @param program the program to execute
\r
514 protected void injectSDNCRestCallbacks(CallbackSet callbacks, String program) {
\r
516 String[] cmds = program.replaceAll("\\s+", "").split(",");
\r
518 for (String cmd : cmds) {
\r
519 String action = cmd;
\r
520 String modifier = "STD";
\r
522 if (cmd.contains(":")) {
\r
523 String[] parts = cmd.split(":");
\r
525 modifier = parts[1];
\r
528 String content = null;
\r
529 String contentType = null;
\r
531 if ("STD".equals(modifier)) {
\r
532 CallbackData callbackData = callbacks.get(action);
\r
534 if (callbackData == null) {
\r
535 String msg = "No callback defined for '" + action + "' SDNC request";
\r
536 System.out.println(msg);
\r
540 content = callbackData.getContent();
\r
541 contentType = callbackData.getContentType();
\r
542 } else if ("ERR".equals(modifier)) {
\r
543 content = "{\"SDNCServiceError\":{\"sdncRequestId\":\"((REQUEST-ID))\",\"responseCode\":\"500\",\"responseMessage\":\"SIMULATED ERROR FROM SDNC ADAPTER\",\"ackFinalIndicator\":\"Y\"}}";
\r
544 contentType = JSON;
\r
546 String msg = "Invalid SDNC program modifier: '" + modifier + "'";
\r
547 System.out.println(msg);
\r
551 if (contentType == null) {
\r
552 // Default for backward compatibility with existing tests.
\r
553 contentType = JSON;
\r
556 if (!injectSDNCRestCallback(contentType, content, 10000)) {
\r
557 fail("Failed to inject SDNC '" + action + "' callback");
\r
561 Thread.sleep(1000);
\r
562 } catch (InterruptedException e) {
\r
563 fail("Interrupted after injection of SDNC '" + action + "' callback");
\r
569 * Runs a program to inject SDNC events into the test environment.
\r
570 * A program is essentially just a list of keys that identify event data
\r
571 * to be injected, in sequence. An example program:
\r
575 * NOTE: Each callback must have a message type associated with it, e.g.
\r
577 * Errors are handled with junit assertions and will cause the test to fail.
\r
578 * @param callbacks an object containing event data for the program
\r
579 * @param program the program to execute
\r
581 protected void injectSDNCEvents(CallbackSet callbacks, String program) {
\r
582 injectWorkflowMessages(callbacks, program);
\r
586 * Runs a program to inject SDNC callback data into the test environment.
\r
587 * A program is essentially just a list of keys that identify callback data
\r
588 * to be injected, in sequence. An example program:
\r
590 * reserve, assign, delete:ERR
\r
592 * Errors are handled with junit assertions and will cause the test to fail.
\r
593 * @param callbacks an object containing callback data for the program
\r
594 * @param program the program to execute
\r
596 protected void injectSDNCCallbacks(CallbackSet callbacks, String program) {
\r
598 String[] cmds = program.replaceAll("\\s+", "").split(",");
\r
600 for (String cmd : cmds) {
\r
601 String action = cmd;
\r
602 String modifier = "STD";
\r
604 if (cmd.contains(":")) {
\r
605 String[] parts = cmd.split(":");
\r
607 modifier = parts[1];
\r
610 String content = null;
\r
611 int respCode = 200;
\r
612 String respMsg = "OK";
\r
614 if ("STD".equals(modifier)) {
\r
615 CallbackData callbackData = callbacks.get(action);
\r
617 if (callbackData == null) {
\r
618 String msg = "No callback defined for '" + action + "' SDNC request";
\r
619 System.out.println(msg);
\r
623 content = callbackData.getContent();
\r
626 } else if ("CREATED".equals(modifier)) {
\r
627 CallbackData callbackData = callbacks.get(action);
\r
629 if (callbackData == null) {
\r
630 String msg = "No callback defined for '" + action + "' SDNC request";
\r
631 System.out.println(msg);
\r
635 content = callbackData.getContent();
\r
637 respMsg = "Created";
\r
638 } else if ("ERR".equals(modifier)) {
\r
639 content = "<svc-request-id>((REQUEST-ID))</svc-request-id><response-code>500</response-code><response-message>SIMULATED ERROR FROM SDNC ADAPTER</response-message>";
\r
641 respMsg = "SERVER ERROR";
\r
643 String msg = "Invalid SDNC program modifier: '" + modifier + "'";
\r
644 System.out.println(msg);
\r
648 if (!injectSDNCCallback(respCode, respMsg, content, 10000)) {
\r
649 fail("Failed to inject SDNC '" + action + "' callback");
\r
653 Thread.sleep(1000);
\r
654 } catch (InterruptedException e) {
\r
655 fail("Interrupted after injection of SDNC '" + action + "' callback");
\r
661 * Runs a program to inject VNF adapter REST callback data into the test environment.
\r
662 * A program is essentially just a list of keys that identify callback data
\r
663 * to be injected, in sequence. An example program:
\r
667 * Errors are handled with junit assertions and will cause the test to fail.
\r
668 * @param callbacks an object containing callback data for the program
\r
669 * @param program the program to execute
\r
671 protected void injectVNFRestCallbacks(CallbackSet callbacks, String program) {
\r
673 String[] cmds = program.replaceAll("\\s+", "").split(",");
\r
675 for (String cmd : cmds) {
\r
676 String action = cmd;
\r
677 String modifier = "STD";
\r
679 if (cmd.contains(":")) {
\r
680 String[] parts = cmd.split(":");
\r
682 modifier = parts[1];
\r
685 String content = null;
\r
686 String contentType = null;
\r
688 if ("STD".equals(modifier)) {
\r
689 CallbackData callbackData = callbacks.get(action);
\r
691 if (callbackData == null) {
\r
692 String msg = "No callback defined for '" + action + "' VNF REST request";
\r
693 System.out.println(msg);
\r
697 content = callbackData.getContent();
\r
698 contentType = callbackData.getContentType();
\r
699 } else if ("ERR".equals(modifier)) {
\r
700 content = "SIMULATED ERROR FROM VNF ADAPTER";
\r
701 contentType = "text/plain";
\r
703 String msg = "Invalid VNF REST program modifier: '" + modifier + "'";
\r
704 System.out.println(msg);
\r
708 if (contentType == null) {
\r
709 // Default for backward compatibility with existing tests.
\r
713 if (!injectVnfAdapterRestCallback(contentType, content, 10000)) {
\r
714 fail("Failed to inject VNF REST '" + action + "' callback");
\r
718 Thread.sleep(1000);
\r
719 } catch (InterruptedException e) {
\r
720 fail("Interrupted after injection of VNF REST '" + action + "' callback");
\r
726 * Runs a program to inject VNF callback data into the test environment.
\r
727 * A program is essentially just a list of keys that identify callback data
\r
728 * to be injected, in sequence. An example program:
\r
730 * createVnf, deleteVnf
\r
732 * Errors are handled with junit assertions and will cause the test to fail.
\r
733 * @param callbacks an object containing callback data for the program
\r
734 * @param program the program to execute
\r
736 protected void injectVNFCallbacks(CallbackSet callbacks, String program) {
\r
738 String[] cmds = program.replaceAll("\\s+", "").split(",");
\r
740 for (String cmd : cmds) {
\r
741 String action = cmd;
\r
742 String modifier = "STD";
\r
744 if (cmd.contains(":")) {
\r
745 String[] parts = cmd.split(":");
\r
747 modifier = parts[1];
\r
750 String content = null;
\r
752 if ("STD".equals(modifier)) {
\r
753 CallbackData callbackData = callbacks.get(action);
\r
755 if (callbackData == null) {
\r
756 String msg = "No callback defined for '" + action + "' VNF request";
\r
757 System.out.println(msg);
\r
761 content = callbackData.getContent();
\r
762 } else if ("ERR".equals(modifier)) {
\r
763 String msg = "Currently unsupported VNF program modifier: '" + modifier + "'";
\r
764 System.out.println(msg);
\r
767 String msg = "Invalid VNF program modifier: '" + modifier + "'";
\r
768 System.out.println(msg);
\r
772 boolean injected = false;
\r
774 if (content.contains("createVnfNotification")) {
\r
775 injected = injectCreateVNFCallback(content, 10000);
\r
776 } else if (content.contains("deleteVnfNotification")) {
\r
777 injected = injectDeleteVNFCallback(content, 10000);
\r
778 } else if (content.contains("updateVnfNotification")) {
\r
779 injected = injectUpdateVNFCallback(content, 10000);
\r
783 String msg = "Failed to inject VNF '" + action + "' callback";
\r
784 System.out.println(msg);
\r
789 Thread.sleep(1000);
\r
790 } catch (InterruptedException e) {
\r
791 fail("Interrupted after injection of VNF '" + action + "' callback");
\r
797 * Waits for the number of running processes with the specified process
\r
798 * definition key to equal a particular count.
\r
799 * @param processKey the process definition key
\r
800 * @param count the desired count
\r
801 * @param timeout the timeout in milliseconds
\r
803 protected void waitForRunningProcessCount(String processKey, int count, long timeout) {
\r
804 System.out.println("Waiting " + timeout + "ms for there to be " + count + " "
\r
805 + processKey + " instances");
\r
807 long now = System.currentTimeMillis() + timeout;
\r
808 long endTime = now + timeout;
\r
811 while (now <= endTime) {
\r
812 int actual = processEngineRule.getRuntimeService()
\r
813 .createProcessInstanceQuery()
\r
814 .processDefinitionKey(processKey)
\r
817 if (actual != last) {
\r
818 System.out.println("There are now " + actual + " "
\r
819 + processKey + " instances");
\r
823 if (actual == count) {
\r
829 } catch (InterruptedException e) {
\r
830 String msg = "Interrupted waiting for there to be " + count + " "
\r
831 + processKey + " instances";
\r
832 System.out.println(msg);
\r
836 now = System.currentTimeMillis();
\r
839 String msg = "Timed out waiting for there to be " + count + " "
\r
840 + processKey + " instances";
\r
841 System.out.println(msg);
\r
846 * Waits for the specified process variable to be set.
\r
847 * @param processKey the process definition key
\r
848 * @param variable the variable name
\r
849 * @param timeout the timeout in milliseconds
\r
850 * @return the variable value, or null if it cannot be obtained
\r
851 * in the specified time
\r
853 protected Object getProcessVariable(String processKey, String variable,
\r
856 System.out.println("Waiting " + timeout + "ms for "
\r
857 + processKey + "." + variable + " to be set");
\r
859 long now = System.currentTimeMillis() + timeout;
\r
860 long endTime = now + timeout;
\r
862 ProcessInstance processInstance = null;
\r
863 Object value = null;
\r
865 while (value == null) {
\r
866 if (now > endTime) {
\r
867 if (processInstance == null) {
\r
868 System.out.println("Timed out waiting for "
\r
869 + processKey + " to start");
\r
871 System.out.println("Timed out waiting for "
\r
872 + processKey + "[" + processInstance.getId()
\r
873 + "]." + variable + " to be set");
\r
879 if (processInstance == null) {
\r
880 processInstance = processEngineRule.getRuntimeService()
\r
881 .createProcessInstanceQuery()
\r
882 .processDefinitionKey(processKey)
\r
886 if (processInstance != null) {
\r
887 value = processEngineRule.getRuntimeService()
\r
888 .getVariable(processInstance.getId(), variable);
\r
893 } catch (InterruptedException e) {
\r
894 System.out.println("Interrupted waiting for "
\r
895 + processKey + "." + variable + " to be set");
\r
899 now = System.currentTimeMillis();
\r
902 System.out.println(processKey + "["
\r
903 + processInstance.getId() + "]." + variable + "="
\r
910 * Injects a single SDNC adapter callback request. The specified callback data
\r
911 * may contain the placeholder string ((REQUEST-ID)) which is replaced with
\r
912 * the actual SDNC request ID. Note: this is not the requestId in the original
\r
914 * @param contentType the HTTP content type for the callback
\r
915 * @param content the content of the callback
\r
916 * @param timeout the timeout in milliseconds
\r
917 * @return true if the callback could be injected, false otherwise
\r
919 protected boolean injectSDNCRestCallback(String contentType, String content, long timeout) {
\r
920 String sdncRequestId = (String) getProcessVariable("SDNCAdapterRestV1",
\r
921 "SDNCAResponse_CORRELATOR", timeout);
\r
923 if (sdncRequestId == null) {
\r
927 content = content.replace("((REQUEST-ID))", sdncRequestId);
\r
928 // Deprecated usage. All test code should switch to the (( ... )) syntax.
\r
929 content = content.replace("{{REQUEST-ID}}", sdncRequestId);
\r
931 System.out.println("Injecting SDNC adapter callback");
\r
932 WorkflowMessageResource workflowMessageResource = new WorkflowMessageResource();
\r
933 workflowMessageResource.setProcessEngineServices4junit(processEngineRule);
\r
934 Response response = workflowMessageResource.deliver(contentType, "SDNCAResponse", sdncRequestId, content);
\r
935 System.out.println("Workflow response to SDNC adapter callback: " + response);
\r
940 * Injects a single SDNC adapter callback request. The specified callback data
\r
941 * may contain the placeholder string ((REQUEST-ID)) which is replaced with
\r
942 * the actual SDNC request ID. Note: this is not the requestId in the original
\r
944 * @param content the content of the callback
\r
945 * @param respCode the response code (normally 200)
\r
946 * @param respMsg the response message (normally "OK")
\r
947 * @param timeout the timeout in milliseconds
\r
948 * @return true if the callback could be injected, false otherwise
\r
950 protected boolean injectSDNCCallback(int respCode, String respMsg,
\r
951 String content, long timeout) {
\r
953 String sdncRequestId = (String) getProcessVariable("sdncAdapter",
\r
954 "SDNCA_requestId", timeout);
\r
956 if (sdncRequestId == null) {
\r
960 content = content.replace("((REQUEST-ID))", sdncRequestId);
\r
961 // Deprecated usage. All test code should switch to the (( ... )) syntax.
\r
962 content = content.replace("{{REQUEST-ID}}", sdncRequestId);
\r
964 System.out.println("Injecting SDNC adapter callback");
\r
965 CallbackHeader callbackHeader = new CallbackHeader();
\r
966 callbackHeader.setRequestId(sdncRequestId);
\r
967 callbackHeader.setResponseCode(String.valueOf(respCode));
\r
968 callbackHeader.setResponseMessage(respMsg);
\r
969 SDNCAdapterCallbackRequest sdncAdapterCallbackRequest = new SDNCAdapterCallbackRequest();
\r
970 sdncAdapterCallbackRequest.setCallbackHeader(callbackHeader);
\r
971 sdncAdapterCallbackRequest.setRequestData(content);
\r
972 SDNCAdapterCallbackServiceImpl callbackService = new SDNCAdapterCallbackServiceImpl();
\r
973 callbackService.setProcessEngineServices4junit(processEngineRule);
\r
974 SDNCAdapterResponse sdncAdapterResponse = callbackService.sdncAdapterCallback(sdncAdapterCallbackRequest);
\r
975 System.out.println("Workflow response to SDNC adapter callback: " + sdncAdapterResponse);
\r
981 * Injects a single VNF adapter callback request. The specified callback data
\r
982 * may contain the placeholder string ((MESSAGE-ID)) which is replaced with
\r
983 * the actual message ID. Note: this is not the requestId in the original
\r
985 * @param contentType the HTTP content type for the callback
\r
986 * @param content the content of the callback
\r
987 * @param timeout the timeout in milliseconds
\r
988 * @return true if the callback could be injected, false otherwise
\r
990 protected boolean injectVnfAdapterRestCallback(String contentType, String content, long timeout) {
\r
991 String messageId = (String) getProcessVariable("vnfAdapterRestV1",
\r
992 "VNFAResponse_CORRELATOR", timeout);
\r
994 if (messageId == null) {
\r
998 content = content.replace("((MESSAGE-ID))", messageId);
\r
999 // Deprecated usage. All test code should switch to the (( ... )) syntax.
\r
1000 content = content.replace("{{MESSAGE-ID}}", messageId);
\r
1002 System.out.println("Injecting VNF adapter callback");
\r
1003 WorkflowMessageResource workflowMessageResource = new WorkflowMessageResource();
\r
1004 workflowMessageResource.setProcessEngineServices4junit(processEngineRule);
\r
1005 Response response = workflowMessageResource.deliver(contentType, "VNFAResponse", messageId, content);
\r
1006 System.out.println("Workflow response to VNF adapter callback: " + response);
\r
1011 * Injects a Create VNF adapter callback request. The specified callback data
\r
1012 * may contain the placeholder string ((MESSAGE-ID)) which is replaced with
\r
1013 * the actual message ID. It may also contain the placeholder string
\r
1014 * ((REQUEST-ID)) which is replaced request ID of the original MSO request.
\r
1015 * @param content the content of the callback
\r
1016 * @param timeout the timeout in milliseconds
\r
1017 * @return true if the callback could be injected, false otherwise
\r
1018 * @throws JAXBException if the content does not adhere to the schema
\r
1020 protected boolean injectCreateVNFCallback(String content, long timeout) {
\r
1022 String messageId = (String) getProcessVariable("vnfAdapterCreateV1",
\r
1023 "VNFC_messageId", timeout);
\r
1025 if (messageId == null) {
\r
1029 content = content.replace("((MESSAGE-ID))", messageId);
\r
1030 // Deprecated usage. All test code should switch to the (( ... )) syntax.
\r
1031 content = content.replace("{{MESSAGE-ID}}", messageId);
\r
1033 if(content.contains("((REQUEST-ID))")){
\r
1034 content = content.replace("((REQUEST-ID))", msoRequestId);
\r
1035 // Deprecated usage. All test code should switch to the (( ... )) syntax.
\r
1036 content = content.replace("{{REQUEST-ID}}", msoRequestId);
\r
1039 System.out.println("Injecting VNF adapter callback");
\r
1041 // Is it possible to unmarshal this with JAXB? I couldn't.
\r
1043 CreateVnfNotification createVnfNotification = new CreateVnfNotification();
\r
1044 XPathTool xpathTool = new VnfNotifyXPathTool();
\r
1045 xpathTool.setXML(content);
\r
1048 String completed = xpathTool.evaluate(
\r
1049 "/tns:createVnfNotification/tns:completed/text()");
\r
1050 createVnfNotification.setCompleted("true".equals(completed));
\r
1052 String vnfId = xpathTool.evaluate(
\r
1053 "/tns:createVnfNotification/tns:vnfId/text()");
\r
1054 createVnfNotification.setVnfId(vnfId);
\r
1056 NodeList entries = (NodeList) xpathTool.evaluate(
\r
1057 "/tns:createVnfNotification/tns:outputs/tns:entry",
\r
1058 XPathConstants.NODESET);
\r
1060 CreateVnfNotificationOutputs outputs = new CreateVnfNotificationOutputs();
\r
1062 for (int i = 0; i < entries.getLength(); i++) {
\r
1063 Node node = entries.item(i);
\r
1065 if (node.getNodeType() == Node.ELEMENT_NODE) {
\r
1066 Element entry = (Element) node;
\r
1067 String key = entry.getElementsByTagNameNS("*", "key").item(0).getTextContent();
\r
1068 String value = entry.getElementsByTagNameNS("*", "value").item(0).getTextContent();
\r
1069 outputs.add(key, value);
\r
1073 createVnfNotification.setOutputs(outputs);
\r
1075 VnfRollback rollback = new VnfRollback();
\r
1077 String cloudSiteId = xpathTool.evaluate(
\r
1078 "/tns:createVnfNotification/tns:rollback/tns:cloudSiteId/text()");
\r
1079 rollback.setCloudSiteId(cloudSiteId);
\r
1081 String requestId = xpathTool.evaluate(
\r
1082 "/tns:createVnfNotification/tns:rollback/tns:msoRequest/tns:requestId/text()");
\r
1083 String serviceInstanceId = xpathTool.evaluate(
\r
1084 "/tns:createVnfNotification/tns:rollback/tns:msoRequest/tns:serviceInstanceId/text()");
\r
1086 if (requestId != null || serviceInstanceId != null) {
\r
1087 MsoRequest msoRequest = new MsoRequest();
\r
1088 msoRequest.setRequestId(requestId);
\r
1089 msoRequest.setServiceInstanceId(serviceInstanceId);
\r
1090 rollback.setMsoRequest(msoRequest);
\r
1093 String tenantCreated = xpathTool.evaluate(
\r
1094 "/tns:createVnfNotification/tns:rollback/tns:tenantCreated/text()");
\r
1095 rollback.setTenantCreated("true".equals(tenantCreated));
\r
1097 String tenantId = xpathTool.evaluate(
\r
1098 "/tns:createVnfNotification/tns:rollback/tns:tenantId/text()");
\r
1099 rollback.setTenantId(tenantId);
\r
1101 String vnfCreated = xpathTool.evaluate(
\r
1102 "/tns:createVnfNotification/tns:rollback/tns:vnfCreated/text()");
\r
1103 rollback.setVnfCreated("true".equals(vnfCreated));
\r
1105 String rollbackVnfId = xpathTool.evaluate(
\r
1106 "/tns:createVnfNotification/tns:rollback/tns:vnfId/text()");
\r
1107 rollback.setVnfId(rollbackVnfId);
\r
1109 createVnfNotification.setRollback(rollback);
\r
1111 } catch (Exception e) {
\r
1112 System.out.println("Failed to unmarshal VNF callback content:");
\r
1113 System.out.println(content);
\r
1117 VnfAdapterNotifyServiceImpl notifyService = new VnfAdapterNotifyServiceImpl();
\r
1118 notifyService.setProcessEngineServices4junit(processEngineRule);
\r
1120 notifyService.createVnfNotification(
\r
1122 createVnfNotification.isCompleted(),
\r
1123 createVnfNotification.getException(),
\r
1124 createVnfNotification.getErrorMessage(),
\r
1125 createVnfNotification.getVnfId(),
\r
1126 createVnfNotification.getOutputs(),
\r
1127 createVnfNotification.getRollback());
\r
1133 * Injects a Delete VNF adapter callback request. The specified callback data
\r
1134 * may contain the placeholder string ((MESSAGE-ID)) which is replaced with
\r
1135 * the actual message ID. It may also contain the placeholder string
\r
1136 * ((REQUEST-ID)) which is replaced request ID of the original MSO request.
\r
1137 * @param content the content of the callback
\r
1138 * @param timeout the timeout in milliseconds
\r
1139 * @return true if the callback could be injected, false otherwise
\r
1140 * @throws JAXBException if the content does not adhere to the schema
\r
1142 protected boolean injectDeleteVNFCallback(String content, long timeout) {
\r
1144 String messageId = (String) getProcessVariable("vnfAdapterDeleteV1",
\r
1145 "VNFDEL_uuid", timeout);
\r
1147 if (messageId == null) {
\r
1151 content = content.replace("((MESSAGE-ID))", messageId);
\r
1152 // Deprecated usage. All test code should switch to the (( ... )) syntax.
\r
1153 content = content.replace("{{MESSAGE-ID}}", messageId);
\r
1155 System.out.println("Injecting VNF adapter delete callback");
\r
1157 // Is it possible to unmarshal this with JAXB? I couldn't.
\r
1159 DeleteVnfNotification deleteVnfNotification = new DeleteVnfNotification();
\r
1160 XPathTool xpathTool = new VnfNotifyXPathTool();
\r
1161 xpathTool.setXML(content);
\r
1164 String completed = xpathTool.evaluate(
\r
1165 "/tns:deleteVnfNotification/tns:completed/text()");
\r
1166 deleteVnfNotification.setCompleted("true".equals(completed));
\r
1167 // if notification failure, set the exception and error message
\r
1168 if (deleteVnfNotification.isCompleted() == false) {
\r
1169 deleteVnfNotification.setException(MsoExceptionCategory.INTERNAL);
\r
1170 deleteVnfNotification.setErrorMessage(xpathTool.evaluate(
\r
1171 "/tns:deleteVnfNotification/tns:errorMessage/text()")) ;
\r
1174 } catch (Exception e) {
\r
1175 System.out.println("Failed to unmarshal VNF Delete callback content:");
\r
1176 System.out.println(content);
\r
1180 VnfAdapterNotifyServiceImpl notifyService = new VnfAdapterNotifyServiceImpl();
\r
1181 notifyService.setProcessEngineServices4junit(processEngineRule);
\r
1183 notifyService.deleteVnfNotification(
\r
1185 deleteVnfNotification.isCompleted(),
\r
1186 deleteVnfNotification.getException(),
\r
1187 deleteVnfNotification.getErrorMessage());
\r
1193 * Injects a Update VNF adapter callback request. The specified callback data
\r
1194 * may contain the placeholder string ((MESSAGE-ID)) which is replaced with
\r
1195 * the actual message ID. It may also contain the placeholder string
\r
1196 * ((REQUEST-ID)) which is replaced request ID of the original MSO request.
\r
1197 * @param content the content of the callback
\r
1198 * @param timeout the timeout in milliseconds
\r
1199 * @return true if the callback could be injected, false otherwise
\r
1200 * @throws JAXBException if the content does not adhere to the schema
\r
1202 protected boolean injectUpdateVNFCallback(String content, long timeout) {
\r
1204 String messageId = (String) getProcessVariable("vnfAdapterUpdate",
\r
1205 "VNFU_messageId", timeout);
\r
1207 if (messageId == null) {
\r
1211 content = content.replace("((MESSAGE-ID))", messageId);
\r
1212 // Deprecated usage. All test code should switch to the (( ... )) syntax.
\r
1213 content = content.replace("{{MESSAGE-ID}}", messageId);
\r
1215 content = content.replace("((REQUEST-ID))", msoRequestId);
\r
1216 // Deprecated usage. All test code should switch to the (( ... )) syntax.
\r
1217 content = content.replace("{{REQUEST-ID}}", msoRequestId);
\r
1219 System.out.println("Injecting VNF adapter callback");
\r
1221 // Is it possible to unmarshal this with JAXB? I couldn't.
\r
1223 UpdateVnfNotification updateVnfNotification = new UpdateVnfNotification();
\r
1224 XPathTool xpathTool = new VnfNotifyXPathTool();
\r
1225 xpathTool.setXML(content);
\r
1228 String completed = xpathTool.evaluate(
\r
1229 "/tns:updateVnfNotification/tns:completed/text()");
\r
1230 updateVnfNotification.setCompleted("true".equals(completed));
\r
1232 NodeList entries = (NodeList) xpathTool.evaluate(
\r
1233 "/tns:updateVnfNotification/tns:outputs/tns:entry",
\r
1234 XPathConstants.NODESET);
\r
1236 UpdateVnfNotificationOutputs outputs = new UpdateVnfNotificationOutputs();
\r
1238 for (int i = 0; i < entries.getLength(); i++) {
\r
1239 Node node = entries.item(i);
\r
1241 if (node.getNodeType() == Node.ELEMENT_NODE) {
\r
1242 Element entry = (Element) node;
\r
1243 String key = entry.getElementsByTagNameNS("*", "key").item(0).getTextContent();
\r
1244 String value = entry.getElementsByTagNameNS("*", "value").item(0).getTextContent();
\r
1245 outputs.add(key, value);
\r
1249 updateVnfNotification.setOutputs(outputs);
\r
1251 VnfRollback rollback = new VnfRollback();
\r
1253 String cloudSiteId = xpathTool.evaluate(
\r
1254 "/tns:updateVnfNotification/tns:rollback/tns:cloudSiteId/text()");
\r
1255 rollback.setCloudSiteId(cloudSiteId);
\r
1257 String requestId = xpathTool.evaluate(
\r
1258 "/tns:updateVnfNotification/tns:rollback/tns:msoRequest/tns:requestId/text()");
\r
1259 String serviceInstanceId = xpathTool.evaluate(
\r
1260 "/tns:updateVnfNotification/tns:rollback/tns:msoRequest/tns:serviceInstanceId/text()");
\r
1262 if (requestId != null || serviceInstanceId != null) {
\r
1263 MsoRequest msoRequest = new MsoRequest();
\r
1264 msoRequest.setRequestId(requestId);
\r
1265 msoRequest.setServiceInstanceId(serviceInstanceId);
\r
1266 rollback.setMsoRequest(msoRequest);
\r
1269 String tenantCreated = xpathTool.evaluate(
\r
1270 "/tns:updateVnfNotification/tns:rollback/tns:tenantCreated/text()");
\r
1271 rollback.setTenantCreated("true".equals(tenantCreated));
\r
1273 String tenantId = xpathTool.evaluate(
\r
1274 "/tns:updateVnfNotification/tns:rollback/tns:tenantId/text()");
\r
1275 rollback.setTenantId(tenantId);
\r
1277 String vnfCreated = xpathTool.evaluate(
\r
1278 "/tns:updateVnfNotification/tns:rollback/tns:vnfCreated/text()");
\r
1279 rollback.setVnfCreated("true".equals(vnfCreated));
\r
1281 String rollbackVnfId = xpathTool.evaluate(
\r
1282 "/tns:updateVnfNotification/tns:rollback/tns:vnfId/text()");
\r
1283 rollback.setVnfId(rollbackVnfId);
\r
1285 updateVnfNotification.setRollback(rollback);
\r
1287 } catch (Exception e) {
\r
1288 System.out.println("Failed to unmarshal VNF callback content:");
\r
1289 System.out.println(content);
\r
1293 VnfAdapterNotifyServiceImpl notifyService = new VnfAdapterNotifyServiceImpl();
\r
1294 notifyService.setProcessEngineServices4junit(processEngineRule);
\r
1296 notifyService.updateVnfNotification(
\r
1298 updateVnfNotification.isCompleted(),
\r
1299 updateVnfNotification.getException(),
\r
1300 updateVnfNotification.getErrorMessage(),
\r
1301 updateVnfNotification.getOutputs(),
\r
1302 updateVnfNotification.getRollback());
\r
1308 * Runs a program to inject workflow messages into the test environment.
\r
1309 * A program is essentially just a list of keys that identify event data
\r
1310 * to be injected, in sequence. An example program:
\r
1314 * Errors are handled with junit assertions and will cause the test to fail.
\r
1315 * NOTE: Each callback must have a workflow message type associated with it.
\r
1316 * @param callbacks an object containing event data for the program
\r
1317 * @param program the program to execute
\r
1319 protected void injectWorkflowMessages(CallbackSet callbacks, String program) {
\r
1321 String[] cmds = program.replaceAll("\\s+", "").split(",");
\r
1323 for (String cmd : cmds) {
\r
1324 String action = cmd;
\r
1325 String modifier = "STD";
\r
1327 if (cmd.contains(":")) {
\r
1328 String[] parts = cmd.split(":");
\r
1329 action = parts[0];
\r
1330 modifier = parts[1];
\r
1333 String messageType = null;
\r
1334 String content = null;
\r
1335 String contentType = null;
\r
1337 if ("STD".equals(modifier)) {
\r
1338 CallbackData callbackData = callbacks.get(action);
\r
1340 if (callbackData == null) {
\r
1341 String msg = "No '" + action + "' workflow message callback is defined";
\r
1342 System.out.println(msg);
\r
1346 messageType = callbackData.getMessageType();
\r
1348 if (messageType == null || messageType.trim().equals("")) {
\r
1349 String msg = "No workflow message type is defined in the '" + action + "' callback";
\r
1350 System.out.println(msg);
\r
1354 content = callbackData.getContent();
\r
1355 contentType = callbackData.getContentType();
\r
1357 String msg = "Invalid workflow message program modifier: '" + modifier + "'";
\r
1358 System.out.println(msg);
\r
1362 if (!injectWorkflowMessage(contentType, messageType, content, 10000)) {
\r
1363 fail("Failed to inject '" + action + "' workflow message");
\r
1367 Thread.sleep(1000);
\r
1368 } catch (InterruptedException e) {
\r
1369 fail("Interrupted after injection of '" + action + "' workflow message");
\r
1375 * Injects a workflow message. The specified callback data may contain the
\r
1376 * placeholder string ((CORRELATOR)) which is replaced with the actual
\r
1377 * correlator value.
\r
1378 * @param contentType the HTTP contentType for the message (possibly null)
\r
1379 * @param messageType the message type
\r
1380 * @param content the message content (possibly null)
\r
1381 * @param timeout the timeout in milliseconds
\r
1382 * @return true if the message could be injected, false otherwise
\r
1384 protected boolean injectWorkflowMessage(String contentType, String messageType, String content, long timeout) {
\r
1385 String correlator = (String) getProcessVariable("ReceiveWorkflowMessage",
\r
1386 messageType + "_CORRELATOR", timeout);
\r
1388 if (correlator == null) {
\r
1392 if (content != null) {
\r
1393 content = content.replace("((CORRELATOR))", correlator);
\r
1396 System.out.println("Injecting " + messageType + " message");
\r
1397 WorkflowMessageResource workflowMessageResource = new WorkflowMessageResource();
\r
1398 workflowMessageResource.setProcessEngineServices4junit(processEngineRule);
\r
1399 Response response = workflowMessageResource.deliver(contentType, messageType, correlator, content);
\r
1400 System.out.println("Workflow response to " + messageType + " message: " + response);
\r
1405 * Runs a program to inject sniro workflow messages into the test environment.
\r
1406 * A program is essentially just a list of keys that identify event data
\r
1407 * to be injected, in sequence. For more details, see
\r
1408 * injectSNIROCallbacks(String contentType, String messageType, String content, long timeout)
\r
1410 * Errors are handled with junit assertions and will cause the test to fail.
\r
1411 * NOTE: Each callback must have a workflow message type associated with it.
\r
1413 * @param callbacks an object containing event data for the program
\r
1414 * @param program the program to execute
\r
1416 protected void injectSNIROCallbacks(CallbackSet callbacks, String program) {
\r
1418 String[] cmds = program.replaceAll("\\s+", "").split(",");
\r
1420 for (String cmd : cmds) {
\r
1421 String action = cmd;
\r
1422 String modifier = "STD";
\r
1424 if (cmd.contains(":")) {
\r
1425 String[] parts = cmd.split(":");
\r
1426 action = parts[0];
\r
1427 modifier = parts[1];
\r
1430 String messageType = null;
\r
1431 String content = null;
\r
1432 String contentType = null;
\r
1434 if ("STD".equals(modifier)) {
\r
1435 CallbackData callbackData = callbacks.get(action);
\r
1437 if (callbackData == null) {
\r
1438 String msg = "No '" + action + "' workflow message callback is defined";
\r
1439 System.out.println(msg);
\r
1443 messageType = callbackData.getMessageType();
\r
1445 if (messageType == null || messageType.trim().equals("")) {
\r
1446 String msg = "No workflow message type is defined in the '" + action + "' callback";
\r
1447 System.out.println(msg);
\r
1451 content = callbackData.getContent();
\r
1452 contentType = callbackData.getContentType();
\r
1454 String msg = "Invalid workflow message program modifier: '" + modifier + "'";
\r
1455 System.out.println(msg);
\r
1459 if (!injectSNIROCallbacks(contentType, messageType, content, 10000)) {
\r
1460 fail("Failed to inject '" + action + "' workflow message");
\r
1464 Thread.sleep(1000);
\r
1465 } catch (InterruptedException e) {
\r
1466 fail("Interrupted after injection of '" + action + "' workflow message");
\r
1472 * Injects a sniro workflow message. The specified callback response may
\r
1473 * contain the placeholder strings ((CORRELATOR)) and ((SERVICE_RESOURCE_ID))
\r
1474 * The ((CORRELATOR)) is replaced with the actual correlator value from the
\r
1475 * request. The ((SERVICE_RESOURCE_ID)) is replaced with the actual serviceResourceId
\r
1476 * value from the sniro request. Currently this only works with sniro request
\r
1477 * that contain only 1 resource.
\r
1479 * @param contentType the HTTP contentType for the message (possibly null)
\r
1480 * @param messageType the message type
\r
1481 * @param content the message content (possibly null)
\r
1482 * @param timeout the timeout in milliseconds
\r
1483 * @return true if the message could be injected, false otherwise
\r
1485 protected boolean injectSNIROCallbacks(String contentType, String messageType, String content, long timeout) {
\r
1486 String correlator = (String) getProcessVariable("ReceiveWorkflowMessage",
\r
1487 messageType + "_CORRELATOR", timeout);
\r
1489 if (correlator == null) {
\r
1492 if (content != null) {
\r
1493 content = content.replace("((CORRELATOR))", correlator);
\r
1494 if(messageType.equalsIgnoreCase("SNIROResponse")){
\r
1495 //TODO figure out a solution for when there is more than 1 resource being homed (i.e. more than 1 reason in the placement list)
\r
1496 ServiceDecomposition decomp = (ServiceDecomposition) getProcessVariable("Homing", "serviceDecomposition", timeout);
\r
1497 List<Resource> resourceList = decomp.getServiceResources();
\r
1498 if(resourceList.size() == 1){
\r
1499 String resourceId = "";
\r
1500 for(Resource resource:resourceList){
\r
1501 resourceId = resource.getResourceId();
\r
1503 //TODO.. most other locations refer to solutionInfo.placementInfo
\r
1504 String homingList = getJsonValue(content, "solutionInfo.placement");
\r
1505 JSONArray placementArr = null;
\r
1507 placementArr = new JSONArray(homingList);
\r
1509 catch (Exception e) {
\r
1512 if(placementArr.length() == 1){
\r
1513 content = content.replace("((SERVICE_RESOURCE_ID))", resourceId);
\r
1515 String licenseInfoList = getJsonValue(content, "solutionInfo.licenseInfo");
\r
1516 JSONArray licenseArr = null;
\r
1518 licenseArr = new JSONArray(licenseInfoList);
\r
1520 catch (Exception e) {
\r
1523 if(licenseArr.length() == 1){
\r
1524 content = content.replace("((SERVICE_RESOURCE_ID))", resourceId);
\r
1529 String homingList = getJsonValue(content, "solutionInfo.placementInfo");
\r
1530 String licenseInfoList = getJsonValue(content, "solutionInfo.licenseInfo");
\r
1531 JSONArray placementArr = new JSONArray(homingList);
\r
1532 JSONArray licenseArr = new JSONArray(licenseInfoList);
\r
1533 for (Resource resource: resourceList) {
\r
1534 String resourceModuleName = resource.getModelInfo().getModelInstanceName();
\r
1535 String resourceId = resource.getResourceId();
\r
1537 for (int i=0; i<placementArr.length(); i++) {
\r
1538 JSONObject placementObj = placementArr.getJSONObject(i);
\r
1539 String placementModuleName = placementObj.getString("resourceModuleName");
\r
1540 if (placementModuleName.equalsIgnoreCase(resourceModuleName)) {
\r
1541 String placementString = placementObj.toString();
\r
1542 placementString = placementString.replace("((SERVICE_RESOURCE_ID))", resourceId);
\r
1543 JSONObject newPlacementObj = new JSONObject(placementString);
\r
1544 placementArr.put(i, newPlacementObj);
\r
1548 for (int i=0; i<licenseArr.length(); i++) {
\r
1549 JSONObject licenseObj = licenseArr.getJSONObject(i);
\r
1550 String licenseModuleName = licenseObj.getString("resourceModuleName");
\r
1551 if (licenseModuleName.equalsIgnoreCase(resourceModuleName)) {
\r
1552 String licenseString = licenseObj.toString();
\r
1553 licenseString = licenseString.replace("((SERVICE_RESOURCE_ID))", resourceId);
\r
1554 JSONObject newLicenseObj = new JSONObject(licenseString);
\r
1555 licenseArr.put(i, newLicenseObj);
\r
1559 String newPlacementInfos = placementArr.toString();
\r
1560 String newLicenseInfos = licenseArr.toString();
\r
1561 content = updJsonValue(content, "solutionInfo.placementInfo", newPlacementInfos);
\r
1562 content = updJsonValue(content, "solutionInfo.licenseInfo", newLicenseInfos);
\r
1564 catch(Exception e) {
\r
1571 System.out.println("Injecting " + messageType + " message");
\r
1572 WorkflowMessageResource workflowMessageResource = new WorkflowMessageResource();
\r
1573 workflowMessageResource.setProcessEngineServices4junit(processEngineRule);
\r
1574 Response response = workflowMessageResource.deliver(contentType, messageType, correlator, content);
\r
1575 System.out.println("Workflow response to " + messageType + " message: " + response);
\r
1581 * Wait for the process to end.
\r
1582 * @param businessKey the process business key
\r
1583 * @param timeout the amount of time to wait, in milliseconds
\r
1585 protected void waitForProcessEnd(String businessKey, long timeout) {
\r
1586 System.out.println("Waiting " + timeout + "ms for process with business key " +
\r
1587 businessKey + " to end");
\r
1589 long now = System.currentTimeMillis() + timeout;
\r
1590 long endTime = now + timeout;
\r
1592 while (now <= endTime) {
\r
1593 if (isProcessEnded(businessKey)) {
\r
1594 System.out.println("Process with business key " + businessKey + " has ended");
\r
1599 Thread.sleep(200);
\r
1600 } catch (InterruptedException e) {
\r
1601 String msg = "Interrupted waiting for process with business key " +
\r
1602 businessKey + " to end";
\r
1603 System.out.println(msg);
\r
1607 now = System.currentTimeMillis();
\r
1610 String msg = "Process with business key " + businessKey +
\r
1611 " did not end within " + timeout + "ms";
\r
1612 System.out.println(msg);
\r
1617 * Verifies that the specified historic process variable has the specified value.
\r
1618 * If the variable does not have the specified value, the test is failed.
\r
1619 * @param businessKey the process business key
\r
1620 * @param variable the variable name
\r
1621 * @param value the expected variable value
\r
1623 protected void checkVariable(String businessKey, String variable, Object value) {
\r
1624 if (!isProcessEnded(businessKey)) {
\r
1625 fail("Cannot get historic variable " + variable + " because process with business key " +
\r
1626 businessKey + " has not ended");
\r
1629 Object variableValue = getVariableFromHistory(businessKey, variable);
\r
1630 assertEquals(value, variableValue);
\r
1634 * Checks to see if the specified process is ended.
\r
1635 * @param businessKey the process business Key
\r
1636 * @return true if the process is ended
\r
1638 protected boolean isProcessEnded(String businessKey) {
\r
1639 HistoricProcessInstance processInstance = processEngineRule.getHistoryService()
\r
1640 .createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
\r
1641 return processInstance != null && processInstance.getEndTime() != null;
\r
1645 * Gets a variable value from a historical process instance.
\r
1646 * @param businessKey the process business key
\r
1647 * @param variableName the variable name
\r
1648 * @return the variable value, or null if the variable could not be
\r
1651 protected Object getVariableFromHistory(String businessKey, String variableName) {
\r
1653 HistoricProcessInstance processInstance = processEngineRule.getHistoryService()
\r
1654 .createHistoricProcessInstanceQuery().processInstanceBusinessKey(businessKey).singleResult();
\r
1656 if (processInstance == null) {
\r
1660 HistoricVariableInstance v = processEngineRule.getHistoryService()
\r
1661 .createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId())
\r
1662 .variableName(variableName).singleResult();
\r
1663 return v == null ? null : v.getValue();
\r
1664 } catch (Exception e) {
\r
1665 System.out.println("Error retrieving variable " + variableName +
\r
1666 " from historical process with business key " + businessKey + ": " + e);
\r
1672 * Gets the value of a subflow variable from the specified subflow's
\r
1673 * historical process instance.
\r
1675 * @param subflowName - the name of the subflow that contains the variable
\r
1676 * @param variableName the variable name
\r
1678 * @return the variable value, or null if the variable could not be obtained
\r
1681 protected Object getVariableFromSubflowHistory(String subflowName, String variableName) {
\r
1683 List<HistoricProcessInstance> processInstanceList = processEngineRule.getHistoryService()
\r
1684 .createHistoricProcessInstanceQuery().processDefinitionName(subflowName).list();
\r
1686 if (processInstanceList == null) {
\r
1690 processInstanceList.sort((m1, m2) -> m1.getStartTime().compareTo(m2.getStartTime()));
\r
1692 HistoricProcessInstance processInstance = processInstanceList.get(0);
\r
1694 HistoricVariableInstance v = processEngineRule.getHistoryService()
\r
1695 .createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId())
\r
1696 .variableName(variableName).singleResult();
\r
1697 return v == null ? null : v.getValue();
\r
1698 } catch (Exception e) {
\r
1699 System.out.println("Error retrieving variable " + variableName +
\r
1700 " from sub flow: " + subflowName + ", Exception is: " + e);
\r
1706 * Gets the value of a subflow variable from the subflow's
\r
1707 * historical process x instance.
\r
1709 * @param subflowName - the name of the subflow that contains the variable
\r
1710 * @param variableName the variable name
\r
1711 * @param subflowInstanceIndex - the instance of the subflow (use when same subflow is called more than once from mainflow)
\r
1713 * @return the variable value, or null if the variable could not be obtained
\r
1715 protected Object getVariableFromSubflowHistory(int subflowInstanceIndex, String subflowName, String variableName) {
\r
1717 List<HistoricProcessInstance> processInstanceList = processEngineRule.getHistoryService()
\r
1718 .createHistoricProcessInstanceQuery().processDefinitionName(subflowName).list();
\r
1720 if (processInstanceList == null) {
\r
1724 processInstanceList.sort((m1, m2) -> m1.getStartTime().compareTo(m2.getStartTime()));
\r
1726 HistoricProcessInstance processInstance = processInstanceList.get(subflowInstanceIndex);
\r
1728 HistoricVariableInstance v = processEngineRule.getHistoryService()
\r
1729 .createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId())
\r
1730 .variableName(variableName).singleResult();
\r
1731 return v == null ? null : v.getValue();
\r
1732 } catch (Exception e) {
\r
1733 System.out.println("Error retrieving variable " + variableName +
\r
1734 " from " + subflowInstanceIndex + " instance index of sub flow: " + subflowName + ", Exception is: " + e);
\r
1741 * Extracts text from an XML element. This method is not namespace aware
\r
1742 * (namespaces are ignored). The first matching element is selected.
\r
1743 * @param xml the XML document or fragment
\r
1744 * @param tag the desired element, e.g. "<name>"
\r
1745 * @return the element text, or null if the element was not found
\r
1747 protected String getXMLTextElement(String xml, String tag) {
\r
1748 xml = removeXMLNamespaces(xml);
\r
1750 if (!tag.startsWith("<")) {
\r
1751 tag = "<" + tag + ">";
\r
1754 int start = xml.indexOf(tag);
\r
1756 if (start == -1) {
\r
1760 int end = xml.indexOf('<', start + tag.length());
\r
1766 return xml.substring(start + tag.length(), end);
\r
1770 * Removes namespace definitions and prefixes from XML, if any.
\r
1772 private String removeXMLNamespaces(String xml) {
\r
1773 // remove xmlns declaration
\r
1774 xml = xml.replaceAll("xmlns.*?(\"|\').*?(\"|\')", "");
\r
1776 // remove opening tag prefix
\r
1777 xml = xml.replaceAll("(<)(\\w+:)(.*?>)", "$1$3");
\r
1779 // remove closing tags prefix
\r
1780 xml = xml.replaceAll("(</)(\\w+:)(.*?>)", "$1$3");
\r
1782 // remove extra spaces left when xmlns declarations are removed
\r
1783 xml = xml.replaceAll("\\s+>", ">");
\r
1789 * Asserts that two XML documents are semantically equivalent. Differences
\r
1790 * in whitespace or in namespace usage do not affect the comparison.
\r
1791 * @param expected the expected XML
\r
1792 * @param actual the XML to test
\r
1793 * @throws SAXException
\r
1794 * @throws IOException
\r
1796 public static void assertXMLEquals(String expected, String actual)
\r
1797 throws SAXException, IOException {
\r
1798 XMLUnit.setIgnoreWhitespace(true);
\r
1799 XMLUnit.setIgnoreAttributeOrder(true);
\r
1800 DetailedDiff diff = new DetailedDiff(XMLUnit.compareXML(expected, actual));
\r
1801 List<?> allDifferences = diff.getAllDifferences();
\r
1802 assertEquals("Differences found: " + diff.toString(), 0, allDifferences.size());
\r
1806 * A test implementation of AsynchronousResponse.
\r
1808 public class TestAsyncResponse implements AsynchronousResponse {
\r
1809 Response response = null;
\r
1815 public synchronized void setResponse(Response response) {
\r
1816 this.response = response;
\r
1820 * Gets the response.
\r
1821 * @return the response, or null if none has been produced yet
\r
1823 public synchronized Response getResponse() {
\r
1829 * An object that contains callback data for a "program".
\r
1831 public class CallbackSet {
\r
1832 private final Map<String, CallbackData> map = new HashMap<>();
\r
1835 * Add untyped callback data to the set.
\r
1836 * @param action the action with which the data is associated
\r
1837 * @param content the callback data
\r
1839 public void put(String action, String content) {
\r
1840 map.put(action, new CallbackData(null, null, content));
\r
1844 * Add callback data to the set.
\r
1845 * @param action the action with which the data is associated
\r
1846 * @param messageType the callback message type
\r
1847 * @param content the callback data
\r
1849 public void put(String action, String messageType, String content) {
\r
1850 map.put(action, new CallbackData(null, messageType, content));
\r
1854 * Add callback data to the set.
\r
1855 * @param action the action with which the data is associated
\r
1856 * @param contentType the callback HTTP content type
\r
1857 * @param messageType the callback message type
\r
1858 * @param content the callback data
\r
1860 public void put(String action, String contentType, String messageType, String content) {
\r
1861 map.put(action, new CallbackData(contentType, messageType, content));
\r
1865 * Retrieve callback data from the set.
\r
1866 * @param action the action with which the data is associated
\r
1867 * @return the callback data, or null if there is none for the specified operation
\r
1869 public CallbackData get(String action) {
\r
1870 return map.get(action);
\r
1875 * Represents a callback data item.
\r
1877 public class CallbackData {
\r
1878 private final String contentType;
\r
1879 private final String messageType;
\r
1880 private final String content;
\r
1884 * @param contentType the HTTP content type (optional)
\r
1885 * @param messageType the callback message type (optional)
\r
1886 * @param content the content
\r
1888 public CallbackData(String contentType, String messageType, String content) {
\r
1889 this.contentType = contentType;
\r
1890 this.messageType = messageType;
\r
1891 this.content = content;
\r
1895 * Gets the callback HTTP content type, possibly null.
\r
1897 public String getContentType() {
\r
1898 return contentType;
\r
1902 * Gets the callback message type, possibly null.
\r
1904 public String getMessageType() {
\r
1905 return messageType;
\r
1909 * Gets the callback content.
\r
1911 public String getContent() {
\r
1917 * A tool for evaluating XPath expressions.
\r
1919 protected class XPathTool {
\r
1920 private final DocumentBuilderFactory factory;
\r
1921 private final SimpleNamespaceContext context = new SimpleNamespaceContext();
\r
1922 private final XPath xpath = XPathFactory.newInstance().newXPath();
\r
1923 private String xml = null;
\r
1924 private Document doc = null;
\r
1929 public XPathTool() {
\r
1930 factory = DocumentBuilderFactory.newInstance();
\r
1931 factory.setNamespaceAware(true);
\r
1932 xpath.setNamespaceContext(context);
\r
1936 * Adds a namespace.
\r
1937 * @param prefix the namespace prefix
\r
1938 * @param uri the namespace uri
\r
1940 public synchronized void addNamespace(String prefix, String uri) {
\r
1941 context.add(prefix, uri);
\r
1945 * Sets the XML content to be operated on.
\r
1946 * @param xml the XML content
\r
1948 public synchronized void setXML(String xml) {
\r
1954 * Returns the document object.
\r
1955 * @return the document object, or null if XML has not been set
\r
1956 * @throws SAXException
\r
1957 * @throws IOException
\r
1958 * @throws ParserConfigurationException
\r
1960 public synchronized Document getDocument()
\r
1961 throws ParserConfigurationException, IOException, SAXException {
\r
1962 if (xml == null) {
\r
1971 * Evaluates the specified XPath expression and returns a string result.
\r
1972 * This method throws exceptions on error.
\r
1973 * @param expression the expression
\r
1974 * @return the result object
\r
1975 * @throws ParserConfigurationException
\r
1976 * @throws IOException
\r
1977 * @throws SAXException
\r
1978 * @throws XPathExpressionException on error
\r
1980 public synchronized String evaluate(String expression)
\r
1981 throws ParserConfigurationException, SAXException,
\r
1982 IOException, XPathExpressionException {
\r
1983 return (String) evaluate(expression, XPathConstants.STRING);
\r
1987 * Evaluates the specified XPath expression.
\r
1988 * This method throws exceptions on error.
\r
1989 * @param expression the expression
\r
1990 * @param returnType the return type
\r
1991 * @return the result object
\r
1992 * @throws ParserConfigurationException
\r
1993 * @throws IOException
\r
1994 * @throws SAXException
\r
1995 * @throws XPathExpressionException on error
\r
1997 public synchronized Object evaluate(String expression, QName returnType)
\r
1998 throws ParserConfigurationException, SAXException,
\r
1999 IOException, XPathExpressionException {
\r
2002 XPathExpression expr = xpath.compile(expression);
\r
2003 return expr.evaluate(doc, returnType);
\r
2007 * Private helper method that builds the document object.
\r
2008 * Assumes the calling method is synchronized.
\r
2009 * @throws ParserConfigurationException
\r
2010 * @throws IOException
\r
2011 * @throws SAXException
\r
2013 private void buildDocument() throws ParserConfigurationException,
\r
2014 IOException, SAXException {
\r
2015 if (doc == null) {
\r
2016 if (xml == null) {
\r
2017 throw new IOException("XML input is null");
\r
2020 DocumentBuilder builder = factory.newDocumentBuilder();
\r
2021 InputSource source = new InputSource(new StringReader(xml));
\r
2022 doc = builder.parse(source);
\r
2028 * A NamespaceContext class based on a Map.
\r
2030 private class SimpleNamespaceContext implements NamespaceContext {
\r
2031 private Map<String, String> prefixMap = new HashMap<>();
\r
2032 private Map<String, String> uriMap = new HashMap<>();
\r
2034 public synchronized void add(String prefix, String uri) {
\r
2035 prefixMap.put(prefix, uri);
\r
2036 uriMap.put(uri, prefix);
\r
2040 public synchronized String getNamespaceURI(String prefix) {
\r
2041 return prefixMap.get(prefix);
\r
2045 public Iterator<String> getPrefixes(String uri) {
\r
2046 List<String> list = new ArrayList<>();
\r
2047 String prefix = uriMap.get(uri);
\r
2048 if (prefix != null) {
\r
2051 return list.iterator();
\r
2055 public String getPrefix(String uri) {
\r
2056 return uriMap.get(uri);
\r
2061 * A VnfNotify XPathTool.
\r
2063 protected class VnfNotifyXPathTool extends XPathTool {
\r
2064 public VnfNotifyXPathTool() {
\r
2065 addNamespace("tns", "http://org.openecomp.mso/vnfNotify");
\r
2070 * Helper class to make it easier to create this type.
\r
2072 private static class CreateVnfNotificationOutputs
\r
2073 extends CreateVnfNotification.Outputs {
\r
2074 public void add(String key, String value) {
\r
2075 Entry entry = new Entry();
\r
2076 entry.setKey(key);
\r
2077 entry.setValue(value);
\r
2078 getEntry().add(entry);
\r
2083 * Helper class to make it easier to create this type.
\r
2085 private static class UpdateVnfNotificationOutputs
\r
2086 extends UpdateVnfNotification.Outputs {
\r
2087 public void add(String key, String value) {
\r
2088 Entry entry = new Entry();
\r
2089 entry.setKey(key);
\r
2090 entry.setValue(value);
\r
2091 getEntry().add(entry);
\r