Merge "Reduced code complexity"
[cli.git] / framework / src / main / java / org / onap / cli / fw / utils / OnapCommandUtils.java
1 /*
2  * Copyright 2017 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.cli.fw.utils;
18
19 import static org.onap.cli.fw.conf.OnapCommandConstants.BOOLEAN_TRUE;
20 import static org.onap.cli.fw.conf.OnapCommandConstants.BOOLEAN_VALUE;
21 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_INCLUDE;
22
23 import java.io.File;
24 import java.io.IOException;
25 import java.nio.charset.Charset;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Map.Entry;
32 import java.util.Set;
33 import java.util.UUID;
34
35 import org.apache.commons.codec.binary.Base64;
36 import org.apache.commons.codec.digest.DigestUtils;
37 import org.apache.commons.io.FileUtils;
38 import org.onap.cli.fw.cmd.OnapCommand;
39 import org.onap.cli.fw.conf.OnapCommandConfig;
40 import org.onap.cli.fw.conf.OnapCommandConstants;
41 import org.onap.cli.fw.error.OnapCommandException;
42 import org.onap.cli.fw.error.OnapCommandInvalidParameterValue;
43 import org.onap.cli.fw.error.OnapCommandParameterNotFound;
44 import org.onap.cli.fw.error.OnapCommandResultEmpty;
45 import org.onap.cli.fw.input.OnapCommandParameter;
46 import org.onap.cli.fw.input.OnapCommandParameterType;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 import com.google.gson.Gson;
51 import com.google.gson.GsonBuilder;
52 import com.jayway.jsonpath.JsonPath;
53
54
55 /**
56  * Provides helper method to parse Yaml files and produce required objects.
57  *
58  */
59 public class OnapCommandUtils {
60
61     static Logger log = LoggerFactory.getLogger(OnapCommandUtils.class);
62     private static Gson gson = new GsonBuilder().serializeNulls().create();
63
64     /**
65      * Private constructor.
66      */
67     private OnapCommandUtils() {
68
69     }
70
71     public static void throwOrCollect(OnapCommandException ex, List<String> list, boolean shouldCollectException)
72             throws OnapCommandException {
73         if (shouldCollectException) {
74             list.add(ex.getMessage());
75         } else {
76             throw ex;
77         }
78     }
79
80     public static void validateTags(List<String> schemaErrors, Map<String, ?> yamlMap, List<String> totalParams,
81             List<String> mandatoryParams, String section) {
82         // mrkanag capture invalid entries as well
83         for (String param : totalParams) {
84             boolean isMandatory = mandatoryParams.contains(param);
85             boolean isYamlContains = yamlMap.containsKey(param);
86             boolean isInclude = yamlMap.containsKey(IS_INCLUDE) && yamlMap.get(IS_INCLUDE).toString().equals(BOOLEAN_TRUE);
87             if (isMandatory) {
88                 if (!isYamlContains && isInclude) {
89                     schemaErrors.add("Mandatory attribute '" + param + "' is missing under '" + section + "'");
90                 } else {
91                     String value = String.valueOf(yamlMap.get(param));
92                     if (value == null || value.isEmpty()) {
93                         schemaErrors.add("Mandatory attribute '" + param + "' under '" + section
94                                 + "' shouldn't be null or empty");
95                     }
96                 }
97             }
98         }
99     }
100
101     /**
102      * Validate Boolean.
103      *
104      * @param toValidate
105      *            string
106      * @return boolean
107      */
108     public static boolean validateBoolean(String toValidate) {
109         return OnapCommandConfig.getCommaSeparatedList(BOOLEAN_VALUE).contains(toValidate.toLowerCase());
110     }
111
112     public static String emptySection(String section) {
113         return "The section '" + section + ":' cann't be null or empty";
114     }
115
116     public static String invalidBooleanValueMessage(String section, String attribute, String value) {
117         return "The value '" + value + "' of '" + attribute + "' present under '" + section + "' should be boolean";
118     }
119
120     public static void parseParameters(String line, Set<String> paramNames) {
121
122         int currentIdx = 0;
123         while (currentIdx < line.length()) {
124             int idxS = line.indexOf("${", currentIdx);
125             if (idxS == -1) {
126                 break;
127             }
128             int idxE = line.indexOf('}', idxS);
129             String paramName = line.substring(idxS + 2, idxE);
130             paramNames.add(paramName.trim());
131
132             currentIdx = idxE + 1;
133         }
134
135     }
136
137     /**
138      * Create Dict from list of Parameters.
139      *
140      * @param inputs
141      *            list of parameters
142      * @return map
143      */
144     public static Map<String, OnapCommandParameter> getInputMap(Set<OnapCommandParameter> inputs) {
145         Map<String, OnapCommandParameter> map = new HashMap<>();
146         for (OnapCommandParameter param : inputs) {
147             map.put(param.getName(), param);
148         }
149         return map;
150     }
151
152     /**
153      * sort the set.
154      *
155      * @param col
156      *            set
157      * @return list
158      */
159     public static List<String> sort(Set<String> col) {
160         List<String> results = new ArrayList<>();
161         results.addAll(col);
162         Collections.sort(results);
163         return results;
164     }
165
166     /**
167      * Flatten the json list.
168      *
169      * @param jsons
170      *            list json strings
171      * @return list
172      */
173     public static List<String> jsonFlatten(List<String> jsons) {
174         List<String> results = new ArrayList<>();
175         for (String json : jsons) {
176             try {
177                 results.add(JsonPath.parse(json).jsonString());
178             } catch (Exception e) { // NOSONAR
179                 results.add(json);
180             }
181         }
182
183         return results;
184     }
185
186     /**
187      * There are unique values like uuid is supported, so when input, output (default) values has
188      * these special entries, then it will get replaced with it's value
189      *
190      * @param lineSpl
191      * @return
192      */
193     public static String replaceLineForSpecialValues(String lineSpl) {
194         return replaceLineForSpecialValues(lineSpl, new HashMap<>());
195     }
196
197     /**
198      *
199      * @param lineSpl
200      * @param values Value for the given entry already known by the caller.
201      * @return
202      */
203     public static String replaceLineFromResults(String line, Map <String, String> values) {
204         StringBuilder resultLine = new StringBuilder();
205
206         if (!line.contains("$r{")) {
207             return line;
208         }
209
210         int currentIdx = 0;
211         while (currentIdx < line.length()) {
212             int idxS = line.indexOf("$r{", currentIdx);
213             if (idxS == -1) {
214                 resultLine.append(line.substring(currentIdx));
215                 break;
216             }
217             int idxE = line.indexOf('}', idxS);
218             String attr = line.substring(idxS + 3, idxE);
219             attr = attr.trim();
220
221             String value = "";
222
223             if (values.get(attr) != null) {
224                 value = values.get(attr);
225             } else {
226                 value = attr;
227             }
228
229             resultLine.append(line.substring(currentIdx, idxS) + value);
230             currentIdx = idxE + 1;
231         }
232
233         return resultLine.toString();
234     }
235
236     public static String replaceLineForSpecialValues(String lineSpl, Map <String, String> values) {
237         StringBuilder resultSpl = new StringBuilder();
238
239         if (!lineSpl.contains("$s{")) {
240             return lineSpl;
241         }
242
243         int currentIdx = 0;
244         while (currentIdx < lineSpl.length()) {
245             int idxS = lineSpl.indexOf("$s{", currentIdx);
246             if (idxS == -1) {
247                 resultSpl.append(lineSpl.substring(currentIdx));
248                 break;
249             }
250             int idxE = lineSpl.indexOf('}', idxS);
251             String splEntry = lineSpl.substring(idxS + 3, idxE);
252             splEntry = splEntry.trim();
253
254             String value = "";
255
256             if (OnapCommandConstants.SPL_ENTRY_UUID.equals(splEntry)) {
257                     value = UUID.randomUUID().toString();
258             }
259                 else{
260                     if (splEntry.startsWith(OnapCommandConstants.SPL_ENTRY_ENV)) {
261                         //start to read after env:ENV_VAR_NAME
262                         String envVarName = splEntry.substring(4);
263                         value = System.getenv(envVarName); //NOSONAR
264                         if (value == null) {
265                             //when env is not defined, assign the same env:ENV_VAR_NAME
266                             //so that it will given hit to user that ENV_VAR_NAME to be
267                             //defined.
268                             value = splEntry;
269                         }
270                     } else if (splEntry.startsWith(OnapCommandConstants.SPL_ENTRY_FILE)) {
271                         //start to read after file:filepath
272                         String fileName = splEntry.substring(5);
273                         try {
274                             value = FileUtils.readFileToString((new File(fileName)), (Charset) null);
275                         } catch (IOException e) {
276                             //when file is not found, assign the same file:FILE_PATH
277                             //so that it will given hit to user that FILE_PATH to be
278                             //exist.
279                             value = "";
280                         }
281                     } else if (splEntry.startsWith(OnapCommandConstants.SPL_ENTRY_MD5)) {
282                             //start to read after md5:entryname
283                             String entryName = splEntry.substring(4);
284                             String content = values.get(entryName);
285                             if (content != null)
286                                 value = OnapCommandUtils.md5(content);
287                             else
288                                 value = splEntry;
289                     } else {
290                         if (values.get(splEntry) != null) {
291                             value = values.get(splEntry);
292                         } else {
293                             value = splEntry;
294                         }
295                     }
296             }
297
298             resultSpl.append(lineSpl.substring(currentIdx, idxS) + value);
299             currentIdx = idxE + 1;
300         }
301
302         return resultSpl.toString();
303     }
304
305     public static String replaceLineFromInputParameters(String line, Map<String, OnapCommandParameter> params)
306             throws OnapCommandException {
307         StringBuilder result = new StringBuilder();
308
309         if (!line.contains("${")) {
310             return line;
311         }
312
313         int currentIdx = 0;
314         while (currentIdx < line.length()) {
315             int idxS = line.indexOf("${", currentIdx);
316             if (idxS == -1) {
317                 result.append(line.substring(currentIdx));
318                 break;
319             }
320             int idxE = line.indexOf('}', idxS);
321             String paramName = line.substring(idxS + 2, idxE);
322             paramName = paramName.trim();
323             if (!params.containsKey(paramName)) {
324                 throw new OnapCommandParameterNotFound(paramName);
325             }
326
327             OnapCommandParameter param = params.get(paramName);
328             if (OnapCommandParameterType.ARRAY.equals(param.getParameterType())
329                     || OnapCommandParameterType.JSON.equals(param.getParameterType())
330                     || OnapCommandParameterType.YAML.equals(param.getParameterType())) {
331                 // ignore the front and back double quotes in json body
332                 String value = params.get(paramName).getValue().toString();
333                 if (idxS > 0)
334                     result.append(line.substring(currentIdx, idxS - 1) + value);
335                 else
336                     result.append(value);
337                 currentIdx = idxE + 2;
338             } else if (OnapCommandParameterType.MAP.equals(param.getParameterType())) {
339                 try {
340                     String value = gson.toJson(params.get(paramName).getValue());
341                     if ((idxS == 0) && (currentIdx == 0)) {
342                         result.replace(0, result.length(), value);
343                     } else {
344                         result.append(line.substring(currentIdx, idxS - 1) + value);
345                     }
346                 } catch (Exception e) {  // NOSONAR
347                     //never occur as map is coverted to json string here
348                 }
349
350                 currentIdx = idxE + 2;
351             }else {
352                 result.append(line.substring(currentIdx, idxS) + params.get(paramName).getValue().toString());
353                 currentIdx = idxE + 1;
354             }
355         }
356
357         return result.toString();
358     }
359
360     /**
361      * Populate result from input parameters.
362      *
363      * @param resultMap
364      *            map
365      * @param params
366      *            Map<String, OnapCommandParameter>
367      * @return map
368      * @throws OnapCommandException
369      */
370     public static Map<String, ArrayList<String>> populateOutputsFromInputParameters(
371             Map<String, ArrayList<String>> resultMap,
372             Map<String, OnapCommandParameter> params)
373             throws OnapCommandException {
374         Map<String, ArrayList<String>> resultsProcessed = new HashMap<>();
375
376         for (Entry<String, ArrayList<String>> entry : resultMap.entrySet()) {
377             String key = entry.getKey();
378             resultsProcessed.put(key, new ArrayList<>());
379             for (String value: entry.getValue()) {
380                 try {
381                     value = replaceLineFromInputParameters(value, params);
382                 } catch(OnapCommandResultEmpty e) {  // NOSONAR
383                     // pass
384                 }
385                 resultsProcessed.get(key).add(value);
386             }
387         }
388
389         return resultsProcessed;
390     }
391
392     /**
393      * Copy the parameters across the commands, mainly used for catalog, login and logout commands
394      *
395      * @throws OnapCommandInvalidParameterValue
396      */
397     public static void copyParamsFrom(OnapCommand from, OnapCommand to, Map<String, String> paramOverride) throws OnapCommandInvalidParameterValue {
398         for (OnapCommandParameter param: to.getParameters()) {
399
400             OnapCommandParameter fromParam = from.getParametersMap().get(param.getName());
401
402             if (fromParam != null) {
403                 param.setValue(fromParam.getValue());
404                 param.setDefaultValue(fromParam.getDefaultValue());
405             }
406
407             if (paramOverride.containsKey(param.getName())) {
408                  param.setValue(paramOverride.get(param.getName()));
409             }
410         }
411     }
412
413     public static void copyParamsFrom(OnapCommand from, OnapCommand to) throws OnapCommandInvalidParameterValue {
414         copyParamsFrom(from, to, new HashMap<>());
415     }
416
417     /**
418      * Copy param schema from source command to destination command, useful in adding login command params into command
419      * @param from
420      * @param to
421      * @throws OnapCommandException
422      */
423     public static void copyParamSchemasFrom(OnapCommand from, OnapCommand to) {
424         for (OnapCommandParameter param: from.getParameters()) {
425             if (!to.getParametersMap().containsKey(param.getName())) {
426                 to.getParameters().add(param);
427             }
428         }
429     }
430
431     public static String md5(String content) {
432         String md5 = DigestUtils.md5Hex(content); //NOSONAR
433
434         byte[] encodeBase64 = Base64.encodeBase64(md5.getBytes());
435         return new String(encodeBase64);
436     }
437 }
438
439
440