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