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