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