1 // Created on: 2002-10-31
2 // Created by: Michael SAZONOV
3 // Copyright (c) 2002-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
21 #include <BinLDrivers_DocumentRetrievalDriver.ixx>
22 #include <BinLDrivers.hxx>
23 #include <BinLDrivers_Marker.hxx>
24 #include <BinMDF_ADriver.hxx>
25 #include <BinMDataStd.hxx>
26 #include <BinObjMgt_Persistent.hxx>
27 #include <FSD_BinaryFile.hxx>
28 #include <FSD_FileHeader.hxx>
29 #include <Standard_ErrorHandler.hxx>
30 #include <Standard_Stream.hxx>
31 #include <Storage_Schema.hxx>
32 #include <TDF_Data.hxx>
33 #include <TDocStd_Document.hxx>
34 #include <TDocStd_Owner.hxx>
36 #define SHAPESECTION_POS "SHAPE_SECTION_POS:"
37 #define SIZEOFSHAPELABEL 18
39 #define DATATYPE_MIGRATION
40 //#define DATATYPE_MIGRATION_DEB
41 //=======================================================================
42 //function : BinLDrivers_DocumentRetrievalDriver
43 //purpose : Constructor
44 //=======================================================================
46 BinLDrivers_DocumentRetrievalDriver::BinLDrivers_DocumentRetrievalDriver ()
48 myReaderStatus = PCDM_RS_OK;
51 //=======================================================================
52 //function : CreateDocument
53 //purpose : pure virtual method definition
54 //=======================================================================
56 Handle(CDM_Document) BinLDrivers_DocumentRetrievalDriver::CreateDocument()
58 return new TDocStd_Document(PCDM_RetrievalDriver::GetFormat());
61 //=======================================================================
62 //function : SchemaName
63 //purpose : pure virtual method definition
64 //=======================================================================
66 TCollection_ExtendedString BinLDrivers_DocumentRetrievalDriver::SchemaName() const
68 TCollection_ExtendedString schemaname;
72 //=======================================================================
74 //purpose : pure virtual method definition
75 //=======================================================================
77 void BinLDrivers_DocumentRetrievalDriver::Make (const Handle(PCDM_Document)&,
78 const Handle(CDM_Document)&)
82 //=======================================================================
85 //=======================================================================
87 #define START_TYPES "START_TYPES"
88 #define END_TYPES "END_TYPES"
90 void BinLDrivers_DocumentRetrievalDriver::Read
91 (const TCollection_ExtendedString& theFileName,
92 const Handle(CDM_Document)& theNewDocument,
93 const Handle(CDM_Application)& theApplication)
95 myReaderStatus = PCDM_RS_DriverFailure;
96 myMsgDriver = theApplication -> MessageDriver();
98 const TCollection_ExtendedString aMethStr
99 ("BinLDrivers_DocumentRetrievalDriver: ");
101 Handle(TDocStd_Document) aDoc =
102 Handle(TDocStd_Document)::DownCast(theNewDocument);
105 WriteMessage (aMethStr + "error: null document");
107 myReaderStatus = PCDM_RS_NoDocument;
111 TCollection_AsciiString aFileName (theFileName,'?');
113 // 1. Read the information section
114 Handle(Storage_HeaderData) aHeaderData;
115 Storage_Position anInfoSectionEnd = ReadInfoSection( aFileName, aHeaderData );
116 if (!anInfoSectionEnd) {
117 WriteMessage (aMethStr + "error: file has invalid header");
118 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
122 // 1.a Version of writer
123 if (!aHeaderData->StorageVersion().IsIntegerValue()) {
124 // file has no format version
125 WriteMessage (aMethStr + "error: file has no format version");
126 myReaderStatus = PCDM_RS_FormatFailure;
129 Standard_Integer aFileVer = aHeaderData->StorageVersion().IntegerValue();
130 Standard_Integer aCurrVer = BinLDrivers::StorageVersion().IntegerValue();
131 // maintain one-way compatibility starting from version 2+
132 if (aFileVer < 2 || aFileVer > aCurrVer) {
133 // file was written with another version
134 WriteMessage (aMethStr + "error: wrong file version: " +
135 aHeaderData->StorageVersion() + " while current is " +
136 BinLDrivers::StorageVersion());
137 myReaderStatus = PCDM_RS_NoVersion;
141 // 1.b Retrieve the Types table
142 TColStd_SequenceOfAsciiString aTypeNames; //Sequence of types in file
143 const TColStd_SequenceOfAsciiString& aUserInfo = aHeaderData->UserInfo();
144 Standard_Boolean begin = Standard_False;
146 for (i=1; i <= aUserInfo.Length(); i++) {
147 //const TCollection_AsciiString& aStr = aUserInfo(i);
148 TCollection_AsciiString aStr = aUserInfo(i);
149 if (aStr == START_TYPES)
150 begin = Standard_True;
151 else if (aStr == END_TYPES)
155 #ifdef DATATYPE_MIGRATION
156 TCollection_AsciiString newName;
157 if(Storage_Schema::CheckTypeMigration(aStr, newName)) {
158 #ifdef DATATYPE_MIGRATION_DEB
159 cout << "CheckTypeMigration:OldType = " <<aStr << " Len = "<<aStr.Length()<<endl;
160 cout << "CheckTypeMigration:NewType = " <<newName << " Len = "<< newName.Length()<<endl;
166 aTypeNames.Append (aStr);
169 if (myDrivers.IsNull())
170 myDrivers = AttributeDrivers (myMsgDriver);
171 myDrivers->AssignIds (aTypeNames);
173 // recognize types not supported by drivers
174 myMapUnsupported.Clear();
175 for (i=1; i <= aTypeNames.Length(); i++)
176 if (myDrivers->GetDriver(i).IsNull())
177 myMapUnsupported.Add(i);
178 if (!myMapUnsupported.IsEmpty()) {
179 WriteMessage (aMethStr + "warning: "
180 "the following attributes have no driver:");
181 for (i=1; i <= aTypeNames.Length(); i++)
182 if (myMapUnsupported.Contains(i))
183 WriteMessage (aTypeNames(i));
186 // Open the file stream
188 ifstream anIS (aFileName.ToCString(), ios::in | ios::binary);
190 ifstream anIS (aFileName.ToCString());
195 WriteMessage (aMethStr + "error: can't open file " + theFileName);
196 myReaderStatus = PCDM_RS_OpenError;
201 anIS.seekg( (streampos) anInfoSectionEnd );
203 // propagate the opened document version to data drivers
204 PropagateDocumentVersion(aFileVer);
206 // 2. Read document contents
208 // 2a. Retrieve data from the stream:
209 myRelocTable.Clear();
212 Handle(TDF_Data) aData = new TDF_Data();
213 streampos aDocumentPos = -1;
215 // 2b. Read the TOC of Sections
217 BinLDrivers_DocumentSection aSection;
219 BinLDrivers_DocumentSection::ReadTOC (aSection, anIS);
220 mySections.Append(aSection);
222 (!aSection.Name().IsEqual((Standard_CString)SHAPESECTION_POS));
223 aDocumentPos = anIS.tellg(); // position of root label
225 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
226 for (; anIterS.More(); anIterS.Next()) {
227 BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue();
228 if (aCurSection.IsPostRead() == Standard_False) {
229 anIS.seekg ((streampos) aCurSection.Offset());
230 if (aCurSection.Name().IsEqual ((Standard_CString)SHAPESECTION_POS))
231 ReadShapeSection (aCurSection, anIS);
233 ReadSection (aCurSection, theNewDocument, anIS);
236 } else { //aFileVer < 3
237 aDocumentPos = anIS.tellg(); // position of root label
239 // retrieve SHAPESECTION_POS string
240 char aShapeSecLabel[SIZEOFSHAPELABEL + 1];
241 aShapeSecLabel[SIZEOFSHAPELABEL] = 0x00;
242 anIS.read ((char*)&aShapeSecLabel, SIZEOFSHAPELABEL);// SHAPESECTION_POS
243 TCollection_AsciiString aShapeLabel(aShapeSecLabel);
244 // detect if a file was written in old fashion (version 2 without shapes)
245 // and if so then skip reading ShapeSection
246 if (aShapeLabel.Length() > 0) {
247 // version 2+(with shapes) and higher goes here
248 if(aShapeLabel.Length() <= 0 || aShapeLabel != SHAPESECTION_POS) {
249 WriteMessage (aMethStr + "error: Format failure");
250 myReaderStatus = PCDM_RS_FormatFailure;
254 // retrieve ShapeSection Position
255 Standard_Integer aShapeSectionPos; // go to ShapeSection
256 anIS.read ((char*)&aShapeSectionPos, sizeof(Standard_Integer));
259 aShapeSectionPos = InverseInt (aShapeSectionPos);
261 #ifdef DATATYPE_MIGRATION_DEB
262 cout <<"aShapeSectionPos = " <<aShapeSectionPos <<endl;
264 if(aShapeSectionPos) {
265 aDocumentPos = anIS.tellg();
266 anIS.seekg((streampos) aShapeSectionPos);
268 CheckShapeSection((streampos)aShapeSectionPos, anIS);
270 BinLDrivers_DocumentSection aCurSection;
271 ReadShapeSection (aCurSection, anIS, Standard_False);
274 } // end of reading Sections or shape section
276 // Return to read of the Document structure
277 anIS.seekg(aDocumentPos);
279 // read the header (tag) of the root label
280 Standard_Integer aTag;
281 anIS.read ((char*)&aTag, sizeof(Standard_Integer));
283 // read sub-tree of the root label
284 Standard_Integer nbRead = ReadSubTree (anIS, aData->Root());
285 myPAtt.Destroy(); // free buffer
286 myRelocTable.Clear();
287 myMapUnsupported.Clear();
290 // attach data to the document
291 aDoc->SetData (aData);
292 TDocStd_Owner::SetDocument (aData, aDoc);
293 aDoc->SetComments(aHeaderData->Comments());
294 myReaderStatus = PCDM_RS_OK;
297 // Read Sections (post-reading type)
299 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
300 for (; anIterS.More(); anIterS.Next()) {
301 BinLDrivers_DocumentSection& aCurSection = anIterS.ChangeValue();
302 if (aCurSection.IsPostRead()) {
303 anIS.seekg ((streampos) aCurSection.Offset());
304 ReadSection (aCurSection, theNewDocument, anIS);
310 //=======================================================================
311 //function : ReadSubTree
313 //=======================================================================
315 Standard_Integer BinLDrivers_DocumentRetrievalDriver::ReadSubTree
316 (Standard_IStream& theIS,
317 const TDF_Label& theLabel)
319 Standard_Integer nbRead = 0;
320 static TCollection_ExtendedString aMethStr
321 ("BinLDrivers_DocumentRetrievalDriver: ");
325 while (theIS && myPAtt.TypeId() > 0 && // not an end marker ?
326 myPAtt.Id() > 0) { // not a garbage ?
327 // get a driver according to TypeId
328 Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver (myPAtt.TypeId());
329 if (!aDriver.IsNull()) {
330 // create transient attribute
332 Standard_Integer anID = myPAtt.Id();
333 Handle(TDF_Attribute) tAtt;
334 Standard_Boolean isBound = myRelocTable.IsBound(anID);
336 tAtt = Handle(TDF_Attribute)::DownCast(myRelocTable.Find(anID));
338 tAtt = aDriver->NewEmpty();
339 if (tAtt->Label().IsNull())
340 theLabel.AddAttribute (tAtt);
342 WriteMessage (aMethStr +
343 "warning: attempt to attach attribute " +
344 aDriver->TypeName() + " to a second label");
346 Standard_Boolean ok = aDriver->Paste (myPAtt, tAtt, myRelocTable);
348 // error converting persistent to transient
349 WriteMessage (aMethStr + "warning: failure reading attribute " +
350 aDriver->TypeName());
353 myRelocTable.Bind (anID, tAtt);
355 else if (!myMapUnsupported.Contains(myPAtt.TypeId()))
356 WriteMessage (aMethStr + "warning: type ID not registered in header: "
359 // read next attribute
362 if (!theIS || myPAtt.TypeId() != BinLDrivers_ENDATTRLIST) {
363 // unexpected EOF or garbage data
364 WriteMessage (aMethStr + "error: unexpected EOF or garbage data");
365 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
370 // read the tag of a child label
371 Standard_Integer aTag = BinLDrivers_ENDLABEL;
372 theIS.read ((char*) &aTag, sizeof(Standard_Integer));
374 aTag = InverseInt (aTag);
376 while (theIS && aTag >= 0) { // not an end marker ?
378 TDF_Label aLab = theLabel.FindChild (aTag, Standard_True);
381 Standard_Integer nbSubRead = ReadSubTree(theIS, aLab);
387 // read the tag of the next child
388 theIS.read ((char*) &aTag, sizeof(Standard_Integer));
390 aTag = InverseInt (aTag);
393 if (aTag != BinLDrivers_ENDLABEL) {
394 // invalid end label marker
395 WriteMessage (aMethStr + "error: invalid end label marker");
396 myReaderStatus = PCDM_RS_UnrecognizedFileFormat;
403 //=======================================================================
404 //function : AttributeDrivers
406 //=======================================================================
408 Handle(BinMDF_ADriverTable) BinLDrivers_DocumentRetrievalDriver::AttributeDrivers
409 (const Handle(CDM_MessageDriver)& theMessageDriver)
411 return BinLDrivers::AttributeDrivers (theMessageDriver);
414 //=======================================================================
415 //function : ReadInfoSection
416 //purpose : Read the info section of theFile, return a file
417 // position corresponding to the info section end
418 //=======================================================================
420 Storage_Position BinLDrivers_DocumentRetrievalDriver::ReadInfoSection
421 (const TCollection_AsciiString& theFileName,
422 Handle(Storage_HeaderData)& theData)
424 TCollection_ExtendedString aMsg
425 ( "BinLDrivers_DocumentRetrievalDriver: error: ");
427 FSD_BinaryFile aFileDriver;
428 Storage_Position aPos = 0;
429 if (aFileDriver.Open( theFileName, Storage_VSRead ) == Storage_VSOk)
431 Storage_Schema aSchema;
432 theData = aSchema.ReadHeaderSection( aFileDriver );
434 if (theData->ErrorStatus() == Storage_VSOk)
435 aPos = aFileDriver.Tell();
437 WriteMessage( aMsg + theData->ErrorStatusExtension() );
440 WriteMessage( aMsg + "can not open file " + theFileName);
447 //=======================================================================
448 //function : WriteMessage
449 //purpose : write theMessage to the MessageDriver of
451 //=======================================================================
453 void BinLDrivers_DocumentRetrievalDriver::WriteMessage
454 (const TCollection_ExtendedString& theMsg)
456 if (!myMsgDriver.IsNull())
457 myMsgDriver->Write (theMsg.ToExtString());
460 //=======================================================================
461 //function : ReadSection
463 //=======================================================================
465 void BinLDrivers_DocumentRetrievalDriver::ReadSection
466 (BinLDrivers_DocumentSection& /*theSection*/,
467 const Handle(CDM_Document)& /*theDocument*/,
468 Standard_IStream& /*theIS*/)
470 // empty; should be redefined in subclasses
473 //=======================================================================
474 //function : ReadShapeSection
476 //=======================================================================
478 void BinLDrivers_DocumentRetrievalDriver::ReadShapeSection
479 (BinLDrivers_DocumentSection& theSection,
480 Standard_IStream& /*theIS*/,
481 const Standard_Boolean isMess)
484 if(isMess && theSection.Length()) {
485 const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: ");
486 WriteMessage (aMethStr + "warning: Geometry is not supported by Lite schema. ");
490 //=======================================================================
491 //function : CheckShapeSection
493 //=======================================================================
494 void BinLDrivers_DocumentRetrievalDriver::CheckShapeSection(
495 const Storage_Position& ShapeSectionPos,
496 Standard_IStream& IS)
499 #if defined(WNT) || defined(HAVE_IOSTREAM)
500 const Storage_Position endPos = IS.rdbuf()->pubseekoff(0L, std::ios_base::end, std::ios_base::in);
502 const Storage_Position endPos = IS.rdbuf()->seekoff(0L, unsafe_ios::end, unsafe_ios::in);
504 #ifdef DATATYPE_MIGRATION_DEB
505 cout << "endPos = " << endPos <<endl;
507 if(ShapeSectionPos != endPos) {
508 const TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentRetrievalDriver: ");
509 WriteMessage (aMethStr + "warning: Geometry is not supported by Lite schema. ");
514 //=======================================================================
515 //function : PropagateDocumentVersion
517 //=======================================================================
518 void BinLDrivers_DocumentRetrievalDriver::PropagateDocumentVersion(const Standard_Integer theDocVersion )
520 BinMDataStd::SetDocumentVersion(theDocVersion);