fipa_acl  1.4
xml_envelope_parser.cpp
Go to the documentation of this file.
1 #include "xml_envelope_parser.h"
2 #include "xml_parser.h"
3 #include <boost/lexical_cast.hpp>
4 #include <boost/algorithm/string.hpp>
5 #include <base-logging/Logging.hpp>
6 #include <stdexcept>
7 
8 namespace fipa {
9 namespace acl {
10 
11 bool XMLEnvelopeParser::parseData(const std::string& storage, ACLEnvelope& envelope)
12 {
13  TiXmlDocument doc;
14  LOG_INFO_S << "XMLEnvelopeParser: starting to parse: " << storage;
15 
16  std::string envelopeXML;
17  std::string payloadData;
18 
19  // check whether we can split the document into envelope and content
20  std::string envelopeEndMarker = "</envelope>";
21  size_t pos = storage.find(envelopeEndMarker);
22  if(pos == std::string::npos)
23  {
24  LOG_WARN_S << "XMLEnvelopeParser: this is not an XML envelope. Could not find </envelope>";
25  return false;
26  } else {
27  envelopeXML = storage.substr(0, pos + envelopeEndMarker.size());
28 
29  size_t payloadPosition = pos + envelopeEndMarker.size();
30  if(payloadPosition < storage.length());
31  {
32  envelope.setPayload(storage.substr(payloadPosition));
33  }
34  }
35 
36  // Load the string into XML doc
37  const char* parseResult = doc.Parse(envelopeXML.c_str());
38  // A non-null parseResult usually indicates an error, but we seem to get that every time.
39  if(parseResult != NULL)
40  {
41  // non-null means some error
42  LOG_WARN_S << "Parsing envelope XML failed for (probably the payload): " << parseResult;
43  }
44  LOG_INFO_S << "XMLEnvelopeParser: basic XML parsing complete.";
45 
46  // The main node (envelope)
47  const TiXmlElement* envelopeElem = doc.FirstChildElement();
48 
49  if(envelopeElem == NULL)
50  {
51  LOG_WARN_S << "Parsing error: XML main node not found.";
52  return false;
53  }
54 
55  if(envelopeElem->ValueStr() != "envelope")
56  {
57  LOG_WARN_S << "Parsing error: XML main node not named 'fipa-message' but " << envelopeElem->ValueStr();
58  return false;
59  }
60 
61  // Parse all child elements
62  const TiXmlElement* pChild = envelopeElem->FirstChildElement();
63 
64  if(pChild == NULL)
65  {
66  LOG_WARN_S << "Parsing error: XML first params node not found.";
67  return false;
68  }
69 
70  // We assume the params have raising indices, starting with one.
71  int paramsIndex = 1;
72  // The first params is the Base envelope
73  try
74  {
75  envelope.setBaseEnvelope(parseParameters(pChild, paramsIndex++));
76  }
77  catch(std::exception& e)
78  {
79  LOG_WARN_S << "Parsing error base envelope: " << e.what();
80  return false;
81  }
82 
83  // All remaining params are extra envelopes
84  for ( pChild = pChild->NextSiblingElement(); pChild != 0; pChild = pChild->NextSiblingElement())
85  {
86  try
87  {
88  envelope.addExtraEnvelope(parseParameters(pChild, paramsIndex++));
89  }
90  catch(std::exception& e)
91  {
92  LOG_WARN_S << "Parsing error extra envelope: " << e.what();
93  return false;
94  }
95  }
96 
97  return true;
98 }
99 
100 const ACLBaseEnvelope XMLEnvelopeParser::parseParameters(const TiXmlElement* paramsElem, int paramsIndex) const
101 {
102  if(paramsElem->ValueStr() != "params")
103  {
104  throw std::runtime_error("Parsing error: params node not named 'params' but " + paramsElem->ValueStr());
105  }
106  if(*(paramsElem->Attribute(std::string("index"))) != boost::lexical_cast<std::string>(paramsIndex))
107  {
108  throw std::runtime_error("Parsing error: params index attribute should be " +
109  boost::lexical_cast<std::string>(paramsIndex) + " but is " + paramsElem->Attribute("index"));
110  }
111 
112  ACLBaseEnvelope envelope;
114 
115  // Parse all child elements
116  const TiXmlElement * pChild;
117  for ( pChild = paramsElem->FirstChildElement(); pChild != 0; pChild = pChild->NextSiblingElement())
118  {
119  // Get the name of the element
120  const std::string& name = pChild->ValueStr();
121 
122  if(name == "to")
123  {
124  envelope.setTo(XMLParser::parseAgentIDSequence(pChild));
125  }
126  else if(name == "from")
127  {
128  // There must be one child: the aid element
129  const TiXmlElement* aid = pChild->FirstChildElement();
130  if(aid == NULL)
131  {
132  throw std::runtime_error("Parsing error: from has no first child");
133  }
134 
135  envelope.setFrom(XMLParser::parseAgentID(aid));
136  }
137  else if(name == "comments")
138  {
139  envelope.setComments(std::string(pChild->GetText()));
140  }
141  else if(name == "acl-representation")
142  {
143  envelope.setACLRepresentation(std::string(pChild->GetText()));
144  }
145  else if(name == "payload-length")
146  {
147  envelope.setPayloadLength(boost::lexical_cast<PayloadLength>(std::string(pChild->GetText())));
148  }
149  else if(name == "payload-encoding")
150  {
151  envelope.setPayloadEncoding(std::string(pChild->GetText()));
152  }
153  else if(name == "date")
154  {
155  envelope.setDate(XMLParser::parseDate(pChild));
156  }
157  else if(name == "intended-receiver")
158  {
159  envelope.setIntendedReceivers(XMLParser::parseAgentIDSequence(pChild));
160  }
161  else if(name == "received")
162  {
163  envelope.setReceivedObject(XMLParser::parseReceivedObject(pChild));
164  }
165  else if(name == "user-defined")
166  {
167  params.push_back(XMLParser::parseUserdefinedParameter(pChild));
168  }
169  else
170  {
171  throw std::runtime_error("Parsing error: unknown node: " + name);
172  }
173  }
174  envelope.setUserdefinedParameters(params);
175 
176  return envelope;
177 }
178 
179 } // end namespace acl
180 } // end namespace fipa
The ACLBaseEnvelope defines the layout for an envelope with which ACLMessage data can be wrapped...
Definition: acl_envelope.h:36
static const ReceivedObject parseReceivedObject(const TiXmlElement *receivedObjectElem)
Definition: xml_parser.cpp:95
ACLMessage envelope (also typed as fipa::acl::Letter) includes the base envelope and updated fields...
Definition: acl_envelope.h:349
bool parseData(const std::string &storage, ACLEnvelope &envelope)
std::vector< UserdefParam > UserdefinedParameterList
Definition: userdef_param.h:94
void setPayload(const std::string &payload)
Definition: acl_envelope.h:467
static const AgentIDList parseAgentIDSequence(const TiXmlElement *aidlElem)
Definition: xml_parser.cpp:47
void setBaseEnvelope(const ACLBaseEnvelope &envelope)
Definition: acl_envelope.h:436
static const UserdefParam parseUserdefinedParameter(const TiXmlElement *paramElem)
Definition: xml_parser.cpp:188
static const AgentID parseAgentID(const TiXmlElement *aidElem)
Definition: xml_parser.cpp:8
void setTo(const AgentIDList &receivers)
void addExtraEnvelope(const ACLBaseEnvelope &envelope)
Definition: acl_envelope.h:417
static const base::Time parseDate(const TiXmlElement *dateElem)
Definition: xml_parser.cpp:59
Foundation of Physical Intelligent Agents.
Definition: conversation.cpp:6