0025748: Parallel version of progress indicator
[occt.git] / src / CDF / CDF_Application.cxx
1 // Created on: 1997-08-08
2 // Created by: Jean-Louis Frenkel
3 // Copyright (c) 1997-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 // Modified by rmi, Wed Jan 14 08:17:35 1998
18
19 #include <CDF_Application.hxx>
20 #include <CDF_Directory.hxx>
21 #include <CDF_Session.hxx>
22 #include <CDF_FWOSDriver.hxx>
23 #include <CDM_CanCloseStatus.hxx>
24 #include <CDM_Document.hxx>
25 #include <CDM_MetaData.hxx>
26 #include <PCDM_Reader.hxx>
27 #include <PCDM_ReadWriter.hxx>
28 #include <PCDM_RetrievalDriver.hxx>
29 #include <PCDM_StorageDriver.hxx>
30 #include <Plugin.hxx>
31 #include <Standard_ErrorHandler.hxx>
32 #include <Standard_GUID.hxx>
33 #include <Standard_NoSuchObject.hxx>
34 #include <Standard_ProgramError.hxx>
35 #include <UTL.hxx>
36
37 IMPLEMENT_STANDARD_RTTIEXT(CDF_Application,CDM_Application)
38 //=======================================================================
39 //function : 
40 //purpose  : 
41 //=======================================================================
42 CDF_Application::CDF_Application():myRetrievableStatus(PCDM_RS_OK) 
43 {
44   myDirectory      = new CDF_Directory();
45   myMetaDataDriver = new CDF_FWOSDriver;
46 }
47
48 //=======================================================================
49 //function : Load
50 //purpose  : 
51 //=======================================================================
52 Handle(CDF_Application) CDF_Application::Load(const Standard_GUID& aGUID) {
53   return Handle(CDF_Application)::DownCast(Plugin::Load(aGUID));
54 }
55
56 //=======================================================================
57 //function : Open
58 //purpose  : 
59 //=======================================================================
60 void CDF_Application::Open(const Handle(CDM_Document)& aDocument) {
61   myDirectory->Add(aDocument);
62   aDocument->Open(this);
63   Activate(aDocument,CDF_TOA_New);
64 }
65
66 //=======================================================================
67 //function : CanClose
68 //purpose  : 
69 //=======================================================================
70 CDM_CanCloseStatus CDF_Application::CanClose(const Handle(CDM_Document)& aDocument) {
71   return aDocument->CanClose();
72 }
73
74 //=======================================================================
75 //function : Close
76 //purpose  : 
77 //=======================================================================
78 void CDF_Application::Close(const Handle(CDM_Document)& aDocument) {
79   myDirectory->Remove(aDocument);
80   aDocument->Close();
81 }
82
83 //=======================================================================
84 //function : Retrieve
85 //purpose  : 
86 //=======================================================================
87 Handle(CDM_Document) CDF_Application::Retrieve (const TCollection_ExtendedString& aFolder, 
88                                                 const TCollection_ExtendedString& aName,
89                                                 const Standard_Boolean UseStorageConfiguration,
90                                                 const Message_ProgressRange& theRange)
91 {
92   TCollection_ExtendedString nullVersion;
93   return Retrieve(aFolder, aName, nullVersion, UseStorageConfiguration, theRange);
94 }
95
96 //=======================================================================
97 //function : Retrieve
98 //purpose  : 
99 //=======================================================================
100 Handle(CDM_Document)  CDF_Application::Retrieve (const TCollection_ExtendedString& aFolder, 
101                                                 const TCollection_ExtendedString& aName,
102                                                 const TCollection_ExtendedString& aVersion,
103                                                 const Standard_Boolean UseStorageConfiguration,
104                                                 const Message_ProgressRange& theRange)
105 {
106   Handle(CDM_MetaData) theMetaData; 
107   
108   if(aVersion.Length() == 0) 
109     theMetaData=myMetaDataDriver->MetaData(aFolder,aName);
110   else 
111     theMetaData=myMetaDataDriver->MetaData(aFolder,aName,aVersion);
112
113   CDF_TypeOfActivation theTypeOfActivation=TypeOfActivation(theMetaData);
114   Handle(CDM_Document) theDocument = Retrieve(theMetaData, UseStorageConfiguration,
115                                               Standard_False, theRange);
116
117   myDirectory->Add(theDocument);
118   Activate(theDocument,theTypeOfActivation);
119
120   theDocument->Open(this);
121   return theDocument;
122 }
123
124 //=======================================================================
125 //function : CanRetrieve
126 //purpose  : 
127 //=======================================================================
128 PCDM_ReaderStatus CDF_Application::CanRetrieve(const TCollection_ExtendedString& aFolder, const TCollection_ExtendedString&  aName) {
129  TCollection_ExtendedString aVersion;
130  return CanRetrieve(aFolder,aName,aVersion);
131 }
132
133 //=======================================================================
134 //function : CanRetrieve
135 //purpose  : 
136 //=======================================================================
137 PCDM_ReaderStatus CDF_Application::CanRetrieve(const TCollection_ExtendedString&  aFolder, const TCollection_ExtendedString&  aName, const TCollection_ExtendedString&  aVersion) {
138   
139   if (!myMetaDataDriver->Find(aFolder,aName,aVersion))
140     return PCDM_RS_UnknownDocument;
141   else if (!myMetaDataDriver->HasReadPermission(aFolder,aName,aVersion))
142     return PCDM_RS_PermissionDenied;
143   else {
144     Handle(CDM_MetaData) theMetaData = myMetaDataDriver->MetaData(aFolder,aName,aVersion);
145
146     if(theMetaData->IsRetrieved()) {
147       return theMetaData->Document()->IsModified()
148         ? PCDM_RS_AlreadyRetrievedAndModified : PCDM_RS_AlreadyRetrieved;
149     }
150     else {
151       TCollection_ExtendedString theFileName=theMetaData->FileName();
152       TCollection_ExtendedString theFormat=PCDM_ReadWriter::FileFormat(theFileName);
153       if(theFormat.Length()==0) {
154         TCollection_ExtendedString ResourceName=UTL::Extension(theFileName);
155         ResourceName+=".FileFormat";
156         if(UTL::Find(Resources(),ResourceName))  {
157           theFormat=UTL::Value(Resources(),ResourceName);
158         }
159         else
160           return PCDM_RS_UnrecognizedFileFormat;
161       }
162
163       // check actual availability of the driver
164       try {
165         Handle(PCDM_Reader) aReader = ReaderFromFormat(theFormat);
166         if (aReader.IsNull())
167           return PCDM_RS_NoDriver;
168       }
169       catch (Standard_Failure const&)
170       {
171         // no need to report error, this was just check for availability
172       }
173     }
174   }
175   return PCDM_RS_OK;
176 }
177
178 //=======================================================================
179 //function : Activate
180 //purpose  : 
181 //=======================================================================
182 //void CDF_Application::Activate(const Handle(CDM_Document)& aDocument,const CDF_TypeOfActivation aTypeOfActivation) {
183 void CDF_Application::Activate(const Handle(CDM_Document)& ,const CDF_TypeOfActivation ) {
184 }
185
186 //=======================================================================
187 //function : DefaultFolder
188 //purpose  : 
189 //=======================================================================
190 Standard_ExtString CDF_Application::DefaultFolder(){
191   if(myDefaultFolder.Length() == 0) {
192     myDefaultFolder=myMetaDataDriver->DefaultFolder();
193   }
194   return myDefaultFolder.ToExtString();
195 }
196
197 //=======================================================================
198 //function : SetDefaultFolder
199 //purpose  : 
200 //=======================================================================
201 Standard_Boolean CDF_Application::SetDefaultFolder(const Standard_ExtString aFolder) {
202   Standard_Boolean found = myMetaDataDriver->FindFolder(aFolder);
203   if(found) myDefaultFolder=aFolder;
204   return found;
205 }
206
207 //=======================================================================
208 //function : Retrieve
209 //purpose  : 
210 //=======================================================================
211 Handle(CDM_Document) CDF_Application::Retrieve(const Handle(CDM_MetaData)& aMetaData,
212                                                const Standard_Boolean UseStorageConfiguration, 
213                                                const Message_ProgressRange& theRange) {
214   return Retrieve(aMetaData, UseStorageConfiguration, Standard_True, theRange);
215
216
217 //=======================================================================
218 //function : Retrieve
219 //purpose  : 
220 //=======================================================================
221 Handle(CDM_Document) CDF_Application::Retrieve (const Handle(CDM_MetaData)& aMetaData, 
222                                                 const Standard_Boolean UseStorageConfiguration, 
223                                                 const Standard_Boolean IsComponent, 
224                                                 const Message_ProgressRange& theRange) {
225   
226   Handle(CDM_Document) theDocumentToReturn;
227   myRetrievableStatus = PCDM_RS_DriverFailure;
228   if(IsComponent) {
229     Standard_SStream aMsg;
230     switch (CanRetrieve(aMetaData)) {
231     case PCDM_RS_UnknownDocument: 
232       aMsg << "could not find the referenced document: " << aMetaData->Path() << "; not found."  <<(char)0 << std::endl;
233       myRetrievableStatus = PCDM_RS_UnknownDocument;
234       throw Standard_Failure(aMsg.str().c_str());
235       break;
236     case PCDM_RS_PermissionDenied:      
237       aMsg << "Could not find the referenced document: " << aMetaData->Path() << "; permission denied. " <<(char)0 << std::endl;
238       myRetrievableStatus = PCDM_RS_PermissionDenied;
239       throw Standard_Failure(aMsg.str().c_str());
240       break;
241     default:
242       break;
243     }
244     
245   }
246   Standard_Boolean AlreadyRetrieved=aMetaData->IsRetrieved();
247   if(AlreadyRetrieved) myRetrievableStatus = PCDM_RS_AlreadyRetrieved;
248   Standard_Boolean Modified=AlreadyRetrieved && aMetaData->Document()->IsModified();
249   if(Modified) myRetrievableStatus = PCDM_RS_AlreadyRetrievedAndModified;
250   if(!AlreadyRetrieved || Modified)
251   {
252     TCollection_ExtendedString aFormat;
253     if (!Format(aMetaData->FileName(), aFormat))
254     {
255       Standard_SStream aMsg;
256       aMsg << "Could not determine format for the file " << aMetaData->FileName() << (char)0;
257       throw Standard_NoSuchObject(aMsg.str().c_str());
258     }
259     Handle(PCDM_Reader) theReader = ReaderFromFormat (aFormat);
260         
261     Handle(CDM_Document) theDocument;
262
263     if(Modified)  {
264       theDocument=aMetaData->Document();
265       theDocument->RemoveAllReferences();
266     }
267     else
268       theDocument=theReader->CreateDocument();
269     
270     SetReferenceCounter(theDocument,PCDM_RetrievalDriver::ReferenceCounter(aMetaData->FileName(), MessageDriver()));
271     
272     SetDocumentVersion(theDocument,aMetaData);
273     myMetaDataDriver->ReferenceIterator()->LoadReferences(theDocument,aMetaData,this,UseStorageConfiguration);
274
275     try {    
276       OCC_CATCH_SIGNALS
277       theReader->Read (aMetaData->FileName(), theDocument, this, theRange);
278     } 
279     catch (Standard_Failure const& anException) {
280       myRetrievableStatus = theReader->GetStatus();
281       if(myRetrievableStatus  > PCDM_RS_AlreadyRetrieved){
282         Standard_SStream aMsg;
283         aMsg << anException << std::endl;
284         throw Standard_Failure(aMsg.str().c_str());
285       } 
286     }
287     myRetrievableStatus = theReader->GetStatus();    
288     theDocument->SetMetaData(aMetaData);
289
290     theDocumentToReturn=theDocument;
291   }
292   else
293     theDocumentToReturn=aMetaData->Document();
294   
295   return theDocumentToReturn;
296 }
297
298 //=======================================================================
299 //function : DocumentVersion
300 //purpose  : 
301 //=======================================================================
302 Standard_Integer CDF_Application::DocumentVersion(const Handle(CDM_MetaData)& theMetaData) {
303 //  const Handle(CDM_MessageDriver)& aMsgDriver = MessageDriver();
304   return PCDM_RetrievalDriver::DocumentVersion(theMetaData->FileName(), MessageDriver());
305 }
306
307 //=======================================================================
308 //function : TypeOfActivation
309 //purpose  : 
310 //=======================================================================
311 CDF_TypeOfActivation CDF_Application::TypeOfActivation(const Handle(CDM_MetaData)& aMetaData) {
312
313   if(aMetaData->IsRetrieved()) {
314     Handle(CDM_Document) theDocument=aMetaData->Document();
315     if(theDocument->IsOpened()) {
316       if(theDocument->IsModified())
317         return CDF_TOA_Modified;
318       else
319         return CDF_TOA_Unchanged;
320     }
321     
322     else
323       return CDF_TOA_New;
324   }
325   return CDF_TOA_New;
326 }
327
328 //=======================================================================
329 //function : Read
330 //purpose  : 
331 //=======================================================================
332 Handle(CDM_Document) CDF_Application::Read (Standard_IStream& theIStream,
333                                             const Message_ProgressRange& theRange)
334 {
335   Handle(CDM_Document) aDoc;
336   Handle(Storage_Data) dData;
337   
338   TCollection_ExtendedString aFormat;
339
340   try
341   {
342     OCC_CATCH_SIGNALS
343     
344     aFormat = PCDM_ReadWriter::FileFormat (theIStream, dData);
345   }
346   catch (Standard_Failure const& anException)
347   {
348     myRetrievableStatus = PCDM_RS_FormatFailure;
349     
350     Standard_SStream aMsg;
351     aMsg << anException << std::endl;
352     throw Standard_Failure(aMsg.str().c_str());
353   }
354
355   if (aFormat.IsEmpty())
356   {
357     myRetrievableStatus = PCDM_RS_FormatFailure;
358     return aDoc;
359   }
360  
361   // 1. use a format name to detect plugin corresponding to the format to continue reading
362   Handle(PCDM_Reader) aReader = ReaderFromFormat (aFormat);
363
364   // 2. create document with the detected reader
365   aDoc = aReader->CreateDocument();
366
367   // 3. read the content of theIStream to aDoc
368   try
369   {
370     OCC_CATCH_SIGNALS
371     aReader->Read (theIStream, dData, aDoc, this, theRange);
372   }
373   catch (Standard_Failure const& anException)
374   {
375     myRetrievableStatus = aReader->GetStatus();
376     if (myRetrievableStatus  > PCDM_RS_AlreadyRetrieved)
377     {
378       Standard_SStream aMsg;
379       aMsg << anException << std::endl;
380       throw Standard_Failure(aMsg.str().c_str());
381     }   
382   }
383
384   myRetrievableStatus = aReader->GetStatus();
385
386   return aDoc;
387 }
388
389 //=======================================================================
390 //function : ReaderFromFormat
391 //purpose  : 
392 //=======================================================================
393 Handle(PCDM_Reader) CDF_Application::ReaderFromFormat(const TCollection_ExtendedString& theFormat)
394 {
395   // check map of readers
396   Handle(PCDM_RetrievalDriver) aReader;
397   if (myReaders.FindFromKey (theFormat, aReader))
398     return aReader;
399
400   // support of legacy method of loading reader as plugin
401   TCollection_ExtendedString aResourceName = theFormat;
402   aResourceName += ".RetrievalPlugin";
403   if (!UTL::Find(Resources(), aResourceName))
404   {
405     Standard_SStream aMsg; 
406     aMsg << "Could not found the item:" << aResourceName <<(char)0;
407     myRetrievableStatus = PCDM_RS_WrongResource;
408     throw Standard_NoSuchObject(aMsg.str().c_str());
409   }
410
411   // Get GUID as a string.
412   TCollection_ExtendedString strPluginId = UTL::Value(Resources(), aResourceName);
413     
414   // If the GUID (as a string) contains blanks, remove them.
415   if (strPluginId.Search(' ') != -1)
416     strPluginId.RemoveAll(' ');
417     
418   // Convert to GUID.
419   Standard_GUID aPluginId = UTL::GUID(strPluginId);
420
421   try {
422     OCC_CATCH_SIGNALS
423     aReader = Handle(PCDM_RetrievalDriver)::DownCast(Plugin::Load(aPluginId));  
424   } 
425   catch (Standard_Failure const& anException)
426   {
427     myRetrievableStatus = PCDM_RS_WrongResource;
428     throw anException;
429   }     
430   if (!aReader.IsNull()) {
431     aReader->SetFormat(theFormat);
432   }
433   else
434   {
435     myRetrievableStatus = PCDM_RS_WrongResource;
436   }
437
438   // record in map
439   myReaders.Add(theFormat, aReader);
440   return aReader;
441 }
442
443 //=======================================================================
444 //function : WriterFromFormat
445 //purpose  : 
446 //=======================================================================
447 Handle(PCDM_StorageDriver) CDF_Application::WriterFromFormat(const TCollection_ExtendedString& theFormat)
448 {  
449   // check map of writers
450   Handle(PCDM_StorageDriver) aDriver;
451   if (myWriters.FindFromKey(theFormat, aDriver))
452     return aDriver;
453
454   // support of legacy method of loading reader as plugin
455   TCollection_ExtendedString aResourceName = theFormat;
456   aResourceName += ".StoragePlugin";  
457   if(!UTL::Find(Resources(), aResourceName))
458   {
459     myWriters.Add(theFormat, aDriver);
460     Standard_SStream aMsg; 
461     aMsg << "Could not found the resource definition:" << aResourceName <<(char)0;
462     throw Standard_NoSuchObject(aMsg.str().c_str());
463   }
464
465   // Get GUID as a string.
466   TCollection_ExtendedString strPluginId = UTL::Value(Resources(), aResourceName);
467     
468   // If the GUID (as a string) contains blanks, remove them.
469   if (strPluginId.Search(' ') != -1)
470     strPluginId.RemoveAll(' ');
471     
472   // Convert to GUID.
473   Standard_GUID aPluginId = UTL::GUID(strPluginId);
474
475   try {
476     OCC_CATCH_SIGNALS
477     aDriver = Handle(PCDM_StorageDriver)::DownCast(Plugin::Load(aPluginId));
478   } 
479   catch (Standard_Failure const& anException)
480   {
481     myWriters.Add(theFormat, aDriver);
482     myRetrievableStatus = PCDM_RS_WrongResource;
483     throw anException;
484   }     
485   if (aDriver.IsNull()) 
486   {
487     myRetrievableStatus = PCDM_RS_WrongResource;
488   }
489   else
490   {
491     aDriver->SetFormat(theFormat);
492   }
493
494   // record in map
495   myWriters.Add(theFormat, aDriver);
496   return aDriver;
497 }
498
499 //=======================================================================
500 //function : Format
501 //purpose  : dp 
502 //=======================================================================
503 Standard_Boolean CDF_Application::Format(const TCollection_ExtendedString& aFileName, 
504                                          TCollection_ExtendedString& theFormat)
505 {
506   
507   theFormat = PCDM_ReadWriter::FileFormat(aFileName);
508 // It is good if the format is in the file. Otherwise base on the extension.
509   if(theFormat.Length()==0) {
510     TCollection_ExtendedString ResourceName;
511     ResourceName=UTL::Extension(aFileName);
512     ResourceName+=".FileFormat";
513     
514     if(UTL::Find(Resources(),ResourceName))  {
515       theFormat = UTL::Value(Resources(),ResourceName);
516     }
517     else return Standard_False;
518   }
519   return Standard_True;
520 }
521
522 //=======================================================================
523 //function : CanRetrieve
524 //purpose  : 
525 //=======================================================================
526 PCDM_ReaderStatus CDF_Application::CanRetrieve(const Handle(CDM_MetaData)& aMetaData) {
527   if(aMetaData->HasVersion())
528     return CanRetrieve(aMetaData->Folder(),aMetaData->Name(),aMetaData->Version());
529   else
530     return CanRetrieve(aMetaData->Folder(),aMetaData->Name());
531 }
532
533 //=======================================================================
534 //function : MetaDataDriver
535 //purpose  :
536 //=======================================================================
537 Handle(CDF_MetaDataDriver) CDF_Application::MetaDataDriver() const {
538   Standard_NoSuchObject_Raise_if(myMetaDataDriver.IsNull(), "no metadatadriver has been provided; this application is not able to store or retrieve files.");
539   return myMetaDataDriver;
540 }