00001 /*************************************************************************** 00002 * Copyright (C) 2007 by Ilya A. Volynets-Evenbakh * 00003 * ilya@total-knowledge.com * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program; if not, write to the * 00017 * Free Software Foundation, Inc., * 00018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00019 ***************************************************************************/ 00020 00021 #include <serverconfig/serverconfig.h> 00022 #include <iostream> 00023 #include <algorithm> 00024 00025 namespace container { 00026 namespace serverconfig { 00027 00028 Context::~Context() 00029 { 00030 for(ctxlist_t::iterator it=m_kids.begin(); it!=m_kids.end(); it++) { 00031 delete *it; 00032 } 00033 } 00034 00040 bool Context::process(ServerConfig& cfg, ConfigNode* node) 00041 { 00042 m_name=node->getName(); 00043 m_type=node->getType(); 00044 ConfigNode::childlist_t kids = cfg.getNodes(node); 00045 for(ConfigNode::childlist_t::iterator it=kids.begin(); 00046 it!=kids.end(); it++) 00047 { 00048 Context* ctx=getContext(**it); 00049 if(ctx) { 00050 addChildContext(ctx); 00051 if(!ctx->process(cfg, *it)) { 00052 std::cerr<< "Error loading context "<<ctx->getName()<<std::endl; 00053 return false; 00054 } 00055 } else { 00056 if(!setParam(**it)) { 00057 std::cerr<<"Failed setting parameter "<<(*it)->getType() 00058 <<" In context "<<getName()<<" of type "<<getType()<<std::endl; 00059 return false; 00060 } 00061 } 00062 } 00063 return true; 00064 } 00065 00066 00070 void Context::addChildContext(Context* ctx) 00071 { 00072 m_kids.push_back(ctx); 00073 } 00074 00075 class NodeNameComparator 00076 { 00077 std::string m_search; 00078 public: 00079 NodeNameComparator(const std::string& s) :m_search(s){} 00080 bool operator()(const ConfigNode& node) 00081 { return node.getName()==m_search;} 00082 }; 00083 00084 bool Context::CfgParamList::add(const ConfigNode& node) 00085 { 00086 if(m_flags&PARAM_SINGLE_OF_TYPE && ! empty()) { 00087 std::cerr<<"Error: parameter of type "<<node.getType()<<" was already set"; 00088 return false; 00089 } 00090 if(m_flags&PARAM_SINGLE_OF_NAME && 00091 std::find_if(begin(),end(),NodeNameComparator(node.getName()))!=end()) 00092 { 00093 std::cerr<<"Error: parameter with name"<<node.getName()<<" was already set"; 00094 return false; 00095 } 00096 push_back(node); 00097 return true; 00098 } 00099 00105 bool Context::setParam(const ConfigNode& node) 00106 { 00107 cfgparamlist_t ¶ms=this->m_params[node.getType()]; 00108 unsetparams_t& unsetParams=getUnsetParams(); 00109 unsetparams_t::iterator it=unsetParams.find(node.getType()); 00110 if(it!=unsetParams.end()) { 00111 params.m_flags=it->second.flags(); 00112 unsetParams.erase(it); 00113 } 00114 if(params.add(node)) 00115 return onSetParam(node); 00116 std::cerr<<"Error setting paramter "<<node.getType()<<" ("<<node.getName()<<')'<<std::endl; 00117 return false; 00118 } 00119 00123 const Context::cfgparamlist_t* Context::getParam(const std::string& type) const 00124 { 00125 params_t::const_iterator it=m_params.find(type); 00126 if(it==m_params.end()) 00127 return 0; 00128 return &it->second; 00129 } 00130 00131 00135 bool Context::complete() 00136 { 00137 unsetparams_t& unsetParams=getUnsetParams(); 00138 for(unsetparams_t::iterator it=unsetParams.begin();it!=unsetParams.end();) { 00139 const cfgparamlist_t* params; 00140 if(m_parent && it->second.inheritable()) { 00141 if((params=m_parent->getParam(it->first))) { 00142 //Have to increment _before_ calling setParam, 00143 //since setParam may erase current element, thus 00144 //invalidating current iterator. 00145 //At the same time I have to increment it _after_ 00146 //I used it to get any data I need 00147 it++; 00148 for(cfgparamlist_t::const_iterator it=params->begin(); 00149 it!=params->end(); it++) 00150 { 00151 setParam(*it); 00152 } 00153 continue; 00154 } 00155 } 00156 if(it->second.required()) { 00157 std::cerr<<"Parameter "<<it->first<<" must be set in context "<<getType()<<" ("<<getName()<<')'<<std::endl; 00158 return false; 00159 } 00160 it++; // see comments above... 00161 } 00162 if(!onPreComplete()) { 00163 std::cerr<<"Error in context setup "<<getType()<<" ("<<getName()<<')'<<std::endl; 00164 return false; 00165 } 00166 for(ctxlist_t::iterator it=m_kids.begin(); it!=m_kids.end(); it++){ 00167 if(!(*it)->complete()) { 00168 std::cerr<<"Error in context setup completion "<<(*it)->getType() 00169 <<" ("<<(*it)->getName()<<')'<<std::endl; 00170 return false; 00171 } 00172 } 00173 return onPostComplete(); 00174 } 00175 00176 bool Context::setString(const ConfigNode& node, std::string& dest) 00177 { 00178 util::param_t::const_iterator value=node.getAttrs().find("value"); 00179 if(value==node.getAttrs().end()) { 00180 std::cerr<<"No value specified"<<std::endl; 00181 return false; 00182 } 00183 dest=value->second; 00184 return true; 00185 } 00186 00187 } 00188 }