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