fipa_acl  1.4
acl_envelope.cpp
Go to the documentation of this file.
1 #include "acl_envelope.h"
2 
3 #include <algorithm>
4 #include <sstream>
5 #include <boost/spirit/include/phoenix_core.hpp>
6 #include <boost/spirit/include/phoenix_operator.hpp>
7 #include <base-logging/Logging.hpp>
8 
9 #include <fipa_acl/message_parser/message_parser.h>
10 #include <fipa_acl/message_generator/message_generator.h>
11 
12 using namespace boost::phoenix;
13 using namespace boost::phoenix::arg_names;
14 using namespace std;
15 using namespace fipa::acl::envelope;
16 
17 namespace fipa {
18 namespace acl {
19 
20 uint32_t ACLEnvelope::mStampCounter = 0;
21 
22 ACLBaseEnvelope::ACLBaseEnvelope()
23  : mParameters(NONE)
24  , mACLRepresentation(representation::UNKNOWN)
25  , mPayloadEncoding("US-ASCII")
26 {}
27 
28 void ACLBaseEnvelope::addTo(const AgentID& agentId)
29 {
30  AgentID agent = agentId;
31  AgentIDList::const_iterator it = find_if(mTo.begin(), mTo.end(), arg1 == agentId );
32  if(it == mTo.end())
33  {
34  mTo.push_back(agentId);
35  }
36 }
37 
38 void ACLBaseEnvelope::setTo(const AgentIDList& receivers)
39 {
40  mParameters = (ParameterId) (mParameters | TO);
41  mTo = receivers;
42 }
43 
44 bool ACLBaseEnvelope::removeTo(const AgentID& agentId)
45 {
46  AgentIDList::iterator it = find_if(mTo.begin(), mTo.end(), arg1 == agentId);
47  if(it != mTo.end())
48  {
49  mTo.erase(it);
50  return true;
51  }
52  return false;
53 }
54 
55 
57 {
58  mParameters = (ParameterId) (mParameters | FROM);
59  mFrom = from;
60 }
61 
62 
64 {
65  mParameters = (ParameterId) (mParameters | COMMENTS);
66  mComments = comments;
67 }
68 
70 {
71  mParameters = (ParameterId) (mParameters | ACL_REPRESENTATION);
72  mACLRepresentation = representation;
73 }
74 
75 
76 void ACLBaseEnvelope::setACLRepresentation(const std::string& representation)
77 {
78  for(int i = (int) representation::UNKNOWN; i < (int) representation::END_MARKER; ++i)
79  {
80  if(representation == representation::TypeTxt[i])
81  {
83  return;
84  }
85  }
86  std::string msg = "Trying to set unknown representation '" + representation + "'";
87  LOG_ERROR_S << msg;
88  throw std::runtime_error(msg);
89 }
90 
92 {
93  mParameters = (ParameterId) (mParameters | PAYLOAD_LENGTH);
94  mPayloadLength = length;
95 }
96 
98 {
99  mParameters = (ParameterId) (mParameters | PAYLOAD_ENCODING);
100  mPayloadEncoding = encoding;
101 }
102 
103 void ACLBaseEnvelope::setDate(const base::Time& date)
104 {
105  mParameters = (ParameterId) (mParameters | DATE);
106  mDate = date;
107 }
108 
110 {
111  mParameters = (ParameterId) (mParameters | INTENDED_RECEIVERS);
112  mIntendedReceivers = receivers;
113 }
114 
116 {
117  AgentIDList::const_iterator it = find_if(mIntendedReceivers.begin(), mIntendedReceivers.end(), arg1 == agentId);
118  if(it == mIntendedReceivers.end())
119  {
120  mIntendedReceivers.push_back(agentId);
121  }
122 }
123 
125 {
126  AgentIDList::iterator it = find_if(mIntendedReceivers.begin(), mIntendedReceivers.end(), arg1 == agentId);
127  if(it != mIntendedReceivers.end())
128  {
129  mIntendedReceivers.erase(it);
130  return true;
131  }
132  return false;
133 }
134 
136 {
137  mParameters = (ParameterId) (mParameters | RECEIVED_OBJECT);
138  mReceivedObject = receivedObject;
139 }
140 
141 bool ACLBaseEnvelope::hasReceivedObject(const ReceivedObject& receivedObject) const
142 {
143  if (mParameters & RECEIVED_OBJECT)
144  {
145  return receivedObject.getBy() == mReceivedObject.getBy();
146  }
147 
148  return false;
149 }
150 
152 {
153  mParameters = (ParameterId) (mParameters | TRANSPORT_BEHAVIOUR);
154  mTransportBehaviour = transportBehaviour;
155 }
156 
158 {
159  mParameters = (ParameterId) (mParameters | USERDEFINED_PARAMETERS);
160  mUserdefinedParameters = parameters;
161 }
162 
164 {
165  ACLBaseEnvelope envelope(*this);
166  if(other.contains(TO))
167  {
168  envelope.setTo(other.getTo());
169  }
170 
171  if(other.contains(FROM))
172  {
173  envelope.setFrom(other.getFrom());
174  }
175 
176  if(other.contains(COMMENTS))
177  {
178  envelope.setComments(other.getComments());
179  }
180 
181  if(other.contains(ACL_REPRESENTATION))
182  {
183  envelope.setACLRepresentation(other.getACLRepresentation());
184  }
185 
186  if(other.contains(PAYLOAD_LENGTH))
187  {
188  envelope.setPayloadLength(other.getPayloadLength());
189  }
190 
191  if(other.contains(PAYLOAD_ENCODING))
192  {
193  envelope.setPayloadEncoding(other.getPayloadEncoding());
194  }
195 
196  if(other.contains(DATE))
197  {
198  envelope.setDate(other.getDate());
199  }
200 
201  if(other.contains(INTENDED_RECEIVERS))
202  {
203  envelope.setIntendedReceivers(other.getIntendedReceivers());
204  }
205 
206  if(other.contains(RECEIVED_OBJECT))
207  {
208  envelope.setReceivedObject(other.getReceivedObject());
209  }
210 
211  if(other.contains(TRANSPORT_BEHAVIOUR))
212  {
214  }
215 
217  {
219  }
220 
221  return envelope;
222 }
223 
225 {
226  ACLBaseEnvelope envelope = *this;
227  ACLBaseEnvelopeList::const_iterator cit = extraEnvelopes.begin();
228  for(; cit != extraEnvelopes.end(); ++cit)
229  {
230  envelope = envelope.merge(*cit);
231  }
232 
233  return envelope;
234 }
235 
237 {}
238 
240 {
241  insert(message,representation);
242 }
243 
245 {
246  using namespace fipa::acl;
247  mPayload = MessageGenerator::create(message, representation);
248 
249  // infer fields from message
250  mBaseEnvelope.setTo(message.getAllReceivers());
251  // By default set the intended receivers
252  // Can be overriden by the user when creating the base envelope,
253  // however that should be avoided and only done by the transport service
254  mBaseEnvelope.setIntendedReceivers(mBaseEnvelope.getTo());
255  mBaseEnvelope.setFrom(message.getSender());
256  // comments have to be set explicitly, so not done here
257  mBaseEnvelope.setACLRepresentation(representation);
258  mBaseEnvelope.setPayloadLength(mPayload.size());
259  mBaseEnvelope.setPayloadEncoding(message.getEncoding());
260  mBaseEnvelope.setDate(base::Time::now());
261 
262  // intended receivers, received object and transport behaviour
263  // will not be set here but have to be either explicitly
264  // or by stamping the message
265 }
266 
268 {
269  AgentIDList deliveryPath;
270  if(mBaseEnvelope.contains(envelope::RECEIVED_OBJECT))
271  {
272  std::string hop = mBaseEnvelope.getReceivedObject().getBy();
273  deliveryPath.push_back(AgentID(hop));
274  }
275 
276  ACLBaseEnvelopeList::const_iterator cit = mExtraEnvelopes.begin();
277  for(; cit != mExtraEnvelopes.end();++cit)
278  {
279  if(cit->contains(envelope::RECEIVED_OBJECT))
280  {
281  std::string hop = cit->getReceivedObject().getBy();
282  deliveryPath.push_back(AgentID(hop));
283  }
284  }
285 
286  return deliveryPath;
287 }
288 
290 {
291  std::string pathString;
292  AgentIDList deliveryPath = getDeliveryPath();
293  AgentIDList::const_iterator cit = deliveryPath.begin();
294  for(; cit != deliveryPath.end();)
295  {
296  pathString += cit->getName();
297  if(++cit != deliveryPath.end())
298  {
299  pathString += ",";
300  }
301  }
302  return pathString;
303 }
304 
306 {
307  using namespace fipa::acl;
308  ACLMessage msg;
309  MessageParser mp;
310  // Get the LATEST representation (from flattened), not from base envelope!
311  representation::Type aclRepresentation = flattened().getACLRepresentation();
312  LOG_DEBUG_S << "getACLMessage from payload: " << mPayload << " with representation: " << representation::TypeTxt[aclRepresentation];
313  if( !mp.parseData(mPayload, msg, aclRepresentation ))
314  {
315  // TODO This makes the process crash, only if someone decides to send us a malformed message. Not so good...
316  throw std::runtime_error("ACLEnvelope::getACLMessage failed for representation '" + std::string(representation::TypeTxt[aclRepresentation]));
317  }
318  return msg;
319 }
320 
322 {
323  ReceivedObject receivedObject;
324 
325  // Mandatory fields
326  receivedObject.setBy(id.getName());
327  receivedObject.setDate(base::Time::now());
328 
329  receivedObject.setId(createLocalId());
330 
331  ACLBaseEnvelope extraEnvelope;
332  extraEnvelope.stamp(receivedObject);
333 
334  mExtraEnvelopes.push_back(extraEnvelope);
335 }
336 
338 {
339  ReceivedObject receivedObject;
340  receivedObject.setBy(id.getName());
341 
342  ACLBaseEnvelopeList::const_iterator cit = mExtraEnvelopes.begin();
343  for(; cit != mExtraEnvelopes.end(); ++cit)
344  {
345  if(cit->hasStamp(receivedObject))
346  {
347  return true;
348  }
349  }
350  return false;
351 }
352 
353 ID ACLEnvelope::createLocalId()
354 {
355  std::stringstream ss;
356  ss << ++mStampCounter;
357  ss << ":" << base::Time::now().toString();
358  return ss.str();
359 }
360 
362 {
363  fipa::acl::Letter updatedLetter = *this;
364  fipa::acl::ACLBaseEnvelope extraEnvelope;
365  AgentIDList intendedReceivers;
366  intendedReceivers.push_back(receiverId);
367  extraEnvelope.setIntendedReceivers(intendedReceivers);
368  updatedLetter.addExtraEnvelope(extraEnvelope);
369 
370  return updatedLetter;
371 }
372 
373 } // end namespace acl
374 } // end namespace fipa
std::string TransportBehaviour
Definition: acl_envelope.h:16
std::string ID
std::string Comments
Definition: acl_envelope.h:12
std::string getEncoding() const
Definition: acl_message.h:258
void setDate(const base::Time &date)
void stamp(const fipa::acl::AgentID &id)
The ACLBaseEnvelope defines the layout for an envelope with which ACLMessage data can be wrapped...
Definition: acl_envelope.h:36
static bool parseData(const std::string &storage, ACLMessage &msg, fipa::acl::representation::Type representation=fipa::acl::representation::BITEFFICIENT)
parses a correctly encoded message according to grammar_bitefficient.h and creates a Message object f...
const representation::Type & getACLRepresentation() const
Definition: acl_envelope.h:203
ACLMessage envelope (also typed as fipa::acl::Letter) includes the base envelope and updated fields...
Definition: acl_envelope.h:349
const PayloadLength & getPayloadLength() const
Definition: acl_envelope.h:226
void setComments(const Comments &comments)
const PayloadEncoding & getPayloadEncoding() const
Definition: acl_envelope.h:236
bool hasStamp(fipa::acl::AgentID id) const
const TransportBehaviour & getTransportBehaviour() const
Definition: acl_envelope.h:297
Definition: debug.h:28
static std::string create(const ACLMessage &msg, const representation::Type &acl_representation)
uint32_t PayloadLength
Definition: acl_envelope.h:13
Allows to parse a bytestream that conforms to the bitefficient representation of FIPA messages to a A...
std::vector< UserdefParam > UserdefinedParameterList
Definition: userdef_param.h:94
bool removeTo(const AgentID &agentId)
ACLBaseEnvelope merge(const ACLBaseEnvelope &other) const
const URL & getBy() const
std::vector< AgentID > AgentIDList
Definition: agent_id.h:20
bool contains(envelope::ParameterId id) const
Definition: acl_envelope.h:144
const base::Time & getDate() const
Definition: acl_envelope.h:246
const Comments & getComments() const
Definition: acl_envelope.h:191
const std::string TypeTxt[]
Definition: types.h:28
void insert(const ACLMessage &msg, const fipa::acl::representation::Type &format)
void setIntendedReceivers(const AgentIDList &receivers)
std::vector< ACLBaseEnvelope > ACLBaseEnvelopeList
Definition: acl_envelope.h:19
const AgentID & getFrom() const
Definition: acl_envelope.h:179
bool removeIntendedReceiver(const AgentID &agent)
void setId(const ID &id)
void setTo(const AgentIDList &receivers)
AgentIDList getDeliveryPath() const
AgentID getSender() const
Definition: acl_message.h:311
void stamp(const ReceivedObject &receivedObject)
Definition: acl_envelope.h:330
void addIntendedReceiver(const AgentID &agent)
This class provides a representation of a message conforming to the FIPA specification SC00061...
Definition: acl_message.h:55
void setUserdefinedParameters(const UserdefinedParameterList &parameters)
void setFrom(const AgentID &from)
fipa::acl::ACLMessage getACLMessage() const
void setACLRepresentation(representation::Type representation)
void addExtraEnvelope(const ACLBaseEnvelope &envelope)
Definition: acl_envelope.h:417
void setReceivedObject(const ReceivedObject &receivedObject)
void addTo(const AgentID &agent)
std::string PayloadEncoding
Definition: acl_envelope.h:14
void setPayloadEncoding(const PayloadEncoding &encoding)
ACLEnvelope createDedicatedEnvelope(const AgentID &receiverId) const
void setPayloadLength(const PayloadLength &length)
bool hasReceivedObject(const ReceivedObject &receivedObject) const
void setBy(const URL &by)
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
AgentIDList getAllReceivers() const
Definition: acl_message.h:166
const ReceivedObject & getReceivedObject() const
Definition: acl_envelope.h:281
ACLBaseEnvelope flatten(const ACLBaseEnvelopeList &extraEnvelopes) const
void setDate(const base::Time &date)
void setTransportBehaviour(const TransportBehaviour &transportBehaviour)
Agent Communication Language.
Definition: conversation.cpp:7
const AgentIDList & getIntendedReceivers() const
Definition: acl_envelope.h:256
const AgentIDList & getTo() const
Definition: acl_envelope.h:150
std::string getDeliveryPathString() const
const UserdefinedParameterList & getUserdefinedParameters() const
Definition: acl_envelope.h:307