0022898: IGES import fails in german environment
[occt.git] / src / Storage / Storage_Schema.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 #include <Storage_Schema.ixx>
20
21 #include <TColStd_HSequenceOfAsciiString.hxx>
22 #include <TColStd_MapOfAsciiString.hxx>
23
24 #include <Storage.hxx>
25 #include <Storage_BucketOfPersistent.hxx>
26 #include <Storage_InternalData.hxx>
27 #include <Storage_TypedCallBack.hxx>
28 #include <Storage_HPArray.hxx>
29 #include <Storage_HSeqOfRoot.hxx>
30 #include <Storage_Root.hxx>
31 #include <Storage_DataMapIteratorOfMapOfCallBack.hxx>
32 #include <Storage_DefaultCallBack.hxx>
33 #include <Storage_HArrayOfCallBack.hxx>
34
35 #include <Storage_StreamModeError.hxx>
36 #include <Storage_StreamFormatError.hxx>
37 #include <Storage_StreamWriteError.hxx>
38 #include <Storage_StreamReadError.hxx>
39 #include <Storage_StreamUnknownTypeError.hxx>
40 #include <Storage_StreamTypeMismatchError.hxx>
41 #include <Storage_StreamExtCharParityError.hxx>
42 #include <Standard_ErrorHandler.hxx>
43
44 #ifdef HAVE_CONFIG_H
45 # include <config.h>
46 #endif
47
48 #if defined(HAVE_TIME_H) || defined(WNT)
49 # include <time.h>
50 #endif
51
52 #ifdef HAVE_SYS_TIME_H
53 # include <sys/time.h>
54 #endif
55
56 #include <locale.h>
57 #include <stdio.h>
58
59 #define DATATYPE_MIGRATION
60
61 #ifdef DATATYPE_MIGRATION
62 #include <NCollection_DataMap.hxx>
63 #include <OSD_File.hxx>
64 #include <OSD_Path.hxx>
65 #include <OSD_Protection.hxx>
66 #include <OSD_Environment.hxx>
67
68 typedef NCollection_DataMap <TCollection_AsciiString, 
69   TCollection_AsciiString> DataMapOfAStringAString;
70
71 #endif
72
73 // IMPLEMENTATION BucketOfPersistent
74 //
75 Storage_Bucket::~Storage_Bucket()
76 {
77   Standard::Free((Standard_Address&)mySpace);
78   mySpace = 0L;
79   mySpaceSize = 0;
80   Clear();
81 }
82
83 //=======================================================================
84 //function : Clear
85 //purpose  : 
86 //=======================================================================
87
88 void Storage_Bucket::Clear()
89 {
90   myCurrentSpace = -1;
91 }
92
93 //=======================================================================
94 //function : Append
95 //purpose  : 
96 //=======================================================================
97
98 void Storage_Bucket::Append(Standard_Persistent *sp)
99 {
100   myCurrentSpace++;
101   mySpace[myCurrentSpace] = sp;
102 }
103
104 //=======================================================================
105 //function : Value
106 //purpose  : 
107 //=======================================================================
108
109 Standard_Persistent* Storage_Bucket::Value
110                          (const Standard_Integer theIndex) const
111 {
112   return mySpace[theIndex];
113 }
114
115 //=======================================================================
116 //function : Storage_BucketOfPersistent
117 //purpose  : 
118 //=======================================================================
119
120 Storage_BucketOfPersistent::Storage_BucketOfPersistent
121                          (const Standard_Integer theBucketSize,
122                           const Standard_Integer theBucketNumber)
123 : myNumberOfBucket(1),myNumberOfBucketAllocated(theBucketNumber),myBucketSize
124                          (theBucketSize)
125 {
126   myBuckets =  (Storage_Bucket**)Standard::Allocate
127                          (sizeof(Storage_Bucket*) * theBucketNumber);
128   myBuckets[0] = new Storage_Bucket(myBucketSize);
129   myCurrentBucket = myBuckets[0];
130   myLength = 0;
131   myCurrentBucketNumber = 0;
132 }
133
134 //=======================================================================
135 //function : Clear
136 //purpose  : 
137 //=======================================================================
138
139 void Storage_BucketOfPersistent::Clear()
140 {
141   if (myBuckets) {
142     Standard_Integer i;
143
144     for (i = 1; i < myNumberOfBucket; i++) delete myBuckets[i];
145     myNumberOfBucket = 1;
146     myCurrentBucket = myBuckets[0];
147     myCurrentBucket->Clear();
148     myCurrentBucketNumber = 0;
149     myLength = 0;
150   }
151 }
152
153 Storage_BucketOfPersistent::~Storage_BucketOfPersistent()
154 {
155   Clear();
156   delete myBuckets[0];
157   Standard::Free((Standard_Address&)myBuckets);
158   myBuckets = 0L;
159 }
160
161 //=======================================================================
162 //function : Value
163 //purpose  : 
164 //=======================================================================
165
166 Standard_Persistent* Storage_BucketOfPersistent::Value
167                          (const Standard_Integer theIndex)
168 {
169   Standard_Integer theInd,theCurrentBucketNumber,tecurrentind = theIndex - 1;
170   theCurrentBucketNumber = tecurrentind / myBucketSize;
171   theInd = tecurrentind - (myBucketSize * theCurrentBucketNumber);
172
173   return myBuckets[theCurrentBucketNumber]->mySpace[theInd];
174
175 }
176
177 //=======================================================================
178 //function : Append
179 //purpose  : 
180 //=======================================================================
181
182 void Storage_BucketOfPersistent::Append(const Handle(Standard_Persistent)& sp)
183 {
184   myCurrentBucket->myCurrentSpace++;
185
186   if (myCurrentBucket->myCurrentSpace != myBucketSize) {
187     myLength++;
188     myCurrentBucket->mySpace[myCurrentBucket->myCurrentSpace] = sp.operator->();
189     return;
190   }
191
192   myCurrentBucket->myCurrentSpace--;
193   myNumberOfBucket++;
194   myCurrentBucketNumber++;
195
196   if (myNumberOfBucket > myNumberOfBucketAllocated) {
197     Standard_Size e = sizeof(Storage_Bucket*) * myNumberOfBucketAllocated;
198     myBuckets =  (Storage_Bucket**)Standard::Reallocate((Standard_Address&)myBuckets, e * 2);
199     myNumberOfBucketAllocated *= 2;
200   }
201
202   myBuckets[myCurrentBucketNumber] = new Storage_Bucket(myBucketSize);
203   myCurrentBucket = myBuckets[myCurrentBucketNumber];
204   myCurrentBucket->myCurrentSpace++;
205   myLength++;
206   myCurrentBucket->mySpace[myCurrentBucket->myCurrentSpace] = sp.operator->();
207 }
208
209 //=======================================================================
210 //function : Storage_BucketIterator
211 //purpose  : 
212 //=======================================================================
213
214 Storage_BucketIterator::Storage_BucketIterator
215                          (Storage_BucketOfPersistent* aBucketManager)
216 {
217   if (aBucketManager) {
218     myBucket             = aBucketManager;
219     myCurrentBucket      = myBucket->myBuckets[0];
220     myBucketNumber       = aBucketManager->myNumberOfBucket;
221     myCurrentBucketIndex = 0;
222     myCurrentIndex       = 0;
223     myMoreObject         = Standard_True;
224   }
225   else myMoreObject         = Standard_False;
226 }
227
228 //=======================================================================
229 //function : Reset
230 //purpose  : 
231 //=======================================================================
232
233 void Storage_BucketIterator::Reset()
234 {
235   if (myBucket) {
236     myCurrentBucket = myBucket->myBuckets[0];
237     myBucketNumber  = myBucket->myNumberOfBucket;
238     myCurrentIndex  = 0;
239     myCurrentBucketIndex = 0;
240     myMoreObject = Standard_True;
241   }
242   else myMoreObject         = Standard_False;
243 }
244
245 //=======================================================================
246 //function : Init
247 //purpose  : 
248 //=======================================================================
249
250 void Storage_BucketIterator::Init(Storage_BucketOfPersistent* aBucketManager)
251 {
252   if (aBucketManager) {
253     myBucket        = aBucketManager;
254     myCurrentBucket = myBucket->myBuckets[0];
255     myBucketNumber  = aBucketManager->myNumberOfBucket;
256     myCurrentIndex  = 0;
257     myCurrentBucketIndex = 0;
258     myMoreObject = Standard_True;
259   }
260   else myMoreObject         = Standard_False;
261 }
262
263 //=======================================================================
264 //function : Next
265 //purpose  : 
266 //=======================================================================
267
268 void Storage_BucketIterator::Next()
269 {
270   if (!myMoreObject) return;
271
272   if (myCurrentIndex < myCurrentBucket->myCurrentSpace) {
273     myCurrentIndex++;
274   }
275   else {
276     myCurrentIndex = 0;
277     myCurrentBucketIndex++;
278     if (myCurrentBucketIndex < myBucketNumber) {
279       myCurrentBucket = myBucket->myBuckets[myCurrentBucketIndex];
280     }
281     else {
282       myMoreObject = Standard_False;
283     }
284   }
285 }
286
287 //=======================================================================
288 //function : Storage_Schema
289 //purpose  : USER API -- --------------------------------------------------------------
290 //           IMPLEMENTATION BucketOfPersistent
291 //=======================================================================
292
293 Storage_Schema::Storage_Schema()
294 {
295   Clear();
296   ResetDefaultCallBack();
297   myCallBackState = Standard_False;
298   myNestedState = Standard_False;
299 }
300
301 //=======================================================================
302 //function : SetVersion
303 //purpose  : returns version of the schema
304 //=======================================================================
305
306 void Storage_Schema::SetVersion(const TCollection_AsciiString& aVersion)
307 {
308   myVersion = aVersion;
309 }
310
311 //=======================================================================
312 //function : Version
313 //purpose  : returns the version of the schema
314 //=======================================================================
315
316 TCollection_AsciiString Storage_Schema::Version() const
317 {
318   return myVersion;
319 }
320
321 //=======================================================================
322 //function : SetName
323 //purpose  : set the schema's name
324 //=======================================================================
325
326 void Storage_Schema::SetName(const TCollection_AsciiString& aSchemaName)
327 {
328   myName = aSchemaName;
329 }
330
331 //=======================================================================
332 //function : Name
333 //purpose  : returns the schema's name
334 //=======================================================================
335
336 TCollection_AsciiString Storage_Schema::Name() const
337 {
338   return myName;
339 }
340
341 //=======================================================================
342 //function : Write
343 //purpose  : write 
344 //Arguments:
345 //           s: driver to write
346 //           raises  if  the  stream  is  not  opened  in  VSWrite  or
347 //           VSReadWrite
348 //=======================================================================
349
350 void Storage_Schema::Write
351                          (Storage_BaseDriver& f,
352                           const Handle(Storage_Data)& aData) const
353 {
354  if (aData.IsNull()) return;
355
356   // add all the persistent to write...
357   //
358   Standard_Integer                 posfrom,posto;
359   Handle(Standard_Persistent)      p;
360   Handle(Storage_HSeqOfRoot)       plist;
361   TCollection_AsciiString          errorContext("AddPersistent");
362   Storage_Schema::ISetCurrentData(aData);
363
364   Handle(Storage_InternalData) iData = aData->InternalData();
365
366   aData->Clear();
367   aData->ClearErrorStatus();
368
369   plist = aData->Roots();
370
371   for (posto = 1; posto <= plist->Length(); posto++) {
372     PersistentToAdd(plist->Value(posto)->Object());
373   }
374
375   for (posto = 1; posto <= plist->Length(); posto++) {
376     AddTypeSelection(plist->Value(posto)->Object());
377   }
378
379   for (posfrom = plist->Length() + 1; posfrom <= iData->myPtoA.Length(); posfrom++) {
380     AddTypeSelection(iData->myPtoA.Value(posfrom));
381   }
382
383   // ...and now we write
384   //
385   Standard_Integer            i,
386                               len;
387
388  aData->HeaderData()->SetCreationDate(ICreationDate());
389  aData->HeaderData()->SetStorageVersion(Storage::Version());
390  aData->HeaderData()->SetNumberOfObjects(iData->myPtoA.Length());
391  aData->HeaderData()->SetSchemaName(myName);
392  aData->HeaderData()->SetSchemaVersion(myVersion);
393
394   if ((f.OpenMode() == Storage_VSWrite) || (f.OpenMode() == Storage_VSReadWrite)) {
395     try {
396       OCC_CATCH_SIGNALS
397       errorContext = "BeginWriteInfoSection";
398       f.BeginWriteInfoSection();
399       errorContext = "WriteInfo";
400       f.WriteInfo(aData->NumberOfObjects(),
401                   aData->StorageVersion(),
402                   aData->CreationDate(),
403                   aData->SchemaName(),
404                   aData->SchemaVersion(),
405                   aData->ApplicationName(),
406                   aData->ApplicationVersion(),
407                   aData->DataType(),
408                   aData->UserInfo());
409       errorContext = "EndWriteInfoSection";
410       f.EndWriteInfoSection();
411
412       errorContext = "BeginWriteCommentSection";
413       f.BeginWriteCommentSection();
414       errorContext = "WriteComment";
415       f.WriteComment(aData->Comments());
416       errorContext = "EndWriteCommentSection";
417       f.EndWriteCommentSection();
418
419       Handle(TColStd_HSequenceOfAsciiString) tlist;
420
421       tlist = aData->Types();
422
423       errorContext = "BeginWriteTypeSection";
424       f.BeginWriteTypeSection();
425       len = aData->NumberOfTypes();
426
427       Handle(Storage_HArrayOfCallBack) WFunc = new Storage_HArrayOfCallBack(1,len);
428
429       f.SetTypeSectionSize(len);
430
431       Storage_DataMapIteratorOfMapOfCallBack cbit(iData->myTypeBinding);
432       Handle(Storage_TypedCallBack) atcallBack;
433
434       for (; cbit.More(); cbit.Next()) {
435         atcallBack = cbit.Value();
436         WFunc->SetValue(atcallBack->Index(),atcallBack->CallBack());
437       }
438
439       errorContext = "WriteTypeInformations";
440       for (i = 1; i <= len; i++) {
441         f.WriteTypeInformations(i,tlist->Value(i).ToCString());
442       }
443
444       errorContext = "EndWriteTypeSection";
445       f.EndWriteTypeSection();
446
447       errorContext = "BeginWriteRootSection";
448       f.BeginWriteRootSection();
449       f.SetRootSectionSize(plist->Length());
450
451       errorContext = "WriteRoot";
452       for (i = 1; i <= plist->Length(); i++) {
453         f.WriteRoot(plist->Value(i)->Name(),i,plist->Value(i)->Type());
454       }
455
456       errorContext = "EndWriteRootSection";
457       f.EndWriteRootSection();
458
459       errorContext = "BeginWriteRefSection";
460       f.BeginWriteRefSection();
461       f.SetRefSectionSize(iData->myObjId - 1);
462       errorContext = "WriteReferenceType";
463
464       Storage_BucketIterator bit(&iData->myPtoA);
465
466       while(bit.More()) {
467         p = bit.Value();
468         if (!p.IsNull()) f.WriteReferenceType(p->_refnum,p->_typenum);
469         bit.Next();
470       }
471
472       errorContext = "EndWriteRefSection";
473       f.EndWriteRefSection();
474
475       errorContext = "BeginWriteDataSection";
476       f.BeginWriteDataSection();
477
478       Handle(Storage_Schema) me = this;
479
480       errorContext = "Write";
481
482       bit.Reset();
483
484       while(bit.More()) {
485         p = bit.Value();
486         if (!p.IsNull()) {
487           WFunc->Value(p->_typenum)->Write(p,f,me);
488           p->_typenum = 0;
489         }
490         bit.Next();
491       }
492
493       errorContext = "EndWriteDataSection";
494       f.EndWriteDataSection();
495     }
496     catch(Storage_StreamWriteError) {
497       aData->SetErrorStatus(Storage_VSWriteError);
498       aData->SetErrorStatusExtension(errorContext);
499     }
500   }
501   else {
502     aData->SetErrorStatus(Storage_VSModeError);
503     aData->SetErrorStatusExtension("OpenMode");
504   }
505
506   iData->Clear();
507   Clear();
508 }
509
510 //=======================================================================
511 //function : Read
512 //purpose  : ...and read a Storage file
513 //Arguments:
514 //           s: driver to read
515 //=======================================================================
516
517 Handle(Storage_Data) Storage_Schema::Read(Storage_BaseDriver& f) const
518 {
519   Handle(Storage_Data)          dData = new Storage_Data;
520   Storage_Error                errorCode;
521 static Standard_Boolean             result;
522 static Standard_Integer             len;
523 static Standard_Integer             i;
524   i = 0 ;
525   Handle(Standard_Persistent)  per;
526   Handle(Storage_HArrayOfCallBack) theCallBack;
527
528   Handle(Storage_InternalData) iData = dData->InternalData();
529   Handle(Storage_TypeData)     tData = dData->TypeData();
530   Handle(Storage_RootData)     rData = dData->RootData();
531   Handle(Storage_HeaderData)   hData = dData->HeaderData();
532
533   if ((f.OpenMode() == Storage_VSRead) || (f.OpenMode() == Storage_VSReadWrite)) {
534
535     Storage_Schema::ISetCurrentData(dData);
536
537     // IReadHeaderSection can set an error status
538     //
539     result = IReadHeaderSection(f,hData);
540
541     if (result) {
542       Handle(Storage_CallBack) accallBack;
543       Standard_Integer            p;
544       TCollection_AsciiString     typeName;
545
546       iData->myReadArray = new Storage_HPArray(1,dData->NumberOfObjects());
547
548       // IReadTypeSection can set an error status
549       //
550       result = IReadTypeSection(f,tData);
551
552       if (result) {
553         len = dData->NumberOfTypes();
554         theCallBack = new Storage_HArrayOfCallBack(1,len);
555         {
556           try {
557             OCC_CATCH_SIGNALS
558             for (i = 1; i <= len; i++) {
559               typeName = tData->Type(i);
560               p = tData->Type(typeName);
561               theCallBack->SetValue(p,CallBackSelection(typeName));
562             }
563           }
564           catch(Storage_StreamUnknownTypeError) {
565             result = Standard_False;
566             dData->SetErrorStatus(Storage_VSUnknownType);
567             dData->SetErrorStatusExtension(typeName);
568           }
569         }
570       }
571       else {
572         dData->SetErrorStatus(tData->ErrorStatus());
573         dData->SetErrorStatusExtension(tData->ErrorStatusExtension());
574       }
575     }
576     else {
577       dData->SetErrorStatus(hData->ErrorStatus());
578       dData->SetErrorStatusExtension(hData->ErrorStatusExtension());
579     }
580
581     if (result) {
582       result = IReadRootSection(f,rData);
583       dData->SetErrorStatus(rData->ErrorStatus());
584       if (!result) dData->SetErrorStatusExtension(rData->ErrorStatusExtension());
585     }
586
587     if (result) {
588       Standard_Integer otype,oref;
589
590       errorCode = f.BeginReadRefSection();
591
592       if (errorCode == Storage_VSOk) {
593         {
594           try {
595             OCC_CATCH_SIGNALS
596             len = f.RefSectionSize();
597
598             for (i = 1; i <= len; i++) {
599               f.ReadReferenceType(oref,otype);
600               iData->myReadArray->ChangeValue(oref) = theCallBack->Value(otype)->New();
601               if (!iData->myReadArray->ChangeValue(oref).IsNull()) iData->myReadArray->ChangeValue(oref)->_typenum = otype;
602             }
603           }
604           catch(Storage_StreamTypeMismatchError) {
605             TCollection_AsciiString aOref = oref;
606             result = Standard_False;
607             dData->SetErrorStatus(Storage_VSTypeMismatch);
608             dData->SetErrorStatusExtension(aOref);
609           }
610         }
611
612         if (result) {
613           errorCode = f.EndReadRefSection();
614           result = (errorCode == Storage_VSOk);
615           dData->SetErrorStatus(errorCode);
616           if (!result) dData->SetErrorStatusExtension("EndReadRefSection");
617         }
618       }
619       else {
620         result = Standard_False;
621         dData->SetErrorStatus(errorCode);
622         dData->SetErrorStatusExtension("BeginReadRefSection");
623       }
624     }
625
626     if (result) {
627       errorCode = f.BeginReadDataSection();
628       result = (errorCode == Storage_VSOk);
629       dData->SetErrorStatus(errorCode);
630       if (!result) dData->SetErrorStatusExtension("BeginReadDataSection");
631     }
632
633     if (result) {
634       Handle(Storage_Schema) me = this;
635       Handle(Storage_CallBack) rcback;
636
637       {
638         try {
639           OCC_CATCH_SIGNALS
640           for (i = 1; i <= dData->NumberOfObjects(); i++) {
641             Handle(Standard_Persistent) pobj = iData->myReadArray->Value(i);
642             if (!pobj.IsNull()) {
643               rcback = theCallBack->Value(pobj->_typenum);
644               rcback->Read(pobj,f,me);
645               pobj->_typenum = 0;
646             }
647           }
648         }
649         catch(Storage_StreamTypeMismatchError) {
650           result = Standard_False;
651           dData->SetErrorStatus(Storage_VSTypeMismatch);
652           dData->SetErrorStatusExtension(i-1);
653         }
654         catch(Storage_StreamFormatError) {
655           result = Standard_False;
656           dData->SetErrorStatus(Storage_VSFormatError);
657           dData->SetErrorStatusExtension(i-1);
658         }
659         catch(Storage_StreamReadError) {
660           result = Standard_False;
661           dData->SetErrorStatus(Storage_VSFormatError);
662           dData->SetErrorStatusExtension(i-1);
663         }
664       }
665
666       if (result) {
667         Handle(Storage_HSeqOfRoot) rlist = rData->Roots();
668         Handle(Storage_Root)       rroot;
669
670         for(i = 1; i <= dData->NumberOfRoots(); i++) {
671           rroot = rlist->Value(i);
672           rData->UpdateRoot(rroot->Name(),iData->myReadArray->Value(rroot->Reference()));
673         }
674
675         errorCode = f.EndReadDataSection();
676         result = (errorCode == Storage_VSOk);
677         dData->SetErrorStatus(errorCode);
678         if (!result) dData->SetErrorStatusExtension("EndReadDataSection");
679       }
680     }
681   }
682   else {
683     dData->SetErrorStatus(Storage_VSModeError);
684     dData->SetErrorStatusExtension("OpenMode");
685   }
686
687   iData->Clear();
688   Clear();
689
690   return dData;
691 }
692
693 //=======================================================================
694 //function : ReadHeaderSection
695 //purpose  : read the header part of the stream
696 //Arguments:
697 //           s: driver to read
698 //=======================================================================
699
700 Handle(Storage_HeaderData) Storage_Schema::ReadHeaderSection
701                          (Storage_BaseDriver& s) const
702 {
703   Handle(Storage_HeaderData) result = new Storage_HeaderData;
704
705   if ((s.OpenMode() == Storage_VSRead) || (s.OpenMode() == Storage_VSReadWrite)) {
706     IReadHeaderSection(s,result);
707   }
708   else {
709     result->SetErrorStatus(Storage_VSModeError);
710     result->SetErrorStatusExtension("OpenMode");
711   }
712
713   return result;
714 }
715
716 //=======================================================================
717 //function : ReadTypeSection
718 //purpose  : fill the TypeData with the  names of the type used
719 //           in a stream
720 //Arguments:
721 //           s: driver to read
722 //=======================================================================
723
724 Handle(Storage_TypeData) Storage_Schema::ReadTypeSection
725                          (Storage_BaseDriver& f) const
726 {
727   Handle(Storage_TypeData) result = new Storage_TypeData;
728
729   if ((f.OpenMode() == Storage_VSRead) || (f.OpenMode() == Storage_VSReadWrite)) {
730     IReadTypeSection(f,result);
731   }
732   else {
733     result->SetErrorStatus(Storage_VSModeError);
734     result->SetErrorStatusExtension("OpenMode");
735   }
736
737   return result;
738 }
739
740 //=======================================================================
741 //function : ReadRootSection
742 //purpose  : read root part of the file
743 //Arguments:
744 //           s: driver to read
745 //=======================================================================
746
747 Handle(Storage_RootData) Storage_Schema::ReadRootSection
748                          (Storage_BaseDriver& f) const
749 {
750   Handle(Storage_RootData) result = new Storage_RootData;
751
752   if ((f.OpenMode() == Storage_VSRead) || (f.OpenMode() == Storage_VSReadWrite)) {
753     IReadRootSection(f,result);
754   }
755   else {
756     result->SetErrorStatus(Storage_VSModeError);
757     result->SetErrorStatusExtension("OpenMode");
758   }
759
760   return result;
761 }
762
763 //=======================================================================
764 //function : SchemaKnownTypes
765 //purpose  : returns the known types of a schema
766 //=======================================================================
767
768 const TColStd_SequenceOfAsciiString& Storage_Schema::SchemaKnownTypes() const
769 {
770   static TColStd_SequenceOfAsciiString aSeq;
771   return aSeq;
772 }
773
774 //=======================================================================
775 //function : GetAllSchemaKnownTypes
776 //purpose  : returns the all known types  of a schema and their
777 //           nested schemes.
778 //PTV      : add get of all known type for inheritance of schemas
779 //=======================================================================
780
781 Handle(TColStd_HSequenceOfAsciiString) Storage_Schema::
782                           GetAllSchemaKnownTypes() const
783 {
784   Handle(TColStd_HSequenceOfAsciiString) aSeqOfType = new TColStd_HSequenceOfAsciiString;
785   const TColStd_SequenceOfAsciiString& alocalTypeList = SchemaKnownTypes();
786
787   for (Standard_Integer k = 1; k <= alocalTypeList.Length(); k++)
788     aSeqOfType->Append(alocalTypeList.Value(k));
789
790   // get nested schemas
791   Handle(Storage_HArrayOfSchema) aNestedSchemas = NestedSchemas();
792   if (!aNestedSchemas.IsNull())
793   {
794     for (Standard_Integer i = aNestedSchemas->Lower(); i <= aNestedSchemas->Upper(); i++)
795     {
796       Handle(Storage_Schema) aSchema = aNestedSchemas->Value(i);
797       if (aSchema.IsNull())
798         continue;
799
800       Handle(TColStd_HSequenceOfAsciiString) typeList = aSchema->GetAllSchemaKnownTypes();
801       for (Standard_Integer j = 1; j <= typeList->Length(); j++)
802         aSeqOfType->Append(typeList->Value(j));
803     }
804   }
805
806   return aSeqOfType;
807 }
808
809 //=======================================================================
810 //function : HasUnknownType
811 //purpose  : indicates whether  the  are  types  in  the driver
812 //           which are not known from  the schema and for which
813 //           no callbacks have been set. The unknown types can
814 //           be read in <theUnknownTypes>.
815 //=======================================================================
816
817 Standard_Boolean Storage_Schema::HasUnknownType
818                          (Storage_BaseDriver& f,
819                           TColStd_SequenceOfAsciiString& theUnknownTypes) const
820 {
821   Standard_Boolean result = Standard_False;
822   Handle(TColStd_HSequenceOfAsciiString) typeList = GetAllSchemaKnownTypes();
823
824   Handle(Storage_TypeData) tData;
825
826   tData = ReadTypeSection(f);
827
828   result = (tData->ErrorStatus() != Storage_VSOk);
829
830   if (!result) {
831     Standard_Integer i;
832     TColStd_MapOfAsciiString names;
833
834     for (i = 1; i <= typeList->Length(); i++) {
835       names.Add(typeList->Value(i));
836     }
837
838     Handle(TColStd_HSequenceOfAsciiString) flist = tData->Types();
839
840     for (i = 1; i <= flist->Length(); i++) {
841       if (!names.Contains(flist->Value(i))) {
842         theUnknownTypes.Append(flist->Value(i));
843         result = Standard_True;
844       }
845     }
846   }
847
848   return result;
849 }
850
851 //=======================================================================
852 //function : SetNestedSchemas
853 //purpose  : 
854 //=======================================================================
855
856 void Storage_Schema::SetNestedSchemas
857                          (const Handle(Storage_HArrayOfSchema)& theSchemas)
858 {
859   myArrayOfSchema = theSchemas;
860 }
861
862 //=======================================================================
863 //function : ClearNestedSchemas
864 //purpose  : 
865 //=======================================================================
866
867 void Storage_Schema::ClearNestedSchemas()
868 {
869   myArrayOfSchema.Nullify();
870 }
871
872 //=======================================================================
873 //function : NestedSchemas
874 //purpose  : 
875 //=======================================================================
876
877 Handle(Storage_HArrayOfSchema) Storage_Schema::NestedSchemas() const
878 {
879   return myArrayOfSchema;
880 }
881
882 //=======================================================================
883 //function : AddReadUnknownTypeCallBack
884 //purpose  : add two functions to the callback list
885 //=======================================================================
886
887 void Storage_Schema::AddReadUnknownTypeCallBack
888                          (const TCollection_AsciiString& aTypeName,
889                           const Handle(Storage_CallBack)& aCallBack)
890 {
891   if (!aCallBack.IsNull()) {
892      Handle(Storage_TypedCallBack) aTCallBack = new Storage_TypedCallBack(aTypeName,aCallBack);
893
894      myCallBack.Bind(aTypeName,aTCallBack);
895   }
896 }
897
898 //=======================================================================
899 //function : RemoveReadUnknownTypeCallBack
900 //purpose  : remove a callback for a type
901 //=======================================================================
902
903 void Storage_Schema::RemoveReadUnknownTypeCallBack
904                          (const TCollection_AsciiString& aTypeName)
905 {
906   if (myCallBack.IsBound(aTypeName)) {
907     myCallBack.UnBind(aTypeName);
908   }
909 }
910
911 //=======================================================================
912 //function : InstalledCallBackList
913 //purpose  : returns  a  list  of   type  name  with  installed
914 //           callback.
915 //=======================================================================
916
917 Handle(TColStd_HSequenceOfAsciiString) Storage_Schema::
918                           InstalledCallBackList() const
919 {
920   Storage_DataMapIteratorOfMapOfCallBack it(myCallBack);
921   Handle(TColStd_HSequenceOfAsciiString) result = new TColStd_HSequenceOfAsciiString;
922
923   for (; it.More(); it.Next()) {
924     result->Append(it.Key());
925   }
926
927   return result;
928 }
929
930 //=======================================================================
931 //function : ClearCallBackList
932 //purpose  : clear all callback from schema instance.
933 //=======================================================================
934
935 void Storage_Schema::ClearCallBackList()
936 {
937   myCallBack.Clear();
938 }
939
940 //=======================================================================
941 //function : UseDefaultCallBack
942 //purpose  : install  a  callback  for  all  unknown  type. the
943 //           objects with unknown types  will be skipped. (look
944 //           SkipObject method in BaseDriver)
945 //=======================================================================
946
947 void Storage_Schema::UseDefaultCallBack()
948 {
949   myCallBackState = Standard_True;
950 }
951
952 //=======================================================================
953 //function : DontUseDefaultCallBack
954 //purpose  : tells schema to uninstall the default callback.
955 //=======================================================================
956
957 void Storage_Schema::DontUseDefaultCallBack()
958 {
959   myCallBackState = Standard_False;
960 }
961
962 //=======================================================================
963 //function : IsUsingDefaultCallBack
964 //purpose  : ask if the schema is using the default callback.
965 //=======================================================================
966
967 Standard_Boolean Storage_Schema::IsUsingDefaultCallBack() const
968 {
969   return myCallBackState;
970 }
971
972 //=======================================================================
973 //function : SetDefaultCallBack
974 //purpose  : overload the  default  function  for build.(use to
975 //           set an  error  message  or  skip  an  object while
976 //           reading an unknown type).
977 //=======================================================================
978
979 void Storage_Schema::SetDefaultCallBack(const Handle(Storage_CallBack)& f)
980 {
981   myDefaultCallBack = f;
982 }
983
984 //=======================================================================
985 //function : ResetDefaultCallBack
986 //purpose  : reset  the  default  function  defined  by Storage
987 //           package.
988 //=======================================================================
989
990 void Storage_Schema::ResetDefaultCallBack()
991 {
992   myDefaultCallBack = new Storage_DefaultCallBack;
993 }
994
995 //=======================================================================
996 //function : DefaultCallBack
997 //purpose  : returns   the   read   function   used   when  the
998 //           UseDefaultCallBack() is set.
999 //=======================================================================
1000
1001 Handle(Storage_CallBack) Storage_Schema::DefaultCallBack() const
1002 {
1003   return myDefaultCallBack;
1004 }
1005
1006 //=======================================================================
1007 //function : ResolveUnknownType
1008 //purpose  : 
1009 //=======================================================================
1010
1011 Handle(Storage_CallBack) Storage_Schema::ResolveUnknownType
1012                          (const TCollection_AsciiString&     aTypeName,
1013                           const Handle(Standard_Persistent)& p,
1014                           const Storage_SolveMode            aMode) const
1015 {
1016   Handle(Storage_CallBack) theCallBack;
1017
1018   if (!myArrayOfSchema.IsNull()) {
1019     Standard_Integer i;
1020     Standard_Boolean IsNotFound     = Standard_True;
1021     Standard_Boolean AlreadyMatched;
1022
1023     for(i = myArrayOfSchema->Lower(); i <= myArrayOfSchema->Upper() && IsNotFound; i++) {
1024       Handle(Storage_Schema) aSchema = myArrayOfSchema->Value(i);
1025
1026       if (!aSchema.IsNull()) {
1027         AlreadyMatched = aSchema->SetNested();
1028         if (!AlreadyMatched) {
1029           if (aMode == Storage_WriteSolve || aMode == Storage_ReadSolve) {
1030             theCallBack = aSchema->CallBackSelection(aTypeName);
1031           }
1032           else if (aMode == Storage_AddSolve) {
1033             theCallBack = aSchema->AddTypeSelection(p);
1034           }
1035           aSchema->UnsetNested();
1036           IsNotFound = theCallBack.IsNull();
1037         }
1038       }
1039     }
1040   }
1041
1042   if (!myNestedState && theCallBack.IsNull()) {
1043     if (myCallBack.IsBound(aTypeName)) {
1044       theCallBack = myCallBack.Find(aTypeName)->CallBack();
1045     }
1046     else if (myCallBackState == Standard_True) {
1047       theCallBack = myDefaultCallBack;
1048     }
1049     else {
1050       Clear();
1051       Standard_SStream aMsg;
1052
1053       aMsg << "Unknown type " << aTypeName << " in schema ";
1054
1055       if (!myName.IsEmpty()) {
1056         aMsg << myName;
1057       }
1058
1059       Storage_StreamUnknownTypeError::Raise(aMsg);
1060     }
1061   }
1062
1063   return theCallBack;
1064 }
1065
1066 //=======================================================================
1067 //function : CallBackSelection
1068 //purpose  : 
1069 //=======================================================================
1070
1071 Handle(Storage_CallBack) Storage_Schema::CallBackSelection
1072                          (const TCollection_AsciiString&) const
1073 {
1074   Handle(Storage_CallBack) theCallBack;
1075
1076   return theCallBack;
1077 }
1078
1079 //=======================================================================
1080 //function : AddTypeSelection
1081 //purpose  : 
1082 //=======================================================================
1083
1084 Handle(Storage_CallBack)  Storage_Schema::AddTypeSelection
1085                          (const Handle(Standard_Persistent)&) const
1086 {
1087   Handle(Storage_CallBack) theCallBack;
1088
1089   return theCallBack;
1090 }
1091
1092 //=======================================================================
1093 //function : BindType
1094 //purpose  : 
1095 //=======================================================================
1096
1097 void Storage_Schema::BindType
1098                          (const TCollection_AsciiString& aTypeName,
1099                           const Handle(Storage_CallBack)& aCallBack) const
1100 {
1101   if (!HasTypeBinding(aTypeName)) {
1102       Handle(Storage_InternalData) iData = Storage_Schema::ICurrentData()->InternalData();
1103       Handle(Storage_TypeData) tData = Storage_Schema::ICurrentData()->TypeData();
1104       Handle(Storage_TypedCallBack) c = new Storage_TypedCallBack(aTypeName,aCallBack);
1105
1106       tData->AddType(aTypeName,iData->myTypeId);
1107       c->SetIndex(iData->myTypeId++);
1108       iData->myTypeBinding.Bind(aTypeName,c);
1109   }
1110 }
1111
1112 //=======================================================================
1113 //function : TypeBinding
1114 //purpose  : 
1115 //=======================================================================
1116
1117 Handle(Storage_CallBack) Storage_Schema::TypeBinding
1118                          (const TCollection_AsciiString& aTypeName) const
1119 {
1120   Handle(Storage_CallBack) result;
1121
1122   if (HasTypeBinding(aTypeName)) {
1123     Handle(Storage_InternalData) iData = Storage_Schema::ICurrentData()->InternalData();
1124
1125     result =  iData->myTypeBinding.Find(aTypeName)->CallBack();
1126   }
1127
1128   return result;
1129 }
1130
1131 //=======================================================================
1132 //function : ReadPersistentReference
1133 //purpose  : 
1134 //=======================================================================
1135
1136 void Storage_Schema::ReadPersistentReference
1137                          (Handle(Standard_Persistent)& sp,
1138                           Storage_BaseDriver&          f)
1139 {
1140   Standard_Integer ref;
1141
1142   f.GetReference(ref);
1143
1144   if (ref != 0) {
1145     Handle(Storage_InternalData) iData = Storage_Schema::ICurrentData()->InternalData();
1146
1147     sp = iData->myReadArray->Value(ref);
1148   }
1149   else {
1150     sp.Nullify();
1151   }
1152 }
1153
1154 //=======================================================================
1155 //function : AddPersistent
1156 //purpose  : 
1157 //=======================================================================
1158
1159 Standard_Boolean Storage_Schema::AddPersistent
1160                          (const Handle(Standard_Persistent)& sp,
1161                           const Standard_CString tName) const
1162 {
1163   Standard_Boolean result = Standard_False;
1164
1165   if (!sp.IsNull()) {
1166     Handle(Storage_InternalData)     iData = Storage_Schema::ICurrentData()->InternalData();
1167
1168     if (sp->_typenum == 0) {
1169       Standard_Integer         aTypenum;
1170       static TCollection_AsciiString  aTypeName;
1171       aTypeName = tName;
1172       Handle(Storage_TypeData) tData = Storage_Schema::ICurrentData()->TypeData();
1173
1174       aTypenum = iData->myTypeBinding.Find(aTypeName)->Index();
1175
1176       sp->_typenum = aTypenum;
1177       sp->_refnum = iData->myObjId++;
1178
1179       result = Standard_True;
1180     }
1181   }
1182
1183   return result;
1184 }
1185
1186 //=======================================================================
1187 //function : PersistentToAdd
1188 //purpose  : 
1189 //=======================================================================
1190
1191 Standard_Boolean Storage_Schema::PersistentToAdd
1192                          (const Handle(Standard_Persistent)& sp) const
1193 {
1194  Standard_Boolean result = Standard_False;
1195
1196   if (!sp.IsNull()) {
1197     Handle(Storage_InternalData) di = Storage_Schema::ICurrentData()->InternalData();
1198
1199     if (sp->_typenum == 0 && sp->_refnum != -1) {
1200       result = Standard_True;
1201       sp->_refnum = -1;
1202       di->myPtoA.Append(sp);
1203     }
1204   }
1205
1206   return result;
1207 }
1208
1209 //=======================================================================
1210 //function : Clear
1211 //purpose  : 
1212 //=======================================================================
1213
1214 void Storage_Schema::Clear() const
1215 {
1216   Storage_Schema::ICurrentData().Nullify();
1217 }
1218
1219 //=======================================================================
1220 //function : IReadHeaderSection
1221 //purpose  : 
1222 //=======================================================================
1223
1224 Standard_Boolean Storage_Schema::IReadHeaderSection
1225                          (Storage_BaseDriver& f,
1226                           const Handle(Storage_HeaderData)& iData) const
1227 {
1228   Standard_Boolean                 result = Standard_False;
1229   Storage_Error                    errorCode;
1230   TCollection_AsciiString          uinfo,mStorageVersion,mDate,mSchemaName,mSchemaVersion,mApplicationVersion;
1231   TCollection_ExtendedString       mApplicationName,mDataType;
1232   TColStd_SequenceOfAsciiString    mUserInfo;
1233   TColStd_SequenceOfExtendedString mComment;
1234   Standard_Integer                 mNBObj;
1235
1236   errorCode = f.BeginReadInfoSection();
1237
1238   if (errorCode == Storage_VSOk) {
1239     {
1240       try {
1241         OCC_CATCH_SIGNALS
1242         f.ReadInfo(mNBObj,
1243                    mStorageVersion,
1244                    mDate,
1245                    mSchemaName,
1246                    mSchemaVersion,
1247                    mApplicationName,
1248                    mApplicationVersion,
1249                    mDataType,
1250                    mUserInfo);
1251       }
1252       catch(Storage_StreamTypeMismatchError) {
1253         iData->SetErrorStatus(Storage_VSTypeMismatch);
1254         iData->SetErrorStatusExtension("ReadInfo");
1255         return Standard_False;
1256       }
1257       catch(Storage_StreamExtCharParityError) {
1258         iData->SetErrorStatus(Storage_VSExtCharParityError);
1259         iData->SetErrorStatusExtension("ReadInfo");
1260         return Standard_False;
1261       }
1262     }
1263
1264
1265     errorCode = f.EndReadInfoSection();
1266
1267     iData->SetErrorStatus(errorCode);
1268
1269     result = (errorCode == Storage_VSOk);
1270
1271     if (result) {
1272       Standard_Integer i;
1273
1274       iData->SetNumberOfObjects(mNBObj);
1275       iData->SetStorageVersion(mStorageVersion);
1276       iData->SetCreationDate(mDate);
1277       iData->SetSchemaName(mSchemaName);
1278       iData->SetSchemaVersion(mSchemaVersion);
1279       iData->SetApplicationName(mApplicationName);
1280       iData->SetApplicationVersion(mApplicationVersion);
1281       iData->SetDataType(mDataType);
1282
1283       for (i = 1; i <= mUserInfo.Length(); i++) {
1284         iData->AddToUserInfo(mUserInfo.Value(i));
1285       }
1286
1287       errorCode = f.BeginReadCommentSection();
1288
1289       if (errorCode == Storage_VSOk) {
1290         {
1291           {
1292             try {
1293               OCC_CATCH_SIGNALS
1294               f.ReadComment(mComment);
1295             }
1296             catch(Storage_StreamTypeMismatchError) {
1297               iData->SetErrorStatus(Storage_VSTypeMismatch);
1298               iData->SetErrorStatusExtension("ReadComment");
1299               return Standard_False;
1300             }
1301             catch(Storage_StreamExtCharParityError) {
1302               iData->SetErrorStatus(Storage_VSExtCharParityError);
1303               iData->SetErrorStatusExtension("ReadComment");
1304               return Standard_False;
1305             }
1306           }
1307         }
1308
1309         errorCode = f.EndReadCommentSection();
1310         iData->SetErrorStatus(errorCode);
1311         iData->SetErrorStatusExtension("EndReadCommentSection");
1312         result = (errorCode == Storage_VSOk);
1313
1314         if (result) {
1315           for (i = 1; i <= mComment.Length(); i++) {
1316             iData->AddToComments(mComment.Value(i));
1317           }
1318         }
1319       }
1320       else {
1321         result = Standard_False;
1322         iData->SetErrorStatus(errorCode);
1323         iData->SetErrorStatusExtension("BeginReadCommentSection");
1324      }
1325     }
1326     else {
1327       iData->SetErrorStatusExtension("EndReadInfoSection");
1328     }
1329   }
1330   else {
1331     iData->SetErrorStatus(errorCode);
1332     iData->SetErrorStatusExtension("BeginReadInfoSection");
1333   }
1334
1335   return result;
1336 }
1337
1338
1339 #ifdef DATATYPE_MIGRATION
1340 //=======================================================================
1341 // environment variable CSF_MIGRATION_TYPES should define full path of a file
1342 // containing migration types table: oldtype - newtype
1343 //=======================================================================
1344 Standard_Boolean Storage_Schema::CheckTypeMigration(
1345                                   const TCollection_AsciiString&  oldName,
1346                                   TCollection_AsciiString&  newName)
1347 {
1348   static Standard_Boolean isChecked(Standard_False);
1349   static DataMapOfAStringAString aDMap;
1350   Standard_Boolean aMigration(Standard_False);
1351   
1352   if(!isChecked) {
1353     isChecked = Standard_True;
1354 //    TCollection_AsciiString aFileName = getenv("CSF_MIGRATION_TYPES");
1355     OSD_Environment csf(TCollection_AsciiString("CSF_MIGRATION_TYPES"));
1356     TCollection_AsciiString aFileName = csf.Value();
1357     if(aFileName.Length() > 0) {
1358       OSD_Path aPath(aFileName,OSD_Default);
1359       OSD_File aFile;
1360       aFile.SetPath(aPath);
1361       if(aFile.Exists()) {
1362         OSD_Protection aProt(OSD_R,OSD_R,OSD_R,OSD_R);
1363         aFile.Open(OSD_ReadOnly, aProt);
1364         if(aFile.IsOpen() && aFile.IsReadable()) {
1365           TCollection_AsciiString aLine;
1366           Standard_Integer aNbReaded(0);
1367           while (1) {
1368             aFile.ReadLine(aLine, 80, aNbReaded);
1369             if(aFile.IsAtEnd() || !aNbReaded) {
1370               aFile.Close();
1371               break;
1372             }
1373 #ifdef DATATYPE_MIGRATION_DEB
1374             cout << "Storage_Sheme:: Line: = " << aLine <<endl;
1375 #endif
1376             TCollection_AsciiString aKey, aValue;
1377             aKey = aLine.Token();
1378             aValue = aLine.Token(" \t\n\r", 2);
1379             aDMap.Bind(aKey, aValue);
1380           }
1381         }
1382       }
1383 #ifdef DATATYPE_MIGRATION_DEB
1384       cout << "Storage_Sheme:: aDataMap.Size = " << aDMap.Extent() <<endl;
1385 #endif
1386     }
1387   }
1388
1389   if(aDMap.Extent()) {
1390     if(aDMap.IsBound(oldName)) {
1391       newName.Clear();
1392       newName = aDMap.Find(oldName);
1393       aMigration = Standard_True;
1394 #ifdef DATATYPE_MIGRATION_DEB
1395       cout << " newName = " << newName << endl;
1396 #endif
1397     }
1398   } 
1399   return aMigration;
1400 }
1401 #endif
1402
1403 //=======================================================================
1404 //function : IReadTypeSection
1405 //purpose  : 
1406 //=======================================================================
1407
1408 Standard_Boolean Storage_Schema::IReadTypeSection
1409                          (Storage_BaseDriver& f,
1410                           const Handle(Storage_TypeData)& tData) const
1411 {
1412 static Standard_Boolean         result;
1413   TCollection_AsciiString  typeName;
1414   Standard_Integer         typeNum;
1415
1416   Storage_Error      errorCode;
1417   Standard_Integer len,i;
1418
1419   result = Standard_False;
1420   errorCode = f.BeginReadTypeSection();
1421
1422   if (errorCode == Storage_VSOk) {
1423     try {
1424       OCC_CATCH_SIGNALS
1425       len = f.TypeSectionSize();
1426
1427       for (i = 1; i <= len; i++) {
1428         f.ReadTypeInformations(typeNum,typeName);
1429 #ifdef DATATYPE_MIGRATION
1430         TCollection_AsciiString  newName;       
1431         if(CheckTypeMigration(typeName, newName)) {
1432 #ifdef DATATYPE_MIGRATION_DEB
1433           cout << "CheckTypeMigration:OldType = " <<typeName << " Len = "<<typeName.Length()<<endl;
1434           cout << "CheckTypeMigration:NewType = " <<newName  << " Len = "<< newName.Length()<<endl;
1435 #endif
1436           typeName = newName;
1437         }
1438 #endif
1439         tData->AddType(typeName,typeNum);
1440       }
1441       result = Standard_True;
1442     }
1443     catch(Storage_StreamTypeMismatchError) {
1444       tData->SetErrorStatus(Storage_VSTypeMismatch);
1445       tData->SetErrorStatusExtension("ReadTypeInformations");
1446       return Standard_False;
1447     }
1448
1449     if (result) {
1450       errorCode = f.EndReadTypeSection();
1451       result = (errorCode == Storage_VSOk);
1452
1453       tData->SetErrorStatus(errorCode);
1454       if (!result) tData->SetErrorStatusExtension("EndReadTypeSection");
1455     }
1456   }
1457   else {
1458     tData->SetErrorStatus(errorCode);
1459     tData->SetErrorStatusExtension("BeginReadTypeSection");
1460   }
1461
1462   return result;
1463 }
1464
1465 //=======================================================================
1466 //function : IReadRootSection
1467 //purpose  : 
1468 //=======================================================================
1469
1470 Standard_Boolean Storage_Schema::IReadRootSection
1471                          (Storage_BaseDriver& f,
1472                           const Handle(Storage_RootData)& rData) const
1473 {
1474 static Standard_Boolean            result;
1475   Standard_Integer            len,i,ref;
1476   Storage_Error               errorCode;
1477   Handle(Standard_Persistent) p;
1478   Handle(Storage_Root)        aRoot;
1479
1480   result = Standard_False;
1481   errorCode = f.BeginReadRootSection();
1482
1483   if (errorCode == Storage_VSOk) {
1484     TCollection_AsciiString rootName,typeName;
1485
1486     try {
1487       OCC_CATCH_SIGNALS
1488       len = f.RootSectionSize();
1489
1490       for (i = 1; i <= len; i++) {
1491         f.ReadRoot(rootName,ref,typeName);
1492         aRoot = new Storage_Root(rootName,p);
1493         aRoot->SetReference(ref);
1494         aRoot->SetType(typeName);
1495         rData->AddRoot(aRoot);
1496       }
1497       result = Standard_True;
1498     }
1499     catch(Storage_StreamTypeMismatchError) {
1500       result = Standard_False;
1501       rData->SetErrorStatus(Storage_VSTypeMismatch);
1502       rData->SetErrorStatusExtension("ReadRoot");
1503     }
1504
1505     if (result) {
1506       errorCode = f.EndReadRootSection();
1507       result = (errorCode == Storage_VSOk);
1508
1509       rData->SetErrorStatus(errorCode);
1510       if (!result) rData->SetErrorStatusExtension("EndReadRootSection");
1511     }
1512   }
1513   else {
1514     rData->SetErrorStatus(errorCode);
1515     rData->SetErrorStatusExtension("BeginReadRootSection");
1516   }
1517
1518   return result;
1519 }
1520
1521 //=======================================================================
1522 //function : ISetCurrentData
1523 //purpose  : 
1524 //=======================================================================
1525
1526 void Storage_Schema::ISetCurrentData(const Handle(Storage_Data)& dData)
1527 {
1528   Storage_Schema::ICurrentData() = dData;
1529 }
1530
1531 //=======================================================================
1532 //function : ICurrentData
1533 //purpose  : 
1534 //=======================================================================
1535
1536 Handle(Storage_Data)& Storage_Schema::ICurrentData()
1537 {
1538   static Handle(Storage_Data) _Storage_CData;
1539   return _Storage_CData;
1540 }
1541
1542 #define SLENGTH 80
1543
1544 //=======================================================================
1545 //function : ICreationDate
1546 //purpose  : 
1547 //=======================================================================
1548
1549 TCollection_AsciiString Storage_Schema::ICreationDate()
1550 {
1551   char nowstr[SLENGTH];
1552   time_t nowbin;
1553   struct tm *nowstruct;
1554   if (time(&nowbin) == (time_t)-1)
1555     cerr << "Storage ERROR : Could not get time of day from time()" << endl;
1556
1557   nowstruct = localtime(&nowbin);
1558
1559   if (strftime(nowstr, SLENGTH, "%m/%d/%Y", nowstruct) == (size_t) 0)
1560     cerr << "Storage ERROR : Could not get string from strftime()" << endl;
1561
1562   TCollection_AsciiString t(nowstr);
1563   return t;
1564 }
1565
1566 //=======================================================================
1567 //function : SetNested
1568 //purpose  : 
1569 //=======================================================================
1570
1571 Standard_Boolean Storage_Schema::SetNested()
1572 {
1573   Standard_Boolean result = myNestedState;
1574
1575   myNestedState = Standard_True;
1576
1577   return result;
1578 }
1579
1580 //=======================================================================
1581 //function : IsNested
1582 //purpose  : 
1583 //=======================================================================
1584
1585 Standard_Boolean Storage_Schema::IsNested() const
1586 {
1587   return myNestedState;
1588 }
1589
1590 //=======================================================================
1591 //function : UnsetNested
1592 //purpose  : 
1593 //=======================================================================
1594
1595 Standard_Boolean Storage_Schema::UnsetNested()
1596 {
1597   Standard_Boolean result = myNestedState;
1598
1599   myNestedState = Standard_False;
1600
1601   return result;
1602 }