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"
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
20 DF_Label DF_Label::Label(const DF_Label& theLabel, const string& theEntry, bool isCreated)
22 if(theLabel.IsNull()) return DF_Label();
24 DF_Label aLabel = theLabel.Root();
25 if(theEntry == "0:") return aLabel;
26 if(theEntry == "0:1") return theLabel.GetDocument()->Main();
28 char* cc = (char*)theEntry.c_str();
33 while ( *cc >= '0' && *cc <= '9') {
34 n = 10*n + (*cc - '0');
37 if (*cc == ':' || *cc == '\0') {
40 if (*cc != '\0') ++cc;
48 if(!tags.size()) return DF_Label();
50 for(int i = 1, len = tags.size(); !aLabel.IsNull() && i<len; i++)
51 aLabel = aLabel.FindChild(tags[i], isCreated);
56 DF_Label::DF_Label(DF_LabelNode* theNode)
68 DF_Label::DF_Label(const DF_Label& theLabel)
70 _node = theLabel._node;
73 DF_Label& DF_Label::operator=(const DF_Label& theLabel)
75 _node = theLabel._node;
85 //Returns a smart pointer to Document which contains this Label
86 DF_Document* DF_Label::GetDocument() const
88 if(!_node) return NULL;
89 return _node->_document;
92 //Returns true if theLabel equals to this label
93 bool DF_Label::operator==(const DF_Label& theLabel)
95 if(IsNull() || theLabel.IsNull()) return false;
96 return (theLabel.Entry() == Entry());
99 //Returns true if theLabel doesn't equals to this label
100 bool DF_Label::operator!=(const DF_Label& theLabel)
102 if(IsNull() || theLabel.IsNull()) return true;
103 return (theLabel.Entry() != Entry());
107 //Returns a tag of this Label
108 int DF_Label::Tag() const
110 if(!_node) return -1;
114 //Returns true if this Label is attached to the tree in the Document.
115 bool DF_Label::IsAttached()
117 if(!_node) return false;
118 return (bool)(_node->_document);
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
125 if(!_node) return NULL;
127 if(_node->_attributes.find(theID) == _node->_attributes.end()) return NULL;
128 return _node->_attributes[theID];
131 //Returns true if there is an Attribute with given ID on this Label.
132 bool DF_Label::IsAttribute(const std::string& theID) const
134 if(!_node) return false;
136 return (_node->_attributes.find(theID) != _node->_attributes.end());
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
143 if(!_node) return false;
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();
153 //Forgets an Attribute with given ID located on the this Label.
154 bool DF_Label::ForgetAttribute(const std::string& theID) const
156 if(!_node) return false;
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);
167 //Forgets all Attributes located on this Label.
168 bool DF_Label::ForgetAllAttributes(bool clearChildren) const
170 if(!_node) return false;
172 vector<DF_Attribute*> va = GetAttributes();
173 _node->_attributes.clear();
175 for(int i = 0, len = va.size(); i<len; i++) {
176 va[i]->BeforeForget();
181 DF_ChildIterator CI(*this, true);
182 for(; CI.More(); CI.Next())
183 CI.Value().ForgetAllAttributes(true);
189 //Returns Father of this Label.
190 DF_Label DF_Label::Father() const
192 if(!_node) return DF_Label();
194 return _node->_father;
197 //Returns is this Label is not initialized
198 bool DF_Label::IsNull() const
200 return (!_node || (_node->_document == NULL));
203 //Returns is this Label is a Root label
204 bool DF_Label::IsRoot() const
206 if(IsNull() || Father().IsNull()) return true;
211 //Returns true if this Label has Attributes.
212 bool DF_Label::HasAttributes() const
214 if(!_node) return false;
216 return !(_node->_attributes.empty());
219 //Returns a list of Attributes of this Label.
220 vector<DF_Attribute*> DF_Label::GetAttributes() const
222 vector<DF_Attribute*> attributes;
223 if(!_node) return attributes;
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);
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]]);
238 //Returns true if this Label has a child Label.
239 bool DF_Label::HasChild() const
241 if(!_node) return false;
243 return (bool)(_node->_firstChild);
246 //Returns a number of child Labels.
247 int DF_Label::NbChildren() const
249 if(!_node) return -1;
251 if(!_node->_firstChild) return 0;
253 DF_LabelNode* next = _node->_firstChild->_next;
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
265 if(!_node) return -1;
267 return _node->_depth;
270 //Returns true if this Label is a descendant of theLabel.
271 bool DF_Label::IsDescendant(const DF_Label& theLabel)
273 if(!_node) return false;
275 DF_LabelNode* father = _node->_father;
276 if(!father) return false;
279 if(father == theLabel._node) return true;
280 father = father->_father;
286 //Returns the root Label of a Label tree to which this Label belongs.
287 DF_Label DF_Label::Root() const
289 if(!_node) return DF_Label();
291 return _node->_document->Main().Father();
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)
298 if(!_node || IsNull()) return DF_Label();
300 DF_LabelNode *aLabel = NULL, *aPrevious = NULL, *aNext = NULL;
301 if(!_node->_firstChild && !isCreate) return DF_Label();
303 if(_node->_firstChild && _node->_firstChild->_tag == theTag)
304 return DF_Label(_node->_firstChild);
306 if(_node->_lastChild) {
307 if(_node->_lastChild->_tag == theTag) return DF_Label(_node->_lastChild);
308 if(_node->_lastChild->_tag < theTag) aPrevious = _node->_lastChild;
312 aLabel = _node->_firstChild;
314 if(aLabel->_tag == theTag) return DF_Label(aLabel);
315 if(aLabel->_tag > theTag) {
319 if(aLabel->_tag < theTag) aPrevious = aLabel;
320 aLabel = aLabel->_next;
324 if(!isCreate) return DF_Label();
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;
332 aChild->_previous = aNext->_previous;
333 aChild->_next = aNext;
334 aNext->_previous = aChild;
337 aChild->_previous = aPrevious;
338 aChild->_next = aPrevious->_next;
339 aPrevious->_next = aChild;
342 if(!_node->_firstChild || (aNext && aNext == _node->_firstChild) ) _node->_firstChild = aChild;
343 if(!_node->_lastChild || !aNext) _node->_lastChild = aChild;
348 //Creates a new child Label of this Label.
349 DF_Label DF_Label::NewChild()
351 if(!_node || IsNull()) return DF_Label();
354 if(_node->_lastChild) tag = _node->_lastChild->_tag+1;
356 return FindChild(tag, true);
359 //Returns a string entry of this Label
360 string DF_Label::Entry() const
364 DF_LabelNode* father = this->_node;
366 vi.push_back(father->_tag);
367 father = father->_father;
376 for(int i = len-1; i>=0; i--) {
378 sprintf(buffer, "%d", tag);
379 entry+=string(buffer);
387 bool DF_Label::IsEqual(const DF_Label& theLabel)
389 if(theLabel.IsNull() || IsNull()) return false;
390 DF_Label L(theLabel);
391 return (L.Entry() == Entry());
395 void DF_Label::Nullify()
401 void DF_Label::dump()
403 if(!_node) cout << "DF_Label addr : " << this << " NULL " << endl;
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;
409 if(_node->_firstChild) cout << " FirstChild : " << _node->_firstChild << " entry : " << DF_Label(_node->_firstChild).Entry() << endl;
410 else cout << " FirstChild : NULL " << endl;
412 if(_node->_lastChild) cout << " LastChild : " << _node->_lastChild << " entry : " << DF_Label(_node->_lastChild).Entry() << endl;
413 else cout << " LastChild : NULL " << endl;
415 if(_node->_previous) cout << " Previous : " << _node->_previous << " entry : " << DF_Label(_node->_previous).Entry() << endl;
416 else cout << " Previous : NULL " << endl;
418 if(_node->_next) cout << " Next : " << _node->_next << " entry : " << DF_Label(_node->_next).Entry() << endl;
419 else cout << " Next : NULL " << endl;
425 ###############################################
427 ###############################################
430 DF_LabelNode::DF_LabelNode()
443 DF_LabelNode::~DF_LabelNode()
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);
450 for(int i = 0, len = va.size(); i<len; i++)
457 void DF_LabelNode::Reset()
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);
467 for(int i = 0, len = va.size(); i<len; i++)