qtmeetings sources to Maemo garage
[qtmeetings] / src / IO / Communication / MessagingUtils.h
1 #ifndef MESSAGINGUTILS_H_
2 #define MESSAGINGUTILS_H_
3
4 #include <QObject>
5 #include <QDomDocument>
6 #include <QDateTime>
7 #include <QStringList>
8
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"
15
16 //Used for http request header to define web service operation
17 #define ACTION_URL "http://schemas.microsoft.com/exchange/services/2006/messages/"
18
19 //Set MessagingUtils Debug on/off
20 //#define MU_DEBUG
21 #undef MU_DEBUG
22
23 class Meeting;
24 class Room;
25
26 //All supported operations for web services
27 //Operations are described here: http://msdn.microsoft.com/en-us/library/bb409286.aspx
28 enum RequestCommandId
29 {
30         ReqCmdNoCommand = 0,
31         ReqCmdAddDelegate, //1
32         ReqCmdConvertId, //2 Used for converting fetched IDs to match the format in GetItem request
33         ReqCmdCopyFolder, //3
34         ReqCmdCopyItem, //4
35         ReqCmdCreateAttachment, //5
36         ReqCmdCreateFolder, //6
37         ReqCmdCreateItem, //7
38         ReqCmdCreateManagedFolder, //8
39         ReqCmdDeleteAttachment, //9
40         ReqCmdDeleteFolder, //10
41         ReqCmdDeleteItem, //11
42         ReqCmdExpandDL, //12
43         ReqCmdFindFolder, //13
44         ReqCmdFindItem, //14
45         ReqCmdGetAttachment, //15
46         ReqCmdGetDelegate, //16
47         ReqCmdGetEvents, //17
48         ReqCmdGetFolder, //18
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
53         ReqCmdMoveItem, //23
54         ReqCmdRemoveDelegate, //24
55         ReqCmdResolveNames, //25
56         ReqCmdSendItem, //26
57         ReqCmdSetUserOofSettings, //27
58         ReqCmdSubscribe, //28
59         ReqCmdSyncFolderHierarchy, //29
60         ReqCmdSyncFolderItems, //30
61         ReqCmdUnsubscribe, //31
62         ReqCmdUpdateDelegate, //32
63         ReqCmdUpdateFolder, //33
64         ReqCmdUpdateItem //34
65 };
66
67 //TODO: Define more specific errors
68 enum MessagingError
69 {
70         MsgErrNoError = 0,
71         MsgErrSomeError
72 };
73
74 //! Struct to present a node in SOAP envelope message.
75 /*!
76  *      Struct to present a node in SOAP envelope message.
77  *  Request messages are formed by using predefined arrays
78  *  of MessageBodyElement objects.
79  */
80 typedef struct MessageBodyElement
81 {
82         //! Depth of the node in document tree. For example, root node should be 0.
83         int iTraversalLevel;
84         //! Namespace of the node. QString::null if not specified.
85         QString iNamespace;
86         //! Name of the node.
87         QString iElementName;
88         //! Type of the node. Currently QDomNode::ElementNode and QDomNode::AttributeNode are supported.
89         QDomNode::NodeType iNodeType;
90 };
91
92 //SOAP Envelope templates for web service operations
93 //Operations are described here: http://msdn.microsoft.com/en-us/library/bb409286.aspx
94 /*
95  * NOTES: 
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.
101  */
102 const MessageBodyElement reqCmdArrayEnvelopeBase[] =
103 {
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 },*/
109 };
110
111 const MessageBodyElement reqCmdMailboxElement[] =
112 {
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 },
118 };
119
120 const MessageBodyElement reqCmdArrayGetUserAvailability[] =
121 {
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 },
132                 //</standardtime>
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 },
139                 //</daylighttime>
140                 //</timezone>
141                 //Use meetingroom addresses to fetch meetings for rooms. Mailboxdata-element for each.
142                 { 2, QString::null, "MailboxDataArray", QDomNode::ElementNode },
143
144                 //MAILBOX DATA(s) MUST BE ADDED AFTERWARDS
145                 //SEE: reqCmdMailboxElement[]
146
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 },
153                 //</timewindow>
154                 { 3, NS_T, "MergedFreeBusyIntervalInMinutes", QDomNode::ElementNode },
155                 { 3, NS_T, "RequestedView", QDomNode::ElementNode },
156                 //</freebusyviewoptions>
157                 //</getuseravailabilityrequest>
158 };
159
160 const MessageBodyElement reqCmdArrayGetCalendarItem[] =
161 {
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 }
170 };
171
172 const MessageBodyElement reqCmdArrayConvertIdHeader[] =
173 {
174                 { 0, NS_SOAP, "Header", QDomNode::ElementNode },
175                 { 1, NS_T, "RequestServerVersion", QDomNode::ElementNode },
176                 { 1, QString::null, "Version", QDomNode::AttributeNode },
177
178 };
179
180 const MessageBodyElement reqCmdArrayConvertId[] =
181 {
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 },
192 };
193
194
195 //! Base class for Request and Response message classes
196 /*!
197  *  This class provides basic functionality to use generated SOAP envelope DomDocument object.
198  */
199 class BaseMessage : public QObject
200 {
201         Q_OBJECT
202
203 public:
204
205         //! Constructor.
206         BaseMessage();
207         //! Destructor.
208         virtual ~BaseMessage();
209
210         //! Current generated SOAP envelope DomDocument object as byte array.
211         /*!
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.
215          */ 
216         QByteArray getMessage();
217
218 protected:
219
220         //! List of QDomNode objects matching desired criteria.
221         /*!
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.
231          */
232         QList<QDomNode> getNodesByName( const QString& aNodeName,
233                                                                         const QString& aParentName = QString::null,
234                                                                         QDomNode* aRootNode = NULL );
235
236         //! Single node matching desired criteria.
237         /*!
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.
249          */
250         QDomNode getNodeFromDocument( const QString& aNodeName,
251                                                                         QDomNode::NodeType aNodeType,
252                                                                         const QString& aParentName = QString::null,
253                                                                         int aIndex = 0,
254                                                                         QDomNode* aRootNode = NULL );
255
256         //! Single element matching desired criteria.
257         /*!
258          *  See getNodeFromDocument for details.
259          */
260         QDomNode getElementFromDocument( const QString& aElementName,
261                                                                         const QString& aParentName = QString::null,
262                                                                         int aIndex = 0,
263                                                                         QDomNode* aRootNode = NULL );
264         
265         //! Single attribute matching desired criteria.
266         /*!
267          *  See getNodeFromDocument for details.
268          */
269         QDomNode getAttributeFromDocument( const QString& aAttributeName,
270                                                                         const QString& aParentName = QString::null,
271                                                                         int aIndex = 0,
272                                                                         QDomNode* aRootNode = NULL );
273
274         //! Compare node name to string.
275         /*!
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.
282          */
283         bool matchName( const QDomNode& aNode, const QString& aName  );
284
285
286
287 protected:
288
289         /*!
290          * Current generated SOAP envelope DomDocument object.
291          */
292         QDomDocument* iMessage;
293
294 };
295
296 //! Base class for Requests
297 /*!
298  *  This class provides basic functionality to use generated SOAP envelope DomDocument object for http requests.
299  */
300 class RequestMessage : public BaseMessage
301 {
302
303 public:
304
305         //! Constructor
306         /*!
307          * \param aCommandId Id to identify operation type.
308          */
309         RequestMessage( RequestCommandId aCommandId = ReqCmdNoCommand );
310         RequestMessage( const QString& aFileName );
311         //! Destructor
312         virtual ~RequestMessage(){};
313
314 public:
315
316         //! Add node to message
317         /*!
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.
325          */
326         int addNode( const QDomNode& aNode,
327                                         QDomNode::NodeType aNodeType = QDomNode::ElementNode,
328                                         const QString& aParentName = QString::null,
329                                         int aIndex = 0,
330                                         QDomNode* aRootNode = NULL );
331
332         //! Set value of the node
333         /*!
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.
345          */
346         int setNodeValue( const QString& aNodeName,
347                                                 const QString& aValue,
348                                                 QDomNode::NodeType aNodeType = QDomNode::ElementNode,
349                                                 const QString& aParentName = QString::null,
350                                                 int aIndex = 0,
351                                                 QDomNode* aRootNode = NULL );
352
353         //! Create the structure of message (soap:Body)
354         /*
355          * \return An error code.
356          */
357         int createMessageStructure();
358         //! Create the structure of message (soap:Body)
359         /*
360          * \param aCommandId Id of command. Structure is constructed according to this.
361          * \return An error code.
362          */
363         int createMessageStructure( RequestCommandId aCommandId );
364         
365         //! Create the base of the request envelope (soap:Envelope)
366         /*!
367          * \return An error code.
368          */
369         int createEnvelopeBase();
370
371         //! Get operation specific content type string for http request header.
372         /*!
373          * \param aCommandId Id of the command (operation)
374          * \return Content type string for header
375          */
376         QString getContentTypeForHeader( RequestCommandId aCommandId = ReqCmdNoCommand );
377
378 protected:
379
380         //! Construct an array of MessageBodyElements to a node.
381         /*!
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.
387          */
388         QDomNode constructArrayToNode( const MessageBodyElement* aArray, int aSize );
389         
390 protected:
391
392         //! Id of current operation
393         RequestCommandId iCurrCmd;
394 };
395
396 //! Base class for Responses.
397 /*!
398  *  This class provides basic functionality to use generated SOAP envelope DomDocument object from http responses.
399  */
400 class ResponseMessage : public BaseMessage
401 {
402
403 public:
404
405         //! Constructor
406         ResponseMessage();
407
408         //! Constructor
409         /*!
410          * \param aData Byte array to construct ResponseMessage from.
411          */
412         ResponseMessage( const QByteArray& aData );
413
414         //! Destructor
415         virtual ~ResponseMessage(){};
416
417         //! Get the value of node.
418         /*!
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.
426          */
427         QString getNodeValue( const QString& aNodeName,
428                                                         QDomNode::NodeType aNodeType,
429                                                         const QString& aParentName = QString::null,
430                                                         int aIndex = 0,
431                                                         QDomNode* aRootNode = NULL );
432
433         //! Checks if there are any errors in response.
434         /*!
435          *  If any value of status elements in response message is not success, this function
436          *  returns true.
437          * \return True if errors exist. Otherwise false.
438          */
439         bool hasErrors();
440
441 protected:
442
443 };
444
445
446 //Operation specific inherited classes
447
448
449 //! Request message for GetUserAvailability operation.
450 class ReqMsgGetUserAvailability : public RequestMessage
451 {
452
453         enum UserAttendeeType
454         {
455                 AttendeeOrganizer = 0,
456                 AttendeeRequired,
457                 AttendeeOptional,
458                 AttendeeRoom,
459                 AttendeeResource
460         };
461
462 public:
463
464         //! Constructor
465         ReqMsgGetUserAvailability();
466         //! Destructor
467         virtual ~ReqMsgGetUserAvailability(){};
468         //! Set the current time zone.
469         /*
470          * \return An error code.
471          */
472         int setTimeZone(); //TODO: initializable with parameters?
473         
474         //! Add user (mailbox) to search availability status from.
475         /*
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.
482          */
483         int addUser( const QString& aAddress, const QString& aAttendeeType = "Required", const QString& aExcludeConflicts = "false" ); //TODO: Is resource a correct type for room?
484         
485         //! Set the time window for request.
486         /*!
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.
493          */
494         int setTimeWindow( const QDateTime& aStart, const QDateTime& aEnd );
495
496 private:
497
498 };
499
500 //! Request message for ConvertId operation.
501 /*!
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.
504  */
505 class ReqMsgConvertMeetingId : public RequestMessage
506 {
507 public:
508         //! Constructor
509         /*!
510          * \param aItemId HexEntryId type Id to convert. Optional (though must be set later).
511          * \param aMailBox EMail address of calendar event's owner.
512          */
513         ReqMsgConvertMeetingId( const QString& aItemId = QString::null, const QString& aMailbox = QString::null );
514         
515         //! Destructor
516         virtual ~ReqMsgConvertMeetingId(){};
517         
518         //! Set item id.
519         /*
520          * \param aItemId Id of calendar event in HexEntryId format
521          * \return An error code.
522          */
523         int setItemId( const QString& aItemId );
524         
525         //! Set Mailbox.
526         /*!
527          *  Set the calendar event owner's mailbox EMail address.
528          * \param aMailBox Mailbox address.
529          * \return An error code.
530          */
531         int setMailbox( const QString& aMailbox );
532         
533 private:
534         
535 };
536
537 //! Request message for GetItem (Calendar) operation.
538 /*!
539  *  This is used to get more detailed information about calendar event.
540  */
541 class ReqMsgGetCalendarItem : public RequestMessage
542 {
543 public:
544
545         //! Constructor
546         /*!
547          * \param aItemId secondary Id ( EwsLegacyId type obtained from ConvertId operation ) of calendar event.
548          */
549         ReqMsgGetCalendarItem( const QString& aItemId = QString::null );
550         
551         //! Destructor
552         virtual ~ReqMsgGetCalendarItem(){};
553         
554         //! Set the Id of calendar event.
555         /*!
556          * This must be EwsLegacyId type obtained from ConvertId operation.
557          * \param aItemId Id of item.
558          * \return An error code.
559          */
560         int setItemId( const QString& aItemId );        
561         //int setChangeKey( const QString& aChangeKey ){};
562         
563 private:
564
565 };
566
567 //! Response message for GetUserAvailability operation.
568 class ResMsgGetUserAvailability : public ResponseMessage
569 {
570 public:
571
572         //! Constructor
573         /*!
574          * \param aData Byte array to construct response message from.
575          */
576         ResMsgGetUserAvailability( const QByteArray& aData );
577         
578         //! Destructor
579         virtual ~ResMsgGetUserAvailability(){};
580         //! Get Meetings from constructed response.
581         /*!
582          * \param aList List of Meeting objects to fill.
583          * \param aRoom Room for Meeting objects.
584          * \return An error code.
585          */
586         int getMeetingsFromResponse( QList<Meeting*>& aList, const Room &aRoom );
587 };
588
589 //! Response message for GetItem (Calendar) operation.
590 class ResMsgGetCalendarItem : public ResponseMessage
591 {
592 public:
593         //! Constructor
594         /*!
595          * \param aData Byte array to construct response message from.
596          */
597         ResMsgGetCalendarItem( const QByteArray& aData ) : ResponseMessage( aData ){};
598         
599         //! Destructor
600         virtual ~ResMsgGetCalendarItem(){};
601         
602         //! Get meeting details from constructed response.
603         /*!
604          * \param aMeeting Meeting to get details for.
605          * \return An error code.
606         */
607         int getMeetingDetailsFromResponse( Meeting& aMeeting );
608
609 };
610
611 #endif /*MESSAGINGUTILS_H_*/