0025748: Parallel version of progress indicator
[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 : CreateDocument
43 //purpose  : Create an empty TDocStd_Document
44 //=======================================================================
45 Handle(CDM_Document) StdLDrivers_DocumentRetrievalDriver::CreateDocument()
46 {
47   return new TDocStd_Document (PCDM_RetrievalDriver::GetFormat());
48 }
49
50 //=======================================================================
51 //function : Read
52 //purpose  : Retrieve the content of a file into a new document
53 //=======================================================================
54 void StdLDrivers_DocumentRetrievalDriver::Read (const TCollection_ExtendedString& theFileName,
55                                                 const Handle(CDM_Document)&       theNewDocument,
56                                                 const Handle(CDM_Application)&                  ,
57                                                 const Message_ProgressRange&     /*theRange*/)
58 {
59   // Read header data and persistent document
60   Storage_HeaderData aHeaderData;
61   Handle(StdObjMgt_Persistent) aPDocument = read (theFileName, aHeaderData);
62   if (aPDocument.IsNull())
63     return;
64
65   // Import transient document from the persistent one
66   aPDocument->ImportDocument (
67     Handle(TDocStd_Document)::DownCast (theNewDocument));
68
69   // Copy comments from the header data
70   theNewDocument->SetComments (aHeaderData.Comments());
71 }
72
73 //=======================================================================
74 //function : read
75 //purpose  : Read persistent document from a file
76 //=======================================================================
77 Handle(StdObjMgt_Persistent) StdLDrivers_DocumentRetrievalDriver::read (
78   const TCollection_ExtendedString& theFileName,
79   Storage_HeaderData&               theHeaderData)
80 {
81   Standard_Integer i;
82
83   // Create a driver appropriate for the given file
84   Handle(Storage_BaseDriver) aFileDriver;
85   if (PCDM::FileDriverType (TCollection_AsciiString (theFileName), aFileDriver) == PCDM_TOFD_Unknown)
86   {
87     myReaderStatus = PCDM_RS_UnknownFileDriver;
88     return NULL;
89   }
90
91   // Try to open the file
92   try
93   {
94     OCC_CATCH_SIGNALS
95     PCDM_ReadWriter::Open (aFileDriver, theFileName, Storage_VSRead);
96     myReaderStatus = PCDM_RS_OK;
97   } 
98   catch (Standard_Failure const& anException)
99   {
100     myReaderStatus = PCDM_RS_OpenError;
101
102     Standard_SStream aMsg;
103     aMsg << anException << std::endl;
104     throw Standard_Failure(aMsg.str().c_str());
105   }
106   
107   // Read header section
108   if (!theHeaderData.Read (aFileDriver))
109     raiseOnStorageError (theHeaderData.ErrorStatus());
110
111   // Read type section
112   Storage_TypeData aTypeData;
113   if (!aTypeData.Read (aFileDriver))
114     raiseOnStorageError (aTypeData.ErrorStatus());
115
116   // Read root section
117   Storage_RootData aRootData;
118   if (!aRootData.Read (aFileDriver))
119     raiseOnStorageError (aRootData.ErrorStatus());
120
121   if (aRootData.NumberOfRoots() < 1)
122   {
123     myReaderStatus = PCDM_RS_NoDocument;
124
125     Standard_SStream aMsg;
126     aMsg << "could not find any document in this file" << std::endl;
127     throw Standard_Failure(aMsg.str().c_str());
128   }
129
130   // Select instantiators for the used types
131   NCollection_Array1<StdObjMgt_Persistent::Instantiator>
132     anInstantiators (1, aTypeData.NumberOfTypes());
133   {
134     StdObjMgt_MapOfInstantiators aMapOfInst;
135     bindTypes (aMapOfInst);
136
137     TColStd_SequenceOfAsciiString anUnknownTypes;
138     Standard_Integer        aCurTypeNum;
139     TCollection_AsciiString aCurTypeName;
140
141     for (i = 1; i <= aTypeData.NumberOfTypes(); i++)
142     {
143       aCurTypeName = aTypeData.Type (i);
144       aCurTypeNum  = aTypeData.Type (aCurTypeName);
145
146           TCollection_AsciiString  newName;
147           if (Storage_Schema::CheckTypeMigration(aCurTypeName, newName)) {
148 #ifdef OCCT_DEBUG
149                   std::cout << "CheckTypeMigration:OldType = " << aCurTypeName << " Len = " << aCurTypeNum << std::endl;
150                   std::cout << "CheckTypeMigration:NewType = " << newName << " Len = " << newName.Length() << std::endl;
151 #endif
152                   aCurTypeName = newName;
153           }
154       StdObjMgt_Persistent::Instantiator anInstantiator;
155       if (aMapOfInst.Find(aCurTypeName, anInstantiator))
156         anInstantiators (aCurTypeNum) = anInstantiator;
157       else
158         anUnknownTypes.Append (aCurTypeName);
159     }
160
161     if (!anUnknownTypes.IsEmpty())
162     {
163       myReaderStatus = PCDM_RS_TypeNotFoundInSchema;
164
165       Standard_SStream aMsg;
166       aMsg << "cannot read: `" << theFileName
167             << "' because it contains the following unknown types: ";
168       for (i = 1; i <= anUnknownTypes.Length(); i++)
169       {
170         aMsg << anUnknownTypes(i);
171         if (i < anUnknownTypes.Length()) aMsg << ",";
172         else                             aMsg << std::endl;
173       }
174
175       throw Standard_Failure(aMsg.str().c_str());
176     }
177   }
178
179   // Read and parse reference section
180   StdObjMgt_ReadData aReadData (aFileDriver, theHeaderData.NumberOfObjects());
181
182   raiseOnStorageError (aFileDriver->BeginReadRefSection());
183
184   Standard_Integer len = aFileDriver->RefSectionSize();
185   for (i = 1; i <= len; i++)
186   {
187     Standard_Integer aRef = 0, aType = 0;
188     Storage_Error anError;
189     try
190     {
191       OCC_CATCH_SIGNALS
192       aFileDriver->ReadReferenceType (aRef, aType);
193       anError = Storage_VSOk;
194     }
195     catch (Storage_StreamTypeMismatchError const&)
196     {
197       anError = Storage_VSTypeMismatch;
198     }
199
200     raiseOnStorageError (anError);
201
202     aReadData.CreatePersistentObject (aRef, anInstantiators (aType));
203   }
204
205   raiseOnStorageError (aFileDriver->EndReadRefSection());
206
207   // Read and parse data section
208   raiseOnStorageError (aFileDriver->BeginReadDataSection());
209
210   for (i = 1; i <= theHeaderData.NumberOfObjects(); i++)
211   {
212     Storage_Error anError;
213     try
214     {
215       OCC_CATCH_SIGNALS
216       aReadData.ReadPersistentObject (i);
217       anError = Storage_VSOk;
218     }
219     catch (Storage_StreamTypeMismatchError const&) { anError = Storage_VSTypeMismatch; }
220     catch (Storage_StreamFormatError const&      ) { anError = Storage_VSFormatError;  }
221     catch (Storage_StreamReadError const&        ) { anError = Storage_VSFormatError;  }
222
223     raiseOnStorageError (anError);
224   }
225
226   raiseOnStorageError (aFileDriver->EndReadDataSection());
227
228   // Get persistent document from the root object
229   return aReadData.PersistentObject (aRootData.Roots()->First()->Reference());
230 }
231
232 //=======================================================================
233 //function : Read
234 //purpose  : not implemented
235 //=======================================================================
236
237 void StdLDrivers_DocumentRetrievalDriver::Read (Standard_IStream&               /*theIStream*/,
238                                                 const Handle(Storage_Data)&     /*theStorageData*/,
239                                                 const Handle(CDM_Document)&     /*theDoc*/,
240                                                 const Handle(CDM_Application)&  /*theApplication*/,
241                                                 const Message_ProgressRange&    /*theRange*/)
242 {
243   throw Standard_NotImplemented("Reading from stream is not supported by StdLDrivers_DocumentRetrievalDriver");
244 }
245
246 //=======================================================================
247 //function : raiseOnStorageError
248 //purpose  : Update the reader status and raise an exception
249 //           appropriate for the given storage error
250 //=======================================================================
251 void StdLDrivers_DocumentRetrievalDriver::raiseOnStorageError (Storage_Error theError)
252 {
253   Standard_SStream aMsg;
254
255   switch (theError)
256   {
257   case Storage_VSOk:
258     break;
259
260   case Storage_VSOpenError:
261   case Storage_VSNotOpen:
262   case Storage_VSAlreadyOpen:
263     myReaderStatus = PCDM_RS_OpenError;
264     aMsg << "Stream Open Error" << std::endl;
265     throw Standard_Failure(aMsg.str().c_str());
266
267   case Storage_VSModeError:
268     myReaderStatus = PCDM_RS_WrongStreamMode;
269     aMsg << "Stream is opened with a wrong mode for operation" << std::endl;
270     throw Standard_Failure(aMsg.str().c_str());
271
272   case Storage_VSSectionNotFound:
273     myReaderStatus = PCDM_RS_FormatFailure;
274     aMsg << "Section is not found" << std::endl;
275     throw Standard_Failure(aMsg.str().c_str());
276
277   case Storage_VSFormatError:
278     myReaderStatus = PCDM_RS_FormatFailure;
279     aMsg << "Wrong format error" << std::endl;
280     throw Standard_Failure(aMsg.str().c_str());
281
282   case Storage_VSUnknownType:
283     myReaderStatus = PCDM_RS_TypeFailure;
284     aMsg << "Try to read an unknown type" << std::endl;
285     throw Standard_Failure(aMsg.str().c_str());
286
287   case Storage_VSTypeMismatch:
288     myReaderStatus = PCDM_RS_TypeFailure;
289     aMsg << "Try to read a wrong primitive type" << std::endl;
290     throw Standard_Failure(aMsg.str().c_str());
291
292   default:
293     myReaderStatus = PCDM_RS_DriverFailure;
294     aMsg << "Retrieval Driver Failure" << std::endl;
295     throw Standard_Failure(aMsg.str().c_str());
296   }
297 }
298
299 //=======================================================================
300 //function : bindTypes
301 //purpose  : Register types
302 //=======================================================================
303 void StdLDrivers_DocumentRetrievalDriver::bindTypes (StdObjMgt_MapOfInstantiators& theMap)
304 {
305   StdLDrivers::BindTypes (theMap);
306 }