Changes for checkstyle 8.32
[policy/apex-pdp.git] / tools / tools-common / src / main / java / org / onap / policy / apex / tools / common / Console.java
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.apex.tools.common;
22
23 import java.io.PrintStream;
24 import java.util.ArrayList;
25 import java.util.List;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.commons.text.StrBuilder;
28 import org.slf4j.ext.XLoggerFactory;
29 import org.slf4j.helpers.MessageFormatter;
30
31 /**
32  * A console for printing messages with functionality similar to loggers. The class provides a static instance for all
33  * parts of an application. The default configuration is to not collect errors or warnings. The default types being
34  * activated are errors, warnings, and info messages.
35  *
36  * @author Sven van der Meer (sven.van.der.meer@ericsson.com)
37  */
38 public final class Console {
39     /** The console as static object. */
40     public static final Console CONSOLE = new Console();
41
42     /** Type for a quiet console, no messages being printed. */
43     public static final int TYPE_QUIET = 0;
44
45     /** Type for printing error messages. */
46     public static final int TYPE_ERROR = 0b0001;
47
48     /** Type for printing warning messages. */
49     public static final int TYPE_WARNING = 0b0010;
50
51     /** Type for printing information messages. */
52     public static final int TYPE_INFO = 0b0100;
53
54     /** Type for printing progress messages. */
55     public static final int TYPE_PROGRESS = 0b1000;
56
57     /** Type for printing debug messages. */
58     public static final int TYPE_DEBUG = 0b001_0000;
59
60     /** Type for printing trace messages. */
61     public static final int TYPE_TRACE = 0b010_0000;
62
63     /** Type for printing stack traces of caught exceptions. */
64     public static final int TYPE_STACKTRACE = 0b110_0000;
65
66     /** Type for a verbose console, activating all message types. */
67     public static final int TYPE_VERBOSE = 0b111_1111;
68
69     /** Configuration for a collecting error messages. */
70     public static final int CONFIG_COLLECT_ERRORS = 0b0001;
71
72     /** Configuration for a collecting warning messages. */
73     public static final int CONFIG_COLLECT_WARNINGS = 0b0010;
74
75     // Input and output streams
76     private static final PrintStream ERR_STREAM = System.err;
77
78     /** The setting for message types, set using type flags. */
79     private int types;
80
81     /** The console configuration, set using configuration flags. */
82     private int configuration;
83
84     /** A name for the application, if set used as prefix for messages. */
85     private String appName;
86
87     /** The list of errors, filled if error collection is activates. */
88     private final List<String> errors;
89
90     /** The list of warnings, filled if warning collection is activates. */
91     private final List<String> warnings;
92
93     /**
94      * Creates a new console. The constructor is private since the class provides static access to an instance. The
95      * default for types is verbose.
96      */
97     private Console() {
98         types = TYPE_VERBOSE;
99
100         configuration = 0;
101         errors = new ArrayList<>();
102         warnings = new ArrayList<>();
103     }
104
105     /**
106      * Sets the application name.
107      *
108      * @param appName new application name, use <code>null</code> to reset the application name, a non-blank string for
109      *        a new name, blank strings are ignored
110      */
111     public void setAppName(final String appName) {
112         if (appName == null) {
113             this.appName = null;
114         } else if (!StringUtils.isBlank(appName)) {
115             this.appName = appName;
116         }
117     }
118
119     /**
120      * Returns the application name.
121      *
122      * @return application name, null if not set, non-blank string otherwise
123      */
124     public String getAppName() {
125         return appName;
126     }
127
128     /**
129      * Activates a type.
130      *
131      * @param type the type to activate
132      */
133     public void activate(final int type) {
134         types = types | type;
135     }
136
137     /**
138      * Deactivates a type.
139      *
140      * @param type type to deactivate
141      */
142     public void deActivate(final int type) {
143         types = types & ~type;
144     }
145
146     /**
147      * Sets the type to the given type, effectively deactivating all other types.
148      *
149      * @param type new type
150      */
151     public void set(final int type) {
152         types = type;
153     }
154
155     /**
156      * Sets the type to the given types, effectively deactivating all other types.
157      *
158      * @param ts array of types to set
159      */
160     public void set(final int... ts) {
161         this.types = 0;
162         for (final int type : ts) {
163             this.activate(type);
164         }
165     }
166
167     /**
168      * Configures the console. Use the configuration flags in combination for the required configuration. For instance,
169      * to collect errors and warnings use <code>CONFIG_COLLECT_ERRORS | CONFIG_COLLECT_WARNINGS</code>.
170      *
171      * @param config the new configuration, overwrites the current configuration, 0 deactivates all settings
172      */
173     public void configure(final int config) {
174         this.configuration = config;
175     }
176
177     /**
178      * Prints an error message with message and objects if {@link #TYPE_ERROR} is set; and increases the error count.
179      * Errors are collected (if configuration is set) and the error counter is increased regardless of the console error
180      * type settings.
181      *
182      * @param message the error message, using the same format as the SLF4J MessageFormatter, nothing done if
183      *        <code>blank</code>
184      * @param objects the objects for substitution in the message
185      */
186     public void error(final String message, final Object... objects) {
187         if (StringUtils.isBlank(message)) {
188             return;
189         }
190
191         final StrBuilder err = new StrBuilder();
192         if (appName != null) {
193             err.append(this.getAppName()).append(": ");
194         }
195         err.append("error: ");
196         err.append(MessageFormatter.arrayFormat(message, objects).getMessage());
197
198         if ((types & TYPE_ERROR) == TYPE_ERROR) {
199             ERR_STREAM.println(err.build());
200         }
201         if ((configuration & CONFIG_COLLECT_ERRORS) == CONFIG_COLLECT_ERRORS) {
202             errors.add(err.build());
203         }
204     }
205
206     /**
207      * Prints a warning message with message and objects if {@link #TYPE_WARNING} is set; and increases the warning
208      * count. Warnings are collected (if configuration is set) and the warning counter is increased regardless of the
209      * console warning type settings.
210      *
211      * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
212      *        <code>blank</code>
213      * @param objects the objects for substitution in the message
214      */
215     public void warn(final String message, final Object... objects) {
216         if (StringUtils.isBlank(message)) {
217             return;
218         }
219
220         final StrBuilder warn = new StrBuilder();
221         if (appName != null) {
222             warn.append(this.getAppName()).append(": ");
223         }
224         warn.append("warning: ");
225         warn.append(MessageFormatter.arrayFormat(message, objects).getMessage());
226
227         if ((types & TYPE_WARNING) == TYPE_WARNING) {
228             ERR_STREAM.println(warn.build());
229         }
230         if ((configuration & CONFIG_COLLECT_WARNINGS) == CONFIG_COLLECT_WARNINGS) {
231             warnings.add(warn.build());
232         }
233     }
234
235     /**
236      * Prints an info message with message and objects if {@link #TYPE_INFO} is set.
237      *
238      * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
239      *        <code>blank</code>
240      * @param objects the objects for substitution in the message
241      */
242     public void info(final String message, final Object... objects) {
243         if (StringUtils.isBlank(message)) {
244             return;
245         }
246
247         if ((types & TYPE_INFO) == TYPE_INFO) {
248             if (appName != null) {
249                 ERR_STREAM.print(appName + ": ");
250             }
251             ERR_STREAM.println(MessageFormatter.arrayFormat(message, objects).getMessage());
252         }
253     }
254
255     /**
256      * Prints a progress message with message and objects if {@link #TYPE_PROGRESS} is set.
257      *
258      * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
259      *        <code>blank</code>
260      * @param objects the objects for substitution in the message
261      */
262     public void progress(final String message, final Object... objects) {
263         if (StringUtils.isBlank(message)) {
264             return;
265         }
266
267         if ((types & TYPE_PROGRESS) == TYPE_PROGRESS) {
268             if (appName != null) {
269                 ERR_STREAM.print(appName + ": ");
270             }
271             ERR_STREAM.print("progress: ");
272             ERR_STREAM.println(MessageFormatter.arrayFormat(message, objects).getMessage());
273         }
274     }
275
276     /**
277      * Prints a debug message with message and objects if {@link #TYPE_DEBUG} is set.
278      *
279      * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
280      *        <code>blank</code>
281      * @param objects the objects for substitution in the message
282      */
283     public void debug(final String message, final Object... objects) {
284         if (StringUtils.isBlank(message)) {
285             return;
286         }
287
288         if ((types & TYPE_DEBUG) == TYPE_DEBUG) {
289             if (appName != null) {
290                 ERR_STREAM.print(appName + ": ");
291             }
292             ERR_STREAM.print("debug: ");
293             ERR_STREAM.println(MessageFormatter.arrayFormat(message, objects).getMessage());
294         }
295     }
296
297     /**
298      * Prints a trace message with message and objects if {@link #TYPE_TRACE} is set.
299      *
300      * @param message the warning message, using the same format as the SLF4J MessageFormatter, nothing done if
301      *        <code>blank</code>
302      * @param objects the objects for substitution in the message
303      */
304     public void trace(final String message, final Object... objects) {
305         if (StringUtils.isBlank(message)) {
306             return;
307         }
308
309         if ((types & TYPE_TRACE) == TYPE_TRACE) {
310             if (appName != null) {
311                 ERR_STREAM.print(appName + ": ");
312             }
313             ERR_STREAM.print("trace: ");
314             ERR_STREAM.println(MessageFormatter.arrayFormat(message, objects).getMessage());
315         }
316     }
317
318     /**
319      * Prints message, cause, and stack trace for a given exception if {@link #TYPE_STACKTRACE} is set.
320      *
321      * @param exception the exception to print, ignored if <code>null</code>
322      */
323     public void stacktrace(final Exception exception) {
324         if (exception == null) {
325             return;
326         }
327
328         if ((types & TYPE_STACKTRACE) == TYPE_STACKTRACE) {
329             if (appName != null) {
330                 ERR_STREAM.print(appName + ": ");
331             }
332             ERR_STREAM.println(" exception message: " + exception.getMessage());
333             if (exception.getCause() != null) {
334                 ERR_STREAM.println(" exception cause: " + exception.getCause());
335             }
336             ERR_STREAM.println("for exception stack trace, please refer logs.");
337             XLoggerFactory.getXLogger(Console.class).error("stacktrace", exception);
338         }
339     }
340
341     /**
342      * Resets the error counter and the list of errors.
343      */
344     public void resetErrors() {
345         errors.clear();
346     }
347
348     /**
349      * Resets the warning counter and the list of warnings.
350      */
351     public void resetWarnings() {
352         warnings.clear();
353     }
354
355 }