fipa_acl  1.4
xml_message_parser.cpp
Go to the documentation of this file.
1 #include "xml_message_parser.h"
2 #include "xml_parser.h"
3 #include <fipa_acl/message_generator/message_format.h>
4 #include <base-logging/Logging.hpp>
5 
6 #include <boost/foreach.hpp>
7 
8 namespace fipa {
9 namespace acl {
10 
11 bool XMLMessageParser::parseData(const std::string& storage, ACLMessage& msg)
12 {
13  TiXmlDocument doc;
14 
15  // Load the string into XML doc
16  const char* parseResult = doc.Parse(storage.c_str());
17  // A non-null parseResult usually indicates an error, but we seem to get that every time.
18  if(parseResult != NULL)
19  {
20  // non-null means some error
21  LOG_WARN_S << "Parsing message XML failed for: " << parseResult;
22  }
23 
24  // The main node (fipa-message)
25  const TiXmlElement* messageElem = doc.FirstChildElement();
26 
27  if(messageElem->ValueStr() != "fipa-message")
28  {
29  LOG_WARN_S << "Parsing error: XML main node not named 'fipa-message' but " << messageElem->ValueStr();
30  return false;
31  }
32 
33  // Load communicative act attribute
34  try
35  {
36  msg.setPerformative(messageElem->Attribute("act"));
37  }
38  catch(const std::exception& e)
39  {
40  // This indicates the performative is unknown
41  LOG_WARN_S << "Parsing error performative: " << e.what();
42  return false;
43  }
44 
45  // If the conversation id is here, save it
46  const std::string* convID = messageElem->Attribute(std::string("conversation-id"));
47  if(convID != NULL)
48  {
49  msg.setConversationID(*convID);
50  }
51 
52  // Parse all child elements
53  const TiXmlElement * pChild;
54  for ( pChild = messageElem->FirstChildElement(); pChild != 0; pChild = pChild->NextSiblingElement())
55  {
56  if(!parseParameter(msg, pChild))
57  {
58  return false;
59  }
60  }
61 
62  return true;
63 }
64 
65 bool XMLMessageParser::parseParameter(ACLMessage& aclMsg, const TiXmlElement* elem) const
66 {
67  using namespace MessageField;
68  const std::string& name = elem->ValueStr();
69 
70  if(name == MessageFieldTxt[RECEIVER])
71  {
72  // This is the only field where FIPA allows multiple occurences, so we must not override anything
73  // Therefore, we use addReceiver instead of setAllReceivers
74  // AgentIDList
75  try
76  {
78  BOOST_FOREACH(AgentID aid, aidl)
79  {
80  aclMsg.addReceiver(aid);
81  }
82  }
83  catch(std::exception& e)
84  {
85  LOG_WARN_S << "Parsing error receivers: " << e.what();
86  return false;
87  }
88  }
89  else if(name == MessageFieldTxt[SENDER])
90  {
91  // There must be one child: the aid element
92  const TiXmlElement* aid = elem->FirstChildElement();
93  if(aid == NULL)
94  {
95  LOG_WARN_S << "Parsing error: sender has no first child";
96  return false;
97  }
98 
99  // AgentID
100  try
101  {
102  aclMsg.setSender(XMLParser::parseAgentID(aid));
103  }
104  catch(std::exception& e)
105  {
106  LOG_WARN_S << "Parsing error sender: " << e.what();
107  return false;
108  }
109  }
110  else if(name == MessageFieldTxt[CONTENT])
111  {
112  const char* value = XMLParser::extractContentOrAttribute(elem);
113  if(value == NULL)
114  {
115  LOG_WARN_S << "Parsing error: content is set but invalid";
116  return false;
117  }
118  aclMsg.setContent(std::string(value));
119  return true;
120  }
121  else if(name == MessageFieldTxt[LANGUAGE])
122  {
123  const char* value = XMLParser::extractContentOrAttribute(elem);
124  if(value == NULL)
125  {
126  LOG_WARN_S << "Parsing error: language is set but invalid";
127  return false;
128  }
129  aclMsg.setLanguage(std::string(value));
130  return true;
131  }
132  else if(name == MessageFieldTxt[ENCODING])
133  {
134  const char* value = XMLParser::extractContentOrAttribute(elem);
135  if(value == NULL)
136  {
137  LOG_WARN_S << "Parsing error: encoding is set but invalid";
138  return false;
139  }
140  aclMsg.setEncoding(std::string(value));
141  return true;
142  }
143  else if(name == MessageFieldTxt[ONTOLOGY])
144  {
145  const char* value = XMLParser::extractContentOrAttribute(elem);
146  if(value == NULL)
147  {
148  LOG_WARN_S << "Parsing error: ontology is set but invalid";
149  return false;
150  }
151  aclMsg.setOntology(std::string(value));
152  return true;
153  }
154  else if(name == MessageFieldTxt[PROTOCOL])
155  {
156  const char* value = XMLParser::extractContentOrAttribute(elem);
157  if(value == NULL)
158  {
159  LOG_WARN_S << "Parsing error: protocol is set but invalid";
160  return false;
161  }
162  aclMsg.setProtocol(std::string(value));
163  return true;
164  }
165  else if(name == MessageFieldTxt[REPLY_WITH])
166  {
167  const char* value = XMLParser::extractContentOrAttribute(elem);
168  if(value == NULL)
169  {
170  LOG_WARN_S << "Parsing error: reply_with is set but invalid";
171  return false;
172  }
173  aclMsg.setReplyWith(std::string(value));
174  return true;
175  }
176  else if(name == MessageFieldTxt[IN_REPLY_TO])
177  {
178  const char* value = XMLParser::extractContentOrAttribute(elem);
179  if(value == NULL)
180  {
181  LOG_WARN_S << "Parsing error: in_reply_to is set but invalid";
182  return false;
183  }
184  aclMsg.setInReplyTo(std::string(value));
185  return true;
186  }
187  else if(name == MessageFieldTxt[REPLY_BY])
188  {
189  // Time. The value is in the attribute "time"
190  const char* value = elem->Attribute("time");
191  if(value == NULL)
192  {
193  LOG_WARN_S << "Parsing error: reply_by is set but invalid";
194  return false;
195  }
196  try
197  {
198  aclMsg.setReplyBy(XMLParser::strToDate(std::string(value)));
199  }
200  catch(std::exception& e)
201  {
202  LOG_WARN_S << "Parsing error reply_by: " << e.what();
203  return false;
204  }
205  }
206  else if(name == MessageFieldTxt[REPLY_TO])
207  {
208  // AgentIDList
209  try
210  {
212  }
213  catch(std::exception& e)
214  {
215  LOG_WARN_S << "Parsing error reply_to: " << e.what();
216  return false;
217  }
218  }
219  else if(name == MessageFieldTxt[CONVERSATION_ID])
220  {
221  // This overrides a conversation id set before
222  const char* value = XMLParser::extractContentOrAttribute(elem);
223  if(value == NULL)
224  {
225  LOG_WARN_S << "Parsing error: conversation_id is set but invalid";
226  return false;
227  }
228  aclMsg.setConversationID(std::string(value));
229  return true;
230  }
231  else if(name == "user-defined")
232  {
233  // It's a user defined parameter
234  try
235  {
237  }
238  catch(std::exception& e)
239  {
240  LOG_WARN_S << "Parsing error user_def_param: " << e.what();
241  return false;
242  }
243  }
244  else
245  {
246  LOG_WARN_S << "Parsing error: unknown node: " << name;
247  return false;
248  }
249 
250  return true;
251 }
252 
253 } // end namespace acl
254 } // end namespace fipa
void setReplyWith(const std::string &str)
Definition: acl_message.h:212
void setConversationID(const std::string &str)
Definition: acl_message.h:222
void setLanguage(const std::string &str)
Definition: acl_message.h:263
bool parseData(const std::string &storage, ACLMessage &msg)
std::map< MessageField::Type, std::string > MessageFieldTxt
void setInReplyTo(const std::string &str)
Definition: acl_message.h:202
std::vector< AgentID > AgentIDList
Definition: agent_id.h:20
static const AgentIDList parseAgentIDSequence(const TiXmlElement *aidlElem)
Definition: xml_parser.cpp:47
static const base::Time strToDate(const std::string &dateStr)
Definition: xml_parser.cpp:202
void setContent(const std::string &content)
Definition: acl_message.h:274
void setSender(const AgentID &sender)
Definition: acl_message.h:305
static const UserdefParam parseUserdefinedParameter(const TiXmlElement *paramElem)
Definition: xml_parser.cpp:188
void addUserdefParam(const UserdefParam &p)
static const AgentID parseAgentID(const TiXmlElement *aidElem)
Definition: xml_parser.cpp:8
void setAllReplyTo(const AgentIDList &replyTo)
Definition: acl_message.h:197
static const char * extractContentOrAttribute(const TiXmlElement *elem, const char *identifier="href")
Definition: xml_parser.cpp:219
This class provides a representation of a message conforming to the FIPA specification SC00061...
Definition: acl_message.h:55
void setReplyBy(const base::Time &time)
Definition: acl_message.h:340
void addReceiver(const AgentID &aid)
void setPerformative(Performative perf)
Set performative.
Implements the general AgentID functionality, which is present throughout the fipa specifications(FIP...
Definition: agent_id.h:37
Foundation of Physical Intelligent Agents.
Definition: conversation.cpp:6
void setEncoding(const std::string &str)
Definition: acl_message.h:253
void setProtocol(const std::string &str)
the method checks whether the passed protocol string is a word or not(according to the fipa spec) ...
void setOntology(const std::string &str)
Definition: acl_message.h:243