1351fd6fb6761ca41a39be73c263c7ec19a42db2
[occt.git] / src / Interface / Interface_FileReaderTool.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 // dce 21/01/99 S3767 : Suppression of general messages
15
16 #include <Interface_Check.hxx>
17 #include <Interface_CheckFailure.hxx>
18 #include <Interface_FileReaderData.hxx>
19 #include <Interface_FileReaderTool.hxx>
20 #include <Interface_GeneralLib.hxx>
21 #include <Interface_GeneralModule.hxx>
22 #include <Interface_InterfaceMismatch.hxx>
23 #include <Interface_InterfaceModel.hxx>
24 #include <Interface_Protocol.hxx>
25 #include <Interface_ReaderLib.hxx>
26 #include <Interface_ReaderModule.hxx>
27 #include <Interface_ReportEntity.hxx>
28 #include <Message.hxx>
29 #include <Message_Messenger.hxx>
30 #include <Message_Msg.hxx>
31 #include <Standard_DomainError.hxx>
32 #include <Standard_ErrorHandler.hxx>
33 #include <Standard_Failure.hxx>
34 #include <Standard_NoSuchObject.hxx>
35 #include <Standard_OutOfRange.hxx>
36 #include <Standard_Transient.hxx>
37 #include <Standard_TypeMismatch.hxx>
38
39 #ifdef _WIN32
40 #include <OSD_Exception.hxx>
41 #else
42 #include <OSD_Signal.hxx>
43 #endif
44 #include <stdio.h>
45
46 // MGE 16/06/98
47 // To use Msg class
48 #include <Message_Msg.hxx>
49 // To use TCollectionHAsciiString
50 #include <TCollection_HAsciiString.hxx>
51
52 // Failure pour recuperer erreur en lecture fichier,
53 // TypeMismatch pour message d erreur circonstancie (cas particulier important)
54
55
56 //  Gere le chargement d un Fichier, prealablement transforme en FileReaderData
57 //  (de la bonne norme), dans un Modele
58
59
60 //=======================================================================
61 //function : Interface_FileReaderTool
62 //purpose  : 
63 //=======================================================================
64
65 Interface_FileReaderTool::Interface_FileReaderTool ()
66 {
67   themessenger = Message::DefaultMessenger();
68   theerrhand = Standard_True;
69   thetrace = 0;
70   thenbrep0 = thenbreps = 0;
71 }
72
73 //=======================================================================
74 //function : SetData
75 //purpose  : 
76 //=======================================================================
77
78 void Interface_FileReaderTool::SetData(const Handle(Interface_FileReaderData)& reader,
79                                        const Handle(Interface_Protocol)& protocol)
80 {
81   thereader = reader;
82   theproto = protocol;
83 }
84
85
86 //=======================================================================
87 //function : Protocol
88 //purpose  : 
89 //=======================================================================
90
91 Handle(Interface_Protocol) Interface_FileReaderTool::Protocol () const
92 {
93   return theproto;
94 }
95
96
97 //=======================================================================
98 //function : Data
99 //purpose  : 
100 //=======================================================================
101
102 Handle(Interface_FileReaderData) Interface_FileReaderTool::Data () const
103 {
104   return thereader;
105 }
106
107
108 //=======================================================================
109 //function : SetModel
110 //purpose  : 
111 //=======================================================================
112
113 void Interface_FileReaderTool::SetModel
114   (const Handle(Interface_InterfaceModel)& amodel)
115 {
116   themodel = amodel;
117 }
118
119
120 //=======================================================================
121 //function : Model
122 //purpose  : 
123 //=======================================================================
124
125 Handle(Interface_InterfaceModel) Interface_FileReaderTool::Model () const
126 {
127   return themodel;
128 }
129
130 //=======================================================================
131 //function : SetMessenger
132 //purpose  : 
133 //=======================================================================
134
135 void Interface_FileReaderTool::SetMessenger (const Handle(Message_Messenger)& messenger)
136 {
137   if ( messenger.IsNull() )
138     themessenger = Message::DefaultMessenger();
139   else   
140     themessenger = messenger;
141 }
142
143 //=======================================================================
144 //function : Messenger
145 //purpose  : 
146 //=======================================================================
147
148 Handle(Message_Messenger) Interface_FileReaderTool::Messenger () const
149 {
150   return themessenger;
151 }
152
153 //=======================================================================
154 //function : SetTraceLevel
155 //purpose  : 
156 //=======================================================================
157
158 void Interface_FileReaderTool::SetTraceLevel (const Standard_Integer tracelev)
159 {
160   thetrace = tracelev;
161 }
162
163 //=======================================================================
164 //function : TraceLevel
165 //purpose  : 
166 //=======================================================================
167
168 Standard_Integer Interface_FileReaderTool::TraceLevel () const
169 {
170   return thetrace;
171 }
172
173 //=======================================================================
174 //function : SetErrorHandle
175 //purpose  : 
176 //=======================================================================
177
178 void Interface_FileReaderTool::SetErrorHandle(const Standard_Boolean err)
179 {
180   theerrhand = err;
181 }
182
183
184 //=======================================================================
185 //function : ErrorHandle
186 //purpose  : 
187 //=======================================================================
188
189 Standard_Boolean  Interface_FileReaderTool::ErrorHandle() const
190 {
191   return theerrhand;
192 }
193
194 //  ....            Actions Connexes au CHARGEMENT DU MODELE            ....
195
196 // SetEntities fait appel a des methodes a fournir :
197 // s appuyant sur un Recognizer adapte a l interface :
198 // - Recognize fait reco->Evaluate(... : selon record no num)
199 //   et recupere le resultat
200 // ainsi que la definition de l entite inconnue de l interface
201
202
203 //=======================================================================
204 //function : SetEntities
205 //purpose  : 
206 //=======================================================================
207
208 void Interface_FileReaderTool::SetEntities ()
209 {
210   Standard_Integer num;
211   thenbreps = 0;  thenbrep0 = 0;
212
213   for (num = thereader->FindNextRecord(0);  num > 0;
214        num = thereader->FindNextRecord(num)) {
215     Handle(Standard_Transient) newent;
216     Handle(Interface_Check) ach = new Interface_Check;
217     if (!Recognize (num,ach,newent)) {
218       newent = UnknownEntity();
219       if (thereports.IsNull()) thereports =
220         new TColStd_HArray1OfTransient (1,thereader->NbRecords());
221       thenbreps ++;  thenbrep0 ++;
222       thereports->SetValue (num,new Interface_ReportEntity(ach,newent));
223     }
224     else if ((ach->NbFails() + ach->NbWarnings() > 0) && !newent.IsNull()) {
225       if (thereports.IsNull()) thereports =
226         new TColStd_HArray1OfTransient (1,thereader->NbRecords());
227       thenbreps ++;  thenbrep0 ++;
228       thereports->SetValue (num,new Interface_ReportEntity(ach,newent));
229     }
230     thereader->BindEntity (num,newent);
231   }
232 }
233
234
235 //=======================================================================
236 //function : RecognizeByLib
237 //purpose  : 
238 //=======================================================================
239
240 Standard_Boolean Interface_FileReaderTool::RecognizeByLib(const Standard_Integer num,
241                                                           Interface_GeneralLib& glib,
242                                                           Interface_ReaderLib& rlib,
243                                                           Handle(Interface_Check)& ach,
244                                                           Handle(Standard_Transient)& ent) const
245 {
246   Handle(Interface_GeneralModule) gmod;
247   Handle(Interface_ReaderModule)  rmod;
248   Handle(Interface_Protocol) proto;
249   Standard_Integer CN = 0;
250 //   Chercher dans ReaderLib : Reconnaissance de cas -> CN , proto
251   for (rlib.Start(); rlib.More(); rlib.Next()) {
252     rmod = rlib.Module();
253     if (rmod.IsNull()) continue;
254     CN = rmod->CaseNum(thereader,num);
255     if (CN > 0)  {  proto = rlib.Protocol();  break;  }
256   }
257   if (CN <= 0 || proto.IsNull()) return Standard_False;
258 //   Se recaler dans GeneralLib : Creation de l entite vide
259   Handle(Standard_Type) typrot = proto->DynamicType();
260   for (glib.Start(); glib.More(); glib.Next()) {
261     proto = glib.Protocol();
262     if (proto.IsNull()) continue;
263     if (proto->DynamicType() != typrot) continue;
264     Standard_Boolean res = glib.Module()->NewVoid(CN,ent);
265     if (res) return res;
266     if (!rmod.IsNull()) return rmod->NewRead (CN,thereader,num,ach,ent);
267 //    return res;
268   }
269   return Standard_False;
270 }
271
272
273 //=======================================================================
274 //function : UnknownEntity
275 //purpose  : 
276 //=======================================================================
277
278 Handle(Standard_Transient) Interface_FileReaderTool::UnknownEntity() const
279 {
280   return theproto->UnknownEntity();
281 }
282
283
284 //=======================================================================
285 //function : NewModel
286 //purpose  : 
287 //=======================================================================
288
289 Handle(Interface_InterfaceModel) Interface_FileReaderTool::NewModel() const
290 {
291   return theproto->NewModel();
292 }
293
294
295 //=======================================================================
296 //function : EndRead
297 //purpose  : 
298 //=======================================================================
299
300 void Interface_FileReaderTool::EndRead(const Handle(Interface_InterfaceModel)& )
301 {
302 }    // par defaut, ne fait rien; redefinissable selon besoin
303
304
305 //  ....               (Sa Majeste le) CHARGEMENT DU MODELE               ....
306
307
308 //=======================================================================
309 //function : LoadModel
310 //purpose  : 
311 //=======================================================================
312
313 void Interface_FileReaderTool::LoadModel
314   (const Handle(Interface_InterfaceModel)& amodel)
315 //
316 //   Methode generale de lecture d un fichier : il est lu via un FileReaderData
317 //   qui doit y donner acces de la facon la plus performante possible
318 //   chaque interface definit son FileHeader avec ses methodes, appelees ici
319 {
320   // MGE 16/06/98
321   // Building of Messages
322   //====================================
323   Handle(Message_Messenger) TF = Messenger();
324   //====================================
325   Handle(Interface_Check) ach = new Interface_Check;
326
327   SetModel(amodel);
328
329 //  ..            Demarrage : Lecture du Header            ..
330   if (theerrhand) {
331     try {
332       OCC_CATCH_SIGNALS
333       BeginRead(amodel);  // selon la norme
334     }
335     catch (Standard_Failure const&) {
336       // Sendinf of message : Internal error during the header reading
337       if (!TF.IsNull())
338       {
339         Message_Msg Msg11("XSTEP_11");
340         TF->Send(Msg11, Message_Info);
341       }
342     }
343   }
344   else
345     BeginRead(amodel);  // selon la norme
346
347   //  ..            Lecture des Entites            ..
348
349   amodel->Reservate (thereader->NbEntities());
350
351   Standard_Integer num, num0 = thereader->FindNextRecord(0);
352   num = num0;
353
354   while (num > 0) {
355     Standard_Integer ierr = 0;  // erreur sur analyse d une entite
356     Handle(Standard_Transient) anent;
357     try {
358       OCC_CATCH_SIGNALS
359       for (num = num0;  num > 0; num = thereader->FindNextRecord(num)) {
360         num0 = num;
361
362         //    Lecture sous protection contre crash
363         //    (fait aussi AddEntity mais pas SetReportEntity)
364         anent = LoadedEntity(num);
365
366         //     Lecture non protegee : utile pour travailler avec dbx
367 ////    else
368 ////      anent = LoadedEntity(num);
369
370         //   ..        Fin Lecture        ..
371         if (anent.IsNull())  {
372           // Sending of message : Number of ignored Null Entities  
373     if (!TF.IsNull())
374     {
375       Message_Msg Msg21("XSTEP_21");
376       Msg21.Arg(amodel->NbEntities());
377       TF->Send(Msg21, Message_Info);
378     }
379           continue;
380         }
381         //      LoadedEntity fait AddEntity MAIS PAS SetReport (en bloc a la fin)
382
383       }    // ---- fin boucle sur entites
384       num0 = 0;    // plus rien
385     }      // ---- fin du try, le catch suit
386
387     //   En cas d erreur NON PREVUE par l analyse, recuperation par defaut
388     //   Attention : la recuperation peut elle-meme planter ... (cf ierr)
389     catch (Standard_Failure const& anException) {
390       //      Au passage suivant, on attaquera le record suivant
391       num0 = thereader->FindNextRecord(num); //:g9 abv 28 May 98: tr8_as2_ug.stp - infinite cycle: (0);
392
393 #ifdef _WIN32
394       if (anException.IsKind(STANDARD_TYPE(OSD_Exception))) ierr = 2;
395 #else
396       if (anException.IsKind(STANDARD_TYPE(OSD_Signal))) ierr = 2;
397 #endif
398 //:abv 03Apr00: anent is actually a previous one:      if (anent.IsNull()) 
399       anent = thereader->BoundEntity(num);
400       if (anent.IsNull()) {
401         if (thetrace > 0)
402         {
403           // Sending of message : Number of ignored Null Entities  
404           if (!TF.IsNull())
405           {
406
407             Message_Msg Msg21("XSTEP_21");
408             Msg21.Arg(amodel->NbEntities() + 1);
409
410             TF->Send(Msg21, Message_Info);
411           }
412             continue;
413         }
414       }
415       /*Handle(Interface_Check)*/ ach = new Interface_Check(anent);
416       //: abv 03 Apr 00: trj3_s1-tc-214.stp: generate a message on exception
417       Message_Msg Msg278("XSTEP_278");
418       Msg278.Arg(amodel->StringLabel(anent));
419       ach->SendFail (Msg278); 
420       
421       if (ierr == 2) {
422        // Sending of message : reading of entity failed 
423         if (!TF.IsNull())
424         {
425           Message_Msg Msg22("XSTEP_22");
426           Msg22.Arg(amodel->StringLabel(anent));
427           TF->Send(Msg22, Message_Info);
428         }
429         return;
430       }
431
432       if (!ierr) {
433         //char mess[100]; svv #2
434         ierr = 1;
435 // ce qui serait bien ici serait de recuperer le texte de l erreur pour ach ...
436         if (thetrace > 0) {
437           // Sending of message : recovered entity
438     if (!TF.IsNull())
439     {
440       Message_Msg Msg23("XSTEP_23");
441       Msg23.Arg(num);
442       TF->Send(Msg23, Message_Info);
443     }
444         }
445
446 //  Finalement, on charge une Entite Inconnue
447         thenbreps ++;
448         Handle(Interface_ReportEntity) rep =
449           new Interface_ReportEntity(ach,anent);
450         Handle(Standard_Transient) undef = UnknownEntity();
451         AnalyseRecord(num,undef,ach);
452         rep->SetContent(undef);
453
454         if (thereports.IsNull()) thereports =
455           new TColStd_HArray1OfTransient (1,thereader->NbRecords());
456         thenbreps ++;
457         thereports->SetValue (num,rep);
458         //if(isValid)
459           amodel->AddEntity (anent);    // pas fait par LoadedEntity ...
460       }
461       else {
462         if (thetrace > 0) {
463           // Sending of message : reading of entity failed  
464     if (!TF.IsNull())
465     {
466       Message_Msg Msg22("XSTEP_22");
467       Msg22.Arg(amodel->StringLabel(anent));
468       TF->Send(Msg22, Message_Info);
469     }
470         }
471 //  On garde <rep> telle quelle : pas d analyse fichier supplementaire,
472 //  Mais la phase preliminaire eventuelle est conservee
473 //  (en particulier, on garde trace du Type lu du fichier, etc...)
474       }
475     }    // -----  fin complete du try/catch
476   }      // -----  fin du while
477
478 //  ..        Ajout des Reports, silya
479   if (!thereports.IsNull()) {
480     if (thetrace > 0) 
481     {
482       // Sending of message : report   
483       if (!TF.IsNull())
484       {
485         Message_Msg Msg24("XSTEP_24");
486         Msg24.Arg(thenbreps);
487         TF->Send(Msg24, Message_Info);
488       }
489     }
490     amodel->Reservate (-thenbreps-10);
491     thenbreps = thereports->Upper();
492     for (Standard_Integer nr = 1; nr <= thenbreps; nr ++) {
493       if (thereports->Value(nr).IsNull()) continue;
494       Handle(Standard_Transient) anent = thereader->BoundEntity (nr);
495       Handle(Interface_ReportEntity) rep =
496         Handle(Interface_ReportEntity)::DownCast(thereports->Value(nr));
497       amodel->SetReportEntity (-amodel->Number(anent),rep);
498     }
499   }
500
501 //   Conclusion : peut ne rien faire : selon necessite
502   if (theerrhand) {
503     try {
504       OCC_CATCH_SIGNALS
505       EndRead(amodel);  // selon la norme
506     }
507     catch (Standard_Failure const&) {
508       // Sendinf of message : Internal error during the header reading
509       if (!TF.IsNull())
510       {
511         Message_Msg Msg11("XSTEP_11");
512         TF->Send(Msg11, Message_Info);
513       }
514     }
515   }
516   else
517     EndRead(amodel);  // selon la norme
518 }
519
520
521 //=======================================================================
522 //function : LoadedEntity
523 //purpose  : 
524 //=======================================================================
525
526 Handle(Standard_Transient) Interface_FileReaderTool::LoadedEntity
527        (const Standard_Integer num)
528 {
529   Handle(Standard_Transient) anent = thereader->BoundEntity(num);
530   Handle(Interface_Check) ach = new Interface_Check(anent);
531   Handle(Interface_ReportEntity) rep;    // entite Report, s il y a lieu
532   Standard_Integer irep = 0;
533   //Standard_Integer nbe  = 0; svv #2
534   if (thenbrep0 > 0) {
535     rep = Handle(Interface_ReportEntity)::DownCast(thereports->Value(num));
536     if (!rep.IsNull()) { irep = num;  ach = rep->Check(); }
537   }
538
539 //    Trace Entite Inconnue
540   if (thetrace >= 2 && theproto->IsUnknownEntity(anent)) {
541     Handle(Message_Messenger) TF = Messenger();
542     if (!TF.IsNull())
543     {
544       Message_Msg Msg22("XSTEP_22");
545       // Sending of message : reading of entity failed
546       Msg22.Arg(themodel->StringLabel(anent)->String());
547       TF->Send(Msg22, Message_Info);
548     }
549   }
550 //  ..        Chargement proprement dit : Specifique de la Norme        ..
551   AnalyseRecord(num,anent,ach);
552
553 //  ..        Ajout dans le modele de l entite telle quelle        ..
554 //            ATTENTION, ReportEntity traitee en bloc apres les Load
555     themodel->AddEntity(anent);
556
557 //   Erreur ou Correction : On cree une ReportEntity qui memorise le Check,
558 //   l Entite, et en cas d Erreur une UndefinedEntity pour les Parametres
559
560 //   On exploite ici le flag IsLoadError : s il a ete defini (a vrai ou faux)
561 //   il a priorite sur les fails du check. Sinon, ce sont les fails qui parlent
562
563   Standard_Integer nbf = ach->NbFails();
564   Standard_Integer nbw = ach->NbWarnings();
565   if (nbf + nbw > 0) {
566     //Standard_Integer n0; svv #2
567     themodel->NbEntities();
568     rep = new Interface_ReportEntity(ach,anent);
569     if (irep == 0) {
570       if (thereports.IsNull()) thereports =
571         new TColStd_HArray1OfTransient (1,thereader->NbRecords());
572       irep = num;
573       thenbreps ++;
574     }
575     thereports->SetValue(irep,rep);
576
577     if ( thetrace >= 2 && !Messenger().IsNull())
578     {
579       Message_Messenger::StreamBuffer sout = Messenger()->SendInfo();
580       ach->Print (sout,2);
581     }
582   }
583   
584 //    Rechargement ? si oui, dans une UnknownEntity fournie par le protocole
585   if (thereader->IsErrorLoad())  nbf = (thereader->ResetErrorLoad() ? 1 : 0);
586   if (nbf > 0)  {
587     Handle(Standard_Transient) undef = UnknownEntity();
588     AnalyseRecord(num,undef,ach);
589     rep->SetContent(undef);
590   }
591
592 //    Conclusion  (Unknown : traite en externe because traitement Raise)
593 ////  if (irep > 0) themodel->SetReportEntity (nbe,rep);  en bloc a la fin
594
595   return anent;
596 }
597
598
599 //=======================================================================
600 //function : ~Interface_FileReaderTool
601 //purpose  : 
602 //=======================================================================
603
604 Interface_FileReaderTool::~Interface_FileReaderTool()
605 {}
606      
607 void Interface_FileReaderTool::Clear()
608 {
609   theproto.Nullify();
610   thereader.Nullify();
611   themodel.Nullify();
612   thereports.Nullify();
613 }