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