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