1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2003-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MsgHandler.h
11 /// @author  Daniel Krajzewicz
12 /// @author  Michael Behrisch
13 /// @author  Jakob Erdmann
14 /// @date    Tue, 17 Jun 2003
15 /// @version $Id$
16 ///
17 // Retrieves messages about the process and gives them further to output
18 /****************************************************************************/
19 #ifndef MsgHandler_h
20 #define MsgHandler_h
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 
27 #include <string>
28 #include <vector>
29 #include <iostream>
30 
31 
32 // ===========================================================================
33 // class declarations
34 // ===========================================================================
35 class OutputDevice;
36 
37 
38 // ===========================================================================
39 // class definitions
40 // ===========================================================================
41 /**
42  * MsgHandler
43  */
44 class MsgHandler {
45 public:
46     /**
47      * @enum MsgType
48      * An enumeration to differ between different types of messages
49      * (errors, warning and information)
50      */
51     enum MsgType {
52         /// The message is only something to show
53         MT_MESSAGE,
54         /// The message is a warning
55         MT_WARNING,
56         /// The message is an error
57         MT_ERROR,
58         /// The message is an debug
59         MT_DEBUG,
60         /// The message is an debug
61         MT_GLDEBUG
62     };
63 
64 private:
65     typedef MsgHandler* (*Factory)(MsgType);
66 
67 public:
68     /// @brief Sets the factory function to use for new MsgHandlers
setFactory(Factory func)69     static void setFactory(Factory func) {
70         myFactory = func;
71     }
72 
73     /// @brief Returns the instance to add normal messages to
74     static MsgHandler* getMessageInstance();
75 
76     /// @brief Returns the instance to add warnings to
77     static MsgHandler* getWarningInstance();
78 
79     /// @brief Returns the instance to add errors to
80     static MsgHandler* getErrorInstance();
81 
82     /// @brief Returns the instance to add debug to
83     static MsgHandler* getDebugInstance();
84 
85     /// @brief Returns the instance to add GLdebug to
86     static MsgHandler* getGLDebugInstance();
87 
88     /// @brief enable/disable debug messages
89     static void enableDebugMessages(bool enable);
90 
91     /// @brief enable/disable gl-debug messages
92     static void enableDebugGLMessages(bool enable);
93 
94     /// @brief check whether to enable/disable debug messages
writeDebugMessages()95     static inline bool writeDebugMessages() {
96         return myWriteDebugMessages;
97     }
98 
99     /// @brief check whether to enable/disable gl-debug messages
writeDebugGLMessages()100     static inline bool writeDebugGLMessages() {
101         return myWriteDebugGLMessages;
102     }
103 
104     /// @brief ensure that that given output device is no longer used as retriever by any instance
105     static void removeRetrieverFromAllInstances(OutputDevice* out);
106 
107     ///@brief init output options
108     static void initOutputOptions();
109 
110     /// @brief Removes pending handler
111     static void cleanupOnEnd();
112 
113     /// @brief adds a new error to the list
114     virtual void inform(std::string msg, bool addType = true);
115 
116     /** @brief Begins a process information
117      *
118      * When a longer action is started, this method should be used to inform the user about it.
119      * There will be no newline printed, but the message handler will be informed that
120      *  a process message has been begun. If an error occurs, a newline will be printed.
121      * After the action has been performed, use endProcessMsg to inform the user about it.
122      */
123     virtual void beginProcessMsg(std::string msg, bool addType = true);
124 
125     /// @brief Ends a process information
126     virtual void endProcessMsg(std::string msg);
127 
128     /// @brief Clears information whether an error occurred previously
129     virtual void clear();
130 
131     /// @brief Adds a further retriever to the instance responsible for a certain msg type
132     virtual void addRetriever(OutputDevice* retriever);
133 
134     /// @brief Removes the retriever from the handler
135     virtual void removeRetriever(OutputDevice* retriever);
136 
137     /// @brief Returns whether the given output device retrieves messages from the handler
138     bool isRetriever(OutputDevice* retriever) const;
139 
140     /// @brief Returns the information whether any messages were added
141     bool wasInformed() const;
142 
143     /** @brief Generic output operator
144      * @return The MsgHandler for further processing
145      */
146     template <class T>
147     MsgHandler& operator<<(const T& t) {
148         // inform all other receivers
149         for (auto i : myRetrievers) {
150             (*i) << t;
151         }
152         return *this;
153     }
154 
155 protected:
156     /// @brief Builds the string which includes the mml-message type
build(const std::string & msg,bool addType)157     inline std::string build(const std::string& msg, bool addType) {
158         if (addType) {
159             switch (myType) {
160                 case MT_MESSAGE:
161                     break;
162                 case MT_WARNING:
163                     return "Warning: " + msg;
164                     break;
165                 case MT_ERROR:
166                     return "Error: " + msg;
167                     break;
168                 case MT_DEBUG:
169                     return "Debug: " + msg;
170                     break;
171                 case MT_GLDEBUG:
172                     return "GLDebug: " + msg;
173                     break;
174                 default:
175                     break;
176             }
177         }
178         return msg;
179     }
180 
181 
182     /// @brief standard constructor
183     MsgHandler(MsgType type);
184 
185     /// @brief destructor
186     virtual ~MsgHandler();
187 
188 private:
189     /// @brief The function to call for new MsgHandlers, nullptr means use default constructor
190     static Factory myFactory;
191 
192     /// @brief The instance to handle debug
193     static MsgHandler* myDebugInstance;
194 
195     /// @brief The instance to handle glDebug
196     static MsgHandler* myGLDebugInstance;
197 
198     /// @brief The instance to handle errors
199     static MsgHandler* myErrorInstance;
200 
201     /// @brief The instance to handle warnings
202     static MsgHandler* myWarningInstance;
203 
204     /// @brief The instance to handle normal messages
205     static MsgHandler* myMessageInstance;
206 
207     /// @brief Information whether a process information is printed to cout
208     static bool myAmProcessingProcess;
209 
210 private:
211     /// @brief The type of the instance
212     MsgType myType;
213 
214     /// @brief information wehther an error occurred at all
215     bool myWasInformed;
216 
217     /// @brief The list of retrievers that shall be informed about new messages or errors
218     std::vector<OutputDevice*> myRetrievers;
219 
220 private:
221     /// @brief invalid copy constructor
222     MsgHandler(const MsgHandler& s) = delete;
223 
224     /// @brief invalid assignment operator
225     MsgHandler& operator=(const MsgHandler& s) = delete;
226 
227     /** @brief Flag to enable or disable debug GL Functions
228      *
229      * This value is used to show more internal information throught warning messages about certain operations
230      */
231     static bool myWriteDebugMessages;
232     static bool myWriteDebugGLMessages;
233 };
234 
235 
236 // ===========================================================================
237 // global definitions
238 // ===========================================================================
239 #define WRITE_WARNING(msg) MsgHandler::getWarningInstance()->inform(msg);
240 #define WRITE_MESSAGE(msg) MsgHandler::getMessageInstance()->inform(msg);
241 #define PROGRESS_BEGIN_MESSAGE(msg) MsgHandler::getMessageInstance()->beginProcessMsg((msg) + std::string("..."));
242 #define PROGRESS_DONE_MESSAGE() MsgHandler::getMessageInstance()->endProcessMsg("done.");
243 #define PROGRESS_TIME_MESSAGE(before) MsgHandler::getMessageInstance()->endProcessMsg("done (" + toString(SysUtils::getCurrentMillis() - before) + "ms).");
244 #define PROGRESS_FAILED_MESSAGE() MsgHandler::getMessageInstance()->endProcessMsg("failed.");
245 #define WRITE_ERROR(msg)   MsgHandler::getErrorInstance()->inform(msg);
246 #define WRITE_DEBUG(msg) if(MsgHandler::writeDebugMessages()){MsgHandler::getDebugInstance()->inform(msg);};
247 #define WRITE_GLDEBUG(msg) if(MsgHandler::writeDebugGLMessages()){MsgHandler::getGLDebugInstance()->inform(msg);};
248 
249 #endif
250 
251 /****************************************************************************/
252