platform/src/VocabularyConfig.cpp

00001 // ------------------------------------------------------------------------
00002 // Pion is a development platform for building Reactors that process Events
00003 // ------------------------------------------------------------------------
00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
00005 //
00006 // Pion is free software: you can redistribute it and/or modify it under the
00007 // terms of the GNU Affero General Public License as published by the Free
00008 // Software Foundation, either version 3 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Pion is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Affero General Public License
00017 // along with Pion.  If not, see <http://www.gnu.org/licenses/>.
00018 //
00019 
00020 #include <pion/platform/VocabularyConfig.hpp>
00021 #include <boost/lexical_cast.hpp>
00022 #include <cstdlib>
00023 
00024 
00025 namespace pion {        // begin namespace pion
00026 namespace platform {    // begin namespace platform (Pion Platform Library)
00027 
00028 
00029 // static members of VocabularyConfig
00030     
00031 const std::string           VocabularyConfig::DEFAULT_CONFIG_FILE = "vocabulary.xml";
00032 const std::string           VocabularyConfig::VOCABULARY_ELEMENT_NAME = "Vocabulary";
00033 const std::string           VocabularyConfig::LOCKED_ELEMENT_NAME = "Locked";
00034 const std::string           VocabularyConfig::TERM_ELEMENT_NAME = "Term";
00035 const std::string           VocabularyConfig::TYPE_ELEMENT_NAME = "Type";
00036 const std::string           VocabularyConfig::SIZE_ATTRIBUTE_NAME = "size";
00037 const std::string           VocabularyConfig::FORMAT_ATTRIBUTE_NAME = "format";
00038     
00039         
00040 // VocabularyConfig member functions
00041 
00042 VocabularyConfig::VocabularyConfig(void)
00043     : ConfigManager(DEFAULT_CONFIG_FILE),
00044     m_vocabulary_node(NULL), m_is_locked(false)
00045 {
00046     setLogger(PION_GET_LOGGER("pion.platform.VocabularyConfig"));
00047 }
00048 
00049 void VocabularyConfig::createConfigFile(void)
00050 {
00051     // just return if it's already open
00052     if (m_vocabulary_node != NULL)
00053         return;
00054     
00055     // create the file with "config" root element
00056     ConfigManager::createConfigFile();
00057     
00058     PION_LOG_INFO(m_logger, "Initializing new Vocabulary configuration file: " << m_config_file);
00059 
00060     // create a new vocabulary element
00061     m_vocabulary_node = xmlNewNode(NULL, reinterpret_cast<const xmlChar*>(VOCABULARY_ELEMENT_NAME.c_str()));
00062     if (m_vocabulary_node == NULL)
00063         throw InitializeConfigException(getConfigFile());
00064     if ((m_vocabulary_node=xmlAddChild(m_config_node_ptr,
00065                                        m_vocabulary_node)) == NULL)
00066     {
00067         xmlFreeNode(m_vocabulary_node);
00068         throw InitializeConfigException(getConfigFile());
00069     }
00070     if (xmlNewProp(m_vocabulary_node,
00071                    reinterpret_cast<const xmlChar*>(ID_ATTRIBUTE_NAME.c_str()),
00072                    reinterpret_cast<const xmlChar*>(m_vocabulary_id.c_str())) == NULL)
00073         throw InitializeConfigException(getConfigFile());
00074     
00075     // create a name child element
00076     if (! m_name.empty()) {
00077         if (xmlNewTextChild(m_vocabulary_node, NULL,
00078                             reinterpret_cast<const xmlChar*>(NAME_ELEMENT_NAME.c_str()),
00079                             reinterpret_cast<const xmlChar*>(m_name.c_str())) == NULL)
00080             throw InitializeConfigException(getConfigFile());
00081     }
00082     
00083     // create a comment child element
00084     if (! m_comment.empty()) {
00085         if (xmlNewTextChild(m_vocabulary_node, NULL,
00086                             reinterpret_cast<const xmlChar*>(COMMENT_ELEMENT_NAME.c_str()),
00087                             reinterpret_cast<const xmlChar*>(m_comment.c_str())) == NULL)
00088             throw InitializeConfigException(getConfigFile());
00089     }
00090     
00091     // create a locked child element
00092     if (m_is_locked) {
00093         if (xmlNewTextChild(m_vocabulary_node, NULL,
00094                             reinterpret_cast<const xmlChar*>(LOCKED_ELEMENT_NAME.c_str()),
00095                             reinterpret_cast<const xmlChar*>("true")) == NULL)
00096             throw InitializeConfigException(getConfigFile());
00097     }
00098 
00099     // save the new XML config file
00100     saveConfigFile();
00101 }
00102 
00103 void VocabularyConfig::openConfigFile(void)
00104 {
00105     // just return if it's already open
00106     if (m_vocabulary_node != NULL)
00107         return;
00108     
00109     // open the file and find the "config" root element
00110     ConfigManager::openConfigFile();
00111 
00112     // find the root "vocabulary" element
00113     m_vocabulary_node = findConfigNodeByName(VOCABULARY_ELEMENT_NAME,
00114                                              m_config_node_ptr->children);
00115     if (m_vocabulary_node == NULL)
00116         throw MissingVocabularyException(getConfigFile());
00117 
00118     // get the unique identifier for the Vocabulary
00119     if (! getNodeId(m_vocabulary_node, m_vocabulary_id))
00120         throw EmptyVocabularyIdException(getConfigFile());
00121     
00122     // find the "name" element
00123     getConfigOption(NAME_ELEMENT_NAME, m_name, m_vocabulary_node->children);
00124 
00125     // find the "comment" element
00126     getConfigOption(COMMENT_ELEMENT_NAME, m_comment, m_vocabulary_node->children);
00127     
00128     // find the "locked" element
00129     m_is_locked = false;
00130     std::string locked_option;
00131     if (getConfigOption(LOCKED_ELEMENT_NAME, locked_option,
00132                         m_vocabulary_node->children))
00133     {
00134         if (locked_option == "true")
00135             m_is_locked = true;
00136     }
00137 
00138     // load Vocabulary Terms
00139     for (xmlNodePtr cur_node = m_vocabulary_node->children;
00140          cur_node != NULL; cur_node = cur_node->next)
00141     {
00142         if (cur_node->type == XML_ELEMENT_NODE
00143             && xmlStrcmp(cur_node->name, reinterpret_cast<const xmlChar*>(TERM_ELEMENT_NAME.c_str()))==0)
00144         {
00145             // parse new term definition
00146             std::string new_term_id;
00147             if (! getNodeId(cur_node, new_term_id))
00148                 throw Vocabulary::EmptyTermIdException();
00149             Vocabulary::Term new_term(new_term_id);
00150             parseTermConfig(new_term, cur_node->children);
00151 
00152             // add the new term (finished parsing basic config)
00153             m_vocabulary.addTerm(new_term);
00154             m_signal_add_term(new_term);
00155             PION_LOG_DEBUG(m_logger, "Added Vocabulary Term: " << new_term.term_id);
00156         }
00157     }
00158     
00159     PION_LOG_INFO(m_logger, "Loaded Vocabulary configuration file: " << m_config_file);
00160 }
00161 
00162 bool VocabularyConfig::addNewTermTypeConfig(xmlNodePtr term_node, const Vocabulary::Term& t)
00163 {
00164     const std::string new_type_string(Vocabulary::getDataTypeAsString(t.term_type));
00165     xmlNodePtr new_type_node = xmlNewTextChild(term_node, NULL,
00166                                                reinterpret_cast<const xmlChar*>(TYPE_ELEMENT_NAME.c_str()),
00167                                                reinterpret_cast<const xmlChar*>(new_type_string.c_str()));
00168     if (new_type_node == NULL)
00169         return false;
00170     // set the size attribute of type if it is non-zero (or if type CHAR)
00171     if (t.term_size != 0 || t.term_type == Vocabulary::TYPE_CHAR) {
00172         std::string new_size_string(boost::lexical_cast<std::string>(t.term_size));
00173         if (t.term_size == 0 && t.term_type == Vocabulary::TYPE_CHAR)
00174             new_size_string = "1";
00175         if (xmlNewProp(new_type_node, reinterpret_cast<const xmlChar*>(SIZE_ATTRIBUTE_NAME.c_str()),
00176                        reinterpret_cast<const xmlChar*>(new_size_string.c_str())) == NULL)
00177             return false;
00178     }
00179     // set the format attribute if it is not empty
00180     if (! t.term_format.empty()) {
00181         if (xmlNewProp(new_type_node, reinterpret_cast<const xmlChar*>(FORMAT_ATTRIBUTE_NAME.c_str()),
00182                        reinterpret_cast<const xmlChar*>(t.term_format.c_str())) == NULL)
00183             return false;
00184     }
00185     return true;
00186 }
00187     
00188 void VocabularyConfig::setId(const std::string& new_id)
00189 {
00190     m_vocabulary_id = new_id;
00191     
00192     // update config file only if it is open
00193     if (m_vocabulary_node != NULL) {
00194         if (xmlSetProp(m_vocabulary_node,
00195                        reinterpret_cast<const xmlChar*>(ID_ATTRIBUTE_NAME.c_str()),
00196                        reinterpret_cast<const xmlChar*>(new_id.c_str())) == NULL)
00197             throw UpdateVocabularyException(getConfigFile());
00198         // save the new XML config file
00199         saveConfigFile();
00200     }
00201 }
00202 
00203 void VocabularyConfig::setName(const std::string& new_name)
00204 {
00205     // change descriptive name
00206     m_name = new_name;
00207     
00208     // update config file only if it is open
00209     if (m_vocabulary_node != NULL) {
00210         if (! updateConfigOption(NAME_ELEMENT_NAME, new_name, m_vocabulary_node))
00211             throw UpdateVocabularyException(getConfigFile());
00212         // save the new XML config file
00213         saveConfigFile();
00214     }
00215 }
00216 
00217 void VocabularyConfig::setComment(const std::string& new_comment)
00218 {
00219     // change comment option
00220     m_comment = new_comment;
00221     
00222     // update config file only if it is open
00223     if (m_vocabulary_node != NULL) {
00224         if (! updateConfigOption(COMMENT_ELEMENT_NAME, new_comment, m_vocabulary_node))
00225             throw UpdateVocabularyException(getConfigFile());
00226         // save the new XML config file
00227         saveConfigFile();
00228     }
00229 }
00230         
00231 void VocabularyConfig::setLocked(bool b)
00232 {
00233     // change locked setting
00234     m_is_locked = b;
00235     
00236     // update config file only if it is open
00237     if (m_vocabulary_node != NULL) {
00238         // note that setting the value to "" (empty) removes the node
00239         const std::string new_locked_value(m_is_locked ? "true" : "");
00240         if (! updateConfigOption(LOCKED_ELEMENT_NAME, new_locked_value, m_vocabulary_node))
00241             throw UpdateVocabularyException(getConfigFile());
00242         // save the new XML config file
00243         saveConfigFile();
00244     }
00245 }
00246 
00247 void VocabularyConfig::setConfig(const xmlNodePtr config_ptr)
00248 {
00249     // get the "Name" value
00250     std::string new_name;
00251     ConfigManager::getConfigOption(NAME_ELEMENT_NAME, new_name, config_ptr);
00252     if (new_name != m_name)
00253         setName(new_name);
00254 
00255     // get the "Comment" value
00256     std::string new_comment;
00257     ConfigManager::getConfigOption(COMMENT_ELEMENT_NAME, new_comment, config_ptr);
00258     if (new_comment != m_comment)
00259         setComment(new_comment);
00260 
00261     // get the "Locked" value
00262     std::string new_locked_str;
00263     ConfigManager::getConfigOption(LOCKED_ELEMENT_NAME, new_locked_str, config_ptr);
00264     const bool new_locked = (new_locked_str == "true");
00265     if (new_locked != m_is_locked)
00266         setLocked(new_locked);
00267 }
00268 
00269 void VocabularyConfig::addTerm(const Vocabulary::Term& new_term)
00270 {
00271     // make sure that the Vocabulary configuration file is open
00272     if (m_vocabulary_node == NULL)
00273         throw ConfigNotOpenException(getConfigFile());
00274     // make sure that the Vocabulary is not locked
00275     if (m_is_locked)
00276         throw VocabularyIsLockedException(getId());
00277         
00278     // add it to the memory structures
00279     m_vocabulary.addTerm(new_term);
00280     m_signal_add_term(new_term);
00281     
00282     // add it to the Vocabulary config file
00283     
00284     // create a new node for the term and add it to the XML config document
00285     xmlNodePtr new_term_node = xmlNewNode(NULL, reinterpret_cast<const xmlChar*>(TERM_ELEMENT_NAME.c_str()));
00286     if (new_term_node == NULL)
00287         throw AddTermConfigException(new_term.term_id);
00288     if ((new_term_node=xmlAddChild(m_vocabulary_node, new_term_node)) == NULL) {
00289         xmlFreeNode(new_term_node);
00290         throw AddTermConfigException(new_term.term_id);
00291     }
00292 
00293     // set the id attribute for the term element
00294     if (xmlNewProp(new_term_node, reinterpret_cast<const xmlChar*>(ID_ATTRIBUTE_NAME.c_str()),
00295                    reinterpret_cast<const xmlChar*>(new_term.term_id.c_str())) == NULL)
00296         throw AddTermConfigException(new_term.term_id);
00297 
00298     // add a type child element to the term 
00299     if (! addNewTermTypeConfig(new_term_node, new_term))
00300         throw AddTermConfigException(new_term.term_id);
00301 
00302     // add a comment child element to the term if it is not empty
00303     if (! new_term.term_comment.empty()) {
00304         if (xmlNewTextChild(new_term_node, NULL,
00305                             reinterpret_cast<const xmlChar*>(COMMENT_ELEMENT_NAME.c_str()),
00306                             reinterpret_cast<const xmlChar*>(new_term.term_comment.c_str())) == NULL)
00307             throw AddTermConfigException(new_term.term_id);
00308     }
00309     
00310     // save the new XML config file
00311     saveConfigFile();
00312     
00313     PION_LOG_DEBUG(m_logger, "Added Vocabulary Term: " << new_term.term_id);
00314 }
00315 
00316 void VocabularyConfig::updateTerm(const Vocabulary::Term& t)
00317 {
00318     // make sure that the Vocabulary configuration file is open
00319     if (m_vocabulary_node == NULL)
00320         throw ConfigNotOpenException(getConfigFile());
00321     // make sure that the Vocabulary is not locked
00322     if (m_is_locked)
00323         throw VocabularyIsLockedException(getId());
00324     
00325     // update the values in memory
00326     m_vocabulary.updateTerm(t);
00327     m_signal_update_term(t);
00328 
00329     // update it within the Vocabulary config file
00330     
00331     // find the term element in the XML config document
00332     xmlNodePtr term_node = findConfigNodeByAttr(TERM_ELEMENT_NAME,
00333                                                 ID_ATTRIBUTE_NAME,
00334                                                 t.term_id,
00335                                                 m_vocabulary_node->children);
00336     if (term_node == NULL)
00337         throw UpdateTermConfigException(t.term_id);
00338     
00339     // find the existing "type" node (if any)
00340     xmlNodePtr type_node = findConfigNodeByName(TYPE_ELEMENT_NAME,
00341                                                 term_node->children);
00342     if (type_node == NULL) {
00343         
00344         // no type node currently exists
00345         // add a new one, so long as the new type is not "NULL"
00346         if (t.term_type != Vocabulary::TYPE_NULL) {
00347             if (! addNewTermTypeConfig(term_node, t))
00348                 throw UpdateTermConfigException(t.term_id);
00349         }
00350         
00351     } else {
00352         
00353         // look for the existing size attribute
00354         const std::string new_size_string(boost::lexical_cast<std::string>(t.term_size));
00355         xmlAttrPtr size_attr_ptr = xmlHasProp(type_node, reinterpret_cast<const xmlChar*>(SIZE_ATTRIBUTE_NAME.c_str()));
00356         if (size_attr_ptr == NULL) {
00357             // no size attribute currently defined -> add a new one if size != 0
00358             if (t.term_size != 0) {
00359                 if (xmlNewProp(type_node, reinterpret_cast<const xmlChar*>(SIZE_ATTRIBUTE_NAME.c_str()),
00360                                reinterpret_cast<const xmlChar*>(new_size_string.c_str())) == NULL)
00361                     throw UpdateTermConfigException(t.term_id);
00362             }
00363         } else if (t.term_size == 0) {
00364             // size is being changed to "0" -> remove the existing attribute
00365             xmlUnsetProp(type_node, reinterpret_cast<const xmlChar*>(SIZE_ATTRIBUTE_NAME.c_str()));
00366         } else {
00367             // update the value of the existing size attribute
00368             xmlSetProp(type_node, reinterpret_cast<const xmlChar*>(SIZE_ATTRIBUTE_NAME.c_str()),
00369                        reinterpret_cast<const xmlChar*>(new_size_string.c_str()));
00370         }
00371 
00372         // look for existing format attribute
00373         xmlAttrPtr format_attr_ptr = xmlHasProp(type_node, reinterpret_cast<const xmlChar*>(FORMAT_ATTRIBUTE_NAME.c_str()));
00374         if (format_attr_ptr == NULL) {
00375             // no format attribute currently defined -> add one if not empty
00376             if (! t.term_format.empty()) {
00377                 if (xmlNewProp(type_node, reinterpret_cast<const xmlChar*>(FORMAT_ATTRIBUTE_NAME.c_str()),
00378                                reinterpret_cast<const xmlChar*>(t.term_format.c_str())) == NULL)
00379                     throw UpdateTermConfigException(t.term_id);
00380             }
00381         } else if (t.term_format.empty()) {
00382             // format is being removed -> remove the existing attribute
00383             xmlUnsetProp(type_node, reinterpret_cast<const xmlChar*>(FORMAT_ATTRIBUTE_NAME.c_str()));
00384         } else {
00385             // update the value of the existing format attribute
00386             xmlSetProp(type_node, reinterpret_cast<const xmlChar*>(FORMAT_ATTRIBUTE_NAME.c_str()),
00387                        reinterpret_cast<const xmlChar*>(t.term_format.c_str()));
00388         }
00389             
00390         // update the content of the type attribute
00391         const std::string new_type_string(Vocabulary::getDataTypeAsString(t.term_type));
00392         xmlNodeSetContent(type_node, reinterpret_cast<const xmlChar*>(new_type_string.c_str()));
00393     }
00394 
00395     // find the existing "comment" node (if any)
00396     xmlNodePtr comment_node = findConfigNodeByName(COMMENT_ELEMENT_NAME,
00397                                                    term_node->children);
00398     if (comment_node == NULL) {
00399         // no comment node currently exists
00400         // add a new one, so long as the new comment is not empty
00401         if (! t.term_comment.empty()) {
00402             if (xmlNewTextChild(term_node, NULL,
00403                                 reinterpret_cast<const xmlChar*>(COMMENT_ELEMENT_NAME.c_str()),
00404                                 reinterpret_cast<const xmlChar*>(t.term_comment.c_str())) == NULL)
00405                 throw UpdateTermConfigException(t.term_id);
00406         }
00407     } else {
00408         // change the value for the existing comment node
00409         xmlNodeSetContent(comment_node, reinterpret_cast<const xmlChar*>(xml_encode(t.term_comment).c_str()));
00410     }
00411     
00412     // save the new XML config file
00413     saveConfigFile();
00414     
00415     PION_LOG_DEBUG(m_logger, "Updated Vocabulary Term: " << t.term_id);
00416 }
00417 
00418 void VocabularyConfig::removeTerm(const std::string& term_id)
00419 {
00420     // make sure that the Vocabulary configuration file is open
00421     if (m_vocabulary_node == NULL)
00422         throw ConfigNotOpenException(getConfigFile());
00423     // make sure that the Vocabulary is not locked
00424     if (m_is_locked)
00425         throw VocabularyIsLockedException(getId());
00426     
00427     // remove the Term from our memory structures
00428     m_vocabulary.removeTerm(term_id);
00429     m_signal_remove_term(term_id);
00430     
00431     // remove it from the Vocabulary config file
00432     xmlNodePtr term_node = findConfigNodeByAttr(TERM_ELEMENT_NAME,
00433                                                 ID_ATTRIBUTE_NAME,
00434                                                 term_id,
00435                                                 m_vocabulary_node->children);
00436     if (term_node == NULL)
00437         throw RemoveTermConfigException(term_id);
00438     xmlUnlinkNode(term_node);
00439     xmlFreeNode(term_node);
00440     
00441     // save the new XML config file
00442     saveConfigFile();
00443     
00444     PION_LOG_DEBUG(m_logger, "Removed Vocabulary Term: " << term_id);
00445 }
00446 
00447 void VocabularyConfig::writeTermConfigXML(std::ostream& out,
00448                                           const Vocabulary::Term& t)
00449 {
00450     // begin Term XML
00451     out << "\t<" << TERM_ELEMENT_NAME << ' ' << ID_ATTRIBUTE_NAME << "=\""
00452         << t.term_id << "\">" << std::endl;
00453 
00454     // Type element
00455     out << "\t\t<" << TYPE_ELEMENT_NAME;
00456     if (t.term_type == Vocabulary::TYPE_CHAR)
00457         out << ' ' << SIZE_ATTRIBUTE_NAME << "=\"" << t.term_size << '\"';
00458     else if (! t.term_format.empty())
00459         out << ' ' << FORMAT_ATTRIBUTE_NAME << "=\"" << t.term_format << '\"';
00460     out << '>' << Vocabulary::getDataTypeAsString(t.term_type)
00461         << "</" << TYPE_ELEMENT_NAME << '>' << std::endl;
00462     
00463     // Comment element
00464     if (! t.term_comment.empty()) {
00465         out << "\t\t<" << COMMENT_ELEMENT_NAME << '>' << xml_encode(t.term_comment)
00466             << "</" << COMMENT_ELEMENT_NAME << '>' << std::endl;
00467     }
00468     
00469     // end Term XML
00470     out << "\t</" << TERM_ELEMENT_NAME << '>' << std::endl;
00471 }
00472 
00473 void VocabularyConfig::parseTermConfig(Vocabulary::Term& new_term,
00474                                        const xmlNodePtr config_ptr)
00475 {
00476     xmlChar *xml_char_ptr;
00477     
00478     // find the existing "type" node (if any)
00479     xmlNodePtr type_node = findConfigNodeByName(TYPE_ELEMENT_NAME, config_ptr);
00480     if (type_node == NULL) {
00481         new_term.term_type = Vocabulary::TYPE_NULL;
00482     } else {
00483         // found a type node (if not found we can leave it as "NULL" (the default)
00484         xml_char_ptr = xmlNodeGetContent(type_node);
00485         if (xml_char_ptr == NULL || xml_char_ptr[0]=='\0') {
00486             if (xml_char_ptr != NULL)
00487                 xmlFree(xml_char_ptr);
00488             throw EmptyTypeException(new_term.term_id);
00489         }
00490         
00491         // set the term's data type
00492         const std::string new_term_type(reinterpret_cast<char*>(xml_char_ptr));
00493         xmlFree(xml_char_ptr);
00494         new_term.term_type = Vocabulary::parseDataType(new_term_type);
00495         
00496         // check for "size" attribute only if type is "char"
00497         if (new_term.term_type == Vocabulary::TYPE_CHAR) {
00498             // use a default size of '1' for char data type
00499             new_term.term_size = 1;
00500             xml_char_ptr = xmlGetProp(type_node, reinterpret_cast<const xmlChar*>(SIZE_ATTRIBUTE_NAME.c_str()));
00501             if (xml_char_ptr != NULL) {
00502                 if (xml_char_ptr[0] != '\0')
00503                     new_term.term_size = strtoul(reinterpret_cast<char*>(xml_char_ptr), NULL, 10);
00504                 // make sure it is not equal to 0 (change to 1 if it is)
00505                 if (new_term.term_size == 0)
00506                     new_term.term_size = 1;
00507                 xmlFree(xml_char_ptr);
00508             }
00509         }
00510     }
00511     
00512     // check for "format" attribute
00513     xml_char_ptr = xmlGetProp(type_node, reinterpret_cast<const xmlChar*>(FORMAT_ATTRIBUTE_NAME.c_str()));
00514     if (xml_char_ptr != NULL) {
00515         new_term.term_format = reinterpret_cast<char*>(xml_char_ptr);
00516         xmlFree(xml_char_ptr);
00517     }               
00518     
00519     // find the existing "comment" node (if any)
00520     getConfigOption(COMMENT_ELEMENT_NAME, new_term.term_comment, config_ptr);
00521 }
00522 
00523     
00524 }   // end namespace platform
00525 }   // end namespace pion

Generated on Wed Apr 13 16:38:34 2011 for pion-platform by  doxygen 1.4.7