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