Back to index

salome-kernel  6.5.0
DF_Label.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "DF_definitions.hxx"
00021 #include "DF_Label.hxx"
00022 #include "DF_Document.hxx"
00023 #include "DF_Attribute.hxx"
00024 #include "DF_ChildIterator.hxx"
00025 
00026 #include <algorithm>
00027 
00028 //Class DF_Label defines a persistence reference in DF_Document that contains a tree of Labels.
00029 //This reference is named "entry" and is a sequence of tags divided by ":". The root entry is "0:".
00030 //For example "0:1:1" corresponds the following structure
00031 // 0_
00032 //   |
00033 //   |_1_
00034 //       |
00035 //       |_ 1
00036 
00037 DF_Label DF_Label::Label(const DF_Label& theLabel, const std::string& theEntry, bool isCreated)
00038 {
00039   if(theLabel.IsNull()) return DF_Label();
00040   
00041   DF_Label aLabel = theLabel.Root();
00042   if(theEntry == "0:") return aLabel;
00043   if(theEntry == "0:1") return theLabel.GetDocument()->Main();
00044 
00045   char* cc = (char*)theEntry.c_str();
00046   int n = 0;
00047   int i=0;
00048 
00049   while (*cc != '\0') {
00050     while ( *cc >= '0' && *cc <= '9') {
00051       n = 10*n + (*cc - '0');
00052       ++cc;
00053     }
00054     if (*cc == ':' || *cc == '\0') {
00055       if(i>0)
00056         {
00057           if(aLabel.IsNull())break;
00058           aLabel = aLabel.FindChild(n, isCreated);
00059         }
00060       i++;
00061       n = 0;
00062       if (*cc != '\0') ++cc;
00063     }
00064     else {
00065       return DF_Label();
00066     }
00067   }
00068 
00069   return aLabel;
00070 }
00071 
00072 DF_Label::DF_Label(DF_LabelNode* theNode)
00073   :_node(theNode)
00074 {
00075 }
00076 
00077 //Constructor
00078 DF_Label::DF_Label()
00079 {
00080   _node = NULL;
00081 }
00082 
00083 //Copy constructor
00084 DF_Label::DF_Label(const DF_Label& theLabel)
00085 {
00086   _node = theLabel._node;
00087 }
00088 
00089 DF_Label& DF_Label::operator=(const DF_Label& theLabel)
00090 {
00091   _node = theLabel._node;
00092   return *this;
00093 }
00094 
00095 //Destructor
00096 DF_Label::~DF_Label()
00097 {
00098   _node = NULL;
00099 }
00100 
00101 //Returns a smart pointer to Document which contains this Label
00102 DF_Document* DF_Label::GetDocument() const
00103 {
00104   if(!_node) return NULL;
00105   return _node->_document;
00106 }
00107 
00108 //Returns true if theLabel equals to this label
00109 bool DF_Label::operator==(const DF_Label& theLabel)
00110 {
00111   if(IsNull() || theLabel.IsNull()) return false;
00112   return (theLabel.Entry() == Entry());
00113 }
00114 
00115 //Returns true if theLabel doesn't equals to this label
00116 bool DF_Label::operator!=(const DF_Label& theLabel)
00117 {
00118   if(IsNull() || theLabel.IsNull()) return true;
00119   return (theLabel.Entry() != Entry());
00120 }
00121 
00122 
00123 //Returns a tag of this Label
00124 int DF_Label::Tag() const
00125 {
00126   if(!_node) return -1;
00127   return _node->_tag;
00128 }
00129 
00130 //Returns true if this Label is attached to the tree in the Document.
00131 bool DF_Label::IsAttached()
00132 {
00133   if(!_node) return false;
00134   return _node->_document != 0;
00135 }
00136 
00137 //Searches an Attribute with given ID located on this Label.
00138 //Returns true if the Attribute is found.
00139 DF_Attribute* DF_Label::FindAttribute(const std::string& theID) const
00140 {
00141   if(!_node) return NULL;
00142 
00143   std::map< std::string, DF_Attribute* >::iterator it=_node->_attributes.find(theID);
00144   if(it == _node->_attributes.end()) return NULL;
00145   return it->second;
00146 
00147 }
00148 
00149 //Returns true if there is an Attribute with given ID on this Label.
00150 bool DF_Label::IsAttribute(const std::string& theID) const
00151 {
00152   if(!_node) return false;
00153 
00154   return (_node->_attributes.find(theID) != _node->_attributes.end());
00155 }
00156 
00157 //Adds theAttribute to the Label where this Attribute is located.
00158 //Returns true if theAttribute was added.
00159 bool DF_Label::AddAttribute(DF_Attribute* theAttribute) const
00160 {
00161   if(!_node) return false;
00162 
00163   if(_node->_attributes.find(theAttribute->ID()) != _node->_attributes.end()) return false;
00164   theAttribute->_node = _node;
00165   _node->_attributes[theAttribute->ID()] = theAttribute;
00166   theAttribute->AfterAddition();    
00167 
00168   return true;
00169 }
00170 
00171 //Forgets an Attribute with given ID located on the this Label.
00172 bool DF_Label::ForgetAttribute(const std::string& theID) const
00173 {
00174   if(!_node) return false;
00175 
00176   if(_node->_attributes.find(theID) == _node->_attributes.end()) return false;
00177   DF_Attribute* attr = _node->_attributes[theID];
00178   attr->BeforeForget();
00179   _node->_attributes.erase(theID);
00180   delete attr;
00181 
00182   return true;
00183 }
00184 
00185 //Forgets all Attributes located on this Label.
00186 bool DF_Label::ForgetAllAttributes(bool clearChildren) const
00187 {
00188   if(!_node) return false;
00189 
00190   std::vector<DF_Attribute*> va = GetAttributes();
00191   _node->_attributes.clear();
00192 
00193   for(int i = 0, len = va.size(); i<len; i++) {
00194     va[i]->BeforeForget();
00195     delete va[i];
00196   }
00197 
00198   if(clearChildren) {
00199     DF_ChildIterator CI(*this, true);
00200     for(; CI.More(); CI.Next()) 
00201       CI.Value().ForgetAllAttributes(true);
00202   }
00203 
00204   return true;
00205 }
00206 
00207 //Returns Father of this Label.
00208 DF_Label DF_Label::Father() const
00209 {
00210   if(!_node) return DF_Label();
00211 
00212   return _node->_father;
00213 }
00214 
00215 //Returns is this Label is not initialized
00216 bool DF_Label::IsNull() const
00217 {
00218   return (!_node || (_node->_document == NULL));
00219 }
00220 
00221 //Returns is this Label is a Root label
00222 bool DF_Label::IsRoot() const
00223 {
00224   if(IsNull() || Father().IsNull()) return true;
00225   return false;
00226 }
00227 
00228 
00229 //Returns true if this Label has Attributes.
00230 bool DF_Label::HasAttributes() const
00231 {
00232   if(!_node) return false;
00233 
00234   return !(_node->_attributes.empty());
00235 }
00236 
00237 //Returns a list of Attributes of this Label.
00238 std::vector<DF_Attribute*> DF_Label::GetAttributes() const
00239 {
00240   std::vector<DF_Attribute*> attributes;
00241   if(!_node) return attributes;
00242   
00243   typedef std::map<std::string, DF_Attribute*>::const_iterator AI;
00244   std::vector<std::string> sorted;
00245   for(AI p = _node->_attributes.begin(); p!=_node->_attributes.end(); p++)
00246     sorted.push_back(p->first);
00247     
00248   sort(sorted.begin(), sorted.end());
00249   int len = sorted.size();    
00250   for(int i = 0; i<len; i++)
00251     attributes.push_back(_node->_attributes[sorted[i]]);
00252 
00253   return attributes;
00254 }
00255 
00256 //Returns true if this Label has a child Label.
00257 bool DF_Label::HasChild() const
00258 {
00259   if(!_node) return false;
00260 
00261   return _node->_firstChild != 0;
00262 }
00263 
00264 //Returns a number of child Labels.
00265 int DF_Label::NbChildren() const
00266 {
00267   if(!_node) return -1;
00268 
00269   if(!_node->_firstChild) return 0;
00270   int nb = 1;
00271   DF_LabelNode* next = _node->_firstChild->_next;
00272   while(next) {
00273     nb++;
00274     next = next->_next;
00275   }
00276 
00277   return nb;
00278 }
00279 
00280 //Returns the depth (a number of fathers required to identify the Label) of this Label in the tree.
00281 int DF_Label::Depth() const
00282 {
00283   if(!_node) return -1;
00284 
00285   return _node->_depth;
00286 }
00287 
00288 //Returns true if this Label is a descendant of theLabel.
00289 bool DF_Label::IsDescendant(const DF_Label& theLabel)
00290 {
00291   if(!_node) return false;
00292 
00293   DF_LabelNode* father = _node->_father;
00294   if(!father) return false;
00295 
00296   while(father) {
00297     if(father == theLabel._node) return true;
00298     father = father->_father;
00299   }
00300 
00301   return false;
00302 }
00303 
00304 //Returns the root Label of a Label tree to which this Label belongs.
00305 DF_Label DF_Label::Root() const
00306 {
00307   if(!_node) return DF_Label();
00308 
00309   return _node->_document->Main().Father();
00310 }
00311 
00312 //Finds a child Label of this Label with a given tag. If isCreate = true and there is no child
00313 //Label with the given tag, the child Label is created.
00314 DF_Label DF_Label::FindChild(int theTag, bool isCreate)
00315 {
00316   if(!_node || IsNull()) return DF_Label();
00317 
00318   DF_LabelNode *aLabel = NULL, *aPrevious = NULL, *aNext = NULL;
00319   if(!_node->_firstChild && !isCreate) return DF_Label();
00320 
00321   if(_node->_firstChild && _node->_firstChild->_tag == theTag)
00322     return DF_Label(_node->_firstChild);
00323  
00324   if(_node->_lastChild) {
00325     if(_node->_lastChild->_tag == theTag) return DF_Label(_node->_lastChild);
00326     if(_node->_lastChild->_tag < theTag) aPrevious = _node->_lastChild;
00327   }
00328   
00329   if(!aPrevious) { 
00330     aLabel = _node->_firstChild;
00331     while(aLabel) {
00332       if(aLabel->_tag == theTag) return DF_Label(aLabel);
00333       if(aLabel->_tag > theTag) {
00334         aNext = aLabel;
00335         break;
00336       }
00337       if(aLabel->_tag < theTag) aPrevious = aLabel;
00338       aLabel = aLabel->_next;
00339     }
00340   }
00341   
00342   if(!isCreate) return DF_Label();
00343 
00344   DF_LabelNode* aChild = new DF_LabelNode();
00345   aChild->_father = this->_node;
00346   aChild->_document = _node->_document;
00347   aChild->_tag = theTag;
00348   aChild->_depth = _node->_depth+1;
00349   if(aNext) {
00350     aChild->_previous = aNext->_previous;
00351     aChild->_next = aNext;
00352     aNext->_previous = aChild;
00353   }
00354   if(aPrevious) {
00355     aChild->_previous = aPrevious;
00356     aChild->_next = aPrevious->_next;
00357     aPrevious->_next = aChild;
00358   }
00359     
00360   if(!_node->_firstChild || (aNext && aNext == _node->_firstChild) ) _node->_firstChild = aChild;
00361   if(!_node->_lastChild || !aNext) _node->_lastChild = aChild;
00362   
00363   return aChild;
00364 }
00365 
00366 //Creates a new child Label of this Label.
00367 DF_Label DF_Label::NewChild()
00368 {
00369   if(!_node || IsNull()) return DF_Label();
00370 
00371   int tag = 1;
00372   if(_node->_lastChild) tag = _node->_lastChild->_tag+1;
00373   
00374   return FindChild(tag, true);
00375 }
00376 
00377 //Returns a string entry of this Label
00378 std::string DF_Label::Entry() const
00379 {
00380   DF_LabelNode* father = this->_node;
00381   if(!father->_father)return "0:";
00382   int tag;
00383   char buff[128];
00384   char* wstr= buff;
00385   char* str = buff;
00386 
00387   while(father)
00388     {
00389       tag=father->_tag;
00390       do{
00391          // Conversion. Number is reversed.
00392          *wstr++ = '0' + (tag % 10);
00393       }while(tag /= 10);
00394       father = father->_father;
00395       if(father)*wstr++ = ':';
00396     }
00397   *wstr-- = '\0';
00398 
00399   //reverse the buffer
00400   char aux;
00401   while (wstr > str)
00402     aux = *wstr, *wstr-- = *str, *str++ = aux;
00403 
00404   return buff;
00405 }
00406 
00407 bool DF_Label::IsEqual(const DF_Label& theLabel)
00408 {
00409   if(theLabel.IsNull() || IsNull()) return false;
00410   DF_Label L(theLabel);
00411   return (L.Entry() == Entry());
00412 }
00413 
00414 
00415 void DF_Label::Nullify() 
00416 {
00417   delete _node;
00418   _node = NULL;
00419 }
00420 
00421 void DF_Label::dump()
00422 {
00423   if(!_node) std::cout << "DF_Label addr : " << this << " NULL " << std::endl;
00424   else {
00425     std::cout << "DF_Label addr : " << this->_node << " entry : " << Entry() << std::endl;
00426     if(_node->_father) std::cout << " Father : " << _node->_father << " entry : " << Father().Entry() << std::endl;
00427     else std::cout << " Father : NULL " << std::endl;
00428 
00429     if(_node->_firstChild) std::cout << " FirstChild : " << _node->_firstChild << " entry : " << DF_Label(_node->_firstChild).Entry() << std::endl;
00430     else std::cout << " FirstChild : NULL " << std::endl;
00431 
00432     if(_node->_lastChild) std::cout << " LastChild : " << _node->_lastChild << " entry : " << DF_Label(_node->_lastChild).Entry() << std::endl;
00433     else std::cout << " LastChild : NULL " << std::endl;
00434 
00435     if(_node->_previous) std::cout << " Previous : " << _node->_previous << " entry : " << DF_Label(_node->_previous).Entry() << std::endl;
00436     else std::cout << " Previous : NULL " << std::endl;
00437 
00438     if(_node->_next) std::cout << " Next : " << _node->_next << " entry : " << DF_Label(_node->_next).Entry() << std::endl;
00439     else std::cout << " Next : NULL " << std::endl;
00440   }
00441 }
00442 
00443 
00444 /*
00445  ###############################################
00446             DF_LabelNode methods
00447  ###############################################
00448 */
00449 
00450 DF_LabelNode::DF_LabelNode()
00451 {
00452   _depth = 0;
00453   _tag = 0;
00454   _attributes.clear();
00455   _document = NULL;
00456   _father = NULL;
00457   _firstChild = NULL;
00458   _lastChild = NULL;
00459   _previous = NULL;
00460   _next = NULL;
00461 }
00462 
00463 DF_LabelNode::~DF_LabelNode()
00464 {
00465   std::vector<DF_Attribute*> va;
00466   typedef std::map<std::string, DF_Attribute*>::const_iterator AI;
00467   for(AI p = _attributes.begin(); p!=_attributes.end(); p++)
00468     va.push_back(p->second);
00469 
00470   for(int i = 0, len = va.size(); i<len; i++) 
00471     delete va[i];
00472 
00473   _attributes.clear();
00474 }
00475 
00476 
00477 void DF_LabelNode::Reset()
00478 {
00479   _depth = 0;
00480   _tag = 0;
00481 
00482   std::vector<DF_Attribute*> va;
00483   typedef std::map<std::string, DF_Attribute*>::const_iterator AI;
00484   for(AI p = _attributes.begin(); p!=_attributes.end(); p++)
00485     va.push_back(p->second);
00486 
00487   for(int i = 0, len = va.size(); i<len; i++) 
00488     delete va[i];
00489 
00490   _attributes.clear();
00491   _document = NULL;
00492   _father = NULL;
00493   _firstChild = NULL;
00494   _lastChild = NULL;
00495   _previous = NULL;
00496   _next = NULL;  
00497 }