Salome HOME
merge from branch BR_For40_DSC tag mergeto_BR_Dev_For_4_0_16apr07
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_AttributeTreeNode.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 //  File   : SALOMEDSImpl_AttributeTreeNode.cxx
21 //  Author : Sergey RUIN
22 //  Module : SALOME
23
24
25 #include "SALOMEDSImpl_AttributeTreeNode.hxx"
26 #include <Standard_DomainError.hxx>
27 #include <TDF_Tool.hxx>
28 #include <TDF_Data.hxx>
29 #include <TDF_DataSet.hxx>
30 #include <TDF_RelocationTable.hxx>
31 #include <TCollection_AsciiString.hxx> 
32
33 using namespace std;
34
35 IMPLEMENT_STANDARD_HANDLE( SALOMEDSImpl_AttributeTreeNode, SALOMEDSImpl_GenericAttribute )
36 IMPLEMENT_STANDARD_RTTIEXT( SALOMEDSImpl_AttributeTreeNode, SALOMEDSImpl_GenericAttribute )
37
38 static char* Entry(const TDF_Label& theLabel) 
39 {
40   TCollection_AsciiString anEntry;
41   TDF_Tool::Entry(theLabel, anEntry);
42   return anEntry.ToCString();
43 }  
44
45 const Standard_GUID&  SALOMEDSImpl_AttributeTreeNode::GetDefaultTreeID()
46 {
47   static Standard_GUID TreeNodeID ("0E1C36E6-379B-4d90-AC37-17A14310E648");
48   return TreeNodeID;
49 }    
50
51
52 SALOMEDSImpl_AttributeTreeNode::SALOMEDSImpl_AttributeTreeNode() 
53 :SALOMEDSImpl_GenericAttribute("AttributeTreeNode"), myFather(NULL),  myPrevious(NULL), myNext(NULL), myFirst(NULL) 
54 {}
55
56
57 Handle(SALOMEDSImpl_AttributeTreeNode) SALOMEDSImpl_AttributeTreeNode::Set (const TDF_Label& L, const Standard_GUID& ID) 
58 {
59   Handle(SALOMEDSImpl_AttributeTreeNode) TN;
60
61   if (!L.FindAttribute(ID,TN)) {
62     TN = new SALOMEDSImpl_AttributeTreeNode ();
63     TN->SetTreeID(ID);
64     L.AddAttribute(TN);
65   }
66
67   return TN;    
68 }
69
70 //=======================================================================
71 //TreeNode : ID
72 //purpose  : Returns GUID of the TreeNode
73 //=======================================================================
74 const Standard_GUID& SALOMEDSImpl_AttributeTreeNode::ID() const
75 {
76   return myTreeID;
77 }  
78
79 //=======================================================================
80 //function : Append
81 //purpose  : Add <TN> as last child of me
82 //=======================================================================
83 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::Append (const Handle(SALOMEDSImpl_AttributeTreeNode)& TN)
84 {
85   CheckLocked();
86
87   if (!(TN->ID() == myTreeID) )
88     Standard_DomainError::Raise("SALOMEDSImpl_AttributeTreeNode::Append : uncompatible GUID");
89
90   if(TN->Label() == Label())
91     Standard_Failure::Raise("Attempt of self linking");
92
93   Handle(SALOMEDSImpl_AttributeTreeNode) bid;
94   TN->SetNext(bid); // Deconnects from next.
95
96   // Find the last
97   if (!HasFirst()) {
98     SetFirst(TN);
99     TN->SetPrevious(bid); // Deconnects from previous.
100   }
101   else {
102     Handle(SALOMEDSImpl_AttributeTreeNode) Last = GetFirst();
103     while (Last->HasNext()) {
104       Last = Last->GetNext();
105     }
106     Last->SetNext(TN);
107     TN->SetPrevious(Last);
108   }
109   // Set Father
110   TN->SetFather(this);
111   
112   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
113   
114   return !TN.IsNull();
115 }
116
117 //=======================================================================
118 //function : Prepend
119 //purpose  : Add <TN> as first child of me
120 //=======================================================================
121 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::Prepend (const Handle(SALOMEDSImpl_AttributeTreeNode)& TN)
122 {
123   CheckLocked();
124
125   if (!(TN->ID() == myTreeID) )
126     Standard_DomainError::Raise("SALOMEDSImpl_AttributeTreeNode::Prepend : uncompatible GUID");
127
128   if(TN->Label() == Label())
129     Standard_Failure::Raise("Attempt of self linking");
130
131   Handle(SALOMEDSImpl_AttributeTreeNode) bid;
132   TN->SetPrevious(bid);
133   if (HasFirst()) {
134     TN->SetNext(GetFirst());
135     GetFirst()->SetPrevious(TN);
136   }
137   else {
138     TN->SetNext(bid);
139   }
140   TN->SetFather(this);
141   SetFirst(TN);
142   
143   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
144   
145   return !TN.IsNull();
146 }                     
147
148
149 //=======================================================================
150 //function : InsertBefore
151 //purpose  : Inserts the TreeNode  <TN> before me
152 //=======================================================================
153 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::InsertBefore (const Handle(SALOMEDSImpl_AttributeTreeNode)& TN)
154 {
155   CheckLocked();
156
157   if (!(TN->ID() == myTreeID) )
158     Standard_DomainError::Raise("SALOMEDSImpl_AttributeTreeNode::InsertBefore : uncompatible GUID");
159
160   if(TN->Label() == Label())
161     Standard_Failure::Raise("Attempt of self linking");
162
163   TN->SetFather(GetFather());
164   TN->SetPrevious(GetPrevious());
165   TN->SetNext(this);
166
167   if (!HasPrevious())
168     GetFather()->SetFirst(TN);
169   else
170     GetPrevious()->SetNext(TN);
171
172   SetPrevious(TN);
173   
174   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
175   
176   return !TN.IsNull();
177 }
178
179 //=======================================================================
180 //function : InsertAfter
181 //purpose  : Inserts the TreeNode  <TN> after me
182 //=======================================================================
183 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::InsertAfter (const Handle(SALOMEDSImpl_AttributeTreeNode)& TN)
184 {
185   CheckLocked();
186
187   if(TN->Label() == Label())
188     Standard_Failure::Raise("Attempt of self linking");
189
190   if (!(TN->ID() == myTreeID) )
191     Standard_DomainError::Raise("SALOMEDSImpl_AttributeTreeNode::InsertAfter : uncompatible GUID");
192
193   TN->SetFather(GetFather());
194   TN->SetPrevious(this);
195   TN->SetNext(GetNext());
196
197   if (HasNext()) GetNext()->SetPrevious(TN);
198
199   SetNext(TN);
200   
201   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
202   
203   return !TN.IsNull();
204 }         
205
206 //=======================================================================
207 //function : Remove
208 //purpose  : Removees the function from the function tree
209 //=======================================================================
210 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::Remove ()
211 {
212   CheckLocked();
213
214   if (IsRoot()) return Standard_True;
215
216   Handle(SALOMEDSImpl_AttributeTreeNode) bid;
217   if (!HasPrevious())
218     GetFather()->SetFirst(GetNext());
219   else
220     GetPrevious()->SetNext(GetNext());
221
222   if (HasNext()) {
223     if (HasPrevious()) GetNext()->SetPrevious(GetPrevious());
224     else GetNext()->SetPrevious(bid);
225   }
226   else {
227     if (HasPrevious()) GetPrevious()->SetNext(bid);
228   }
229
230   if (GetFather()->HasFirst()) {
231     if (Handle(SALOMEDSImpl_AttributeTreeNode)::DownCast(this) == GetFather()->GetFirst()) {
232       if (HasNext()) {
233         GetFather()->SetFirst(GetNext());
234       }
235       else GetFather()->SetFirst(bid);
236     }
237   }
238
239   SetFather(bid);
240   SetNext(bid);
241   SetPrevious(bid);
242
243   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
244
245   return Standard_True;
246 }         
247
248 //=======================================================================
249 //function : Depth
250 //purpose  :
251 //=======================================================================
252 Standard_Integer SALOMEDSImpl_AttributeTreeNode::Depth () const
253 {
254   Standard_Integer depth = 0;
255   Handle(SALOMEDSImpl_AttributeTreeNode) current = this;
256   while (current->HasFather()) {
257     depth++;
258     current = current->GetFather();
259   }
260   return depth;
261 }
262
263 //=======================================================================
264 //function : SetTreeID
265 //purpose  : Finds or creates a TreeNode  attribute with explicit ID
266 //         : a driver for it
267 //=======================================================================
268 void SALOMEDSImpl_AttributeTreeNode::SetTreeID (const Standard_GUID& explicitID)
269 {
270   myTreeID = explicitID;
271   
272   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
273 }
274
275
276 //=======================================================================
277 //function : IsAscendant
278 //purpose  :
279 //=======================================================================
280 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsAscendant (const Handle(SALOMEDSImpl_AttributeTreeNode)& ofTN) const
281 {
282   return ofTN->IsDescendant(this);
283 }                
284
285 //=======================================================================
286 //function : IsDescendant
287 //purpose  :
288 //=======================================================================
289
290 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsDescendant (const Handle(SALOMEDSImpl_AttributeTreeNode)& ofTN) const
291 {
292   Handle(SALOMEDSImpl_AttributeTreeNode) current = this;
293   while (current->HasFather()) {
294     if (current->GetFather() == ofTN) return Standard_True;
295     current = current->GetFather();
296   }
297   return Standard_False;
298 }
299
300 //=======================================================================
301 //function : IsFather
302 //purpose  :
303 //=======================================================================
304
305 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsFather (const Handle(SALOMEDSImpl_AttributeTreeNode)& ofTN) const
306 {
307   return (ofTN->GetFather() == this);
308 }
309
310
311 //=======================================================================
312 //function : IsChild
313 //purpose  :
314 //=======================================================================
315
316 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsChild (const Handle(SALOMEDSImpl_AttributeTreeNode)& ofTN) const
317 {
318   return (myFather == ofTN);
319 }
320
321 //=======================================================================
322 //TreeNode : IsRoot
323 //purpose  : Returns Standard_True if the TreeNode is not attached to a
324 //           TreeNode tree or hasn't an Father.
325 //=======================================================================
326 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::IsRoot() const
327 {
328   if (myFather.IsNull() &&
329       myPrevious.IsNull() &&
330       myNext.IsNull())
331     return Standard_True;
332   return Standard_False;
333 }
334
335 //=======================================================================
336 //TreeNode : Root
337 //purpose  : Returns the TreeNode which has no Father
338 //=======================================================================
339 Handle(SALOMEDSImpl_AttributeTreeNode) SALOMEDSImpl_AttributeTreeNode::Root() const
340 {
341   Handle(SALOMEDSImpl_AttributeTreeNode) O = this;
342   while (O->HasFather())
343     O = O->GetFather();
344   return O;
345 }       
346
347 //=======================================================================
348 //TreeNode : SetFather
349 //purpose  : Sets the TreeNode F as Father of me
350 //=======================================================================
351 void SALOMEDSImpl_AttributeTreeNode::SetFather(const Handle(SALOMEDSImpl_AttributeTreeNode)& F)
352 {
353   CheckLocked();
354   Backup();
355   myFather = F;
356   
357   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
358 }
359
360 //=======================================================================
361 //TreeNode : SetNext
362 //purpose  : Sets the TreeNode F next to me
363 //=======================================================================
364 void SALOMEDSImpl_AttributeTreeNode::SetNext(const Handle(SALOMEDSImpl_AttributeTreeNode)& F)
365 {
366   CheckLocked();
367   Backup();
368   myNext = F;
369   
370   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
371 }
372
373
374 //=======================================================================
375 //TreeNode : SetPrevious
376 //purpose  : Sets the TreeNode F previous to me
377 //=======================================================================
378 void SALOMEDSImpl_AttributeTreeNode::SetPrevious(const Handle(SALOMEDSImpl_AttributeTreeNode)& F)
379 {
380   CheckLocked();
381   Backup();
382   myPrevious = F;
383   
384   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
385 }
386
387 //=======================================================================
388 //TreeNode : SetFirst
389 //purpose  : Sets the TreeNode F as first in the TreeNode tree
390 //=======================================================================
391 void SALOMEDSImpl_AttributeTreeNode::SetFirst(const Handle(SALOMEDSImpl_AttributeTreeNode)& F)
392 {
393   CheckLocked();
394   Backup();
395   myFirst = F;
396   
397   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
398 }         
399
400 //=======================================================================
401 //TreeNode : AfterAddition
402 //purpose  : Connects the TreeNode to the tree.
403 //           Backuped attribute must stay disconnected
404 //=======================================================================
405 void SALOMEDSImpl_AttributeTreeNode::AfterAddition() 
406 {
407   if (!IsBackuped()) {
408     if (!myPrevious.IsNull()) {
409       myPrevious->SetNext(this);
410     }
411     else if (!myFather.IsNull()) {
412       myFather->SetFirst(this);
413     }
414     if (!myNext.IsNull())
415       myNext->SetPrevious(this);
416   }
417 }
418
419 //=======================================================================
420 //TreeNode : BeforeForget
421 //purpose  : Disconnect the TreeNode from the tree.
422 //           Backuped attribute is normaly not concerned by such an operation
423 //=======================================================================
424 void SALOMEDSImpl_AttributeTreeNode::BeforeForget() 
425 {
426   if (!IsBackuped()) {
427     Remove();
428     while (HasFirst()) GetFirst()->Remove();
429   }
430 }
431
432 //=======================================================================
433 //TreeNode : AfterResume
434 //purpose  : Connects the TreeNode to the tree
435 //=======================================================================
436 void SALOMEDSImpl_AttributeTreeNode::AfterResume() 
437 {
438   AfterAddition();
439 }
440
441 //=======================================================================
442 //TreeNode : BeforeUndo
443 //purpose  : Disconnect the TreeNode from the tree.
444 //=======================================================================
445 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::BeforeUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
446                                                             const Standard_Boolean forceIt)
447 {
448   if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnAddition))) BeforeForget(); // Disconnect.
449   return Standard_True;
450 }           
451
452 //=======================================================================
453 //TreeNode : AfterUndo
454 //purpose  : Connect the TreeNode from the tree.
455 //=======================================================================
456 Standard_Boolean SALOMEDSImpl_AttributeTreeNode::AfterUndo(const Handle(TDF_AttributeDelta)& anAttDelta,
457                                                            const Standard_Boolean forceIt)
458 {
459   if (anAttDelta->IsKind(STANDARD_TYPE(TDF_DeltaOnRemoval))) AfterAddition(); // Reconnect.
460   return Standard_True;
461 }
462
463 //=======================================================================
464 //TreeNode : Restore
465 //purpose  :
466 //=======================================================================
467 void SALOMEDSImpl_AttributeTreeNode::Restore(const Handle(TDF_Attribute)& other) 
468 {
469   Handle(SALOMEDSImpl_AttributeTreeNode) F =  Handle(SALOMEDSImpl_AttributeTreeNode)::DownCast(other);
470   myFather     = F->myFather;
471   myPrevious   = F->myPrevious;
472   myNext       = F->myNext;
473   myFirst      = F->myFirst;
474   myTreeID     = F->myTreeID;
475 }       
476
477 //=======================================================================
478 //TreeNode : Paste
479 //purpose  : Method for Copy mechanism
480 //=======================================================================
481
482 void SALOMEDSImpl_AttributeTreeNode::Paste(const Handle(TDF_Attribute)& into,
483                                            const Handle(TDF_RelocationTable)& RT) const
484 {
485   Handle(SALOMEDSImpl_AttributeTreeNode) intof = Handle(SALOMEDSImpl_AttributeTreeNode)::DownCast(into);
486   Handle(SALOMEDSImpl_AttributeTreeNode) func;
487   if (!RT->HasRelocation(myFather, func) && RT->AfterRelocate()) {
488     func.Nullify();
489   }
490   intof->SetFather(func);
491   if (!RT->HasRelocation(myNext, func) && RT->AfterRelocate()) {
492     func.Nullify();
493   }
494   intof->SetNext(func);
495   if (!RT->HasRelocation(myPrevious, func) && RT->AfterRelocate()) {
496     func.Nullify();
497   }
498   intof->SetPrevious(func);
499   if (!RT->HasRelocation(myFirst, func) && RT->AfterRelocate()) {
500     func.Nullify();
501   }
502
503   intof->SetFirst(func);
504   intof->SetTreeID(myTreeID);
505 }
506
507 //=======================================================================
508 //TreeNode : NewEmpty
509 //purpose  : Returns new empty TreeNode attribute
510 //=======================================================================
511
512 Handle(TDF_Attribute) SALOMEDSImpl_AttributeTreeNode::NewEmpty() const
513 {
514   Handle(SALOMEDSImpl_AttributeTreeNode) T = new SALOMEDSImpl_AttributeTreeNode();
515   T->SetTreeID(myTreeID);
516   return T;
517 }
518
519 //=======================================================================
520 //TreeNode : References
521 //purpose  : Collects the references
522 //=======================================================================
523 void SALOMEDSImpl_AttributeTreeNode::References(const Handle(TDF_DataSet)& aDataSet) const
524 {
525   Handle(SALOMEDSImpl_AttributeTreeNode) fct = myFirst;
526   while (!fct.IsNull()) {
527     aDataSet->AddAttribute(fct);
528     fct = fct->myNext;
529   }
530 }          
531
532 TCollection_AsciiString SALOMEDSImpl_AttributeTreeNode::Type()
533 {
534    char* aNodeName = new char[60];
535    char aGUID[40];
536    ID().ToCString(aGUID);
537    sprintf(aNodeName, "AttributeTreeNodeGUID%s",aGUID);
538    TCollection_AsciiString ret(aNodeName); 
539    delete aNodeName;
540    
541    return ret;                               
542 }
543
544 TCollection_AsciiString SALOMEDSImpl_AttributeTreeNode::Save() 
545 {
546   TCollection_AsciiString aFather, aPrevious, aNext, aFirst;
547
548   if (HasFather()) aFather = Entry(GetFather()->Label()); else aFather = "!";
549   if (HasPrevious()) aPrevious = Entry(GetPrevious()->Label()); else aPrevious = "!";
550   if (HasNext()) aNext = Entry(GetNext()->Label()); else aNext = "!";
551   if (HasFirst()) aFirst = Entry(GetFirst()->Label()); else aFirst = "!";
552
553   int aLength = 4;
554   aLength += aFather.Length() + aPrevious.Length() + aNext.Length() + aFirst.Length();
555   char* aResult = new char[aLength];
556   sprintf(aResult, "%s %s %s %s", aFather.ToCString(), aPrevious.ToCString(), aNext.ToCString(), aFirst.ToCString());
557   TCollection_AsciiString ret(aResult);
558   delete aResult;
559   return ret;
560 }
561
562 void SALOMEDSImpl_AttributeTreeNode::Load(const TCollection_AsciiString& value) 
563 {
564   Handle(TDF_Data) DF = Label().Data();
565   
566   char* aCopy = (char*)value.ToCString();
567   char* adr = strtok(aCopy, " ");
568   
569   TDF_Label aLabel;
570   Handle(SALOMEDSImpl_AttributeTreeNode) aDepNode;
571
572   if (adr && adr[0] != '!') {
573     TDF_Tool::Label(DF, adr, aLabel, 1);
574     if (!aLabel.FindAttribute(ID(), aDepNode)) 
575       aDepNode =  SALOMEDSImpl_AttributeTreeNode::Set(aLabel, ID());
576
577     SetFather(aDepNode);
578   }
579
580   adr = strtok(NULL, " ");
581   if (adr && adr[0] != '!') {
582     TDF_Tool::Label(DF, adr, aLabel, 1);
583     if (!aLabel.FindAttribute(ID(), aDepNode)) 
584       aDepNode = SALOMEDSImpl_AttributeTreeNode::Set(aLabel, ID());
585     SetPrevious(aDepNode);
586   }
587
588   adr = strtok(NULL, " ");
589   if (adr && adr[0] != '!') {
590     TDF_Tool::Label(DF, adr, aLabel, 1);
591     if (!aLabel.FindAttribute(ID(), aDepNode)) 
592       aDepNode = SALOMEDSImpl_AttributeTreeNode::Set(aLabel, ID());
593     SetNext(aDepNode);
594   }
595
596   adr = strtok(NULL, " ");
597   if (adr && adr[0] != '!') {
598     TDF_Tool::Label(DF, adr, aLabel, 1);
599     if (!aLabel.FindAttribute(ID(), aDepNode)) 
600       aDepNode = SALOMEDSImpl_AttributeTreeNode::Set(aLabel, ID());
601     SetFirst(aDepNode);
602   }
603 }
604
605