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