0024023: Revamp the OCCT Handle -- general
[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//
d5f74e42 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
973c2be1 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>
7fd59977 24#include <TCollection_AsciiString.hxx>
25#include <TColStd_SequenceOfInteger.hxx>
26#include <TColStd_HSequenceOfInteger.hxx>
27#include <TColStd_HSequenceOfHExtendedString.hxx>
28#include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
ec357c5c 29#include <TColStd_HPackedMapOfInteger.hxx>
7fd59977 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
135//=======================================================================
15cea4ef 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
162//=======================================================================
7fd59977 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
7fd59977 190 // Iterate on all set flags in the specified range
191 for ( Standard_Integer i = Message_ExecStatus::FirstStatus;
192 i <= Message_ExecStatus::LastStatus; i++ )
193 {
194 Message_Status stat = Message_ExecStatus::StatusByIndex( i );
15cea4ef 195 if (!theStatus.IsSet (stat) || !myStatus.IsSet (stat))
196 {
7fd59977 197 continue;
15cea4ef 198 }
199
c04c30b3 200 NCollection_Handle<Message_Msg> aMsgCustom;
201 if (! myReportMessages.IsNull())
202 aMsgCustom = myReportMessages->Value (i);
15cea4ef 203 if (!aMsgCustom.IsNull())
204 {
205 // print custom message
206 aMsgr->Send (*aMsgCustom, theTraceLevel);
207 continue;
208 }
7fd59977 209
210 // construct message suffix
211 TCollection_AsciiString aSuffix;
212 switch( Message_ExecStatus::TypeOfStatus( stat ) )
213 {
214 case Message_DONE: aSuffix.AssignCat( ".Done" ); break;
215 case Message_WARN: aSuffix.AssignCat( ".Warn" ); break;
216 case Message_ALARM: aSuffix.AssignCat( ".Alarm"); break;
217 case Message_FAIL: aSuffix.AssignCat( ".Fail" ); break;
218 default: continue;
219 }
220 aSuffix.AssignCat( Message_ExecStatus::LocalStatusIndex( stat ) );
221
69ff08ff 222 // find message, prefixed by class type name, iterating by base classes if necessary
223 TCollection_AsciiString aMsgName;
224 for (Handle(Standard_Type) aType = DynamicType(); ! aType.IsNull(); aType = aType->Parent())
7fd59977 225 {
69ff08ff 226 aMsgName = aType->Name();
227 aMsgName += aSuffix;
228 if (Message_MsgFile::HasMsg(aMsgName))
229 break;
7fd59977 230 }
231
232 // create a message
233 Message_Msg aMsg ( aMsgName );
234
235 // if additional parameters are defined for a given status flag,
236 // try to feed them into the message
15cea4ef 237 if (!myReportIntegers.IsNull())
7fd59977 238 {
239 Handle(TColStd_HPackedMapOfInteger) aMapErrors =
15cea4ef 240 Handle(TColStd_HPackedMapOfInteger)::DownCast(myReportIntegers->Value(i));
241 if (!aMapErrors.IsNull())
242 {
243 aMsg << PrepareReport (aMapErrors, theMaxCount);
244 }
7fd59977 245 }
15cea4ef 246 if (!myReportStrings.IsNull()
247 && !myReportStrings->Value (i).IsNull())
7fd59977 248 {
15cea4ef 249 Handle(TColStd_HSequenceOfHExtendedString) aReportSeq =
250 Handle(TColStd_HSequenceOfHExtendedString)::DownCast (myReportStrings->Value(i));
251 if (!aReportSeq.IsNull())
252 {
253 aMsg << PrepareReport (aReportSeq->Sequence(), theMaxCount);
254 }
7fd59977 255 }
256
257 // output the message
258 aMsgr->Send(aMsg, theTraceLevel);
259 }
260}
261
262//=======================================================================
263//function : SendMessages
264//purpose :
265//=======================================================================
266
267void Message_Algorithm::SendMessages (const Message_Gravity theTraceLevel,
268 const Standard_Integer theMaxCount) const
269{
270 Message_ExecStatus aStat;
271 aStat.SetAllWarn();
272 aStat.SetAllAlarm();
273 aStat.SetAllFail();
274 SendStatusMessages( aStat, theTraceLevel, theMaxCount );
275}
276
277//=======================================================================
278//function : AddStatus
279//purpose :
280//=======================================================================
281
282void Message_Algorithm::AddStatus
283 (const Handle(Message_Algorithm)& theOtherAlgo)
284{
285 AddStatus( theOtherAlgo->GetStatus(), theOtherAlgo );
286}
287
288//=======================================================================
289//function : AddStatus
290//purpose :
291//=======================================================================
292
293void Message_Algorithm::AddStatus
294 (const Message_ExecStatus& theAllowedStatus,
295 const Handle(Message_Algorithm)& theOtherAlgo)
296{
297 // Iterate on all set flags in the specified range
298 const Message_ExecStatus& aStatusOfAlgo = theOtherAlgo->GetStatus();
299 for ( Standard_Integer i = Message_ExecStatus::FirstStatus;
300 i <= Message_ExecStatus::LastStatus; i++ )
301 {
302 Message_Status stat = Message_ExecStatus::StatusByIndex( i );
303 if ( ! theAllowedStatus.IsSet( stat ) || ! aStatusOfAlgo.IsSet( stat ) )
304 continue;
305
306 SetStatus ( stat );
307
308 // if additional parameters are defined for a given status flag,
309 // move them to <this> algorithm
310 // a) numbers
311 Handle(TColStd_HPackedMapOfInteger) aNumsOther =
312 theOtherAlgo->GetMessageNumbers (stat);
313 if ( ! aNumsOther.IsNull() )
314 {
315 // Create sequence of integer parameters for a given flag, if not yet done
316 if ( myReportIntegers.IsNull() )
317 myReportIntegers =
318 new TColStd_HArray1OfTransient(Message_ExecStatus::FirstStatus,
319 Message_ExecStatus::LastStatus);
320 Handle(Standard_Transient)& aData =
321 myReportIntegers->ChangeValue(i);
322 if ( aData.IsNull() )
323 aData = new TColStd_HPackedMapOfInteger;
324
325 // add integer parameter for the status
326 Handle(TColStd_HPackedMapOfInteger)::DownCast(aData)
327 ->ChangeMap().Unite(aNumsOther->Map());
328 }
329 // b) strings
330 Handle(TColStd_HSequenceOfHExtendedString) aStrsOther =
331 theOtherAlgo->GetMessageStrings (stat);
332 if ( ! aStrsOther.IsNull() )
333 {
334 for (Standard_Integer n=1; n < aStrsOther->Length(); n++ )
335 SetStatus (stat, aStrsOther->Value(n));
336 }
337 }
338}
339
340//=======================================================================
341//function : GetMessageNumbers
342//purpose :
343//=======================================================================
344
345Handle(TColStd_HPackedMapOfInteger) Message_Algorithm::GetMessageNumbers
346 (const Message_Status& theStatus) const
347{
348 if ( myReportIntegers.IsNull() )
349 return 0;
350
351 // Find index of bit corresponding to that flag
352 Standard_Integer aFlagIndex = Message_ExecStatus::StatusIndex(theStatus);
353 if ( ! aFlagIndex ) return 0;
354
355 return Handle(TColStd_HPackedMapOfInteger)::DownCast(myReportIntegers->Value(aFlagIndex));
356}
357
358//=======================================================================
359//function : GetMessageStrings
360//purpose :
361//=======================================================================
362
363Handle(TColStd_HSequenceOfHExtendedString) Message_Algorithm::GetMessageStrings
364 (const Message_Status& theStatus) const
365{
366 if ( myReportStrings.IsNull() )
367 return 0;
368
369 // Find index of bit corresponding to that flag
370 Standard_Integer aFlagIndex = Message_ExecStatus::StatusIndex(theStatus);
371 if ( ! aFlagIndex ) return 0;
372
373 return Handle(TColStd_HSequenceOfHExtendedString)::DownCast(myReportStrings->Value(aFlagIndex));
374}
375
376//=======================================================================
377//function : PrepareReport
378//purpose : static method
379//=======================================================================
380
381TCollection_ExtendedString Message_Algorithm::PrepareReport
382 (const Handle(TColStd_HPackedMapOfInteger)& theMapError,
383 const Standard_Integer theMaxCount)
384{
385 TCollection_ExtendedString aNewReport;
386 TColStd_MapIteratorOfPackedMapOfInteger anIt(theMapError->Map());
387 Standard_Integer nb = 1;
388 for (; anIt.More() && nb <= theMaxCount; anIt.Next(), nb++ )
389 {
390 if ( nb > 1 )
391 aNewReport += " ";
392 aNewReport += anIt.Key();
393 }
394
395 if ( anIt.More() )
396 {
397 aNewReport += " ... (total ";
398 aNewReport += theMapError->Map().Extent();
399 aNewReport += ")";
400 }
401 return aNewReport;
402}
403
404//=======================================================================
405//function : PrepareReport
406//purpose : static method
407//=======================================================================
408
409TCollection_ExtendedString Message_Algorithm::PrepareReport
410 (const TColStd_SequenceOfHExtendedString& theReportSeq,
411 const Standard_Integer theMaxCount)
412{
413 TCollection_ExtendedString aNewReport;
414 Standard_Integer nb = 1;
415 for ( ; nb <= theReportSeq.Length() && nb <= theMaxCount; nb++)
416 {
417 aNewReport += (Standard_CString)( nb > 1 ? ", \'" : "\'" );
418 aNewReport += theReportSeq.Value(nb)->String();
419 aNewReport += "\'";
420 }
421
422 if (theReportSeq.Length() > theMaxCount )
423 {
424 aNewReport += " ... (total ";
425 aNewReport += theReportSeq.Length();
426 aNewReport += ") ";
427 }
428 return aNewReport;
429}