tools/schema/tag.cpp

Go to the documentation of this file.
00001 /* $Id: tag.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2011 - 2012 by Sytyi Nick <nsytyi@gmail.com>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 /**
00017  * @file
00018  * Implementation of tag.hpp.
00019  */
00020 
00021 #include "tools/schema/tag.hpp"
00022 
00023 #include "config.hpp"
00024 #include "foreach.hpp"
00025 namespace schema_validation{
00026 
00027 /*WIKI
00028  * @begin{parent}{name="wml_schema/tag/"}
00029  * @begin{tag}{name="key"}{min=0}{max=-1}
00030  * @begin{table}{config}
00031  *     name & string & &              The name of key. $
00032  *     type & string & &              The type of key value. $
00033  *     default & string & &        The default value of the key. $
00034  *     mandatory & string & &   Shows if key is mandatory $
00035  * @end{table}
00036  * @end{tag}{name="key"}
00037  * @end{parent}{name="wml_schema/tag/"}
00038  */
00039 
00040  class_key::class_key(const config & cfg)
00041     : name_(cfg["name"].str())
00042     , type_(cfg["type"].str())
00043     , default_()
00044     , mandatory_(false)
00045  {
00046      if (cfg.has_attribute("mandatory")){
00047          mandatory_ = cfg["mandatory"].to_bool();
00048      }else{
00049          if (cfg.has_attribute("default")){
00050              default_= cfg["default"].str();
00051          }
00052      }
00053  }
00054 void class_key::print(std::ostream& os,int level) const {
00055     std::string s;
00056     for (int j=0;j<level;j++){
00057         s.append(" ");
00058     }
00059     os << s << "[key]\n"
00060             << s << "    name=\""<< name_ <<"\"\n"
00061             << s << "    type=\""<< type_ <<"\"\n";
00062     if (is_mandatory()){
00063         os << s << "    mandatory=\"true\"\n";
00064     }else{
00065         os << s <<"    default="<< default_ <<"\n";
00066     }
00067     os << s << "[/key]\n";
00068 }
00069 class_tag::class_tag(const config & cfg)
00070     : name_(cfg["name"].str())
00071     , min_(cfg["min"].to_int())
00072     , max_(cfg["max"].to_int())
00073     , super_("")
00074     , tags_()
00075     , keys_()
00076     , links_()
00077 {
00078         if (max_ < 0){
00079             max_ = INT_MAX;
00080         }
00081         if (cfg.has_attribute("super")){
00082             super_ = cfg["super"].str();
00083         }
00084         foreach (const config &child, cfg.child_range("tag")) {
00085             class_tag child_tag (child);
00086             add_tag(child_tag);
00087         }
00088         foreach (const config &child, cfg.child_range("key")) {
00089             class_key child_key (child);
00090             add_key(child_key);
00091         }
00092         foreach (const config &link, cfg.child_range("link")) {
00093             std::string link_name = link["name"].str();
00094             add_link(link_name);
00095         }
00096 }
00097 
00098 void class_tag::print(std::ostream& os){
00099     printl(os,4,4);
00100 }
00101 
00102 void class_tag::add_link(const std::string &link){
00103     std::string::size_type pos_last = link.rfind('/');
00104     //if (pos_last == std::string::npos) return;
00105     std::string name_link = link.substr(pos_last+1,link.length());
00106     links_.insert(std::pair<std::string,std::string>(name_link,link));
00107 }
00108 
00109 const class_key * class_tag::find_key(const std::string &name) const{
00110     key_map::const_iterator it_keys = keys_.find(name);
00111     if ( it_keys!= keys_.end() ){
00112         return &(it_keys->second);
00113     }
00114     return NULL;
00115 }
00116 
00117 const std::string * class_tag::find_link(const std::string &name) const{
00118     link_map::const_iterator it_links = links_.find(name);
00119     if ( it_links!= links_.end() ){
00120         return &(it_links->second);
00121     }
00122     return NULL;
00123 }
00124 
00125 const class_tag * class_tag::find_tag(const std::string &fullpath,
00126                                        const class_tag &root) const{
00127      if (fullpath.empty()) return NULL;
00128      std::string::size_type pos = fullpath.find('/');
00129      std::string name;
00130      std::string next_path;
00131      if (pos != std::string::npos) {
00132          name = fullpath.substr(0,pos);
00133          next_path = fullpath.substr(pos+1,fullpath.length());
00134      }else{
00135          name = fullpath;
00136      }
00137      tag_map::const_iterator it_tags = tags_.find(name);
00138      if (it_tags != tags_.end()){
00139          if (next_path.empty()){
00140              return &(it_tags->second);
00141                  }else{
00142              return it_tags->second.find_tag(next_path,root);
00143          }
00144      }
00145      link_map::const_iterator it_links = links_.find(name);
00146      if (it_links != links_.end()){
00147          return root.find_tag(it_links->second + "/" +next_path,root);
00148      }
00149      return NULL;
00150 
00151  }
00152 
00153 void class_tag::expand_all(class_tag &root){
00154     for (tag_map::iterator i = tags_.begin(); i!= tags_.end(); ++i){
00155         i->second.expand(root);
00156         i->second.expand_all(root);
00157     }
00158 }
00159 void class_tag::remove_keys_by_type (const std::string & type){
00160     key_iterator i= keys_.begin ();
00161     while(i != keys_.end()) {
00162         if(i->second.get_type() == type) {
00163             keys_.erase(i++);
00164         } else {
00165             ++i;
00166         }
00167     }
00168     for (tag_iterator t = tags_.begin(); t!=tags_.end();++t){
00169         t->second.remove_keys_by_type(type);
00170     }
00171 }
00172 
00173 /*WIKI
00174  * @begin{parent}{name="wml_schema/"}
00175  * @begin{tag}{name="tag"}{min=0}{max=1}
00176  * @begin{table}{config}
00177  *     name & string & &          The name of tag. $
00178  *     min & int & &           The min number of occurences. $
00179  *     max & int & &           The max number of occurences. $
00180  *     super & string & "" &   The super-tag of this tag $
00181  * @end{table}
00182  * @begin{tag}{name="link"}{min=0}{max=-1}
00183  * @begin{table}{config}
00184  *     name & string & &          The name of link. $
00185  * @end{table}
00186  * @end{tag}{name="link"}
00187  * @begin{tag}{name="tag"}{min=0}{max=-1}{super="wml_schema/tag"}
00188  * @end{tag}{name="tag"}
00189  * @end{tag}{name="tag"}
00190  * @begin{tag}{name="type"}{min=0}{max=-1}
00191  * @begin{table}{config}
00192  *     name & string & &          The name of type. $
00193  *     value & string & &         The value of the type, regex. $
00194  * @end{table}
00195  * @end{tag}{name="type"}
00196  * @end{parent}{name="wml_schema/"}
00197  */
00198 void class_tag::printl(std::ostream &os,int level, int step){
00199 
00200     std::string s;
00201     for (int j=0;j<level;j++){
00202         s.append(" ");
00203     }
00204     os << s << "[tag]\n"
00205             << s <<"    name=\""<< name_ <<"\"\n"
00206             << s <<"    min=\""<< min_ <<"\"\n"
00207             << s <<"    max=\""<< max_ <<"\"\n";
00208     if (! super_.empty() ){
00209         os<< s <<"    super=\""<< super_ <<"\"\n";
00210     }
00211     for (tag_map::iterator i = tags_.begin();
00212     i != tags_.end(); ++i ){
00213         i->second.printl(os,level+step,step);
00214     }
00215     for (link_map::iterator i = links_.begin();
00216     i != links_.end(); ++i ){
00217         os << s << "" << "[link]\n"
00218                 << s << "" << "    name=\"" <<i->second << "\"\n"
00219                 << s << "" << "[/link]\n";
00220     }
00221     for (key_map::iterator i = keys_.begin();
00222     i != keys_.end(); ++i ){
00223         i->second.print(os,level+step);
00224     }
00225     os<< s << "[/tag]\n";
00226 }
00227 
00228  class_tag * class_tag::find_tag(const std::string &fullpath,
00229                                        class_tag &root) {
00230      if (fullpath.empty()) return NULL;
00231      std::string::size_type pos = fullpath.find('/');
00232      std::string name;
00233      std::string next_path;
00234      if (pos != std::string::npos) {
00235          name = fullpath.substr(0,pos);
00236          next_path = fullpath.substr(pos+1,fullpath.length());
00237      }else{
00238          name = fullpath;
00239      }
00240 
00241      tag_map::iterator it_tags = tags_.find(name);
00242      if (it_tags != tags_.end()){
00243          if (next_path.empty()){
00244              return &(it_tags->second);
00245                  }else{
00246              return it_tags->second.find_tag(next_path,root);
00247          }
00248      }
00249      link_map::iterator it_links = links_.find(name);
00250      if (it_links != links_.end()){
00251          return root.find_tag(it_links->second +"/" +next_path,root);
00252      }
00253      return NULL;
00254 
00255  }
00256 // class_tag & class_tag::operator= (class_tag const& t){
00257 //   if (&t != this){
00258 //       name_ = t.name_;
00259 //       min_ = t.min_;
00260 //       max_ = t.max_;
00261 //       super_ = t.super_;
00262 //       tags_ = t.tags_;
00263 //       keys_ = t.keys_;
00264 //       links_ = t.links_;
00265 //   }
00266 //   return *this;
00267 // }
00268 
00269 void class_tag::add_tag(const std::string &path, const class_tag &tag,
00270                         class_tag &root){
00271     if ( path.empty() || path == "/" ){
00272         tag_map::iterator it = tags_.find(tag.name_);
00273         if (it == tags_.end()){
00274             tags_.insert(tag_map_value(tag.name_,tag));
00275         }else{
00276             it->second.set_min(tag.min_);
00277             it->second.set_max(tag.max_);
00278             it->second.add_tags(tag.tags_);
00279             it->second.add_keys(tag.keys_);
00280             it->second.add_links(tag.links_);
00281         }
00282         links_.erase (tag.get_name ());
00283         return ;
00284     }
00285     std::string::size_type pos = path.find('/');
00286     std::string name = path.substr(0,pos);
00287     std::string next_path = path.substr(pos+1,path.length());
00288 
00289     link_map::const_iterator it_links= links_.find(name);
00290     if (it_links != links_.end()){
00291         root.add_tag(it_links->second + "/" + next_path,tag,root);
00292     }
00293     tag_map::iterator it_tags = tags_.find(name);
00294     if (it_tags == tags_.end()){
00295         class_tag subtag;
00296         subtag.set_name(name);
00297         subtag.add_tag(next_path,tag,root);
00298         tags_.insert(tag_map_value(name,subtag));
00299         return;
00300     }
00301     it_tags->second.add_tag(next_path,tag,root);
00302 }
00303 
00304 void class_tag::append_super(const class_tag &tag,const std::string & path){
00305     add_keys(tag.keys_);
00306     add_links(tag.links_);
00307     for (tag_map::const_iterator i = tag.tags_.begin();i!=tag.tags_.end();++i){
00308         links_.erase(i->first);
00309         add_link(path + "/" + i->first);
00310 
00311     }
00312 }
00313 
00314 void class_tag::expand(class_tag &root){
00315     if (! super_.empty()){
00316         class_tag * super_tag = root.find_tag(super_,root);
00317         if (super_tag){
00318             if (super_tag != this){
00319                 super_tag->expand(root);
00320                 append_super(*super_tag,super_);
00321                 super_.clear();
00322             }else{
00323                 std::cerr << "the same" << super_tag->name_ <<"\n";
00324             }
00325         }
00326     }
00327 }
00328 }//namespace schema_generator
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:13 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs