1 // File: BinLDrivers_DocumentStorageDriver.cxx
2 // Created: 29.10.02 11:53:01
3 // Author: Michael SAZONOV
4 // Copyright: Open CASCADE 2002
6 #include <BinLDrivers_DocumentStorageDriver.ixx>
7 #include <BinLDrivers.hxx>
8 #include <BinLDrivers_Marker.hxx>
9 #include <BinMDF_ADriver.hxx>
10 #include <BinObjMgt_Persistent.hxx>
11 #include <CDM_Application.hxx>
12 #include <FSD_BinaryFile.hxx>
13 #include <FSD_FileHeader.hxx>
14 #include <PCDM_ReadWriter.hxx>
15 #include <Standard_ErrorHandler.hxx>
16 #include <Storage_Schema.hxx>
17 #include <TColStd_Array1OfInteger.hxx>
18 #include <TColStd_ListIteratorOfListOfInteger.hxx>
19 #include <TColStd_ListOfInteger.hxx>
20 #include <TCollection_AsciiString.hxx>
21 #include <TDF_AttributeIterator.hxx>
22 #include <TDF_ChildIterator.hxx>
23 #include <TDF_Data.hxx>
24 #include <TDF_Tool.hxx>
25 #include <TDocStd_Document.hxx>
27 #define SHAPESECTION_POS (Standard_CString)"SHAPE_SECTION_POS:"
29 //=======================================================================
30 //function : BinLDrivers_DocumentStorageDriver
31 //purpose : Constructor
32 //=======================================================================
34 BinLDrivers_DocumentStorageDriver::BinLDrivers_DocumentStorageDriver ()
38 //=======================================================================
39 //function : SchemaName
41 //=======================================================================
43 TCollection_ExtendedString BinLDrivers_DocumentStorageDriver::SchemaName() const
45 TCollection_ExtendedString schemaname;
49 //=======================================================================
52 //=======================================================================
54 void BinLDrivers_DocumentStorageDriver::Write
55 (const Handle(CDM_Document)& theDocument,
56 const TCollection_ExtendedString& theFileName)
58 myIsError = Standard_False;
59 myMsgDriver = theDocument -> Application() -> MessageDriver();
60 myMapUnsupported.Clear();
62 #if defined(_DEBUG) || defined(DEB)
63 TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentStorageDriver, ");
65 TCollection_ExtendedString aMethStr;
67 TCollection_ExtendedString anErrorStr ("Error: ");
69 Handle(TDocStd_Document) aDoc =
70 Handle(TDocStd_Document)::DownCast(theDocument);
72 myIsError = Standard_True;
76 TCollection_AsciiString aFileName (theFileName,'?');
78 // First pass: collect empty labels, assign IDs to the types
79 if (myDrivers.IsNull())
80 myDrivers = AttributeDrivers (myMsgDriver);
81 Handle(TDF_Data) aData = aDoc->GetData();
82 FirstPass (aData->Root());
84 // 1. Write info section (including types table)
85 WriteInfoSection(theDocument, aFileName);
90 #if !defined(IRIX) // 10.10.2005
91 ofstream anOS (aFileName.ToCString(), ios::in | ios::binary | ios::ate);
93 ofstream anOS (aFileName.ToCString(), ios::ate);
94 //ofstream anOS (aFileName.ToCString(), ios::out| ios::binary | ios::ate);
97 const Standard_Integer aP = (Standard_Integer) anOS.tellp();
98 cout << "POS = " << aP <<endl;
104 // 2. Write the Table of Contents of Sections
105 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
106 for (; anIterS.More(); anIterS.Next())
107 anIterS.ChangeValue().WriteTOC (anOS);
109 // Shapes Section is the last one, it indicates the end of the table.
110 BinLDrivers_DocumentSection aShapesSection (SHAPESECTION_POS,
112 aShapesSection.WriteTOC (anOS);
114 // 3. Write document contents
115 // (Storage data to the stream)
116 myRelocTable.Clear();
119 // Write Doc structure
120 WriteSubTree (aData->Root(), anOS); // Doc is written
122 // 4. Write Shapes section
123 WriteShapeSection(aShapesSection, anOS);
125 // Write application-defined sections
126 for (anIterS.Init (mySections); anIterS.More(); anIterS.Next()) {
127 BinLDrivers_DocumentSection& aSection = anIterS.ChangeValue();
128 const Standard_Size aSectionOffset = (Standard_Size) anOS.tellp();
129 WriteSection (aSection.Name(), theDocument, anOS);
130 aSection.Write (anOS, aSectionOffset);
133 // End of processing: close structures and check the status
134 myPAtt.Destroy(); // free buffer
135 myEmptyLabels.Clear();
136 myMapUnsupported.Clear();
138 if (!myRelocTable.Extent()) {
139 // No objects written
141 WriteMessage (aMethStr + "no objects written");
143 myIsError = Standard_True;
145 myRelocTable.Clear();
149 // A problem with the stream
150 #if defined(_DEBUG) || defined(DEB)
151 WriteMessage (anErrorStr + aMethStr +
152 "Problem with the file stream, rdstate="
155 TCollection_ExtendedString aStr =
156 anErrorStr + aMethStr + "Problem writing the file ";
157 WriteMessage (aStr + theFileName);
159 myIsError = Standard_True;
165 //=======================================================================
166 //function : UnsupportedAttrMsg
168 //=======================================================================
170 void BinLDrivers_DocumentStorageDriver::UnsupportedAttrMsg
171 (const Handle(Standard_Type)& theType)
174 static TCollection_ExtendedString aMsg
175 ("BinDrivers_DocumentStorageDriver: warning: attribute driver for type ");
177 if (!myMapUnsupported.Contains(theType)) {
178 myMapUnsupported.Add(theType);
180 WriteMessage (aMsg + theType->Name() + " not found");
185 //=======================================================================
186 //function : WriteSubTree
188 //=======================================================================
190 void BinLDrivers_DocumentStorageDriver::WriteSubTree
191 (const TDF_Label& theLabel,
192 Standard_OStream& theOS)
195 if (!myEmptyLabels.IsEmpty() && myEmptyLabels.First() == theLabel) {
196 myEmptyLabels.RemoveFirst();
200 // Write label header: tag
201 Standard_Integer aTag = theLabel.Tag();
203 aTag = InverseInt (aTag);
205 theOS.write ((char*)&aTag, sizeof(Standard_Integer));
208 TDF_AttributeIterator itAtt (theLabel);
209 for ( ; itAtt.More() && theOS; itAtt.Next()) {
210 const Handle(TDF_Attribute)& tAtt = itAtt.Value();
211 const Handle(Standard_Type)& aType = tAtt->DynamicType();
212 // Get type ID and driver
213 Handle(BinMDF_ADriver) aDriver;
214 const Standard_Integer aTypeId = myDrivers->GetDriver (aType,aDriver);
216 // Add source to relocation table
217 const Standard_Integer anId = myRelocTable.Add (tAtt);
219 // Create and fill data item
220 myPAtt.SetTypeId (aTypeId);
222 aDriver->Paste (tAtt, myPAtt, myRelocTable);
224 // Write data to the stream -->!!!
229 UnsupportedAttrMsg (aType);
233 // Problem with the stream
237 // Write the end attributes list marker
238 BinLDrivers_Marker anEndAttr = BinLDrivers_ENDATTRLIST;
240 anEndAttr = (BinLDrivers_Marker) InverseInt (anEndAttr);
242 theOS.write ((char*)&anEndAttr, sizeof(anEndAttr));
244 // Process sub-labels
245 TDF_ChildIterator itChld (theLabel);
246 for ( ; itChld.More(); itChld.Next())
248 const TDF_Label& aChildLab = itChld.Value();
249 WriteSubTree (aChildLab, theOS);
252 // Write the end label marker
253 BinLDrivers_Marker anEndLabel = BinLDrivers_ENDLABEL;
255 anEndLabel = (BinLDrivers_Marker) InverseInt (anEndLabel);
257 theOS.write ((char*)&anEndLabel, sizeof(anEndLabel));
261 //=======================================================================
264 //=======================================================================
266 Standard_Boolean BinLDrivers_DocumentStorageDriver::IsError () const
271 //=======================================================================
272 //function : AttributeDrivers
274 //=======================================================================
276 Handle(BinMDF_ADriverTable) BinLDrivers_DocumentStorageDriver::AttributeDrivers
277 (const Handle(CDM_MessageDriver)& theMessageDriver)
279 return BinLDrivers::AttributeDrivers (theMessageDriver);
282 //=======================================================================
283 //function : FirstPassSubTree
285 //=======================================================================
287 Standard_Boolean BinLDrivers_DocumentStorageDriver::FirstPassSubTree
289 TDF_LabelList& ListOfEmptyL)
291 // are there writable attributes on L ?
292 Standard_Boolean hasAttr = Standard_False;
293 TDF_AttributeIterator itAtt (L);
294 for ( ; itAtt.More(); itAtt.Next()) {
295 const Handle(Standard_Type)& aType = itAtt.Value()->DynamicType();
296 Handle(BinMDF_ADriver) aDriver;
297 // do not rely on a value returned by GetDriver here, because
298 // the IDs have not yet been assigned to the types
299 myDrivers->GetDriver (aType, aDriver);
300 if (!aDriver.IsNull()) {
301 hasAttr = Standard_True;
302 myTypesMap.Add (aType);
306 UnsupportedAttrMsg (aType);
310 // are there writable attributes on sub-labels ?
311 Standard_Boolean hasChildAttr = Standard_False;
312 TDF_LabelList emptyChildrenList;
313 TDF_ChildIterator itChld (L);
314 for ( ; itChld.More(); itChld.Next())
316 if (FirstPassSubTree (itChld.Value(), emptyChildrenList))
317 emptyChildrenList.Append( itChld.Value() );
319 hasChildAttr = Standard_True;
322 Standard_Boolean isEmpty = !(hasAttr || hasChildAttr);
325 ListOfEmptyL.Append( emptyChildrenList );
330 //=======================================================================
331 //function : FirstPass
333 //=======================================================================
335 void BinLDrivers_DocumentStorageDriver::FirstPass
336 (const TDF_Label& theRoot)
339 myEmptyLabels.Clear();
341 if (FirstPassSubTree( theRoot, myEmptyLabels))
342 myEmptyLabels.Append( theRoot );
344 myDrivers->AssignIds (myTypesMap);
347 //=======================================================================
348 //function : WriteInfoSection
349 //purpose : Write info secton using FSD_BinaryFile driver
350 //=======================================================================
352 #define START_TYPES "START_TYPES"
353 #define END_TYPES "END_TYPES"
355 void BinLDrivers_DocumentStorageDriver::WriteInfoSection
356 (const Handle(CDM_Document)& theDocument,
357 const TCollection_AsciiString& theFileName)
359 FSD_BinaryFile aFileDriver;
360 if (aFileDriver.Open( theFileName, Storage_VSWrite ) != Storage_VSOk) {
361 #if defined(DEB) || defined(_DEBUG)
362 WriteMessage ("BinDrivers_DocumentStorageDriver: error opening file");
364 WriteMessage (TCollection_ExtendedString("Error: Cannot open file ") +
367 myIsError = Standard_True;
371 if (aFileDriver.BeginWriteInfoSection() == Storage_VSOk)
374 Handle(Storage_Data) theData = new Storage_Data;
375 PCDM_ReadWriter::WriteFileFormat( theData, theDocument );
376 PCDM_ReadWriter::Writer()->WriteReferenceCounter(theData,theDocument);
377 PCDM_ReadWriter::Writer()->WriteReferences(theData,theDocument,theFileName);
378 PCDM_ReadWriter::Writer()->WriteExtensions(theData,theDocument);
379 PCDM_ReadWriter::Writer()->WriteVersion(theData,theDocument);
381 // add the types table
382 theData->AddToUserInfo(START_TYPES);
384 for (i = 1; i <= myTypesMap.Extent(); i++) {
385 Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver(i);
386 if (!aDriver.IsNull()) {
387 const TCollection_AsciiString& aTypeName = aDriver->TypeName();
388 theData->AddToUserInfo(aTypeName);
391 theData->AddToUserInfo(END_TYPES);
393 // add document comments
394 TColStd_SequenceOfExtendedString aComments;
395 theDocument->Comments(aComments);
396 for (i = 1; i <= aComments.Length(); i++)
397 theData->AddToComments(aComments(i));
400 aFileDriver.WriteInfo
402 BinLDrivers::StorageVersion(),
403 Storage_Schema::ICreationDate(),
404 TCollection_AsciiString(SchemaName(),'?'),
406 theData->ApplicationName(),
407 theData->ApplicationVersion(),
412 // we write a complete header section: info and comments
413 aFileDriver.EndWriteInfoSection();
414 aFileDriver.BeginWriteCommentSection();
415 aFileDriver.WriteComment(theData->Comments());// <=== !!! szy - it was missed
416 aFileDriver.EndWriteCommentSection();
417 // here the location of info and comment sections is written
418 aFileDriver.EndWriteDataSection();
421 #if defined(DEB) || defined(_DEBUG)
422 WriteMessage("BinDrivers_DocumentStorageDriver: error writing header");
424 WriteMessage(TCollection_ExtendedString("Error: Problem writing header "
425 "into file ") + theFileName);
427 myIsError = Standard_True;
430 const Standard_Integer aP = (Standard_Integer) aFileDriver.Tell();
431 cout << "POS = " << aP <<endl;
436 //=======================================================================
437 //function : WriteMessage
438 //purpose : write theMessage to the MessageDriver of the
440 //=======================================================================
442 void BinLDrivers_DocumentStorageDriver::WriteMessage
443 (const TCollection_ExtendedString& theMsg)
445 if (!myMsgDriver.IsNull())
446 myMsgDriver->Write (theMsg.ToExtString());
449 //=======================================================================
450 //function : AddSection
452 //=======================================================================
454 void BinLDrivers_DocumentStorageDriver::AddSection
455 (const TCollection_AsciiString& theName,
456 const Standard_Boolean isPostRead)
458 mySections.Append (BinLDrivers_DocumentSection (theName, isPostRead));
461 //=======================================================================
462 //function : WriteSection
464 //=======================================================================
466 void BinLDrivers_DocumentStorageDriver::WriteSection
467 (const TCollection_AsciiString& /*theName*/,
468 const Handle_CDM_Document& /*theDocument*/,
469 Standard_OStream& /*theOS*/)
471 // empty; should be redefined in subclasses
474 //=======================================================================
475 //function : WriteShapeSection
476 //purpose : defines WriteShapeSection
477 //=======================================================================
478 void BinLDrivers_DocumentStorageDriver::WriteShapeSection
479 (BinLDrivers_DocumentSection& theSection,
480 Standard_OStream& theOS)
482 const Standard_Size aShapesSectionOffset = (Standard_Size) theOS.tellp();
483 theSection.Write (theOS, aShapesSectionOffset);