presage  0.8.7
profile.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************
00003  *  Presage, an extensible predictive text entry system
00004  *  ---------------------------------------------------
00005  *
00006  *  Copyright (C) 2008  Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License along
00019     with this program; if not, write to the Free Software Foundation, Inc.,
00020     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021                                                                              *
00022                                                                 **********(*)*/
00023 
00024 
00025 #include "core/profile.h"
00026 
00027 #include <iostream>
00028 #include <sstream>
00029 
00030 Profile::Profile(const std::string& profile_file)
00031 {
00032     xmlProfileDoc = new TiXmlDocument();
00033     assert( xmlProfileDoc );
00034 
00035     xml_filename = profile_file;
00036 
00037     xml_profile_read_ok = xmlProfileDoc->LoadFile (xml_filename.c_str());
00038 }
00039 
00040 Profile::~Profile()
00041 {
00042     delete xmlProfileDoc;
00043 }
00044 
00045 bool Profile::file_read_ok () const
00046 {
00047     return xml_profile_read_ok;
00048 }
00049 
00050 void Profile::read_into_configuration(Configuration* config)
00051 {
00052     init_configuration(config, xmlProfileDoc);
00053 }
00054 
00055 void Profile::init_configuration(Configuration* config, TiXmlDocument* root)
00056 {
00057     std::vector<std::string> variable;
00058 
00059     visit_node(config, root, variable);
00060 }
00061 
00062 void Profile::visit_node(Configuration* configuration,
00063                          TiXmlNode* node,
00064                          std::vector<std::string> variable)
00065 {
00066     if (node) {
00067         // visit the node only if it is one
00068 
00069         // first visit our siblings
00070         visit_node(configuration, node->NextSibling(), variable);
00071 
00072         // then check this element contains a
00073         // configuration variable
00074         TiXmlElement* element = node->ToElement();
00075         if (element) {
00076             // append element name to variable to
00077             // build fully qualified variable name
00078             // before visit children
00079             variable.push_back(element->Value());
00080 
00081             // if element contains text, we have a value for our
00082             // config variable, so add it to our configuration
00083             const char* text = element->GetText();
00084             if (text) {
00085                 configuration->insert (Variable::vector_to_string(variable), text);
00086 
00087                 //std::cerr << "[Profile] Inserted variable: " << Variable::vector_to_string(variable) << " = " << text << std::endl;
00088             }
00089         }
00090 
00091         // then descend down the tree
00092         visit_node(configuration, node->FirstChild(), variable);
00093     }
00094 }
00095 
00096 bool Profile::write_to_file () const
00097 {
00098     //std::cerr << "Saving profile to file: " << xml_filename << std::endl;
00099     return xmlProfileDoc->SaveFile(xml_filename.c_str());
00100 }
00101 
00102 void Profile::read_from_configuration (Configuration* configuration)
00103 {
00104     TiXmlNode* node = 0;
00105 
00106     // insert initial mandatory declaration if not present
00107     TiXmlNode* decl = 0;
00108     for (TiXmlNode* child = xmlProfileDoc->FirstChild();
00109          child && !decl; child = child->NextSibling() ) {
00110         decl = child->ToDeclaration ();
00111     }
00112     if (! decl) {
00113         node = xmlProfileDoc->InsertEndChild( TiXmlDeclaration( "1.0", "UTF-8", "no" ) );
00114         assert (node);
00115     }
00116 
00117     // for each configuration variable in configuration
00118     for (std::map<std::string, Variable*>::const_iterator conf_it = configuration->begin();
00119          conf_it != configuration->end();
00120          conf_it ++) {
00121 
00122         // start from root of DOM
00123         node = xmlProfileDoc;
00124 
00125         // get the variable name and break it up in its component vector
00126         std::string variable_name = conf_it->second->get_name ();
00127         std::vector<std::string> variable_name_vector = Variable::string_to_vector (variable_name);
00128 
00129         // for each component in variable name vector
00130         for (size_t i = 0; i < variable_name_vector.size(); i++) {
00131 
00132             // check if component element exists
00133             TiXmlElement* existing = node->FirstChildElement (variable_name_vector[i].c_str());
00134             if (existing) {
00135                 // carry on with existing component
00136                 node = existing;
00137 
00138             } else {
00139                 // create missing component element and carry on with new component
00140                 node = node->InsertEndChild (TiXmlElement (variable_name_vector[i].c_str()));
00141                 assert (node);
00142             }
00143         }
00144 
00145         // check if a text node for element exists
00146         TiXmlText* text = 0;
00147         for(TiXmlNode* child = node->FirstChild(); child && !text; child = child->NextSibling() ) {
00148             text = child->ToText ();
00149         }
00150         if (text) {
00151             // text child already exists, so remove it to set new value
00152             node->RemoveChild (text);
00153         }
00154         node = node->InsertEndChild (TiXmlText (conf_it->second->get_value ().c_str ()));
00155         assert (node);
00156     
00157     }
00158 }