0024927: Getting rid of "Persistent" functionality -- Code
[occt.git] / src / MDF / MDF_Tool.cxx
1 // Created by: DAUTRY Philippe
2 // Copyright (c) 1997-1999 Matra Datavision
3 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 //              --------------
17
18 // Version:     0.0
19 //Version       Date            Purpose
20 //              0.0     Mar 13 1997     Creation
21
22
23
24 #include <MDF_Tool.ixx>
25
26 #include <MDF_ARDriver.hxx>
27 #include <MDF_ASDriver.hxx>
28 #include <MDF_RRelocationTable.hxx>
29 #include <MDF_SRelocationTable.hxx>
30
31 #include <PDF_Attribute.hxx>
32 #include <PDF_HAttributeArray1.hxx>
33
34 #include <TDF_Attribute.hxx>
35 #include <TDF_AttributeIterator.hxx>
36 #include <TDF_ListIteratorOfAttributeList.hxx>
37 #include <TDF_AttributeList.hxx>
38 #include <TDF_ChildIterator.hxx>
39 #include <TDF_Label.hxx>
40 #include <TDF_Tool.hxx>
41
42 #include <TColStd_HArray1OfInteger.hxx>
43
44 #include <PTColStd_DataMapIteratorOfPersistentTransientMap.hxx>
45 #include <PTColStd_DataMapIteratorOfTransientPersistentMap.hxx>
46 #include <PTColStd_PersistentTransientMap.hxx>
47 #include <PTColStd_TransientPersistentMap.hxx>
48
49 #include <Standard_GUID.hxx>
50
51 #ifdef OCCT_DEBUG
52 #include <Standard_ConstructionError.hxx>
53 #endif
54
55 #define DeclareAndSpeedCast(V,T,Vdown) Handle(T) Vdown = *((Handle(T)*)& V)
56 #define DeclareConstAndSpeedCast(V,T,Vdown) const Handle(T)& Vdown = (Handle(T)&) V
57 #define SpeedCast(V,T,Vdown) Vdown = *((Handle(T)*)& V)
58
59 #include <NCollection_List.hxx>
60 typedef struct {
61         Handle(PDF_Attribute) pAtt;
62         Handle(TDF_Attribute) tAtt;
63 } ATTR;
64 typedef NCollection_List<ATTR> MDF_AttributeList;
65 typedef MDF_AttributeList::Iterator MDF_ListIteratorOfAttributeList;
66
67 #undef DEB_MDF_TOOL
68
69 // Persistent structure:
70 //
71 // Label Array Item
72 //
73 // (Tag; NbOfAttributes; NbOfChildren)
74 //
75 // The attributes are stored sequencially in the Attribute Array.
76 // The children of a label are stored recursively after the label item itself.
77
78
79 //      W       W  RRRRR   III  TTTTT  EEEEE
80 //      W       W  R    R   I     T    E
81 //       W     W   R    R   I     T    E
82 //       W  W  W   RRRRR    I     T    EEE
83 //        WW WW    R  R     I     T    E
84 //        W   W    R   R   III    T    EEEEE
85
86
87 //=======================================================================
88 //function : MDF_NbAttributesWithDriver
89 //purpose  : 
90 //=======================================================================
91
92 static Standard_Integer MDF_NbAttributesWithDriver
93 (const TDF_Label& aLabel,
94  const MDF_TypeASDriverMap& aDriverMap)
95 {
96   Standard_Integer n = 0;
97   for (TDF_AttributeIterator itr1(aLabel); itr1.More(); itr1.Next())
98     if (aDriverMap.IsBound(itr1.Value()->DynamicType())) ++n;
99   for (TDF_ChildIterator itr2(aLabel); itr2.More(); itr2.Next())
100     n += MDF_NbAttributesWithDriver(itr2.Value(),aDriverMap);
101   return n;
102 }
103
104
105 //=======================================================================
106 //function : WriteLabels
107 //purpose  : TRANSIENT -> PERSISTENT;
108 //           writes the arrays contents with empty attributes.
109 //=======================================================================
110
111 void MDF_Tool::WriteLabels
112 (const Handle(TDF_Data)& aSource,
113  const Handle(PDF_Data)& aTarget,
114  const MDF_TypeASDriverMap& aDriverMap,
115  const Handle(MDF_SRelocationTable)& aReloc)
116 {
117   TDF_Label aSourceLab = aSource->Root();
118
119   // Label array sizing.
120   Handle(PColStd_HArray1OfInteger) theLabels;
121   Standard_Integer nbLab = TDF_Tool::NbLabels(aSourceLab);
122   if (nbLab) {
123     theLabels = new PColStd_HArray1OfInteger(1,nbLab*3);
124     aTarget->Labels(theLabels);
125   }
126   // In fact, some labels whithout attributes attached to themselves
127   // nor to their descendants will not be kept.
128
129   // Attribute array sizing.
130   Handle(PDF_HAttributeArray1) theAttributes;
131   Standard_Integer nbAtt = 0;
132   if (nbLab) {
133     nbAtt = MDF_NbAttributesWithDriver(aSourceLab,aDriverMap);
134     if (nbAtt) {
135       theAttributes = new PDF_HAttributeArray1(1,nbAtt);
136       aTarget->Attributes(theAttributes);
137     }
138     // In fact, some attributes will not be kept by the filter.
139   }
140
141   if (nbLab && nbAtt) {
142     // labAlloc & attAlloc content the last used cell address.
143     Standard_Integer labAlloc = 0;
144     Standard_Integer attAlloc = 0;
145     MDF_Tool::WriteLabels(aSourceLab, aTarget->Labels(), aTarget->Attributes(),
146                           aDriverMap, aReloc, labAlloc, attAlloc);
147
148     // Label array REsizing.
149     if (labAlloc < theLabels->Upper()) {
150 #ifdef OCCT_DEBUG
151       cout<<"MDF_Tool::WriteLabels LABEL array resizing from "<<theLabels->Upper()<<" to "<<labAlloc<<endl;
152 #endif
153       Handle(PColStd_HArray1OfInteger) newLabels =
154         new PColStd_HArray1OfInteger(1,labAlloc);
155       for (Standard_Integer i = 1; i <= labAlloc; ++i)
156         newLabels->SetValue(i,theLabels->Value(i));
157       aTarget->Labels(newLabels);
158     }
159
160
161     // Attribute array REsizing.
162     if (attAlloc < theAttributes->Upper()) {
163 #ifdef OCCT_DEBUG
164       cout<<"MDF_Tool::WriteLabels ATTRIBUTES array resizing from "<<theAttributes->Upper()<<" to "<<attAlloc<<endl;
165 #endif
166       Handle(PDF_HAttributeArray1) newAttributes =
167         new PDF_HAttributeArray1(1,attAlloc);
168       for (Standard_Integer i = 1; i <= attAlloc; ++i)
169         newAttributes->SetValue(i,theAttributes->Value(i));
170       aTarget->Attributes(newAttributes);
171     }
172   }
173 }
174
175
176 //=======================================================================
177 //function : WriteLabels
178 //purpose  : TRANSIENT -> PERSISTENT;
179 //           writes the arrays contents with empty attributes.
180 //=======================================================================
181
182 void MDF_Tool::WriteLabels
183 (const TDF_Label& aSourceLab,
184  const Handle(PColStd_HArray1OfInteger)& theLabels,
185  const Handle(PDF_HAttributeArray1)& theAttributes,
186  const MDF_TypeASDriverMap& aDriverMap,
187  const Handle(MDF_SRelocationTable)& aReloc,
188  Standard_Integer& labAlloc,
189  Standard_Integer& attAlloc)
190 {
191   // Cells allocation.
192   Standard_Integer labIndex = labAlloc;
193   labAlloc += 3;
194   Standard_Integer attIndex = attAlloc; // Backup the value.
195
196   // Tag.
197   theLabels->SetValue(++labIndex,aSourceLab.Tag());
198
199   Standard_Integer count = 0;
200
201   // Attributes.
202   Handle(PDF_Attribute) pAtt;
203   TDF_AttributeIterator itr1(aSourceLab);
204   for ( ; itr1.More(); itr1.Next()) {
205     const Handle(TDF_Attribute)& tAtt = itr1.Value();
206     const Handle(Standard_Type)& type = tAtt->DynamicType();
207     if (aDriverMap.IsBound(type)) {
208       ++count;
209       const Handle(MDF_ASDriver)& driver = aDriverMap.Find(type);
210       pAtt = driver->NewEmpty();
211       theAttributes->SetValue(++attAlloc,pAtt);
212       aReloc->SetRelocation(tAtt,pAtt);
213     }
214   }
215   theLabels->SetValue(++labIndex,count); // Nb Attributes.
216   count = 0;
217
218   // Label Children.
219   Standard_Integer childLabIndex;
220   TDF_ChildIterator itr2(aSourceLab);
221   for ( ; itr2.More(); itr2.Next()) {
222     childLabIndex = labAlloc;
223     const TDF_Label& label = itr2.Value();
224     MDF_Tool::WriteLabels(label, theLabels, theAttributes,
225                           aDriverMap, aReloc, labAlloc, attAlloc);
226     if (childLabIndex < labAlloc) ++count;
227   }
228
229 #ifdef OCCT_DEBUG_MDF_TOOL
230   aSourceLab.EntryDump(cout);
231   cout<<" Count="<<count<<" attIndex="<<attIndex<<" attAlloc="<<attAlloc;
232 #endif
233   if (attIndex < attAlloc) { // At least one attribute has been stored.
234     theLabels->SetValue(++labIndex,count); // Nb Children.
235   }
236   else {
237     labAlloc -= 2;
238     theLabels->SetValue(labAlloc--,0); // To clean the tag value.
239 #ifdef OCCT_DEBUG_MDF_TOOL
240     cout<<"    <== Cleared";
241 #endif
242   }
243 #ifdef OCCT_DEBUG_MDF_TOOL
244   cout<<endl;
245 #endif
246 }
247
248
249 //=======================================================================
250 //function : WriteAttributes
251 //purpose  : TRANSIENT -> PERSISTENT
252 //           writes the persistent attributes content.
253 //=======================================================================
254
255 void MDF_Tool::WriteAttributes
256 (const MDF_TypeASDriverMap& aDriverMap,
257  const Handle(MDF_SRelocationTable)& aReloc) 
258 {
259   // Iterer sur la map pour traduire si target.IsNull().
260   const PTColStd_TransientPersistentMap& attMap = aReloc->AttributeTable();
261   PTColStd_DataMapIteratorOfTransientPersistentMap itr(attMap);
262   Handle(PDF_Attribute) pAtt;
263   for ( ; itr.More(); itr.Next()) {
264     DeclareConstAndSpeedCast(itr.Key(),TDF_Attribute,tAtt);
265     const Handle(Standard_Type)& type = tAtt->DynamicType();
266     if (aDriverMap.IsBound(type)) {
267       SpeedCast(itr.Value(),PDF_Attribute,pAtt);
268       const Handle(MDF_ASDriver)& driver = aDriverMap.Find(type);
269       driver->Paste(tAtt, pAtt, aReloc);
270     }
271   }
272 }
273
274
275
276 //      RRRRR   EEEEE    A    DDDD
277 //      R    R  E       A A   D   D
278 //      R    R  E      A   A  D   D
279 //      RRRRR   EEE    AAAAA  D   D
280 //      R  R    E      A   A  D   D
281 //      R   R   EEEEE  A   A  DDDD
282
283 //=======================================================================
284 //function : ReadLabels
285 //purpose  : PERSISTENT -> TRANSIENT;
286 //           reads the arrays contents and build the objects
287 //           with empty attributes.
288 //=======================================================================
289
290 void MDF_Tool::ReadLabels
291 (const Handle(PDF_Data)& aSource,
292  const Handle(TDF_Data)& aTarget,
293  const MDF_TypeARDriverMap& aDriverMap,
294  const Handle(MDF_RRelocationTable)& aReloc)
295 {
296   // Root label creation.
297   //TDF_Insertor ins(aTarget->Root());
298   TDF_Label ins = aTarget->Root();
299
300   // labAlloc & attAlloc content the last used cell address.
301   Standard_Integer labRead = 1; // Root already used above.
302   Standard_Integer attRead = 0;
303   MDF_Tool::ReadLabels(ins, aSource->Labels(), aSource->Attributes(),
304                        aDriverMap, aReloc, labRead, attRead);
305 }
306
307
308 //=======================================================================
309 //function : ReadLabels
310 //purpose  : PERSISTENT -> TRANSIENT;
311 //           Reads the arrays contents and build the objects
312 //           with empty attributes.
313 //=======================================================================
314
315 void MDF_Tool::ReadLabels
316 (TDF_Label& anIns,
317  const Handle(PColStd_HArray1OfInteger)& theLabels,
318  const Handle(PDF_HAttributeArray1)& theAttributes,
319  const MDF_TypeARDriverMap& aDriverMap,
320  const Handle(MDF_RRelocationTable)& aReloc,
321  Standard_Integer& labRead,
322  Standard_Integer& attRead)
323 {
324   // Empty attributes creation.
325   Handle(TDF_Attribute) tAtt;
326   // Number of attributes.
327   Standard_Integer nbAtt = theLabels->Value(++labRead);
328   for (Standard_Integer iAtt = 1 ; iAtt <= nbAtt; iAtt++) {
329     const Handle(PDF_Attribute)& pAtt = theAttributes->Value(++attRead);
330     if (pAtt.IsNull()) {
331       // This case occurs only if somebody modified manually the file.
332       tAtt.Nullify();
333     }
334     else {
335       const Standard_GUID anEmptyID;
336       Handle(MDF_RRelocationTable) anEmptyRelocaTable = new MDF_RRelocationTable(Standard_True);
337       const Handle(Standard_Type)& type = pAtt->DynamicType();
338       if (aDriverMap.IsBound(type)) {
339         const Handle(MDF_ARDriver)& driver = aDriverMap.Find(type);
340         tAtt = driver->NewEmpty();
341         if (tAtt->ID() == anEmptyID) driver->Paste(pAtt, tAtt, anEmptyRelocaTable);
342         anIns.AddAttribute(tAtt);
343       }
344       aReloc->SetRelocation(pAtt,tAtt);
345     }
346   }
347
348   // Label Children creation.
349   Standard_Integer tag;
350   // Number of labels.
351   Standard_Integer nbLab = theLabels->Value(++labRead);
352   for (Standard_Integer iLab = 1 ; iLab <= nbLab; iLab++) {
353     // Label creation.
354     tag = theLabels->Value(++labRead);
355
356
357     //TDF_Insertor ins(anIns,tag);
358     TDF_Label ins = anIns.FindChild(tag,Standard_True);
359
360     MDF_Tool::ReadLabels(ins, theLabels, theAttributes,
361                          aDriverMap, aReloc, labRead, attRead);
362   }
363 }
364
365
366 //=======================================================================
367 //function : ReadAttributes
368 //purpose  : PERSISTENT -> TRANSIENT
369 //           Reads the persistent attributes content.
370 //=======================================================================
371 //#define DEB_ORIENT
372 void MDF_Tool::ReadAttributes
373 (const MDF_TypeARDriverMap& aDriverMap,
374  const Handle(MDF_RRelocationTable)& aReloc) 
375 {
376 //  cout<<"MDF_Tool::ReadAttributes ..."<<endl;
377   // Iterer sur la map pour traduire si target.IsNull().
378   const PTColStd_PersistentTransientMap& attMap = aReloc->AttributeTable();
379   PTColStd_DataMapIteratorOfPersistentTransientMap itr(attMap);
380   Handle(TDF_Attribute) tAtt;
381   MDF_AttributeList attNList;
382   Standard_Boolean isName1(Standard_False);
383   ATTR pairAtt;
384   for ( ; itr.More(); itr.Next()) {
385     DeclareConstAndSpeedCast(itr.Key(),PDF_Attribute,pAtt);
386     if (!pAtt.IsNull()) { // See above...
387       const Handle(Standard_Type)& type = pAtt->DynamicType();
388           
389           if(!strcmp (type->Name(), "PNaming_Naming_1") ) {
390 #ifdef OCCT_DEBUG_ORIENT
391                   cout << "TYPE = " << type->Name() << endl;
392 #endif
393                   isName1 = Standard_True;
394           } else isName1 = Standard_False;
395
396       if (aDriverMap.IsBound(type)) {
397             SpeedCast(itr.Value(),TDF_Attribute,tAtt);
398             const Handle(MDF_ARDriver)& driver = aDriverMap.Find(type);
399                 if(isName1) {
400                   pairAtt.pAtt = pAtt;
401                   pairAtt.tAtt = tAtt;
402                   attNList.Append(pairAtt);
403                 }
404                 else 
405               driver->Paste(pAtt, tAtt, aReloc);
406       }
407     }
408   }
409
410 // post processing for compartibiliy with previous versions (24.07.2013)
411   if(attNList.Extent()) {
412     MDF_ListIteratorOfAttributeList listIt(attNList);
413         for(;listIt.More();listIt.Next()) {
414                 const  Handle(PDF_Attribute)& pAtt = listIt.Value().pAtt;
415                 if (!pAtt.IsNull()) { 
416           const Handle(Standard_Type)& type = pAtt->DynamicType();
417                   if (aDriverMap.IsBound(type)) {               
418                 const Handle(MDF_ARDriver)& driver = aDriverMap.Find(type);             
419                 driver->Paste(pAtt, listIt.Value().tAtt, aReloc);
420                   }
421                 }
422         }
423   }
424 //
425   TDF_AttributeList attList;
426   for (itr.Initialize(attMap); itr.More(); itr.Next()) {
427     SpeedCast(itr.Value(),TDF_Attribute,tAtt);
428     attList.Append(tAtt);
429   }
430
431   TDF_ListIteratorOfAttributeList itr2;
432   Standard_Boolean noDeadLock = Standard_True;
433   Standard_Integer nbAtt = attList.Extent();
434   while (noDeadLock && (nbAtt != 0)) {
435     itr2.Initialize(attList);
436     while (itr2.More()) {
437       if (!itr2.Value()->AfterRetrieval())
438         itr2.Next();
439       else
440         attList.Remove(itr2);
441     }
442     noDeadLock = (nbAtt > attList.Extent());
443     nbAtt = attList.Extent();
444   }
445
446   if (!noDeadLock) {
447 #ifdef OCCT_DEBUG
448     cout<<"AfterRetrieval(): dead lock between these attributes:"<<endl;
449     for (itr2.Initialize(attList); itr2.More(); itr2.Next())
450       cout<<"Attribute type = "<<itr2.Value()->DynamicType()->Name()<<endl;;
451     Standard_ConstructionError::Raise("AfterRetrieval: dead lock.");
452 #endif
453     for (itr2.Initialize(attList); itr2.More(); itr2.Next())
454       itr2.Value()->AfterRetrieval(Standard_True);
455   }
456 }