diff options
author | Hyunho Kang <hhstark.kang@samsung.com> | 2017-02-06 16:12:01 +0900 |
---|---|---|
committer | jusung son <jusung07.son@samsung.com> | 2017-03-09 15:45:16 +0900 |
commit | 2538329f7b12b5e63a8e7ff72fc6068a00c698cc (patch) | |
tree | e80347c7a23609a7de15cc2b130f45fd0d8521c6 | |
parent | a1334779fd8ede77e70182cf5bab7bfc5216c634 (diff) | |
download | data-control-submit/tizen/20170310.033151.tar.gz data-control-submit/tizen/20170310.033151.tar.bz2 data-control-submit/tizen/20170310.033151.zip |
Initial updatesubmit/tizen/20170310.033151submit/tizen/20170309.090943
Change-Id: I0ade91b17623af9486a919bdb05670815f964b30
Signed-off-by: Hyunho Kang <hhstark.kang@samsung.com>
Signed-off-by: jusung son <jusung07.son@samsung.com>
19 files changed, 4832 insertions, 0 deletions
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Tizen.Applications.DataControl/Interop/Interop.DataControl.cs b/Tizen.Applications.DataControl/Interop/Interop.DataControl.cs new file mode 100755 index 0000000..d20ec84 --- /dev/null +++ b/Tizen.Applications.DataControl/Interop/Interop.DataControl.cs @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; +using System.Text; +using Tizen.Applications; +using Tizen; +using Tizen.Applications.DataControl; + +internal static partial class Interop +{ + internal static partial class DataControl + { + + internal enum NativeResultType : int + { + Success = Tizen.Internals.Errors.ErrorCode.None, + OutOfMemory = Tizen.Internals.Errors.ErrorCode.OutOfMemory, + IoError = Tizen.Internals.Errors.ErrorCode.IoError, + InvalidParamer = Tizen.Internals.Errors.ErrorCode.InvalidParameter, + PermissionDenied = Tizen.Internals.Errors.ErrorCode.PermissionDenied, + MaxExceed = -0x01190000 | 0x01, + } + + internal sealed class SafeBulkDataHandle : SafeHandle + { + internal SafeBulkDataHandle() + : base(IntPtr.Zero, true) + { + } + + internal SafeBulkDataHandle(IntPtr existingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + SetHandle(existingHandle); + } + + public override bool IsInvalid + { + get { return this.handle == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + DataControl.BulkFree(this.handle); + this.SetHandle(IntPtr.Zero); + return true; + } + } + + internal sealed class SafeBulkResultDataHandle : SafeHandle + { + internal SafeBulkResultDataHandle() + : base(IntPtr.Zero, true) + { + } + + internal SafeBulkResultDataHandle(IntPtr existingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + SetHandle(existingHandle); + } + + public override bool IsInvalid + { + get { return this.handle == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + DataControl.BulkResultFree(this.handle); + this.SetHandle(IntPtr.Zero); + return true; + } + } + + internal sealed class SafeCursorHandle : SafeHandle + { + internal SafeCursorHandle() + : base(IntPtr.Zero, true) + { + } + + internal SafeCursorHandle(IntPtr existingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + SetHandle(existingHandle); + } + + public override bool IsInvalid + { + get { return this.handle == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + this.SetHandle(IntPtr.Zero); + return true; + } + } + + internal sealed class SafeDataControlHandle : SafeHandle + { + internal SafeDataControlHandle() + : base(IntPtr.Zero, true) + { + } + + internal SafeDataControlHandle(IntPtr existingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle) + { + SetHandle(existingHandle); + } + + public override bool IsInvalid + { + get { return this.handle == IntPtr.Zero; } + } + + protected override bool ReleaseHandle() + { + DataControl.Destroy(this.handle); + this.SetHandle(IntPtr.Zero); + return true; + } + } + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_create")] + internal static extern ResultType DataControlCreate(out SafeDataControlHandle handle); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_destroy")] + internal static extern ResultType Destroy(IntPtr handle); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_provider_id")] + internal static extern ResultType DataControlGetProviderId(SafeDataControlHandle handle, out string providerId); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_set_provider_id")] + internal static extern ResultType DataControlSetProviderId(SafeDataControlHandle handle, string providerId); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_set_data_id")] + internal static extern ResultType DataControlSetDataId(SafeDataControlHandle handle, string dataId); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_data_id")] + internal static extern ResultType DataControlGetDataId(SafeDataControlHandle handle, out string dataId); + + internal delegate void MapGetResponseCallback(int requestID, + IntPtr provider, string[] resultValueList, int resultValueCount, bool providerResult, string error, IntPtr userData); + internal delegate void MapSetResponseCallback(int requestID, + IntPtr provider, bool providerResult, string error, IntPtr userData); + internal delegate void MapAddResponseCallback(int requestID, + IntPtr provider, bool providerResult, string error, IntPtr userData); + internal delegate void MapRemoveResponseCallback(int requestID, + IntPtr provider, bool providerResult, string error, IntPtr userData); + internal delegate void MapBulkAddResponseCallback(int requestID, + IntPtr provider, IntPtr bulkResults, bool providerResult, string error, IntPtr userData); + + [StructLayoutAttribute(LayoutKind.Sequential)] + internal struct MapResponseCallbacks + { + public MapGetResponseCallback Get; + public MapSetResponseCallback Set; + public MapAddResponseCallback Add; + public MapRemoveResponseCallback Remove; + } + + internal delegate void SqlSelectResponseCallback(int requestID, + IntPtr provider, IntPtr cursor, bool providerResult, string error, IntPtr userData); + internal delegate void SqlInsertResponseCallback(int requestID, + IntPtr provider, long inserted_row_id, bool providerResult, string error, IntPtr userData); + internal delegate void SqlUpdateResponseCallback(int requestID, + IntPtr provider, bool providerResult, string error, IntPtr userData); + internal delegate void SqlDeleteResponseCallback(int requestID, + IntPtr provider, bool providerResult, string error, IntPtr userData); + internal delegate void SqlBulkInsertResponseCallback(int requestID, + IntPtr provider, IntPtr bulk_results, bool providerResult, string error, IntPtr userData); + + [StructLayoutAttribute(LayoutKind.Sequential)] + internal struct SqlResponseCallbacks + { + public SqlSelectResponseCallback Select; + public SqlInsertResponseCallback Insert; + public SqlUpdateResponseCallback Update; + public SqlDeleteResponseCallback Delete; + } + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_register_response_cb")] + internal static extern ResultType RegisterMapResponse(SafeDataControlHandle provider, ref MapResponseCallbacks callback, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_unregister_response_cb")] + internal static extern ResultType UnregisterMapResponse(SafeDataControlHandle provider); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_register_add_bulk_data_response_cb")] + internal static extern ResultType RegisterMapBulkResponseCallback(SafeDataControlHandle provider, MapBulkAddResponseCallback callback, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_unregister_add_bulk_data_response_cb")] + internal static extern ResultType UnregisterMapBulkResponseCallback(SafeDataControlHandle provider); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_register_response_cb")] + internal static extern ResultType RegisterSqlResponseCallback(SafeDataControlHandle provider, ref SqlResponseCallbacks callback, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_unregister_response_cb")] + internal static extern ResultType UnregisterSqlResponseCallback(SafeDataControlHandle provider); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_register_insert_bulk_data_response_cb")] + internal static extern ResultType RegisterSqlBulkResponseCallback(SafeDataControlHandle provider, SqlBulkInsertResponseCallback callback, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_unregister_insert_bulk_data_response_cb")] + internal static extern ResultType UnregisterSqlBulkResponseCallback(SafeDataControlHandle provider); + + internal delegate void MapGetRequestCallback(int requestID, + IntPtr provider, string key, IntPtr userData); + internal delegate void MapSetRequestCallback(int requestID, + IntPtr provider, string key, string oldValue, string newValue, IntPtr userData); + internal delegate void MapAddRequestCallback(int requestID, + IntPtr provider, string key, string value, IntPtr userData); + internal delegate void MapRemoveRequestCallback(int requestID, + IntPtr provider, string key, string value, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void MapBulkAddRequestCallback(int requestID, + IntPtr provider, IntPtr bulkData, IntPtr userData); + + [StructLayoutAttribute(LayoutKind.Sequential)] + internal struct MapRequestCallbacks + { + public MapGetRequestCallback Get; + public MapSetRequestCallback Set; + public MapAddRequestCallback Add; + public MapRemoveRequestCallback Remove; + } + + internal delegate void SqlInsertRequestCallback(int requestID, + IntPtr provider, IntPtr insertData, IntPtr userData); + internal delegate void SqlSelectRequestCallback(int requestID, + IntPtr provider, IntPtr columnList, int columnCount, string where, string order, IntPtr userData); + internal delegate void SqlUpdateRequestCallback(int requestID, + IntPtr provider, IntPtr updateData, string where, IntPtr userData); + internal delegate void SqlDeleteRequestCallback(int requestID, + IntPtr provider, string where, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SqlBulkInsertRequestCallback(int requestID, + IntPtr provider, IntPtr bulk_data, IntPtr userData); + + [StructLayoutAttribute(LayoutKind.Sequential)] + internal struct SqlRequestCallbacks + { + public SqlInsertRequestCallback Insert; + public SqlSelectRequestCallback Select; + public SqlUpdateRequestCallback Update; + public SqlDeleteRequestCallback Delete; + } + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_map_register_cb")] + internal static extern ResultType RegisterMapRequest(ref MapRequestCallbacks callback, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_sql_register_cb")] + internal static extern ResultType RegisterSqlRequest(ref SqlRequestCallbacks callback, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_sql_register_insert_bulk_data_request_cb")] + internal static extern ResultType RegisterSqlBulkRequest(SqlBulkInsertRequestCallback callback, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_sql_unregister_insert_bulk_data_request_cb")] + internal static extern ResultType UnregisterSqlBulkRequest(); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_map_register_add_bulk_data_request_cb")] + internal static extern ResultType RegisterMapBulkRequest(MapBulkAddRequestCallback callback, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_map_unregister_add_bulk_data_request_cb")] + internal static extern ResultType UnregisterMapBulkRequest(); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_map_result")] + internal static extern ResultType SendMapResult(int requestID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_map_get_value_result")] + internal static extern ResultType SendMapGetResult(int requestID, string[] valueList, int valueCount); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_insert_result")] + internal static extern ResultType SendInsertResult(int requestID, long rowId); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_update_result")] + internal static extern ResultType SendUpdateResult(int requestID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_delete_result")] + internal static extern ResultType SendDeleteResult(int requestID); + + [DllImport(Libraries.DataControl, EntryPoint = "datacontrol_provider_send_select_result_without_data")] + internal static extern ResultType SendSelectResult(int requestID, out int fd); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_error")] + internal static extern ResultType SendError(int requestID, string error); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_insert")] + internal static extern ResultType Insert(SafeDataControlHandle provider, SafeBundleHandle insertData, out int requestId); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_select_with_page")] + internal static extern ResultType Select(SafeDataControlHandle provider, string[] columnList, int columnCount, string where, string order, int pageNumber, + int countPerPage, out int requestID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_delete")] + internal static extern ResultType Delete(SafeDataControlHandle provider, string where, out int requestID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_update")] + internal static extern ResultType Update(SafeDataControlHandle provider, SafeBundleHandle updatetData, string where, out int requestID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_insert_bulk_data")] + internal static extern ResultType BulkInsert(SafeDataControlHandle provider, SafeBulkDataHandle insertData, out int requestID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_add")] + internal static extern ResultType MapAdd(SafeDataControlHandle provider, string key, string value, out int requestId); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_set")] + internal static extern ResultType MapSet(SafeDataControlHandle provider, string key, string oldValue, string newValue, out int requestId); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_remove")] + internal static extern ResultType MapRemove(SafeDataControlHandle provider, string key, string value, out int requestId); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_get_with_page")] + internal static extern ResultType MapGet(SafeDataControlHandle provider, string key, out int requestId, int pageNumber, + int countPerPage); + [DllImport(Libraries.DataControl, EntryPoint = "data_control_map_add_bulk_data")] + internal static extern ResultType BulkAdd(SafeDataControlHandle provider, SafeBulkDataHandle insertData, out int requestID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_create_insert_statement")] + internal static extern string CreateInsertStatement(SafeDataControlHandle provider, SafeBundleHandle insertData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_create_delete_statement")] + internal static extern string CreateDeleteStatement(SafeDataControlHandle provider, string where); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_create_update_statement")] + internal static extern string CreateUpdateStatement(SafeDataControlHandle provider, SafeBundleHandle updateData, string where); + + [DllImport(Libraries.DataControl, EntryPoint = "datacontrol_provider_get_select_page_info")] + internal static extern ResultType GetSelectPageInfo(int requestId, out int pageNum, out int countPerPage); + + [DllImport(Libraries.DataControl, EntryPoint = "datacontrol_provider_write_socket")] + internal static extern unsafe ResultType WriteSelectResult(int socketFd, byte* buffer, uint nbytes, out uint bytesWrite); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_data_change_noti")] + internal static extern ResultType SendDataChange(IntPtr handle, ChangeType type, SafeBundleHandle data); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_step_next")] + internal static extern ResultType Next(SafeCursorHandle cursor); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_step_last")] + internal static extern ResultType Last(SafeCursorHandle cursor); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_step_first")] + internal static extern ResultType First(SafeCursorHandle cursor); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_step_previous")] + internal static extern ResultType Prev(SafeCursorHandle cursor); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_column_count")] + internal static extern int GetColumnCount(SafeCursorHandle cursor); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_column_name")] + internal static extern ResultType GetColumnName(SafeCursorHandle cursor, int idx, StringBuilder name); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_column_item_size")] + internal static extern int GetItemSize(SafeCursorHandle cursor, int idx); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_column_item_type")] + internal static extern ResultType GetItemType(SafeCursorHandle cursor, int idx, out int type); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_blob_data")] + internal static extern ResultType GetBlob(SafeCursorHandle cursor, int idx, byte[] buffer, int size); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_int_data")] + internal static extern ResultType GetInt(SafeCursorHandle cursor, int idx, out int data); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_int64_data")] + internal static extern ResultType GetInt64(SafeCursorHandle cursor, int idx, out long data); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_double_data")] + internal static extern ResultType Getdouble(SafeCursorHandle cursor, int idx, out double data); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_sql_get_text_data")] + internal static extern unsafe ResultType GetText(SafeCursorHandle cursor, int idx, byte[] data); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_data_create")] + internal static extern ResultType BulkCreate(out SafeBulkDataHandle handle); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_data_add")] + internal static extern ResultType BulkAdd(SafeBulkDataHandle handle, SafeBundleHandle data); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_data_get_count")] + internal static extern ResultType BulkGetCount(SafeBulkDataHandle handle, out int count); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_data_destroy")] + internal static extern ResultType BulkFree(IntPtr handle); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_data_get_data")] + internal static extern ResultType BulkGetData(SafeBulkDataHandle handle, int idx, out IntPtr data); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_result_data_create")] + internal static extern ResultType BulkResultCreate(out SafeBulkResultDataHandle handle); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_result_data_add")] + internal static extern ResultType BulkResultAdd(SafeBulkResultDataHandle handle, SafeBundleHandle data, int result); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_result_data_get_count")] + internal static extern ResultType BulkResultGetCount(SafeBulkResultDataHandle handle, out int count); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_result_data_get_result_data")] + internal static extern ResultType BulkResultGetData(SafeBulkResultDataHandle handle, int idx, out IntPtr data, out int result); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_result_data_get_result_data")] + internal static extern ResultType BulkResultGetResult(SafeBulkResultDataHandle handle, int idx, out IntPtr data, out int result); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_bulk_result_data_destroy")] + internal static extern ResultType BulkResultFree(IntPtr handle); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void AddCallbackResultCallback(IntPtr handle, ResultType type, int callbackID, IntPtr userData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void DataChangeCallback(IntPtr handle, ChangeType type, IntPtr data, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_add_data_change_cb", CallingConvention = CallingConvention.Cdecl)] + internal static extern ResultType AddDataChangeCallback(SafeDataControlHandle provider, DataChangeCallback callback, + IntPtr userData, AddCallbackResultCallback resultCallback, IntPtr resultCbUserData, out int callbackID); + + [DllImport(Libraries.DataControl, EntryPoint = "datacontrol_remove_data_change_cb", CallingConvention = CallingConvention.Cdecl)] + internal static extern ResultType RemoveDataChangeCallback(SafeDataControlHandle provider, int callbackID); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool DataChangeConsumerFilterCb(IntPtr handle, string consumerAppid, IntPtr userData); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_add_data_change_consumer_filter_cb", CallingConvention = CallingConvention.Cdecl)] + internal static extern ResultType AddDataChangeConsumerFilterCallback(DataChangeConsumerFilterCb callback, + IntPtr userData, + out int callbackID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_remove_data_change_consumer_filter_cb")] + internal static extern int RemoveDataChangeConsumerFilterCallback(int callbackID); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_bulk_insert_result")] + internal static extern ResultType SendBulkInsertResult(int requestId, SafeBulkResultDataHandle result); + + [DllImport(Libraries.DataControl, EntryPoint = "data_control_provider_send_map_bulk_add_result")] + internal static extern ResultType SendMapBulkAddResult(int requestId, SafeBulkResultDataHandle result); + + internal static class UnsafeCode + { + internal static unsafe ResultType WriteResult(int socketFd, byte[] value, int nbytes, out uint bytesWrite) + { + fixed (byte* pointer = value) + { + return WriteSelectResult(socketFd, pointer, (uint)nbytes, out bytesWrite); + } + } + } + + } +} diff --git a/Tizen.Applications.DataControl/Interop/Interop.Libraries.cs b/Tizen.Applications.DataControl/Interop/Interop.Libraries.cs new file mode 100755 index 0000000..1658ec6 --- /dev/null +++ b/Tizen.Applications.DataControl/Interop/Interop.Libraries.cs @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +internal static partial class Interop +{ + internal static partial class Libraries + { + public const string DataControl = "libdata-control.so.0"; + } +} diff --git a/Tizen.Applications.DataControl/Properties/AssemblyInfo.cs b/Tizen.Applications.DataControl/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..0893ef3 --- /dev/null +++ b/Tizen.Applications.DataControl/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tizen.Applications.DataControl")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Tizen.Applications.DataControl")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6f7e4ff6-4cea-4bb6-87b4-56498d6f3b24")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Tizen.Applications.DataControl/Tizen.Application.DataControl.snk b/Tizen.Applications.DataControl/Tizen.Application.DataControl.snk Binary files differnew file mode 100755 index 0000000..af23c55 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Application.DataControl.snk diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl.Core/CloneCursorCore.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl.Core/CloneCursorCore.cs new file mode 100755 index 0000000..03ee2b5 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl.Core/CloneCursorCore.cs @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +using System.IO; +using System.Text; +using System.Collections.Generic; +using System.Threading; + +namespace Tizen.Applications.DataControl.Core +{ + internal class CloneCursorCore : ICursor + { + internal const int MaxColumnNameSize = 1024; + private const string LogTag = "Tizen.Applications.DataControl"; + private long _rowCount; + private int _columnCount; + private const int ResultNoData = -1; + private Interop.DataControl.SafeCursorHandle _cursor; + internal CloneCursorCore(Interop.DataControl.SafeCursorHandle cursor) + { + _cursor = cursor; + _columnCount = Interop.DataControl.GetColumnCount(cursor); + + if (_columnCount == ResultNoData) + { + _rowCount = 0; + return; + } + + Interop.DataControl.First(cursor); + + do + { + _rowCount++; + } + while (Interop.DataControl.Next(cursor) == (int)ResultType.Success); + Interop.DataControl.First(cursor); + } + + public int GetColumnCount() + { + return Interop.DataControl.GetColumnCount(_cursor); + } + + public ColumnType GetColumnType(int index) + { + int type; + ResultType ret; + + if (index < 0 || index >= _columnCount) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + ret = Interop.DataControl.GetItemType(_cursor, index, out type); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Column Index " + index.ToString()); + } + + return (ColumnType)type; + } + + public string GetColumnName(int index) + { + string retStr; + ResultType ret; + StringBuilder columnName = new StringBuilder(); + + if (index < 0 || index >= _columnCount) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + columnName.Length = MaxColumnNameSize; + ret = Interop.DataControl.GetColumnName(_cursor, index, columnName); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Column Index " + index.ToString()); + } + + retStr = columnName.ToString(); + columnName.Clear(); + columnName = null; + + return retStr; + } + + public long GetRowCount() + { + return _rowCount; + } + + public bool Next() + { + ResultType type = Interop.DataControl.Next(_cursor); + + if (type != ResultType.Success) + { + return false; + } + + return true; + } + + public bool Prev() + { + ResultType type = Interop.DataControl.Prev(_cursor); + + if (type != ResultType.Success) + { + return false; + } + + return true; + } + + public bool Reset() + { + ResultType type = Interop.DataControl.First(_cursor); + + if (type != ResultType.Success) + { + return false; + } + + return true; + } + + public int GetIntValue(int index) + { + ResultType ret; + int value; + + if (index < 0 || index >= _columnCount) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + ret = Interop.DataControl.GetInt(_cursor, index, out value); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Column Index " + index.ToString()); + } + + return value; + } + + public Int64 GetInt64Value(int index) + { + ResultType ret; + Int64 value; + + if (index < 0 || index >= _columnCount) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + ret = Interop.DataControl.GetInt64(_cursor, index, out value); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Column Index " + index.ToString()); + } + + return value; + } + + public double GetDoubleValue(int index) + { + ResultType ret; + double value; + + if (index < 0 || index >= _columnCount) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + ret = Interop.DataControl.Getdouble(_cursor, index, out value); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Column Index " + index.ToString()); + } + + return value; + } + + public string GetStringValue(int index) + { + ResultType ret; + int size; + byte[] value; + string text; + + if (index < 0 || index >= _columnCount) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + size = Interop.DataControl.GetItemSize(_cursor, index); + if (size < 0) + { + ErrorFactory.ThrowException(ResultType.IoError, false, "Invalid size"); + } + + value = new byte[size + 1]; + ret = Interop.DataControl.GetText(_cursor, index, value); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false); + } + + text = Encoding.UTF8.GetString(value); + + return text; + } + + public byte[] GetBlobValue(int index) + { + ResultType ret; + int size; + byte[] byte_array; + + if (index < 0 || index >= _columnCount) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + size = Interop.DataControl.GetItemSize(_cursor, index); + if (size < 0) + { + ErrorFactory.ThrowException(ResultType.IoError, false, "Invalid size"); + } + + byte_array = new byte[size]; + ret = Interop.DataControl.GetBlob(_cursor, index, byte_array, size); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false); + } + + return byte_array; + } + } +}
\ No newline at end of file diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl.csproj b/Tizen.Applications.DataControl/Tizen.Applications.DataControl.csproj new file mode 100755 index 0000000..22e9e2a --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl.csproj @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>8.0.30703</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{6F7E4FF6-4CEA-4BB6-87B4-56498D6F3B24}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Tizen.Applications.DataControl</RootNamespace> + <AssemblyName>Tizen.Applications.DataControl</AssemblyName> + <FileAlignment>512</FileAlignment> + <DefaultLanguage>en-US</DefaultLanguage> + </PropertyGroup> + <PropertyGroup> + <TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier> + <TargetFrameworkVersion>v1.3</TargetFrameworkVersion> + <NuGetTargetMoniker>.NETStandard,Version=v1.3</NuGetTargetMoniker> + <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences> + <NoStdLib>true</NoStdLib> + <NoWarn>$(NoWarn);1701</NoWarn> + <UseVSHostingProcess>false</UseVSHostingProcess> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup> + <SignAssembly>true</SignAssembly> + </PropertyGroup> + <PropertyGroup> + <AssemblyOriginatorKeyFile>Tizen.Application.DataControl.snk</AssemblyOriginatorKeyFile> + </PropertyGroup> + <ItemGroup> + <None Include="Tizen.Application.DataControl.snk" /> + <None Include="Tizen.Applications.DataControl.project.json" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Interop\Interop.Libraries.cs" /> + <Compile Include="Interop\Interop.DataControl.cs" /> + <Compile Include="Tizen.Applications.DataControl\ICursor.cs" /> + <Compile Include="Tizen.Applications.DataControl\Consumer.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Tizen.Applications.DataControl\BulkData.cs" /> + <Compile Include="Tizen.Applications.DataControl.Core\CloneCursorCore.cs" /> + <Compile Include="Tizen.Applications.DataControl\ErrorFactory.cs" /> + <Compile Include="Tizen.Applications.DataControl\MatrixCursor.cs" /> + <Compile Include="Tizen.Applications.DataControl\Provider.cs" /> + <Compile Include="Tizen.Applications.DataControl\Types.cs" /> + <Compile Include="Tizen.Applications.DataControl\Results.cs" /> + </ItemGroup> + <ItemGroup /> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> + <PropertyGroup> + <!-- https://github.com/dotnet/corefxlab/tree/master/samples/NetCoreSample and + https://docs.microsoft.com/en-us/dotnet/articles/core/tutorials/target-dotnetcore-with-msbuild + --> + <!-- We don't use any of MSBuild's resolution logic for resolving the framework, so just set these two + properties to any folder that exists to skip the GetReferenceAssemblyPaths task (not target) and + to prevent it from outputting a warning (MSB3644). + --> + <_TargetFrameworkDirectories>$(MSBuildThisFileDirectory)</_TargetFrameworkDirectories> + <_FullFrameworkReferenceAssemblyPaths>$(MSBuildThisFileDirectory)</_FullFrameworkReferenceAssemblyPaths> + <AutoUnifyAssemblyReferences>true</AutoUnifyAssemblyReferences> + </PropertyGroup> + <ProjectExtensions> + <VisualStudio> + <UserProperties Tizen_1Applications_1DataControl_1project_1json__JSONSchema="http://json.schemastore.org/sarif-1.0.0.json" /> + </VisualStudio> + </ProjectExtensions> +</Project>
\ No newline at end of file diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl.nuspec b/Tizen.Applications.DataControl/Tizen.Applications.DataControl.nuspec new file mode 100755 index 0000000..972ed2c --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl.nuspec @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<package> + <metadata> + <id>Tizen.Applications.DataControl</id> + <version>$version$</version> + <authors>Samsung Electronics</authors> + <requireLicenseAcceptance>false</requireLicenseAcceptance> + <licenseUrl>https://www.apache.org/licenses/LICENSE-2.0</licenseUrl> + <projectUrl>https://www.tizen.org/</projectUrl> + <iconUrl>https://developer.tizen.org/sites/default/files/images/tizen-pinwheel-on-light-rgb_64_64.png</iconUrl> + <copyright>© Samsung Electronics Co., Ltd All Rights Reserved</copyright> + <description>Provides the Data Control API for Tizen.Net</description> + <dependencies> + <dependency id="Tizen" version="1.0.2" /> + <dependency id="Tizen.Applications" version="1.2.0" /> + </dependencies> + </metadata> + <files> + <file src="bin/$Configuration$/Tizen.Applications.DataControl.dll" target="lib/netstandard1.3" /> + </files> +</package> diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl.project.json b/Tizen.Applications.DataControl/Tizen.Applications.DataControl.project.json new file mode 100755 index 0000000..ed5f888 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl.project.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Threading.Thread": "4.3.0", + "Tizen": "1.0.2", + "Tizen.Applications": "1.2.0" + }, + "frameworks": { + "netstandard1.3": {} + } +}
\ No newline at end of file diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl/BulkData.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/BulkData.cs new file mode 100755 index 0000000..90aa0a1 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/BulkData.cs @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +using System; +using System.Collections.Generic; + +namespace Tizen.Applications.DataControl +{ + /// <summary> + /// Represents BulkData class for DataControl bulk request. + /// </summary> + public class BulkData : IDisposable + { + private bool _disposed = false; + private Interop.DataControl.SafeBulkDataHandle _handle; + + /// <summary> + /// Initializes BulkData class. + /// </summary> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + public BulkData() + { + ResultType ret; + + ret = Interop.DataControl.BulkCreate(out _handle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkCreate"); + } + + } + + internal BulkData(Interop.DataControl.SafeBulkDataHandle handle) + { + ResultType ret; + int count, i; + + ret = Interop.DataControl.BulkCreate(out _handle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkCreate"); + } + + ret = Interop.DataControl.BulkGetCount(handle, out count); + for ( i = 0; i < count; i++) + { + IntPtr bundleHandle; + Bundle bundle; + + ret = Interop.DataControl.BulkGetData(handle, i, out bundleHandle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkGetData"); + } + + bundle = new Bundle(new SafeBundleHandle(bundleHandle, false)); + ret = Interop.DataControl.BulkAdd(_handle, bundle.SafeBundleHandle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkAdd"); + } + } + } + + internal Interop.DataControl.SafeBulkDataHandle SafeBulkDataHandle + { + get { return _handle; } + } + + /// <summary> + /// Adds bulk data. + /// </summary> + /// <param name="data">Bulk data</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public void Add(Bundle data) + { + ResultType ret; + + if (data == null || data.SafeBundleHandle.IsInvalid) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "data"); + } + + ret = Interop.DataControl.BulkAdd(_handle, data.SafeBundleHandle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkAdd"); + } + } + + /// <summary> + /// Gets current data count. + /// </summary> + public int GetCount() + { + int count; + ResultType ret; + + ret = Interop.DataControl.BulkGetCount(_handle, out count); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkGetCount"); + } + + return count; + } + + /// <summary> + /// Returns the data at the given zero-based data index. + /// </summary> + /// <param name="index">Target data index</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public Bundle GetData(int index) + { + IntPtr bundlePtr; + Bundle bundle; + ResultType ret; + + if (index < 0) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "index"); + } + + ret = Interop.DataControl.BulkGetData(_handle, index, out bundlePtr); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkGetData"); + } + + bundle = new Bundle(new SafeBundleHandle(bundlePtr, false)); + return bundle; + } + + /// <summary> + /// Releases all resources used by the BulkData class. + /// </summary> + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// <summary> + /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects. + /// </summary> + /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param> + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (_handle != null && !_handle.IsInvalid) + { + _handle.Dispose(); + } + + _disposed = true; + } + } + + ~BulkData() + { + Dispose(false); + } + } + + /// <summary> + /// Represents BulkResultData class for DataControl bulk request. + /// </summary> + public class BulkResultData : IDisposable + { + private const string LogTag = "Tizen.Applications.DataControl"; + private bool _disposed = false; + private Interop.DataControl.SafeBulkResultDataHandle _handle; + /// <summary> + /// Initializes BulkResultData class. + /// </summary> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + public BulkResultData() + { + ResultType ret; + + ret = Interop.DataControl.BulkResultCreate(out _handle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true,"BulkResultCreate"); + } + } + + internal BulkResultData(Interop.DataControl.SafeBulkResultDataHandle handle) + { + ResultType ret; + + ret = Interop.DataControl.BulkResultCreate(out _handle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true,"BulkResultCreate"); + } + + int count; + ret = Interop.DataControl.BulkResultGetCount(handle, out count); + for (int i = 0; i < count; i++) + { + IntPtr bundleHandle; + Bundle bundle; + int result; + + ret = Interop.DataControl.BulkResultGetData(handle, i, out bundleHandle, out result); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkResultGetData"); + } + + bundle = new Bundle(new SafeBundleHandle(bundleHandle, false)); + ret = Interop.DataControl.BulkResultAdd(_handle, bundle.SafeBundleHandle, result); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkResultAdd"); + } + } + } + + /// <summary> + /// Adds bulk operation result data. + /// </summary> + /// <param name="data">Result data</param> + /// <param name="result">Result</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public void Add(Bundle data, int result) + { + ResultType ret; + + if (data == null || data.SafeBundleHandle.IsInvalid) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "data"); + } + + ret = Interop.DataControl.BulkResultAdd(_handle, data.SafeBundleHandle, result); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkResultAdd"); + } + } + + internal Interop.DataControl.SafeBulkResultDataHandle SafeBulkDataHandle + { + get { return _handle; } + } + + /// <summary> + /// Gets current result data count. + /// </summary> + public int GetCount() + { + int count; + ResultType ret; + + ret = Interop.DataControl.BulkResultGetCount(_handle, out count); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true,"BulkResultGetCount"); + } + + return count; + } + + /// <summary> + /// Returns the result data at the given zero-based data index. + /// </summary> + /// <param name="index">Target result data index</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public Bundle GetData(int index) + { + IntPtr bundlePtr; + Bundle bundle; + ResultType ret; + int result; + + if (index < 0) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "index"); + } + + ret = Interop.DataControl.BulkResultGetData(_handle, index, out bundlePtr, out result); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkResultGetData"); + } + + bundle = new Bundle(new SafeBundleHandle(bundlePtr, false)); + return bundle; + } + + /// <summary> + /// Returns the result at the given zero-based data index. + /// </summary> + /// <param name="index">Target result index</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public int GetResult(int index) + { + IntPtr bundlePtr; + ResultType ret; + int result; + + if (index < 0) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "index"); + } + + ret = Interop.DataControl.BulkResultGetData(_handle, index, out bundlePtr, out result); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, true, "BulkResultGetData"); + } + + return result; + } + + /// <summary> + /// Releases all resources used by the BulkResultData class. + /// </summary> + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// <summary> + /// Releases any unmanaged resources used by this object. Can also dispose any other disposable objects. + /// </summary> + /// <param name="disposing">If true, disposes any disposable objects. If false, does not dispose disposable objects.</param> + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (_handle != null && !_handle.IsInvalid) + { + _handle.Dispose(); + } + + _disposed = true; + } + } + + ~BulkResultData() + { + Dispose(false); + } + } +} diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Consumer.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Consumer.cs new file mode 100755 index 0000000..0d50911 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Consumer.cs @@ -0,0 +1,973 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +using System; +using System.Collections.Generic; +using Tizen.Applications.DataControl.Core; +using System.Threading; + +namespace Tizen.Applications.DataControl +{ + /// <summary> + /// Represents Consumer class for DataControl consumer application. + /// </summary> + public abstract class Consumer : IDisposable + { + + private Interop.DataControl.SafeDataControlHandle _handle; + private string _dataID, _providerID; + private int _changeCallbackID = 0; + private const string LogTag = "Tizen.Applications.DataControl"; + private bool _disposed = false; + private static Mutex _lock = new Mutex(); + private Interop.DataControl.DataChangeCallback _dataChangeCallback; + private Interop.DataControl.AddCallbackResultCallback _addCallbackResultCallback; + + private static class CallbackManager + { + private static IDictionary<string, Interop.DataControl.MapResponseCallbacks> _mapResponseCallbacks = new Dictionary<string, Interop.DataControl.MapResponseCallbacks>(); + private static IDictionary<string, Interop.DataControl.MapBulkAddResponseCallback> _mapBulkResponseCallback = new Dictionary<string, Interop.DataControl.MapBulkAddResponseCallback>(); + private static IDictionary<string, Interop.DataControl.SqlResponseCallbacks> _sqlResponseCallbacks = new Dictionary<string, Interop.DataControl.SqlResponseCallbacks>(); + private static IDictionary<string, Interop.DataControl.SqlBulkInsertResponseCallback> _sqlBulkResponseCallback = new Dictionary<string, Interop.DataControl.SqlBulkInsertResponseCallback>(); + private static IDictionary<int, Consumer> _reqConsumerDictionary = new Dictionary<int, Consumer>(); + private static IDictionary<string, int> _reqProviderList = new Dictionary<string, int>(); + private static void InsertResponse(int reqId, IntPtr provider, long insertedRowId, bool providerResult, string error, IntPtr userData) + { + Log.Debug(LogTag, $"InsertResponse {reqId.ToString()}"); + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}, rowID : {insertedRowId.ToString()}"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnInsertResult(new InsertResult(insertedRowId, providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static void BulkInsertResponse(int reqId, IntPtr provider, IntPtr bulkResults, bool providerResult, string error, IntPtr userData) + { + BulkResultData brd; + Log.Debug(LogTag, $"BulkInsertResponse {reqId.ToString()}"); + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + if (bulkResults != IntPtr.Zero) + { + brd = new BulkResultData(new Interop.DataControl.SafeBulkResultDataHandle(bulkResults, false)); + } + else + { + brd = new BulkResultData(); + Log.Error(LogTag, $"reqId {reqId.ToString()}, bulkResults is null"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnBulkInsertResult(new BulkInsertResult(brd, providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static void SelectResponse(int reqId, IntPtr provider, IntPtr cursor, bool providerResult, string error, IntPtr userData) + { + MatrixCursor dmc; + Log.Debug(LogTag, $"SelectResponse {reqId.ToString()}"); + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + if (cursor != IntPtr.Zero) + { + try + { + dmc = CloneCursor(new CloneCursorCore(new Interop.DataControl.SafeCursorHandle(cursor, true))); + } + catch (Exception ex) + { + dmc = new MatrixCursor(); + Log.Error(LogTag, $"reqId {reqId.ToString()}, {ex.ToString()}"); + } + } + else + { + dmc = new MatrixCursor(); + Log.Error(LogTag, $"reqId {reqId.ToString()}, cursor is null"); + } + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnSelectResult(new SelectResult(dmc, providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static void UpdateResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData) + { + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnUpdateResult(new UpdateResult(providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static void DeleteResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData) + { + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnDeleteResult(new DeleteResult(providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static void MapGetResponse(int reqId, IntPtr provider, string[] valueList, int valueCount, bool providerResult, string error, IntPtr userData) + { + MapGetResult mgr; + Log.Debug(LogTag, $"MapGetResponse {reqId.ToString()}"); + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + if (valueList !=null) + { + mgr = new MapGetResult(valueList, providerResult); + } + else + { + mgr = new MapGetResult(new string[0], providerResult); + Log.Error(LogTag, $"reqId {reqId.ToString()}, valueList is null"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnMapGetResult(mgr); + _reqConsumerDictionary.Remove(reqId); + } + + private static void MapBulkAddResponse(int reqId, IntPtr provider, IntPtr bulkResults, bool providerResult, string error, IntPtr userData) + { + BulkResultData brd; + Log.Debug(LogTag, $"MapBulkAddResponse {reqId.ToString()}"); + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + if (bulkResults != IntPtr.Zero) + { + brd = new BulkResultData(new Interop.DataControl.SafeBulkResultDataHandle(bulkResults, false)); + } + else + { + brd = new BulkResultData(); + Log.Error(LogTag, $"reqId {reqId.ToString()}, bulkResults is null"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnMapBulkAddResult(new MapBulkAddResult(brd, providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static void MapAddResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData) + { + Log.Debug(LogTag, $"MapAddResponse {reqId.ToString()}"); + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnMapAddResult(new MapAddResult(providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static void MapSetResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData) + { + Log.Debug(LogTag, $"MapSetResponse {reqId.ToString()}"); + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnMapSetResult(new MapSetResult(providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static void MapRemoveResponse(int reqId, IntPtr provider, bool providerResult, string error, IntPtr userData) + { + if (!_reqConsumerDictionary.ContainsKey(reqId)) + { + Log.Error(LogTag, $"Invalid reqId {reqId.ToString()}"); + return; + } + + if (!providerResult) + { + Log.Error(LogTag, $"reqId {reqId.ToString()}, error : {error}"); + } + + Consumer consumer = _reqConsumerDictionary[reqId]; + consumer.OnMapRemoveResult(new MapRemoveResult(providerResult)); + _reqConsumerDictionary.Remove(reqId); + } + + private static MatrixCursor CloneCursor(CloneCursorCore coreCursor) + { + int size = coreCursor.GetColumnCount(); + int i; + string[] name = new string[size]; + object[] newRow = new object[size]; + ColumnType[] type = new ColumnType[size]; + + for (i = 0; i < size; i++) + { + name[i] = coreCursor.GetColumnName(i); + type[i] = coreCursor.GetColumnType(i); + } + + MatrixCursor dmc = new MatrixCursor(name, type); + + if (coreCursor.GetRowCount() <= 0) + { + return dmc; + } + + coreCursor.Reset(); + do + { + for (i = 0; i < size; i++) + { + switch (type[i]) + { + case ColumnType.ColumnTypeInt: + newRow[i] = coreCursor.GetInt64Value(i); + break; + case ColumnType.ColumnTypeDouble: + newRow[i] = coreCursor.GetDoubleValue(i); + break; + case ColumnType.ColumnTypeBlob: + newRow[i] = coreCursor.GetBlobValue(i); + break; + case ColumnType.ColumnTypeString: + newRow[i] = coreCursor.GetStringValue(i); + break; + } + } + + dmc.AddRow(newRow); + } + while (coreCursor.Next()); + + return dmc; + } + + internal static void RegisterReqId(int reqId, Consumer consumer) + { + _lock.WaitOne(); + _reqConsumerDictionary.Add(reqId, consumer); + _lock.ReleaseMutex(); + } + + internal static void RegisterCallback(Interop.DataControl.SafeDataControlHandle handle, string providerId) + { + ResultType ret; + Interop.DataControl.SqlResponseCallbacks sqlCallbacks; + Interop.DataControl.SqlBulkInsertResponseCallback sqlBulkCallbacks; + Interop.DataControl.MapResponseCallbacks mapCallbacks; + Interop.DataControl.MapBulkAddResponseCallback mapBulkCallbacks; + bool sqlRegistered = false; + bool mapRegistered = false; + + if (_reqProviderList.ContainsKey(providerId)) + { + _reqProviderList[providerId]++; + Log.Error(LogTag, "The data control is already set"); + return; + } + + sqlCallbacks.Insert = new Interop.DataControl.SqlInsertResponseCallback(InsertResponse); + sqlCallbacks.Select = new Interop.DataControl.SqlSelectResponseCallback(SelectResponse); + sqlCallbacks.Update = new Interop.DataControl.SqlUpdateResponseCallback(UpdateResponse); + sqlCallbacks.Delete = new Interop.DataControl.SqlDeleteResponseCallback(DeleteResponse); + ret = Interop.DataControl.RegisterSqlResponseCallback(handle, ref sqlCallbacks, IntPtr.Zero); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "Registering the sql callback function is failed : " + ret); + } + else + { + _sqlResponseCallbacks.Add(providerId, sqlCallbacks); + sqlRegistered = true; + } + + sqlBulkCallbacks = new Interop.DataControl.SqlBulkInsertResponseCallback(BulkInsertResponse); + ret = Interop.DataControl.RegisterSqlBulkResponseCallback(handle, sqlBulkCallbacks, IntPtr.Zero); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "Registering the sql bulk callback function is failed : " + ret); + } + else + { + _sqlBulkResponseCallback.Add(providerId, sqlBulkCallbacks); + } + + mapCallbacks.Add = new Interop.DataControl.MapAddResponseCallback(MapAddResponse); + mapCallbacks.Set = new Interop.DataControl.MapSetResponseCallback(MapSetResponse); + mapCallbacks.Get = new Interop.DataControl.MapGetResponseCallback(MapGetResponse); + mapCallbacks.Remove = new Interop.DataControl.MapRemoveResponseCallback(MapRemoveResponse); + ret = Interop.DataControl.RegisterMapResponse(handle, ref mapCallbacks, IntPtr.Zero); + + if (ret != ResultType.Success) + { + Log.Error(LogTag, "Registering the map callback function is failed : " + ret); + } + else + { + _mapResponseCallbacks.Add(providerId, mapCallbacks); + mapRegistered = true; + } + + mapBulkCallbacks = new Interop.DataControl.MapBulkAddResponseCallback(MapBulkAddResponse); + ret = Interop.DataControl.RegisterMapBulkResponseCallback(handle, mapBulkCallbacks, IntPtr.Zero); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "Registering the map bulk callback function is failed : " + ret); + } + else + { + _mapBulkResponseCallback.Add(providerId, mapBulkCallbacks); + } + + if (!mapRegistered && !sqlRegistered) + { + ErrorFactory.ThrowException(ret, true, "Registering the response callback function is failed"); + } + + _reqProviderList.Add(providerId, 1); + } + + internal static void UnregisterCallback(Interop.DataControl.SafeDataControlHandle handle, string providerId) + { + int count; + + _reqProviderList[providerId]--; + count = _reqProviderList[providerId]; + if (count <= 0) + { + _reqProviderList.Remove(providerId); + + _mapResponseCallbacks.Remove(providerId); + Interop.DataControl.UnregisterMapResponse(handle); + + _mapBulkResponseCallback.Remove(providerId); + Interop.DataControl.UnregisterMapBulkResponseCallback(handle); + + _sqlResponseCallbacks.Remove(providerId); + Interop.DataControl.UnregisterSqlResponseCallback(handle); + + _sqlBulkResponseCallback.Remove(providerId); + Interop.DataControl.UnregisterSqlBulkResponseCallback(handle); + } + + } + } + + /// <summary> + /// Sends insert request to provider application. + /// </summary> + /// <remarks>OnInsertResult will recieve result of this API</remarks> + /// <param name="insertData">Insert data</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit(1MB)</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void Insert(Bundle insertData) + { + int reqId; + ResultType ret; + + if (insertData == null || insertData.SafeBundleHandle.IsInvalid) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "insertData"); + } + + _lock.WaitOne(); + ret = Interop.DataControl.Insert(_handle, insertData.SafeBundleHandle, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Insert"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends select request to provider application. + /// </summary> + /// <remarks>OnSelectResult will recieve result of this API</remarks> + /// <param name="columnList">Select target column list</param> + /// <param name="where">Where statement for select query</param> + /// <param name="order">Order statement for select query</param> + /// <param name="pageNumber">Select target page number</param> + /// <param name="countPerPage">Select row count per page</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void Select(string[] columnList, string where, string order, int pageNumber = 1, int countPerPage = 20) + { + int reqId, i; + ResultType ret; + if (columnList == null || columnList.Length == 0) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "column_list"); + } + + for (i = 0; i < columnList.Length; i++) + { + if (string.IsNullOrEmpty(columnList[i])) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "column_list index " + i.ToString()); + } + } + + _lock.WaitOne(); + ret = Interop.DataControl.Select(_handle, columnList, columnList.Length, where, order, pageNumber, countPerPage, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Select"); + } + Log.Info(LogTag, "select end. " + reqId.ToString()); + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends delete request to provider application. + /// </summary> + /// <remarks>OnDeleteResult will recieve result of this API</remarks> + /// <param name="where">Where statement for delete query</param> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void Delete(string where) + { + int reqId; + ResultType ret; + + _lock.WaitOne(); + ret = Interop.DataControl.Delete(_handle, where, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Delete"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends update request to provider application. + /// </summary> + /// <remarks>OnUpdateResult will recieve result of this API</remarks> + /// <param name="updateData">Update data</param> + /// <param name="where">Where statement for query</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit(1MB)</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void Update(Bundle updateData, string where) + { + int reqId; + ResultType ret; + + if (updateData == null || updateData.SafeBundleHandle.IsInvalid) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "insertData"); + } + + if (string.IsNullOrEmpty(where)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "where"); + } + + _lock.WaitOne(); + ret = Interop.DataControl.Update(_handle, updateData.SafeBundleHandle, where, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Update"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends bulk insert request to provider application. + /// </summary> + /// <remarks>OnBulkInsertResult will recieve result of this API</remarks> + /// <param name="insertData">Bulk insert data</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit(1MB)</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void BulkInsert(BulkData insertData) + { + int reqId; + ResultType ret; + + if (insertData == null || insertData.SafeBulkDataHandle.IsInvalid) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "insertData"); + } + + _lock.WaitOne(); + ret = Interop.DataControl.BulkInsert(_handle, insertData.SafeBulkDataHandle, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "BulkInsert"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends map add request to provider application. + /// </summary> + /// <remarks>OnMapAddResult will recieve result of this API</remarks> + /// <param name="key">The key of the value to add</param> + /// <param name="value">The value to add</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit(1MB)</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void MapAdd(string key, string value) + { + int reqId; + ResultType ret; + + if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + _lock.WaitOne(); + ret = Interop.DataControl.MapAdd(_handle, key, value, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "MapAdd"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends map get request to provider application. + /// </summary> + /// <remarks>OnMapGetResult will recieve result of this API</remarks> + /// <param name="key">The key of the value list to obtain</param> + /// <param name="pageNumber">The page number of the value set</param> + /// <param name="countPerPage">The desired maximum count of the data items per page</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void MapGet(string key, int pageNumber = 1, int countPerPage = 20) + { + int reqId; + ResultType ret; + + if (string.IsNullOrEmpty(key) || pageNumber <= 0 || countPerPage <= 0) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + _lock.WaitOne(); + ret = Interop.DataControl.MapGet(_handle, key, out reqId, pageNumber, countPerPage); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "MapGet"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends map remove request to provider application. + /// </summary> + /// <remarks>OnMapRemoveResult will recieve result of this API</remarks> + /// <param name="key">The key of the value to remove</param> + /// <param name="value">The value to remove</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void MapRemove(string key, string value) + { + int reqId; + ResultType ret; + + if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + _lock.WaitOne(); + ret = Interop.DataControl.MapRemove(_handle, key, value, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "MapRemove"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends map set request to provider application. + /// </summary> + /// <remarks>OnMapSetResult will recieve result of this API</remarks> + /// <param name="key">The key of the value to replace</param> + /// <param name="oldValue">The value to be replaced</param> + /// <param name="newValue"> The new value that replaces the existing value</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit(1MB)</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void MapSet(string key, string oldValue, string newValue) + { + int reqId; + ResultType ret; + + if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(oldValue) || string.IsNullOrEmpty(newValue)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + _lock.WaitOne(); + ret = Interop.DataControl.MapSet(_handle, key, oldValue, newValue, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "MapSet"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + /// <summary> + /// Sends map bulk add request to provider application. + /// </summary> + /// <remarks>OnMapBulkAddResult will recieve result of this API</remarks> + /// <param name="addData">Map bulk add data</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="ArgumentOutOfRangeException">Thrown when message has exceeded the maximum limit(1MB)</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void MapBulkAdd(BulkData addData) + { + int reqId; + ResultType ret; + + if (addData == null || addData.SafeBulkDataHandle.IsInvalid) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "addData"); + } + + _lock.WaitOne(); + ret = Interop.DataControl.BulkAdd(_handle, addData.SafeBulkDataHandle, out reqId); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "BulkAdd"); + } + + CallbackManager.RegisterReqId(reqId, this); + } + + private void DataChange(IntPtr handle, ChangeType type, IntPtr data, IntPtr userData) + { + OnDataChange(type, new Bundle(new SafeBundleHandle(data, false))); + } + + private void DataChangeListenResult(IntPtr handle, ResultType type, int callbackId, IntPtr userData) + { + OnDataChangeListenResult(new DataChangeListenResult(type)); + } + + /// <summary> + /// Listen DataChange event + /// </summary> + /// <remarks>OnDataChangeListenResult will recieve result of this API</remarks> + /// <remarks>If success, OnDataChange will recieve DataChange event</remarks> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + /// <privilege>http://tizen.org/privilege/appmanager.launch</privilege> + public void DataChangeListen() + { + ResultType ret; + _lock.WaitOne(); + /* Only one callback is allowed for every obejct */ + if (_changeCallbackID > 0) + { + _lock.ReleaseMutex(); + return; + } + _dataChangeCallback = new Interop.DataControl.DataChangeCallback(DataChange); + _addCallbackResultCallback = new Interop.DataControl.AddCallbackResultCallback(DataChangeListenResult); + ret = Interop.DataControl.AddDataChangeCallback(_handle, _dataChangeCallback, IntPtr.Zero, + _addCallbackResultCallback , IntPtr.Zero, out _changeCallbackID); + _lock.ReleaseMutex(); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "DataChangeListen"); + } + } + + /// <summary> + /// Initializes Consumer class with providerId and dataId. + /// </summary> + /// <param name="providerId">DataControl Provider ID</param> + /// <param name="dataId">DataControl Data ID</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + public Consumer(string providerId, string dataId) + { + ResultType ret; + + if (string.IsNullOrEmpty(providerId)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "providerId"); + } + + if (string.IsNullOrEmpty(dataId)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "dataId"); + } + + ret = Interop.DataControl.DataControlCreate(out _handle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false, "Creating data control handle is failed"); + } + + Interop.DataControl.DataControlSetProviderId(_handle, providerId); + Interop.DataControl.DataControlSetDataId(_handle, dataId); + CallbackManager.RegisterCallback(_handle, providerId); + _dataID = dataId; + _providerID = providerId; + } + + ~Consumer() + { + Dispose(false); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the DataChangeListen result is received. + /// </summary> + protected virtual void OnDataChangeListenResult(DataChangeListenResult result) + { + Log.Info(LogTag, "The OnDataChangeListenResult is not implemented."); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the data change event is received. + /// </summary> + protected virtual void OnDataChange(ChangeType type, Bundle data) + { + Log.Info(LogTag, "The OnDataChange is not implemented."); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the select response is received. + /// </summary> + protected abstract void OnSelectResult(SelectResult result); + + /// <summary> + /// Overrides this method if want to handle behavior when the insert response is received. + /// </summary> + protected abstract void OnInsertResult(InsertResult result); + + /// <summary> + /// Overrides this method if want to handle behavior when the update response is received. + /// </summary> + protected abstract void OnUpdateResult(UpdateResult result); + + /// <summary> + /// Overrides this method if want to handle behavior when the delete response is received. + /// </summary> + protected abstract void OnDeleteResult(DeleteResult result); + /// <summary> + /// Overrides this method if want to handle behavior when the BulkInsert response is received. + /// </summary> + protected virtual void OnBulkInsertResult(BulkInsertResult result) + { + Log.Info(LogTag, "The OnBulkInsertResult is not implemented."); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the map get response is received. + /// </summary> + protected virtual void OnMapGetResult(MapGetResult result) + { + Log.Info(LogTag, "The OnMapGetResult is not implemented."); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the map add response is received. + /// </summary> + protected virtual void OnMapAddResult(MapAddResult result) + { + Log.Info(LogTag, "The OnMapAddResult is not implemented."); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the map set response is received. + /// </summary> + protected virtual void OnMapSetResult(MapSetResult result) + { + Log.Info(LogTag, "The OnMapSetResult is not implemented."); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the map remove response is received. + /// </summary> + protected virtual void OnMapRemoveResult(MapRemoveResult result) + { + Log.Info(LogTag, "The OnMapRemoveResult is not implemented."); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the BulkAdd response is received. + /// </summary> + protected virtual void OnMapBulkAddResult(MapBulkAddResult result) + { + Log.Info(LogTag, "The OnMapBulkAddResult is not implemented."); + } + + /// <summary> + /// Releases the unmanaged resourced used by the Consumer class specifying whether to perform a normal dispose operation. + /// </summary> + /// <param name="disposing">true for a normal dispose operation; false to finalize the handle.</param> + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (_changeCallbackID > 0) + { + Interop.DataControl.RemoveDataChangeCallback(_handle, _changeCallbackID); + } + + CallbackManager.UnregisterCallback(_handle, _providerID); + _handle.Dispose(); + _disposed = true; + } + + if (disposing) + { + GC.SuppressFinalize(this); + } + } + + /// <summary> + /// Releases all resources used by the Consumer class. + /// </summary> + public void Dispose() + { + Dispose(true); + } + } +} diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl/ErrorFactory.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/ErrorFactory.cs new file mode 100755 index 0000000..16fd3cb --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/ErrorFactory.cs @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.CompilerServices; + +namespace Tizen.Applications.DataControl +{ + internal enum ErronType : int + { + Success = Interop.DataControl.NativeResultType.Success, + OutOfMemory = Interop.DataControl.NativeResultType.OutOfMemory, + IoError = Interop.DataControl.NativeResultType.IoError, + InvalidParamer = Interop.DataControl.NativeResultType.InvalidParamer, + PermissionDenied = Interop.DataControl.NativeResultType.PermissionDenied, + MaxExceed = Interop.DataControl.NativeResultType.MaxExceed, + } + + internal static class ErrorFactory + { + private const string LogTag = "Tizen.Applications.DataControl"; + + internal static void ThrowException(ResultType errorCode, bool ignoreType, string errorMessage = null, + [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0) + { + Log.Error(LogTag, $"{memberName}({lineNumber.ToString()}) : {filePath}"); + if (ignoreType) + { + throw new InvalidOperationException(string.IsNullOrEmpty(errorMessage) ? "error code : " + errorCode.ToString() : + $"{errorMessage} - {errorCode}"); + } + + switch (errorCode) + { + case ResultType.Success: + return; + case ResultType.OutOfMemory: + case ResultType.IoError: + throw new InvalidOperationException(string.IsNullOrEmpty(errorMessage) ? "error code : " + errorCode.ToString() : + $"{errorMessage} - {errorCode}"); + case ResultType.InvalidParamer: + Log.Error(LogTag, "Invalid parameter : " + errorMessage); + throw new ArgumentException(string.IsNullOrEmpty(errorMessage) ? "Invalid parameter" : "Invalid parameter : " + errorMessage); + case ResultType.PermissionDenied: + Log.Error(LogTag, "Permission denied : " + errorMessage); + throw new UnauthorizedAccessException(string.IsNullOrEmpty(errorMessage) ? "Permission denied" : "Permission denied : " + errorMessage); + case ResultType.MaxExceed: + Log.Error(LogTag, "Too long argument : " + errorMessage); + throw new ArgumentOutOfRangeException(string.IsNullOrEmpty(errorMessage) ? "Too long argument" : "Too long argument : " + errorMessage); + default: + Log.Error(LogTag, $"Unknown error : {errorMessage} - {errorCode}"); + throw new InvalidOperationException(string.IsNullOrEmpty(errorMessage) ? "Unknown error : " + errorCode.ToString() : + $"Unknown error : {errorMessage} - {errorCode}"); + } + } + } +} diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl/ICursor.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/ICursor.cs new file mode 100755 index 0000000..4136358 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/ICursor.cs @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +using System; + +namespace Tizen.Applications.DataControl +{ + /// <summary> + /// This interface is for DataControl cursor. + /// </summary> + public interface ICursor + { + /// <summary> + /// Gets a column count. + /// </summary> + int GetColumnCount(); + /// <summary> + /// Gets a column type. + /// </summary> + /// <param name="index">The index of column.</param> + ColumnType GetColumnType(int index); + /// <summary> + /// Gets a column name. + /// </summary> + /// <param name="index">The index of column.</param> + string GetColumnName(int index); + /// <summary> + /// Gets the numbers of rows in the cursor. + /// </summary> + long GetRowCount(); + /// <summary> + /// Gets a next row. + /// </summary> + bool Next(); + /// <summary> + /// Gets a prev row. + /// </summary> + bool Prev(); + /// <summary> + /// Gets a first row. + /// </summary> + bool Reset(); + /// <summary> + /// / Gets an int value. + /// </summary> + /// <param name="index">The index of row.</param> + int GetIntValue(int index); + /// <summary> + /// / Gets an int64 value. + /// </summary> + /// <param name="index">The index of row.</param> + Int64 GetInt64Value(int index); + /// <summary> + /// Gets an double value. + /// </summary> + /// <param name="index">The index of row.</param> + double GetDoubleValue(int index); + /// <summary> + /// Gets an string value. + /// </summary> + /// <param name="index">The index of row.</param> + string GetStringValue(int index); + /// <summary> + /// Gets a blob value. + /// </summary> + /// <param name="index">The index of row.</param> + byte[] GetBlobValue(int index); + } +}
\ No newline at end of file diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl/MatrixCursor.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/MatrixCursor.cs new file mode 100755 index 0000000..685a554 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/MatrixCursor.cs @@ -0,0 +1,616 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; +using System.Threading; + +namespace Tizen.Applications.DataControl +{ + /// <summary> + /// Represents MatrixCursor class for DataControl provider's matrix cursor. + /// </summary> + public class MatrixCursor : IDisposable, ICursor + { + private const string LogTag = "Tizen.Applications.DataControl"; + private FileStream _fs; + private bool _disposed = false; + private string _cursorPath; + private long _rowCount = 0; + private long _rowCountPosition = 0; + private int _currentRowIndex = 0; + private IList<long> _rowFieldOffset = new List<long>(); + private string[] _columnNames; + private ColumnType[] _columnTypes; + private const int ColumnTypeNull = 5; + + private byte[] GetValue(int index) + { + byte[] int_tmp = new byte[sizeof(int)]; + byte[] ret_array; + ColumnType type; + int size, read_len; + + MoveToColumn(index); + + read_len = _fs.Read(int_tmp, 0, int_tmp.Length); + if (read_len != int_tmp.Length) + { + ErrorFactory.ThrowException(ResultType.IoError, true, "Column Type " + index.ToString()); + } + + type = (ColumnType)BitConverter.ToInt32(int_tmp, 0); + + if (type != _columnTypes[index]) + { + if ((int)type == ColumnTypeNull && + (_columnTypes[index] == ColumnType.ColumnTypeBlob || _columnTypes[index] == ColumnType.ColumnTypeString)) + { + return null; /* null type */ + } + + ErrorFactory.ThrowException(ResultType.IoError, true, "Type mismatch " + index.ToString()); + } + + read_len = _fs.Read(int_tmp, 0, int_tmp.Length); + if (read_len != int_tmp.Length) + { + ErrorFactory.ThrowException(ResultType.IoError, true, "Column size " + index.ToString()); + } + + size = BitConverter.ToInt32(int_tmp, 0); + + if (size < 0) + { + ErrorFactory.ThrowException(ResultType.IoError, true, "Invalid data size " + index.ToString()); + } + + ret_array = new byte[size]; + read_len = _fs.Read(ret_array, 0, ret_array.Length); + if (read_len != ret_array.Length) + { + ErrorFactory.ThrowException(ResultType.IoError, true, "Column value size " + index.ToString()); + return null; + } + + return ret_array; + } + + private void MoveToColumn(int ColumnIndex) + { + int i, tmp_position; + byte[] int_tmp = new byte[sizeof(int)]; + int read_len; + long seek_len; + + seek_len = _fs.Seek(_rowFieldOffset[_currentRowIndex], SeekOrigin.Begin); + if (seek_len != _rowFieldOffset[_currentRowIndex]) + { + ErrorFactory.ThrowException(ResultType.IoError, true, "Row index " + _currentRowIndex.ToString()); + } + + for (i = 0; i < ColumnIndex; i++) + { + /* type(int) size(int) value */ + switch (_columnTypes[i]) + { + case ColumnType.ColumnTypeInt: + tmp_position = sizeof(int) * 2 + sizeof(Int64); + _fs.Seek(tmp_position, SeekOrigin.Current); + break; + case ColumnType.ColumnTypeDouble: + tmp_position = sizeof(int) * 2 + sizeof(double); + _fs.Seek(tmp_position, SeekOrigin.Current); + break; + case ColumnType.ColumnTypeString: + tmp_position = sizeof(int); + _fs.Seek(tmp_position, SeekOrigin.Current); + read_len = _fs.Read(int_tmp, 0, int_tmp.Length); + if (read_len != int_tmp.Length) + { + ErrorFactory.ThrowException(ResultType.IoError, true, "Column Index " + ColumnIndex.ToString()); + } + + tmp_position = BitConverter.ToInt32(int_tmp, 0); + + if (tmp_position > 0) + { + _fs.Seek(tmp_position, SeekOrigin.Current); + } + + break; + case ColumnType.ColumnTypeBlob: + tmp_position = sizeof(int); + _fs.Seek(tmp_position, SeekOrigin.Current); + + read_len = _fs.Read(int_tmp, 0, int_tmp.Length); + if (read_len != int_tmp.Length) + { + ErrorFactory.ThrowException(ResultType.IoError, true, "Column Index " + ColumnIndex.ToString()); + } + + tmp_position = BitConverter.ToInt32(int_tmp, 0); + + if (tmp_position > 0) + { + _fs.Seek(tmp_position, SeekOrigin.Current); + } + + break; + } + } + + } + + internal FileStream GetFileStream() + { + return _fs; + } + + /// <summary> + /// Gets column count of MatrixCursor. + /// </summary> + public int GetColumnCount() + { + return _columnTypes.Length; + } + + /// <summary> + /// Returns the column type at the given zero-based column index. + /// </summary> + /// <param name="index">Target column index</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public ColumnType GetColumnType(int index) + { + if (index < 0 || index >= _columnTypes.Length) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + return _columnTypes[index]; + } + + /// <summary> + /// Returns the column name at the given zero-based column index. + /// </summary> + /// <param name="index">Target column index</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public string GetColumnName(int index) + { + if (index < 0 || index >= _columnTypes.Length) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + return _columnNames[index]; + } + + /// <summary> + /// Gets MatrixCursor's row count. + /// </summary> + public long GetRowCount() + { + return _rowCount; + } + + /// <summary> + /// Move the MatrixCursor to the next row. + /// </summary> + public bool Next() + { + if (_currentRowIndex >= _rowCount - 1) + { + return false; + } + + _currentRowIndex++; + return true; + } + + /// <summary> + /// Move the MatrixCursor to the previous row. + /// </summary> + public bool Prev() + { + if (_currentRowIndex <= 0) + { + return false; + } + + _currentRowIndex--; + return true; + } + + /// <summary> + /// Move the MatrixCursor to the first row. + /// </summary> + public bool Reset() + { + _currentRowIndex = 0; + return true; + } + + /// <summary> + /// Returns the value of the requested column as a int. + /// </summary> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public int GetIntValue(int index) + { + int ret; + byte[] byte_array; + + if (index < 0 || index >= _columnTypes.Length) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + byte_array = GetValue(index); + ret = BitConverter.ToInt32(byte_array, 0); + + return ret; + } + + /// <summary> + /// Returns the value of the requested column as a int64. + /// </summary> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public Int64 GetInt64Value(int index) + { + Int64 ret; + byte[] byte_array; + + if (index < 0 || index >= _columnTypes.Length) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + byte_array = GetValue(index); + ret = BitConverter.ToInt64(byte_array, 0); + + return ret; + } + + /// <summary> + /// Returns the value of the requested column as a double. + /// </summary> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public double GetDoubleValue(int index) + { + double ret; + byte[] byte_array; + + if (index < 0 || index >= _columnTypes.Length) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + byte_array = GetValue(index); + ret = BitConverter.ToDouble(byte_array, 0); + + return ret; + } + + /// <summary> + /// Returns the value of the requested column as a string. + /// </summary> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public string GetStringValue(int index) + { + string ret; + byte[] byte_array; + + if (index < 0 || index >= _columnTypes.Length) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + byte_array = GetValue(index); + + if (byte_array == null) + { + return null; + } + + ret = Encoding.UTF8.GetString(byte_array); + return ret; + + } + + /// <summary> + /// Returns the value of the requested column as a blob. + /// </summary> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public byte[] GetBlobValue(int index) + { + byte[] byte_array; + + if (index < 0 || index >= _columnTypes.Length) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + byte_array = GetValue(index); + return byte_array; + } + + private static class FileManager + { + private static readonly string DATACONTROL_DIRECTORY = "/tmp/"; + private static Dictionary<int, int> fileTable = new Dictionary<int, int>(); + public static string OpenFileStream(int threadID) + { + string path; + int index; + + if (threadID < 0) + { + Log.Error(LogTag, "threadID is " + threadID.ToString()); + return null; + } + + if (fileTable.ContainsKey(threadID) == false) + { + fileTable.Add(threadID, 0); + } + + index = fileTable[threadID]; + index++; + fileTable[threadID] = index; + + path = DATACONTROL_DIRECTORY + Application.Current.ApplicationInfo.ApplicationId + "_"+Application.Current.ApplicationInfo.ProcessId.ToString() + "_" + threadID.ToString() + "_" + index.ToString(); + + return path; + } + } + + /// <summary> + /// Initializes MatrixCursor class with columnNames and columnTypes. + /// </summary> + /// <param name="columnNames">MatrixCursor's column name list</param> + /// <param name="columnTypes">MatrixCursor's column type list</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + public MatrixCursor(string[] columnNames, ColumnType[] columnTypes) + { + byte[] byte_tmp, length_tmp, string_tmp; + int i, total_len_of_column_names = 0; + + if (columnNames == null || columnTypes == null || + (columnNames.Length != columnTypes.Length) || columnNames.Length < 1) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + for (i = 0; i < columnNames.Length; i++) + { + if (string.IsNullOrEmpty(columnNames[i])) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "columnNames index " + i.ToString()); + } + } + + for (i = 0; i < columnTypes.Length; i++) + { + if ( columnTypes[i] < ColumnType.ColumnTypeInt || columnTypes[i] > ColumnType.ColumnTypeBlob) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "columnTypes index" + i.ToString()); + } + } + + _columnNames = columnNames; + _columnTypes = columnTypes; + + _cursorPath = FileManager.OpenFileStream(Thread.CurrentThread.ManagedThreadId); + if (_cursorPath == null) + { + Log.Error(LogTag, "Unable to create a cursor file : " + _cursorPath); + ErrorFactory.ThrowException(ResultType.IoError, true); + } + + _fs = new FileStream(_cursorPath, FileMode.Create); + /* column count */ + byte_tmp = BitConverter.GetBytes(columnNames.Length); + _fs.Write(byte_tmp, 0, byte_tmp.Length); + + /* column type */ + for (i = 0; i < columnTypes.Length; i++) + { + byte_tmp = BitConverter.GetBytes((int)_columnTypes[i]); + _fs.Write(byte_tmp, 0, byte_tmp.Length); + } + + /* column name */ + for (i = 0; i < columnTypes.Length; i++) + { + string_tmp = Encoding.UTF8.GetBytes(columnNames[i]); + byte_tmp = new byte[string_tmp.Length + 1];/*insert null */ + + string_tmp.CopyTo(byte_tmp, 0); + + length_tmp = BitConverter.GetBytes(byte_tmp.Length); + total_len_of_column_names += length_tmp.Length; + + _fs.Write(length_tmp, 0, length_tmp.Length); + _fs.Write(byte_tmp, 0, byte_tmp.Length); + } + + /* total length of column names */ + byte_tmp = BitConverter.GetBytes(total_len_of_column_names); + _fs.Write(byte_tmp, 0, byte_tmp.Length); + + _rowCountPosition = _fs.Position; + /* row count */ + byte_tmp = BitConverter.GetBytes(_rowCount); + _fs.Write(byte_tmp, 0, byte_tmp.Length); + _fs.Flush(); + } + + internal MatrixCursor() + { + _columnNames = new string[0]; + _columnTypes = new ColumnType[0]; + _fs = null; + _cursorPath = null; + } + + /// <summary> + /// Adds a new row to the end with the given column values. + /// </summary> + /// <param name="columnValues">New column values</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public void AddRow(object[] columnValues) + { + int i, size = 0; + byte[] type_array, length_array, value_array = null, string_array, byte_tmp; + + if (columnValues == null || columnValues.Length <= 0 || columnValues.Length != _columnTypes.Length) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false); + } + + using (MemoryStream ms = new MemoryStream()) + { + for (i = 0; i < _columnTypes.Length; i++) + { + type_array = BitConverter.GetBytes((int)_columnTypes[i]); + switch (_columnTypes[i]) + { + case ColumnType.ColumnTypeInt: + if (!(columnValues[i] is Int64) && !(columnValues[i] is Int32)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "Type mismatch :Index " + i.ToString()); + } + + value_array = BitConverter.GetBytes(Convert.ToUInt64(columnValues[i])); + size = value_array.Length; + break; + case ColumnType.ColumnTypeDouble: + if (!(columnValues[i] is Double)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "Type mismatch :Index " + i.ToString()); + } + + value_array = BitConverter.GetBytes(Convert.ToDouble(columnValues[i])); + size = value_array.Length; + break; + case ColumnType.ColumnTypeString: + if (columnValues[i] == null) + { + type_array = BitConverter.GetBytes(ColumnTypeNull); + size = 0; + break; + } + + if (!(columnValues[i] is string)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "Type mismatch :Index " + i.ToString()); + } + + string_array = Encoding.UTF8.GetBytes(Convert.ToString(columnValues[i])); + value_array = new byte[string_array.Length + 1];/*insert null */ + string_array.CopyTo(value_array, 0); + size = value_array.Length; + break; + + case ColumnType.ColumnTypeBlob: + if (columnValues[i] == null) + { + type_array = BitConverter.GetBytes(ColumnTypeNull); + size = 0; + break; + } + + if (!(columnValues[i] is byte[])) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "Type mismatch :Index " + i.ToString()); + } + + value_array = (byte[])columnValues[i]; + size = value_array.Length; + break; + } + + ms.Write(type_array, 0, type_array.Length); + + length_array = BitConverter.GetBytes(size); + ms.Write(length_array, 0, length_array.Length); + if (size > 0) + { + ms.Write(value_array, 0, value_array.Length); + } + } + + /* update row count */ + _rowCount++; + byte_tmp = BitConverter.GetBytes(_rowCount); + _fs.Seek(_rowCountPosition, SeekOrigin.Begin); + _fs.Write(byte_tmp, 0, byte_tmp.Length); + + _fs.Seek(0, SeekOrigin.End); + + _rowFieldOffset.Add(_fs.Position); + ms.WriteTo(_fs);/* row data */ + _fs.Flush(); + + Log.Debug(LogTag, "_fs pos = " + _fs.Position.ToString()); + Log.Debug(LogTag, "_fs len = " + _fs.Length.ToString()); + } + } + + /// <summary> + /// Releases all resources used by the MatrixCursor class. + /// </summary> + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (!string.IsNullOrEmpty(_cursorPath)) + { + FileInfo fi = new FileInfo(_cursorPath); + + if (_fs != null) + { + _fs.Dispose(); + } + + if (fi.Exists) + { + fi.Delete(); + } + } + + _disposed = true; + } + + if (disposing) + { + GC.SuppressFinalize(this); + } + } + + ~MatrixCursor() + { + Dispose(false); + } + } +} diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Provider.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Provider.cs new file mode 100755 index 0000000..b2bc00c --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Provider.cs @@ -0,0 +1,1078 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; +using Tizen.Applications.DataControl; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Tizen.Applications.DataControl +{ + /// <summary> + /// Represents Provider class for DataControl provider application. + /// </summary> + public abstract class Provider : IDisposable + { + private const string LogTag = "Tizen.Applications.DataControl"; + private static IDictionary<string, Provider> _providerDict = new Dictionary<string, Provider>(); + private static Interop.DataControl.SqlRequestCallbacks _sqlRequestCallbacks; + private static Interop.DataControl.MapRequestCallbacks _mapRequestCallbacks; + private IntPtr _nativeHandle; + private static Interop.DataControl.DataChangeConsumerFilterCb _filterCallback; + private static int _filterCallbackID; + private static bool _filterRegistered; + private static Interop.DataControl.SqlBulkInsertRequestCallback _sqlBulkCallback; + private static Interop.DataControl.MapBulkAddRequestCallback _mapBulkCallback; + private static Mutex _lock = new Mutex(); + private bool _disposed = false; + + /// <summary> + /// Gets the data ID + /// </summary> + public string DataID + { + get; + private set; + } + + private static bool DataChangeListenFilter(IntPtr handlePtr, string consumerAppid, IntPtr userData) + { + Provider provider; + DataChangeListenResult result; + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist "); + return false; + } + + result = provider.OnDataChangeListenRequest(consumerAppid); + if (result == null || result.Result != ResultType.Success) + { + return false; + } + else + { + return true; + } + } + + private enum OperationType : short + { + Select, + Update, + Insert, + Delete + } + + private static string CreateSelectQuery(IntPtr handlePtr, string[] columnList, int columnCount, string where, string order, int pageNum, int countPerPage) + { + Interop.DataControl.SafeDataControlHandle handle = new Interop.DataControl.SafeDataControlHandle(handlePtr, false); + string query = "SELECT"; + string dataId; + if (columnList == null) + { + query += " * "; + } + else + { + for (int i = 0; i < columnCount; i++) + { + if (i != 0) + { + query += ","; + } + + query += " " + columnList[i]; + } + } + + Interop.DataControl.DataControlGetDataId(handle, out dataId); + query += " FROM " + dataId; + if (where != null) + { + query += " WHERE " + where; + } + + if (order != null) + { + query += " ORDER BY " + order; + } + + if (pageNum != 0) + { + query += " LIMIT " + countPerPage + " OFFSET " + (countPerPage * (pageNum - 1)); + } + + return query; + } + + private static void InsertRequest(int requestId, IntPtr handlePtr, IntPtr insertData, IntPtr userData) + { + Provider provider; + InsertResult result; + SafeBundleHandle sbh = new SafeBundleHandle(insertData, false); + string query = GetQuery(handlePtr, sbh, null, OperationType.Update); + ResultType ret; + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist "); + return; + } + + result = provider.OnInsert(query, new Bundle(sbh)); + if (result != null) + { + if (result.Result) + { + ret = Interop.DataControl.SendInsertResult(requestId, result.RowID); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendInsertResult fail " + ret.ToString()); + } + } + else + { + ret = Interop.DataControl.SendError(requestId, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + } + else + { + Log.Info(LogTag, $"InsertResult is null : {requestId.ToString()}"); + } + } + + private static void BulkInsertRequest(int requestId, IntPtr handlePtr, IntPtr bulk_data, IntPtr userData) + { + Provider provider; + BulkInsertResult result; + BulkData bulkData = new BulkData(new Interop.DataControl.SafeBulkDataHandle(bulk_data, false)); + Interop.DataControl.SafeBulkDataHandle sbdh = bulkData.SafeBulkDataHandle; + IntPtr bundleHandel; + ResultType ret; + + int count = bulkData.GetCount(); + List<string> queryList = new List<string>(); + + for (int i = 0; i < count; i++) + { + Interop.DataControl.BulkGetData(sbdh, i, out bundleHandel); + queryList.Add(GetQuery(handlePtr, new SafeBundleHandle(bundleHandel, false), null, OperationType.Insert)); + } + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist "); + return; + } + + result = provider.OnBulkInsert(queryList, bulkData); + if (result != null) + { + if (result.Result) + { + ret = Interop.DataControl.SendBulkInsertResult(requestId, result.BulkResultData.SafeBulkDataHandle); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendBulkInsertResult fail " + ret.ToString()); + } + } + else + { + ret = Interop.DataControl.SendError(requestId, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + + if (result.BulkResultData != null) + { + result.BulkResultData.Dispose(); + } + } + else + { + Log.Info(LogTag, $"BulkInsertResult is null : {requestId.ToString()}"); + } + } + + private static void SendNativeProtocol(int socketFd, ICursor cursor, int requestId) + { + uint write_len; + int DATACONTROL_RESULT_NO_DATA = -1; + int COLUMN_TYPE_NULL = 5; + int column_count, i, rowcount, size = 0, total_len_of_column_names = 0; + byte[] type_array, length_array, string_array, int_tmp, value_array = null; + string txt; + ResultType result; + MemoryStream ms; + + if (cursor.Reset() == false) + { + Log.Error(LogTag, "Reset is failed : " + requestId.ToString()); + return; + } + + if (cursor.GetRowCount() <= 0) + { + Log.Error(LogTag, "The DB does not have another row : " + requestId.ToString()); + int_tmp = BitConverter.GetBytes(DATACONTROL_RESULT_NO_DATA); + result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, int_tmp, int_tmp.Length, out write_len); + return; + } + + /* 1. column count */ + column_count = cursor.GetColumnCount(); + int_tmp = BitConverter.GetBytes(column_count); + result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, int_tmp, int_tmp.Length, out write_len); + if (result != ResultType.Success) + { + Log.Error(LogTag, "Writing a column_count to a file descriptor is failed."); + return; + } + + Log.Info(LogTag, "Writing a column_count " + column_count.ToString()); + + /* 2.column type x column_count */ + for (i = 0; i < column_count; i++) + { + type_array = BitConverter.GetBytes((int)cursor.GetColumnType(i)); + result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, type_array, type_array.Length, out write_len); + if (result != ResultType.Success) + { + Log.Error(LogTag, "Writing a type to a file descriptor is failed."); + return; + } + + Log.Info(LogTag, "Writing a column_type " + cursor.GetColumnType(i).ToString()); + } + + /* 3. column name x column_count */ + for (i = 0; i < column_count; i++) + { + Log.Info(LogTag, "Writing a name " + cursor.GetColumnName(i)); + + total_len_of_column_names += cursor.GetColumnName(i).Length; + string_array = Encoding.UTF8.GetBytes(cursor.GetColumnName(i)); + value_array = new byte[string_array.Length + 1];/*insert null */ + string_array.CopyTo(value_array, 0); + length_array = BitConverter.GetBytes(value_array.Length); + + result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, length_array, length_array.Length, out write_len); + if (result != ResultType.Success) + { + Log.Error(LogTag, "Writing a type to a file descriptor is failed."); + return; + } + + result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, value_array, value_array.Length, out write_len); + if (result != ResultType.Success) + { + Log.Error(LogTag, "Writing a type to a file descriptor is failed."); + return; + } + + } + + /* 4. total length of column names */ + length_array = BitConverter.GetBytes(total_len_of_column_names); + result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, length_array, length_array.Length, out write_len); + if (result != ResultType.Success) + { + Log.Error(LogTag, "Writing a total_len_of_column_names to a file descriptor is failed"); + return; + } + + Log.Info(LogTag, "Writing total length of column namese " + total_len_of_column_names.ToString()); + + /* 5. row count */ + length_array = BitConverter.GetBytes(cursor.GetRowCount()); + Log.Error(LogTag, "=========================== select rowcount " + cursor.GetRowCount().ToString()); + result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, length_array, length_array.Length, out write_len); + if (result != ResultType.Success) + { + Log.Error(LogTag, "Writing a row count to a file descriptor is failed"); + return; + } + + Log.Error(LogTag, "Writing a row count " + cursor.GetRowCount().ToString()); + + rowcount = 0; + do + { + ms = new MemoryStream(); + + for (i = 0; i < column_count; i++) + { + type_array = BitConverter.GetBytes((int)cursor.GetColumnType(i)); + switch (cursor.GetColumnType(i)) + { + case ColumnType.ColumnTypeInt: + value_array = BitConverter.GetBytes(cursor.GetInt64Value(i)); + size = value_array.Length; + break; + + case ColumnType.ColumnTypeDouble: + value_array = BitConverter.GetBytes(cursor.GetDoubleValue(i)); + size = value_array.Length; + break; + + case ColumnType.ColumnTypeString: + txt = cursor.GetStringValue(i); + if (txt == null) + { + type_array = BitConverter.GetBytes(COLUMN_TYPE_NULL); + size = 0; + break; + } + + string_array = Encoding.UTF8.GetBytes(txt); + value_array = new byte[string_array.Length + 1];/*insert null */ + string_array.CopyTo(value_array, 0); + size = value_array.Length; + break; + + case ColumnType.ColumnTypeBlob: + int_tmp = cursor.GetBlobValue(i); + if (int_tmp == null) + { + type_array = BitConverter.GetBytes(COLUMN_TYPE_NULL); + size = 0; + break; + } + + value_array = int_tmp; + size = value_array.Length; + break; + } + + ms.Write(type_array, 0, type_array.Length); + + length_array = BitConverter.GetBytes(size); + ms.Write(length_array, 0, length_array.Length); + if (size > 0) + { + ms.Write(value_array, 0, value_array.Length); + } + } + + value_array = ms.ToArray(); + + result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, value_array, value_array.Length, out write_len); + if (result != ResultType.Success) + { + Log.Error(LogTag, "Writing a row to a file descriptor is failed"); + ms.Dispose(); + return; + } + + ms.Dispose(); + Log.Info(LogTag, "row_count ~~~~ ", rowcount.ToString()); + + } + while (cursor.Next()); + } + + private static void SelectRequest(int requestId, + IntPtr handlePtr, IntPtr columnList, int columnCount, string where, string order, IntPtr userData) + { + Provider provider; + SelectResult result; + int pageNum = 0; + int countPerPage = 0; + int MAX_WRITE_SIZE = 1024; /* 1kbyte */ + string query = null; + int socketFd, write_size, i; + uint write_len; + ResultType ret; + string[] _columnList = new string[columnCount]; + byte[] buffer; + + unsafe + { + byte** _sbyte_columnList = (byte**)columnList; + + for (i = 0; i < columnCount; i++) + { + _columnList[i] = Marshal.PtrToStringAnsi((IntPtr)_sbyte_columnList[i]); + } + } + + Interop.DataControl.GetSelectPageInfo(requestId, out pageNum, out countPerPage); + query = CreateSelectQuery(handlePtr, _columnList, _columnList.Length, where, order, pageNum, countPerPage); + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist "); + return; + } + + result = provider.OnSelect(query, where, _columnList, _columnList.Length, order, pageNum, countPerPage); + if (result != null) + { + if (result.Result) + { + Interop.DataControl.SendSelectResult(requestId, out socketFd); + + MatrixCursor mc = result.ResultCursor as MatrixCursor; + + if (mc == null) + { + SendNativeProtocol(socketFd, result.ResultCursor, requestId); + } + else + { + FileStream fs = mc.GetFileStream(); + fs.Seek(0, SeekOrigin.Begin); + + buffer = new byte[MAX_WRITE_SIZE]; + + do + { + write_size = fs.Read(buffer, 0, MAX_WRITE_SIZE); + + if (write_size > 0) + { + ret = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, buffer, write_size, out write_len); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "Writing a row to a file descriptor is failed"); + return; + } + } + } + while (write_size > 0); + } + + mc.Dispose(); + } + else + { + ret = Interop.DataControl.SendError(requestId, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + } + else + { + Log.Info(LogTag, $"SelectResult is null : {requestId.ToString()}"); + } + } + + private static void UpdateRequest(int requestId, + IntPtr handlePtr, IntPtr updateData, string where, IntPtr userData) + { + Provider provider; + UpdateResult result; + SafeBundleHandle sbh = new SafeBundleHandle(updateData, false); + string query = GetQuery(handlePtr, sbh, where, OperationType.Update); + ResultType ret; + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist "); + return; + } + + result = provider.OnUpdate(query, where, new Bundle(sbh)); + if (result != null) + { + if (result.Result) + { + ret = Interop.DataControl.SendUpdateResult(requestId); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendUpdateResult fail " + ret.ToString()); + } + } + else + { + ret = Interop.DataControl.SendError(requestId, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + } + else + { + Log.Info(LogTag, $"UpdateResult is null : {requestId.ToString()}"); + } + } + + private static void DeleteRequest(int requestId, + IntPtr handlePtr, string where, IntPtr userData) + { + Provider provider; + DeleteResult result; + string query = GetQuery(handlePtr, null, where, OperationType.Delete); + ResultType ret; + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist "); + return; + } + + result = provider.OnDelete(query, where); + if (result != null) + { + if (result.Result) + { + ret = Interop.DataControl.SendDeleteResult(requestId); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendDeleteResult fail " + ret.ToString()); + } + + } + else + { + ret = Interop.DataControl.SendError(requestId, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + } + else + { + Log.Info(LogTag, $"DeleteResult is null : {requestId.ToString()}"); + } + } + + private static void MapAddRequest(int requestId, IntPtr handlePtr, string key, string value, IntPtr userData) + { + Provider provider; + MapAddResult result; + ResultType ret; + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist"); + return; + } + + result = provider.OnMapAdd(key, value); + if (result != null) + { + if (result.Result) + { + ret = Interop.DataControl.SendMapResult(requestId); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendMapResult fail " + ret.ToString()); + } + } + else + { + ret = Interop.DataControl.SendError(requestId, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + } + else + { + Log.Info(LogTag, $"MapAddResult is null : {requestId.ToString()}"); + } + } + + private static void MapSetRequest(int requestId, IntPtr handlePtr, string key, string oldValue, string newValue, IntPtr userData) + { + Provider provider; + MapSetResult result; + ResultType ret; + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist"); + return; + } + + result = provider.OnMapSet(key, oldValue, newValue); + if (result != null) + { + if (result.Result) + { + ret = Interop.DataControl.SendMapResult(requestId); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendMapResult fail " + ret.ToString()); + } + } + else + { + ret = Interop.DataControl.SendError(requestId, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + } + else + { + Log.Info(LogTag, $"MapSetResult is null : {requestId.ToString()}"); + } + } + + private static void MapRemoveRequest(int requestId, IntPtr handlePtr, string key, string value, IntPtr userData) + { + Provider provider; + MapRemoveResult result; + ResultType ret; + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist"); + return; + } + + result = provider.OnMapRemove(key, value); + if (result != null) + { + if (result.Result) + { + ret = Interop.DataControl.SendMapResult(requestId); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendMapResult fail " + ret.ToString()); + } + + } + else + { + ret = Interop.DataControl.SendError(requestId, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + } + else + { + Log.Info(LogTag, $"MapRemoveRequest is null : {requestId.ToString()}"); + } + } + + private static void MapGetRequest(int requestID, IntPtr handlePtr, string key, IntPtr userData) + { + Provider provider; + MapGetResult result; + ResultType ret; + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist"); + return; + } + + result = provider.OnMapGet(key); + if (result != null) + { + if (result.Result) + { + int valueCount = 0; + if (result.ValueList != null) + valueCount = result.ValueList.Length; + ret = Interop.DataControl.SendMapGetResult(requestID, result.ValueList, valueCount); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendMapGetResult fail " + ret.ToString()); + } + + } + else + { + ret = Interop.DataControl.SendError(requestID, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + } + else + { + Log.Info(LogTag, $"MapRemoveRequest is null : {requestID.ToString()}"); + } + } + + private static void MapBulkAddRequest(int requestID, IntPtr handlePtr, IntPtr bulkDataPtr, IntPtr userData) + { + Provider provider; + MapBulkAddResult result; + BulkData bulkData = new BulkData(new Interop.DataControl.SafeBulkDataHandle(bulkDataPtr, false)); + Interop.DataControl.SafeBulkDataHandle sbdh = bulkData.SafeBulkDataHandle; + IntPtr bundleHandel; + int count = bulkData.GetCount(); + List<string> queryList = new List<string>(); + ResultType ret; + + for (int i = 0; i < count; i++) + { + Interop.DataControl.BulkGetData(sbdh, i, out bundleHandel); + queryList.Add(GetQuery(handlePtr, new SafeBundleHandle(bundleHandel, false), null, OperationType.Insert)); + } + + provider = GetProvider(handlePtr); + if (provider == null) + { + Log.Error(LogTag, "Provider not exist"); + return; + } + + result = provider.OnMapBulkAdd(bulkData); + if (result != null) + { + if (result.Result) + { + ret = Interop.DataControl.SendMapBulkAddResult(requestID, result.BulkResultData.SafeBulkDataHandle); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendMapBulkAddResult fail " + ret.ToString()); + } + } + else + { + ret = Interop.DataControl.SendError(requestID, result.Result.ToString()); + if (ret != ResultType.Success) + { + Log.Error(LogTag, "SendError fail " + ret.ToString()); + } + } + + if (result.BulkResultData != null) + { + result.BulkResultData.Dispose(); + } + } + else + { + Log.Info(LogTag, $"MapBulkAddRequest is null : {requestID.ToString()}"); + } + } + + private static string GetQuery(IntPtr handlePtr, SafeBundleHandle data, string where, OperationType type) + { + Interop.DataControl.SafeDataControlHandle handle = new Interop.DataControl.SafeDataControlHandle(handlePtr, false); + string query = null; + + switch (type) + { + case OperationType.Select: + break; + case OperationType.Update: + query = Interop.DataControl.CreateUpdateStatement(handle, data, where); + break; + case OperationType.Delete: + query = Interop.DataControl.CreateDeleteStatement(handle, where); + break; + case OperationType.Insert: + query = Interop.DataControl.CreateInsertStatement(handle, data); + break; + default: + break; + } + + return query; + } + + private static Provider GetProvider(IntPtr handlePtr) + { + Interop.DataControl.SafeDataControlHandle handle = new Interop.DataControl.SafeDataControlHandle(handlePtr, false); + Provider provider = null; + string dataID; + + Interop.DataControl.DataControlGetDataId(handle, out dataID); + if (dataID != null && _providerDict.ContainsKey(dataID)) + { + provider = _providerDict[dataID]; + provider._nativeHandle = handlePtr; + } + + return provider; + } + + /// <summary> + /// Sends a data change notification to consumer applications which have successfully added a data change listen. + /// </summary> + /// <param name="type">Changed data type</param> + /// <param name="changedData">Customized information about changed data</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + public void SendDataChange(ChangeType type, Bundle changedData) + { + ResultType ret; + + if (changedData == null | changedData.SafeBundleHandle.IsInvalid) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "changedData"); + } + + if (this._nativeHandle == IntPtr.Zero) + { + return; + } + + ret = Interop.DataControl.SendDataChange(this._nativeHandle, type, changedData.SafeBundleHandle); + if (ret != ResultType.Success) + { + ErrorFactory.ThrowException(ret, false); + } + } + + /// <summary> + /// Initializes Provider class with dataID. + /// </summary> + /// <param name="dataId">DataControl Data ID</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public Provider(string dataID) + { + if (string.IsNullOrEmpty(dataID)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "dataID"); + } + + DataID = dataID; + } + + /// <summary> + /// Starts Provider service. + /// </summary> + /// <remarks>Only one Provider service can be ran for each process</remarks> + /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception> + /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception> + /// <privilege>http://tizen.org/privilege/datasharing</privilege> + public void Run() + { + ResultType ret; + _lock.WaitOne(); + if (_providerDict.ContainsKey(DataID)) + { + _lock.ReleaseMutex(); + return; + } + + if (_providerDict.Count == 0) + { + Log.Debug(LogTag, "Provider create"); + + _sqlRequestCallbacks.Insert = new Interop.DataControl.SqlInsertRequestCallback(InsertRequest); + _sqlRequestCallbacks.Select = new Interop.DataControl.SqlSelectRequestCallback(SelectRequest); + _sqlRequestCallbacks.Update = new Interop.DataControl.SqlUpdateRequestCallback(UpdateRequest); + _sqlRequestCallbacks.Delete = new Interop.DataControl.SqlDeleteRequestCallback(DeleteRequest); + + ret = Interop.DataControl.RegisterSqlRequest(ref _sqlRequestCallbacks, IntPtr.Zero); + if (ret != ResultType.Success) + { + _lock.ReleaseMutex(); + ErrorFactory.ThrowException(ret, false); + } + + _sqlBulkCallback = new Interop.DataControl.SqlBulkInsertRequestCallback(BulkInsertRequest); + ret = Interop.DataControl.RegisterSqlBulkRequest(_sqlBulkCallback, IntPtr.Zero); + if (ret != ResultType.Success) + { + _lock.ReleaseMutex(); + ErrorFactory.ThrowException(ret, false); + } + + _mapRequestCallbacks.Add = new Interop.DataControl.MapAddRequestCallback(MapAddRequest); + _mapRequestCallbacks.Remove = new Interop.DataControl.MapRemoveRequestCallback(MapRemoveRequest); + _mapRequestCallbacks.Set = new Interop.DataControl.MapSetRequestCallback(MapSetRequest); + _mapRequestCallbacks.Get = new Interop.DataControl.MapGetRequestCallback(MapGetRequest); + ret = Interop.DataControl.RegisterMapRequest(ref _mapRequestCallbacks, IntPtr.Zero); + if (ret != ResultType.Success) + { + _lock.ReleaseMutex(); + ErrorFactory.ThrowException(ret, false); + } + + _mapBulkCallback = new Interop.DataControl.MapBulkAddRequestCallback(MapBulkAddRequest); + ret = Interop.DataControl.RegisterMapBulkRequest(_mapBulkCallback, IntPtr.Zero); + if (ret != ResultType.Success) + { + _lock.ReleaseMutex(); + ErrorFactory.ThrowException(ret, false); + } + + if (_filterRegistered == false) + { + if (_filterCallback == null) + _filterCallback = new Interop.DataControl.DataChangeConsumerFilterCb(DataChangeListenFilter); + + ret = Interop.DataControl.AddDataChangeConsumerFilterCallback( + _filterCallback, + IntPtr.Zero, out _filterCallbackID); + + if (ret != ResultType.Success) + { + _lock.ReleaseMutex(); + ErrorFactory.ThrowException(ret, false); + } + } + + _filterRegistered = true; + } + + _providerDict.Add(DataID, this); + _lock.ReleaseMutex(); + } + + /// <summary> + /// Stop Provider service. + /// </summary> + public void Stop() + { + _providerDict.Remove(DataID); + } + + ~Provider() + { + Dispose(false); + } + + /// <summary> + /// Overrides this method if want to handle behavior when the select request is received. + /// </summary> + protected abstract SelectResult OnSelect(string query, string where, string[] columList, int columnCount, string order, int pageNum, int countPerPage); + + /// <summary> + /// Overrides this method if want to handle behavior when the insert request is received. + /// </summary> + protected abstract InsertResult OnInsert(string query, Bundle insertData); + + /// <summary> + /// Overrides this method if want to handle behavior when the update request is received. + /// </summary> + protected abstract UpdateResult OnUpdate(string query, string where, Bundle updateData); + + /// <summary> + /// Overrides this method if want to handle behavior when the delete request is received. + /// </summary> + protected abstract DeleteResult OnDelete(string query, string where); + + /// <summary> + /// Overrides this method if want to handle behavior when the bulk insert request is received. + /// </summary> + protected virtual BulkInsertResult OnBulkInsert(IEnumerable<string> query, BulkData bulkInsertData) + { + Log.Info(LogTag, "The OnBulkInsert is not implemented."); + return null; + } + + /// <summary> + /// Overrides this method if want to handle behavior when the map get request is received. + /// </summary> + protected virtual MapGetResult OnMapGet(string key) + { + Log.Info(LogTag, "The OnMapGet is not implemented."); + return null; + } + + /// <summary> + /// Overrides this method if want to handle behavior when the map add request is received. + /// </summary> + protected virtual MapAddResult OnMapAdd(string key, string value) + { + Log.Info(LogTag, "The OnMapAdd is not implemented."); + return null; + } + + /// <summary> + /// Overrides this method if want to handle behavior when the update request is received. + /// </summary> + protected virtual MapSetResult OnMapSet(string key, string oldValue, string newValue) + { + Log.Info(LogTag, "The OnMapSet is not implemented."); + return null; + } + + /// <summary> + /// Overrides this method if want to handle behavior when the delete request is received. + /// </summary> + protected virtual MapRemoveResult OnMapRemove(string key, string value) + { + Log.Info(LogTag, "The OnMapRemove is not implemented."); + return null; + } + + /// <summary> + /// Overrides this method if want to handle behavior when the bulk add request is received. + /// </summary> + protected virtual MapBulkAddResult OnMapBulkAdd(BulkData bulkAddData) + { + Log.Info(LogTag, "The OnMapBulkAdd is not implemented."); + return null; + } + + /// <summary> + /// Overrides this method if want to handle behavior when the data change listen request is received. + /// </summary> + protected virtual DataChangeListenResult OnDataChangeListenRequest(string requestAppID) + { + Log.Info(LogTag, "The OnDataChangeListenRequest is not implemented."); + return null; + } + + /// <summary> + /// Releases the unmanaged resourced used by the Provider class specifying whether to perform a normal dispose operation. + /// </summary> + /// <param name="disposing">true for a normal dispose operation; false to finalize the handle.</param> + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + Stop(); + _disposed = true; + } + if (disposing) + { + GC.SuppressFinalize(this); + } + } + + /// <summary> + /// Releases all resources used by the Provider class. + /// </summary> + public void Dispose() + { + Dispose(true); + } + } +} diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Results.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Results.cs new file mode 100755 index 0000000..3e7e0d3 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Results.cs @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Applications.DataControl +{ + /// <summary> + /// This class is for containing insert operation result. + /// </summary> + public class InsertResult + { + /// <summary> + /// Gets the insert data's row id. + /// </summary> + public long RowID + { + get; + private set; + } + + /// <summary> + /// Gets the insert operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes InsertResult class with columnNames and columnTypes. + /// </summary> + /// <param name="rowID">Inserted row ID</param> + /// <param name="result">Insert request result</param> + public InsertResult(long rowID, bool result) + { + RowID = rowID; + Result = result; + } + } + + /// <summary> + /// This class is for containing bulk insert operation result. + /// </summary> + public class BulkInsertResult + { + /// <summary> + /// Gets the bulk insert operation result data. + /// </summary> + public BulkResultData BulkResultData + { + get; + private set; + } + + /// <summary> + /// Gets the bulk insert operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes InsertResult class with bulkResultData and result. + /// </summary> + /// <param name="bulkResultData">Bulk insert request result data</param> + /// <param name="result">Bulk insert request result</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public BulkInsertResult(BulkResultData bulkResultData, bool result) + { + if (result == true && (bulkResultData == null || bulkResultData.SafeBulkDataHandle.IsInvalid)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "bulkResultData"); + } + + BulkResultData = bulkResultData; + Result = result; + } + } + + /// <summary> + /// This class is for containing update operation result. + /// </summary> + public class UpdateResult + { + /// <summary> + /// Gets the update operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes UpdateResult class with result. + /// </summary> + /// <param name="result">Update request result</param> + public UpdateResult(bool result) + { + Result = result; + } + } + + /// <summary> + /// This class is for containing delete operation result. + /// </summary> + public class DeleteResult + { + /// <summary> + /// Gets the delete operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes DeleteResult class with result. + /// </summary> + /// <param name="result">Delete request result</param> + public DeleteResult(bool result) + { + Result = result; + } + } + + /// <summary> + /// This class is for containing select operation result. + /// </summary> + public class SelectResult + { + /// <summary> + /// Gets the select operation result cursor. + /// </summary> + public ICursor ResultCursor + { + get; + private set; + } + /// <summary> + /// Gets the select operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes SelectResult class with cursor and result. + /// </summary> + /// <param name="cursor">Cursor with selected data</param> + /// <param name="result">Select request result</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public SelectResult(ICursor cursor, bool result) + { + int i; + + if (result == true && cursor == null) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "cursor"); + } + + if (result == true && (cursor is MatrixCursor) == false) + { + if (cursor.GetColumnCount() <= 0) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "column count"); + } + + for (i = 0; i < cursor.GetColumnCount(); i++) + { + if (string.IsNullOrEmpty(cursor.GetColumnName(i))) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "column name index " + i.ToString()); + } + + if (cursor.GetColumnType(i) < ColumnType.ColumnTypeInt || cursor.GetColumnType(i) > ColumnType.ColumnTypeBlob) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "column type index" + i.ToString()); + } + } + } + + ResultCursor = cursor; + Result = result; + } + } + + /// <summary> + /// This class is for containing MapAdd operation result. + /// </summary> + public class MapAddResult + { + + /// <summary> + /// Gets the MapAdd operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes MapAddResult class with result. + /// </summary> + /// <param name="result">MapAdd request result</param> + public MapAddResult(bool result) + { + Result = result; + } + } + + /// <summary> + /// This class is for containing MapBulkAdd operation result. + /// </summary> + public class MapBulkAddResult + { + /// <summary> + /// Gets the MapBulkAdd operation result data. + /// </summary> + public BulkResultData BulkResultData + { + get; + private set; + } + + /// <summary> + /// Gets the MapBulkAdd operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes MapBulkAddResult class with bulkResultData and result. + /// </summary> + /// <param name="bulkResultData">MapBulkAdd request result data</param> + /// <param name="result">MapBulkAdd request result</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public MapBulkAddResult(BulkResultData bulkResultData, bool result) + { + if (result == true && (bulkResultData == null || bulkResultData.SafeBulkDataHandle.IsInvalid)) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "bulkResultData"); + } + + BulkResultData = bulkResultData; + Result = result; + } + } + + /// <summary> + /// This class is for containing MapSet operation result. + /// </summary> + public class MapSetResult + { + /// <summary> + /// Gets the MapSet operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes MapSetResult class with result. + /// </summary> + /// <param name="result">MapSet request result</param> + public MapSetResult(bool result) + { + Result = result; + } + } + + /// <summary> + /// This class is for containing MapRemove operation result. + /// </summary> + public class MapRemoveResult + { + /// <summary> + /// Gets the MapRemove operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes MapRemoveResult class with result. + /// </summary> + /// <param name="result">MapRemove request result</param> + public MapRemoveResult(bool result) + { + Result = result; + } + } + + /// <summary> + /// This class is for containing MapGet operation result. + /// </summary> + public class MapGetResult + { + /// <summary> + /// Gets the result value list of the MapGet operation. + /// </summary> + public string[] ValueList + { + get; + private set; + } + /// <summary> + /// Gets the MapGet operation result. + /// </summary> + public bool Result + { + get; + private set; + } + + /// <summary> + /// Initializes MapGetResult class with data and result. + /// </summary> + /// <param name="valueLIst">MapGet request result data</param> + /// <param name="result">MapGet request result</param> + /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception> + public MapGetResult(string[] valueLIst, bool result) + { + if (result == true && valueLIst == null) + { + ErrorFactory.ThrowException(ResultType.InvalidParamer, false, "valueLIst"); + } + + ValueList = valueLIst; + Result = result; + } + } + + /// <summary> + /// This class is for containing DataChangeListen operation result. + /// </summary> + public class DataChangeListenResult + { + /// <summary> + /// Gets the DataChangeListen operation result. + /// </summary> + public ResultType Result + { + get; + private set; + } + + /// <summary> + /// Initializes DataChangeListenResult class with result. + /// </summary> + /// <param name="result">DataChangeListen request result</param> + public DataChangeListenResult(ResultType result) + { + Result = result; + } + } +} diff --git a/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Types.cs b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Types.cs new file mode 100755 index 0000000..e18a5b3 --- /dev/null +++ b/Tizen.Applications.DataControl/Tizen.Applications.DataControl/Types.cs @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Applications.DataControl +{ + + /// <summary> + /// Enumeration for DataControl column type + /// </summary> + public enum ColumnType : short + { + /// <summary> + /// Value representing DataControl operation Success + /// </summary> + ColumnTypeInt = 1, + /// <summary> + /// Value representing DataControl operation Success + /// </summary> + ColumnTypeDouble = 2, + /// <summary> + /// Value representing DataControl operation Success + /// </summary> + ColumnTypeString = 3, + /// <summary> + /// Value representing DataControl operation Success + /// </summary> + ColumnTypeBlob = 4 + } + + /// <summary> + /// Enumeration for DataControl column type + /// </summary> + public enum ChangeType : short + { + /// <summary> + /// Value representing DataControl provider data changed by update + /// </summary> + Update, + /// <summary> + /// Value representing DataControl provider data changed by insert + /// </summary> + Insert, + /// <summary> + /// Value representing DataControl provider data changed by delete + /// </summary> + Delete, + /// <summary> + /// Value representing DataControl provider data changed by map add + /// </summary> + MapAdd, + /// <summary> + /// Value representing DataControl provider data changed by map remove + /// </summary> + MapRemove, + /// <summary> + /// Value representing DataControl provider data changed by map set + /// </summary> + MapSet, + } + + /// <summary> + /// Enumeration for DataControl result type + /// </summary> + public enum ResultType : int + { + /// <summary> + /// Value representing DataControl operation success + /// </summary> + Success = Interop.DataControl.NativeResultType.Success, + /// <summary> + /// Value representing DataControl operation cause out of memory error + /// </summary> + OutOfMemory = Interop.DataControl.NativeResultType.OutOfMemory, + /// <summary> + /// Value representing DataControl operation cause IO error + /// </summary> + IoError = Interop.DataControl.NativeResultType.IoError, + /// <summary> + /// Value representing DataControl operation cause Invalid parameter error + /// </summary> + InvalidParamer = Interop.DataControl.NativeResultType.InvalidParamer, + /// <summary> + /// Value representing DataControl operation cause permission denied error + /// </summary> + PermissionDenied = Interop.DataControl.NativeResultType.PermissionDenied, + /// <summary> + /// Value representing DataControl operation cause max exceed error + /// </summary> + MaxExceed = Interop.DataControl.NativeResultType.MaxExceed, + } +} diff --git a/packaging/csapi-data-control.manifest b/packaging/csapi-data-control.manifest new file mode 100755 index 0000000..75b0fa5 --- /dev/null +++ b/packaging/csapi-data-control.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_"/> + </request> +</manifest> diff --git a/packaging/csapi-data-control.spec b/packaging/csapi-data-control.spec new file mode 100755 index 0000000..4843cc3 --- /dev/null +++ b/packaging/csapi-data-control.spec @@ -0,0 +1,45 @@ +Name: csapi-data-control +Summary: Tizen data-control API for C# +Version: 1.0.0 +Release: 1 +Group: Development/Libraries +License: Apache-2.0 +URL: https://www.tizen.org +Source0: %{name}-%{version}.tar.gz +Source1: %{name}.manifest + +AutoReqProv: no +ExcludeArch: aarch64 %ix86 + +BuildRequires: dotnet-build-tools + +# C# API Requires +BuildRequires: csapi-tizen-nuget +BuildRequires: csapi-application-nuget + +%define Assemblies Tizen.Applications.DataControl + +%description +%{summary} + +%dotnet_import_sub_packages + +%prep +%setup -q +cp %{SOURCE1} . + +%build +for ASM in %{Assemblies}; do +%dotnet_build $ASM +%dotnet_pack $ASM/$ASM.nuspec %{version} +done + +%install +for ASM in %{Assemblies}; do +%dotnet_install $ASM +done + +%files +%manifest %{name}.manifest +%license LICENSE +%attr(644,root,root) %{dotnet_assembly_files} |