Make use of try with resource
[cli.git] / framework / src / main / java / org / onap / cli / fw / output / print / OnapCommandPrint.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.output.print;
18
19 import java.io.IOException;
20 import java.io.StringWriter;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.StringTokenizer;
28
29 import org.apache.commons.csv.CSVFormat;
30 import org.apache.commons.csv.CSVPrinter;
31 import org.onap.cli.fw.conf.OnapCommandConstants;
32 import org.onap.cli.fw.error.OnapCommandOutputPrintingFailed;
33 import org.onap.cli.fw.output.OnapCommandPrintDirection;
34
35 import com.fasterxml.jackson.core.JsonProcessingException;
36 import com.fasterxml.jackson.databind.ObjectMapper;
37 import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
38
39 import net.minidev.json.JSONArray;
40 import net.minidev.json.JSONObject;
41 /**
42  * Oclip Command Table print.
43  *
44  */
45 public class OnapCommandPrint {
46
47     public static final int MAX_COLUMN_LENGTH = 50;
48
49     private OnapCommandPrintDirection direction;
50
51     private Map<String, List<String>> data = new LinkedHashMap<>();
52
53     private boolean printTitle = true;
54
55     public OnapCommandPrintDirection getDirection() {
56         return direction;
57     }
58
59     public void setDirection(OnapCommandPrintDirection direction) {
60         this.direction = direction;
61     }
62
63     public void addColumn(String header, List<String> data) {
64         this.data.put(header, data);
65     }
66
67     /**
68      * Get column.
69      *
70      * @param header
71      *            string
72      * @return list
73      */
74     public List<String> getColumn(String header) {
75         if (this.data.get(header) == null) {
76             this.data.put(header, new ArrayList<String>());
77         }
78         return this.data.get(header);
79     }
80
81     public boolean isPrintTitle() {
82         return printTitle;
83     }
84
85     public void setPrintTitle(boolean printTitle) {
86         this.printTitle = printTitle;
87     }
88
89     private int findMaxRows() {
90         int max = 1;
91         if (!this.isPrintTitle()) {
92             max = 0;
93         }
94         for (List<String> cols : this.data.values()) {
95             if (cols != null && max < cols.size()) {
96                 max = cols.size();
97             }
98         }
99
100         return max;
101     }
102
103     /**
104      * Helps to form the rows from columns.
105      *
106      * @param isNormalize
107      *            boolean
108      * @return +--------------+-----------+-----------------------------+ | header1 | header 2 | header 3 |
109      *         +--------------+-----------+-----------------------------+ | v1 | List[line| v 3 | | | 1, line2]| |
110      *         +--------------+-----------+-----------------------------+ | null | yyyyyy 2 | xxxxxx 3 |
111      *         +--------------+-----------+-----------------------------+
112      */
113     private List<List<Object>> formRows(boolean isNormalize) {
114         List<List<Object>> rows = new ArrayList<>();
115
116         // add title
117         if (this.isPrintTitle()) {
118             List<Object> list = new ArrayList<>();
119             for (String key : this.data.keySet()) {
120                 if (isNormalize && key != null && key.length() > MAX_COLUMN_LENGTH) {
121                     list.add(splitIntoList(key, MAX_COLUMN_LENGTH));
122                 } else {
123                     list.add(key);
124                 }
125             }
126             rows.add(list);
127         }
128
129         // form row
130         for (int i = 0; i < this.findMaxRows(); i++) {
131             List<Object> row = new ArrayList<>();
132             for (List<String> cols : this.data.values()) {
133                 if (cols != null && cols.size() > i) {
134                     String value = cols.get(i);
135                     // split the cell into multiple sub rows
136                     if (isNormalize && value != null && value.length() > MAX_COLUMN_LENGTH) {
137                         row.add(splitIntoList(value, MAX_COLUMN_LENGTH));
138                     } else {
139                         // store as string (one entry)
140                         row.add(value);
141                     }
142                 } else {
143                     // no value exist for this column
144                     row.add(null);
145                 }
146             }
147             rows.add(row);
148         }
149
150         return rows;
151     }
152
153     /**
154      * Splits big strings into list of strings based on maxCharInLine size.
155      *
156      * @param input
157      *            input string
158      * @param maxCharInLine
159      *            max length
160      * @return list of strings
161      */
162     public List<String> splitIntoList(String input, int maxCharInLine) {
163
164         String inp = input;
165
166         if (inp == null || "".equals(inp) || maxCharInLine <= 0) {
167             return Collections.emptyList();
168         }
169         // new line is converted to space char
170         if (inp.contains("\n")) {
171             inp = inp.replaceAll("\n", "");
172         }
173
174         StringTokenizer tok = new StringTokenizer(inp, " ");
175         StringBuilder output = new StringBuilder(inp.length());
176         int lineLen = 0;
177         while (tok.hasMoreTokens()) {
178             String word = tok.nextToken();
179
180             while (word.length() >= maxCharInLine) {
181                 output.append(word.substring(0, maxCharInLine - lineLen) + "\n");
182                 word = word.substring(maxCharInLine - lineLen);
183                 lineLen = 0;
184             }
185
186             if (lineLen + word.length() >= maxCharInLine) {
187                 output.append("\n");
188                 lineLen = 0;
189             }
190             output.append(word + " ");
191
192             lineLen += word.length() + 1;
193         }
194         String[] strArray = output.toString().split("\n");
195
196         return Arrays.asList(strArray);
197     }
198
199     /**
200      * Helps to print table.
201      *
202      * @param printSeparator
203      *            Prints with line separator
204      * @return +--------------+-----------+-----------------------------+ | header1 | header 2 | header 3 |
205      *         +--------------+-----------+-----------------------------+ | v1 | line 1 | v 3 | | | line 2 | |
206      *         +--------------+-----------+-----------------------------+ | | yyyyyy 2 | xxxxxx 3 |
207      *         +--------------+-----------+-----------------------------+
208      */
209     public String printTable(boolean printSeparator) {
210         List<List<Object>> rows = this.formRows(true);
211         TableGenerator table = new TableGenerator();
212         return table.generateTable(rows, printSeparator);
213     }
214
215     /**
216      * Print output in csv format.
217      *
218      * @return string
219      * @throws OnapCommandOutputPrintingFailed
220      *             exception
221      */
222     public String printCsv() throws OnapCommandOutputPrintingFailed {
223         CSVFormat formattor = CSVFormat.DEFAULT.withRecordSeparator(System.getProperty("line.separator"));
224
225         try (StringWriter writer = new StringWriter();
226              CSVPrinter printer = new CSVPrinter(writer, formattor);) {
227
228             List<List<Object>> rows = this.formRows(false);
229
230             for (int i = 0; i < this.findMaxRows(); i++) {
231                 printer.printRecord(rows.get(i));
232             }
233
234             return writer.toString();
235         } catch (IOException e) {
236             throw new OnapCommandOutputPrintingFailed(e);
237         }
238     }
239
240     public String printJson() {
241         List<List<Object>> rows = this.formRows(false);
242
243         JSONArray array = new JSONArray();
244
245         //skip first row title
246         List<Object> titleRow = rows.get(0);
247
248         for (int i=1; i<rows.size(); i++) {
249             JSONObject rowO = new JSONObject();
250
251             for (int j=0; j<titleRow.size(); j++) {
252                 rowO.put(titleRow.get(j).toString(), rows.get(i).get(j).toString());
253             }
254
255             array.add(rowO);
256         }
257
258         JSONObject json = new JSONObject();
259         json.put(OnapCommandConstants.RESULTS, array);
260         return json.toJSONString();
261     }
262
263     public String printYaml() throws OnapCommandOutputPrintingFailed {
264         try {
265             return new YAMLMapper().writeValueAsString(new ObjectMapper().readTree(this.printJson()));
266         } catch (JsonProcessingException e) {
267             throw new OnapCommandOutputPrintingFailed(e);  // NOSONAR
268         } catch (IOException e) {
269             throw new OnapCommandOutputPrintingFailed(e);  // NOSONAR
270         }
271     }
272 }