00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <pion/platform/VocabularyConfig.hpp>
00021 #include <boost/lexical_cast.hpp>
00022 #include <cstdlib>
00023
00024
00025 namespace pion {
00026 namespace platform {
00027
00028
00029
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
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
00052 if (m_vocabulary_node != NULL)
00053 return;
00054
00055
00056 ConfigManager::createConfigFile();
00057
00058 PION_LOG_INFO(m_logger, "Initializing new Vocabulary configuration file: " << m_config_file);
00059
00060
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
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
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
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
00100 saveConfigFile();
00101 }
00102
00103 void VocabularyConfig::openConfigFile(void)
00104 {
00105
00106 if (m_vocabulary_node != NULL)
00107 return;
00108
00109
00110 ConfigManager::openConfigFile();
00111
00112
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
00119 if (! getNodeId(m_vocabulary_node, m_vocabulary_id))
00120 throw EmptyVocabularyIdException(getConfigFile());
00121
00122
00123 getConfigOption(NAME_ELEMENT_NAME, m_name, m_vocabulary_node->children);
00124
00125
00126 getConfigOption(COMMENT_ELEMENT_NAME, m_comment, m_vocabulary_node->children);
00127
00128
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
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
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
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
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
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
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
00199 saveConfigFile();
00200 }
00201 }
00202
00203 void VocabularyConfig::setName(const std::string& new_name)
00204 {
00205
00206 m_name = new_name;
00207
00208
00209 if (m_vocabulary_node != NULL) {
00210 if (! updateConfigOption(NAME_ELEMENT_NAME, new_name, m_vocabulary_node))
00211 throw UpdateVocabularyException(getConfigFile());
00212
00213 saveConfigFile();
00214 }
00215 }
00216
00217 void VocabularyConfig::setComment(const std::string& new_comment)
00218 {
00219
00220 m_comment = new_comment;
00221
00222
00223 if (m_vocabulary_node != NULL) {
00224 if (! updateConfigOption(COMMENT_ELEMENT_NAME, new_comment, m_vocabulary_node))
00225 throw UpdateVocabularyException(getConfigFile());
00226
00227 saveConfigFile();
00228 }
00229 }
00230
00231 void VocabularyConfig::setLocked(bool b)
00232 {
00233
00234 m_is_locked = b;
00235
00236
00237 if (m_vocabulary_node != NULL) {
00238
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
00243 saveConfigFile();
00244 }
00245 }
00246
00247 void VocabularyConfig::setConfig(const xmlNodePtr config_ptr)
00248 {
00249
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
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
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
00272 if (m_vocabulary_node == NULL)
00273 throw ConfigNotOpenException(getConfigFile());
00274
00275 if (m_is_locked)
00276 throw VocabularyIsLockedException(getId());
00277
00278
00279 m_vocabulary.addTerm(new_term);
00280 m_signal_add_term(new_term);
00281
00282
00283
00284
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
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
00299 if (! addNewTermTypeConfig(new_term_node, new_term))
00300 throw AddTermConfigException(new_term.term_id);
00301
00302
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
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
00319 if (m_vocabulary_node == NULL)
00320 throw ConfigNotOpenException(getConfigFile());
00321
00322 if (m_is_locked)
00323 throw VocabularyIsLockedException(getId());
00324
00325
00326 m_vocabulary.updateTerm(t);
00327 m_signal_update_term(t);
00328
00329
00330
00331
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
00340 xmlNodePtr type_node = findConfigNodeByName(TYPE_ELEMENT_NAME,
00341 term_node->children);
00342 if (type_node == NULL) {
00343
00344
00345
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
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
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
00365 xmlUnsetProp(type_node, reinterpret_cast<const xmlChar*>(SIZE_ATTRIBUTE_NAME.c_str()));
00366 } else {
00367
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
00373 xmlAttrPtr format_attr_ptr = xmlHasProp(type_node, reinterpret_cast<const xmlChar*>(FORMAT_ATTRIBUTE_NAME.c_str()));
00374 if (format_attr_ptr == NULL) {
00375
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
00383 xmlUnsetProp(type_node, reinterpret_cast<const xmlChar*>(FORMAT_ATTRIBUTE_NAME.c_str()));
00384 } else {
00385
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
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
00396 xmlNodePtr comment_node = findConfigNodeByName(COMMENT_ELEMENT_NAME,
00397 term_node->children);
00398 if (comment_node == NULL) {
00399
00400
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
00409 xmlNodeSetContent(comment_node, reinterpret_cast<const xmlChar*>(xml_encode(t.term_comment).c_str()));
00410 }
00411
00412
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
00421 if (m_vocabulary_node == NULL)
00422 throw ConfigNotOpenException(getConfigFile());
00423
00424 if (m_is_locked)
00425 throw VocabularyIsLockedException(getId());
00426
00427
00428 m_vocabulary.removeTerm(term_id);
00429 m_signal_remove_term(term_id);
00430
00431
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
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
00451 out << "\t<" << TERM_ELEMENT_NAME << ' ' << ID_ATTRIBUTE_NAME << "=\""
00452 << t.term_id << "\">" << std::endl;
00453
00454
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
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
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
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
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
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
00497 if (new_term.term_type == Vocabulary::TYPE_CHAR) {
00498
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
00505 if (new_term.term_size == 0)
00506 new_term.term_size = 1;
00507 xmlFree(xml_char_ptr);
00508 }
00509 }
00510 }
00511
00512
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
00520 getConfigOption(COMMENT_ELEMENT_NAME, new_term.term_comment, config_ptr);
00521 }
00522
00523
00524 }
00525 }