0025266: Debug statements in the source are getting flushed on to the console
[occt.git] / src / BinLDrivers / BinLDrivers_DocumentStorageDriver.cxx
CommitLineData
b311480e 1// Created on: 2002-10-29
2// Created by: Michael SAZONOV
973c2be1 3// Copyright (c) 2002-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
16#include <BinLDrivers_DocumentStorageDriver.ixx>
17#include <BinLDrivers.hxx>
18#include <BinLDrivers_Marker.hxx>
19#include <BinMDF_ADriver.hxx>
20#include <BinObjMgt_Persistent.hxx>
21#include <CDM_Application.hxx>
22#include <FSD_BinaryFile.hxx>
23#include <FSD_FileHeader.hxx>
24#include <PCDM_ReadWriter.hxx>
25#include <Standard_ErrorHandler.hxx>
26#include <Storage_Schema.hxx>
27#include <TColStd_Array1OfInteger.hxx>
28#include <TColStd_ListIteratorOfListOfInteger.hxx>
29#include <TColStd_ListOfInteger.hxx>
30#include <TCollection_AsciiString.hxx>
31#include <TDF_AttributeIterator.hxx>
32#include <TDF_ChildIterator.hxx>
33#include <TDF_Data.hxx>
34#include <TDF_Tool.hxx>
35#include <TDocStd_Document.hxx>
36
37#define SHAPESECTION_POS (Standard_CString)"SHAPE_SECTION_POS:"
38
39//=======================================================================
40//function : BinLDrivers_DocumentStorageDriver
41//purpose : Constructor
42//=======================================================================
43
44BinLDrivers_DocumentStorageDriver::BinLDrivers_DocumentStorageDriver ()
45{
46}
47
48//=======================================================================
49//function : SchemaName
50//purpose :
51//=======================================================================
52
53TCollection_ExtendedString BinLDrivers_DocumentStorageDriver::SchemaName() const
54{
55 TCollection_ExtendedString schemaname;
56 return schemaname;
57}
58
59//=======================================================================
60//function : Write
61//purpose :
62//=======================================================================
63
64void BinLDrivers_DocumentStorageDriver::Write
65 (const Handle(CDM_Document)& theDocument,
66 const TCollection_ExtendedString& theFileName)
67{
15e8b082
M
68 SetIsError(Standard_False);
69 SetStoreStatus(PCDM_SS_OK);
70
7fd59977 71 myMsgDriver = theDocument -> Application() -> MessageDriver();
72 myMapUnsupported.Clear();
73
74#if defined(_DEBUG) || defined(DEB)
75 TCollection_ExtendedString aMethStr ("BinLDrivers_DocumentStorageDriver, ");
76#else
77 TCollection_ExtendedString aMethStr;
78#endif
79 TCollection_ExtendedString anErrorStr ("Error: ");
80
81 Handle(TDocStd_Document) aDoc =
82 Handle(TDocStd_Document)::DownCast(theDocument);
83 if (aDoc.IsNull()) {
15e8b082
M
84 SetIsError(Standard_True);
85 SetStoreStatus(PCDM_SS_Doc_IsNull);
7fd59977 86 }
87 else {
88 // Open the file
d9ff84e8 89 TCollection_AsciiString aFileName (theFileName);
7fd59977 90
91 // First pass: collect empty labels, assign IDs to the types
92 if (myDrivers.IsNull())
93 myDrivers = AttributeDrivers (myMsgDriver);
94 Handle(TDF_Data) aData = aDoc->GetData();
95 FirstPass (aData->Root());
96
97// 1. Write info section (including types table)
98 WriteInfoSection(theDocument, aFileName);
99 myTypesMap.Clear();
15e8b082
M
100 if (IsError())
101 {
102 SetStoreStatus(PCDM_SS_Info_Section_Error);
103 return;
104 }
7fd59977 105
d9ff84e8 106#if defined(_WIN32)
107 ofstream anOS ((const wchar_t*) theFileName.ToExtString(), ios::in | ios::binary | ios::ate);
108#elif !defined(IRIX) // 10.10.2005
7fd59977 109 ofstream anOS (aFileName.ToCString(), ios::in | ios::binary | ios::ate);
110#else
111 ofstream anOS (aFileName.ToCString(), ios::ate);
9293178b 112 //ofstream anOS (aFileName.ToCString(), ios::out| ios::binary | ios::ate);
7fd59977 113#endif
63c629aa 114#ifdef BINLDRIVERS_DEB
9293178b 115 const Standard_Integer aP = (Standard_Integer) anOS.tellp();
7fd59977 116 cout << "POS = " << aP <<endl;
117#endif
118//#endif
119
120 if (anOS) {
121
122// 2. Write the Table of Contents of Sections
123 BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections);
124 for (; anIterS.More(); anIterS.Next())
125 anIterS.ChangeValue().WriteTOC (anOS);
126
9293178b 127 // Shapes Section is the last one, it indicates the end of the table.
7fd59977 128 BinLDrivers_DocumentSection aShapesSection (SHAPESECTION_POS,
129 Standard_False);
9293178b 130 aShapesSection.WriteTOC (anOS);
7fd59977 131
132// 3. Write document contents
133 // (Storage data to the stream)
134 myRelocTable.Clear();
135 myPAtt.Init();
136
137// Write Doc structure
138 WriteSubTree (aData->Root(), anOS); // Doc is written
139
140// 4. Write Shapes section
141 WriteShapeSection(aShapesSection, anOS);
142
143// Write application-defined sections
144 for (anIterS.Init (mySections); anIterS.More(); anIterS.Next()) {
145 BinLDrivers_DocumentSection& aSection = anIterS.ChangeValue();
146 const Standard_Size aSectionOffset = (Standard_Size) anOS.tellp();
147 WriteSection (aSection.Name(), theDocument, anOS);
148 aSection.Write (anOS, aSectionOffset);
149 }
150
9293178b 151// End of processing: close structures and check the status
7fd59977 152 myPAtt.Destroy(); // free buffer
153 myEmptyLabels.Clear();
154 myMapUnsupported.Clear();
155
156 if (!myRelocTable.Extent()) {
157 // No objects written
158#ifdef DEB
159 WriteMessage (aMethStr + "no objects written");
160#endif
15e8b082
M
161 SetIsError(Standard_True);
162 SetStoreStatus(PCDM_SS_No_Obj);
163
7fd59977 164 }
165 myRelocTable.Clear();
166 }
167
168 if (!anOS) {
169 // A problem with the stream
170#if defined(_DEBUG) || defined(DEB)
171 WriteMessage (anErrorStr + aMethStr +
172 "Problem with the file stream, rdstate="
9293178b 173 + (Standard_Integer )anOS.rdstate());
7fd59977 174#else
175 TCollection_ExtendedString aStr =
176 anErrorStr + aMethStr + "Problem writing the file ";
177 WriteMessage (aStr + theFileName);
178#endif
15e8b082 179 SetIsError(Standard_True);
566f8441 180 SetStoreStatus(PCDM_SS_WriteFailure);
7fd59977 181 }
182
183 }
184}
185
186//=======================================================================
187//function : UnsupportedAttrMsg
9293178b 188//purpose :
7fd59977 189//=======================================================================
190
191void BinLDrivers_DocumentStorageDriver::UnsupportedAttrMsg
192 (const Handle(Standard_Type)& theType)
193{
194#ifdef DEB
195 static TCollection_ExtendedString aMsg
196 ("BinDrivers_DocumentStorageDriver: warning: attribute driver for type ");
197#endif
198 if (!myMapUnsupported.Contains(theType)) {
199 myMapUnsupported.Add(theType);
200#ifdef DEB
201 WriteMessage (aMsg + theType->Name() + " not found");
202#endif
203 }
204}
205
206//=======================================================================
207//function : WriteSubTree
208//purpose :
209//=======================================================================
210
211void BinLDrivers_DocumentStorageDriver::WriteSubTree
212 (const TDF_Label& theLabel,
213 Standard_OStream& theOS)
214{
215 // Skip empty labels
216 if (!myEmptyLabels.IsEmpty() && myEmptyLabels.First() == theLabel) {
217 myEmptyLabels.RemoveFirst();
218 return;
219 }
220
221 // Write label header: tag
222 Standard_Integer aTag = theLabel.Tag();
223#if DO_INVERSE
224 aTag = InverseInt (aTag);
225#endif
226 theOS.write ((char*)&aTag, sizeof(Standard_Integer));
227
228 // Write attributes
229 TDF_AttributeIterator itAtt (theLabel);
230 for ( ; itAtt.More() && theOS; itAtt.Next()) {
231 const Handle(TDF_Attribute)& tAtt = itAtt.Value();
232 const Handle(Standard_Type)& aType = tAtt->DynamicType();
233 // Get type ID and driver
234 Handle(BinMDF_ADriver) aDriver;
235 const Standard_Integer aTypeId = myDrivers->GetDriver (aType,aDriver);
236 if (aTypeId > 0) {
237 // Add source to relocation table
238 const Standard_Integer anId = myRelocTable.Add (tAtt);
239
240 // Create and fill data item
241 myPAtt.SetTypeId (aTypeId);
242 myPAtt.SetId (anId);
243 aDriver->Paste (tAtt, myPAtt, myRelocTable);
244
245 // Write data to the stream -->!!!
246 theOS << myPAtt;
247 }
248#ifdef DEB
249 else
250 UnsupportedAttrMsg (aType);
251#endif
252 }
253 if (!theOS) {
254 // Problem with the stream
255 return;
256 }
257
258 // Write the end attributes list marker
259 BinLDrivers_Marker anEndAttr = BinLDrivers_ENDATTRLIST;
260#if DO_INVERSE
261 anEndAttr = (BinLDrivers_Marker) InverseInt (anEndAttr);
262#endif
263 theOS.write ((char*)&anEndAttr, sizeof(anEndAttr));
264
265 // Process sub-labels
266 TDF_ChildIterator itChld (theLabel);
267 for ( ; itChld.More(); itChld.Next())
268 {
269 const TDF_Label& aChildLab = itChld.Value();
270 WriteSubTree (aChildLab, theOS);
271 }
272
273 // Write the end label marker
274 BinLDrivers_Marker anEndLabel = BinLDrivers_ENDLABEL;
275#if DO_INVERSE
276 anEndLabel = (BinLDrivers_Marker) InverseInt (anEndLabel);
277#endif
278 theOS.write ((char*)&anEndLabel, sizeof(anEndLabel));
279
280}
281
7fd59977 282//=======================================================================
283//function : AttributeDrivers
284//purpose :
285//=======================================================================
286
287Handle(BinMDF_ADriverTable) BinLDrivers_DocumentStorageDriver::AttributeDrivers
288 (const Handle(CDM_MessageDriver)& theMessageDriver)
289{
290 return BinLDrivers::AttributeDrivers (theMessageDriver);
291}
292
293//=======================================================================
294//function : FirstPassSubTree
295//purpose :
296//=======================================================================
297
298Standard_Boolean BinLDrivers_DocumentStorageDriver::FirstPassSubTree
299 (const TDF_Label& L,
300 TDF_LabelList& ListOfEmptyL)
301{
302 // are there writable attributes on L ?
303 Standard_Boolean hasAttr = Standard_False;
304 TDF_AttributeIterator itAtt (L);
305 for ( ; itAtt.More(); itAtt.Next()) {
306 const Handle(Standard_Type)& aType = itAtt.Value()->DynamicType();
307 Handle(BinMDF_ADriver) aDriver;
308 // do not rely on a value returned by GetDriver here, because
309 // the IDs have not yet been assigned to the types
310 myDrivers->GetDriver (aType, aDriver);
311 if (!aDriver.IsNull()) {
312 hasAttr = Standard_True;
313 myTypesMap.Add (aType);
314 }
315#ifdef DEB
316 else
317 UnsupportedAttrMsg (aType);
318#endif
319 }
320
321 // are there writable attributes on sub-labels ?
322 Standard_Boolean hasChildAttr = Standard_False;
323 TDF_LabelList emptyChildrenList;
324 TDF_ChildIterator itChld (L);
325 for ( ; itChld.More(); itChld.Next())
326 {
327 if (FirstPassSubTree (itChld.Value(), emptyChildrenList))
328 emptyChildrenList.Append( itChld.Value() );
329 else
330 hasChildAttr = Standard_True;
331 }
332
333 Standard_Boolean isEmpty = !(hasAttr || hasChildAttr);
334
335 if (!isEmpty)
336 ListOfEmptyL.Append( emptyChildrenList );
337
338 return isEmpty;
339}
340
341//=======================================================================
342//function : FirstPass
343//purpose :
344//=======================================================================
345
346void BinLDrivers_DocumentStorageDriver::FirstPass
347 (const TDF_Label& theRoot)
348{
349 myTypesMap.Clear();
350 myEmptyLabels.Clear();
351
352 if (FirstPassSubTree( theRoot, myEmptyLabels))
353 myEmptyLabels.Append( theRoot );
354
355 myDrivers->AssignIds (myTypesMap);
356}
357
358//=======================================================================
359//function : WriteInfoSection
360//purpose : Write info secton using FSD_BinaryFile driver
361//=======================================================================
362
363#define START_TYPES "START_TYPES"
364#define END_TYPES "END_TYPES"
365
366void BinLDrivers_DocumentStorageDriver::WriteInfoSection
367 (const Handle(CDM_Document)& theDocument,
368 const TCollection_AsciiString& theFileName)
369{
370 FSD_BinaryFile aFileDriver;
371 if (aFileDriver.Open( theFileName, Storage_VSWrite ) != Storage_VSOk) {
372#if defined(DEB) || defined(_DEBUG)
373 WriteMessage ("BinDrivers_DocumentStorageDriver: error opening file");
374#else
375 WriteMessage (TCollection_ExtendedString("Error: Cannot open file ") +
376 theFileName);
377#endif
15e8b082 378 SetIsError(Standard_True);
7fd59977 379 return;
380 }
381
382 if (aFileDriver.BeginWriteInfoSection() == Storage_VSOk)
383 {
384 // add format
385 Handle(Storage_Data) theData = new Storage_Data;
386 PCDM_ReadWriter::WriteFileFormat( theData, theDocument );
387 PCDM_ReadWriter::Writer()->WriteReferenceCounter(theData,theDocument);
388 PCDM_ReadWriter::Writer()->WriteReferences(theData,theDocument,theFileName);
389 PCDM_ReadWriter::Writer()->WriteExtensions(theData,theDocument);
390 PCDM_ReadWriter::Writer()->WriteVersion(theData,theDocument);
391
392 // add the types table
393 theData->AddToUserInfo(START_TYPES);
394 Standard_Integer i;
395 for (i = 1; i <= myTypesMap.Extent(); i++) {
396 Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver(i);
397 if (!aDriver.IsNull()) {
398 const TCollection_AsciiString& aTypeName = aDriver->TypeName();
399 theData->AddToUserInfo(aTypeName);
400 }
401 }
402 theData->AddToUserInfo(END_TYPES);
403
404 // add document comments
405 TColStd_SequenceOfExtendedString aComments;
406 theDocument->Comments(aComments);
407 for (i = 1; i <= aComments.Length(); i++)
408 theData->AddToComments(aComments(i));
409
410 // Info
411 aFileDriver.WriteInfo
9293178b 412 (1, // nbObj
7fd59977 413 BinLDrivers::StorageVersion(),
414 Storage_Schema::ICreationDate(),
415 TCollection_AsciiString(SchemaName(),'?'),
9293178b 416 1, // schemaVersion
7fd59977 417 theData->ApplicationName(),
418 theData->ApplicationVersion(),
419 theData->DataType(),
420 theData->UserInfo()
421 );
422
423 // we write a complete header section: info and comments
424 aFileDriver.EndWriteInfoSection();
425 aFileDriver.BeginWriteCommentSection();
426 aFileDriver.WriteComment(theData->Comments());// <=== !!! szy - it was missed
427 aFileDriver.EndWriteCommentSection();
428 // here the location of info and comment sections is written
429 aFileDriver.EndWriteDataSection();
430 }
431 else {
432#if defined(DEB) || defined(_DEBUG)
433 WriteMessage("BinDrivers_DocumentStorageDriver: error writing header");
434#else
435 WriteMessage(TCollection_ExtendedString("Error: Problem writing header "
436 "into file ") + theFileName);
437#endif
15e8b082 438 SetIsError(Standard_True);
7fd59977 439 }
63c629aa 440#ifdef BINLDRIVERS_DEB
9293178b 441 const Standard_Integer aP = (Standard_Integer) aFileDriver.Tell();
7fd59977 442 cout << "POS = " << aP <<endl;
9293178b 443#endif
7fd59977 444 aFileDriver.Close();
445}
446
447//=======================================================================
448//function : WriteMessage
449//purpose : write theMessage to the MessageDriver of the
450// Application
451//=======================================================================
452
453void BinLDrivers_DocumentStorageDriver::WriteMessage
454 (const TCollection_ExtendedString& theMsg)
455{
456 if (!myMsgDriver.IsNull())
457 myMsgDriver->Write (theMsg.ToExtString());
458}
459
460//=======================================================================
461//function : AddSection
9293178b 462//purpose :
7fd59977 463//=======================================================================
464
465void BinLDrivers_DocumentStorageDriver::AddSection
466 (const TCollection_AsciiString& theName,
467 const Standard_Boolean isPostRead)
468{
469 mySections.Append (BinLDrivers_DocumentSection (theName, isPostRead));
470}
471
472//=======================================================================
473//function : WriteSection
9293178b 474//purpose :
7fd59977 475//=======================================================================
476
477void BinLDrivers_DocumentStorageDriver::WriteSection
478 (const TCollection_AsciiString& /*theName*/,
857ffd5e 479 const Handle(CDM_Document)& /*theDocument*/,
7fd59977 480 Standard_OStream& /*theOS*/)
481{
482 // empty; should be redefined in subclasses
483}
484
485//=======================================================================
486//function : WriteShapeSection
487//purpose : defines WriteShapeSection
488//=======================================================================
489void BinLDrivers_DocumentStorageDriver::WriteShapeSection
490 (BinLDrivers_DocumentSection& theSection,
491 Standard_OStream& theOS)
492{
493 const Standard_Size aShapesSectionOffset = (Standard_Size) theOS.tellp();
494 theSection.Write (theOS, aShapesSectionOffset);
495}