1 // Created on: 2017-06-26
2 // Created by: Andrey Betenev
3 // Copyright (c) 2017 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15 
16 #include <Message_Report.hxx>
17 
18 #include <Message.hxx>
19 #include <Message_AlertExtended.hxx>
20 #include <Message_AttributeMeter.hxx>
21 #include <Message_Attribute.hxx>
22 #include <Message_CompositeAlerts.hxx>
23 #include <Message_Msg.hxx>
24 #include <Message_Messenger.hxx>
25 #include <Message_PrinterToReport.hxx>
26 
27 #include <Precision.hxx>
28 #include <Standard_Dump.hxx>
29 
IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient)30 IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient)
31 
32 //=======================================================================
33 //function : Message_Report
34 //purpose  :
35 //=======================================================================
36 
37 Message_Report::Message_Report ()
38 : myLimit (-1),
39   myIsActiveInMessenger (Standard_False)
40 {
41 }
42 
43 //=======================================================================
44 //function : AddAlert
45 //purpose  :
46 //=======================================================================
47 
AddAlert(Message_Gravity theGravity,const Handle (Message_Alert)& theAlert)48 void Message_Report::AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert)
49 {
50   Standard_Mutex::Sentry aSentry (myMutex);
51 
52    // alerts of the top level
53   if (myAlertLevels.IsEmpty())
54   {
55     Handle (Message_CompositeAlerts) aCompositeAlert = compositeAlerts (Standard_True);
56     if (aCompositeAlert->AddAlert (theGravity, theAlert))
57     {
58       return;
59     }
60 
61     // remove alerts under the report only
62     const Message_ListOfAlert& anAlerts = aCompositeAlert->Alerts (theGravity);
63     if (anAlerts.Extent() > myLimit)
64     {
65       aCompositeAlert->RemoveAlert (theGravity, anAlerts.First());
66     }
67     return;
68   }
69 
70   // if there are some levels of alerts, the new alert will be placed below the root
71   myAlertLevels.Last()->AddAlert (theGravity, theAlert);
72 }
73 
74 //=======================================================================
75 //function : GetAlerts
76 //purpose  :
77 //=======================================================================
78 
GetAlerts(Message_Gravity theGravity) const79 const Message_ListOfAlert& Message_Report::GetAlerts (Message_Gravity theGravity) const
80 {
81   static const Message_ListOfAlert anEmptyList;
82   if (myCompositAlerts.IsNull())
83   {
84     return anEmptyList;
85   }
86   return myCompositAlerts->Alerts (theGravity);
87 }
88 
89 //=======================================================================
90 //function : HasAlert
91 //purpose  :
92 //=======================================================================
93 
HasAlert(const Handle (Standard_Type)& theType)94 Standard_Boolean Message_Report::HasAlert (const Handle(Standard_Type)& theType)
95 {
96   for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity)
97   {
98     if (HasAlert (theType, (Message_Gravity)iGravity))
99       return Standard_True;
100   }
101   return Standard_False;
102 }
103 
104 //=======================================================================
105 //function : HasAlert
106 //purpose  :
107 //=======================================================================
108 
HasAlert(const Handle (Standard_Type)& theType,Message_Gravity theGravity)109 Standard_Boolean Message_Report::HasAlert (const Handle(Standard_Type)& theType, Message_Gravity theGravity)
110 {
111   if (compositeAlerts().IsNull())
112   {
113     return Standard_False;
114   }
115 
116   return compositeAlerts()->HasAlert (theType, theGravity);
117 }
118 
119 //=======================================================================
120 //function : IsActiveInMessenger
121 //purpose  :
122 //=======================================================================
IsActiveInMessenger(const Handle (Message_Messenger)&) const123 Standard_Boolean Message_Report::IsActiveInMessenger (const Handle(Message_Messenger)&) const
124 {
125   return myIsActiveInMessenger;
126 }
127 
128 //=======================================================================
129 //function : ActivateInMessenger
130 //purpose  :
131 //=======================================================================
ActivateInMessenger(const Standard_Boolean toActivate,const Handle (Message_Messenger)& theMessenger)132 void Message_Report::ActivateInMessenger (const Standard_Boolean toActivate,
133                                           const Handle(Message_Messenger)& theMessenger)
134 {
135   if (toActivate == IsActiveInMessenger())
136     return;
137 
138   myIsActiveInMessenger = toActivate;
139   Handle(Message_Messenger) aMessenger = theMessenger.IsNull() ? Message::DefaultMessenger() : theMessenger;
140   if (toActivate)
141   {
142     Handle (Message_PrinterToReport) aPrinterToReport = new Message_PrinterToReport();
143     aPrinterToReport->SetReport (this);
144     aMessenger->AddPrinter (aPrinterToReport);
145   }
146   else // deactivate
147   {
148     Message_SequenceOfPrinters aPrintersToRemove;
149     for (Message_SequenceOfPrinters::Iterator anIterator (aMessenger->Printers()); anIterator.More(); anIterator.Next())
150     {
151       const Handle(Message_Printer) aPrinter = anIterator.Value();
152       if (aPrinter->IsKind(STANDARD_TYPE (Message_PrinterToReport)) &&
153           Handle(Message_PrinterToReport)::DownCast (aPrinter)->Report() == this)
154         aPrintersToRemove.Append (aPrinter);
155     }
156     for (Message_SequenceOfPrinters::Iterator anIterator (aPrintersToRemove); anIterator.More(); anIterator.Next())
157     {
158       aMessenger->RemovePrinter (anIterator.Value());
159     }
160   }
161 }
162 
163 //=======================================================================
164 //function : UpdateActiveInMessenger
165 //purpose  :
166 //=======================================================================
UpdateActiveInMessenger(const Handle (Message_Messenger)& theMessenger)167 void Message_Report::UpdateActiveInMessenger (const Handle(Message_Messenger)& theMessenger)
168 {
169   Handle(Message_Messenger) aMessenger = theMessenger.IsNull() ? Message::DefaultMessenger() : theMessenger;
170   for (Message_SequenceOfPrinters::Iterator anIterator (aMessenger->Printers()); anIterator.More(); anIterator.Next())
171   {
172     if (anIterator.Value()->IsKind(STANDARD_TYPE (Message_PrinterToReport)) &&
173         Handle(Message_PrinterToReport)::DownCast (anIterator.Value())->Report() == this)
174     {
175       myIsActiveInMessenger = Standard_True;
176       return;
177     }
178   }
179   myIsActiveInMessenger = Standard_False;
180 }
181 
182 //=======================================================================
183 //function : AddLevel
184 //purpose  :
185 //=======================================================================
AddLevel(Message_Level * theLevel,const TCollection_AsciiString & theName)186 void Message_Report::AddLevel (Message_Level* theLevel, const TCollection_AsciiString& theName)
187 {
188   Standard_Mutex::Sentry aSentry (myMutex);
189 
190   myAlertLevels.Append (theLevel);
191 
192   Handle(Message_AlertExtended) aLevelRootAlert = new Message_AlertExtended();
193 
194   Handle(Message_Attribute) anAttribute;
195   if (!ActiveMetrics().IsEmpty())
196   {
197     anAttribute =  new Message_AttributeMeter (theName);
198   }
199   else
200   {
201     anAttribute = new Message_Attribute (theName);
202   }
203   aLevelRootAlert->SetAttribute (anAttribute);
204   theLevel->SetRootAlert (aLevelRootAlert, myAlertLevels.Size() == 1);
205 
206   if (myAlertLevels.Size() == 1) // this is the first level, so root alert should be pushed in the report composite of alerts
207   {
208     compositeAlerts (Standard_True)->AddAlert (Message_Info, theLevel->RootAlert());
209   }
210   if (myAlertLevels.Size() > 1) // this is the first level, so root alert should be pushed in the report composite of alerts
211   {
212     // root alert of next levels should be pushed under the previous level
213     Message_Level* aPrevLevel = myAlertLevels.Value (myAlertLevels.Size() - 1); // previous level
214     aPrevLevel->AddAlert (Message_Info, aLevelRootAlert);
215   }
216 }
217 
218 //=======================================================================
219 //function : RemoveLevel
220 //purpose  :
221 //=======================================================================
222 
RemoveLevel(Message_Level * theLevel)223 void Message_Report::RemoveLevel (Message_Level* theLevel)
224 {
225   Standard_Mutex::Sentry aSentry (myMutex);
226 
227   for (int aLevelIndex = myAlertLevels.Size(); aLevelIndex >= 1; aLevelIndex--)
228   {
229     Message_Level* aLevel = myAlertLevels.Value (aLevelIndex);
230     Message_AttributeMeter::StopAlert (aLevel->RootAlert());
231 
232     myAlertLevels.Remove (aLevelIndex);
233     if (aLevel == theLevel)
234     {
235       return;
236     }
237   }
238 }
239 
240 //=======================================================================
241 //function : Clear
242 //purpose  :
243 //=======================================================================
Clear()244 void Message_Report::Clear()
245 {
246   if (compositeAlerts().IsNull())
247   {
248     return;
249   }
250 
251   Standard_Mutex::Sentry aSentry (myMutex);
252 
253   compositeAlerts()->Clear();
254   myAlertLevels.Clear();
255 }
256 
257 //=======================================================================
258 //function : Clear
259 //purpose  :
260 //=======================================================================
Clear(Message_Gravity theGravity)261 void Message_Report::Clear (Message_Gravity theGravity)
262 {
263   if (compositeAlerts().IsNull())
264   {
265     return;
266   }
267 
268   Standard_Mutex::Sentry aSentry (myMutex);
269 
270   compositeAlerts()->Clear (theGravity);
271   myAlertLevels.Clear();
272 }
273 
274 //=======================================================================
275 //function : Clear
276 //purpose  :
277 //=======================================================================
Clear(const Handle (Standard_Type)& theType)278 void Message_Report::Clear (const Handle(Standard_Type)& theType)
279 {
280   if (compositeAlerts().IsNull())
281   {
282     return;
283   }
284 
285   Standard_Mutex::Sentry aSentry (myMutex);
286 
287   compositeAlerts()->Clear (theType);
288   myAlertLevels.Clear();
289 }
290 
291 //=======================================================================
292 //function : SetActiveMetric
293 //purpose  :
294 //=======================================================================
SetActiveMetric(const Message_MetricType theMetricType,const Standard_Boolean theActivate)295 void Message_Report::SetActiveMetric (const Message_MetricType theMetricType,
296                                       const Standard_Boolean theActivate)
297 {
298   if (theActivate == myActiveMetrics.Contains (theMetricType))
299   {
300     return;
301   }
302 
303   if (theActivate)
304   {
305     myActiveMetrics.Add (theMetricType);
306   }
307   else
308   {
309     myActiveMetrics.RemoveKey (theMetricType);
310   }
311 }
312 
313 //=======================================================================
314 //function : Dump
315 //purpose  :
316 //=======================================================================
317 
Dump(Standard_OStream & theOS)318 void Message_Report::Dump (Standard_OStream& theOS)
319 {
320   for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity)
321   {
322     Dump (theOS, (Message_Gravity)iGravity);
323   }
324 }
325 
326 //=======================================================================
327 //function : Dump
328 //purpose  :
329 //=======================================================================
330 
Dump(Standard_OStream & theOS,Message_Gravity theGravity)331 void Message_Report::Dump (Standard_OStream& theOS, Message_Gravity theGravity)
332 {
333   if (compositeAlerts().IsNull())
334   {
335     return;
336   }
337 
338   if (compositeAlerts().IsNull())
339   {
340     return;
341   }
342 
343   dumpMessages (theOS, theGravity, compositeAlerts());
344 }
345 
346 //=======================================================================
347 //function : SendMessages
348 //purpose  :
349 //=======================================================================
350 
SendMessages(const Handle (Message_Messenger)& theMessenger)351 void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger)
352 {
353   for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter)
354   {
355     SendMessages (theMessenger, (Message_Gravity)aGravIter);
356   }
357 }
358 
359 //=======================================================================
360 //function : SendMessages
361 //purpose  :
362 //=======================================================================
363 
SendMessages(const Handle (Message_Messenger)& theMessenger,Message_Gravity theGravity)364 void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger, Message_Gravity theGravity)
365 {
366   if (compositeAlerts().IsNull())
367   {
368     return;
369   }
370 
371   sendMessages (theMessenger, theGravity, compositeAlerts());
372 }
373 
374 //=======================================================================
375 //function : Merge
376 //purpose  :
377 //=======================================================================
378 
Merge(const Handle (Message_Report)& theOther)379 void Message_Report::Merge (const Handle(Message_Report)& theOther)
380 {
381   for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter)
382   {
383     Merge (theOther, (Message_Gravity)aGravIter);
384   }
385 }
386 
387 //=======================================================================
388 //function : Merge
389 //purpose  :
390 //=======================================================================
391 
Merge(const Handle (Message_Report)& theOther,Message_Gravity theGravity)392 void Message_Report::Merge (const Handle(Message_Report)& theOther, Message_Gravity theGravity)
393 {
394   for (Message_ListOfAlert::Iterator anIt (theOther->GetAlerts(theGravity)); anIt.More(); anIt.Next())
395   {
396     AddAlert (theGravity, anIt.Value());
397   }
398 }
399 
400 //=======================================================================
401 //function : CompositeAlerts
402 //purpose  :
403 //=======================================================================
Handle(Message_CompositeAlerts)404 const Handle(Message_CompositeAlerts)& Message_Report::compositeAlerts (const Standard_Boolean isCreate)
405 {
406   if (myCompositAlerts.IsNull() && isCreate)
407   {
408     myCompositAlerts = new Message_CompositeAlerts();
409   }
410 
411   return myCompositAlerts;
412 }
413 
414 //=======================================================================
415 //function : sendMessages
416 //purpose  :
417 //=======================================================================
sendMessages(const Handle (Message_Messenger)& theMessenger,Message_Gravity theGravity,const Handle (Message_CompositeAlerts)& theCompositeAlert)418 void Message_Report::sendMessages (const Handle(Message_Messenger)& theMessenger, Message_Gravity theGravity,
419                                    const Handle(Message_CompositeAlerts)& theCompositeAlert)
420 {
421   if (theCompositeAlert.IsNull())
422   {
423     return;
424   }
425 
426   const Message_ListOfAlert& anAlerts = theCompositeAlert->Alerts (theGravity);
427   for (Message_ListOfAlert::Iterator anIt (anAlerts); anIt.More(); anIt.Next())
428   {
429     theMessenger->Send (anIt.Value()->GetMessageKey(), theGravity);
430     Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (anIt.Value());
431     if (anExtendedAlert.IsNull())
432     {
433       continue;
434     }
435 
436     Handle(Message_CompositeAlerts) aCompositeAlerts = anExtendedAlert->CompositeAlerts();
437     if (aCompositeAlerts.IsNull())
438     {
439       continue;
440     }
441 
442     sendMessages (theMessenger, theGravity, aCompositeAlerts);
443   }
444 }
445 
446 //=======================================================================
447 //function : dumpMessages
448 //purpose  :
449 //=======================================================================
dumpMessages(Standard_OStream & theOS,Message_Gravity theGravity,const Handle (Message_CompositeAlerts)& theCompositeAlert)450 void Message_Report::dumpMessages (Standard_OStream& theOS, Message_Gravity theGravity,
451                                    const Handle(Message_CompositeAlerts)& theCompositeAlert)
452 {
453   if (theCompositeAlert.IsNull())
454   {
455     return;
456   }
457 
458   const Message_ListOfAlert& anAlerts = theCompositeAlert->Alerts (theGravity);
459   for (Message_ListOfAlert::Iterator anIt (anAlerts); anIt.More(); anIt.Next())
460   {
461     theOS << anIt.Value()->GetMessageKey() << std::endl;
462 
463     Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (anIt.Value());
464     if (anExtendedAlert.IsNull())
465     {
466       continue;
467     }
468 
469     dumpMessages (theOS, theGravity, anExtendedAlert->CompositeAlerts());
470   }
471 }
472 
473 //=======================================================================
474 //function : DumpJson
475 //purpose  :
476 //=======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const477 void Message_Report::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
478 {
479   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
480 
481   if (!myCompositAlerts.IsNull())
482   {
483     OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myCompositAlerts.get())
484   }
485 
486   Standard_Integer anAlertLevels = myAlertLevels.Size();
487   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, anAlertLevels)
488 
489   Standard_Integer anInc = 1;
490   for (NCollection_IndexedMap<Message_MetricType>::Iterator anIterator (myActiveMetrics); anIterator.More(); anIterator.Next())
491   {
492     Message_MetricType anActiveMetric = anIterator.Value();
493     OCCT_DUMP_FIELD_VALUE_NUMERICAL_INC (theOStream, anActiveMetric, anInc++)
494   }
495 
496   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myLimit)
497   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsActiveInMessenger)
498 }
499