]>
Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created by: DAUTRY Philippe |
2 | // Copyright (c) 1997-1999 Matra Datavision | |
3 | // Copyright (c) 1999-2012 OPEN CASCADE SAS | |
4 | // | |
5 | // The content of this file is subject to the Open CASCADE Technology Public | |
6 | // License Version 6.5 (the "License"). You may not use the content of this file | |
7 | // except in compliance with the License. Please obtain a copy of the License | |
8 | // at http://www.opencascade.org and read it completely before using this file. | |
9 | // | |
10 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its | |
11 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. | |
12 | // | |
13 | // The Original Code and all software distributed under the License is | |
14 | // distributed on an "AS IS" basis, without warranty of any kind, and the | |
15 | // Initial Developer hereby disclaims all such warranties, including without | |
16 | // limitation, any warranties of merchantability, fitness for a particular | |
17 | // purpose or non-infringement. Please see the License for the specific terms | |
18 | // and conditions governing the rights and limitations under the License. | |
19 | ||
7fd59977 | 20 | #include <TDF_Data.ixx> |
21 | ||
22 | #include <TCollection_AsciiString.hxx> | |
23 | ||
24 | #include <TDF_Attribute.hxx> | |
25 | #include <TDF_AttributeIterator.hxx> | |
26 | #include <TDF_AttributeIndexedMap.hxx> | |
27 | #include <TDF_ChildIterator.hxx> | |
28 | #include <TDF_Delta.hxx> | |
29 | #include <TDF_AttributeDelta.hxx> | |
30 | #include <TDF_DeltaOnAddition.hxx> | |
31 | #include <TDF_DeltaOnForget.hxx> | |
32 | #include <TDF_DeltaOnModification.hxx> | |
33 | #include <TDF_DeltaOnRemoval.hxx> | |
34 | #include <TDF_DeltaOnResume.hxx> | |
35 | #include <TDF_Label.hxx> | |
36 | #include <TDF_LabelNode.hxx> | |
37 | #include <TDF_LabelNodePtr.hxx> | |
38 | #include <TDF_Tool.hxx> | |
39 | ||
40 | #include <Standard_NoMoreObject.hxx> | |
41 | #include <Standard_NullObject.hxx> | |
42 | ||
60d4560d | 43 | #include <NCollection_IncAllocator.hxx> |
44 | ||
7fd59977 | 45 | #undef DEB_DELTA_CREATION |
46 | #undef TDF_DATA_COMMIT_OPTIMIZED | |
47 | ||
48 | #define BUC60879 | |
49 | ||
50 | #ifdef DEB_DELTA | |
51 | #define TDF_Data_DebugModified(ACTION) \ | |
52 | cout<<"After "<<ACTION<<" #"<<myTransaction+1<<", DF "<<this<<" had "<<myNbTouchedAtt<<" attribute(s) touched. Time = "<<myTime<<endl; \ | |
53 | if (!myTransaction) { \ | |
54 | TCollection_AsciiString entry; \ | |
55 | for (TDF_ChildIterator itr(Root(),Standard_True); itr.More(); itr.Next()) { \ | |
56 | const TDF_LabelNode* lnp = itr.Value().myLabelNode; \ | |
57 | if (lnp->AttributesModified() || lnp->MayBeModified()) { \ | |
58 | TDF_Tool::Entry(itr.Value(),entry); \ | |
59 | cout<<ACTION<<" on "<<entry<<" : flag(s) "; \ | |
60 | if (lnp->AttributesModified()) cout<<"AttributesModified "; \ | |
61 | if (lnp->MayBeModified()) cout<<"MayBeModified already set in transaction 0! Please contact TDF developer."; \ | |
62 | cout<<endl; \ | |
63 | cout<<itr.Value()<<endl; \ | |
64 | entry.Clear(); \ | |
65 | }}} | |
66 | #else | |
67 | #define TDF_Data_DebugModified(ACTION) | |
68 | #endif | |
69 | ||
70 | #ifdef DEB_DELTA_CREATION | |
71 | #define TDF_DataDebugDeltaCreation(DELTATYPE) \ | |
72 | { \ | |
73 | TCollection_AsciiString entry; \ | |
74 | TDF_Tool::Entry(currentAtt->Label(),entry); \ | |
75 | cout<<"Creation of a DeltaOn"<<DELTATYPE<<" \tat "<<entry<<" \ton "<<currentAtt->DynamicType()<<endl; \ | |
76 | } | |
77 | #else | |
78 | #define TDF_DataDebugDeltaCreation(DELTATYPE) | |
79 | #endif | |
80 | ||
81 | #define TDF_Data_DeltaCreation(DELTACOMMENT,DELTACREATION) \ | |
82 | if (withDelta) { \ | |
83 | TDF_DataDebugDeltaCreation(DELTACOMMENT); \ | |
84 | aDelta->AddAttributeDelta(DELTACREATION); \ | |
85 | } | |
86 | ||
7fd59977 | 87 | //======================================================================= |
88 | //function : TDF_Data | |
89 | //purpose : empty constructor | |
90 | //======================================================================= | |
91 | ||
92 | TDF_Data::TDF_Data() : | |
93 | myTransaction (0), | |
94 | myNbTouchedAtt (0), | |
95 | myNotUndoMode (Standard_True), | |
96 | myTime (0), | |
97 | myAllowModification (Standard_True) | |
98 | { | |
99 | const Handle(NCollection_IncAllocator) anIncAllocator= | |
100 | new NCollection_IncAllocator (16000); | |
101 | myLabelNodeAllocator = anIncAllocator; | |
102 | myRoot = new (anIncAllocator) TDF_LabelNode (this); | |
103 | } | |
104 | ||
7fd59977 | 105 | //======================================================================= |
106 | //function : Destroy | |
107 | //purpose : Used to implement the destructor ~. | |
108 | //======================================================================= | |
109 | ||
110 | void TDF_Data::Destroy() | |
111 | { | |
112 | AbortUntilTransaction(1); | |
60d4560d | 113 | myRoot->Destroy (myLabelNodeAllocator); |
114 | myRoot = NULL; | |
7fd59977 | 115 | } |
116 | ||
117 | ||
118 | //======================================================================= | |
119 | //function : OpenTransaction | |
120 | //purpose : | |
121 | //======================================================================= | |
122 | ||
123 | Standard_Integer TDF_Data::OpenTransaction() | |
124 | { | |
125 | myTimes.Push(myTime); | |
126 | return ++myTransaction; | |
127 | } | |
128 | ||
129 | ||
130 | //======================================================================= | |
131 | //function : CommitTransaction | |
132 | //purpose : Commits the current transaction. | |
133 | //======================================================================= | |
134 | ||
135 | Handle(TDF_Delta) TDF_Data::CommitTransaction | |
136 | (const Standard_Boolean withDelta) | |
137 | { | |
138 | Handle(TDF_Delta) delta; | |
139 | if (myTransaction>0) { | |
140 | if (withDelta) delta = new TDF_Delta(); | |
141 | #ifdef DEB_DELTA | |
142 | cout<<"TDF_Data::Begin Commit #"<<myTransaction<<endl; | |
143 | #endif | |
144 | #ifdef TDF_DATA_COMMIT_OPTIMIZED | |
145 | myNbTouchedAtt = 0; | |
146 | if (Root().myLabelNode->MayBeModified()) | |
147 | #endif | |
148 | myNbTouchedAtt = | |
149 | TDF_Data::CommitTransaction(Root(),delta,withDelta); | |
150 | ||
151 | if (myNbTouchedAtt && !(withDelta && delta->IsEmpty())) ++myTime; | |
152 | --myTransaction; | |
153 | if (withDelta) { | |
154 | if (!delta->IsEmpty()) { | |
155 | delta->Validity(myTimes.Top(),myTime); | |
156 | #ifdef DEB_DELTA | |
157 | if (myTransaction == 0) { | |
158 | cout<<"TDF_Data::Commit generated this delta in t=0:"<<endl; | |
159 | delta->Dump(cout); | |
160 | } | |
161 | #endif | |
162 | } | |
163 | #ifdef DEB_DELTA | |
164 | else { | |
165 | if (myTransaction == 0) | |
166 | cout<<"TDF_Data::Commit generated NO delta."<<endl; | |
167 | } | |
168 | #endif | |
169 | } | |
170 | myTimes.Pop(); | |
171 | } | |
172 | TDF_Data_DebugModified("COMMIT"); | |
173 | return delta; | |
174 | } | |
175 | ||
176 | ||
177 | //======================================================================= | |
178 | //function : CommitUntilTransaction | |
179 | //purpose : Commits the transactions until AND including | |
180 | // the given transaction index. | |
181 | //======================================================================= | |
182 | ||
183 | Handle(TDF_Delta) TDF_Data::CommitUntilTransaction | |
184 | (const Standard_Integer untilTransaction, | |
185 | const Standard_Boolean withDelta) | |
186 | { | |
187 | Handle(TDF_Delta) delta; | |
188 | if ((untilTransaction>0) && (myTransaction >= untilTransaction)) { | |
189 | while (myTransaction > untilTransaction) { | |
190 | delta = TDF_Data::CommitTransaction(Standard_False); | |
191 | } | |
192 | delta = TDF_Data::CommitTransaction(withDelta); | |
193 | } | |
194 | return delta; | |
195 | } | |
196 | ||
197 | ||
198 | //======================================================================= | |
199 | //function : CommitTransaction | |
200 | //purpose : Recursive method used to implement the commit action. | |
201 | //======================================================================= | |
202 | ||
203 | Standard_Integer TDF_Data::CommitTransaction | |
204 | (const TDF_Label& aLabel, | |
205 | const Handle(TDF_Delta)& aDelta, | |
206 | const Standard_Boolean withDelta) | |
207 | { | |
208 | aLabel.myLabelNode->MayBeModified(Standard_False); | |
209 | Standard_Integer nbTouchedAtt = 0; | |
210 | #ifdef TDF_DATA_COMMIT_OPTIMIZED | |
211 | Standard_Boolean attMod = aLabel.myLabelNode->AttributesModified(); | |
212 | #else | |
213 | Standard_Boolean attMod = Standard_True; | |
214 | #endif | |
215 | ||
216 | if (attMod) { | |
217 | Handle(TDF_Attribute) lastAtt; | |
218 | Handle(TDF_Attribute) backupAtt; | |
219 | Standard_Boolean currentIsRemoved = Standard_False; | |
220 | attMod = Standard_False; | |
221 | ||
222 | TDF_AttributeIterator itr1(aLabel, Standard_False); | |
223 | while (itr1.More()) { | |
224 | TDF_Attribute * aPtrCurrentAtt = itr1.Value(); | |
225 | itr1.Next(); | |
226 | // currentAtt = itr1.Value(); | |
227 | ||
228 | #ifdef BUC60879 | |
229 | // A callback: | |
230 | aPtrCurrentAtt->BeforeCommitTransaction(); | |
231 | #endif | |
232 | ||
233 | backupAtt = aPtrCurrentAtt->myBackup; | |
234 | ||
235 | if (aPtrCurrentAtt->myTransaction == myTransaction) { | |
236 | ++nbTouchedAtt; | |
237 | --(aPtrCurrentAtt->myTransaction); | |
238 | ||
239 | // ------------------------------------------------------- Forgotten | |
240 | if (aPtrCurrentAtt->IsForgotten()) { | |
241 | if (aPtrCurrentAtt->mySavedTransaction >= | |
242 | aPtrCurrentAtt->myTransaction) | |
243 | { | |
244 | const Handle(TDF_Attribute) currentAtt = aPtrCurrentAtt; | |
245 | // Collision with a not forgotten version. | |
246 | if (backupAtt.IsNull()) { | |
247 | TDF_Data_DeltaCreation | |
248 | ("Removal(1)", | |
249 | currentAtt->DeltaOnRemoval()); | |
250 | if (myNotUndoMode) currentAtt->BeforeRemoval(); | |
251 | aLabel.myLabelNode->RemoveAttribute(lastAtt,currentAtt); | |
252 | currentIsRemoved = Standard_True; | |
253 | attMod = Standard_True; | |
254 | } | |
255 | else { | |
256 | // Modified then Forgotten... | |
257 | // Forgotten flag spreading? | |
258 | currentAtt->Resume(); | |
259 | currentAtt->Restore(backupAtt); | |
260 | currentAtt->myTransaction = backupAtt->myTransaction; | |
261 | currentAtt->RemoveBackup(); | |
262 | backupAtt = currentAtt->myBackup; | |
263 | if (myTransaction == 1) { | |
264 | TDF_Data_DeltaCreation | |
265 | ("Removal(2)", | |
266 | currentAtt->DeltaOnRemoval()); | |
267 | if (myNotUndoMode) currentAtt->BeforeRemoval(); | |
268 | aLabel.myLabelNode->RemoveAttribute(lastAtt,currentAtt); | |
269 | currentIsRemoved = Standard_True; | |
270 | } | |
271 | else { | |
272 | // BeforeForget has already been called once. | |
273 | // if (myNotUndoMode) currentAtt->BeforeForget(); | |
274 | currentAtt->Forget(myTransaction-1); | |
275 | TDF_Data_DeltaCreation | |
276 | ("Forget(1)", | |
277 | currentAtt->DeltaOnForget()); | |
278 | attMod = Standard_True; | |
279 | } | |
280 | } | |
281 | } | |
282 | else { | |
283 | // Forgotten in lower transaction than the current one. | |
284 | TDF_Data_DeltaCreation | |
285 | ("Forget(2)", | |
286 | aPtrCurrentAtt->DeltaOnForget()); | |
287 | } | |
288 | } | |
289 | // ---------------------------------------------------------- Resumed. | |
290 | else if (aPtrCurrentAtt->mySavedTransaction < 0) { | |
291 | TDF_Data_DeltaCreation | |
292 | ("Resume", | |
293 | aPtrCurrentAtt->DeltaOnResume()); | |
294 | aPtrCurrentAtt->mySavedTransaction = 0; | |
295 | attMod = attMod || (aPtrCurrentAtt->myTransaction > 0); | |
296 | } | |
297 | ||
298 | // ------------------------------------------------------------ Added. | |
299 | else if (backupAtt.IsNull()) { | |
300 | TDF_Data_DeltaCreation | |
301 | ("Addition", | |
302 | aPtrCurrentAtt->DeltaOnAddition()); | |
303 | attMod = attMod || (aPtrCurrentAtt->myTransaction > 0); | |
304 | } | |
305 | // --------------------------------------------------------- Modified. | |
306 | else { | |
307 | TDF_Data_DeltaCreation | |
308 | ("Modification", | |
309 | aPtrCurrentAtt->DeltaOnModification(backupAtt)); | |
310 | if (aPtrCurrentAtt->myTransaction == backupAtt->myTransaction) | |
311 | aPtrCurrentAtt->RemoveBackup(); | |
312 | attMod = attMod || (aPtrCurrentAtt->myTransaction > 0); | |
313 | } | |
314 | ||
315 | } | |
316 | else attMod = attMod || (aPtrCurrentAtt->myTransaction > 0); | |
317 | ||
318 | if (currentIsRemoved) currentIsRemoved = Standard_False; | |
319 | else lastAtt = aPtrCurrentAtt; | |
320 | } | |
321 | aLabel.myLabelNode->AttributesModified(attMod); | |
322 | } | |
323 | ||
324 | // Iteration on the children to do the same! | |
325 | //------------------------------------------ | |
326 | for (TDF_ChildIterator itr2(aLabel); itr2.More(); itr2.Next()) { | |
327 | #ifdef TDF_DATA_COMMIT_OPTIMIZED | |
328 | if (itr2.Value().myLabelNode->MayBeModified()) | |
329 | #endif | |
330 | nbTouchedAtt += | |
331 | TDF_Data::CommitTransaction(itr2.Value(),aDelta,withDelta); | |
332 | } | |
333 | ||
334 | return nbTouchedAtt; | |
335 | } | |
336 | ||
337 | ||
338 | //======================================================================= | |
339 | //function : AbortTransaction | |
340 | //purpose : Aborts the current transaction. | |
341 | //======================================================================= | |
342 | ||
343 | void TDF_Data::AbortTransaction() | |
344 | { | |
345 | if (myTransaction>0) | |
346 | Undo(TDF_Data::CommitTransaction(Standard_True),Standard_False); | |
347 | TDF_Data_DebugModified("New ABORT"); | |
348 | } | |
349 | ||
350 | ||
351 | //======================================================================= | |
352 | //function : AbortUntilTransaction | |
353 | //purpose : Aborts the transactions until AND including the given index. | |
354 | //======================================================================= | |
355 | ||
356 | void TDF_Data::AbortUntilTransaction(const Standard_Integer untilTransaction) | |
357 | { | |
358 | if (untilTransaction>0) | |
359 | Undo(TDF_Data::CommitUntilTransaction(untilTransaction,Standard_True),Standard_False); | |
360 | } | |
361 | ||
362 | ||
363 | //======================================================================= | |
364 | //function : IsApplicable | |
365 | //purpose : | |
366 | //======================================================================= | |
367 | ||
368 | Standard_Boolean TDF_Data::IsApplicable | |
369 | (const Handle(TDF_Delta)& aDelta) const | |
370 | { | |
371 | return !aDelta.IsNull() && aDelta->IsApplicable(myTime); | |
372 | } | |
373 | ||
374 | ||
375 | //======================================================================= | |
376 | //function : Undo | |
377 | //purpose : Applies a delta to undo actions. | |
378 | //======================================================================= | |
379 | ||
380 | Handle(TDF_Delta) TDF_Data::Undo | |
381 | (const Handle(TDF_Delta)& aDelta, | |
382 | const Standard_Boolean withDelta) | |
383 | { | |
384 | Handle(TDF_Delta) newDelta; | |
385 | if (!aDelta.IsNull ()) { | |
386 | if (aDelta->IsApplicable(myTime)) { | |
387 | if (withDelta) OpenTransaction(); | |
388 | #ifdef DEB_DELTA | |
389 | cout<<"TDF_Data::Undo applies this delta:"<<endl; | |
390 | aDelta->Dump(cout); | |
391 | #endif | |
392 | aDelta->BeforeOrAfterApply(Standard_True); | |
393 | myNotUndoMode = Standard_False; | |
394 | aDelta->Apply (); | |
395 | myNotUndoMode = Standard_True; | |
396 | if (withDelta) { | |
397 | newDelta = CommitTransaction(Standard_True); | |
398 | newDelta->Validity(aDelta->EndTime(),aDelta->BeginTime()); | |
399 | #ifdef DEB_DELTA | |
400 | cout<<"TDF_Data::Undo, after validity correction, Delta is now available from time \t#"<<newDelta->BeginTime()<<" to time \t#"<<newDelta->EndTime()<<endl; | |
401 | #endif | |
402 | } | |
403 | myTime = aDelta->BeginTime(); | |
404 | aDelta->BeforeOrAfterApply(Standard_False); | |
405 | } | |
406 | } | |
407 | return newDelta; | |
408 | } | |
409 | ||
410 | ||
411 | ||
412 | //======================================================================= | |
413 | //function : Dump | |
414 | //purpose : | |
415 | //======================================================================= | |
416 | ||
417 | Standard_OStream& TDF_Data::Dump(Standard_OStream& anOS) const | |
418 | { | |
419 | anOS<<"Dump of a TDF_Data."<<endl; | |
420 | anOS<<"Current transaction: "<<myTransaction; | |
421 | anOS<<"; Current tick: "<<myTime<<";"<<endl; | |
422 | return anOS; | |
423 | } |