3 // Author: DAUTRY Philippe
4 // <fid@fox.paris1.matra-dtv.fr>
5 // Copyright: Matra Datavision 1997
8 // History: Version Date Purpose
9 // 0.0 Feb 6 1997 Creation
13 #include <TDF_Data.ixx>
15 #include <TCollection_AsciiString.hxx>
17 #include <TDF_Attribute.hxx>
18 #include <TDF_AttributeIterator.hxx>
19 #include <TDF_AttributeIndexedMap.hxx>
20 #include <TDF_ChildIterator.hxx>
21 #include <TDF_Delta.hxx>
22 #include <TDF_AttributeDelta.hxx>
23 #include <TDF_DeltaOnAddition.hxx>
24 #include <TDF_DeltaOnForget.hxx>
25 #include <TDF_DeltaOnModification.hxx>
26 #include <TDF_DeltaOnRemoval.hxx>
27 #include <TDF_DeltaOnResume.hxx>
28 #include <TDF_Label.hxx>
29 #include <TDF_LabelNode.hxx>
30 #include <TDF_LabelNodePtr.hxx>
31 #include <TDF_Tool.hxx>
33 #include <Standard_NoMoreObject.hxx>
34 #include <Standard_NullObject.hxx>
36 #undef DEB_DELTA_CREATION
37 #undef TDF_DATA_COMMIT_OPTIMIZED
42 #define TDF_Data_DebugModified(ACTION) \
43 cout<<"After "<<ACTION<<" #"<<myTransaction+1<<", DF "<<this<<" had "<<myNbTouchedAtt<<" attribute(s) touched. Time = "<<myTime<<endl; \
44 if (!myTransaction) { \
45 TCollection_AsciiString entry; \
46 for (TDF_ChildIterator itr(Root(),Standard_True); itr.More(); itr.Next()) { \
47 const TDF_LabelNode* lnp = itr.Value().myLabelNode; \
48 if (lnp->AttributesModified() || lnp->MayBeModified()) { \
49 TDF_Tool::Entry(itr.Value(),entry); \
50 cout<<ACTION<<" on "<<entry<<" : flag(s) "; \
51 if (lnp->AttributesModified()) cout<<"AttributesModified "; \
52 if (lnp->MayBeModified()) cout<<"MayBeModified already set in transaction 0! Please contact TDF developer."; \
54 cout<<itr.Value()<<endl; \
58 #define TDF_Data_DebugModified(ACTION)
61 #ifdef DEB_DELTA_CREATION
62 #define TDF_DataDebugDeltaCreation(DELTATYPE) \
64 TCollection_AsciiString entry; \
65 TDF_Tool::Entry(currentAtt->Label(),entry); \
66 cout<<"Creation of a DeltaOn"<<DELTATYPE<<" \tat "<<entry<<" \ton "<<currentAtt->DynamicType()<<endl; \
69 #define TDF_DataDebugDeltaCreation(DELTATYPE)
72 #define TDF_Data_DeltaCreation(DELTACOMMENT,DELTACREATION) \
74 TDF_DataDebugDeltaCreation(DELTACOMMENT); \
75 aDelta->AddAttributeDelta(DELTACREATION); \
79 // Disable the warning: "operator new unmatched by delete"
80 #pragma warning (disable:4291)
83 //=======================================================================
85 //purpose : empty constructor
86 //=======================================================================
88 TDF_Data::TDF_Data() :
91 myNotUndoMode (Standard_True),
93 myAllowModification (Standard_True)
95 const Handle(NCollection_IncAllocator) anIncAllocator=
96 new NCollection_IncAllocator (16000);
97 myLabelNodeAllocator = anIncAllocator;
98 myRoot = new (anIncAllocator) TDF_LabelNode (this);
102 #pragma warning (default:4291)
105 //=======================================================================
107 //purpose : Used to implement the destructor ~.
108 //=======================================================================
110 void TDF_Data::Destroy()
112 AbortUntilTransaction(1);
117 //=======================================================================
118 //function : OpenTransaction
120 //=======================================================================
122 Standard_Integer TDF_Data::OpenTransaction()
124 myTimes.Push(myTime);
125 return ++myTransaction;
129 //=======================================================================
130 //function : CommitTransaction
131 //purpose : Commits the current transaction.
132 //=======================================================================
134 Handle(TDF_Delta) TDF_Data::CommitTransaction
135 (const Standard_Boolean withDelta)
137 Handle(TDF_Delta) delta;
138 if (myTransaction>0) {
139 if (withDelta) delta = new TDF_Delta();
141 cout<<"TDF_Data::Begin Commit #"<<myTransaction<<endl;
143 #ifdef TDF_DATA_COMMIT_OPTIMIZED
145 if (Root().myLabelNode->MayBeModified())
148 TDF_Data::CommitTransaction(Root(),delta,withDelta);
150 if (myNbTouchedAtt && !(withDelta && delta->IsEmpty())) ++myTime;
153 if (!delta->IsEmpty()) {
154 delta->Validity(myTimes.Top(),myTime);
156 if (myTransaction == 0) {
157 cout<<"TDF_Data::Commit generated this delta in t=0:"<<endl;
164 if (myTransaction == 0)
165 cout<<"TDF_Data::Commit generated NO delta."<<endl;
171 TDF_Data_DebugModified("COMMIT");
176 //=======================================================================
177 //function : CommitUntilTransaction
178 //purpose : Commits the transactions until AND including
179 // the given transaction index.
180 //=======================================================================
182 Handle(TDF_Delta) TDF_Data::CommitUntilTransaction
183 (const Standard_Integer untilTransaction,
184 const Standard_Boolean withDelta)
186 Handle(TDF_Delta) delta;
187 if ((untilTransaction>0) && (myTransaction >= untilTransaction)) {
188 while (myTransaction > untilTransaction) {
189 delta = TDF_Data::CommitTransaction(Standard_False);
191 delta = TDF_Data::CommitTransaction(withDelta);
197 //=======================================================================
198 //function : CommitTransaction
199 //purpose : Recursive method used to implement the commit action.
200 //=======================================================================
202 Standard_Integer TDF_Data::CommitTransaction
203 (const TDF_Label& aLabel,
204 const Handle(TDF_Delta)& aDelta,
205 const Standard_Boolean withDelta)
207 aLabel.myLabelNode->MayBeModified(Standard_False);
208 Standard_Integer nbTouchedAtt = 0;
209 #ifdef TDF_DATA_COMMIT_OPTIMIZED
210 Standard_Boolean attMod = aLabel.myLabelNode->AttributesModified();
212 Standard_Boolean attMod = Standard_True;
216 Handle(TDF_Attribute) lastAtt;
217 Handle(TDF_Attribute) backupAtt;
218 Standard_Boolean currentIsRemoved = Standard_False;
219 attMod = Standard_False;
221 TDF_AttributeIterator itr1(aLabel, Standard_False);
222 while (itr1.More()) {
223 TDF_Attribute * aPtrCurrentAtt = itr1.Value();
225 // currentAtt = itr1.Value();
229 aPtrCurrentAtt->BeforeCommitTransaction();
232 backupAtt = aPtrCurrentAtt->myBackup;
234 if (aPtrCurrentAtt->myTransaction == myTransaction) {
236 --(aPtrCurrentAtt->myTransaction);
238 // ------------------------------------------------------- Forgotten
239 if (aPtrCurrentAtt->IsForgotten()) {
240 if (aPtrCurrentAtt->mySavedTransaction >=
241 aPtrCurrentAtt->myTransaction)
243 const Handle(TDF_Attribute) currentAtt = aPtrCurrentAtt;
244 // Collision with a not forgotten version.
245 if (backupAtt.IsNull()) {
246 TDF_Data_DeltaCreation
248 currentAtt->DeltaOnRemoval());
249 if (myNotUndoMode) currentAtt->BeforeRemoval();
250 aLabel.myLabelNode->RemoveAttribute(lastAtt,currentAtt);
251 currentIsRemoved = Standard_True;
252 attMod = Standard_True;
255 // Modified then Forgotten...
256 // Forgotten flag spreading?
257 currentAtt->Resume();
258 currentAtt->Restore(backupAtt);
259 currentAtt->myTransaction = backupAtt->myTransaction;
260 currentAtt->RemoveBackup();
261 backupAtt = currentAtt->myBackup;
262 if (myTransaction == 1) {
263 TDF_Data_DeltaCreation
265 currentAtt->DeltaOnRemoval());
266 if (myNotUndoMode) currentAtt->BeforeRemoval();
267 aLabel.myLabelNode->RemoveAttribute(lastAtt,currentAtt);
268 currentIsRemoved = Standard_True;
271 // BeforeForget has already been called once.
272 // if (myNotUndoMode) currentAtt->BeforeForget();
273 currentAtt->Forget(myTransaction-1);
274 TDF_Data_DeltaCreation
276 currentAtt->DeltaOnForget());
277 attMod = Standard_True;
282 // Forgotten in lower transaction than the current one.
283 TDF_Data_DeltaCreation
285 aPtrCurrentAtt->DeltaOnForget());
288 // ---------------------------------------------------------- Resumed.
289 else if (aPtrCurrentAtt->mySavedTransaction < 0) {
290 TDF_Data_DeltaCreation
292 aPtrCurrentAtt->DeltaOnResume());
293 aPtrCurrentAtt->mySavedTransaction = 0;
294 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
297 // ------------------------------------------------------------ Added.
298 else if (backupAtt.IsNull()) {
299 TDF_Data_DeltaCreation
301 aPtrCurrentAtt->DeltaOnAddition());
302 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
304 // --------------------------------------------------------- Modified.
306 TDF_Data_DeltaCreation
308 aPtrCurrentAtt->DeltaOnModification(backupAtt));
309 if (aPtrCurrentAtt->myTransaction == backupAtt->myTransaction)
310 aPtrCurrentAtt->RemoveBackup();
311 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
315 else attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
317 if (currentIsRemoved) currentIsRemoved = Standard_False;
318 else lastAtt = aPtrCurrentAtt;
320 aLabel.myLabelNode->AttributesModified(attMod);
323 // Iteration on the children to do the same!
324 //------------------------------------------
325 for (TDF_ChildIterator itr2(aLabel); itr2.More(); itr2.Next()) {
326 #ifdef TDF_DATA_COMMIT_OPTIMIZED
327 if (itr2.Value().myLabelNode->MayBeModified())
330 TDF_Data::CommitTransaction(itr2.Value(),aDelta,withDelta);
337 //=======================================================================
338 //function : AbortTransaction
339 //purpose : Aborts the current transaction.
340 //=======================================================================
342 void TDF_Data::AbortTransaction()
345 Undo(TDF_Data::CommitTransaction(Standard_True),Standard_False);
346 TDF_Data_DebugModified("New ABORT");
350 //=======================================================================
351 //function : AbortUntilTransaction
352 //purpose : Aborts the transactions until AND including the given index.
353 //=======================================================================
355 void TDF_Data::AbortUntilTransaction(const Standard_Integer untilTransaction)
357 if (untilTransaction>0)
358 Undo(TDF_Data::CommitUntilTransaction(untilTransaction,Standard_True),Standard_False);
362 //=======================================================================
363 //function : IsApplicable
365 //=======================================================================
367 Standard_Boolean TDF_Data::IsApplicable
368 (const Handle(TDF_Delta)& aDelta) const
370 return !aDelta.IsNull() && aDelta->IsApplicable(myTime);
374 //=======================================================================
376 //purpose : Applies a delta to undo actions.
377 //=======================================================================
379 Handle(TDF_Delta) TDF_Data::Undo
380 (const Handle(TDF_Delta)& aDelta,
381 const Standard_Boolean withDelta)
383 Handle(TDF_Delta) newDelta;
384 if (!aDelta.IsNull ()) {
385 if (aDelta->IsApplicable(myTime)) {
386 if (withDelta) OpenTransaction();
388 cout<<"TDF_Data::Undo applies this delta:"<<endl;
391 aDelta->BeforeOrAfterApply(Standard_True);
392 myNotUndoMode = Standard_False;
394 myNotUndoMode = Standard_True;
396 newDelta = CommitTransaction(Standard_True);
397 newDelta->Validity(aDelta->EndTime(),aDelta->BeginTime());
399 cout<<"TDF_Data::Undo, after validity correction, Delta is now available from time \t#"<<newDelta->BeginTime()<<" to time \t#"<<newDelta->EndTime()<<endl;
402 myTime = aDelta->BeginTime();
403 aDelta->BeforeOrAfterApply(Standard_False);
411 //=======================================================================
414 //=======================================================================
416 Standard_OStream& TDF_Data::Dump(Standard_OStream& anOS) const
418 anOS<<"Dump of a TDF_Data."<<endl;
419 anOS<<"Current transaction: "<<myTransaction;
420 anOS<<"; Current tick: "<<myTime<<";"<<endl;