platform/src/VocabularyManager.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/VocabularyManager.hpp>
00021 
00022 
00023 namespace pion {        // begin namespace pion
00024 namespace platform {    // begin namespace platform (Pion Platform Library)
00025 
00026 
00027 // static members of VocabularyManager
00028 
00029 const std::string           VocabularyManager::DEFAULT_CONFIG_FILE = "vocabularies.xml";
00030 const std::string           VocabularyManager::DEFAULT_VOCABULARY_PATH = ".";
00031 const std::string           VocabularyManager::VOCABULARY_PATH_ELEMENT_NAME = "VocabularyPath";
00032 const std::string           VocabularyManager::VOCABULARY_CONFIG_ELEMENT_NAME = "VocabularyConfig";
00033 const std::string           VocabularyManager::VOCABULARIES_PERMISSION_TYPE = "Vocabularies";
00034 
00035 
00036 // VocabularyManager member functions
00037 
00038 VocabularyManager::VocabularyManager(void)
00039     : ConfigManager(DEFAULT_CONFIG_FILE),
00040     m_vocab_path(DEFAULT_VOCABULARY_PATH)
00041 {
00042     setLogger(PION_GET_LOGGER("pion.platform.VocabularyManager"));
00043 }
00044 
00045 void VocabularyManager::createConfigFile(void)
00046 {
00047     boost::mutex::scoped_lock manager_lock(m_mutex);
00048     
00049     // just return if it's already open
00050     if (configIsOpen())
00051         return;
00052     
00053     // create the file with "config" root element
00054     ConfigManager::createConfigFile();
00055     
00056     PION_LOG_INFO(m_logger, "Initializing new global Vocabulary configuration file: " << m_config_file);
00057 
00058     // update the vocabulary path now that we know where the config file is located
00059     // this is just to resolve relative vocabulary paths
00060     m_vocab_path = ConfigManager::resolveRelativePath(getVocabularyPath());
00061     
00062     // add the current vocabulary path to the config file
00063     ConfigManager::updateConfigOption(VOCABULARY_PATH_ELEMENT_NAME,
00064                                       getVocabularyPath(),
00065                                       m_config_node_ptr);
00066 
00067     // save the new XML config file
00068     saveConfigFile();
00069 }
00070     
00071 void VocabularyManager::openConfigFile(void)
00072 {
00073     boost::mutex::scoped_lock manager_lock(m_mutex);
00074     
00075     // just return if it's already open
00076     if (configIsOpen())
00077         return;
00078     
00079     // open the file and find the "config" root element
00080     ConfigManager::openConfigFile();
00081 
00082     // get the vocabulary path
00083     if (! ConfigManager::getConfigOption(VOCABULARY_PATH_ELEMENT_NAME, m_vocab_path,
00084                                          m_config_node_ptr->children))
00085         throw MissingVocabularyPathException(getConfigFile());
00086     
00087     // resolve relative vocabulary paths
00088     m_vocab_path = ConfigManager::resolveRelativePath(getVocabularyPath());
00089     
00090     // Step through and load Vocabulary config files
00091     xmlNodePtr config_node = m_config_node_ptr->children;
00092     while ( (config_node = ConfigManager::findConfigNodeByName(VOCABULARY_CONFIG_ELEMENT_NAME, config_node)) != NULL)
00093     {
00094         // get the unique identifier for the Vocabulary
00095         std::string vocab_id;
00096         if (! getNodeId(config_node, vocab_id))
00097             throw VocabularyConfig::EmptyVocabularyIdException(getConfigFile());
00098 
00099         // make sure it has not already been loaded
00100         if (m_vocab_map.find(vocab_id) != m_vocab_map.end())
00101             throw DuplicateVocabularyException(vocab_id);
00102 
00103         // get the name of the file that contains the Vocabulary's configuration
00104         xmlChar *xml_char_ptr = xmlNodeGetContent(config_node);
00105         if (xml_char_ptr == NULL || xml_char_ptr[0]=='\0') {
00106             if (xml_char_ptr != NULL)
00107                 xmlFree(xml_char_ptr);
00108             throw EmptyVocabularyConfigException(getConfigFile());
00109         }
00110         const std::string vocab_file(reinterpret_cast<char*>(xml_char_ptr));
00111         xmlFree(xml_char_ptr);
00112 
00113         // open and parse the Vocabulary configuration file
00114         VocabularyConfigPtr new_config(new VocabularyConfig());
00115         new_config->setConfigFile(resolveRelativePath(vocab_file));
00116         new_config->openConfigFile();
00117         
00118         // add it to the vocabulary map and bind it
00119         m_vocab_map.insert(std::make_pair(vocab_id, new_config));
00120         new_config->bind(m_vocabulary);
00121         
00122         // step to the next Vocabulary configuration
00123         config_node = config_node->next;
00124     }
00125     
00126     // unlock class mutex to prevent deadlock
00127     manager_lock.unlock();
00128 
00129     // notify everyone that the vocabulary was updated
00130     PION_LOG_INFO(m_logger, "Loaded global Vocabulary configuration file: " << m_config_file);
00131     boost::mutex::scoped_lock signal_lock(m_signal_mutex);
00132     m_signal_vocabulary_updated();
00133 }
00134     
00135 bool VocabularyManager::writeConfigXML(std::ostream& out,
00136                                        const std::string& vocab_id) const
00137 {
00138     boost::mutex::scoped_lock manager_lock(m_mutex);
00139     
00140     // find the VocabularyConfig object
00141     VocabularyMap::const_iterator vocab_iterator = m_vocab_map.find(vocab_id);
00142     if (vocab_iterator == m_vocab_map.end())
00143         return false;
00144     
00145     // found it
00146     ConfigManager::writeConfigXMLHeader(out);
00147     vocab_iterator->second->writeConfigXML(out);
00148     return true;
00149 }
00150     
00151 bool VocabularyManager::writeTermConfigXML(std::ostream& out,
00152                                            const std::string& term_id) const
00153 {
00154     boost::mutex::scoped_lock manager_lock(m_mutex);
00155 
00156     Vocabulary::TermRef term_ref = m_vocabulary.findTerm(term_id);
00157     if (term_ref == Vocabulary::UNDEFINED_TERM_REF)
00158         return false;
00159 
00160     ConfigManager::writeBeginPionConfigXML(out);
00161     VocabularyConfig::writeTermConfigXML(out, m_vocabulary[term_ref]);
00162     ConfigManager::writeEndPionConfigXML(out);
00163 
00164     return true;
00165 }
00166     
00167 void VocabularyManager::writeTermConfigXML(std::ostream& out) const
00168 {
00169     ConfigManager::writeBeginPionConfigXML(out);
00170     boost::mutex::scoped_lock manager_lock(m_mutex);
00171     for (Vocabulary::TermRef ref = 1; ref <= m_vocabulary.size(); ++ref) {
00172         if (m_vocabulary[ref].term_ref != Vocabulary::UNDEFINED_TERM_REF) {
00173             VocabularyConfig::writeTermConfigXML(out, m_vocabulary[ref]);
00174         }
00175     }
00176     ConfigManager::writeEndPionConfigXML(out);
00177 }
00178     
00179 void VocabularyManager::addVocabulary(const std::string& vocab_id,
00180                                       const std::string& vocab_name,
00181                                       const std::string& vocab_comment)
00182 {
00183     boost::mutex::scoped_lock manager_lock(m_mutex);
00184 
00185     // make sure that the Vocabulary configuration file is open
00186     if (! configIsOpen())
00187         throw ConfigNotOpenException(getConfigFile());
00188 
00189     // make sure it has not already been loaded
00190     if (m_vocab_map.find(vocab_id) != m_vocab_map.end())
00191         throw DuplicateVocabularyException(vocab_id);
00192 
00193     // create a unique filename and open it up
00194     const std::string file_name(ConfigManager::createFilename(m_vocab_path));
00195     VocabularyConfigPtr new_config(new VocabularyConfig());
00196     new_config->setId(vocab_id);
00197     new_config->setName(vocab_name);
00198     new_config->setComment(vocab_comment);
00199     new_config->setConfigFile(file_name);
00200     new_config->createConfigFile();
00201     
00202     // add it to the vocabulary map and bind it
00203     m_vocab_map.insert(std::make_pair(vocab_id, new_config));
00204     new_config->bind(m_vocabulary);
00205 
00206     // add an entry for it to the config file
00207     xmlNodePtr new_node = xmlNewTextChild(m_config_node_ptr, NULL,
00208                                           reinterpret_cast<const xmlChar*>(VOCABULARY_CONFIG_ELEMENT_NAME.c_str()),
00209                                           reinterpret_cast<const xmlChar*>(file_name.c_str()));
00210     if (new_node == NULL)
00211         throw AddVocabularyConfigException(vocab_id);
00212     
00213     // set the id attribute for the VocabularyConfig element
00214     if (xmlNewProp(new_node, reinterpret_cast<const xmlChar*>(ID_ATTRIBUTE_NAME.c_str()),
00215                    reinterpret_cast<const xmlChar*>(vocab_id.c_str())) == NULL)
00216         throw AddVocabularyConfigException(vocab_id);
00217     
00218     // save the new XML config file
00219     saveConfigFile();
00220     
00221     // unlock class mutex to prevent deadlock
00222     manager_lock.unlock();
00223     
00224     // notify everyone that the vocabulary was updated
00225     PION_LOG_DEBUG(m_logger, "Added new Vocabulary: " << vocab_id);
00226     boost::mutex::scoped_lock signal_lock(m_signal_mutex);
00227     m_signal_vocabulary_updated();
00228 }
00229 
00230 void VocabularyManager::addVocabulary(const std::string& vocab_id,
00231                                       const char *content_buf,
00232                                       std::size_t content_length)
00233 {
00234     std::string vocab_name;
00235     std::string vocab_comment;
00236 
00237     // extract the XML config info from the content buffer
00238     xmlNodePtr config_ptr = ConfigManager::createResourceConfig(VocabularyConfig::getVocabularyElementName(),
00239                                                                 content_buf, content_length);
00240     if (config_ptr != NULL) {
00241         // get the "Name" value
00242         ConfigManager::getConfigOption(NAME_ELEMENT_NAME, vocab_name, config_ptr);
00243         // get the "Comment" value
00244         ConfigManager::getConfigOption(COMMENT_ELEMENT_NAME, vocab_comment, config_ptr);
00245         xmlFreeNodeList(config_ptr);
00246     }
00247     
00248     // call addVocabulary() to do the real work
00249     addVocabulary(vocab_id, vocab_name, vocab_comment);
00250 }
00251 
00252 void VocabularyManager::removeVocabulary(const std::string& vocab_id)
00253 {
00254     boost::mutex::scoped_lock manager_lock(m_mutex);
00255     
00256     // make sure that the Vocabulary configuration file is open
00257     if (! configIsOpen())
00258         throw ConfigNotOpenException(getConfigFile());
00259     
00260     // remove the Vocabulary from memory & remove the config file
00261     VocabularyMap::iterator vocab_iterator = m_vocab_map.find(vocab_id);
00262     if (vocab_iterator == m_vocab_map.end())
00263         throw VocabularyNotFoundException(vocab_id);
00264     vocab_iterator->second->removeConfigFile();
00265     m_vocab_map.erase(vocab_iterator);
00266     
00267     // remove it from the Vocabulary config file
00268     xmlNodePtr config_node = findConfigNodeByAttr(VOCABULARY_CONFIG_ELEMENT_NAME,
00269                                                   ID_ATTRIBUTE_NAME,
00270                                                   vocab_id,
00271                                                   m_config_node_ptr->children);
00272     if (config_node == NULL)
00273         throw RemoveVocabularyConfigException(vocab_id);
00274     xmlUnlinkNode(config_node);
00275     xmlFreeNode(config_node);
00276     
00277     // save the new XML config file
00278     saveConfigFile();
00279 
00280     // unlock class mutex to prevent deadlock
00281     manager_lock.unlock();
00282     
00283     // notify everyone that the vocabulary was updated
00284     PION_LOG_DEBUG(m_logger, "Removed Vocabulary: " << vocab_id);
00285     boost::mutex::scoped_lock signal_lock(m_signal_mutex);
00286     m_signal_vocabulary_updated();
00287 }
00288     
00289 void VocabularyManager::setVocabularyPath(const std::string& vocab_path)
00290 {
00291     boost::mutex::scoped_lock manager_lock(m_mutex);
00292 
00293     // resolve relative vocabulary paths
00294     m_vocab_path = ConfigManager::resolveRelativePath(vocab_path);
00295     
00296     // make sure that the Vocabulary configuration file is open
00297     if (configIsOpen()) {
00298         // update the vocabulary path in the config file
00299         if (! updateConfigOption(VOCABULARY_PATH_ELEMENT_NAME, getVocabularyPath(), m_config_node_ptr))
00300             throw UpdateVocabularyPathException(getConfigFile());
00301 
00302         // save the new XML config file
00303         saveConfigFile();
00304     }
00305     
00306     PION_LOG_DEBUG(m_logger, "Updated Vocabulary config file path: " << vocab_path);
00307 }
00308 
00309 
00310 }   // end namespace platform
00311 }   // end namespace pion

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