|
TOBI Interface A
0.1
|
00001 /* 00002 This file is part of the TOBI Interface A (TiA) library. 00003 00004 Commercial Usage 00005 Licensees holding valid Graz University of Technology Commercial 00006 licenses may use this file in accordance with the Graz University 00007 of Technology Commercial License Agreement provided with the 00008 Software or, alternatively, in accordance with the terms contained in 00009 a written agreement between you and Graz University of Technology. 00010 00011 -------------------------------------------------- 00012 00013 GNU Lesser General Public License Usage 00014 Alternatively, this file may be used under the terms of the GNU Lesser 00015 General Public License version 3.0 as published by the Free Software 00016 Foundation and appearing in the file lgpl.txt included in the 00017 packaging of this file. Please review the following information to 00018 ensure the GNU General Public License version 3.0 requirements will be 00019 met: http://www.gnu.org/copyleft/lgpl.html. 00020 00021 In case of GNU Lesser General Public License Usage ,the TiA library 00022 is distributed in the hope that it will be useful, 00023 but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 GNU General Public License for more details. 00026 00027 You should have received a copy of the GNU Lesser General Public License 00028 along with the TiA library. If not, see <http://www.gnu.org/licenses/>. 00029 00030 Copyright 2010 Graz University of Technology 00031 Contact: TiA@tobi-project.org 00032 */ 00033 00034 #include "tia-private/newtia/tia_meta_info_parse_and_build_functions.h" 00035 #include "tia-private/newtia/tia_exceptions.h" 00036 00037 #include "tia-private/newtia/string_utils.h" 00038 #include <rapidxml/rapidxml.hpp> 00039 #include <rapidxml/rapidxml_print.hpp> 00040 00041 #include <sstream> 00042 #include <map> 00043 #include <set> 00044 00045 using std::string; 00046 using std::map; 00047 using std::set; 00048 00049 namespace tia 00050 { 00051 00052 namespace XML_TAGS 00053 { 00054 std::string const TIA_META_INFO = "tiaMetaInfo"; 00055 std::string const TIA_META_INFO_VERSION = "version"; 00056 std::string const TIA_META_INFO_CURRENT_VERSION = "1.0"; 00057 00058 std::string const SUBJECT = "subject"; 00059 std::string const SUBJECT_ID = "id"; 00060 std::string const SUBJECT_FIRSTNAME = "firstName"; 00061 std::string const SUBJECT_SURNAME = "surname"; 00062 00063 std::string const MASTER_SIGNAL = "masterSignal"; 00064 std::string const SIGNAL = "signal"; 00065 std::string const SIGNAL_TYPE = "type"; 00066 std::string const SIGNAL_SAMPLINGRATE = "samplingRate"; 00067 std::string const SIGNAL_NUMCHANNELS = "numChannels"; 00068 std::string const SIGNAL_BLOCKSIZE = "blockSize"; 00069 string const SIGNAL_REQUIRED_ATTRIBUTES_ARRAY[] = {SIGNAL_TYPE, SIGNAL_SAMPLINGRATE, SIGNAL_BLOCKSIZE, SIGNAL_NUMCHANNELS}; 00070 set<string> const SIGNAL_REQUIRED_ATTRIBUTES (SIGNAL_REQUIRED_ATTRIBUTES_ARRAY, SIGNAL_REQUIRED_ATTRIBUTES_ARRAY + 4); 00071 00072 std::string const CHANNEL = "channel"; 00073 std::string const CHANNEL_NR = "nr"; 00074 std::string const CHANNEL_LABEL = "label"; 00075 string const CHANNEL_REQUIRED_ATTRIBUTES_ARRAY[] = {CHANNEL_NR, CHANNEL_LABEL}; 00076 set<string> const CHANNEL_REQUIRED_ATTRIBUTES (CHANNEL_REQUIRED_ATTRIBUTES_ARRAY, CHANNEL_REQUIRED_ATTRIBUTES_ARRAY + 2); 00077 } 00078 00079 //----------------------------------------------------------------------------- 00080 void addAttribute (rapidxml::xml_document<>* doc, rapidxml::xml_node<>* node, std::string const& attribute_name, std::string const& attribute_value); 00081 void addAttribute (rapidxml::xml_document<>* doc, rapidxml::xml_node<>* node, std::string const& attribute_name, unsigned attribute_value); 00082 map<string, string> getAttributes (rapidxml::xml_node<>* node); 00083 map<string, string> getAttributes (rapidxml::xml_node<>* node, set<string> required_attributes); 00084 00085 //----------------------------------------------------------------------------- 00086 SSConfig parseTiAMetaInfoFromXMLString (std::string const& tia_meta_info_xml_string) 00087 { 00088 SSConfig tia_meta_info; 00089 rapidxml::xml_document<> xml_doc; 00090 try 00091 { 00092 xml_doc.parse<rapidxml::parse_non_destructive | rapidxml::parse_validate_closing_tags> ((char*)tia_meta_info_xml_string.c_str ()); 00093 } 00094 catch (rapidxml::parse_error &error) 00095 { 00096 throw TiAException (string (error.what())); 00097 } 00098 00099 rapidxml::xml_node<>* tia_metainfo_node = xml_doc.first_node (); 00100 if (tia_metainfo_node->next_sibling ()) 00101 throw TiAException ("Parsing TiAMetaInfo String: Too many first level nodes."); 00102 00103 // parse subject 00104 rapidxml::xml_node<>* subject_node = tia_metainfo_node->first_node (XML_TAGS::SUBJECT.c_str()); 00105 if (subject_node) 00106 { 00107 std::map<string, string> attributes = getAttributes (subject_node); 00108 if (attributes.count (XML_TAGS::SUBJECT_ID)) 00109 tia_meta_info.subject_info.setId (attributes.at(XML_TAGS::SUBJECT_ID)); 00110 if (attributes.count (XML_TAGS::SUBJECT_FIRSTNAME)) 00111 tia_meta_info.subject_info.setFirstName (attributes.at(XML_TAGS::SUBJECT_FIRSTNAME)); 00112 if (attributes.count (XML_TAGS::SUBJECT_SURNAME)) 00113 tia_meta_info.subject_info.setSurname (attributes.at(XML_TAGS::SUBJECT_SURNAME)); 00114 } 00115 00116 // parse master signal info 00117 rapidxml::xml_node<>* master_signal_node = 0; 00118 master_signal_node = tia_metainfo_node->first_node (XML_TAGS::MASTER_SIGNAL.c_str()); 00119 if (master_signal_node) 00120 { 00121 std::map<string, string> attributes = getAttributes (master_signal_node); 00122 if (attributes.count (XML_TAGS::SIGNAL_SAMPLINGRATE)) 00123 tia_meta_info.signal_info.setMasterSamplingRate (toUnsigned (attributes.at(XML_TAGS::SIGNAL_SAMPLINGRATE))); 00124 if (attributes.count (XML_TAGS::SIGNAL_BLOCKSIZE)) 00125 tia_meta_info.signal_info.setMasterBlockSize (toUnsigned (attributes.at(XML_TAGS::SIGNAL_BLOCKSIZE))); 00126 } 00127 00128 00129 // parse signals 00130 rapidxml::xml_node<>* signal_node = 0; 00131 signal_node = tia_metainfo_node->first_node (XML_TAGS::SIGNAL.c_str()); 00132 SignalInfo::SignalMap& signal_map = tia_meta_info.signal_info.signals (); 00133 while (signal_node) 00134 { 00135 Signal signal; 00136 map<string, string> signal_attributes = getAttributes (signal_node, XML_TAGS::SIGNAL_REQUIRED_ATTRIBUTES); 00137 signal.setType (signal_attributes[XML_TAGS::SIGNAL_TYPE]); 00138 signal.setSamplingRate (toUnsigned (signal_attributes[XML_TAGS::SIGNAL_SAMPLINGRATE])); 00139 signal.setBlockSize (toUnsigned (signal_attributes[XML_TAGS::SIGNAL_BLOCKSIZE])); 00140 00141 unsigned const num_channels = toUnsigned (signal_attributes[XML_TAGS::SIGNAL_NUMCHANNELS]); 00142 00143 // parse channels 00144 std::vector<Channel>& channel_vector = signal.channels(); 00145 for (unsigned channel_nr = 0; channel_nr < num_channels; channel_nr++) 00146 { 00147 Channel channel; 00148 channel.setId (toString (channel_nr)); 00149 channel_vector.push_back (channel); 00150 } 00151 00152 rapidxml::xml_node<>* channel_node = signal_node->first_node (XML_TAGS::CHANNEL.c_str()); 00153 while (channel_node) 00154 { 00155 map<string, string> channel_attributes = getAttributes (channel_node, XML_TAGS::CHANNEL_REQUIRED_ATTRIBUTES); 00156 unsigned channel_nr = toUnsigned (channel_attributes[XML_TAGS::CHANNEL_NR]); 00157 if (channel_nr > num_channels) 00158 throw TiAException ("Parse TiAMetaInfo: nr-attribute of channel exceeds numChannels attribute of signal!"); 00159 00160 channel_vector[channel_nr - 1].setId (channel_attributes[XML_TAGS::CHANNEL_LABEL]); 00161 channel_node = channel_node->next_sibling (XML_TAGS::CHANNEL.c_str ()); 00162 } 00163 00164 signal_map[signal_attributes[XML_TAGS::SIGNAL_TYPE]] = signal; 00165 signal_node = signal_node->next_sibling (XML_TAGS::SIGNAL.c_str ()); 00166 } 00167 00168 return tia_meta_info; 00169 } 00170 00171 //----------------------------------------------------------------------------- 00172 std::string buildTiAMetaInfoXMLString (SSConfig const& tia_meta_info) 00173 { 00174 rapidxml::xml_document<> xml_doc; 00175 00176 char *tia_metainfo_node_name = xml_doc.allocate_string (XML_TAGS::TIA_META_INFO.c_str ()); 00177 rapidxml::xml_node<>* tia_metainfo_node = xml_doc.allocate_node (rapidxml::node_element, tia_metainfo_node_name); 00178 00179 addAttribute (&xml_doc, tia_metainfo_node, 00180 XML_TAGS::TIA_META_INFO_VERSION, XML_TAGS::TIA_META_INFO_CURRENT_VERSION); 00181 00182 // subject node 00183 char *subject_node_name = xml_doc.allocate_string (XML_TAGS::SUBJECT.c_str ()); 00184 rapidxml::xml_node<>* subject_node = xml_doc.allocate_node (rapidxml::node_element, subject_node_name); 00185 addAttribute (&xml_doc, subject_node, XML_TAGS::SUBJECT_ID, tia_meta_info.subject_info.id()); 00186 addAttribute (&xml_doc, subject_node, XML_TAGS::SUBJECT_FIRSTNAME, tia_meta_info.subject_info.firstName()); 00187 addAttribute (&xml_doc, subject_node, XML_TAGS::SUBJECT_SURNAME, tia_meta_info.subject_info.surname()); 00188 // TODO: add further attributes 00189 tia_metainfo_node->append_node (subject_node); 00190 00191 00192 // master signal data 00193 char *master_signal_node_name = xml_doc.allocate_string (XML_TAGS::MASTER_SIGNAL.c_str ()); 00194 rapidxml::xml_node<>* master_signal_node = xml_doc.allocate_node (rapidxml::node_element, master_signal_node_name); 00195 addAttribute (&xml_doc, master_signal_node, XML_TAGS::SIGNAL_SAMPLINGRATE, tia_meta_info.signal_info.masterSamplingRate()); 00196 addAttribute (&xml_doc, master_signal_node, XML_TAGS::SIGNAL_BLOCKSIZE, tia_meta_info.signal_info.masterBlockSize()); 00197 tia_metainfo_node->append_node (master_signal_node); 00198 00199 00200 // signals 00201 for (SignalInfo::SignalMap::const_iterator signal_iter = tia_meta_info.signal_info.signals().begin (); 00202 signal_iter != tia_meta_info.signal_info.signals ().end (); ++signal_iter) 00203 { 00204 char *signal_node_name = xml_doc.allocate_string (XML_TAGS::SIGNAL.c_str ()); 00205 rapidxml::xml_node<>* signal_node = xml_doc.allocate_node (rapidxml::node_element, signal_node_name); 00206 addAttribute (&xml_doc, signal_node, XML_TAGS::SIGNAL_TYPE, signal_iter->second.type ()); 00207 addAttribute (&xml_doc, signal_node, XML_TAGS::SIGNAL_SAMPLINGRATE, signal_iter->second.samplingRate()); 00208 addAttribute (&xml_doc, signal_node, XML_TAGS::SIGNAL_BLOCKSIZE, signal_iter->second.blockSize()); 00209 addAttribute (&xml_doc, signal_node, XML_TAGS::SIGNAL_NUMCHANNELS, signal_iter->second.channels().size ()); 00210 00211 for (unsigned channel_nr = 0; channel_nr < signal_iter->second.channels().size (); channel_nr++) 00212 { 00213 char *channel_node_name = xml_doc.allocate_string (XML_TAGS::CHANNEL.c_str ()); 00214 rapidxml::xml_node<>* channel_node = xml_doc.allocate_node (rapidxml::node_element, channel_node_name); 00215 addAttribute (&xml_doc, channel_node, XML_TAGS::CHANNEL_NR, channel_nr + 1); 00216 addAttribute (&xml_doc, channel_node, XML_TAGS::CHANNEL_LABEL, signal_iter->second.channels ()[channel_nr].id()); 00217 signal_node->append_node (channel_node); 00218 } 00219 00220 tia_metainfo_node->append_node (signal_node); 00221 } 00222 00223 00224 xml_doc.append_node (tia_metainfo_node); 00225 00226 string xml_string; 00227 rapidxml::print (std::back_inserter (xml_string), xml_doc, 0); 00228 return xml_string; 00229 } 00230 00231 //----------------------------------------------------------------------------- 00232 void addAttribute (rapidxml::xml_document<>* doc, rapidxml::xml_node<>* node, std::string const& attribute_name, std::string const& attribute_value) 00233 { 00234 if (attribute_value.size()) 00235 { 00236 char *attribute_name_rx = doc->allocate_string (attribute_name.c_str ()); 00237 char *attribute_value_rx = doc->allocate_string (attribute_value.c_str()); 00238 00239 rapidxml::xml_attribute<>* attribute = doc->allocate_attribute (attribute_name_rx, attribute_value_rx, attribute_name.size (), attribute_value.size()); 00240 node->append_attribute (attribute); 00241 } 00242 } 00243 00244 //----------------------------------------------------------------------------- 00245 void addAttribute (rapidxml::xml_document<>* doc, rapidxml::xml_node<>* node, std::string const& attribute_name, unsigned attribute_value) 00246 { 00247 std::ostringstream oss; 00248 oss << std::dec << attribute_value; 00249 addAttribute (doc, node, attribute_name, oss.str ()); 00250 } 00251 00252 00253 //----------------------------------------------------------------------------- 00254 map<string, string> getAttributes (rapidxml::xml_node<>* node) 00255 { 00256 set<string> no_required_attributes; 00257 return getAttributes (node, no_required_attributes); 00258 } 00259 00260 //----------------------------------------------------------------------------- 00261 map<std::string, std::string> getAttributes (rapidxml::xml_node<>* node, set<string> required_attributes) 00262 { 00263 std::map<string, string> attributes; 00264 if (!node) 00265 return attributes; 00266 rapidxml::xml_attribute<>* attribute = node->first_attribute (); 00267 while (attribute) 00268 { 00269 string key (attribute->name (), attribute->name_size ()); 00270 required_attributes.erase (key); 00271 string value (attribute->value (), attribute->value_size ()); 00272 attributes[key] = value; 00273 attribute = attribute->next_attribute (); 00274 } 00275 00276 if (required_attributes.size ()) 00277 { 00278 string missing_attributes; 00279 for (set<string>::const_iterator iter = required_attributes.begin (); iter != required_attributes.end (); ) 00280 { 00281 missing_attributes += *iter; 00282 if (++iter != required_attributes.end ()) 00283 missing_attributes += ", "; 00284 } 00285 throw TiAException (string ("Parse TiAMetaInfo: Required attributes missing: ") + missing_attributes); 00286 } 00287 return attributes; 00288 } 00289 00290 00291 00292 }