Merge "Review libteec API cs files"
[platform/core/csapi/tizenfx.git] / src / Tizen.Pims.Contacts / Tizen.Pims.Contacts / ContactsDatabase.cs
1 /*
2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 using System;
18 using System.Collections.Generic;
19 using System.Diagnostics.CodeAnalysis;
20 using System.Runtime.InteropServices;
21
22 namespace Tizen.Pims.Contacts
23 {
24     /// <summary>
25     /// Delegate for detecting the contacts database changes
26     /// </summary>
27     /// <param name="uri">The contacts view URI</param>
28     /// <remarks>
29     /// The delegate must be registered using AddDBChangedDelegate.
30     /// It's invoked when the designated view changes.
31     /// </remarks>
32     public delegate void ContactsDBChanged(string uri);
33
34     /// <summary>
35     /// ContactsDatabase provides methods to manage contacts information from/to the database.
36     /// </summary>
37     /// <remarks>
38     /// This class allows user to access/create/update db operations for contacts information.
39     /// </remarks>
40     public class ContactsDatabase
41     {
42         private Object thisLock = new Object();
43         private Interop.Database.ContactsDBStatusChangedCallback _contactsDBStatusChangedCallback;
44         private EventHandler<DBStatusChangedEventArgs> _dbStatusChanged;
45         private Dictionary<string, ContactsDBChanged> _delegateMap = new Dictionary<string, ContactsDBChanged>();
46         private Dictionary<string, Interop.Database.ContactsDBChangedCallback> _callbackMap = new Dictionary<string, Interop.Database.ContactsDBChangedCallback>();
47         private Interop.Database.ContactsDBChangedCallback _dbChangedDelegate;
48
49         internal ContactsDatabase()
50         {
51             /*To be created in ContactsManager only.*/
52         }
53
54         /// <summary>
55         /// Enumeration for contacts database status.
56         /// </summary>
57         public enum DBStatus
58         {
59             /// <summary>
60             /// Normal
61             /// </summary>
62             Normal,
63             /// <summary>
64             /// Changing collation.
65             /// </summary>
66             ChangingCollation
67         }
68
69         /// <summary>
70         /// Enumeration for Contacts search range.
71         /// </summary>
72         [Flags]
73         public enum SearchRanges
74         {
75             /// <summary>
76             /// None
77             /// </summary>
78             None = 0,
79             /// <summary>
80             /// Search record from name
81             /// </summary>
82             Name = 0x00000001,
83             /// <summary>
84             /// Search record from number
85             /// </summary>
86             Number = 0x00000002,
87             /// <summary>
88             /// Search record from data
89             /// </summary>
90             Data = 0x00000004,
91             /// <summary>
92             /// Search record from email. Now, support only PersonEmail view
93             /// </summary>
94             Email = 0x00000008,
95         }
96
97         /// <summary>
98         /// Occurs when contacts database status is changed.
99         /// </summary>
100         public event EventHandler<DBStatusChangedEventArgs> DBStatusChanged
101         {
102             add
103             {
104                 lock (thisLock)
105                 {
106                     if (_contactsDBStatusChangedCallback == null)
107                     {
108                         _contactsDBStatusChangedCallback = (DBStatus status, IntPtr userData) =>
109                         {
110                             DBStatusChangedEventArgs args = new DBStatusChangedEventArgs(status);
111                             _dbStatusChanged?.Invoke(this, args);
112                         };
113                     }
114
115                     if (_dbStatusChanged == null)
116                     {
117                         int error = Interop.Database.AddStatusChangedCb(_contactsDBStatusChangedCallback, IntPtr.Zero);
118                         if ((int)ContactsError.None != error)
119                         {
120                             Log.Error(Globals.LogTag, "Add StatusChanged Failed with error " + error);
121                         }
122                     }
123
124                     _dbStatusChanged += value;
125                 }
126
127             }
128
129             remove
130             {
131                 lock (thisLock)
132                 {
133                     _dbStatusChanged -= value;
134
135                     if (_dbStatusChanged == null)
136                     {
137                         int error = Interop.Database.RemoveStatusChangedCb(_contactsDBStatusChangedCallback, IntPtr.Zero);
138                         if ((int)ContactsError.None != error)
139                         {
140                             Log.Error(Globals.LogTag, "Remove StatusChanged Failed with error " + error);
141                         }
142                     }
143                 }
144             }
145
146         }
147
148         /// <summary>
149         /// The current contacts database version.
150         /// </summary>
151         /// <value>The current contacts database version.</value>
152         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
153         public int Version
154         {
155             get
156             {
157                 int version = -1;
158                 int error = Interop.Database.GetVersion(out version);
159                 if ((int)ContactsError.None != error)
160                 {
161                     Log.Error(Globals.LogTag, "Version Failed with error " + error);
162                 }
163                 return version;
164             }
165         }
166
167         /// <summary>
168         /// The last successful changed contacts database version on the current connection.
169         /// </summary>
170         /// <value>The last successful changed contacts database version on the current connection.</value>
171         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
172         public int LastChangeVersion
173         {
174             get
175             {
176                 int version = -1;
177                 int error = Interop.Database.GetLastChangeVersion(out version);
178                 if ((int)ContactsError.None != error)
179                 {
180                     Log.Error(Globals.LogTag, "LastChangeVersion Failed with error " + error);
181                 }
182                 return version;
183             }
184         }
185
186         /// <summary>
187         /// The contacts database status.
188         /// </summary>
189         /// <value>The contacts database status.</value>
190         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
191         public DBStatus Status
192         {
193             get
194             {
195                 DBStatus status = DBStatus.Normal;
196                 int error = Interop.Database.GetStatus(out status);
197                 if ((int)ContactsError.None != error)
198                 {
199                     Log.Error(Globals.LogTag, "GetStatus Failed with error " + error);
200                 }
201                 return status;
202             }
203         }
204
205         /// <summary>
206         /// Inserts a record into the contacts database.
207         /// </summary>
208         /// <param name="record">The record to insert</param>
209         /// <returns>The ID of inserted record</returns>
210         /// <privilege>http://tizen.org/privilege/contact.write</privilege>
211         /// <privilege>http://tizen.org/privilege/callhistory.write</privilege>
212         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
213         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
214         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
215         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
216         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
217         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
218         public int Insert(ContactsRecord record)
219         {
220             int id = -1;
221             int error = Interop.Database.Insert(record._recordHandle, out id);
222             if ((int)ContactsError.None != error)
223             {
224                 Log.Error(Globals.LogTag, "Insert Failed with error " + error);
225                 throw ContactsErrorFactory.CheckAndCreateException(error);
226             }
227             return id;
228         }
229
230         /// <summary>
231         /// Inserts multiple records into the contacts database as a batch operation.
232         /// </summary>
233         /// <param name="list">The record list</param>
234         /// <returns>The inserted record ID array</returns>
235         /// <privilege>http://tizen.org/privilege/contact.write</privilege>
236         /// <privilege>http://tizen.org/privilege/callhistory.write</privilege>
237         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
238         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
239         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
240         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
241         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
242         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
243         public int[] Insert(ContactsList list)
244         {
245             IntPtr ids;
246             int count;
247             int error = Interop.Database.InsertRecords(list._listHandle, out ids, out count);
248             if ((int)ContactsError.None != error)
249             {
250                 Log.Error(Globals.LogTag, "Insert Failed with error " + error);
251                 throw ContactsErrorFactory.CheckAndCreateException(error);
252             }
253
254             int[] idArr = new int[count];
255             Marshal.Copy(ids, idArr, 0, count);
256
257             return idArr;
258         }
259
260         /// <summary>
261         /// Gets a record from the contacts database.
262         /// </summary>
263         /// <param name="viewUri">The view URI of a record</param>
264         /// <param name="recordId">The record ID</param>
265         /// <returns>The record associated with the record ID</returns>
266         /// <privilege>http://tizen.org/privilege/contact.read</privilege>
267         /// <privilege>http://tizen.org/privilege/callhistory.read</privilege>
268         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
269         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
270         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
271         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
272         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
273         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
274         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
275         public ContactsRecord Get(string viewUri, int recordId)
276         {
277             IntPtr handle;
278             int error = Interop.Database.Get(viewUri, recordId, out handle);
279             if ((int)ContactsError.None != error)
280             {
281                 Log.Error(Globals.LogTag, "Get Failed with error " + error);
282                 throw ContactsErrorFactory.CheckAndCreateException(error);
283             }
284             return new ContactsRecord(handle);
285         }
286
287         /// <summary>
288         /// Updates a record in the contacts database.
289         /// </summary>
290         /// <param name="record">The record to update</param>
291         /// <privilege>http://tizen.org/privilege/contact.write</privilege>
292         /// <privilege>http://tizen.org/privilege/callhistory.write</privilege>
293         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
294         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
295         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
296         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
297         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
298         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
299         public void Update(ContactsRecord record)
300         {
301             int error = Interop.Database.Update(record._recordHandle);
302             if ((int)ContactsError.None != error)
303             {
304                 Log.Error(Globals.LogTag, "Update Failed with error " + error);
305                 throw ContactsErrorFactory.CheckAndCreateException(error);
306             }
307         }
308
309         /// <summary>
310         /// Updates multiple records in the contacts database as a batch operation.
311         /// </summary>
312         /// <param name="list">The record list</param>
313         /// <privilege>http://tizen.org/privilege/contact.write</privilege>
314         /// <privilege>http://tizen.org/privilege/callhistory.write</privilege>
315         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
316         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
317         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
318         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
319         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
320         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
321         public void Update(ContactsList list)
322         {
323             int error = Interop.Database.UpdateRecords(list._listHandle);
324             if ((int)ContactsError.None != error)
325             {
326                 Log.Error(Globals.LogTag, "Update Failed with error " + error);
327                 throw ContactsErrorFactory.CheckAndCreateException(error);
328             }
329         }
330
331         /// <summary>
332         /// Deletes a record from the contacts database with related child records.
333         /// </summary>
334         /// <param name="viewUri">The view URI of a record</param>
335         /// <param name="recordId">The record ID to delete</param>
336         /// <privilege>http://tizen.org/privilege/contact.write</privilege>
337         /// <privilege>http://tizen.org/privilege/callhistory.write</privilege>
338         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
339         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
340         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
341         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
342         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
343         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
344         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
345         public void Delete(string viewUri, int recordId)
346         {
347             int error = Interop.Database.Delete(viewUri, recordId);
348             if ((int)ContactsError.None != error)
349             {
350                 Log.Error(Globals.LogTag, "Delete Failed with error " + error);
351                 throw ContactsErrorFactory.CheckAndCreateException(error);
352             }
353         }
354
355         /// <summary>
356         /// Deletes multiple records with related child records from the contacts database as a batch operation.
357         /// </summary>
358         /// <param name="viewUri">The view URI of the records to delete</param>
359         /// <param name="idArray">The record IDs to delete</param>
360         /// <privilege>http://tizen.org/privilege/contact.write</privilege>
361         /// <privilege>http://tizen.org/privilege/callhistory.write</privilege>
362         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
363         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
364         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
365         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
366         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
367         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
368         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
369         public void Delete(string viewUri, int[] idArray)
370         {
371             int error = Interop.Database.DeleteRecords(viewUri, idArray, idArray.Length);
372             if ((int)ContactsError.None != error)
373             {
374                 Log.Error(Globals.LogTag, "Delete Failed with error " + error);
375                 throw ContactsErrorFactory.CheckAndCreateException(error);
376             }
377         }
378
379         /// <summary>
380         /// Replaces a record in the contacts database.
381         /// </summary>
382         /// <param name="record">The record to replace</param>
383         /// <param name="recordId">the record ID to be replaced</param>
384         /// <privilege>http://tizen.org/privilege/contact.write</privilege>
385         /// <privilege>http://tizen.org/privilege/callhistory.write</privilege>
386         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
387         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
388         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
389         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
390         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
391         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
392         public void Replace(ContactsRecord record, int recordId)
393         {
394             int error = Interop.Database.Replace(record._recordHandle, recordId);
395             if ((int)ContactsError.None != error)
396             {
397                 Log.Error(Globals.LogTag, "Replace Failed with error " + error);
398                 throw ContactsErrorFactory.CheckAndCreateException(error);
399             }
400         }
401
402         /// <summary>
403         /// Replaces multiple records in the contacts database as a batch operation.
404         /// </summary>
405         /// <param name="list">The record list to replace</param>
406         /// <param name="idArray">The record IDs to be replaced</param>
407         /// <privilege>http://tizen.org/privilege/contact.write</privilege>
408         /// <privilege>http://tizen.org/privilege/callhistory.write</privilege>
409         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
410         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
411         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
412         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
413         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
414         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
415         public void Replace(ContactsList list, int[] idArray)
416         {
417             int error = Interop.Database.ReplaceRecords(list._listHandle, idArray, idArray.Length);
418             if ((int)ContactsError.None != error)
419             {
420                 Log.Error(Globals.LogTag, "Replace Failed with error " + error);
421                 throw ContactsErrorFactory.CheckAndCreateException(error);
422             }
423         }
424
425         /// <summary>
426         /// Retrieves all records as a list.
427         /// </summary>
428         /// <param name="viewUri">The view URI to get records</param>
429         /// <param name="offset">The index from which results</param>
430         /// <param name="limit">The number to limit results(value 0 is used for all records)</param>
431         /// <returns>
432         /// The record list
433         /// </returns>
434         /// <privilege>http://tizen.org/privilege/contact.read</privilege>
435         /// <privilege>http://tizen.org/privilege/callhistory.read</privilege>
436         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
437         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
438         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
439         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
440         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
441         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
442         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
443         public ContactsList GetAll(string viewUri, int offset, int limit)
444         {
445             IntPtr handle;
446             int error = Interop.Database.GetRecords(viewUri, offset, limit, out handle);
447             if ((int)ContactsError.None != error)
448             {
449                 Log.Error(Globals.LogTag, "GetAll Failed with error " + error);
450                 throw ContactsErrorFactory.CheckAndCreateException(error);
451             }
452             return new ContactsList(handle);
453         }
454
455         /// <summary>
456         /// Retrieves records using a query.
457         /// </summary>
458         /// <param name="query">The query to filter the results</param>
459         /// <param name="offset">The index from which to get results</param>
460         /// <param name="limit">The number to limit results(value 0 is used for get all records)</param>
461         /// <returns>
462         /// The record list
463         /// </returns>
464         /// <privilege>http://tizen.org/privilege/contact.read</privilege>
465         /// <privilege>http://tizen.org/privilege/callhistory.read</privilege>
466         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
467         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
468         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
469         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
470         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
471         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
472         public ContactsList GetRecordsWithQuery(ContactsQuery query, int offset, int limit)
473         {
474             IntPtr handle;
475             int error = Interop.Database.GetRecords(query._queryHandle, offset, limit, out handle);
476             if ((int)ContactsError.None != error)
477             {
478                 Log.Error(Globals.LogTag, "GetAllWithQuery Failed with error " + error);
479                 throw ContactsErrorFactory.CheckAndCreateException(error);
480             }
481             return new ContactsList(handle);
482         }
483
484         /// <summary>
485         /// Retrieves records changes since the given database version.
486         /// </summary>
487         /// <param name="viewUri">The view URI to get records</param>
488         /// <param name="addressBookId">The address book ID to filter</param>
489         /// <param name="contactsDBVersion">The contacts database version</param>
490         /// <param name="currentDBVersion">The current contacts database version</param>
491         /// <returns>
492         /// The record list
493         /// </returns>
494         /// <privilege>http://tizen.org/privilege/contact.read</privilege>
495         /// <exception cref="InvalidOperationException">Thrown when method failed due to invalid operation</exception>
496         /// <exception cref="NotSupportedException">Thrown when an invoked method is not supported</exception>
497         /// <exception cref="ArgumentException">Thrown when one of the arguments provided to a method is not valid</exception>
498         /// <exception cref="OutOfMemoryException">Thrown when failed due to out of memory</exception>
499         /// <exception cref="UnauthorizedAccessException">Thrown when application does not have proper privileges</exception>
500         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
501         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
502         public ContactsList GetChangesByVersion(string viewUri, int addressBookId, int contactsDBVersion, out int currentDBVersion)
503         {
504             IntPtr recordList;
505             int error = Interop.Database.GetChangesByVersion(viewUri, addressBookId, contactsDBVersion, out recordList,out currentDBVersion);
506             if ((int)ContactsError.None != error)
507             {
508                 Log.Error(Globals.LogTag, "GetChangesByVersion Failed with error " + error);
509                 throw ContactsErrorFactory.CheckAndCreateException(error);
510             }
511             return new ContactsList(recordList);
512         }
513
514         /// <summary>
515         /// Finds records based on a given keyword.
516         /// </summary>
517         /// <remarks>
518         /// This API works only for the Views below.
519         /// Person, PersonContact, PersonGroupRelation, PersonGroupAssigned and PersonGroupNotAssigned.
520         /// </remarks>
521         /// <param name="viewUri">The view URI to find records</param>
522         /// <param name="keyword">The keyword</param>
523         /// <param name="offset">The index from which to get results</param>
524         /// <param name="limit">The number to limit results(value 0 is used for get all records)</param>
525         /// <returns>The record list</returns>
526         /// <privilege>http://tizen.org/privilege/contact.read</privilege>
527         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
528         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
529         public ContactsList Search(string viewUri, string keyword, int offset, int limit)
530         {
531             IntPtr recordList;
532             int error = Interop.Database.Search(viewUri, keyword, offset, limit, out recordList);
533             if ((int)ContactsError.None != error)
534             {
535                 Log.Error(Globals.LogTag, "Search Failed with error " + error);
536                 throw ContactsErrorFactory.CheckAndCreateException(error);
537             }
538             return new ContactsList(recordList);
539         }
540
541         /// <summary>
542         /// Finds records based on given query and keyword.
543         /// </summary>
544         /// <remarks>
545         /// This API works only for the Views below.
546         /// Person, PersonContact, PersonGroupRelation, PersonGroupAssigned and PersonGroupNotAssigned.
547         /// </remarks>
548         /// <param name="query">The query to filter</param>
549         /// <param name="keyword">The keyword</param>
550         /// <param name="offset">The index from which to get results</param>
551         /// <param name="limit">The number to limit results(value 0 used for get all records)</param>
552         /// <returns>The record list</returns>
553         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
554         public ContactsList Search(ContactsQuery query, string keyword, int offset, int limit)
555         {
556             IntPtr recordList;
557             int error = Interop.Database.Search(query._queryHandle, keyword, offset, limit, out recordList);
558             if ((int)ContactsError.None != error)
559             {
560                 Log.Error(Globals.LogTag, "Search Failed with error " + error);
561                 throw ContactsErrorFactory.CheckAndCreateException(error);
562             }
563             return new ContactsList(recordList);
564         }
565
566         /// <summary>
567         /// Finds records based on a keyword and range.
568         /// </summary>
569         /// <remarks>
570         /// This API works only for the Views below.
571         /// Person, PersonContact, PersonGroupRelation, PersonGroupAssigned, PersonGroupNotAssigned, PersonNumber and PersonEmail
572         /// </remarks>
573         /// <param name="viewUri">The view URI</param>
574         /// <param name="keyword">The keyword</param>
575         /// <param name="offset">The index from which to get results</param>
576         /// <param name="limit">The number to limit results(value 0 is used for get all records)</param>
577         /// <param name="range">The search range, it should be a element of SearchRange or bitwise OR operation of them</param>
578         /// <returns>The record list</returns>
579         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
580         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
581         public ContactsList Search(string viewUri, string keyword, int offset, int limit, int range)
582         {
583             IntPtr recordList;
584             int error = Interop.Database.Search(viewUri, keyword, offset, limit, range, out recordList);
585             if ((int)ContactsError.None != error)
586             {
587                 Log.Error(Globals.LogTag, "Search Failed with error " + error);
588                 throw ContactsErrorFactory.CheckAndCreateException(error);
589             }
590             return new ContactsList(recordList);
591         }
592
593         /// <summary>
594         /// Finds records based on a given keyword for snippet
595         /// </summary>
596         /// <remarks>
597         /// This API works only for the Views below.
598         /// Person, PersonContact, PersonGroupRelation, PersonGroupAssigned and PersonGroupNotAssigned.
599         /// Because start match and end match are needed to be composed with keyword, this API performance is lower than Search(string viewUri, string keyword, int offset, int limit).
600         /// </remarks>
601         /// <param name="viewUri">The view URI to find records</param>
602         /// <param name="keyword">The keyword</param>
603         /// <param name="offset">The index from which to get results</param>
604         /// <param name="limit">The number to limit results(value 0 used for get all records)</param>
605         /// <param name="startMatch">The text which is inserted into the fragment before the keyword(If NULL, default is "[")</param>
606         /// <param name="endMatch">The text which is inserted into the fragment after the keyword(If NULL, default is "]")</param>
607         /// <param name="tokenNumber">The one side extra number of tokens near keyword(If negative value, full sentence is printed. e.g. if token number is 3 with 'abc' keyword, "my name is [abc]de and my home")</param>
608         /// <returns>The record list</returns>
609         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
610         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
611         public ContactsList Search(string viewUri, string keyword, int offset, int limit, string startMatch, string endMatch, int tokenNumber)
612         {
613             IntPtr recordList;
614             int error = Interop.Database.Search(viewUri, keyword, offset, limit, startMatch, endMatch, tokenNumber, out recordList);
615             if ((int)ContactsError.None != error)
616             {
617                 Log.Error(Globals.LogTag, "Search Failed with error " + error);
618                 throw ContactsErrorFactory.CheckAndCreateException(error);
619             }
620             return new ContactsList(recordList);
621         }
622
623         /// <summary>
624         /// Finds records based on given query and keyword for snippet.
625         /// </summary>
626         /// <remarks>
627         /// This API works only for the Views below.
628         /// Person, PersonContact, PersonGroupRelation, PersonGroupAssigned and PersonGroupNotAssigned.
629         /// Because start match and end match are needed to be composed with keyword, this API performance is lower than Search(ContactsQuery query, string keyword, int offset, int limit).
630         /// </remarks>
631         /// <param name="query">The query to filter</param>
632         /// <param name="keyword">The keyword</param>
633         /// <param name="offset">The index from which to get results</param>
634         /// <param name="limit">The number to limit results(value 0 used for get all records)</param>
635         /// <param name="startMatch">The text which is inserted into the fragment before the keyword(If NULL, default is "[")</param>
636         /// <param name="endMatch">The text which is inserted into the fragment after the keyword(If NULL, default is "]")</param>
637         /// <param name="tokenNumber">The one side extra number of tokens near keyword(If negative value, full sentence is printed. e.g. if token number is 3 with 'abc' keyword, "my name is [abc]de and my home")</param>
638         /// <returns>The record list</returns>
639         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
640         public ContactsList Search(ContactsQuery query, string keyword, int offset, int limit, string startMatch, string endMatch, int tokenNumber)
641         {
642             IntPtr recordList;
643             int error = Interop.Database.Search(query._queryHandle, keyword, offset, limit, startMatch, endMatch, tokenNumber, out recordList);
644             if ((int)ContactsError.None != error)
645             {
646                 Log.Error(Globals.LogTag, "Search Failed with error " + error);
647                 throw ContactsErrorFactory.CheckAndCreateException(error);
648             }
649             return new ContactsList(recordList);
650         }
651
652         /// <summary>
653         /// Finds records based on a keyword and range for snippet.
654         /// </summary>
655         /// <remarks>
656         /// This API works only for the Views below.
657         /// Person, PersonContact, PersonGroupRelation, PersonGroupAssigned, PersonGroupNotAssigned, PersonNumber and PersonEmail
658         /// Because start match and end match are needed to be composed with keyword, this API performance is lower than Search(string viewUri, string keyword, int offset, int limit, int range).
659         /// </remarks>
660         /// <param name="viewUri">The view URI</param>
661         /// <param name="keyword">The keyword</param>
662         /// <param name="offset">The index from which to get results</param>
663         /// <param name="limit">The number to limit results(value 0 is used for get all records)</param>
664         /// <param name="range">The search range, it should be a element of SearchRange or bitwise OR operation of them</param>
665         /// <param name="startMatch">The text which is inserted into the fragment before the keyword(If NULL, default is "[")</param>
666         /// <param name="endMatch">The text which is inserted into the fragment after the keyword(If NULL, default is "]")</param>
667         /// <param name="tokenNumber">The one side extra number of tokens near keyword(If negative value, full sentence is printed. e.g. if token number is 3 with 'abc' keyword, "my name is [abc]de and my home")</param>
668         /// <returns>The record list</returns>
669         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
670         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
671         public ContactsList Search(string viewUri, string keyword, int offset, int limit, int range, string startMatch, string endMatch, int tokenNumber)
672         {
673             IntPtr recordList;
674             int error = Interop.Database.Search(viewUri, keyword, offset, limit, range, startMatch, endMatch, tokenNumber, out recordList);
675             if ((int)ContactsError.None != error)
676             {
677                 Log.Error(Globals.LogTag, "Search Failed with error " + error);
678                 throw ContactsErrorFactory.CheckAndCreateException(error);
679             }
680             return new ContactsList(recordList);
681         }
682
683         /// <summary>
684         /// Gets the number of records in a specific view
685         /// </summary>
686         /// <param name="viewUri">The view URI</param>
687         /// <returns>The count of records</returns>
688         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
689         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
690         public int GetCount(string viewUri)
691         {
692             int count = -1;
693             int error = Interop.Database.GetCount(viewUri, out count);
694             if ((int)ContactsError.None != error)
695             {
696                 Log.Error(Globals.LogTag, "GetCount Failed with error " + error);
697                 throw ContactsErrorFactory.CheckAndCreateException(error);
698             }
699             return count;
700         }
701
702         /// <summary>
703         /// Gets the number of records matching a query.
704         /// </summary>
705         /// <param name="query">The query used for filtering the results</param>
706         /// <returns>The count of records</returns>
707         [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
708         public int GetCount(ContactsQuery query)
709         {
710             int count = -1;
711             int error = Interop.Database.GetCount(query._queryHandle, out count);
712             if ((int)ContactsError.None != error)
713             {
714                 Log.Error(Globals.LogTag, "GetCount Failed with error " + error);
715                 throw ContactsErrorFactory.CheckAndCreateException(error);
716             }
717             return count;
718         }
719
720         /// <summary>
721         /// Registers a callback function to be invoked when a record changes.
722         /// </summary>
723         /// <param name="viewUri">The view URI of records whose changes are monitored</param>
724         /// <param name="callback">The callback function to register</param>
725         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
726         public void AddDBChangedDelegate(string viewUri, ContactsDBChanged callback)
727         {
728             if (_callbackMap[viewUri] == null)
729             {
730                 _callbackMap[viewUri] = (string uri, IntPtr userData) =>
731                 {
732                     _delegateMap[uri](uri);
733                 };
734
735                 int error = Interop.Database.AddChangedCb(viewUri, _callbackMap[viewUri], IntPtr.Zero);
736                 if ((int)ContactsError.None != error)
737                 {
738                     Log.Error(Globals.LogTag, "AddDBChangedDelegate Failed with error " + error);
739                     throw ContactsErrorFactory.CheckAndCreateException(error);
740                 }
741             }
742
743             _delegateMap[viewUri] += callback;
744         }
745
746         /// <summary>
747         /// Deregisters a callback function.
748         /// </summary>
749         /// <param name="viewUri">The view URI of records whose changes are monitored</param>
750         /// <param name="callback">The callback function to register</param>
751         [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings")]
752         public void RemoveDBChangedDelegate(string viewUri, ContactsDBChanged callback)
753         {
754             _delegateMap[viewUri] -= callback;
755
756             if (_delegateMap[viewUri] == null)
757             {
758                 int error = Interop.Database.RemoveChangedCb(viewUri, _callbackMap[viewUri], IntPtr.Zero);
759                 if ((int)ContactsError.None != error)
760                 {
761                     Log.Error(Globals.LogTag, "RemoveDBChangedDelegate Failed with error " + error);
762                     throw ContactsErrorFactory.CheckAndCreateException(error);
763                 }
764                 _callbackMap.Remove(viewUri);
765             }
766         }
767     }
768 }