Fix wrong intprt check (#381)
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.DataControl / Tizen.Applications.DataControl / Consumer.cs
1 /*
2  * Copyright (c) 2017 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 using System;
17 using System.Collections.Generic;
18 using Tizen.Applications.DataControl.Core;
19 using System.Threading;
20 using System.Runtime.InteropServices;
21
22 namespace Tizen.Applications.DataControl
23 {
24     /// <summary>
25     /// Represents the Consumer class for the DataControl consumer application.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public abstract class Consumer : IDisposable
29     {
30
31         private Interop.DataControl.SafeDataControlHandle _handle;
32         private string _dataID, _providerID;
33         private int _changeCallbackID = 0;
34         private const string LogTag = "Tizen.Applications.DataControl";
35         private bool _disposed = false;
36         private static Mutex _lock = new Mutex();
37         private Interop.DataControl.DataChangeCallback _dataChangeCallback;
38         private Interop.DataControl.AddCallbackResultCallback _addCallbackResultCallback;
39
40         private static class CallbackManager
41         {
42             private static IDictionary<string, Interop.DataControl.MapResponseCallbacks> _mapResponseCallbacks = new Dictionary<string, Interop.DataControl.MapResponseCallbacks>();
43             private static IDictionary<string, Interop.DataControl.MapBulkAddResponseCallback> _mapBulkResponseCallback = new Dictionary<string, Interop.DataControl.MapBulkAddResponseCallback>();
44             private static IDictionary<string, Interop.DataControl.SqlResponseCallbacks> _sqlResponseCallbacks = new Dictionary<string, Interop.DataControl.SqlResponseCallbacks>();
45             private static IDictionary<string, Interop.DataControl.SqlBulkInsertResponseCallback> _sqlBulkResponseCallback = new Dictionary<string, Interop.DataControl.SqlBulkInsertResponseCallback>();
46             private static IDictionary<int, Consumer> _reqConsumerDictionary = new Dictionary<int, Consumer>();
47             private static IDictionary<string, int> _reqProviderList = new Dictionary<string, int>();
48             private static void InsertResponse(int reqId, IntPtr provider, long insertedRowId, bool providerResult, string error, IntPtr userData)
49             {
50                 Log.Debug(LogTag, $"InsertResponse {reqId.ToString()}");
51                 if (!_reqConsumerDictionary.ContainsKey(reqId))
52                 {
53                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
54                     return;
55                 }
56
57                 if (!providerResult)
58                 {
59                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}, rowID : {insertedRowId.ToString()}");
60                 }
61
62                 Consumer consumer = _reqConsumerDictionary[reqId];
63                 consumer.OnInsertResult(new InsertResult(insertedRowId, providerResult));
64                 _reqConsumerDictionary.Remove(reqId);
65             }
66
67             private static void BulkInsertResponse(int reqId, IntPtr provider, IntPtr bulkResults, bool providerResult, string error, IntPtr userData)
68             {
69                 BulkResultData brd;
70                 Log.Debug(LogTag, $"BulkInsertResponse {reqId.ToString()}");
71                 if (!_reqConsumerDictionary.ContainsKey(reqId))
72                 {
73                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
74                     return;
75                 }
76
77                 if (!providerResult)
78                 {
79                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
80                 }
81
82                 if (bulkResults != IntPtr.Zero)
83                 {
84                     brd = new BulkResultData(new Interop.DataControl.SafeBulkResultDataHandle(bulkResults, false));
85                 }
86                 else
87                 {
88                     brd = new BulkResultData();
89                     Log.Error(LogTag, $"reqId {reqId.ToString()}, bulkResults is null");
90                 }
91
92                 Consumer consumer = _reqConsumerDictionary[reqId];
93                 consumer.OnBulkInsertResult(new BulkInsertResult(brd, providerResult));
94                 _reqConsumerDictionary.Remove(reqId);
95             }
96
97             private static void SelectResponse(int reqId, IntPtr provider, IntPtr cursor, bool providerResult, string error, IntPtr userData)
98             {
99                 MatrixCursor dmc;
100                 Log.Debug(LogTag, $"SelectResponse {reqId.ToString()}");
101                 if (!_reqConsumerDictionary.ContainsKey(reqId))
102                 {
103                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
104                     return;
105                 }
106
107                 if (!providerResult)
108                 {
109                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
110                 }
111
112                 if (cursor != IntPtr.Zero)
113                 {
114                     try
115                     {
116                         dmc = CloneCursor(new CloneCursorCore(new Interop.DataControl.SafeCursorHandle(cursor, true)));
117                     }
118                     catch (Exception ex)
119                     {
120                         dmc = new MatrixCursor();
121                         Log.Error(LogTag, $"reqId {reqId.ToString()},  {ex.ToString()}");
122                     }
123                 }
124                 else
125                 {
126                     dmc = new MatrixCursor();
127                     Log.Error(LogTag, $"reqId {reqId.ToString()}, cursor is null");
128                 }
129                 Consumer consumer = _reqConsumerDictionary[reqId];
130                 consumer.OnSelectResult(new SelectResult(dmc, providerResult));
131                 _reqConsumerDictionary.Remove(reqId);
132             }
133
134             private static void UpdateResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData)
135             {
136                 if (!_reqConsumerDictionary.ContainsKey(reqId))
137                 {
138                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
139                     return;
140                 }
141
142                 if (!providerResult)
143                 {
144                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
145                 }
146
147                 Consumer consumer = _reqConsumerDictionary[reqId];
148                 consumer.OnUpdateResult(new UpdateResult(providerResult));
149                 _reqConsumerDictionary.Remove(reqId);
150             }
151
152             private static void DeleteResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData)
153             {
154                 if (!_reqConsumerDictionary.ContainsKey(reqId))
155                 {
156                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
157                     return;
158                 }
159
160                 if (!providerResult)
161                 {
162                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
163                 }
164
165                 Consumer consumer = _reqConsumerDictionary[reqId];
166                 consumer.OnDeleteResult(new DeleteResult(providerResult));
167                 _reqConsumerDictionary.Remove(reqId);
168             }
169
170             static void IntPtrToStringArray(IntPtr unmanagedArray, int size, out string[] managedArray)
171             {
172                 managedArray = new string[size];
173                 IntPtr[] IntPtrArray = new IntPtr[size];
174                 Marshal.Copy(unmanagedArray, IntPtrArray, 0, size);
175                 for (int iterator = 0; iterator < size; iterator++)
176                 {
177                     managedArray[iterator] = Marshal.PtrToStringAnsi(IntPtrArray[iterator]);
178                 }
179             }
180
181             private static void MapGetResponse(int reqId, IntPtr provider, IntPtr valueList, int valueCount, bool providerResult, string error, IntPtr userData)
182             {
183                 MapGetResult mgr;
184                 Log.Debug(LogTag, $"MapGetResponse {reqId.ToString()}");
185                 if (!_reqConsumerDictionary.ContainsKey(reqId))
186                 {
187                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
188                     return;
189                 }
190
191                 if (!providerResult)
192                 {
193                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
194                 }
195
196                 if (valueList != IntPtr.Zero)
197                 {
198                     string[] stringArray;
199                     IntPtrToStringArray(valueList, valueCount, out stringArray);
200                     mgr = new MapGetResult(stringArray, providerResult);
201                 }
202                 else
203                 {
204                     mgr = new MapGetResult(new string[0], providerResult);
205                     Log.Error(LogTag, $"reqId {reqId.ToString()}, valueList is null");
206                 }
207
208                 Consumer consumer = _reqConsumerDictionary[reqId];
209                 consumer.OnMapGetResult(mgr);
210                 _reqConsumerDictionary.Remove(reqId);
211             }
212
213             private static void MapBulkAddResponse(int reqId, IntPtr provider, IntPtr bulkResults, bool providerResult, string error, IntPtr userData)
214             {
215                 BulkResultData brd;
216                 Log.Debug(LogTag, $"MapBulkAddResponse {reqId.ToString()}");
217                 if (!_reqConsumerDictionary.ContainsKey(reqId))
218                 {
219                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
220                     return;
221                 }
222
223                 if (!providerResult)
224                 {
225                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
226                 }
227
228                 if (bulkResults != IntPtr.Zero)
229                 {
230                     brd = new BulkResultData(new Interop.DataControl.SafeBulkResultDataHandle(bulkResults, false));
231                 }
232                 else
233                 {
234                     brd = new BulkResultData();
235                     Log.Error(LogTag, $"reqId {reqId.ToString()}, bulkResults is null");
236                 }
237
238                 Consumer consumer = _reqConsumerDictionary[reqId];
239                 consumer.OnMapBulkAddResult(new MapBulkAddResult(brd, providerResult));
240                 _reqConsumerDictionary.Remove(reqId);
241             }
242
243             private static void MapAddResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData)
244             {
245                 Log.Debug(LogTag, $"MapAddResponse {reqId.ToString()}");
246                 if (!_reqConsumerDictionary.ContainsKey(reqId))
247                 {
248                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
249                     return;
250                 }
251
252                 if (!providerResult)
253                 {
254                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
255                 }
256
257                 Consumer consumer = _reqConsumerDictionary[reqId];
258                 consumer.OnMapAddResult(new MapAddResult(providerResult));
259                 _reqConsumerDictionary.Remove(reqId);
260             }
261
262             private static void MapSetResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData)
263             {
264                 Log.Debug(LogTag, $"MapSetResponse {reqId.ToString()}");
265                 if (!_reqConsumerDictionary.ContainsKey(reqId))
266                 {
267                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
268                     return;
269                 }
270
271                 if (!providerResult)
272                 {
273                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
274                 }
275
276                 Consumer consumer = _reqConsumerDictionary[reqId];
277                 consumer.OnMapSetResult(new MapSetResult(providerResult));
278                 _reqConsumerDictionary.Remove(reqId);
279             }
280
281             private static void MapRemoveResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData)
282             {
283                 if (!_reqConsumerDictionary.ContainsKey(reqId))
284                 {
285                     Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}");
286                     return;
287                 }
288
289                 if (!providerResult)
290                 {
291                     Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}");
292                 }
293
294                 Consumer consumer = _reqConsumerDictionary[reqId];
295                 consumer.OnMapRemoveResult(new MapRemoveResult(providerResult));
296                 _reqConsumerDictionary.Remove(reqId);
297             }
298
299             private static MatrixCursor CloneCursor(CloneCursorCore coreCursor)
300             {
301                 int size = coreCursor.GetColumnCount();
302                 int i;
303                 string[] name = new string[size];
304                 object[] newRow = new object[size];
305                 ColumnType[] type = new ColumnType[size];
306
307                 for (i = 0; i < size; i++)
308                 {
309                     name[i] = coreCursor.GetColumnName(i);
310                     type[i] = coreCursor.GetColumnType(i);
311                 }
312
313                 MatrixCursor dmc = new MatrixCursor(name, type);
314
315                 if (coreCursor.GetRowCount() <= 0)
316                 {
317                     return dmc;
318                 }
319
320                 coreCursor.Reset();
321                 do
322                 {
323                     for (i = 0; i < size; i++)
324                     {
325                         switch (type[i])
326                         {
327                             case ColumnType.ColumnTypeInt:
328                                 newRow[i] = coreCursor.GetInt64Value(i);
329                                 break;
330                             case ColumnType.ColumnTypeDouble:
331                                 newRow[i] = coreCursor.GetDoubleValue(i);
332                                 break;
333                             case ColumnType.ColumnTypeBlob:
334                                 newRow[i] = coreCursor.GetBlobValue(i);
335                                 break;
336                             case ColumnType.ColumnTypeString:
337                                 newRow[i] = coreCursor.GetStringValue(i);
338                                 break;
339                         }
340                     }
341
342                     dmc.AddRow(newRow);
343                 }
344                 while (coreCursor.Next());
345
346                 return dmc;
347             }
348
349             internal static void RegisterReqId(int reqId, Consumer consumer)
350             {
351                 _lock.WaitOne();
352                 _reqConsumerDictionary.Add(reqId, consumer);
353                 _lock.ReleaseMutex();
354             }
355
356             internal static void RegisterCallback(Interop.DataControl.SafeDataControlHandle handle, string providerId)
357             {
358                 ResultType ret;
359                 Interop.DataControl.SqlResponseCallbacks sqlCallbacks;
360                 Interop.DataControl.SqlBulkInsertResponseCallback sqlBulkCallbacks;
361                 Interop.DataControl.MapResponseCallbacks mapCallbacks;
362                 Interop.DataControl.MapBulkAddResponseCallback mapBulkCallbacks;
363                 bool sqlRegistered = false;
364                 bool mapRegistered = false;
365
366                 if (_reqProviderList.ContainsKey(providerId))
367                 {
368                     _reqProviderList[providerId]++;
369                     Log.Error(LogTag, "The data control is already set");
370                     return;
371                 }
372
373                 sqlCallbacks.Insert = new Interop.DataControl.SqlInsertResponseCallback(InsertResponse);
374                 sqlCallbacks.Select = new Interop.DataControl.SqlSelectResponseCallback(SelectResponse);
375                 sqlCallbacks.Update = new Interop.DataControl.SqlUpdateResponseCallback(UpdateResponse);
376                 sqlCallbacks.Delete = new Interop.DataControl.SqlDeleteResponseCallback(DeleteResponse);
377                 ret = Interop.DataControl.RegisterSqlResponseCallback(handle, ref sqlCallbacks, IntPtr.Zero);
378                 if (ret != ResultType.Success)
379                 {
380                     Log.Error(LogTag, "Registering the sql callback function is failed : " + ret);
381                 }
382                 else
383                 {
384                     _sqlResponseCallbacks.Add(providerId, sqlCallbacks);
385                     sqlRegistered = true;
386                 }
387
388                 sqlBulkCallbacks = new Interop.DataControl.SqlBulkInsertResponseCallback(BulkInsertResponse);
389                 ret = Interop.DataControl.RegisterSqlBulkResponseCallback(handle, sqlBulkCallbacks, IntPtr.Zero);
390                 if (ret != ResultType.Success)
391                 {
392                     Log.Error(LogTag, "Registering the sql bulk callback function is failed : " + ret);
393                 }
394                 else
395                 {
396                     _sqlBulkResponseCallback.Add(providerId, sqlBulkCallbacks);
397                 }
398
399                 mapCallbacks.Add = new Interop.DataControl.MapAddResponseCallback(MapAddResponse);
400                 mapCallbacks.Set = new Interop.DataControl.MapSetResponseCallback(MapSetResponse);
401                 mapCallbacks.Get = new Interop.DataControl.MapGetResponseCallback(MapGetResponse);
402                 mapCallbacks.Remove = new Interop.DataControl.MapRemoveResponseCallback(MapRemoveResponse);
403                 ret = Interop.DataControl.RegisterMapResponse(handle, ref mapCallbacks, IntPtr.Zero);
404
405                 if (ret != ResultType.Success)
406                 {
407                     Log.Error(LogTag, "Registering the map callback function is failed : " + ret);
408                 }
409                 else
410                 {
411                     _mapResponseCallbacks.Add(providerId, mapCallbacks);
412                     mapRegistered = true;
413                 }
414
415                 mapBulkCallbacks = new Interop.DataControl.MapBulkAddResponseCallback(MapBulkAddResponse);
416                 ret = Interop.DataControl.RegisterMapBulkResponseCallback(handle, mapBulkCallbacks, IntPtr.Zero);
417                 if (ret != ResultType.Success)
418                 {
419                     Log.Error(LogTag, "Registering the map bulk callback function is failed : " + ret);
420                 }
421                 else
422                 {
423                     _mapBulkResponseCallback.Add(providerId, mapBulkCallbacks);
424                 }
425
426                 if (!mapRegistered && !sqlRegistered)
427                 {
428                     ErrorFactory.ThrowException(ret, true, "Registering the response callback function is failed");
429                 }
430
431                 _reqProviderList.Add(providerId, 1);
432             }
433
434             internal static void UnregisterCallback(Interop.DataControl.SafeDataControlHandle handle, string providerId)
435             {
436                 int count;
437
438                 if (!_reqProviderList.ContainsKey(providerId))
439                 {
440                     Log.Error(LogTag, "The provider id is not contained : " + providerId);
441                     return;
442                 }
443
444                 _reqProviderList[providerId]--;
445                 count = _reqProviderList[providerId];
446                 if (count <= 0)
447                 {
448                     _reqProviderList.Remove(providerId);
449
450                     _mapResponseCallbacks.Remove(providerId);
451                     Interop.DataControl.UnregisterMapResponse(handle);
452
453                     _mapBulkResponseCallback.Remove(providerId);
454                     Interop.DataControl.UnregisterMapBulkResponseCallback(handle);
455
456                     _sqlResponseCallbacks.Remove(providerId);
457                     Interop.DataControl.UnregisterSqlResponseCallback(handle);
458
459                     _sqlBulkResponseCallback.Remove(providerId);
460                     Interop.DataControl.UnregisterSqlBulkResponseCallback(handle);
461                 }
462
463             }
464         }
465
466         /// <summary>
467         /// Sends the insert request to the provider application.
468         /// </summary>
469         /// <remarks>The OnInsertResult will recieve the result of this API.</remarks>
470         /// <param name="insertData">The insert data.</param>
471         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
472         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied.</exception>
473         /// <exception cref="ArgumentOutOfRangeException">Thrown when the message has exceeded the maximum limit (1MB).</exception>
474         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
475         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
476         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
477         /// <since_tizen> 3 </since_tizen>
478         public void Insert(Bundle insertData)
479         {
480             int reqId;
481             ResultType ret;
482
483             if (insertData == null || insertData.SafeBundleHandle.IsInvalid)
484             {
485                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "insertData");
486             }
487
488             _lock.WaitOne();
489             ret = Interop.DataControl.Insert(_handle, insertData.SafeBundleHandle, out reqId);
490             _lock.ReleaseMutex();
491             if (ret != ResultType.Success)
492             {
493                 ErrorFactory.ThrowException(ret, false, "Insert");
494             }
495
496             CallbackManager.RegisterReqId(reqId, this);
497         }
498
499         /// <summary>
500         /// Sends the select request to the provider application.
501         /// </summary>
502         /// <remarks>The OnSelectResult will recieve the result of this API.</remarks>
503         /// <param name="columnList">Select the target column list.</param>
504         /// <param name="where">The Where statement for the select query.</param>
505         /// <param name="order">The Order statement for the select query.</param>
506         /// <param name="pageNumber">Select the target page number.</param>
507         /// <param name="countPerPage">Select the row count per page.</param>
508         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
509         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied..</exception>
510         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
511         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
512         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
513         /// <since_tizen> 3 </since_tizen>
514         public void Select(string[] columnList, string where, string order, int pageNumber = 1, int countPerPage = 20)
515         {
516             int reqId, i;
517             ResultType ret;
518             if (columnList == null || columnList.Length == 0)
519             {
520                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "column_list");
521             }
522
523             for (i = 0; i < columnList.Length; i++)
524             {
525                 if (string.IsNullOrEmpty(columnList[i]))
526                 {
527                     ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "column_list index " + i.ToString());
528                 }
529             }
530
531             _lock.WaitOne();
532             ret = Interop.DataControl.Select(_handle, columnList, columnList.Length, where, order, pageNumber, countPerPage, out reqId);
533             _lock.ReleaseMutex();
534             if (ret != ResultType.Success)
535             {
536                 ErrorFactory.ThrowException(ret, false, "Select");
537             }
538             Log.Info(LogTag, "select end. " + reqId.ToString());
539
540             CallbackManager.RegisterReqId(reqId, this);
541         }
542
543         /// <summary>
544         /// Sends the delete request to the provider application.
545         /// </summary>
546         /// <remarks>The OnDeleteResult will recieve the result of this API</remarks>
547         /// <param name="where">The Where statement for the delete query.</param>
548         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied.</exception>
549         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
550         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
551         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
552         /// <since_tizen> 3 </since_tizen>
553         public void Delete(string where)
554         {
555             int reqId;
556             ResultType ret;
557
558             _lock.WaitOne();
559             ret = Interop.DataControl.Delete(_handle, where, out reqId);
560             _lock.ReleaseMutex();
561             if (ret != ResultType.Success)
562             {
563                 ErrorFactory.ThrowException(ret, false, "Delete");
564             }
565
566             CallbackManager.RegisterReqId(reqId, this);
567         }
568
569         /// <summary>
570         /// Sends the update request to the provider application.
571         /// </summary>
572         /// <remarks>The OnUpdateResult will recieve result of this API.</remarks>
573         /// <param name="updateData">The update data.</param>
574         /// <param name="where">The Where statement for the query.</param>
575         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
576         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied.</exception>
577         /// <exception cref="ArgumentOutOfRangeException">Thrown when the message has exceeded the maximum limit (1MB).</exception>
578         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
579         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
580         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
581         /// <since_tizen> 3 </since_tizen>
582         public void Update(Bundle updateData, string where)
583         {
584             int reqId;
585             ResultType ret;
586
587             if (updateData == null || updateData.SafeBundleHandle.IsInvalid)
588             {
589                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "insertData");
590             }
591
592             if (string.IsNullOrEmpty(where))
593             {
594                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "where");
595             }
596
597             _lock.WaitOne();
598             ret = Interop.DataControl.Update(_handle, updateData.SafeBundleHandle, where, out reqId);
599             _lock.ReleaseMutex();
600             if (ret != ResultType.Success)
601             {
602                 ErrorFactory.ThrowException(ret, false, "Update");
603             }
604
605             CallbackManager.RegisterReqId(reqId, this);
606         }
607
608         /// <summary>
609         /// Sends the bulk insert request to the provider application.
610         /// </summary>
611         /// <remarks>The OnBulkInsertResult will recieve the result of this API.</remarks>
612         /// <param name="insertData">The bulk insert data.</param>
613         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
614         /// <exception cref="UnauthorizedAccessException">Thrown in case oif a permission is denied.</exception>
615         /// <exception cref="ArgumentOutOfRangeException">Thrown when the message has exceeded the maximum limit (1MB).</exception>
616         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
617         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
618         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
619         /// <since_tizen> 3 </since_tizen>
620         public void BulkInsert(BulkData insertData)
621         {
622             int reqId;
623             ResultType ret;
624
625             if (insertData == null || insertData.SafeBulkDataHandle.IsInvalid)
626             {
627                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "insertData");
628             }
629
630             _lock.WaitOne();
631             ret = Interop.DataControl.BulkInsert(_handle, insertData.SafeBulkDataHandle, out reqId);
632             _lock.ReleaseMutex();
633             if (ret != ResultType.Success)
634             {
635                 ErrorFactory.ThrowException(ret, false, "BulkInsert");
636             }
637
638             CallbackManager.RegisterReqId(reqId, this);
639         }
640
641         /// <summary>
642         /// Sends the map add request to the provider application.
643         /// </summary>
644         /// <remarks>The OnMapAddResult will recieve the result of this API.</remarks>
645         /// <param name="key">The key of the value to add.</param>
646         /// <param name="value">The value to add.</param>
647         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
648         /// <exception cref="UnauthorizedAccessException">Thrown in case of if a permission is denied.</exception>
649         /// <exception cref="ArgumentOutOfRangeException">Thrown when the message has exceeded the maximum limit (1MB).</exception>
650         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
651         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
652         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
653         /// <since_tizen> 3 </since_tizen>
654         public void MapAdd(string key, string value)
655         {
656             int reqId;
657             ResultType ret;
658
659             if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value))
660             {
661                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false);
662             }
663
664             _lock.WaitOne();
665             ret = Interop.DataControl.MapAdd(_handle, key, value, out reqId);
666             _lock.ReleaseMutex();
667             if (ret != ResultType.Success)
668             {
669                 ErrorFactory.ThrowException(ret, false, "MapAdd");
670             }
671
672             CallbackManager.RegisterReqId(reqId, this);
673         }
674
675         /// <summary>
676         /// Sends the map get request to the provider application.
677         /// </summary>
678         /// <remarks>The OnMapGetResult will recieve the result of this API.</remarks>
679         /// <param name="key">The key of the value list to obtain.</param>
680         /// <param name="pageNumber">The page number of the value set.</param>
681         /// <param name="countPerPage">The desired maximum count of the data items per page.</param>
682         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
683         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied.</exception>
684         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
685         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
686         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
687         /// <since_tizen> 3 </since_tizen>
688         public void MapGet(string key, int pageNumber = 1, int countPerPage = 20)
689         {
690             int reqId;
691             ResultType ret;
692
693             if (string.IsNullOrEmpty(key) || pageNumber <= 0 || countPerPage <= 0)
694             {
695                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false);
696             }
697
698             _lock.WaitOne();
699             ret = Interop.DataControl.MapGet(_handle, key, out reqId, pageNumber, countPerPage);
700             _lock.ReleaseMutex();
701             if (ret != ResultType.Success)
702             {
703                 ErrorFactory.ThrowException(ret, false, "MapGet");
704             }
705
706             CallbackManager.RegisterReqId(reqId, this);
707         }
708
709         /// <summary>
710         /// Sends the map remove request to the provider application.
711         /// </summary>
712         /// <remarks>The OnMapRemoveResult will recieve the result of this API.</remarks>
713         /// <param name="key">The key of the value to remove.</param>
714         /// <param name="value">The value to remove.</param>
715         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
716         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied.</exception>
717         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
718         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
719         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
720         /// <since_tizen> 3 </since_tizen>
721         public void MapRemove(string key, string value)
722         {
723             int reqId;
724             ResultType ret;
725
726             if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value))
727             {
728                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false);
729             }
730
731             _lock.WaitOne();
732             ret = Interop.DataControl.MapRemove(_handle, key, value, out reqId);
733             _lock.ReleaseMutex();
734             if (ret != ResultType.Success)
735             {
736                 ErrorFactory.ThrowException(ret, false, "MapRemove");
737             }
738
739             CallbackManager.RegisterReqId(reqId, this);
740         }
741
742         /// <summary>
743         /// Sends the map set request to the provider application.
744         /// </summary>
745         /// <remarks>The OnMapSetResult will recieve the result of this API.</remarks>
746         /// <param name="key">The key of the value to replace.</param>
747         /// <param name="oldValue">The value to be replaced.</param>
748         /// <param name="newValue"> The new value that replaces the existing value.</param>
749         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
750         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied.</exception>
751         /// <exception cref="ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit (1MB).</exception>
752         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
753         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
754         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
755         /// <since_tizen> 3 </since_tizen>
756         public void MapSet(string key, string oldValue, string newValue)
757         {
758             int reqId;
759             ResultType ret;
760
761             if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(oldValue) || string.IsNullOrEmpty(newValue))
762             {
763                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false);
764             }
765
766             _lock.WaitOne();
767             ret = Interop.DataControl.MapSet(_handle, key, oldValue, newValue, out reqId);
768             _lock.ReleaseMutex();
769             if (ret != ResultType.Success)
770             {
771                 ErrorFactory.ThrowException(ret, false, "MapSet");
772             }
773
774             CallbackManager.RegisterReqId(reqId, this);
775         }
776
777         /// <summary>
778         /// Sends the map bulk add request to the provider application.
779         /// </summary>
780         /// <remarks>The OnMapBulkAddResult will recieve the result of this API.</remarks>
781         /// <param name="addData">The map bulk add data.</param>
782         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
783         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied.</exception>
784         /// <exception cref="ArgumentOutOfRangeException">Thrown when the message has exceeded the maximum limit (1MB).</exception>
785         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
786         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
787         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
788         /// <since_tizen> 3 </since_tizen>
789         public void MapBulkAdd(BulkData addData)
790         {
791             int reqId;
792             ResultType ret;
793
794             if (addData == null || addData.SafeBulkDataHandle.IsInvalid)
795             {
796                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "addData");
797             }
798
799             _lock.WaitOne();
800             ret = Interop.DataControl.BulkAdd(_handle, addData.SafeBulkDataHandle, out reqId);
801             _lock.ReleaseMutex();
802             if (ret != ResultType.Success)
803             {
804                 ErrorFactory.ThrowException(ret, false, "BulkAdd");
805             }
806
807             CallbackManager.RegisterReqId(reqId, this);
808         }
809
810         private void DataChange(IntPtr handle, ChangeType type, IntPtr data, IntPtr userData)
811         {
812             OnDataChange(type, new Bundle(new SafeBundleHandle(data, false)));
813         }
814
815         private void DataChangeListenResult(IntPtr handle, ResultType type, int callbackId, IntPtr userData)
816         {
817             OnDataChangeListenResult(new DataChangeListenResult(type));
818         }
819
820         /// <summary>
821         /// Listens the DataChange event.
822         /// </summary>
823         /// <remarks>The OnDataChangeListenResult will recieve the result of this API.</remarks>
824         /// <remarks>If success, the OnDataChange will recieve the DataChange event.</remarks>
825         /// <exception cref="UnauthorizedAccessException">Thrown in case if a permission is denied.</exception>
826         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
827         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
828         /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
829         /// <since_tizen> 3 </since_tizen>
830         public void DataChangeListen()
831         {
832             ResultType ret;
833             _lock.WaitOne();
834             /* Only one callback is allowed for every obejct */
835             if (_changeCallbackID > 0)
836             {
837                 _lock.ReleaseMutex();
838                 return;
839             }
840             _dataChangeCallback = new Interop.DataControl.DataChangeCallback(DataChange);
841             _addCallbackResultCallback = new Interop.DataControl.AddCallbackResultCallback(DataChangeListenResult);
842             ret = Interop.DataControl.AddDataChangeCallback(_handle, _dataChangeCallback, IntPtr.Zero,
843                       _addCallbackResultCallback , IntPtr.Zero, out _changeCallbackID);
844             _lock.ReleaseMutex();
845             if (ret != ResultType.Success)
846             {
847                 ErrorFactory.ThrowException(ret, false, "DataChangeListen");
848             }
849         }
850
851         /// <summary>
852         /// Initializes the Consumer class with the providerId and the ataId.
853         /// </summary>
854         /// <param name="providerId">The DataControl Provider ID.</param>
855         /// <param name="dataId">The DataControl Data ID.</param>
856         /// <exception cref="ArgumentException">Thrown in case of an invalid parmaeter.</exception>
857         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
858         /// <since_tizen> 3 </since_tizen>
859         public Consumer(string providerId, string dataId)
860         {
861             ResultType ret;
862
863             if (string.IsNullOrEmpty(providerId))
864             {
865                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "providerId");
866             }
867
868             if (string.IsNullOrEmpty(dataId))
869             {
870                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "dataId");
871             }
872
873             ret = Interop.DataControl.DataControlCreate(out _handle);
874             if (ret != ResultType.Success)
875             {
876                 ErrorFactory.ThrowException(ret, false, "Creating data control handle is failed");
877             }
878
879             Interop.DataControl.DataControlSetProviderId(_handle, providerId);
880             Interop.DataControl.DataControlSetDataId(_handle, dataId);
881             _lock.WaitOne();
882             CallbackManager.RegisterCallback(_handle, providerId);
883             _lock.ReleaseMutex();
884             _dataID = dataId;
885             _providerID = providerId;
886         }
887
888         /// <summary>
889         /// Destructor of the Consumer class.
890         /// </summary>
891         ~Consumer()
892         {
893             Dispose(false);
894         }
895
896         /// <summary>
897         /// Overrides this method if you want to handle the behavior when the DataChangeListen result is received.
898         /// </summary>
899         /// <since_tizen> 3 </since_tizen>
900         protected virtual void OnDataChangeListenResult(DataChangeListenResult result)
901         {
902             Log.Info(LogTag, "The OnDataChangeListenResult is not implemented.");
903         }
904
905         /// <summary>
906         /// Overrides this method if you want to handle the behavior when the data change event is received.
907         /// </summary>
908         /// <since_tizen> 3 </since_tizen>
909         protected virtual void OnDataChange(ChangeType type, Bundle data)
910         {
911             Log.Info(LogTag, "The OnDataChange is not implemented.");
912         }
913
914         /// <summary>
915         /// Overrides this method if you want to handle the behavior when the select response is received.
916         /// </summary>
917         /// <since_tizen> 3 </since_tizen>
918         protected abstract void OnSelectResult(SelectResult result);
919
920         /// <summary>
921         /// Overrides this method if you want to handle the behavior when the insert response is received.
922         /// </summary>
923         /// <since_tizen> 3 </since_tizen>
924         protected abstract void OnInsertResult(InsertResult result);
925
926         /// <summary>
927         /// Overrides this method if you want to handle the behavior when the update response is received.
928         /// </summary>
929         /// <since_tizen> 3 </since_tizen>
930         protected abstract void OnUpdateResult(UpdateResult result);
931
932         /// <summary>
933         /// Overrides this method if want to handle the behavior when the delete response is received.
934         /// </summary>
935         /// <since_tizen> 3 </since_tizen>
936         protected abstract void OnDeleteResult(DeleteResult result);
937         /// <summary>
938         /// Overrides this method if you want to handle the behavior when the BulkInsert response is received.
939         /// </summary>
940         /// <since_tizen> 3 </since_tizen>
941         protected virtual void OnBulkInsertResult(BulkInsertResult result)
942         {
943             Log.Info(LogTag, "The OnBulkInsertResult is not implemented.");
944         }
945
946         /// <summary>
947         /// Overrides this method if you want to handle the behavior when the map get response is received.
948         /// </summary>
949         /// <since_tizen> 3 </since_tizen>
950         protected virtual void OnMapGetResult(MapGetResult result)
951         {
952             Log.Info(LogTag, "The OnMapGetResult is not implemented.");
953         }
954
955         /// <summary>
956         /// Overrides this method if you want to handle the behavior when the map add response is received.
957         /// </summary>
958         /// <since_tizen> 3 </since_tizen>
959         protected virtual void OnMapAddResult(MapAddResult result)
960         {
961             Log.Info(LogTag, "The OnMapAddResult is not implemented.");
962         }
963
964         /// <summary>
965         /// Overrides this method if you want to handle the behavior when the map set response is received.
966         /// </summary>
967         /// <since_tizen> 3 </since_tizen>
968         protected virtual void OnMapSetResult(MapSetResult result)
969         {
970             Log.Info(LogTag, "The OnMapSetResult is not implemented.");
971         }
972
973         /// <summary>
974         /// Overrides this method if you want to handle the behavior when the map remove response is received.
975         /// </summary>
976         /// <since_tizen> 3 </since_tizen>
977         protected virtual void OnMapRemoveResult(MapRemoveResult result)
978         {
979             Log.Info(LogTag, "The OnMapRemoveResult is not implemented.");
980         }
981
982         /// <summary>
983         /// Overrides this method if you want to handle the behavior when the BulkAdd response is received.
984         /// </summary>
985         /// <since_tizen> 3 </since_tizen>
986         protected virtual void OnMapBulkAddResult(MapBulkAddResult result)
987         {
988             Log.Info(LogTag, "The OnMapBulkAddResult is not implemented.");
989         }
990
991         /// <summary>
992         /// Releases the unmanaged resources used by the Consumer class specifying whether to perform a normal dispose operation.
993         /// </summary>
994         /// <param name="disposing">true for a normal dispose operation; false to finalize the handle.</param>
995         /// <since_tizen> 3 </since_tizen>
996         protected virtual void Dispose(bool disposing)
997         {
998             if (!_disposed)
999             {
1000                 if (_changeCallbackID > 0)
1001                 {
1002                     Interop.DataControl.RemoveDataChangeCallback(_handle, _changeCallbackID);
1003                 }
1004
1005                 _lock.WaitOne();
1006                 CallbackManager.UnregisterCallback(_handle, _providerID);
1007                 _lock.ReleaseMutex();
1008                 _handle.Dispose();
1009                 _disposed = true;
1010             }
1011
1012             if (disposing)
1013             {
1014                 GC.SuppressFinalize(this);
1015             }
1016         }
1017
1018         /// <summary>
1019         /// Releases all resources used by the Consumer class.
1020         /// </summary>
1021         /// <since_tizen> 3 </since_tizen>
1022         public void Dispose()
1023         {
1024             Dispose(true);
1025         }
1026     }
1027 }