1 #ifndef MESSAGINGUTILS_H_
2 #define MESSAGINGUTILS_H_
5 #include <QDomDocument>
9 //Namespace definitions
10 #define NS_XSI "http://www.w3.org/2001/XMLSchema-instance"
11 #define NS_XSD "http://www.w3.org/2001/XMLSchema"
12 #define NS_SOAP "http://schemas.xmlsoap.org/soap/envelope/"
13 #define NS_T "http://schemas.microsoft.com/exchange/services/2006/types"
14 #define NS_MSG "http://schemas.microsoft.com/exchange/services/2006/messages"
16 //Used for http request header to define web service operation
17 #define ACTION_URL "http://schemas.microsoft.com/exchange/services/2006/messages/"
19 //Set MessagingUtils Debug on/off
26 //All supported operations for web services
27 //Operations are described here: http://msdn.microsoft.com/en-us/library/bb409286.aspx
31 ReqCmdAddDelegate, //1
32 ReqCmdConvertId, //2 Used for converting fetched IDs to match the format in GetItem request
35 ReqCmdCreateAttachment, //5
36 ReqCmdCreateFolder, //6
38 ReqCmdCreateManagedFolder, //8
39 ReqCmdDeleteAttachment, //9
40 ReqCmdDeleteFolder, //10
41 ReqCmdDeleteItem, //11
43 ReqCmdFindFolder, //13
45 ReqCmdGetAttachment, //15
46 ReqCmdGetDelegate, //16
49 ReqCmdGetItem, //19 Used for getting the detailed information about some item (calendar event)
50 ReqCmdGetUserAvailability, //20 Used for fetching meetings
51 ReqCmdGetUserOofSettings, //21
52 ReqCmdMoveFolder, //22
54 ReqCmdRemoveDelegate, //24
55 ReqCmdResolveNames, //25
57 ReqCmdSetUserOofSettings, //27
59 ReqCmdSyncFolderHierarchy, //29
60 ReqCmdSyncFolderItems, //30
61 ReqCmdUnsubscribe, //31
62 ReqCmdUpdateDelegate, //32
63 ReqCmdUpdateFolder, //33
67 //TODO: Define more specific errors
74 //! Struct to present a node in SOAP envelope message.
76 * Struct to present a node in SOAP envelope message.
77 * Request messages are formed by using predefined arrays
78 * of MessageBodyElement objects.
80 typedef struct MessageBodyElement
82 //! Depth of the node in document tree. For example, root node should be 0.
84 //! Namespace of the node. QString::null if not specified.
88 //! Type of the node. Currently QDomNode::ElementNode and QDomNode::AttributeNode are supported.
89 QDomNode::NodeType iNodeType;
92 //SOAP Envelope templates for web service operations
93 //Operations are described here: http://msdn.microsoft.com/en-us/library/bb409286.aspx
96 * - First node's TraversalLevel must always be 0.
97 * - Namespace can be defined as an URI or QString::null
98 * - NodeType can be QDomNode::ElementNode or QDomNode::AttributeNode
99 * - Nodes must be defined in descending order, according to schema.
100 * - Attribute must be defined right after it's owner element and it's traversal level must be same.
102 const MessageBodyElement reqCmdArrayEnvelopeBase[] =
104 { 0, NS_SOAP, "Envelope", QDomNode::ElementNode }/*,
105 { 0, "xmlns", "xsi", QDomNode::AttributeNode },
106 { 0, "xmlns", "xsd", QDomNode::AttributeNode },
107 { 0, "xmlns", "soap", QDomNode::AttributeNode },
108 { 0, "xmlns", "t", QDomNode::AttributeNode },*/
111 const MessageBodyElement reqCmdMailboxElement[] =
113 { 0, NS_T, "MailboxData", QDomNode::ElementNode },
114 { 1, NS_T, "Email", QDomNode::ElementNode },
115 { 2, NS_T, "Address", QDomNode::ElementNode },
116 { 1, NS_T, "AttendeeType", QDomNode::ElementNode },
117 { 1, NS_T, "ExcludeConflicts", QDomNode::ElementNode },
120 const MessageBodyElement reqCmdArrayGetUserAvailability[] =
122 { 0, NS_SOAP, "Body", QDomNode::ElementNode },
123 { 1, NS_MSG, "GetUserAvailabilityRequest", QDomNode::ElementNode },
124 { 2, NS_T, "TimeZone", QDomNode::ElementNode },
125 { 3, QString::null, "Bias", QDomNode::ElementNode },
126 { 3, QString::null, "StandardTime", QDomNode::ElementNode },
127 { 4, QString::null, "Bias", QDomNode::ElementNode },
128 { 4, QString::null, "Time", QDomNode::ElementNode },
129 { 4, QString::null, "DayOrder", QDomNode::ElementNode },
130 { 4, QString::null, "Month", QDomNode::ElementNode },
131 { 4, QString::null, "DayOfWeek", QDomNode::ElementNode },
133 { 3, QString::null, "DaylightTime", QDomNode::ElementNode },
134 { 4, QString::null, "Bias", QDomNode::ElementNode },
135 { 4, QString::null, "Time", QDomNode::ElementNode },
136 { 4, QString::null, "DayOrder", QDomNode::ElementNode },
137 { 4, QString::null, "Month", QDomNode::ElementNode },
138 { 4, QString::null, "DayOfWeek", QDomNode::ElementNode },
141 //Use meetingroom addresses to fetch meetings for rooms. Mailboxdata-element for each.
142 { 2, QString::null, "MailboxDataArray", QDomNode::ElementNode },
144 //MAILBOX DATA(s) MUST BE ADDED AFTERWARDS
145 //SEE: reqCmdMailboxElement[]
147 //</mailboxdeataarray>
148 { 2, NS_T, "FreeBusyViewOptions", QDomNode::ElementNode },
149 //Use Timewindow to define from which period we want to fetch meetings
150 { 3, NS_T, "TimeWindow", QDomNode::ElementNode },
151 { 4, NS_T, "StartTime", QDomNode::ElementNode },
152 { 4, NS_T, "EndTime", QDomNode::ElementNode },
154 { 3, NS_T, "MergedFreeBusyIntervalInMinutes", QDomNode::ElementNode },
155 { 3, NS_T, "RequestedView", QDomNode::ElementNode },
156 //</freebusyviewoptions>
157 //</getuseravailabilityrequest>
160 const MessageBodyElement reqCmdArrayGetCalendarItem[] =
162 { 0, NS_SOAP, "Body", QDomNode::ElementNode },
163 { 1, NS_MSG, "GetItem", QDomNode::ElementNode },
164 //{ 1, QString::null, "xmlns", QDomNode::AttributeNode },
165 { 2, QString::null, "ItemShape", QDomNode::ElementNode },
166 { 3, NS_T, "BaseShape", QDomNode::ElementNode },
167 { 2, QString::null, "ItemIds", QDomNode::ElementNode },
168 { 3, NS_T, "ItemId", QDomNode::ElementNode },
169 { 3, QString::null, "Id", QDomNode::AttributeNode }
172 const MessageBodyElement reqCmdArrayConvertIdHeader[] =
174 { 0, NS_SOAP, "Header", QDomNode::ElementNode },
175 { 1, NS_T, "RequestServerVersion", QDomNode::ElementNode },
176 { 1, QString::null, "Version", QDomNode::AttributeNode },
180 const MessageBodyElement reqCmdArrayConvertId[] =
182 { 0, NS_SOAP, "Body", QDomNode::ElementNode },
183 { 1, NS_MSG, "ConvertId", QDomNode::ElementNode },
184 //{ 1, QString::null, "xmlns:t", QDomNode::AttributeNode },
185 //{ 2, "xmlns", "t", QDomNode::AttributeNode },
186 { 1, QString::null, "DestinationFormat", QDomNode::AttributeNode },
187 { 2, QString::null, "SourceIds", QDomNode::ElementNode },
188 { 3, NS_T, "AlternateId", QDomNode::ElementNode },
189 { 3, QString::null, "Format", QDomNode::AttributeNode },
190 { 3, QString::null, "Id", QDomNode::AttributeNode },
191 { 3, QString::null, "Mailbox", QDomNode::AttributeNode },
195 //! Base class for Request and Response message classes
197 * This class provides basic functionality to use generated SOAP envelope DomDocument object.
199 class BaseMessage : public QObject
208 virtual ~BaseMessage();
210 //! Current generated SOAP envelope DomDocument object as byte array.
212 * Returns current message envelope as byte array.
213 * This array is used to provide a content for http request.
214 * \return current message envelope as byte array.
216 QByteArray getMessage();
220 //! List of QDomNode objects matching desired criteria.
222 * Returns a list of nodes that matches the given aNodeName.
223 * Optional parameters can be provided to narrow the search.
224 * \param aNodeName Name of the node(s).
225 * \param aParentName Name of the parent node. Optional.
226 * If not specified, base node of the QDomDocument is used.
227 * \param aRootNode Root node for the search. Optional.
228 * If provided, only it's childnodes will be searched.
229 * If not specified, base node of the QDomDocument is used.
230 * \return List of QDomNodes matching the criteria.
232 QList<QDomNode> getNodesByName( const QString& aNodeName,
233 const QString& aParentName = QString::null,
234 QDomNode* aRootNode = NULL );
236 //! Single node matching desired criteria.
238 * Returns a single node that matches the given aNodeName.
239 * Optional parameters can be provided to narrow the search.
240 * \param aNodeName Name of the node.
241 * \param aNodeType Type of the node. Currently QDomNode::ElementNode and QDomNode::AttributeNode are supported.
242 * \param aParentName Name of the parent node. Optional.
243 * If not specified, base node of the QDomDocument is used.
244 * \param aIndex If multiple results are found, an index of desired node can be used. Optional.
245 * \param aRootNode Root node for the search. Optional.
246 * If provided, only it's childnodes will be searched.
247 * If not specified, base node of the QDomDocument is used.
248 * \return QDomNode matching the criteria.
250 QDomNode getNodeFromDocument( const QString& aNodeName,
251 QDomNode::NodeType aNodeType,
252 const QString& aParentName = QString::null,
254 QDomNode* aRootNode = NULL );
256 //! Single element matching desired criteria.
258 * See getNodeFromDocument for details.
260 QDomNode getElementFromDocument( const QString& aElementName,
261 const QString& aParentName = QString::null,
263 QDomNode* aRootNode = NULL );
265 //! Single attribute matching desired criteria.
267 * See getNodeFromDocument for details.
269 QDomNode getAttributeFromDocument( const QString& aAttributeName,
270 const QString& aParentName = QString::null,
272 QDomNode* aRootNode = NULL );
274 //! Compare node name to string.
276 * Checks if name of the provided node matches aName.
277 * Node can be QDomNode::ElementNode or QDomNode::AttributeNode.
278 * \param aNode Node to compare.
279 * \param aName Name to compare.
280 * \return True if comparison matches. Otherwise false.
281 * NOTE: This function does comparison for node's local name, so it ignores possible prefixes in a tag name.
283 bool matchName( const QDomNode& aNode, const QString& aName );
290 * Current generated SOAP envelope DomDocument object.
292 QDomDocument* iMessage;
296 //! Base class for Requests
298 * This class provides basic functionality to use generated SOAP envelope DomDocument object for http requests.
300 class RequestMessage : public BaseMessage
307 * \param aCommandId Id to identify operation type.
309 RequestMessage( RequestCommandId aCommandId = ReqCmdNoCommand );
310 RequestMessage( const QString& aFileName );
312 virtual ~RequestMessage(){};
316 //! Add node to message
318 * Adds node to a request message. Parameters can be provided to specify location.
319 * \param aNode Node to add.
320 * \param aNodeType Type of node. QDomNode::ElementNode and QDomNode::AttributeNode are supported. Default is QDomNode::ElementNode.
321 * \param aParentName Name of the parent. Optional. If provided, node will be added as it's child. Otherwise root of the QDomDocument is used.
322 * \param aIndex Index to add. Optional. If multiple parents are found, index to add can be specified.
323 * \param aRootNode Root node to search. Optional. Searches only it's child nodes for a parent if provided. Otherwise root of the QDomDocument is used.
324 * \return An error code.
326 int addNode( const QDomNode& aNode,
327 QDomNode::NodeType aNodeType = QDomNode::ElementNode,
328 const QString& aParentName = QString::null,
330 QDomNode* aRootNode = NULL );
332 //! Set value of the node
334 * Sets the value of specified node. Parameters can be used to narrow the search.
335 * \param aNodeName Name of the node.
336 * \param aValue Value to set.
337 * \param aNodeType Type of node. QDomNode::ElementNode and QDomNode::AttributeNode are supported. Default is QDomNode::ElementNode.
338 * \param aParentName Name of the parent node. Optional.
339 * If not specified, base node of the QDomDocument is used.
340 * \param aIndex If multiple results are found, an index of desired node can be used. Optional.
341 * \param aRootNode Root node for the search. Optional.
342 * If provided, only it's childnodes will be searched.
343 * If not specified, base node of the QDomDocument is used.
344 * \return An error code.
346 int setNodeValue( const QString& aNodeName,
347 const QString& aValue,
348 QDomNode::NodeType aNodeType = QDomNode::ElementNode,
349 const QString& aParentName = QString::null,
351 QDomNode* aRootNode = NULL );
353 //! Create the structure of message (soap:Body)
355 * \return An error code.
357 int createMessageStructure();
358 //! Create the structure of message (soap:Body)
360 * \param aCommandId Id of command. Structure is constructed according to this.
361 * \return An error code.
363 int createMessageStructure( RequestCommandId aCommandId );
365 //! Create the base of the request envelope (soap:Envelope)
367 * \return An error code.
369 int createEnvelopeBase();
371 //! Get operation specific content type string for http request header.
373 * \param aCommandId Id of the command (operation)
374 * \return Content type string for header
376 QString getContentTypeForHeader( RequestCommandId aCommandId = ReqCmdNoCommand );
380 //! Construct an array of MessageBodyElements to a node.
382 * Constructs an array of predefined MessageBodyElements to node.
383 * This function is used to form different parts of message from MessageBodyElements to QDomNodes
384 * \param aArray Array of MessageBodyElements.
385 * \param aSize Size of an array.
386 * \return Created node.
388 QDomNode constructArrayToNode( const MessageBodyElement* aArray, int aSize );
392 //! Id of current operation
393 RequestCommandId iCurrCmd;
396 //! Base class for Responses.
398 * This class provides basic functionality to use generated SOAP envelope DomDocument object from http responses.
400 class ResponseMessage : public BaseMessage
410 * \param aData Byte array to construct ResponseMessage from.
412 ResponseMessage( const QByteArray& aData );
415 virtual ~ResponseMessage(){};
417 //! Get the value of node.
419 * Gets a value of single node. Optional parameters are used to define desired node in more detail.
420 * \param aNodeName Name of the node.
421 * \param aNodeType Type of the node. QDomNode::ElementNode and QDomNode::AttributeNode are supported.
422 * \param aParentname Name of the parent node. Optional. Can be specified to narrow the search.
423 * \param aIndex Index of the node. Optional. If multiple results are found, index can be defined to specify the result.
424 * \param aRootNode Root node. Optional. If specified, only it's children are included in search. Otherwise, root node of QDomDocument is used.
425 * \return Value of the node.
427 QString getNodeValue( const QString& aNodeName,
428 QDomNode::NodeType aNodeType,
429 const QString& aParentName = QString::null,
431 QDomNode* aRootNode = NULL );
433 //! Checks if there are any errors in response.
435 * If any value of status elements in response message is not success, this function
437 * \return True if errors exist. Otherwise false.
446 //Operation specific inherited classes
449 //! Request message for GetUserAvailability operation.
450 class ReqMsgGetUserAvailability : public RequestMessage
453 enum UserAttendeeType
455 AttendeeOrganizer = 0,
465 ReqMsgGetUserAvailability();
467 virtual ~ReqMsgGetUserAvailability(){};
468 //! Set the current time zone.
470 * \return An error code.
472 int setTimeZone(); //TODO: initializable with parameters?
474 //! Add user (mailbox) to search availability status from.
476 * Add user (mailbox) to search calendar events from.
477 * Multiple users can be added in one request.
478 * \param aAddress User's EMail address.
479 * \param aAttendeeType Type of the attendance. Default is "Required".
480 * \param aExcludeConflicts Exclude conflicting meetings. Default is "false".
481 * \return An error code.
483 int addUser( const QString& aAddress, const QString& aAttendeeType = "Required", const QString& aExcludeConflicts = "false" ); //TODO: Is resource a correct type for room?
485 //! Set the time window for request.
487 * Set the time window to search availability statuses from.
488 * \param aStart Start date time.
489 * \param aEnd End date time.
490 * \return An error code.
491 * NOTE: Server might give an error if too wide time window is specified.
492 * ~3 weeks should be safe.
494 int setTimeWindow( const QDateTime& aStart, const QDateTime& aEnd );
500 //! Request message for ConvertId operation.
502 * This is used to convert HexEntryId type unique Id's of calendar events
503 * To EwsLegacyId type. Latter type of Id must be provided in order to get detailed information for calendar event.
505 class ReqMsgConvertMeetingId : public RequestMessage
510 * \param aItemId HexEntryId type Id to convert. Optional (though must be set later).
511 * \param aMailBox EMail address of calendar event's owner.
513 ReqMsgConvertMeetingId( const QString& aItemId = QString::null, const QString& aMailbox = QString::null );
516 virtual ~ReqMsgConvertMeetingId(){};
520 * \param aItemId Id of calendar event in HexEntryId format
521 * \return An error code.
523 int setItemId( const QString& aItemId );
527 * Set the calendar event owner's mailbox EMail address.
528 * \param aMailBox Mailbox address.
529 * \return An error code.
531 int setMailbox( const QString& aMailbox );
537 //! Request message for GetItem (Calendar) operation.
539 * This is used to get more detailed information about calendar event.
541 class ReqMsgGetCalendarItem : public RequestMessage
547 * \param aItemId secondary Id ( EwsLegacyId type obtained from ConvertId operation ) of calendar event.
549 ReqMsgGetCalendarItem( const QString& aItemId = QString::null );
552 virtual ~ReqMsgGetCalendarItem(){};
554 //! Set the Id of calendar event.
556 * This must be EwsLegacyId type obtained from ConvertId operation.
557 * \param aItemId Id of item.
558 * \return An error code.
560 int setItemId( const QString& aItemId );
561 //int setChangeKey( const QString& aChangeKey ){};
567 //! Response message for GetUserAvailability operation.
568 class ResMsgGetUserAvailability : public ResponseMessage
574 * \param aData Byte array to construct response message from.
576 ResMsgGetUserAvailability( const QByteArray& aData );
579 virtual ~ResMsgGetUserAvailability(){};
580 //! Get Meetings from constructed response.
582 * \param aList List of Meeting objects to fill.
583 * \param aRoom Room for Meeting objects.
584 * \return An error code.
586 int getMeetingsFromResponse( QList<Meeting*>& aList, const Room &aRoom );
589 //! Response message for GetItem (Calendar) operation.
590 class ResMsgGetCalendarItem : public ResponseMessage
595 * \param aData Byte array to construct response message from.
597 ResMsgGetCalendarItem( const QByteArray& aData ) : ResponseMessage( aData ){};
600 virtual ~ResMsgGetCalendarItem(){};
602 //! Get meeting details from constructed response.
604 * \param aMeeting Meeting to get details for.
605 * \return An error code.
607 int getMeetingDetailsFromResponse( Meeting& aMeeting );
611 #endif /*MESSAGINGUTILS_H_*/