View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.openr66.client.utils;
21  
22  import com.fasterxml.jackson.core.JsonParseException;
23  import com.fasterxml.jackson.core.type.TypeReference;
24  import com.fasterxml.jackson.databind.JsonMappingException;
25  import com.fasterxml.jackson.databind.node.ObjectNode;
26  import org.waarp.common.json.JsonHandler;
27  import org.waarp.openr66.protocol.configuration.Messages;
28  
29  import java.io.IOException;
30  import java.util.Map;
31  import java.util.Map.Entry;
32  
33  /**
34   * This method allows to format output for Waarp R66 clients
35   */
36  public class OutputFormat extends JsonHandler {
37    private static final String XML = "XML";
38    private static final String PROPERTY = "PROPERTY";
39    private static final String CSV = "CSV";
40    private static final String MESSAGE_CANT_CONVERT = "Message.CantConvert";
41  
42    public enum OUTPUTFORMAT {
43      QUIET, JSON, XML, PROPERTY, CSV
44    }
45  
46    static OUTPUTFORMAT defaultOutput = OUTPUTFORMAT.JSON;
47  
48    public enum FIELDS {
49      command, args, status, statusTxt, transfer, error, remote, statusCode,
50      specialid, originalPath, finalPath, ruleid, requester, requested,
51      originalSize, fileInformation, transferInformation
52    }
53  
54    /**
55     * Helper to set the output format desired for the command
56     *
57     * @param args
58     */
59    public static void getParams(final String[] args) {
60      for (int i = 1; i < args.length; i++) {
61        if ("-quiet".equalsIgnoreCase(args[i])) {
62          defaultOutput = OUTPUTFORMAT.QUIET;
63        } else if ("-xml".equalsIgnoreCase(args[i])) {
64          defaultOutput = OUTPUTFORMAT.XML;
65        } else if ("-csv".equalsIgnoreCase(args[i])) {
66          defaultOutput = OUTPUTFORMAT.CSV;
67        } else if ("-json".equalsIgnoreCase(args[i])) {
68          defaultOutput = OUTPUTFORMAT.JSON;
69        } else if ("-property".equalsIgnoreCase(args[i])) {
70          defaultOutput = OUTPUTFORMAT.PROPERTY;
71        }
72      }
73    }
74  
75    /**
76     * To set the default OutputFormat
77     *
78     * @param outputformat
79     */
80    public static void setDefaultOutput(final OUTPUTFORMAT outputformat) {
81      defaultOutput = outputformat;
82    }
83  
84    private OUTPUTFORMAT format = defaultOutput;
85    private final ObjectNode node = createObjectNode();
86  
87    /**
88     * Create an OutputFormat helper using the default Format defined in
89     * defaultOutput
90     *
91     * @param command
92     * @param args
93     */
94    public OutputFormat(final String command, final String[] args) {
95      setValue(FIELDS.command.name(), command);
96      if (args != null) {
97        final StringBuilder builder = new StringBuilder();
98        for (final String string : args) {
99          builder.append(string).append(' ');
100       }
101       setValue(FIELDS.args.name(), builder.toString());
102     }
103   }
104 
105   /**
106    * To change the applied format
107    *
108    * @param format
109    */
110   public final void setFormat(final OUTPUTFORMAT format) {
111     this.format = format;
112   }
113 
114   public final OUTPUTFORMAT getFormat() {
115     return format;
116   }
117 
118   /**
119    * @param values
120    */
121   public final void setValue(final Map<String, Object> values) {
122     final String json = writeAsString(values);
123     final ObjectNode temp = getFromString(json);
124     node.setAll(temp);
125   }
126 
127   /**
128    * @param values
129    */
130   public final void setValueString(final Map<String, String> values) {
131     final String json = writeAsString(values);
132     final ObjectNode temp = getFromString(json);
133     node.setAll(temp);
134   }
135 
136   /**
137    * @param node
138    */
139   public final void setValueString(final ObjectNode node) {
140     node.setAll(node);
141   }
142 
143   /**
144    * @param field
145    * @param value
146    */
147   public final void setValue(final String field, final boolean value) {
148     setValue(node, field, value);
149   }
150 
151   /**
152    * @param field
153    * @param value
154    */
155   public final void setValue(final String field, final double value) {
156     setValue(node, field, value);
157   }
158 
159   /**
160    * @param field
161    * @param value
162    */
163   public final void setValue(final String field, final int value) {
164     setValue(node, field, value);
165   }
166 
167   /**
168    * @param field
169    * @param value
170    */
171   public final void setValue(final String field, final long value) {
172     setValue(node, field, value);
173   }
174 
175   /**
176    * @param field
177    * @param value
178    */
179   public final void setValue(final String field, final String value) {
180     setValue(node, field, value);
181   }
182 
183   /**
184    * @param field
185    * @param value
186    */
187   public final void setValue(final String field, final byte[] value) {
188     setValue(node, field, value);
189   }
190 
191   /**
192    * @param field
193    *
194    * @return True if all fields exist
195    */
196   public final boolean exist(final String... field) {
197     return exist(node, field);
198   }
199 
200   /**
201    * @return True if the current default output format is on QUIET
202    */
203   public static boolean isQuiet() {
204     return defaultOutput == OUTPUTFORMAT.QUIET;
205   }
206 
207   /**
208    * @return True if the current default output format is on XML
209    */
210   public static boolean isXml() {
211     return defaultOutput == OUTPUTFORMAT.XML;
212   }
213 
214   /**
215    * @return True if the current default output format is on CSV
216    */
217   public static boolean isCsv() {
218     return defaultOutput == OUTPUTFORMAT.CSV;
219   }
220 
221   /**
222    * @return True if the current default output format is on JSON
223    */
224   public static boolean isJson() {
225     return defaultOutput == OUTPUTFORMAT.JSON;
226   }
227 
228   /**
229    * @return True if the current default output format is on PROPERTY
230    */
231   public static boolean isProperty() {
232     return defaultOutput == OUTPUTFORMAT.PROPERTY;
233   }
234 
235   /**
236    * Helper for sysOut
237    */
238   public final void sysout() {
239     if (format != OUTPUTFORMAT.QUIET) {
240       System.out.println(getContext());//NOSONAR
241       System.out.println(toString(format));//NOSONAR
242     }
243   }
244 
245   private String getContext() {
246     return '[' + getValue(node, FIELDS.command, "") + "] " +
247            getValue(node, FIELDS.statusTxt, "");
248   }
249 
250   /**
251    * Helper for Logger
252    *
253    * @return the String to print in logger
254    */
255   public final String loggerOut() {
256     return getContext() + " => " + toString(OUTPUTFORMAT.JSON);
257   }
258 
259   @Override
260   public final String toString() {
261     return toString(format);
262   }
263 
264   private String commonEscaped(final String toEscape) {
265     return toEscape.replace('\n', ' ').replace('\r', ' ');
266   }
267 
268   private String escapedCSV(final String toEscape) {
269     String escaped = commonEscaped(toEscape);
270     if (escaped.indexOf(';') >= 0) {
271       escaped = "\"" + escaped + "\"";
272     }
273     return escaped;
274   }
275 
276   private String escapedXML(final String toEscape) {
277     return toEscape.replace('<', '[').replace('>', ']').replace('&', ':');
278   }
279 
280   private String escapedProperty(final String toEscape) {
281     return commonEscaped(toEscape);
282   }
283 
284   /**
285    * Helper to get string representation of the current object
286    *
287    * @param format
288    *
289    * @return the String representation
290    */
291   public final String toString(final OUTPUTFORMAT format) {
292     final String inString = writeAsString(node);
293     switch (format) {
294       case CSV:
295         try {
296           final Map<String, Object> map = mapper.readValue(inString,
297                                                            JsonHandler.typeReferenceMapStringObject);
298           final StringBuilder builderKeys = new StringBuilder();
299           final StringBuilder builderValues = new StringBuilder();
300           boolean next = false;
301           for (final Entry<String, Object> entry : map.entrySet()) {
302             if (next) {
303               builderKeys.append(';');
304               builderValues.append(';');
305             } else {
306               next = true;
307             }
308             builderKeys.append(entry.getKey());
309             String value = entry.getValue().toString();
310             value = escapedCSV(value);
311             builderValues.append(value);
312           }
313           return builderKeys + "\n" + builderValues;
314         } catch (final JsonParseException e) {
315           return Messages.getString(MESSAGE_CANT_CONVERT, CSV) + inString;
316         } catch (final JsonMappingException e) {
317           return Messages.getString(MESSAGE_CANT_CONVERT, CSV) + inString;
318         } catch (final IOException e) {
319           return Messages.getString(MESSAGE_CANT_CONVERT, CSV) + inString;
320         }
321       case PROPERTY:
322         try {
323           final Map<String, Object> map = mapper.readValue(inString,
324                                                            new TypeReference<Map<String, Object>>() {
325                                                            });
326           final StringBuilder builder = new StringBuilder();
327           boolean next = false;
328           for (final Entry<String, Object> entry : map.entrySet()) {
329             if (next) {
330               builder.append('\n');
331             } else {
332               next = true;
333             }
334             String value = entry.getValue().toString();
335             value = escapedProperty(value);
336             builder.append(entry.getKey()).append('=').append(value);
337           }
338           return builder.toString();
339         } catch (final JsonParseException e) {
340           return Messages.getString(MESSAGE_CANT_CONVERT, PROPERTY) + inString;
341         } catch (final JsonMappingException e) {
342           return Messages.getString(MESSAGE_CANT_CONVERT, PROPERTY) + inString;
343         } catch (final IOException e) {
344           return Messages.getString(MESSAGE_CANT_CONVERT, PROPERTY) + inString;
345         }
346       case XML:
347         try {
348           final Map<String, Object> map = mapper.readValue(inString,
349                                                            JsonHandler.typeReferenceMapStringObject);
350           final StringBuilder builder = new StringBuilder("<xml>");
351           for (final Entry<String, Object> entry : map.entrySet()) {
352             String value = entry.getValue().toString();
353             value = escapedXML(value);
354             builder.append('<').append(entry.getKey()).append('>').append(value)
355                    .append("</").append(entry.getKey()).append('>');
356           }
357           builder.append("</xml>");
358           return builder.toString();
359         } catch (final JsonParseException e) {
360           return Messages.getString(MESSAGE_CANT_CONVERT, XML) + inString;
361         } catch (final JsonMappingException e) {
362           return Messages.getString(MESSAGE_CANT_CONVERT, XML) + inString;
363         } catch (final IOException e) {
364           return Messages.getString(MESSAGE_CANT_CONVERT, XML) + inString;
365         }
366       case QUIET:
367       case JSON:
368       default:
369         return commonEscaped(inString);
370     }
371   }
372 }