0025748: Parallel version of progress indicator
[occt.git] / src / TDocStd / TDocStd_Application.cxx
1 // Created on: 1999-06-30
2 // Created by: Denis PASCAL
3 // Copyright (c) 1999-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <TDocStd_Application.hxx>
18
19 #include <CDF_Directory.hxx>
20 #include <CDF_DirectoryIterator.hxx>
21 #include <CDF_Session.hxx>
22 #include <CDF_Store.hxx>
23 #include <PCDM_RetrievalDriver.hxx>
24 #include <PCDM_StorageDriver.hxx>
25 #include <Plugin.hxx>
26 #include <Plugin_Failure.hxx>
27 #include <Resource_Manager.hxx>
28 #include <Standard_DomainError.hxx>
29 #include <Standard_Dump.hxx>
30 #include <Standard_ErrorHandler.hxx>
31 #include <Standard_NoSuchObject.hxx>
32 #include <Standard_NotImplemented.hxx>
33 #include <TCollection_ExtendedString.hxx>
34 #include <TDocStd_Document.hxx>
35 #include <TDocStd_Owner.hxx>
36 #include <TDocStd_PathParser.hxx>
37 #include <OSD_Thread.hxx>
38
39 IMPLEMENT_STANDARD_RTTIEXT(TDocStd_Application,CDF_Application)
40
41 // TDocStd_Owner attribute have pointer of closed TDocStd_Document
42 //=======================================================================
43 //function : TDocStd_Application
44 //purpose  :
45 //=======================================================================
46 TDocStd_Application::TDocStd_Application()
47         : myIsDriverLoaded (Standard_True)
48 {
49   AddToSession();
50   if(myMetaDataDriver.IsNull())
51     myIsDriverLoaded = Standard_False;
52 }
53
54
55 //=======================================================================
56 //function : IsDriverLoaded
57 //purpose  :
58 //=======================================================================
59 Standard_Boolean TDocStd_Application::IsDriverLoaded() const
60 {
61   return myIsDriverLoaded;
62 }
63
64 //=======================================================================
65 //function : Resources
66 //purpose  :
67 //=======================================================================
68
69 Handle(Resource_Manager)  TDocStd_Application::Resources()  {
70   if (myResources.IsNull()) {
71     myResources = new Resource_Manager(ResourcesName());
72   }
73   return myResources;
74 }
75
76 //=======================================================================
77 //function : ResourcesName
78 //purpose  :
79 //=======================================================================
80
81 Standard_CString TDocStd_Application::ResourcesName()
82 {
83   return "";
84 }
85
86 //=======================================================================
87 //function : DefineFormat
88 //purpose  : 
89 //=======================================================================
90 void TDocStd_Application::DefineFormat (const TCollection_AsciiString& theFormat,
91                                         const TCollection_AsciiString& theDescription,
92                                         const TCollection_AsciiString& theExtension,
93                                         const Handle(PCDM_RetrievalDriver)& theReader,
94                                         const Handle(PCDM_StorageDriver)& theWriter)
95 {
96   // register resources for CDM mechanics to work
97   Handle(Resource_Manager) aResources = Resources();
98   aResources->SetResource ((theFormat + ".Description"  ).ToCString(), theDescription.ToCString());
99   aResources->SetResource ((theFormat + ".FileExtension").ToCString(), theExtension.ToCString());
100   aResources->SetResource ((theExtension + ".FileFormat").ToCString(), theFormat.ToCString());
101
102   // set format ID in the drivers to allow them putting it in
103   // the OCAF documents opened by these drivers
104   if (!theReader.IsNull())
105     theReader->SetFormat(theFormat);
106   if (!theWriter.IsNull())
107     theWriter->SetFormat(theFormat);
108
109   // register drivers
110   myReaders.Add(theFormat, theReader);
111   myWriters.Add(theFormat, theWriter);
112 }
113
114 //=======================================================================
115 //function : ReadingFormats
116 //purpose  :
117 //=======================================================================
118
119 void TDocStd_Application::ReadingFormats(TColStd_SequenceOfAsciiString &theFormats)
120 {
121         theFormats.Clear();
122
123   NCollection_IndexedDataMap<TCollection_ExtendedString, Handle(PCDM_RetrievalDriver)>::Iterator
124     anIter(myReaders);
125   for (; anIter.More(); anIter.Next()) {
126     Handle(PCDM_RetrievalDriver) aDriver = anIter.Value();
127     if (aDriver.IsNull() == Standard_False) {
128       theFormats.Append(anIter.Key());
129     }
130   }
131 }
132
133 //=======================================================================
134 //function : WritingFormats
135 //purpose  :
136 //=======================================================================
137
138 void TDocStd_Application::WritingFormats(TColStd_SequenceOfAsciiString &theFormats)
139 {
140   theFormats.Clear();
141
142   NCollection_IndexedDataMap<TCollection_ExtendedString, Handle(PCDM_StorageDriver)>::Iterator
143     anIter(myWriters);
144   for (; anIter.More(); anIter.Next()) {
145     Handle(PCDM_StorageDriver) aDriver = anIter.Value();
146     if (aDriver.IsNull() == Standard_False) {
147       theFormats.Append(anIter.Key());
148     }
149   }
150 }
151
152 //=======================================================================
153 //function : NbDocuments
154 //purpose  :
155 //=======================================================================
156
157 Standard_Integer TDocStd_Application::NbDocuments() const
158 {
159   if (!CDF_Session::Exists())
160     throw Standard_DomainError("TDocStd_Application::NbDocuments");
161   return this->myDirectory->Length();
162 }
163
164 //=======================================================================
165 //function : GetDocument
166 //purpose  :
167 //=======================================================================
168
169 void TDocStd_Application::GetDocument(const Standard_Integer index,Handle(TDocStd_Document)& aDoc) const
170 {
171   if (!CDF_Session::Exists())
172     throw Standard_DomainError("TDocStd_Application::NbDocuments");
173   CDF_DirectoryIterator it (myDirectory);
174   Standard_Integer current = 0;
175   for (;it.MoreDocument();it.NextDocument()) {
176     current++;
177     if (index == current) {
178       Handle(TDocStd_Document) D =
179         Handle(TDocStd_Document)::DownCast(it.Document());
180       aDoc = D;
181       return;
182     }
183   }
184 }
185
186 //=======================================================================
187 //function : NewDocument
188 //purpose  :
189 //=======================================================================
190
191 void TDocStd_Application::NewDocument(const TCollection_ExtendedString& format,Handle(TDocStd_Document)& aDoc)
192 {
193   Handle(TDocStd_Document) D = new TDocStd_Document(format);
194   InitDocument (D);
195   CDF_Application::Open(D); // add the document in the session
196   aDoc = D;
197 }
198
199 //=======================================================================
200 //function : InitDocument
201 //purpose  : do nothing
202 //=======================================================================
203
204 void TDocStd_Application::InitDocument(const Handle(TDocStd_Document)& /*aDoc*/) const
205 {
206 }
207
208 //=======================================================================
209 //function : Close
210 //purpose  :
211 //=======================================================================
212
213 void TDocStd_Application::Close(const Handle(TDocStd_Document)& aDoc)
214 {
215   if (aDoc.IsNull())
216   {
217     return;
218   }
219
220   Handle(TDocStd_Owner) Owner;
221   if (aDoc->Main().Root().FindAttribute(TDocStd_Owner::GetID(),Owner)) {
222     Handle(TDocStd_Document) emptyDoc;
223     Owner->SetDocument(emptyDoc);
224   }
225   aDoc->BeforeClose();
226   CDF_Application::Close(aDoc);
227 }
228
229 //=======================================================================
230 //function : IsInSession
231 //purpose  :
232 //=======================================================================
233
234 Standard_Integer TDocStd_Application::IsInSession (const TCollection_ExtendedString& path) const
235 {
236     TCollection_ExtendedString unifiedPath(path);
237     unifiedPath.ChangeAll('/', '|');
238     unifiedPath.ChangeAll('\\', '|');
239
240     Standard_Integer nbdoc = NbDocuments();
241     Handle(TDocStd_Document) D;
242     for (Standard_Integer i = 1; i <= nbdoc; i++) 
243     {
244         GetDocument(i,D);
245         if (D->IsSaved()) 
246         {
247             TCollection_ExtendedString unifiedDocPath(D->GetPath());
248             unifiedDocPath.ChangeAll('/', '|');
249             unifiedDocPath.ChangeAll('\\', '|');
250
251             if (unifiedPath == unifiedDocPath) 
252                 return i;
253         }
254     }
255     return 0;
256 }
257
258 //=======================================================================
259 //function : Open
260 //purpose  :
261 //=======================================================================
262
263 PCDM_ReaderStatus TDocStd_Application::Open (const TCollection_ExtendedString& path, 
264                                              Handle(TDocStd_Document)& aDoc, 
265                                              const Message_ProgressRange& theRange)
266 {
267   PCDM_ReaderStatus status = PCDM_RS_DriverFailure;
268   TDocStd_PathParser tool (path);
269   TCollection_ExtendedString directory = tool.Trek();
270   TCollection_ExtendedString file = tool.Name();
271   file += ".";
272   file += tool.Extension();
273   status = CanRetrieve(directory, file);
274
275   if (status != PCDM_RS_OK)
276   {
277     return status;
278   }
279
280   try
281   {
282     OCC_CATCH_SIGNALS
283     Handle(TDocStd_Document) D =
284       Handle(TDocStd_Document)::DownCast(Retrieve(directory, file, Standard_True, theRange));
285     CDF_Application::Open(D);
286     aDoc = D;
287   }
288   catch (Standard_Failure const& anException)
289   {
290     //    status = GetRetrieveStatus();
291     if (!MessageDriver().IsNull())
292     {
293       //      Standard_SStream aMsg;
294       //      aMsg << Standard_Failure::Caught() << std::endl;
295       //      std::cout << "TDocStd_Application::Open(): " << aMsg.rdbuf()->str() << std::endl;
296       TCollection_ExtendedString aString (anException.GetMessageString());
297       MessageDriver()->Send(aString.ToExtString(), Message_Fail);
298     }
299   }
300   status = GetRetrieveStatus();
301 #ifdef OCCT_DEBUG
302   std::cout << "TDocStd_Application::Open(): The status = " << status << std::endl;
303 #endif
304   return status;
305 }
306
307 //=======================================================================
308 //function : Open
309 //purpose  :
310 //=======================================================================
311 PCDM_ReaderStatus TDocStd_Application::Open (Standard_IStream& theIStream,
312                                              Handle(TDocStd_Document)& theDoc,
313                                              const Message_ProgressRange& theRange)
314
315   try
316   {
317     OCC_CATCH_SIGNALS
318     Handle(TDocStd_Document) D = Handle(TDocStd_Document)::DownCast(Read(theIStream, theRange));
319
320     if (!D.IsNull())
321     {
322       CDF_Application::Open(D);
323       theDoc = D;
324     }
325   }
326
327   catch (Standard_Failure const& anException)
328   {
329     if (!MessageDriver().IsNull())
330     {
331       TCollection_ExtendedString aFailureMessage (anException.GetMessageString());
332       MessageDriver()->Send (aFailureMessage.ToExtString(), Message_Fail);
333     }
334   }
335   return GetRetrieveStatus();
336 }
337
338 //=======================================================================
339 //function : SaveAs
340 //purpose  :
341 //=======================================================================
342
343 PCDM_StoreStatus TDocStd_Application::SaveAs (const Handle(TDocStd_Document)& D, 
344                                               const TCollection_ExtendedString& path,
345                                               const Message_ProgressRange& theRange)
346 {
347   TDocStd_PathParser tool (path);
348   TCollection_ExtendedString directory = tool.Trek();
349   TCollection_ExtendedString file = tool.Name();
350   file+=".";
351   file+=tool.Extension();
352   D->Open(this);
353   CDF_Store storer (D);
354   if (!storer.SetFolder(directory))
355   {
356     TCollection_ExtendedString aMsg ("TDocStd_Application::SaveAs() - folder ");
357     aMsg += directory;
358     aMsg += " does not exist";
359     if(!MessageDriver().IsNull())
360       MessageDriver()->Send(aMsg.ToExtString(), Message_Fail);
361     return storer.StoreStatus(); //CDF_SS_Failure;
362   }
363   storer.SetName (file);
364   try {
365     OCC_CATCH_SIGNALS
366     storer.Realize (theRange);
367   }
368   catch (Standard_Failure const& anException) {
369     if (!MessageDriver().IsNull()) {
370       TCollection_ExtendedString aString (anException.GetMessageString());
371       MessageDriver()->Send(aString.ToExtString(), Message_Fail);
372     }
373   }
374   if(storer.StoreStatus() == PCDM_SS_OK)
375     D->SetSaved();
376 #ifdef OCCT_DEBUG
377   std::cout<<"TDocStd_Application::SaveAs(): The status = "<<storer.StoreStatus()<<std::endl;
378 #endif
379   return storer.StoreStatus();
380 }
381
382 //=======================================================================
383 //function : SaveAs
384 //purpose  :
385 //=======================================================================
386 PCDM_StoreStatus TDocStd_Application::SaveAs(const Handle(TDocStd_Document)& theDoc, 
387                                              Standard_OStream& theOStream,
388                                              const Message_ProgressRange& theRange)
389 {
390   try
391   {
392     Handle(PCDM_StorageDriver) aDocStorageDriver = WriterFromFormat(theDoc->StorageFormat());
393
394     if (aDocStorageDriver.IsNull())
395     {
396       return PCDM_SS_DriverFailure;
397     }
398
399     aDocStorageDriver->SetFormat(theDoc->StorageFormat());
400     aDocStorageDriver->Write(theDoc, theOStream, theRange);
401
402     if (aDocStorageDriver->GetStoreStatus() == PCDM_SS_OK)
403     {
404       theDoc->SetSaved();
405     }
406
407     return aDocStorageDriver->GetStoreStatus();
408   }
409   catch (Standard_Failure const& anException)
410   {
411     if (!MessageDriver().IsNull())
412     {
413       TCollection_ExtendedString aString(anException.GetMessageString());
414       MessageDriver()->Send(aString.ToExtString(), Message_Fail);
415     }
416   }
417   return PCDM_SS_Failure;
418 }
419
420 //=======================================================================
421 //function : Save
422 //purpose  :
423 //=======================================================================
424
425 PCDM_StoreStatus TDocStd_Application::Save (const Handle(TDocStd_Document)& D,
426                                             const Message_ProgressRange&    theRange)
427 {
428   PCDM_StoreStatus status = PCDM_SS_OK;
429   if (D->IsSaved()) {
430     CDF_Store storer (D);
431     try{
432       OCC_CATCH_SIGNALS
433       storer.Realize (theRange);
434     }
435     catch (Standard_Failure const& anException) {
436       if (!MessageDriver().IsNull()) {
437         TCollection_ExtendedString aString (anException.GetMessageString());
438         MessageDriver()->Send(aString.ToExtString(), Message_Fail);
439       }
440     }
441     if(storer.StoreStatus() == PCDM_SS_OK)
442       D->SetSaved();
443     status = storer.StoreStatus();
444   } else {
445     if(!MessageDriver().IsNull()) {
446       TCollection_ExtendedString aMsg("Document has not been saved yet");
447       MessageDriver()->Send(aMsg.ToExtString(), Message_Fail);
448     }
449     status = PCDM_SS_Failure;
450   }
451 #ifdef OCCT_DEBUG
452   std::cout<<"TDocStd_Application::Save(): The status = "<<status<<std::endl;
453 #endif
454   return status;
455 }
456
457 //=======================================================================
458 //function : SaveAs
459 //purpose  : 
460 //=======================================================================
461
462 PCDM_StoreStatus TDocStd_Application::SaveAs(const Handle(TDocStd_Document)& D,
463                                              const TCollection_ExtendedString& path,
464                                              TCollection_ExtendedString& theStatusMessage,
465                                              const Message_ProgressRange& theRange)
466
467   TDocStd_PathParser tool (path);
468   PCDM_StoreStatus aStatus = PCDM_SS_Failure;
469   TCollection_ExtendedString directory = tool.Trek();   
470   TCollection_ExtendedString file = tool.Name();   
471   file+=".";   
472   file+=tool.Extension();
473   D->Open(this);
474   CDF_Store storer (D);  
475   if (storer.SetFolder(directory)) {
476     storer.SetName (file);
477     try {
478       OCC_CATCH_SIGNALS
479       storer.Realize (theRange);
480     }
481     catch (Standard_Failure const& anException) {
482       if (!MessageDriver().IsNull()) {
483         TCollection_ExtendedString aString (anException.GetMessageString());
484         MessageDriver()->Send(aString.ToExtString(), Message_Fail);
485       }
486     }
487     if(storer.StoreStatus() == PCDM_SS_OK)
488       D->SetSaved();
489     theStatusMessage = storer.AssociatedStatusText();
490     aStatus = storer.StoreStatus();
491   } else {
492     theStatusMessage =
493       TCollection_ExtendedString("TDocStd_Application::SaveAs"
494                                  ": No such directory ") + directory;
495     aStatus = PCDM_SS_Failure;
496   }
497   return aStatus;
498 }
499
500 //=======================================================================
501 //function : SaveAs
502 //purpose  : 
503 //=======================================================================
504
505 PCDM_StoreStatus TDocStd_Application::SaveAs (const Handle(TDocStd_Document)& theDoc,
506                                               Standard_OStream&               theOStream,
507                                               TCollection_ExtendedString&     theStatusMessage,
508                                               const Message_ProgressRange&    theRange)
509
510   try
511   {
512     Handle(PCDM_StorageDriver) aDocStorageDriver = WriterFromFormat (theDoc->StorageFormat());
513     if (aDocStorageDriver.IsNull())
514     {
515       theStatusMessage = TCollection_ExtendedString("TDocStd_Application::SaveAs: no storage driver");
516       return PCDM_SS_DriverFailure;
517     }
518
519     aDocStorageDriver->SetFormat(theDoc->StorageFormat());
520     aDocStorageDriver->Write(theDoc, theOStream, theRange);
521         
522     if (aDocStorageDriver->GetStoreStatus() == PCDM_SS_OK)
523     {
524       theDoc->SetSaved();
525     }
526
527     return aDocStorageDriver->GetStoreStatus();
528   }
529   catch (Standard_Failure const& anException)
530   {
531     if (!MessageDriver().IsNull())
532     {
533       TCollection_ExtendedString aString(anException.GetMessageString());
534       MessageDriver()->Send(aString.ToExtString(), Message_Fail);
535     }
536   }
537   return PCDM_SS_Failure;
538 }
539
540 //=======================================================================
541 //function : Save
542 //purpose  : 
543 //=======================================================================
544
545 PCDM_StoreStatus TDocStd_Application::Save (const Handle(TDocStd_Document)& D,
546                                             TCollection_ExtendedString&     theStatusMessage, 
547                                             const Message_ProgressRange&    theRange)
548 {  
549   PCDM_StoreStatus status = PCDM_SS_OK;
550   if (D->IsSaved()) {  
551     CDF_Store storer (D);  
552     try {
553       OCC_CATCH_SIGNALS
554       storer.Realize (theRange);
555     }
556     catch (Standard_Failure const& anException) {
557       if (!MessageDriver().IsNull()) {
558         TCollection_ExtendedString aString (anException.GetMessageString());
559         MessageDriver()->Send(aString.ToExtString(), Message_Fail);
560       }
561     }
562     if(storer.StoreStatus() == PCDM_SS_OK)
563       D->SetSaved();
564     status = storer.StoreStatus();
565     theStatusMessage = storer.AssociatedStatusText();
566   } else {
567     theStatusMessage = "TDocStd_Application::the document has not been saved yet";
568     status = PCDM_SS_Failure;
569   }
570   return status;
571 }
572
573
574 //=======================================================================
575 //function : OnOpenTransaction
576 //purpose  : 
577 //=======================================================================
578
579 void TDocStd_Application::OnOpenTransaction (const Handle(TDocStd_Document)&)
580 {
581   // nothing to do on this level
582 }
583
584 //=======================================================================
585 //function : OnAbortTransaction
586 //purpose  : 
587 //=======================================================================
588
589 void TDocStd_Application::OnAbortTransaction (const Handle(TDocStd_Document)&)
590 {
591   // nothing to do on this level
592 }
593
594 //=======================================================================
595 //function : OnCommitTransaction
596 //purpose  : 
597 //=======================================================================
598
599 void TDocStd_Application::OnCommitTransaction (const Handle(TDocStd_Document)&)
600 {
601   // nothing to do on this level
602 }
603
604 //
605 void TDocStd_Application::AddToSession()
606 {
607   Handle(CDF_Session) S = CDF_Session::Create();
608   S->AddApplication(this, OSD_Thread::Current());
609 }
610
611 Standard_Boolean TDocStd_Application::RemoveFromSession()
612 {
613   Handle(CDF_Session) aSession = CDF_Session::Create();
614   return aSession->RemoveApplication(OSD_Thread::Current());
615 }
616
617 //=======================================================================
618 //function : DumpJson
619 //purpose  : 
620 //=======================================================================
621 void TDocStd_Application::DumpJson (Standard_OStream& theOStream, Standard_Integer) const
622 {
623   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
624
625   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsDriverLoaded)
626 }