]> SALOME platform Git repositories - modules/kernel.git/blob - src/DF/DF_Label.cxx
Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/kernel.git] / src / DF / DF_Label.cxx
1 #include "DF_definitions.hxx"
2 #include "DF_Label.hxx"
3 #include "DF_Document.hxx"
4 #include "DF_Attribute.hxx"
5 #include "DF_ChildIterator.hxx"
6
7 #include <algorithm>
8
9 using namespace std;
10
11 //Class DF_Label defines a persistence reference in DF_Document that contains a tree of Labels.
12 //This reference is named "entry" and is a sequence of tags divided by ":". The root entry is "0:".
13 //For example "0:1:1" corresponds the following structure
14 // 0_
15 //   |
16 //   |_1_
17 //       |
18 //       |_ 1
19
20 DF_Label DF_Label::Label(const DF_Label& theLabel, const string& theEntry, bool isCreated)
21 {
22   if(theLabel.IsNull()) return DF_Label();
23   
24   DF_Label aLabel = theLabel.Root();
25   if(theEntry == "0:") return aLabel;
26   if(theEntry == "0:1") return theLabel.GetDocument()->Main();
27
28   char* cc = (char*)theEntry.c_str();
29   int n = 0;
30   vector<int> tags;
31
32   while (*cc != '\0') {
33     while ( *cc >= '0' && *cc <= '9') {
34       n = 10*n + (*cc - '0');
35       ++cc;
36     }
37     if (*cc == ':' || *cc == '\0') {
38       tags.push_back(n);
39       n = 0;
40       if (*cc != '\0') ++cc;
41     }
42     else {
43       tags.clear();
44       break;
45     }
46   }
47
48   if(!tags.size()) return DF_Label();
49   
50   for(int i = 1, len = tags.size(); !aLabel.IsNull() && i<len; i++)
51     aLabel = aLabel.FindChild(tags[i], isCreated);
52
53   return aLabel;
54 }
55
56 DF_Label::DF_Label(DF_LabelNode* theNode)
57   :_node(theNode)
58 {
59 }
60
61 //Constructor
62 DF_Label::DF_Label()
63 {
64   _node = NULL;
65 }
66
67 //Copy constructor
68 DF_Label::DF_Label(const DF_Label& theLabel)
69 {
70   _node = theLabel._node;
71 }
72
73 DF_Label& DF_Label::operator=(const DF_Label& theLabel)
74 {
75   _node = theLabel._node;
76   return *this;
77 }
78
79 //Destructor
80 DF_Label::~DF_Label()
81 {
82   _node = NULL;
83 }
84
85 //Returns a smart pointer to Document which contains this Label
86 DF_Document* DF_Label::GetDocument() const
87 {
88   if(!_node) return NULL;
89   return _node->_document;
90 }
91
92 //Returns true if theLabel equals to this label
93 bool DF_Label::operator==(const DF_Label& theLabel)
94 {
95   if(IsNull() || theLabel.IsNull()) return false;
96   return (theLabel.Entry() == Entry());
97 }
98
99 //Returns true if theLabel doesn't equals to this label
100 bool DF_Label::operator!=(const DF_Label& theLabel)
101 {
102   if(IsNull() || theLabel.IsNull()) return true;
103   return (theLabel.Entry() != Entry());
104 }
105
106
107 //Returns a tag of this Label
108 int DF_Label::Tag() const
109 {
110   if(!_node) return -1;
111   return _node->_tag;
112 }
113
114 //Returns true if this Label is attached to the tree in the Document.
115 bool DF_Label::IsAttached()
116 {
117   if(!_node) return false;
118   return (bool)(_node->_document);
119 }
120
121 //Searches an Attribute with given ID located on this Label.
122 //Returns true if the Attribute is found.
123 DF_Attribute* DF_Label::FindAttribute(const std::string& theID) const
124 {
125   if(!_node) return NULL;
126
127   if(_node->_attributes.find(theID) == _node->_attributes.end()) return NULL;
128   return _node->_attributes[theID];
129 }
130
131 //Returns true if there is an Attribute with given ID on this Label.
132 bool DF_Label::IsAttribute(const std::string& theID) const
133 {
134   if(!_node) return false;
135
136   return (_node->_attributes.find(theID) != _node->_attributes.end());
137 }
138
139 //Adds theAttribute to the Label where this Attribute is located.
140 //Returns true if theAttribute was added.
141 bool DF_Label::AddAttribute(DF_Attribute* theAttribute) const
142 {
143   if(!_node) return false;
144
145   if(_node->_attributes.find(theAttribute->ID()) != _node->_attributes.end()) return false;
146   theAttribute->_node = _node;
147   _node->_attributes[theAttribute->ID()] = theAttribute;
148   theAttribute->AfterAddition();    
149
150   return true;
151 }
152
153 //Forgets an Attribute with given ID located on the this Label.
154 bool DF_Label::ForgetAttribute(const std::string& theID) const
155 {
156   if(!_node) return false;
157
158   if(_node->_attributes.find(theID) == _node->_attributes.end()) return false;
159   DF_Attribute* attr = _node->_attributes[theID];
160   attr->BeforeForget();
161   _node->_attributes.erase(theID);
162   delete attr;
163
164   return true;
165 }
166
167 //Forgets all Attributes located on this Label.
168 bool DF_Label::ForgetAllAttributes(bool clearChildren) const
169 {
170   if(!_node) return false;
171
172   vector<DF_Attribute*> va = GetAttributes();
173   _node->_attributes.clear();
174
175   for(int i = 0, len = va.size(); i<len; i++) {
176     va[i]->BeforeForget();
177     delete va[i];
178   }
179
180   if(clearChildren) {
181     DF_ChildIterator CI(*this, true);
182     for(; CI.More(); CI.Next()) 
183       CI.Value().ForgetAllAttributes(true);
184   }
185
186   return true;
187 }
188
189 //Returns Father of this Label.
190 DF_Label DF_Label::Father() const
191 {
192   if(!_node) return DF_Label();
193
194   return _node->_father;
195 }
196
197 //Returns is this Label is not initialized
198 bool DF_Label::IsNull() const
199 {
200   return (!_node || (_node->_document == NULL));
201 }
202
203 //Returns is this Label is a Root label
204 bool DF_Label::IsRoot() const
205 {
206   if(IsNull() || Father().IsNull()) return true;
207   return false;
208 }
209
210
211 //Returns true if this Label has Attributes.
212 bool DF_Label::HasAttributes() const
213 {
214   if(!_node) return false;
215
216   return !(_node->_attributes.empty());
217 }
218
219 //Returns a list of Attributes of this Label.
220 vector<DF_Attribute*> DF_Label::GetAttributes() const
221 {
222   vector<DF_Attribute*> attributes;
223   if(!_node) return attributes;
224   
225   typedef map<string, DF_Attribute*>::const_iterator AI;
226   vector<string> sorted;
227   for(AI p = _node->_attributes.begin(); p!=_node->_attributes.end(); p++)
228     sorted.push_back(p->first);
229     
230   sort(sorted.begin(), sorted.end());
231   int len = sorted.size();    
232   for(int i = 0; i<len; i++)
233     attributes.push_back(_node->_attributes[sorted[i]]);
234
235   return attributes;
236 }
237
238 //Returns true if this Label has a child Label.
239 bool DF_Label::HasChild() const
240 {
241   if(!_node) return false;
242
243   return (bool)(_node->_firstChild);
244 }
245
246 //Returns a number of child Labels.
247 int DF_Label::NbChildren() const
248 {
249   if(!_node) return -1;
250
251   if(!_node->_firstChild) return 0;
252   int nb = 1;
253   DF_LabelNode* next = _node->_firstChild->_next;
254   while(next) {
255     nb++;
256     next = next->_next;
257   }
258
259   return nb;
260 }
261
262 //Returns the depth (a number of fathers required to identify the Label) of this Label in the tree.
263 int DF_Label::Depth() const
264 {
265   if(!_node) return -1;
266
267   return _node->_depth;
268 }
269
270 //Returns true if this Label is a descendant of theLabel.
271 bool DF_Label::IsDescendant(const DF_Label& theLabel)
272 {
273   if(!_node) return false;
274
275   DF_LabelNode* father = _node->_father;
276   if(!father) return false;
277
278   while(father) {
279     if(father == theLabel._node) return true;
280     father = father->_father;
281   }
282
283   return false;
284 }
285
286 //Returns the root Label of a Label tree to which this Label belongs.
287 DF_Label DF_Label::Root() const
288 {
289   if(!_node) return DF_Label();
290
291   return _node->_document->Main().Father();
292 }
293
294 //Finds a child Label of this Label with a given tag. If isCreate = true and there is no child
295 //Label with the given tag, the child Label is created.
296 DF_Label DF_Label::FindChild(int theTag, bool isCreate)
297 {
298   if(!_node || IsNull()) return DF_Label();
299
300   DF_LabelNode *aLabel = NULL, *aPrevious = NULL, *aNext = NULL;
301   if(!_node->_firstChild && !isCreate) return DF_Label();
302
303   if(_node->_firstChild && _node->_firstChild->_tag == theTag)
304     return DF_Label(_node->_firstChild);
305  
306   if(_node->_lastChild) {
307     if(_node->_lastChild->_tag == theTag) return DF_Label(_node->_lastChild);
308     if(_node->_lastChild->_tag < theTag) aPrevious = _node->_lastChild;
309   }
310   
311   if(!aPrevious) { 
312     aLabel = _node->_firstChild;
313     while(aLabel) {
314       if(aLabel->_tag == theTag) return DF_Label(aLabel);
315       if(aLabel->_tag > theTag) {
316         aNext = aLabel;
317         break;
318       }
319       if(aLabel->_tag < theTag) aPrevious = aLabel;
320       aLabel = aLabel->_next;
321     }
322   }
323   
324   if(!isCreate) return DF_Label();
325
326   DF_LabelNode* aChild = new DF_LabelNode();
327   aChild->_father = this->_node;
328   aChild->_document = _node->_document;
329   aChild->_tag = theTag;
330   aChild->_depth = _node->_depth+1;
331   if(aNext) {
332     aChild->_previous = aNext->_previous;
333     aChild->_next = aNext;
334     aNext->_previous = aChild;
335   }
336   if(aPrevious) {
337     aChild->_previous = aPrevious;
338     aChild->_next = aPrevious->_next;
339     aPrevious->_next = aChild;
340   }
341     
342   if(!_node->_firstChild || (aNext && aNext == _node->_firstChild) ) _node->_firstChild = aChild;
343   if(!_node->_lastChild || !aNext) _node->_lastChild = aChild;
344   
345   return aChild;
346 }
347
348 //Creates a new child Label of this Label.
349 DF_Label DF_Label::NewChild()
350 {
351   if(!_node || IsNull()) return DF_Label();
352
353   int tag = 1;
354   if(_node->_lastChild) tag = _node->_lastChild->_tag+1;
355   
356   return FindChild(tag, true);
357 }
358
359 //Returns a string entry of this Label
360 string DF_Label::Entry() const
361 {
362   string entry = "";
363   vector<int> vi;
364   DF_LabelNode* father = this->_node;
365   while(father) {
366     vi.push_back(father->_tag);
367     father = father->_father;
368   }
369
370   int len = vi.size();
371   if(len == 1) {
372     entry = "0:";
373   }
374   else {
375     char buffer[128];
376     for(int i = len-1; i>=0; i--) {
377       int tag = vi[i];
378       sprintf(buffer, "%d", tag);
379       entry+=string(buffer);
380       if(i) entry += ":";
381     }
382   }
383
384   return entry;
385 }
386
387 bool DF_Label::IsEqual(const DF_Label& theLabel)
388 {
389   if(theLabel.IsNull() || IsNull()) return false;
390   DF_Label L(theLabel);
391   return (L.Entry() == Entry());
392 }
393
394
395 void DF_Label::Nullify() 
396 {
397   delete _node;
398   _node = NULL;
399 }
400
401 void DF_Label::dump()
402 {
403   if(!_node) cout << "DF_Label addr : " << this << " NULL " << endl;
404   else {
405     cout << "DF_Label addr : " << this->_node << " entry : " << Entry() << endl;
406     if(_node->_father) cout << " Father : " << _node->_father << " entry : " << Father().Entry() << endl;
407     else cout << " Father : NULL " << endl;
408
409     if(_node->_firstChild) cout << " FirstChild : " << _node->_firstChild << " entry : " << DF_Label(_node->_firstChild).Entry() << endl;
410     else cout << " FirstChild : NULL " << endl;
411
412     if(_node->_lastChild) cout << " LastChild : " << _node->_lastChild << " entry : " << DF_Label(_node->_lastChild).Entry() << endl;
413     else cout << " LastChild : NULL " << endl;
414
415     if(_node->_previous) cout << " Previous : " << _node->_previous << " entry : " << DF_Label(_node->_previous).Entry() << endl;
416     else cout << " Previous : NULL " << endl;
417
418     if(_node->_next) cout << " Next : " << _node->_next << " entry : " << DF_Label(_node->_next).Entry() << endl;
419     else cout << " Next : NULL " << endl;
420   }
421 }
422
423
424 /*
425  ###############################################
426             DF_LabelNode methods
427  ###############################################
428 */
429
430 DF_LabelNode::DF_LabelNode()
431 {
432   _depth = 0;
433   _tag = 0;
434   _attributes.clear();
435   _document = NULL;
436   _father = NULL;
437   _firstChild = NULL;
438   _lastChild = NULL;
439   _previous = NULL;
440   _next = NULL;
441 }
442
443 DF_LabelNode::~DF_LabelNode()
444 {
445   vector<DF_Attribute*> va;
446   typedef map<string, DF_Attribute*>::const_iterator AI;
447   for(AI p = _attributes.begin(); p!=_attributes.end(); p++)
448     va.push_back(p->second);
449
450   for(int i = 0, len = va.size(); i<len; i++) 
451     delete va[i];
452
453   _attributes.clear();
454 }
455
456
457 void DF_LabelNode::Reset()
458 {
459   _depth = 0;
460   _tag = 0;
461
462   vector<DF_Attribute*> va;
463   typedef map<string, DF_Attribute*>::const_iterator AI;
464   for(AI p = _attributes.begin(); p!=_attributes.end(); p++)
465     va.push_back(p->second);
466
467   for(int i = 0, len = va.size(); i<len; i++) 
468     delete va[i];
469
470   _attributes.clear();
471   _document = NULL;
472   _father = NULL;
473   _firstChild = NULL;
474   _lastChild = NULL;
475   _previous = NULL;
476   _next = NULL;  
477 }