Integration of OCCT 6.5.0 from SVN
[occt.git] / src / BinLDrivers / BinLDrivers_DocumentRetrievalDriver.cxx
CommitLineData
7fd59977 1// File: BinLDrivers_DocumentRetrievalDriver.cxx
2// Created: 31.10.02 11:12:22
3// Author: Michael SAZONOV
4// Copyright: Open CASCADE 2002
5
6#include <BinLDrivers_DocumentRetrievalDriver.ixx>
7#include <BinLDrivers.hxx>
8#include <BinLDrivers_Marker.hxx>
9#include <BinMDF_ADriver.hxx>
10#include <BinMDataStd.hxx>
11#include <BinObjMgt_Persistent.hxx>
12#include <FSD_BinaryFile.hxx>
13#include <FSD_FileHeader.hxx>
14#include <Standard_ErrorHandler.hxx>
15#include <Standard_Stream.hxx>
16#include <Storage_Schema.hxx>
17#include <TDF_Data.hxx>
18#include <TDocStd_Document.hxx>
19#include <TDocStd_Owner.hxx>
20
21#define SHAPESECTION_POS "SHAPE_SECTION_POS:"
22#define SIZEOFSHAPELABEL 18
23
24#define DATATYPE_MIGRATION
25//#define DATATYPE_MIGRATION_DEB
26//=======================================================================
27//function : BinLDrivers_DocumentRetrievalDriver
28//purpose : Constructor
29//=======================================================================
30
31BinLDrivers_DocumentRetrievalDriver::BinLDrivers_DocumentRetrievalDriver ()
32{
33 myReaderStatus = PCDM_RS_OK;
34}
35
36//=======================================================================
37//function : CreateDocument
38//purpose : pure virtual method definition
39//=======================================================================
40
41Handle(CDM_Document) BinLDrivers_DocumentRetrievalDriver::CreateDocument()
42{
43 return new TDocStd_Document(PCDM_RetrievalDriver::GetFormat());
44}
45
46//=======================================================================
47//function : SchemaName
48//purpose : pure virtual method definition
49//=======================================================================
50
51TCollection_ExtendedString BinLDrivers_DocumentRetrievalDriver::SchemaName() const
52{
53 TCollection_ExtendedString schemaname;
54 return schemaname;
55}
56
57//=======================================================================
58//function : Make
59//purpose : pure virtual method definition
60//=======================================================================
61
62void BinLDrivers_DocumentRetrievalDriver::Make (const Handle(PCDM_Document)&,
63 const Handle(CDM_Document)&)
64{
65}
66
67//=======================================================================
68//function : Read
69//purpose :
70//=======================================================================
71
72#define START_TYPES "START_TYPES"
73#define END_TYPES "END_TYPES"
74
75void BinLDrivers_DocumentRetrievalDriver::Read
76 (const TCollection_ExtendedString& theFileName,
77 const Handle(CDM_Document)& theNewDocument,
78 const Handle(CDM_Application)& theApplication)
79{
80 myReaderStatus = PCDM_RS_DriverFailure;
81 myMsgDriver = theApplication -> MessageDriver();
82
83 const TCollection_ExtendedString aMethStr
84 ("BinLDrivers_DocumentRetrievalDriver: ");
85
86 Handle(TDocStd_Document) aDoc =
87 Handle(TDocStd_Document)::DownCast(theNewDocument);
88 if (aDoc.IsNull()) {
89#ifdef DEB
90 WriteMessage (aMethStr + "error: null document");
91#endif
92 myReaderStatus = PCDM_RS_NoDocument;
93 return;
94 }
95
96 TCollection_AsciiString aFileName (theFileName,'?');
97
98 // 1. Read the information section
99 Handle(Storage_HeaderData) aHeaderData;
100 Storage_Position anInfoSectionEnd = ReadInfoSection( aFileName, aHeaderData );
101 if (!anInfoSectionEnd) {
102 WriteMessage (aMethStr + "error: file has invalid header");
103 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
104 return;
105 }
106
107 // 1.a Version of writer
108 if (!aHeaderData->StorageVersion().IsIntegerValue()) {
109 // file has no format version
110 WriteMessage (aMethStr + "error: file has no format version");
111 myReaderStatus = PCDM_RS_FormatFailure;
112 return;
113 }
114 Standard_Integer aFileVer = aHeaderData->StorageVersion().IntegerValue();
115 Standard_Integer aCurrVer = BinLDrivers::StorageVersion().IntegerValue();
116 // maintain one-way compatibility starting from version 2+
117 if (aFileVer < 2 || aFileVer > aCurrVer) {
118 // file was written with another version
119 WriteMessage (aMethStr + "error: wrong file version: " +
120 aHeaderData->StorageVersion() + " while current is " +
121 BinLDrivers::StorageVersion());
122 myReaderStatus = PCDM_RS_NoVersion;
123 return;
124 }
125
126 // 1.b Retrieve the Types table
127 TColStd_SequenceOfAsciiString aTypeNames; //Sequence of types in file
128 const TColStd_SequenceOfAsciiString& aUserInfo = aHeaderData->UserInfo();
129 Standard_Boolean begin = Standard_False;
130 Standard_Integer i;
131 for (i=1; i <= aUserInfo.Length(); i++) {
132 //const TCollection_AsciiString& aStr = aUserInfo(i);
133 TCollection_AsciiString aStr = aUserInfo(i);
134 if (aStr == START_TYPES)
135 begin = Standard_True;
136 else if (aStr == END_TYPES)
137 break;
138 else if (begin) {
139 if(aFileVer < 5) {
140#ifdef DATATYPE_MIGRATION
141 TCollection_AsciiString newName;
142 if(Storage_Schema::CheckTypeMigration(aStr, newName)) {
143#ifdef DATATYPE_MIGRATION_DEB
144 cout << "CheckTypeMigration:OldType = " <<aStr << " Len = "<<aStr.Length()<<endl;
145 cout << "CheckTypeMigration:NewType = " <<newName << " Len = "<< newName.Length()<<endl;
146#endif
147 aStr = newName;
148 }
149#endif
150 }
151 aTypeNames.Append (aStr);
152 }
153 }
154 if (myDrivers.IsNull())
155 myDrivers = AttributeDrivers (myMsgDriver);
156 myDrivers->AssignIds (aTypeNames);
157
158 // recognize types not supported by drivers
159 myMapUnsupported.Clear();
160 for (i=1; i <= aTypeNames.Length(); i++)
161 if (myDrivers->GetDriver(i).IsNull())
162 myMapUnsupported.Add(i);
163 if (!myMapUnsupported.IsEmpty()) {
164 WriteMessage (aMethStr + "warning: "
165 "the following attributes have no driver:");
166 for (i=1; i <= aTypeNames.Length(); i++)
167 if (myMapUnsupported.Contains(i))
168 WriteMessage (aTypeNames(i));
169 }
170
171 // Open the file stream
172#ifdef WNT
173 ifstream anIS (aFileName.ToCString(), ios::in | ios::binary);
174#else
175 ifstream anIS (aFileName.ToCString());
176#endif
177
178 if (!anIS) {
179 // Can not open file
180 WriteMessage (aMethStr + "error: can't open file " + theFileName);
181 myReaderStatus = PCDM_RS_OpenError;
182 return;
183 }
184
185 // skip info section
186 anIS.seekg( (streampos) anInfoSectionEnd );
187
188 // propagate the opened document version to data drivers
189 PropagateDocumentVersion(aFileVer);
190
191 // 2. Read document contents
192
193 // 2a. Retrieve data from the stream:
194 myRelocTable.Clear();
195 mySections.Clear();
196 myPAtt.Init();
197 Handle(TDF_Data) aData = new TDF_Data();
198 Standard_Integer aDocumentPos = -1;
199
200 // 2b. Read the TOC of Sections
201 if (aFileVer >= 3) {
202 BinLDrivers_DocumentSection aSection;
203 do {
204 BinLDrivers_DocumentSection::ReadTOC (aSection, anIS);
205 mySections.Append(aSection);
206 } while
207 (!aSection.Name().IsEqual((Standard_CString)SHAPESECTION_POS));
208 aDocumentPos = anIS.tellg(); // position of root label
209
210 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
211 for (; anIterS.More(); anIterS.Next()) {
212 BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue();
213 if (aCurSection.IsPostRead() == Standard_False) {
214 anIS.seekg ((streampos) aCurSection.Offset());
215 if (aCurSection.Name().IsEqual ((Standard_CString)SHAPESECTION_POS))
216 ReadShapeSection (aCurSection, anIS);
217 else
218 ReadSection (aCurSection, theNewDocument, anIS);
219 }
220 }
221 } else { //aFileVer < 3
222 aDocumentPos = anIS.tellg(); // position of root label
223
224 // retrieve SHAPESECTION_POS string
225 char aShapeSecLabel[SIZEOFSHAPELABEL + 1];
226 aShapeSecLabel[SIZEOFSHAPELABEL] = 0x00;
227 anIS.read ((char*)&aShapeSecLabel, SIZEOFSHAPELABEL);// SHAPESECTION_POS
228 TCollection_AsciiString aShapeLabel(aShapeSecLabel);
229 // detect if a file was written in old fashion (version 2 without shapes)
230 // and if so then skip reading ShapeSection
231 if (aShapeLabel.Length() > 0) {
232 // version 2+(with shapes) and higher goes here
233 if(aShapeLabel.Length() <= 0 || aShapeLabel != SHAPESECTION_POS) {
234 WriteMessage (aMethStr + "error: Format failure");
235 myReaderStatus = PCDM_RS_FormatFailure;
236 return;
237 }
238
239 // retrieve ShapeSection Position
240 Standard_Integer aShapeSectionPos; // go to ShapeSection
241 anIS.read ((char*)&aShapeSectionPos, sizeof(Standard_Integer));
242
243#if DO_INVERSE
244 aShapeSectionPos = InverseInt (aShapeSectionPos);
245#endif
246#ifdef DATATYPE_MIGRATION_DEB
247 cout <<"aShapeSectionPos = " <<aShapeSectionPos <<endl;
248#endif
249 if(aShapeSectionPos) {
250 aDocumentPos = anIS.tellg();
251 anIS.seekg((streampos) aShapeSectionPos);
252
253 CheckShapeSection((streampos)aShapeSectionPos, anIS);
254 // Read Shapes
255 BinLDrivers_DocumentSection aCurSection;
256 ReadShapeSection (aCurSection, anIS, Standard_False);
257 }
258 }
259 } // end of reading Sections or shape section
260
261 // Return to read of the Document structure
262 anIS.seekg((streampos) aDocumentPos);
263
264 // read the header (tag) of the root label
265 Standard_Integer aTag;
266 anIS.read ((char*)&aTag, sizeof(Standard_Integer));
267
268 // read sub-tree of the root label
269 Standard_Integer nbRead = ReadSubTree (anIS, aData->Root());
270 myPAtt.Destroy(); // free buffer
271 myRelocTable.Clear();
272 myMapUnsupported.Clear();
273
274 if (nbRead > 0) {
275 // attach data to the document
276 aDoc->SetData (aData);
277 TDocStd_Owner::SetDocument (aData, aDoc);
278 aDoc->SetComments(aHeaderData->Comments());
279 myReaderStatus = PCDM_RS_OK;
280 }
281
282 // Read Sections (post-reading type)
283 if (aFileVer >= 3) {
284 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
285 for (; anIterS.More(); anIterS.Next()) {
286 BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue();
287 if (aCurSection.IsPostRead()) {
288 anIS.seekg ((streampos) aCurSection.Offset());
289 ReadSection (aCurSection, theNewDocument, anIS);
290 }
291 }
292 }
293}
294
295//=======================================================================
296//function : ReadSubTree
297//purpose :
298//=======================================================================
299
300Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
301 (Standard_IStream& theIS,
302 const TDF_Label& theLabel)
303{
304 Standard_Integer nbRead = 0;
305 static TCollection_ExtendedString aMethStr
306 ("BinLDrivers_DocumentRetrievalDriver: ");
307
308 // Read attributes:
309 theIS >> myPAtt;
310 while (theIS && myPAtt.TypeId() > 0 && // not an end marker ?
311 myPAtt.Id() > 0) { // not a garbage ?
312 // get a driver according to TypeId
313 Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver (myPAtt.TypeId());
314 if (!aDriver.IsNull()) {
315 // create transient attribute
316 nbRead++;
317 Standard_Integer anID = myPAtt.Id();
318 Handle(TDF_Attribute) tAtt;
319 Standard_Boolean isBound = myRelocTable.IsBound(anID);
320 if (isBound)
321 tAtt = Handle(TDF_Attribute)::DownCast(myRelocTable.Find(anID));
322 else
323 tAtt = aDriver->NewEmpty();
324 if (tAtt->Label().IsNull())
325 theLabel.AddAttribute (tAtt);
326 else
327 WriteMessage (aMethStr +
328 "warning: attempt to attach attribute " +
329 aDriver->TypeName() + " to a second label");
330
331 Standard_Boolean ok = aDriver->Paste (myPAtt, tAtt, myRelocTable);
332 if (!ok) {
333 // error converting persistent to transient
334 WriteMessage (aMethStr + "warning: failure reading attribute " +
335 aDriver->TypeName());
336 }
337 else if (!isBound)
338 myRelocTable.Bind (anID, tAtt);
339 }
340 else if (!myMapUnsupported.Contains(myPAtt.TypeId()))
341 WriteMessage (aMethStr + "warning: type ID not registered in header: "
342 + myPAtt.TypeId());
343
344 // read next attribute
345 theIS >> myPAtt;
346 }
347 if (!theIS || myPAtt.TypeId() != BinLDrivers_ENDATTRLIST) {
348 // unexpected EOF or garbage data
349 WriteMessage (aMethStr + "error: unexpected EOF or garbage data");
350 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
351 return -1;
352 }
353
354 // Read children:
355 // read the tag of a child label
356 Standard_Integer aTag = BinLDrivers_ENDLABEL;
357 theIS.read ((char*) &aTag, sizeof(Standard_Integer));
358#if DO_INVERSE
359 aTag = InverseInt (aTag);
360#endif
361 while (theIS && aTag >= 0) { // not an end marker ?
362 // create sub-label
363 TDF_Label aLab = theLabel.FindChild (aTag, Standard_True);
364
365 // read sub-tree
366 Standard_Integer nbSubRead = ReadSubTree(theIS, aLab);
367 // check for error
368 if (nbSubRead == -1)
369 return -1;
370 nbRead += nbSubRead;
371
372 // read the tag of the next child
373 theIS.read ((char*) &aTag, sizeof(Standard_Integer));
374#if DO_INVERSE
375 aTag = InverseInt (aTag);
376#endif
377 }
378 if (aTag != BinLDrivers_ENDLABEL) {
379 // invalid end label marker
380 WriteMessage (aMethStr + "error: invalid end label marker");
381 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
382 return -1;
383 }
384
385 return nbRead;
386}
387
388//=======================================================================
389//function : AttributeDrivers
390//purpose :
391//=======================================================================
392
393Handle(BinMDF_ADriverTable) BinLDrivers_DocumentRetrievalDriver::AttributeDrivers
394 (const Handle(CDM_MessageDriver)& theMessageDriver)
395{
396 return BinLDrivers::AttributeDrivers (theMessageDriver);
397}
398
399//=======================================================================
400//function : ReadInfoSection
401//purpose : Read the info section of theFile, return a file
402// position corresponding to the info section end
403//=======================================================================
404
405Storage_Position BinLDrivers_DocumentRetrievalDriver::ReadInfoSection
406 (const TCollection_AsciiString& theFileName,
407 Handle(Storage_HeaderData)& theData)
408{
409 TCollection_ExtendedString aMsg
410 ( "BinLDrivers_DocumentRetrievalDriver: error: ");
411
412 FSD_BinaryFile aFileDriver;
413 Storage_Position aPos = 0;
414 if (aFileDriver.Open( theFileName, Storage_VSRead ) == Storage_VSOk)
415 {
416 Storage_Schema aSchema;
417 theData = aSchema.ReadHeaderSection( aFileDriver );
418
419 if (theData->ErrorStatus() == Storage_VSOk)
420 aPos = aFileDriver.Tell();
421 else
422 WriteMessage( aMsg + theData->ErrorStatusExtension() );
423 }
424 else
425 WriteMessage( aMsg + "can not open file " + theFileName);
426
427 aFileDriver.Close();
428
429 return aPos;
430}
431
432//=======================================================================
433//function : WriteMessage
434//purpose : write theMessage to the MessageDriver of
435// theApplication
436//=======================================================================
437
438void BinLDrivers_DocumentRetrievalDriver::WriteMessage
439 (const TCollection_ExtendedString& theMsg)
440{
441 if (!myMsgDriver.IsNull())
442 myMsgDriver->Write (theMsg.ToExtString());
443}
444
445//=======================================================================
446//function : ReadSection
447//purpose :
448//=======================================================================
449
450void BinLDrivers_DocumentRetrievalDriver::ReadSection
451 (BinLDrivers_DocumentSection& /*theSection*/,
452 const Handle(CDM_Document)& /*theDocument*/,
453 Standard_IStream& /*theIS*/)
454{
455 // empty; should be redefined in subclasses
456}
457
458//=======================================================================
459//function : ReadShapeSection
460//purpose :
461//=======================================================================
462
463void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection
464 (BinLDrivers_DocumentSection& theSection,
465 Standard_IStream& /*theIS*/,
466 const Standard_Boolean isMess)
467
468{
469 if(isMess && theSection.Length()) {
470 const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: ");
471 WriteMessage (aMethStr + "warning: Geometry is not supported by Lite schema. ");
472 }
473}
474
475//=======================================================================
476//function : CheckShapeSection
477//purpose :
478//=======================================================================
479void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection(
480 const Storage_Position& ShapeSectionPos,
481 Standard_IStream& IS)
482{
483 if(!IS.eof()) {
484#if defined(WNT) || defined(HAVE_IOSTREAM)
485 const Storage_Position endPos = IS.rdbuf()->pubseekoff(0L, std::ios_base::end, std::ios_base::in);
486#else
487 const Storage_Position endPos = IS.rdbuf()->seekoff(0L, unsafe_ios::end, unsafe_ios::in);
488#endif
489#ifdef DATATYPE_MIGRATION_DEB
490 cout << "endPos = " << endPos <<endl;
491#endif
492 if(ShapeSectionPos != endPos) {
493 const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: ");
494 WriteMessage (aMethStr + "warning: Geometry is not supported by Lite schema. ");
495 }
496 }
497}
498
499//=======================================================================
500//function : PropagateDocumentVersion
501//purpose :
502//=======================================================================
503void BinLDrivers_DocumentRetrievalDriver::PropagateDocumentVersion(const Standard_Integer theDocVersion )
504{
505 BinMDataStd::SetDocumentVersion(theDocVersion);
506}