00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "tools/schema/tag.hpp"
00022
00023 #include "config.hpp"
00024 #include "foreach.hpp"
00025 namespace schema_validation{
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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
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
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
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
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
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 }