0023002: empty delete operator in TDF_LabelNode
[occt.git] / src / TDF / TDF_Data.cxx
CommitLineData
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; \
53if (!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{ \
73TCollection_AsciiString entry; \
74TDF_Tool::Entry(currentAtt->Label(),entry); \
75cout<<"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) \
82if (withDelta) { \
83 TDF_DataDebugDeltaCreation(DELTACOMMENT); \
84 aDelta->AddAttributeDelta(DELTACREATION); \
85}
86
7fd59977 87//=======================================================================
88//function : TDF_Data
89//purpose : empty constructor
90//=======================================================================
91
92TDF_Data::TDF_Data() :
93myTransaction (0),
94myNbTouchedAtt (0),
95myNotUndoMode (Standard_True),
96myTime (0),
97myAllowModification (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
110void 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
123Standard_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
135Handle(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
183Handle(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
203Standard_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
343void 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
356void 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
368Standard_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
380Handle(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
417Standard_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}