0031918: Application Framework - New binary format for fast reading part of OCAF...
[occt.git] / src / StdLDrivers / StdLDrivers_DocumentRetrievalDriver.cxx
1 // Copyright (c) 2015 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <StdLDrivers_DocumentRetrievalDriver.hxx>
15 #include <StdLDrivers.hxx>
16
17 #include <StdObjMgt_Persistent.hxx>
18 #include <StdObjMgt_MapOfInstantiators.hxx>
19 #include <StdObjMgt_ReadData.hxx>
20
21 #include <Storage_HeaderData.hxx>
22 #include <Storage_TypeData.hxx>
23 #include <Storage_RootData.hxx>
24 #include <Storage_BaseDriver.hxx>
25 #include <Storage_StreamTypeMismatchError.hxx>
26 #include <Storage_StreamFormatError.hxx>
27 #include <Storage_StreamReadError.hxx>
28
29 #include <PCDM.hxx>
30 #include <PCDM_ReadWriter.hxx>
31
32 #include <Standard_ErrorHandler.hxx>
33 #include <Standard_NotImplemented.hxx>
34 #include <NCollection_Array1.hxx>
35 #include <NCollection_Handle.hxx>
36 #include <TDocStd_Document.hxx>
37 #include <Storage_Schema.hxx>
38
39 IMPLEMENT_STANDARD_RTTIEXT (StdLDrivers_DocumentRetrievalDriver, PCDM_RetrievalDriver)
40
41 //=======================================================================
42 //function : Read
43 //purpose  : Retrieve the content of a file into a new document
44 //=======================================================================
45 void StdLDrivers_DocumentRetrievalDriver::Read (const TCollection_ExtendedString& theFileName,
46                                                 const Handle(CDM_Document)&       theNewDocument,
47                                                 const Handle(CDM_Application)&                  ,
48                                                 const Handle(PCDM_ReaderFilter)&                ,
49                                                 const Message_ProgressRange&     /*theRange*/)
50 {
51   // Read header data and persistent document
52   Storage_HeaderData aHeaderData;
53   Handle(StdObjMgt_Persistent) aPDocument = read (theFileName, aHeaderData);
54   if (aPDocument.IsNull())
55     return;
56
57   // Import transient document from the persistent one
58   aPDocument->ImportDocument (
59     Handle(TDocStd_Document)::DownCast (theNewDocument));
60
61   // Copy comments from the header data
62   theNewDocument->SetComments (aHeaderData.Comments());
63 }
64
65 //=======================================================================
66 //function : read
67 //purpose  : Read persistent document from a file
68 //=======================================================================
69 Handle(StdObjMgt_Persistent) StdLDrivers_DocumentRetrievalDriver::read (
70   const TCollection_ExtendedString& theFileName,
71   Storage_HeaderData&               theHeaderData)
72 {
73   Standard_Integer i;
74
75   // Create a driver appropriate for the given file
76   Handle(Storage_BaseDriver) aFileDriver;
77   if (PCDM::FileDriverType (TCollection_AsciiString (theFileName), aFileDriver) == PCDM_TOFD_Unknown)
78   {
79     myReaderStatus = PCDM_RS_UnknownFileDriver;
80     return NULL;
81   }
82
83   // Try to open the file
84   try
85   {
86     OCC_CATCH_SIGNALS
87     PCDM_ReadWriter::Open (aFileDriver, theFileName, Storage_VSRead);
88     myReaderStatus = PCDM_RS_OK;
89   } 
90   catch (Standard_Failure const& anException)
91   {
92     myReaderStatus = PCDM_RS_OpenError;
93
94     Standard_SStream aMsg;
95     aMsg << anException << std::endl;
96     throw Standard_Failure(aMsg.str().c_str());
97   }
98   
99   // Read header section
100   if (!theHeaderData.Read (aFileDriver))
101     raiseOnStorageError (theHeaderData.ErrorStatus());
102
103   // Read type section
104   Storage_TypeData aTypeData;
105   if (!aTypeData.Read (aFileDriver))
106     raiseOnStorageError (aTypeData.ErrorStatus());
107
108   // Read root section
109   Storage_RootData aRootData;
110   if (!aRootData.Read (aFileDriver))
111     raiseOnStorageError (aRootData.ErrorStatus());
112
113   if (aRootData.NumberOfRoots() < 1)
114   {
115     myReaderStatus = PCDM_RS_NoDocument;
116
117     Standard_SStream aMsg;
118     aMsg << "could not find any document in this file" << std::endl;
119     throw Standard_Failure(aMsg.str().c_str());
120   }
121
122   // Select instantiators for the used types
123   NCollection_Array1<StdObjMgt_Persistent::Instantiator>
124     anInstantiators (1, aTypeData.NumberOfTypes());
125   {
126     StdObjMgt_MapOfInstantiators aMapOfInst;
127     bindTypes (aMapOfInst);
128
129     TColStd_SequenceOfAsciiString anUnknownTypes;
130     Standard_Integer        aCurTypeNum;
131     TCollection_AsciiString aCurTypeName;
132
133     for (i = 1; i <= aTypeData.NumberOfTypes(); i++)
134     {
135       aCurTypeName = aTypeData.Type (i);
136       aCurTypeNum  = aTypeData.Type (aCurTypeName);
137
138           TCollection_AsciiString  newName;
139           if (Storage_Schema::CheckTypeMigration(aCurTypeName, newName)) {
140 #ifdef OCCT_DEBUG
141                   std::cout << "CheckTypeMigration:OldType = " << aCurTypeName << " Len = " << aCurTypeNum << std::endl;
142                   std::cout << "CheckTypeMigration:NewType = " << newName << " Len = " << newName.Length() << std::endl;
143 #endif
144                   aCurTypeName = newName;
145           }
146       StdObjMgt_Persistent::Instantiator anInstantiator;
147       if (aMapOfInst.Find(aCurTypeName, anInstantiator))
148         anInstantiators (aCurTypeNum) = anInstantiator;
149       else
150         anUnknownTypes.Append (aCurTypeName);
151     }
152
153     if (!anUnknownTypes.IsEmpty())
154     {
155       myReaderStatus = PCDM_RS_TypeNotFoundInSchema;
156
157       Standard_SStream aMsg;
158       aMsg << "cannot read: `" << theFileName
159             << "' because it contains the following unknown types: ";
160       for (i = 1; i <= anUnknownTypes.Length(); i++)
161       {
162         aMsg << anUnknownTypes(i);
163         if (i < anUnknownTypes.Length()) aMsg << ",";
164         else                             aMsg << std::endl;
165       }
166
167       throw Standard_Failure(aMsg.str().c_str());
168     }
169   }
170
171   // Read and parse reference section
172   StdObjMgt_ReadData aReadData (aFileDriver, theHeaderData.NumberOfObjects());
173
174   raiseOnStorageError (aFileDriver->BeginReadRefSection());
175
176   Standard_Integer len = aFileDriver->RefSectionSize();
177   for (i = 1; i <= len; i++)
178   {
179     Standard_Integer aRef = 0, aType = 0;
180     Storage_Error anError;
181     try
182     {
183       OCC_CATCH_SIGNALS
184       aFileDriver->ReadReferenceType (aRef, aType);
185       anError = Storage_VSOk;
186     }
187     catch (Storage_StreamTypeMismatchError const&)
188     {
189       anError = Storage_VSTypeMismatch;
190     }
191
192     raiseOnStorageError (anError);
193
194     aReadData.CreatePersistentObject (aRef, anInstantiators (aType));
195   }
196
197   raiseOnStorageError (aFileDriver->EndReadRefSection());
198
199   // Read and parse data section
200   raiseOnStorageError (aFileDriver->BeginReadDataSection());
201
202   for (i = 1; i <= theHeaderData.NumberOfObjects(); i++)
203   {
204     Storage_Error anError;
205     try
206     {
207       OCC_CATCH_SIGNALS
208       aReadData.ReadPersistentObject (i);
209       anError = Storage_VSOk;
210     }
211     catch (Storage_StreamTypeMismatchError const&) { anError = Storage_VSTypeMismatch; }
212     catch (Storage_StreamFormatError const&      ) { anError = Storage_VSFormatError;  }
213     catch (Storage_StreamReadError const&        ) { anError = Storage_VSFormatError;  }
214
215     raiseOnStorageError (anError);
216   }
217
218   raiseOnStorageError (aFileDriver->EndReadDataSection());
219
220   // Get persistent document from the root object
221   return aReadData.PersistentObject (aRootData.Roots()->First()->Reference());
222 }
223
224 //=======================================================================
225 //function : Read
226 //purpose  : not implemented
227 //=======================================================================
228
229 void StdLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&               /*theIStream*/,
230                                                 const Handle(Storage_Data)&     /*theStorageData*/,
231                                                 const Handle(CDM_Document)&     /*theDoc*/,
232                                                 const Handle(CDM_Application)&  /*theApplication*/,
233                                                 const Handle(PCDM_ReaderFilter)&/*theFilter*/,
234                                                 const Message_ProgressRange&    /*theRange*/)
235 {
236   throw Standard_NotImplemented("Reading from stream is not supported by StdLDrivers_DocumentRetrievalDriver");
237 }
238
239 //=======================================================================
240 //function : raiseOnStorageError
241 //purpose  : Update the reader status and raise an exception
242 //           appropriate for the given storage error
243 //=======================================================================
244 void StdLDrivers_DocumentRetrievalDriver::raiseOnStorageError (Storage_Error theError)
245 {
246   Standard_SStream aMsg;
247
248   switch (theError)
249   {
250   case Storage_VSOk:
251     break;
252
253   case Storage_VSOpenError:
254   case Storage_VSNotOpen:
255   case Storage_VSAlreadyOpen:
256     myReaderStatus = PCDM_RS_OpenError;
257     aMsg << "Stream Open Error" << std::endl;
258     throw Standard_Failure(aMsg.str().c_str());
259
260   case Storage_VSModeError:
261     myReaderStatus = PCDM_RS_WrongStreamMode;
262     aMsg << "Stream is opened with a wrong mode for operation" << std::endl;
263     throw Standard_Failure(aMsg.str().c_str());
264
265   case Storage_VSSectionNotFound:
266     myReaderStatus = PCDM_RS_FormatFailure;
267     aMsg << "Section is not found" << std::endl;
268     throw Standard_Failure(aMsg.str().c_str());
269
270   case Storage_VSFormatError:
271     myReaderStatus = PCDM_RS_FormatFailure;
272     aMsg << "Wrong format error" << std::endl;
273     throw Standard_Failure(aMsg.str().c_str());
274
275   case Storage_VSUnknownType:
276     myReaderStatus = PCDM_RS_TypeFailure;
277     aMsg << "Try to read an unknown type" << std::endl;
278     throw Standard_Failure(aMsg.str().c_str());
279
280   case Storage_VSTypeMismatch:
281     myReaderStatus = PCDM_RS_TypeFailure;
282     aMsg << "Try to read a wrong primitive type" << std::endl;
283     throw Standard_Failure(aMsg.str().c_str());
284
285   default:
286     myReaderStatus = PCDM_RS_DriverFailure;
287     aMsg << "Retrieval Driver Failure" << std::endl;
288     throw Standard_Failure(aMsg.str().c_str());
289   }
290 }
291
292 //=======================================================================
293 //function : bindTypes
294 //purpose  : Register types
295 //=======================================================================
296 void StdLDrivers_DocumentRetrievalDriver::bindTypes (StdObjMgt_MapOfInstantiators& theMap)
297 {
298   StdLDrivers::BindTypes (theMap);
299 }