1 // Created by: DAUTRY Philippe
2 // Copyright (c) 1997-1999 Matra Datavision
3 // Copyright (c) 1999-2012 OPEN CASCADE SAS
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.
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.
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.
20 #include <TDF_Data.ixx>
22 #include <TCollection_AsciiString.hxx>
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>
40 #include <Standard_NoMoreObject.hxx>
41 #include <Standard_NullObject.hxx>
43 #include <NCollection_IncAllocator.hxx>
45 #undef DEB_DELTA_CREATION
46 #undef TDF_DATA_COMMIT_OPTIMIZED
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."; \
63 cout<<itr.Value()<<endl; \
67 #define TDF_Data_DebugModified(ACTION)
70 #ifdef DEB_DELTA_CREATION
71 #define TDF_DataDebugDeltaCreation(DELTATYPE) \
73 TCollection_AsciiString entry; \
74 TDF_Tool::Entry(currentAtt->Label(),entry); \
75 cout<<"Creation of a DeltaOn"<<DELTATYPE<<" \tat "<<entry<<" \ton "<<currentAtt->DynamicType()<<endl; \
78 #define TDF_DataDebugDeltaCreation(DELTATYPE)
81 #define TDF_Data_DeltaCreation(DELTACOMMENT,DELTACREATION) \
83 TDF_DataDebugDeltaCreation(DELTACOMMENT); \
84 aDelta->AddAttributeDelta(DELTACREATION); \
87 //=======================================================================
89 //purpose : empty constructor
90 //=======================================================================
92 TDF_Data::TDF_Data() :
95 myNotUndoMode (Standard_True),
97 myAllowModification (Standard_True)
99 const Handle(NCollection_IncAllocator) anIncAllocator=
100 new NCollection_IncAllocator (16000);
101 myLabelNodeAllocator = anIncAllocator;
102 myRoot = new (anIncAllocator) TDF_LabelNode (this);
105 //=======================================================================
107 //purpose : Used to implement the destructor ~.
108 //=======================================================================
110 void TDF_Data::Destroy()
112 AbortUntilTransaction(1);
113 myRoot->Destroy (myLabelNodeAllocator);
118 //=======================================================================
119 //function : OpenTransaction
121 //=======================================================================
123 Standard_Integer TDF_Data::OpenTransaction()
125 myTimes.Push(myTime);
126 return ++myTransaction;
130 //=======================================================================
131 //function : CommitTransaction
132 //purpose : Commits the current transaction.
133 //=======================================================================
135 Handle(TDF_Delta) TDF_Data::CommitTransaction
136 (const Standard_Boolean withDelta)
138 Handle(TDF_Delta) delta;
139 if (myTransaction>0) {
140 if (withDelta) delta = new TDF_Delta();
142 cout<<"TDF_Data::Begin Commit #"<<myTransaction<<endl;
144 #ifdef TDF_DATA_COMMIT_OPTIMIZED
146 if (Root().myLabelNode->MayBeModified())
149 TDF_Data::CommitTransaction(Root(),delta,withDelta);
151 if (myNbTouchedAtt && !(withDelta && delta->IsEmpty())) ++myTime;
154 if (!delta->IsEmpty()) {
155 delta->Validity(myTimes.Top(),myTime);
157 if (myTransaction == 0) {
158 cout<<"TDF_Data::Commit generated this delta in t=0:"<<endl;
165 if (myTransaction == 0)
166 cout<<"TDF_Data::Commit generated NO delta."<<endl;
172 TDF_Data_DebugModified("COMMIT");
177 //=======================================================================
178 //function : CommitUntilTransaction
179 //purpose : Commits the transactions until AND including
180 // the given transaction index.
181 //=======================================================================
183 Handle(TDF_Delta) TDF_Data::CommitUntilTransaction
184 (const Standard_Integer untilTransaction,
185 const Standard_Boolean withDelta)
187 Handle(TDF_Delta) delta;
188 if ((untilTransaction>0) && (myTransaction >= untilTransaction)) {
189 while (myTransaction > untilTransaction) {
190 delta = TDF_Data::CommitTransaction(Standard_False);
192 delta = TDF_Data::CommitTransaction(withDelta);
198 //=======================================================================
199 //function : CommitTransaction
200 //purpose : Recursive method used to implement the commit action.
201 //=======================================================================
203 Standard_Integer TDF_Data::CommitTransaction
204 (const TDF_Label& aLabel,
205 const Handle(TDF_Delta)& aDelta,
206 const Standard_Boolean withDelta)
208 aLabel.myLabelNode->MayBeModified(Standard_False);
209 Standard_Integer nbTouchedAtt = 0;
210 #ifdef TDF_DATA_COMMIT_OPTIMIZED
211 Standard_Boolean attMod = aLabel.myLabelNode->AttributesModified();
213 Standard_Boolean attMod = Standard_True;
217 Handle(TDF_Attribute) lastAtt;
218 Handle(TDF_Attribute) backupAtt;
219 Standard_Boolean currentIsRemoved = Standard_False;
220 attMod = Standard_False;
222 TDF_AttributeIterator itr1(aLabel, Standard_False);
223 while (itr1.More()) {
224 TDF_Attribute * aPtrCurrentAtt = itr1.Value();
226 // currentAtt = itr1.Value();
230 aPtrCurrentAtt->BeforeCommitTransaction();
233 backupAtt = aPtrCurrentAtt->myBackup;
235 if (aPtrCurrentAtt->myTransaction == myTransaction) {
237 --(aPtrCurrentAtt->myTransaction);
239 // ------------------------------------------------------- Forgotten
240 if (aPtrCurrentAtt->IsForgotten()) {
241 if (aPtrCurrentAtt->mySavedTransaction >=
242 aPtrCurrentAtt->myTransaction)
244 const Handle(TDF_Attribute) currentAtt = aPtrCurrentAtt;
245 // Collision with a not forgotten version.
246 if (backupAtt.IsNull()) {
247 TDF_Data_DeltaCreation
249 currentAtt->DeltaOnRemoval());
250 if (myNotUndoMode) currentAtt->BeforeRemoval();
251 aLabel.myLabelNode->RemoveAttribute(lastAtt,currentAtt);
252 currentIsRemoved = Standard_True;
253 attMod = Standard_True;
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
266 currentAtt->DeltaOnRemoval());
267 if (myNotUndoMode) currentAtt->BeforeRemoval();
268 aLabel.myLabelNode->RemoveAttribute(lastAtt,currentAtt);
269 currentIsRemoved = Standard_True;
272 // BeforeForget has already been called once.
273 // if (myNotUndoMode) currentAtt->BeforeForget();
274 currentAtt->Forget(myTransaction-1);
275 TDF_Data_DeltaCreation
277 currentAtt->DeltaOnForget());
278 attMod = Standard_True;
283 // Forgotten in lower transaction than the current one.
284 TDF_Data_DeltaCreation
286 aPtrCurrentAtt->DeltaOnForget());
289 // ---------------------------------------------------------- Resumed.
290 else if (aPtrCurrentAtt->mySavedTransaction < 0) {
291 TDF_Data_DeltaCreation
293 aPtrCurrentAtt->DeltaOnResume());
294 aPtrCurrentAtt->mySavedTransaction = 0;
295 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
298 // ------------------------------------------------------------ Added.
299 else if (backupAtt.IsNull()) {
300 TDF_Data_DeltaCreation
302 aPtrCurrentAtt->DeltaOnAddition());
303 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
305 // --------------------------------------------------------- Modified.
307 TDF_Data_DeltaCreation
309 aPtrCurrentAtt->DeltaOnModification(backupAtt));
310 if (aPtrCurrentAtt->myTransaction == backupAtt->myTransaction)
311 aPtrCurrentAtt->RemoveBackup();
312 attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
316 else attMod = attMod || (aPtrCurrentAtt->myTransaction > 0);
318 if (currentIsRemoved) currentIsRemoved = Standard_False;
319 else lastAtt = aPtrCurrentAtt;
321 aLabel.myLabelNode->AttributesModified(attMod);
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())
331 TDF_Data::CommitTransaction(itr2.Value(),aDelta,withDelta);
338 //=======================================================================
339 //function : AbortTransaction
340 //purpose : Aborts the current transaction.
341 //=======================================================================
343 void TDF_Data::AbortTransaction()
346 Undo(TDF_Data::CommitTransaction(Standard_True),Standard_False);
347 TDF_Data_DebugModified("New ABORT");
351 //=======================================================================
352 //function : AbortUntilTransaction
353 //purpose : Aborts the transactions until AND including the given index.
354 //=======================================================================
356 void TDF_Data::AbortUntilTransaction(const Standard_Integer untilTransaction)
358 if (untilTransaction>0)
359 Undo(TDF_Data::CommitUntilTransaction(untilTransaction,Standard_True),Standard_False);
363 //=======================================================================
364 //function : IsApplicable
366 //=======================================================================
368 Standard_Boolean TDF_Data::IsApplicable
369 (const Handle(TDF_Delta)& aDelta) const
371 return !aDelta.IsNull() && aDelta->IsApplicable(myTime);
375 //=======================================================================
377 //purpose : Applies a delta to undo actions.
378 //=======================================================================
380 Handle(TDF_Delta) TDF_Data::Undo
381 (const Handle(TDF_Delta)& aDelta,
382 const Standard_Boolean withDelta)
384 Handle(TDF_Delta) newDelta;
385 if (!aDelta.IsNull ()) {
386 if (aDelta->IsApplicable(myTime)) {
387 if (withDelta) OpenTransaction();
389 cout<<"TDF_Data::Undo applies this delta:"<<endl;
392 aDelta->BeforeOrAfterApply(Standard_True);
393 myNotUndoMode = Standard_False;
395 myNotUndoMode = Standard_True;
397 newDelta = CommitTransaction(Standard_True);
398 newDelta->Validity(aDelta->EndTime(),aDelta->BeginTime());
400 cout<<"TDF_Data::Undo, after validity correction, Delta is now available from time \t#"<<newDelta->BeginTime()<<" to time \t#"<<newDelta->EndTime()<<endl;
403 myTime = aDelta->BeginTime();
404 aDelta->BeforeOrAfterApply(Standard_False);
412 //=======================================================================
415 //=======================================================================
417 Standard_OStream& TDF_Data::Dump(Standard_OStream& anOS) const
419 anOS<<"Dump of a TDF_Data."<<endl;
420 anOS<<"Current transaction: "<<myTransaction;
421 anOS<<"; Current tick: "<<myTime<<";"<<endl;