1 // Copyright (c) 2015 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <StdLDrivers_DocumentRetrievalDriver.hxx>
15 #include <StdLDrivers.hxx>
17 #include <StdObjMgt_Persistent.hxx>
18 #include <StdObjMgt_MapOfInstantiators.hxx>
19 #include <StdObjMgt_ReadData.hxx>
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>
30 #include <PCDM_ReadWriter.hxx>
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>
39 IMPLEMENT_STANDARD_RTTIEXT (StdLDrivers_DocumentRetrievalDriver, PCDM_RetrievalDriver)
41 //=======================================================================
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 Message_ProgressRange& /*theRange*/)
50 // Read header data and persistent document
51 Storage_HeaderData aHeaderData;
52 Handle(StdObjMgt_Persistent) aPDocument = read (theFileName, aHeaderData);
53 if (aPDocument.IsNull())
56 // Import transient document from the persistent one
57 aPDocument->ImportDocument (
58 Handle(TDocStd_Document)::DownCast (theNewDocument));
60 // Copy comments from the header data
61 theNewDocument->SetComments (aHeaderData.Comments());
64 //=======================================================================
66 //purpose : Read persistent document from a file
67 //=======================================================================
68 Handle(StdObjMgt_Persistent) StdLDrivers_DocumentRetrievalDriver::read (
69 const TCollection_ExtendedString& theFileName,
70 Storage_HeaderData& theHeaderData)
74 // Create a driver appropriate for the given file
75 Handle(Storage_BaseDriver) aFileDriver;
76 if (PCDM::FileDriverType (TCollection_AsciiString (theFileName), aFileDriver) == PCDM_TOFD_Unknown)
78 myReaderStatus = PCDM_RS_UnknownFileDriver;
82 // Try to open the file
86 PCDM_ReadWriter::Open (aFileDriver, theFileName, Storage_VSRead);
87 myReaderStatus = PCDM_RS_OK;
89 catch (Standard_Failure const& anException)
91 myReaderStatus = PCDM_RS_OpenError;
93 Standard_SStream aMsg;
94 aMsg << anException << std::endl;
95 throw Standard_Failure(aMsg.str().c_str());
98 // Read header section
99 if (!theHeaderData.Read (aFileDriver))
100 raiseOnStorageError (theHeaderData.ErrorStatus());
103 Storage_TypeData aTypeData;
104 if (!aTypeData.Read (aFileDriver))
105 raiseOnStorageError (aTypeData.ErrorStatus());
108 Storage_RootData aRootData;
109 if (!aRootData.Read (aFileDriver))
110 raiseOnStorageError (aRootData.ErrorStatus());
112 if (aRootData.NumberOfRoots() < 1)
114 myReaderStatus = PCDM_RS_NoDocument;
116 Standard_SStream aMsg;
117 aMsg << "could not find any document in this file" << std::endl;
118 throw Standard_Failure(aMsg.str().c_str());
121 // Select instantiators for the used types
122 NCollection_Array1<StdObjMgt_Persistent::Instantiator>
123 anInstantiators (1, aTypeData.NumberOfTypes());
125 StdObjMgt_MapOfInstantiators aMapOfInst;
126 bindTypes (aMapOfInst);
128 TColStd_SequenceOfAsciiString anUnknownTypes;
129 Standard_Integer aCurTypeNum;
130 TCollection_AsciiString aCurTypeName;
132 for (i = 1; i <= aTypeData.NumberOfTypes(); i++)
134 aCurTypeName = aTypeData.Type (i);
135 aCurTypeNum = aTypeData.Type (aCurTypeName);
137 TCollection_AsciiString newName;
138 if (Storage_Schema::CheckTypeMigration(aCurTypeName, newName)) {
140 std::cout << "CheckTypeMigration:OldType = " << aCurTypeName << " Len = " << aCurTypeNum << std::endl;
141 std::cout << "CheckTypeMigration:NewType = " << newName << " Len = " << newName.Length() << std::endl;
143 aCurTypeName = newName;
145 StdObjMgt_Persistent::Instantiator anInstantiator;
146 if (aMapOfInst.Find(aCurTypeName, anInstantiator))
147 anInstantiators (aCurTypeNum) = anInstantiator;
149 anUnknownTypes.Append (aCurTypeName);
152 if (!anUnknownTypes.IsEmpty())
154 myReaderStatus = PCDM_RS_TypeNotFoundInSchema;
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++)
161 aMsg << anUnknownTypes(i);
162 if (i < anUnknownTypes.Length()) aMsg << ",";
163 else aMsg << std::endl;
166 throw Standard_Failure(aMsg.str().c_str());
170 // Read and parse reference section
171 StdObjMgt_ReadData aReadData (aFileDriver, theHeaderData.NumberOfObjects());
173 raiseOnStorageError (aFileDriver->BeginReadRefSection());
175 Standard_Integer len = aFileDriver->RefSectionSize();
176 for (i = 1; i <= len; i++)
178 Standard_Integer aRef = 0, aType = 0;
179 Storage_Error anError;
183 aFileDriver->ReadReferenceType (aRef, aType);
184 anError = Storage_VSOk;
186 catch (Storage_StreamTypeMismatchError const&)
188 anError = Storage_VSTypeMismatch;
191 raiseOnStorageError (anError);
193 aReadData.CreatePersistentObject (aRef, anInstantiators (aType));
196 raiseOnStorageError (aFileDriver->EndReadRefSection());
198 // Read and parse data section
199 raiseOnStorageError (aFileDriver->BeginReadDataSection());
201 for (i = 1; i <= theHeaderData.NumberOfObjects(); i++)
203 Storage_Error anError;
207 aReadData.ReadPersistentObject (i);
208 anError = Storage_VSOk;
210 catch (Storage_StreamTypeMismatchError const&) { anError = Storage_VSTypeMismatch; }
211 catch (Storage_StreamFormatError const& ) { anError = Storage_VSFormatError; }
212 catch (Storage_StreamReadError const& ) { anError = Storage_VSFormatError; }
214 raiseOnStorageError (anError);
217 raiseOnStorageError (aFileDriver->EndReadDataSection());
219 // Get persistent document from the root object
220 return aReadData.PersistentObject (aRootData.Roots()->First()->Reference());
223 //=======================================================================
225 //purpose : not implemented
226 //=======================================================================
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 Message_ProgressRange& /*theRange*/)
234 throw Standard_NotImplemented("Reading from stream is not supported by StdLDrivers_DocumentRetrievalDriver");
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)
244 Standard_SStream aMsg;
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());
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());
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());
268 case Storage_VSFormatError:
269 myReaderStatus = PCDM_RS_FormatFailure;
270 aMsg << "Wrong format error" << std::endl;
271 throw Standard_Failure(aMsg.str().c_str());
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());
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());
284 myReaderStatus = PCDM_RS_DriverFailure;
285 aMsg << "Retrieval Driver Failure" << std::endl;
286 throw Standard_Failure(aMsg.str().c_str());
290 //=======================================================================
291 //function : bindTypes
292 //purpose : Register types
293 //=======================================================================
294 void StdLDrivers_DocumentRetrievalDriver::bindTypes (StdObjMgt_MapOfInstantiators& theMap)
296 StdLDrivers::BindTypes (theMap);