Improve coverage FlowControlNode #7
[appc.git] / appc-config / appc-flow-controller / provider / src / main / java / org / onap / appc / flow / controller / node / FlowControlNode.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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  *
19  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.appc.flow.controller.node;
24
25 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.ACTION_LEVEL;
26 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.APPC_FLOW_CONTROLLER;
27 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.DESINGTIME;
28 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.EXTERNAL;
29 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.FLOW_SEQUENCE;
30 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.GENERATION_NODE;
31 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.GRAPH;
32 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.INPUT_PARAM_RESPONSE_PREFIX;
33 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.NODE;
34 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.OUTPUT_PARAM_ERROR_MESSAGE;
35 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.OUTPUT_PARAM_STATUS;
36 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.OUTPUT_STATUS_FAILURE;
37 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.OUTPUT_STATUS_MESSAGE;
38 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.OUTPUT_STATUS_SUCCESS;
39 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.PAYLOAD;
40 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.REQUEST_ACTION;
41 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.REQUEST_ID;
42 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.RESPONSE_PREFIX;
43 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.REST;
44 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.RUNTIME;
45 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.SEQUENCE_TYPE;
46 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.SEQ_GENERATOR_PWD;
47 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.SEQ_GENERATOR_UID;
48 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.SEQ_GENERATOR_URL;
49 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VF_MODULE;
50 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VM;
51 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VNF;
52 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VNFC;
53 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VNFC_NAME;
54 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VNFC_TYPE;
55 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VNF_ID;
56 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VNF_TYPE;
57 import static org.onap.appc.flow.controller.utils.FlowControllerConstants.VSERVER_ID;
58
59 import com.att.eelf.configuration.EELFLogger;
60 import com.att.eelf.configuration.EELFManager;
61 import com.fasterxml.jackson.annotation.JsonInclude.Include;
62 import com.fasterxml.jackson.core.type.TypeReference;
63 import com.fasterxml.jackson.databind.DeserializationFeature;
64 import com.fasterxml.jackson.databind.JsonNode;
65 import com.fasterxml.jackson.databind.ObjectMapper;
66 import com.fasterxml.jackson.databind.SerializationFeature;
67 import java.io.IOException;
68 import java.util.ArrayList;
69 import java.util.Arrays;
70 import java.util.HashMap;
71 import java.util.List;
72 import java.util.Map;
73 import java.util.Properties;
74 import org.apache.commons.lang3.StringUtils;
75 import org.json.JSONObject;
76 import org.onap.appc.flow.controller.ResponseHandlerImpl.DefaultResponseHandler;
77 import org.onap.appc.flow.controller.data.PrecheckOption;
78 import org.onap.appc.flow.controller.data.ResponseAction;
79 import org.onap.appc.flow.controller.data.Transaction;
80 import org.onap.appc.flow.controller.data.Transactions;
81 import org.onap.appc.flow.controller.dbervices.FlowControlDBService;
82 import org.onap.appc.flow.controller.executorImpl.GraphExecutor;
83 import org.onap.appc.flow.controller.executorImpl.NodeExecutor;
84 import org.onap.appc.flow.controller.executorImpl.RestExecutor;
85 import org.onap.appc.flow.controller.interfaceData.ActionIdentifier;
86 import org.onap.appc.flow.controller.interfaceData.Capabilities;
87 import org.onap.appc.flow.controller.interfaceData.DependencyInfo;
88 import org.onap.appc.flow.controller.interfaceData.Input;
89 import org.onap.appc.flow.controller.interfaceData.InventoryInfo;
90 import org.onap.appc.flow.controller.interfaceData.RequestInfo;
91 import org.onap.appc.flow.controller.interfaceData.Vnfcs;
92 import org.onap.appc.flow.controller.interfaces.FlowExecutorInterface;
93 import org.onap.appc.flow.controller.utils.EncryptionTool;
94 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
95 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
96 import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
97
98 public class FlowControlNode implements SvcLogicJavaPlugin {
99
100   private static final EELFLogger log = EELFManager.getInstance().getLogger(FlowControlNode.class);
101   private static final String SDNC_CONFIG_DIR_VAR = "SDNC_CONFIG_DIR";
102
103   private final EnvVariables envVariables;
104   private final FlowControlDBService dbService;
105
106   public FlowControlNode() {
107     this.envVariables = new EnvVariables();
108     this.dbService = FlowControlDBService.initialise();
109   }
110
111   FlowControlNode(EnvVariables envVariables, FlowControlDBService dbService) {
112     this.envVariables = envVariables;
113     this.dbService = dbService;
114   }
115
116   public void processFlow(Map<String, String> inParams, SvcLogicContext ctx)
117       throws SvcLogicException {
118     log.debug("Received processParamKeys call with params : " + inParams);
119     String responsePrefix = inParams.get(INPUT_PARAM_RESPONSE_PREFIX);
120     try {
121       responsePrefix = StringUtils.isNotBlank(responsePrefix) ? (responsePrefix + ".") : "";
122       SvcLogicContext localContext = new SvcLogicContext();
123
124       localContext.setAttribute(REQUEST_ID, ctx.getAttribute(REQUEST_ID));
125       localContext.setAttribute(VNF_TYPE, ctx.getAttribute(VNF_TYPE));
126       localContext.setAttribute(REQUEST_ACTION, ctx.getAttribute(REQUEST_ACTION));
127       localContext.setAttribute(ACTION_LEVEL, ctx.getAttribute(ACTION_LEVEL));
128       localContext.setAttribute(RESPONSE_PREFIX, responsePrefix);
129       ctx.setAttribute(RESPONSE_PREFIX, responsePrefix);
130
131       dbService.getFlowReferenceData(ctx, inParams, localContext);
132
133       for (String key : localContext.getAttributeKeySet()) {
134         log.debug("processFlow " + key + "=" + ctx.getAttribute(key));
135       }
136       processFlowSequence(inParams, ctx, localContext);
137       if (!ctx.getAttribute(responsePrefix + OUTPUT_PARAM_STATUS).equals(OUTPUT_STATUS_SUCCESS)) {
138         throw new SvcLogicException(ctx.getAttribute(responsePrefix + OUTPUT_STATUS_MESSAGE));
139       }
140     } catch (Exception e) {
141       ctx.setAttribute(responsePrefix + OUTPUT_PARAM_STATUS, OUTPUT_STATUS_FAILURE);
142       ctx.setAttribute(responsePrefix + OUTPUT_PARAM_ERROR_MESSAGE, e.getMessage());
143       log.error("Error occurred in processFlow ", e);
144       throw new SvcLogicException(e.getMessage());
145     }
146   }
147
148   private void processFlowSequence(Map<String, String> inParams, SvcLogicContext ctx, SvcLogicContext localContext)
149       throws Exception {
150
151     String fn = "FlowExecutorNode.processflowSequence";
152     log.debug(fn + "Received model for flow : " + localContext.toString());
153     
154     String flowSequence = null;
155     for (String key : localContext.getAttributeKeySet()) {
156       log.debug(key + "=" + ctx.getAttribute(key));
157     }
158     if (localContext.getAttribute(SEQUENCE_TYPE) != null) {
159       if (localContext.getAttribute(GENERATION_NODE) != null) {
160         GraphExecutor transactionExecutor = new GraphExecutor();
161         Boolean generatorExists = transactionExecutor.hasGraph(
162             "APPC_COMMOM",
163             localContext.getAttribute(GENERATION_NODE),
164             null,
165             "sync"
166         );
167
168         if (generatorExists) {
169           flowSequence = transactionExecutor.executeGraph(
170               "APPC_COMMOM",
171               localContext.getAttribute(GENERATION_NODE),
172               null, "sync", null)
173               .getProperty(FLOW_SEQUENCE);
174         } else {
175           throw new Exception("Can not find Custom defined Flow Generator for "
176               + localContext.getAttribute(GENERATION_NODE));
177         }
178
179       } else if ((localContext.getAttribute(SEQUENCE_TYPE)).equalsIgnoreCase(DESINGTIME)) {
180
181         localContext.setAttribute(VNFC_TYPE, ctx.getAttribute(VNFC_TYPE));
182         flowSequence = dbService.getDesignTimeFlowModel(localContext);
183
184         if (flowSequence == null) {
185           throw new Exception("Flow Sequence is not found User Designed VNF " + ctx.getAttribute(VNF_TYPE));
186         }
187
188       } else if ((localContext.getAttribute(SEQUENCE_TYPE)).equalsIgnoreCase(RUNTIME)) {
189
190         Transaction transaction = new Transaction();
191         String input = collectInputParams(ctx, transaction);
192         log.info("CollectInputParamsData-Input: " + input);
193
194         RestExecutor restExe = new RestExecutor();
195         Map<String, String> flowSeq = restExe.execute(transaction, localContext);
196
197         JSONObject sequence = new JSONObject(flowSeq.get("restResponse"));
198         if (sequence.has("output")) {
199           flowSequence = sequence.getJSONObject("output").toString();
200         }
201         log.info("MultistepSequenceGenerator-Output: " + flowSequence);
202
203         if (flowSequence == null) {
204           throw new Exception("Failed to get the Flow Sequece runtime for VNF type"
205               + ctx.getAttribute(VNF_TYPE));
206         }
207
208       } else if ((localContext.getAttribute(SEQUENCE_TYPE)).equalsIgnoreCase(EXTERNAL)) {
209         //String input = collectInputParams(localContext);
210         //    flowSequnce = ""; //get it from the External interface calling the Rest End point - TBD
211         //if(flowSequnce == null)
212
213         throw new Exception("Flow Sequence not found for " + ctx.getAttribute(VNF_TYPE));
214
215       } else {
216         //No other type of model supported...
217         //in Future can get flowModel from other generators which will be included here
218         throw new Exception("No information found for sequence Owner Design-Time Vs Run-Time");
219       }
220
221     } else {
222       FlowGenerator flowGenerator = new FlowGenerator();
223       Transactions trans = flowGenerator.createSingleStepModel(inParams, ctx);
224       ObjectMapper mapper = new ObjectMapper();
225       flowSequence = mapper.writeValueAsString(trans);
226       log.debug("Single step Flow Sequence : " + flowSequence);
227     }
228
229     log.debug("Received Flow Sequence : " + flowSequence);
230     HashMap<Integer, Transaction> transactionMap = createTransactionMap(flowSequence, localContext);
231     executeAllTransaction(transactionMap, ctx);
232     log.info("Executed all the transaction successfully");
233   }
234
235   private void executeAllTransaction(HashMap<Integer, Transaction> transactionMap, SvcLogicContext ctx)
236       throws Exception {
237
238     String fn = "FlowExecutorNode.executeAllTransaction ";
239     int retry = 0;
240     FlowExecutorInterface flowExecutor;
241     for (int key = 1; key <= transactionMap.size(); key++) {
242       log.debug(fn + "Starting transactions ID " + key + " :)=" + retry);
243       Transaction transaction = transactionMap.get(key);
244       if (!preProcessor(transactionMap, transaction)) {
245         log.info("Skipping Transaction ID " + transaction.getTransactionId());
246         continue;
247       }
248       if (transaction.getExecutionType() != null) {
249         switch (transaction.getExecutionType()) {
250           case GRAPH:
251             flowExecutor = new GraphExecutor();
252             break;
253           case NODE:
254             flowExecutor = new NodeExecutor();
255             break;
256           case REST:
257             flowExecutor = new RestExecutor();
258             break;
259           default:
260             throw new Exception("No Executor found for transaction ID" + transaction.getTransactionId());
261         }
262         flowExecutor.execute(transaction, ctx);
263         ResponseAction responseAction = handleResponse(transaction);
264
265         if (responseAction.getWait() != null && Integer.parseInt(responseAction.getWait()) > 0) {
266           log.debug(fn + "Going to Sleep .... " + responseAction.getWait());
267           Thread.sleep(Integer.parseInt(responseAction.getWait()) * 1000L);
268         }
269         if (responseAction.isIntermediateMessage()) {
270           log.debug(fn + "Sending Intermediate Message back  .... ");
271           sendIntermediateMessage();
272         }
273         if (responseAction.getRetry() != null && Integer.parseInt(responseAction.getRetry()) > retry) {
274           log.debug(fn + "Ooppss!!! We will retry again ....... ");
275           key--;
276           retry++;
277           log.debug(fn + "key =" + key + "retry =" + retry);
278         }
279         if (responseAction.isIgnore()) {
280           log.debug(fn + "Ignoring this Error and moving ahead  ....... ");
281           continue;
282         }
283         if (responseAction.isStop()) {
284           log.debug(fn + "Need to Stop  ....... ");
285           break;
286         }
287         if (responseAction.getJump() != null && Integer.parseInt(responseAction.getJump()) > 0) {
288           key = Integer.parseInt(responseAction.getJump());
289           key--;
290         }
291         log.debug(fn + "key =" + key + "retry =" + retry);
292
293       } else {
294         throw new Exception("Don't know how to execute transaction ID " + transaction.getTransactionId());
295       }
296     }
297   }
298
299   private void sendIntermediateMessage() {
300     // TODO Auto-generated method stub
301   }
302
303   private ResponseAction handleResponse(Transaction transaction) {
304     log.info("Handling Response for transaction Id " + transaction.getTransactionId());
305     DefaultResponseHandler defaultHandler = new DefaultResponseHandler();
306     return defaultHandler.handlerResponse(transaction);
307   }
308
309   private boolean preProcessor(HashMap<Integer, Transaction> transactionMap, Transaction transaction)
310       throws IOException {
311
312     log.debug("Starting Preprocessing Logic ");
313     boolean runThisStep = false;
314     try {
315       if (transaction.getPrecheck() != null
316           && transaction.getPrecheck().getPrecheckOptions() != null
317           && !transaction.getPrecheck().getPrecheckOptions().isEmpty()) {
318
319         List<PrecheckOption> precheckOptions = transaction.getPrecheck().getPrecheckOptions();
320         for (PrecheckOption precheck : precheckOptions) {
321           Transaction trans = transactionMap.get(precheck.getpTransactionID());
322           ObjectMapper mapper = new ObjectMapper();
323           log.info("Mapper= " + mapper.writeValueAsString(trans));
324           HashMap trmap = mapper.readValue(mapper.writeValueAsString(trans), HashMap.class);
325           runThisStep = trmap.get(precheck.getParamName()) != null
326               && ((String) trmap.get(precheck.getParamName()))
327               .equalsIgnoreCase(precheck.getParamValue());
328
329           if (("any").equalsIgnoreCase(transaction.getPrecheck().getPrecheckOperator()) && runThisStep) {
330             break;
331           }
332         }
333       } else {
334         log.debug("No Pre check defined for transaction ID " + transaction.getTransactionId());
335         runThisStep = true;
336       }
337     } catch (Exception e) {
338       log.error("Error occured when Preprocessing Logic ", e);
339       throw e;
340     }
341     log.debug("Returing process current Transaction = " + runThisStep);
342     return runThisStep;
343   }
344
345   private HashMap<Integer, Transaction> createTransactionMap(String flowSequence, SvcLogicContext localContext)
346       throws Exception {
347
348     ObjectMapper mapper = new ObjectMapper();
349     Transactions transactions = mapper.readValue(flowSequence, Transactions.class);
350     HashMap<Integer, Transaction> transMap = new HashMap<>();
351     for (Transaction transaction : transactions.getTransactions()) {
352       compileFlowDependencies(transaction, localContext);
353       //parse the Transactions Object and create records in process_flow_status table
354       //loadTransactionIntoStatus(transactions, ctx);
355       transMap.put(transaction.getTransactionId(), transaction);
356     }
357     return transMap;
358   }
359
360   private void compileFlowDependencies(Transaction transaction, SvcLogicContext localContext)
361       throws Exception {
362
363     dbService.populateModuleAndRPC(transaction, localContext.getAttribute(VNF_TYPE));
364     ObjectMapper mapper = new ObjectMapper();
365     log.debug("Individual Transaction Details :" + transaction.toString());
366
367     if ((localContext.getAttribute(SEQUENCE_TYPE) == null)
368         || (localContext.getAttribute(SEQUENCE_TYPE) != null
369         && !localContext.getAttribute(SEQUENCE_TYPE)
370         .equalsIgnoreCase(DESINGTIME))) {
371
372       localContext.setAttribute("artifact-content", mapper.writeValueAsString(transaction));
373       dbService.loadSequenceIntoDB(localContext);
374     }
375     //get a field in transction class as transactionhandle interface and register the Handler here for each trnactions
376   }
377
378   private String collectInputParams(SvcLogicContext ctx, Transaction transaction) throws Exception {
379
380     String fn = "FlowExecuteNode.collectInputParams";
381     Properties prop = loadProperties();
382     log.info("Loaded Properties " + prop.toString());
383
384     String vnfId = ctx.getAttribute(VNF_ID);
385     String inputData = null;
386     log.debug(fn + "vnfId :" + vnfId);
387
388     if (StringUtils.isBlank(vnfId)) {
389       throw new Exception("VnfId is missing");
390     }
391
392     try {
393       ActionIdentifier actionIdentifier = new ActionIdentifier();
394       log.debug("Enter ActionIdentifier");
395       if (StringUtils.isNotBlank(vnfId)) {
396         actionIdentifier.setVnfId(vnfId);
397       }
398       if (StringUtils.isNotBlank(ctx.getAttribute(VSERVER_ID))) {
399         actionIdentifier.setVserverId(ctx.getAttribute(VSERVER_ID));
400       }
401       if (StringUtils.isNotBlank(ctx.getAttribute(VNFC_NAME))) {
402         actionIdentifier.setVnfcName(ctx.getAttribute(VNFC_NAME));
403       }
404       log.info("ActionIdentifierData" + actionIdentifier.toString());
405
406       RequestInfo requestInfo = new RequestInfo();
407       log.info("Enter RequestInfo");
408       requestInfo.setAction(ctx.getAttribute(REQUEST_ACTION));
409       requestInfo.setActionLevel(ctx.getAttribute(ACTION_LEVEL));
410       requestInfo.setPayload(ctx.getAttribute(PAYLOAD));
411       requestInfo.setActionIdentifier(actionIdentifier);
412       log.debug("RequestInfo: " + requestInfo.toString());
413
414       InventoryInfo inventoryInfo = new InventoryInfoExtractor().getInventoryInfo(ctx, vnfId);
415       DependencyInfo dependencyInfo = getDependencyInfo(ctx);
416       Capabilities capabilities = getCapabilitiesData(ctx);
417
418       Input input = new Input();
419       log.info("Enter InputData");
420       input.setRequestInfo(requestInfo);
421       input.setInventoryInfo(inventoryInfo);
422       input.setDependencyInfo(dependencyInfo);
423       input.setCapabilities(capabilities);
424       log.info(fn + "Input parameters:" + input.toString());
425
426       ObjectMapper mapper = new ObjectMapper();
427       mapper.setSerializationInclusion(Include.NON_NULL);
428       mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
429       inputData = mapper.writeValueAsString(input);
430       log.info("InputDataJson:" + inputData);
431
432     } catch (Exception e) {
433       log.error("Error occurred in " + fn, e);
434     }
435
436     String resourceUri = prop.getProperty(SEQ_GENERATOR_URL);
437     log.info(fn + "resourceUri= " + resourceUri);
438
439     EncryptionTool et = EncryptionTool.getInstance();
440     String pass = et.decrypt(prop.getProperty(SEQ_GENERATOR_PWD));
441
442     transaction.setPayload(inputData);
443     transaction.setExecutionRPC("POST");
444     transaction.setuId(prop.getProperty(SEQ_GENERATOR_UID));
445     transaction.setPswd(pass);
446     transaction.setExecutionEndPoint(resourceUri);
447
448     return inputData;
449   }
450
451   private DependencyInfo getDependencyInfo(SvcLogicContext ctx) throws Exception {
452
453     String fn = "FlowExecutorNode.getDependencyInfo";
454     DependencyInfo dependencyInfo = new DependencyInfo();
455     String dependencyData = dbService.getDependencyInfo(ctx);
456     log.info(fn + "dependencyDataInput:" + dependencyData);
457
458     if (dependencyData != null) {
459       ObjectMapper mapper = new ObjectMapper();
460       mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
461       mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
462       //JsonNode dependencyInfoData = mapper.readTree(dependencyData).get("dependencyInfo");
463       JsonNode vnfcData = mapper.readTree(dependencyData).get("vnfcs");
464       List<Vnfcs> vnfclist = Arrays.asList(mapper.readValue(vnfcData.toString(), Vnfcs[].class));
465       dependencyInfo.getVnfcs().addAll(vnfclist);
466
467       log.info("Dependency Output:" + dependencyInfo.toString());
468     }
469     return dependencyInfo;
470   }
471
472   Capabilities getCapabilitiesData(SvcLogicContext ctx) throws Exception {
473
474     String fn = "FlowExecutorNode.getCapabilitiesData";
475     String capabilitiesData = dbService.getCapabilitiesData(ctx);
476     log.info(fn + "capabilitiesDataInput:" + capabilitiesData);
477
478     Capabilities capabilities = new Capabilities();
479     if (capabilitiesData == null) {
480       return capabilities;
481     }
482
483     ObjectMapper mapper = new ObjectMapper();
484     mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
485     mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
486
487     JsonNode capabilitiesNode = mapper.readTree(capabilitiesData);
488     log.info("capabilitiesNode:" + capabilitiesNode.toString());
489
490     capabilities.getVfModule().addAll(extractParameterList(mapper, capabilitiesNode, VF_MODULE));
491     capabilities.getVnfc().addAll(extractParameterList(mapper, capabilitiesNode, VNFC));
492     capabilities.getVnf().addAll(extractParameterList(mapper, capabilitiesNode, VNF));
493     capabilities.getVm().addAll(extractParameterList(mapper, capabilitiesNode, VM));
494
495     log.info("Capabilities Output:" + capabilities.toString());
496
497     return capabilities;
498   }
499
500   private <T> List<T> extractParameterList(ObjectMapper mapper, JsonNode root, String parameter) throws IOException {
501     JsonNode parameterNode = root.get(parameter);
502     if (parameterNode == null) {
503       return new ArrayList<>();
504     }
505     return mapper.readValue(parameterNode.toString(), new TypeReference<List<T>>() {});
506   }
507
508   private Properties loadProperties() throws Exception {
509     String directory = envVariables.getenv(SDNC_CONFIG_DIR_VAR);
510     if (directory == null) {
511       throw new Exception("Cannot find Property file -" + SDNC_CONFIG_DIR_VAR);
512     }
513     String path = directory + APPC_FLOW_CONTROLLER;
514     return PropertiesLoader.load(path);
515   }
516 }