00001
00006 #ifndef DATAELEMENTFACTORY_H_
00007 #define DATAELEMENTFACTORY_H_
00008
00009 #include "robot_instance/RobonetDataElement.h"
00010 #include "robot_instance/StringUtilities.h"
00011 #include "robot_instance/XmlParserExceptions.h"
00012 #include "nasa_common_logging/Logger.h"
00013 #include "tinyxml.h"
00014 #include <string>
00015 #include <sstream>
00016 #include <utility>
00017 #include <vector>
00018 #include <stdexcept>
00019 #include "shared_memory_transport/smtclient.hpp"
00020
00021
00022
00025 class InvalidDataElementTypeException: public std::exception
00026 {
00027 virtual const char* what() const throw()
00028 {
00029 return "Cannot call DataElementFactory methods for DataElement type T when T does not equal RobonetDataElement. A specialization of this method needs to be added to DataElementFactory.cpp to support your DataElement type.";
00030 }
00031 };
00032
00035 template <typename T>
00036 class DataElementFactory
00037 {
00041 std::shared_ptr<SMT::SMTClient> smtclient;
00042 public:
00043 DataElementFactory(std::shared_ptr<SMT::SMTClient> client = nullptr):
00044 smtclient(client) {};
00045 virtual ~DataElementFactory() {};
00046
00051 std::pair< std::string, boost::shared_ptr<T> > fromXml(const std::string& elementName, const std::string& robonetNode, const std::string& xml)
00052 {
00053 InvalidDataElementTypeException invalidDataElementTypeException;
00054 throw invalidDataElementTypeException;
00055 }
00056
00061 std::pair< std::string, boost::shared_ptr<T> > stringsToDataElement(const std::string& name, const std::string& type, const std::string& direction, const std::string& channel, const std::string& node, const std::string& offset1, const std::string& offset2, const std::string& group, const std::string& style)
00062 {
00063 InvalidDataElementTypeException invalidDataElementTypeException;
00064 throw invalidDataElementTypeException;
00065 }
00066 };
00067
00070 template <>
00071 class DataElementFactory<RobonetDataElement>
00072 {
00076 std::shared_ptr<SMT::SMTClient> smtclient;
00077 public:
00078 DataElementFactory(std::shared_ptr<SMT::SMTClient> client = nullptr):
00079 smtclient(client) {};
00080 virtual ~DataElementFactory() {};
00081
00094 std::pair< std::string, RobonetDataElementPtr > fromXml(const std::string& elementName, const std::string& robonetNode, const std::string& xml)
00095 {
00096 TiXmlDocument file;
00097 file.Parse(xml.c_str());
00098
00099 TiXmlHandle doc(&file);
00100
00101 RobonetDataElementPtr dataElement;
00102 std::string str;
00103 std::string name;
00104 std::string type;
00105 std::string channel;
00106 std::string node;
00107 std::string offset1;
00108 std::string offset2;
00109 DataElement::ReadWrite direction = DataElement::Read;
00110 std::string group;
00111 RobonetDataElement::ElementStyle style = RobonetDataElement::Normal;
00112
00113 std::stringstream err;
00114 std::string smttype;
00115
00116 TiXmlHandle elementHandle(doc.FirstChild("Element"));
00117
00118 if (elementHandle.ToElement())
00119 {
00120 if (elementHandle.ToElement()->Attribute("id"))
00121 {
00122 if (robonetNode.size() <= 0)
00123 {
00124 std::stringstream err;
00125 err << "The robonetNode parameter is required.";
00126 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00127 throw std::runtime_error(err.str());
00128 }
00129
00130 if (elementName.size() > 0)
00131 {
00132 name = StringUtilities::makeFullyQualifiedRoboDynElement(elementName, elementHandle.ToElement()->Attribute("id"));
00133 }
00134 else
00135 {
00136 std::stringstream err;
00137 err << "The elementName parameter is required.";
00138 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00139 throw std::runtime_error(err.str());
00140 }
00141 }
00142 else
00143 {
00144 std::stringstream err;
00145 err << "The attribute [id] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00146 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00147
00148 MissingXMLElementException missingXMLElementException;
00149 throw missingXMLElementException;
00150 }
00151
00152 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "Element name: " << name;
00153
00154 if (elementHandle.ToElement()->Attribute("type"))
00155 {
00156 type = elementHandle.ToElement()->Attribute("type");
00157 }
00158 else
00159 {
00160 std::stringstream err;
00161 err << "The attribute [type] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00162 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00163
00164 MissingXMLElementException missingXMLElementException;
00165 throw missingXMLElementException;
00166 }
00167
00168 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << " type: " << type;
00169
00170 if (elementHandle.ToElement()->Attribute("direction"))
00171 {
00172 str = elementHandle.ToElement()->Attribute("direction");
00173
00174 if ( str.compare("Read") == 0 )
00175 {
00176 direction = DataElement::Read;
00177 }
00178 else if ( str.compare("Write") == 0 )
00179 {
00180 direction = DataElement::Write;
00181 }
00182 else
00183 {
00184 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, "DataElementFactory::xmlToDataElement() - Direction must be either Read or Write, not '" + str + "'");
00185 MissingXMLElementException missingXMLElementException;
00186 throw missingXMLElementException;
00187 }
00188 }
00189 else
00190 {
00191 std::stringstream err;
00192 err << "The attribute [direction] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00193 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00194
00195 MissingXMLElementException missingXMLElementException;
00196 throw missingXMLElementException;
00197 }
00198
00199 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << " direction: " << str;
00200
00201 channel = StringUtilities::getRobonetChannel(robonetNode);
00202 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << " channel: " << channel;
00203
00204 node = StringUtilities::getRobonetNode(robonetNode);
00205 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << " node: " << node;
00206
00207 if (elementHandle.ToElement()->Attribute("offset1"))
00208 {
00209 offset1 = elementHandle.ToElement()->Attribute("offset1");
00210 }
00211 else
00212 {
00213 std::stringstream err;
00214 err << "The attribute [offset1] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00215 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00216
00217 MissingXMLElementException missingXMLElementException;
00218 throw missingXMLElementException;
00219 }
00220
00221 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << " offset1: " << offset1;
00222
00223 if (elementHandle.ToElement()->Attribute("offset2"))
00224 {
00225 offset2 = elementHandle.ToElement()->Attribute("offset2");
00226 }
00227
00228 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << " offset2: " << offset2;
00229
00230 if (elementHandle.ToElement()->Attribute("group"))
00231 {
00232 group = elementHandle.ToElement()->Attribute("group");
00233 }
00234 else
00235 {
00236 std::stringstream err;
00237 err << "The attribute [group] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00238 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00239
00240 MissingXMLElementException missingXMLElementException;
00241 throw missingXMLElementException;
00242 }
00243
00244 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << " group: " << group;
00245
00246 if (elementHandle.ToElement()->Attribute("style"))
00247 {
00248 str = elementHandle.ToElement()->Attribute("style");
00249
00250 if ( str.compare("Normal") == 0 )
00251 {
00252 style = RobonetDataElement::Normal;
00253 }
00254 else if ( str.compare("MotCom") == 0 )
00255 {
00256 style = RobonetDataElement::MotCom;
00257 }
00258 else if ( str.compare("Temperature") == 0 )
00259 {
00260 style = RobonetDataElement::Temperature;
00261 }
00262 else if ( str.compare("BrakePwm") == 0 )
00263 {
00264 style = RobonetDataElement::BrakePwm;
00265 }
00266 else if ( str.compare("FixedPointMilli") == 0 )
00267 {
00268 style = RobonetDataElement::FixedPointMilli;
00269 }
00270 else if ( str.compare("UnsignedFixedPointMilli") == 0 )
00271 {
00272 style = RobonetDataElement::UnsignedFixedPointMilli;
00273 }
00274 else if ( str.compare("FixedPointCenti") == 0 )
00275 {
00276 style = RobonetDataElement::FixedPointCenti;
00277 }
00278 else if ( str.compare("UnsignedFixedPointCenti") == 0 )
00279 {
00280 style = RobonetDataElement::UnsignedFixedPointCenti;
00281 }
00282 else if ( str.compare("PowConTemperature") == 0 )
00283 {
00284 style = RobonetDataElement::PowConTemperature;
00285 }
00286 else if ( str.compare("PowConCurrentMany") == 0 )
00287 {
00288 style = RobonetDataElement::PowConCurrentMany;
00289 }
00290 else if ( str.compare("PowConVoltageMany") == 0 )
00291 {
00292 style = RobonetDataElement::PowConVoltageMany;
00293 }
00294 else
00295 {
00296 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, "DataElementFactory::xmlToDataElement() - Style must be either Normal, MotCom, Temperature or BrakePwm, not '" + str + "'");
00297 MissingXMLElementException missingXMLElementException;
00298 throw missingXMLElementException;
00299 }
00300 }
00301 else
00302 {
00303 std::stringstream err;
00304 err << "The attribute [style] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00305 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00306
00307 MissingXMLElementException missingXMLElementException;
00308 throw missingXMLElementException;
00309 }
00310
00311 NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << " style: " << str;
00312 }
00313 else
00314 {
00315 std::stringstream err;
00316 err << "The element [Element] was not found.";
00317 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00318
00319 MissingXMLElementException missingXMLElementException;
00320 throw missingXMLElementException;
00321 }
00322
00323
00324 if ( smtclient ) {
00325 try {
00326
00327 smttype = type.substr(0, type.rfind("_t"));
00328
00329 if ( !smttype.compare("float") ){
00330 smttype = "float32";
00331 }
00332 if ( !smttype.compare("double") ){
00333 smttype = "float64";
00334 }
00335
00336 if ( !smttype.compare("bool") ){
00337 smttype = "uint8";
00338 }
00339
00340 auto resource = std::make_shared<SMT::Resource>( smtclient->createResource(name, smttype, 0, 0, "big", "") );
00341
00342 dataElement.reset(new RobonetDataElement(type, direction, channel, node, RobonetDataElement::OffsetPair(offset1, offset2), group, style, resource));
00343 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::DEBUG, "Added RDE `" + name + "` with SMT::Resource");
00344 }
00345 catch (const SMT::SMTException e) {
00346
00347
00348
00349 err << "DataElementFactory::xmlToDataElement() - Problem creating SMT Resource `" << name << "`: ";
00350 err << e.what();
00351 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::DEBUG, err.str());
00352
00353 dataElement.reset(new RobonetDataElement(type, direction, channel, node, RobonetDataElement::OffsetPair(offset1, offset2), group, style));
00354 }
00355 } else {
00356
00357 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::WARN, "DataElementFactory::xmlToDataElement() - SMTClient not specified. Not using SMT for now. This will be DEPRECATED soon.");
00358
00359 dataElement.reset(new RobonetDataElement(type, direction, channel, node, RobonetDataElement::OffsetPair(offset1, offset2), group, style));
00360 }
00361
00362 return std::make_pair(name, dataElement);
00363 }
00364
00365 };
00366
00367 #endif