0024438: Message_Algorithm - allow customized status descriptions
[occt.git] / src / Message / Message_Algorithm.cxx
CommitLineData
b311480e 1// Created on: 2003-03-04
2// Created by: Pavel TELKOV
973c2be1 3// Copyright (c) 2003-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
973c2be1 7// This library is free software; you can redistribute it and / or modify it
8// under the terms of the GNU Lesser General Public 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.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
b311480e 15
7fd59977 16// The original implementation copyright (c) RINA S.p.A.
17
18#include <Message_Algorithm.ixx>
19
20#include <Message.hxx>
21#include <Message_Msg.hxx>
22#include <Message_MsgFile.hxx>
23#include <Message_Messenger.hxx>
24#include <Standard_AncestorIterator.hxx>
25#include <TCollection_AsciiString.hxx>
26#include <TColStd_SequenceOfInteger.hxx>
27#include <TColStd_HSequenceOfInteger.hxx>
28#include <TColStd_HSequenceOfHExtendedString.hxx>
29#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
30
31//=======================================================================
32//function : SetMessenger
33//purpose :
34//=======================================================================
35
36Message_Algorithm::Message_Algorithm ()
37{
38 myMessenger = Message::DefaultMessenger();
39}
40
41//=======================================================================
42//function : SetMessenger
43//purpose :
44//=======================================================================
45
46void Message_Algorithm::SetMessenger (const Handle(Message_Messenger)& theMsgr)
47{
48 if ( theMsgr.IsNull() )
49 myMessenger = Message::DefaultMessenger();
50 else
51 myMessenger = theMsgr;
52}
53
54//=======================================================================
55//function : SetStatus
56//purpose :
57//=======================================================================
58
59void Message_Algorithm::SetStatus(const Message_Status& theStat)
60{
61 myStatus.Set( theStat );
62}
63
64//=======================================================================
65//function : SetStatus
66//purpose :
67//=======================================================================
68
69void Message_Algorithm::SetStatus (const Message_Status& theStat,
70 const Standard_Integer theInt)
71{
72 // Set status flag
73 SetStatus ( theStat );
74
75 // Find index of bit corresponding to that flag
76 Standard_Integer aFlagIndex = Message_ExecStatus::StatusIndex(theStat);
77 if ( !aFlagIndex ) return;
78
79 // Create map of integer parameters for a given flag, if not yet done
80 if ( myReportIntegers.IsNull() )
81 myReportIntegers = new TColStd_HArray1OfTransient (Message_ExecStatus::FirstStatus,
82 Message_ExecStatus::LastStatus);
83 Handle(Standard_Transient)& aData =
84 myReportIntegers->ChangeValue(aFlagIndex);
85 if ( aData.IsNull() )
86 aData = new TColStd_HPackedMapOfInteger;
87
88 // add integer parameter for the status
89 Handle(TColStd_HPackedMapOfInteger)::DownCast(aData)->ChangeMap().Add(theInt);
90}
91
92//=======================================================================
93//function : SetStatus
94//purpose :
95//=======================================================================
96
97void Message_Algorithm::SetStatus (const Message_Status& theStat,
98 const Handle(TCollection_HExtendedString) &theStr,
99 const Standard_Boolean noRepetitions)
100{
101 // Set status flag
102 SetStatus ( theStat );
103 if ( theStr.IsNull() )
104 return;
105
106 // Find index of bit corresponding to that flag
107 Standard_Integer aFlagIndex = Message_ExecStatus::StatusIndex(theStat);
108 if ( !aFlagIndex ) return;
109
110 // Create sequence of string parameters for a given flag, if not yet done
111 if ( myReportStrings.IsNull() )
112 myReportStrings = new TColStd_HArray1OfTransient (Message_ExecStatus::FirstStatus,
113 Message_ExecStatus::LastStatus);
114 Handle(Standard_Transient)& aData =
115 myReportStrings->ChangeValue(aFlagIndex);
116 if ( aData.IsNull() )
117 aData = new TColStd_HSequenceOfHExtendedString;
118
119 // Add string parameter
120 Handle(TColStd_HSequenceOfHExtendedString) aReportSeq =
121 Handle(TColStd_HSequenceOfHExtendedString)::DownCast(aData);
122 if ( aReportSeq.IsNull() )
123 return;
124 if ( noRepetitions )
125 {
126 // if the provided string has been already registered, just do nothing
127 for ( Standard_Integer i=1; i <= aReportSeq->Length(); i++ )
128 if ( aReportSeq->Value(i)->String().IsEqual( theStr->String() ) )
129 return;
130 }
131
132 aReportSeq->Append ( theStr );
133}
134
15cea4ef 135//=======================================================================
136//function : SetStatus
137//purpose :
138//=======================================================================
139
140void Message_Algorithm::SetStatus (const Message_Status& theStat,
141 const Message_Msg& theMsg)
142{
143 // Set status flag
144 SetStatus (theStat);
145
146 // Find index of bit corresponding to that flag
147 Standard_Integer aFlagIndex = Message_ExecStatus::StatusIndex (theStat);
148 if (aFlagIndex == 0)
149 {
150 return;
151 }
152
153 // Create sequence of messages for a given flag, if not yet done
154 if (myReportMessages.IsNull())
155 {
156 myReportMessages = new Message_ArrayOfMsg (Message_ExecStatus::FirstStatus, Message_ExecStatus::LastStatus);
157 }
158
159 myReportMessages->ChangeValue (aFlagIndex) = new Message_Msg (theMsg);
160}
161
7fd59977 162//=======================================================================
163//function : ClearStatus
164//purpose :
165//=======================================================================
166
15cea4ef 167void Message_Algorithm::ClearStatus()
168{
7fd59977 169 myStatus.Clear();
170 myReportIntegers.Nullify();
171 myReportStrings.Nullify();
15cea4ef 172 myReportMessages.Nullify();
7fd59977 173}
174
175//=======================================================================
176//function : SendStatusMessages
15cea4ef 177//purpose :
7fd59977 178//=======================================================================
179
180void Message_Algorithm::SendStatusMessages (const Message_ExecStatus& theStatus,
15cea4ef 181 const Message_Gravity theTraceLevel,
182 const Standard_Integer theMaxCount) const
7fd59977 183{
184 Handle(Message_Messenger) aMsgr = GetMessenger();
15cea4ef 185 if (aMsgr.IsNull())
186 {
187 return;
188 }
7fd59977 189
15cea4ef 190 const TCollection_AsciiString aClassName (DynamicType()->Name());
7fd59977 191
192 // Iterate on all set flags in the specified range
193 for ( Standard_Integer i = Message_ExecStatus::FirstStatus;
194 i <= Message_ExecStatus::LastStatus; i++ )
195 {
196 Message_Status stat = Message_ExecStatus::StatusByIndex( i );
15cea4ef 197 if (!theStatus.IsSet (stat) || !myStatus.IsSet (stat))
198 {
7fd59977 199 continue;
15cea4ef 200 }
201
202 Handle(Message_Msg) aMsgCustom = !myReportMessages.IsNull()
203 ? myReportMessages->Value (i)
204 : Handle(Message_Msg)();
205 if (!aMsgCustom.IsNull())
206 {
207 // print custom message
208 aMsgr->Send (*aMsgCustom, theTraceLevel);
209 continue;
210 }
7fd59977 211
212 // construct message suffix
213 TCollection_AsciiString aSuffix;
214 switch( Message_ExecStatus::TypeOfStatus( stat ) )
215 {
216 case Message_DONE: aSuffix.AssignCat( ".Done" ); break;
217 case Message_WARN: aSuffix.AssignCat( ".Warn" ); break;
218 case Message_ALARM: aSuffix.AssignCat( ".Alarm"); break;
219 case Message_FAIL: aSuffix.AssignCat( ".Fail" ); break;
220 default: continue;
221 }
222 aSuffix.AssignCat( Message_ExecStatus::LocalStatusIndex( stat ) );
223
224 // find message, iterating by base classes if necessary
225 TCollection_AsciiString aMsgName = aClassName + aSuffix;
226 Handle(Standard_Type) aType = DynamicType();
227 while (Message_MsgFile::Msg(aMsgName).Length() == 0 && !aType.IsNull())
228 {
229 Standard_AncestorIterator it(aType);
230 aType.Nullify();
231 for (; it.More(); it.Next())
232 {
233 aType = it.Value();
234 TCollection_AsciiString aClassName1 (aType->Name());
235 TCollection_AsciiString aMsgName1 = aClassName1 + aSuffix;
236 if (Message_MsgFile::Msg(aMsgName1).Length() != 0)
237 {
238 aMsgName = aMsgName1;
239 break;
240 }
241 }
242 }
243
244 // create a message
245 Message_Msg aMsg ( aMsgName );
246
247 // if additional parameters are defined for a given status flag,
248 // try to feed them into the message
15cea4ef 249 if (!myReportIntegers.IsNull())
7fd59977 250 {
251 Handle(TColStd_HPackedMapOfInteger) aMapErrors =
15cea4ef 252 Handle(TColStd_HPackedMapOfInteger)::DownCast(myReportIntegers->Value(i));
253 if (!aMapErrors.IsNull())
254 {
255 aMsg << PrepareReport (aMapErrors, theMaxCount);
256 }
7fd59977 257 }
15cea4ef 258 if (!myReportStrings.IsNull()
259 && !myReportStrings->Value (i).IsNull())
7fd59977 260 {
15cea4ef 261 Handle(TColStd_HSequenceOfHExtendedString) aReportSeq =
262 Handle(TColStd_HSequenceOfHExtendedString)::DownCast (myReportStrings->Value(i));
263 if (!aReportSeq.IsNull())
264 {
265 aMsg << PrepareReport (aReportSeq->Sequence(), theMaxCount);
266 }
7fd59977 267 }
268
269 // output the message
270 aMsgr->Send(aMsg, theTraceLevel);
271 }
272}
273
274//=======================================================================
275//function : SendMessages
276//purpose :
277//=======================================================================
278
279void Message_Algorithm::SendMessages (const Message_Gravity theTraceLevel,
280 const Standard_Integer theMaxCount) const
281{
282 Message_ExecStatus aStat;
283 aStat.SetAllWarn();
284 aStat.SetAllAlarm();
285 aStat.SetAllFail();
286 SendStatusMessages( aStat, theTraceLevel, theMaxCount );
287}
288
289//=======================================================================
290//function : AddStatus
291//purpose :
292//=======================================================================
293
294void Message_Algorithm::AddStatus
295 (const Handle(Message_Algorithm)& theOtherAlgo)
296{
297 AddStatus( theOtherAlgo->GetStatus(), theOtherAlgo );
298}
299
300//=======================================================================
301//function : AddStatus
302//purpose :
303//=======================================================================
304
305void Message_Algorithm::AddStatus
306 (const Message_ExecStatus& theAllowedStatus,
307 const Handle(Message_Algorithm)& theOtherAlgo)
308{
309 // Iterate on all set flags in the specified range
310 const Message_ExecStatus& aStatusOfAlgo = theOtherAlgo->GetStatus();
311 for ( Standard_Integer i = Message_ExecStatus::FirstStatus;
312 i <= Message_ExecStatus::LastStatus; i++ )
313 {
314 Message_Status stat = Message_ExecStatus::StatusByIndex( i );
315 if ( ! theAllowedStatus.IsSet( stat ) || ! aStatusOfAlgo.IsSet( stat ) )
316 continue;
317
318 SetStatus ( stat );
319
320 // if additional parameters are defined for a given status flag,
321 // move them to <this> algorithm
322 // a) numbers
323 Handle(TColStd_HPackedMapOfInteger) aNumsOther =
324 theOtherAlgo->GetMessageNumbers (stat);
325 if ( ! aNumsOther.IsNull() )
326 {
327 // Create sequence of integer parameters for a given flag, if not yet done
328 if ( myReportIntegers.IsNull() )
329 myReportIntegers =
330 new TColStd_HArray1OfTransient(Message_ExecStatus::FirstStatus,
331 Message_ExecStatus::LastStatus);
332 Handle(Standard_Transient)& aData =
333 myReportIntegers->ChangeValue(i);
334 if ( aData.IsNull() )
335 aData = new TColStd_HPackedMapOfInteger;
336
337 // add integer parameter for the status
338 Handle(TColStd_HPackedMapOfInteger)::DownCast(aData)
339 ->ChangeMap().Unite(aNumsOther->Map());
340 }
341 // b) strings
342 Handle(TColStd_HSequenceOfHExtendedString) aStrsOther =
343 theOtherAlgo->GetMessageStrings (stat);
344 if ( ! aStrsOther.IsNull() )
345 {
346 for (Standard_Integer n=1; n < aStrsOther->Length(); n++ )
347 SetStatus (stat, aStrsOther->Value(n));
348 }
349 }
350}
351
352//=======================================================================
353//function : GetMessageNumbers
354//purpose :
355//=======================================================================
356
357Handle(TColStd_HPackedMapOfInteger) Message_Algorithm::GetMessageNumbers
358 (const Message_Status& theStatus) const
359{
360 if ( myReportIntegers.IsNull() )
361 return 0;
362
363 // Find index of bit corresponding to that flag
364 Standard_Integer aFlagIndex = Message_ExecStatus::StatusIndex(theStatus);
365 if ( ! aFlagIndex ) return 0;
366
367 return Handle(TColStd_HPackedMapOfInteger)::DownCast(myReportIntegers->Value(aFlagIndex));
368}
369
370//=======================================================================
371//function : GetMessageStrings
372//purpose :
373//=======================================================================
374
375Handle(TColStd_HSequenceOfHExtendedString) Message_Algorithm::GetMessageStrings
376 (const Message_Status& theStatus) const
377{
378 if ( myReportStrings.IsNull() )
379 return 0;
380
381 // Find index of bit corresponding to that flag
382 Standard_Integer aFlagIndex = Message_ExecStatus::StatusIndex(theStatus);
383 if ( ! aFlagIndex ) return 0;
384
385 return Handle(TColStd_HSequenceOfHExtendedString)::DownCast(myReportStrings->Value(aFlagIndex));
386}
387
388//=======================================================================
389//function : PrepareReport
390//purpose : static method
391//=======================================================================
392
393TCollection_ExtendedString Message_Algorithm::PrepareReport
394 (const Handle(TColStd_HPackedMapOfInteger)& theMapError,
395 const Standard_Integer theMaxCount)
396{
397 TCollection_ExtendedString aNewReport;
398 TColStd_MapIteratorOfPackedMapOfInteger anIt(theMapError->Map());
399 Standard_Integer nb = 1;
400 for (; anIt.More() && nb <= theMaxCount; anIt.Next(), nb++ )
401 {
402 if ( nb > 1 )
403 aNewReport += " ";
404 aNewReport += anIt.Key();
405 }
406
407 if ( anIt.More() )
408 {
409 aNewReport += " ... (total ";
410 aNewReport += theMapError->Map().Extent();
411 aNewReport += ")";
412 }
413 return aNewReport;
414}
415
416//=======================================================================
417//function : PrepareReport
418//purpose : static method
419//=======================================================================
420
421TCollection_ExtendedString Message_Algorithm::PrepareReport
422 (const TColStd_SequenceOfHExtendedString& theReportSeq,
423 const Standard_Integer theMaxCount)
424{
425 TCollection_ExtendedString aNewReport;
426 Standard_Integer nb = 1;
427 for ( ; nb <= theReportSeq.Length() && nb <= theMaxCount; nb++)
428 {
429 aNewReport += (Standard_CString)( nb > 1 ? ", \'" : "\'" );
430 aNewReport += theReportSeq.Value(nb)->String();
431 aNewReport += "\'";
432 }
433
434 if (theReportSeq.Length() > theMaxCount )
435 {
436 aNewReport += " ... (total ";
437 aNewReport += theReportSeq.Length();
438 aNewReport += ") ";
439 }
440 return aNewReport;
441}