From 4b63cfc07f4e5b9cbc5876d756263ecd7375720c Mon Sep 17 00:00:00 2001 From: Haejun Lee Date: Wed, 6 Jul 2016 20:37:27 +0900 Subject: [PATCH] initial commit of smart reply API library Change-Id: I51dc7f75377e9a996968ec75d77a980753f810ca --- CMakeLists.txt | 76 +++ LICENSE | 204 ++++++++ doc/smartreply_doc.h | 45 ++ include/analyzer_iface.h | 45 ++ include/analyzer_mgr.h | 41 ++ include/analyzer_mgr_iface.h | 39 ++ include/db_listener_iface.h | 56 +++ include/db_mgr.h | 79 +++ include/db_mgr_iface.h | 42 ++ include/dbus_listener_iface.h | 41 ++ include/dbus_server.h | 47 ++ include/dbus_server_iface.h | 40 ++ include/event.h | 54 ++ include/json.h | 137 +++++ include/request_handler.h | 48 ++ include/response_handler.h | 26 + include/scope_mutex.h | 37 ++ include/smartreply_service.h | 204 ++++++++ include/smartreply_util.h | 102 ++++ include/types_internal.h | 132 +++++ packaging/smartreply.manifest | 5 + packaging/smartreply.spec | 90 ++++ smartreply.pc.in | 13 + src/db_mgr.cpp | 58 +++ src/dbus_client.cpp | 308 ++++++++++++ src/dbus_client.h | 41 ++ src/dbus_server.cpp | 39 ++ src/event.cpp | 119 +++++ src/json.cpp | 909 ++++++++++++++++++++++++++++++++++ src/request_handler.cpp | 269 ++++++++++ src/scope_mutex.cpp | 27 + src/smartreply_service.cpp | 342 +++++++++++++ src/starter.cpp | 29 ++ 33 files changed, 3744 insertions(+) create mode 100755 CMakeLists.txt create mode 100755 LICENSE create mode 100644 doc/smartreply_doc.h create mode 100755 include/analyzer_iface.h create mode 100755 include/analyzer_mgr.h create mode 100755 include/analyzer_mgr_iface.h create mode 100755 include/db_listener_iface.h create mode 100755 include/db_mgr.h create mode 100755 include/db_mgr_iface.h create mode 100755 include/dbus_listener_iface.h create mode 100755 include/dbus_server.h create mode 100755 include/dbus_server_iface.h create mode 100755 include/event.h create mode 100755 include/json.h create mode 100755 include/request_handler.h create mode 100755 include/response_handler.h create mode 100755 include/scope_mutex.h create mode 100755 include/smartreply_service.h create mode 100755 include/smartreply_util.h create mode 100755 include/types_internal.h create mode 100755 packaging/smartreply.manifest create mode 100755 packaging/smartreply.spec create mode 100755 smartreply.pc.in create mode 100755 src/db_mgr.cpp create mode 100755 src/dbus_client.cpp create mode 100755 src/dbus_client.h create mode 100755 src/dbus_server.cpp create mode 100755 src/event.cpp create mode 100755 src/json.cpp create mode 100755 src/request_handler.cpp create mode 100755 src/scope_mutex.cpp create mode 100755 src/smartreply_service.cpp create mode 100755 src/starter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..2be5678 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,76 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(smartreply) + +SET(target "smartreply") +SET(DEST_INCLUDE_DIR "include/smartreply") +SET(SRC_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include") + +FILE(GLOB_RECURSE SRCS src/*.cpp) +MESSAGE("Sources: ${SRCS}") + +SET(VERSION_MAJOR 1) +SET(VERSION "${VERSION_MAJOR}.0.0") + +SET(CMAKE_INSTALL_PREFIX /usr) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +# dependency +SET(DEPS "aul dlog glib-2.0 json-glib-1.0 gio-2.0 bundle pkgmgr-info") + +INCLUDE(FindPkgConfig) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/include + /usr/include + /usr/include/glib-2.0 + /usr/lib/glib-2.0/include + /usr/include/dlog + /usr/include/json-glib-1.0 +) + +ADD_DEFINITIONS(-O2 -Wall -std=c++0x -fPIC -fvisibility=default -Wl,--as-needed -Wl,--rpath=/usr/lib) + +#Building Library +pkg_check_modules(api_pkg REQUIRED ${DEPS}) + +FOREACH(flag ${api_pkg_CFLAGS}) + SET(API_EXTRA_CFLAGS "${API_EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${API_EXTRA_CFLAGS} -fPIC -Wall -Werror") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") +#SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") + + +ADD_LIBRARY(${target} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target} ${api_pkg_LDFLAGS}) +#SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_FLAGS ${API_EXTRA_CFLAGS}) +SET_TARGET_PROPERTIES(${target} PROPERTIES COMPILE_DEFINITIONS "LOG_TAG=\"SMARTREPLY-API\"") +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${VERSION}) + +# Installing +INSTALL(TARGETS ${target} DESTINATION lib) + +# Install header file +FILE(GLOB HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/*.h) +INSTALL(FILES ${HEADER_FILES} DESTINATION ${DEST_INCLUDE_DIR}) +#INSTALL( +# DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include DESTINATION include/smartreply +# FILES_MATCHING PATTERN "*.h" +#) +SET(PC_NAME ${PROJECT_NAME}) +SET(PC_INCLUDE "/usr/include/smartreply") +SET(PC_DESCRIPTION "Tizen SmartReply Framework Native API") +SET(PC_REQUIRED ${DEPS}) +SET(PC_LDFLAGS -l${target}) +SET(PC_CFLAGS -I\${includedir}/smartreply) + +CONFIGURE_FILE( + ${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc + @ONLY +) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) + +#test case +#ADD_SUBDIRECTORY(test) diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..1da314d --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + + 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 (c) 2014 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. + diff --git a/doc/smartreply_doc.h b/doc/smartreply_doc.h new file mode 100644 index 0000000..66ac76b --- /dev/null +++ b/doc/smartreply_doc.h @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of + * SAMSUNG ELECTRONICS ("Confidential Information"). + * You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement + * you entered into with SAMSUNG ELECTRONICS. + * SAMSUNG make no representations or warranties about the suitability + * of the software, either express or implied, including but not + * limited to the implied warranties of merchantability, fitness for + * a particular purpose, or non-infringement. + * SAMSUNG shall not be liable for any damages suffered by licensee as + * a result of using, modifying or distributing this software or its derivatives. + */ + +#ifndef __SMARTREPLY_DOC_H__ +#define __SMARTREPLY_DOC_H__ + +/** +* @ingroup CAPI_SMARTREPLY_SERVICE_MODULE +* @defgroup CAPI_SMARTREPLY_SERVICE SmartReply Service +* @brief The Smart Reply APIs provides functions to generate reply candidates for received message. +* +* @section CAPI_SMARTREPLY_SERVICE_HEADER Required Header +* \#include +* +* @section CAPI_SMARTREPLY_SERVICE_OVERVIEW Overview +* The Smat Reply APIs provides functions to generate reply candidates for received message.\n +* This provides following functionalities.\n +* - Get candidate reply messages for a given received message sync/asynchronously +* - Access & destory candidate reply list +* - Record user's replied message to update future candidate messages +* - Preload engine to reduce message generation time +* +* @section CAPI_SMARTREPLY_SERVICE Related Features +* This API is related with the following features:\n +* - http://developer.samsung.com/tizen/feature/samsung_extension\n +* +*/ + +#endif /* __SMARTREPLY_DOC_H__ */ + diff --git a/include/analyzer_iface.h b/include/analyzer_iface.h new file mode 100755 index 0000000..68da144 --- /dev/null +++ b/include/analyzer_iface.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_ANALYZER_INTERFACE_H__ +#define __SMARTREPLY_ANALYZER_INTERFACE_H__ + +namespace smr { + + /* Forward Declaration */ + class json; + + class analyzer_iface { + public: + virtual ~analyzer_iface() {} + + virtual bool init() = 0; + + virtual bool is_supported(const char* subject) = 0; + + virtual int subscribe(const char* subject, smr::json option, smr::json* request_result) = 0; + + virtual int unsubscribe(const char* subject, smr::json option) = 0; + + virtual int read(const char* subject, smr::json option, smr::json* request_result) = 0; + + virtual int write(const char* subject, smr::json data, smr::json* request_result) = 0; + + }; /* class analyzer_iface */ + +} /* namespace smr */ + +#endif /* End of __SMARTREPLY_ANALYZER_INTERFACE_H__ */ diff --git a/include/analyzer_mgr.h b/include/analyzer_mgr.h new file mode 100755 index 0000000..757ca30 --- /dev/null +++ b/include/analyzer_mgr.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_ANALYZER_MANAGER_H__ +#define __SMARTREPLY_ANALYZER_MANAGER_H__ + +namespace smr { + /* Forward Declaration */ + class json; + class analyzer_iface; + + namespace analyzer_manager { + /* + */ + bool register_subject(const char* subject, smr::analyzer_iface* ca); + + /* + */ + bool publish(const char* subject, smr::json option, int error, smr::json data_updated); + + /* + */ + bool reply_to_read(const char* subject, smr::json option, int error, smr::json data_read); + + } /* namespace smr::analyzer_manager */ +} /* namespace smr */ + +#endif /* End of __SMARTREPLY_ANALYZER_MANAGER_H__ */ diff --git a/include/analyzer_mgr_iface.h b/include/analyzer_mgr_iface.h new file mode 100755 index 0000000..1a6c785 --- /dev/null +++ b/include/analyzer_mgr_iface.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_ANALYZER_MANAGER_INTERFACE_H__ +#define __SMARTREPLY_ANALYZER_MANAGER_INTERFACE_H__ + +namespace smr { + /* Forward Declaration */ + class json; + class analyzer_iface; + + class analyzer_manager_iface { + public: + virtual ~analyzer_manager_iface() {} + // virtual bool register_subject(const char* subject, smr::analyzer_iface* ca) = 0; + // virtual bool publish(const char* subject, smr::json& option, int error, smr::json& data_updated) = 0; + // virtual bool reply_to_read(const char* subject, smr::json& option, int error, smr::json& data_read) = 0; + }; /* class analyzer_manager_iface */ + + namespace analyzer_manager { + void set_instance(analyzer_manager_iface* mgr); + } /* namespace smr::analyzer_manager */ + +} /* namespace smr */ + +#endif /* End of __SMARTREPLY_ANALYZER_MANAGER_INTERFACE_H__ */ diff --git a/include/db_listener_iface.h b/include/db_listener_iface.h new file mode 100755 index 0000000..37e21b8 --- /dev/null +++ b/include/db_listener_iface.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_DATABASE_LISTENER_INTERFACE_H__ +#define __SMARTREPLY_DATABASE_LISTENER_INTERFACE_H__ + +#include + +namespace smr { + /* Forward Declaration */ + class json; + + class db_listener_iface { + public: + virtual ~db_listener_iface() {} + + /** + * @brief Called when a table creation is done. + * @param[in] query_id The query id passed through smr::db_manager::create_table(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + */ + virtual void on_creation_result_received(unsigned int query_id, int error) = 0; + + /** + * @brief Called when a record insertion is done. + * @param[in] query_id The query id passed through smr::db_manager::insert(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + * @param[in] row_id The row id of the inserted record. + */ + virtual void on_insertion_result_received(unsigned int query_id, int error, int64_t row_id) = 0; + + /** + * @brief Called when a query execution is done. + * @param[in] query_id The query id passed through smr::db_manager::execute(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + * @param[in] records Data records retreived. + */ + virtual void on_query_result_received(unsigned int query_id, int error, std::vector& records) = 0; + }; + +} /* namespace smr */ + +#endif /* End of __SMARTREPLY_DATABASE_LISTENER_INTERFACE_H__ */ diff --git a/include/db_mgr.h b/include/db_mgr.h new file mode 100755 index 0000000..0749ea7 --- /dev/null +++ b/include/db_mgr.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_DB_MANAGER_H__ +#define __SMARTREPLY_DB_MANAGER_H__ + +#include +#include +#include + +namespace smr { + /* Forward Declaration */ + class json; + class db_listener_iface; + + namespace db_manager { + /** + * @brief Create a table if not exists. Async. + * @details The column @c row_id is created by default, thus do not use the same column name. + * It is the primary of the auto-increment integer type. + * @param[in] query_id This number will be returned through db_listener_iface::on_creation_result_received(). + * @param[in] table_name A table name to be created. + * @param[in] columns Columns. In SQL format. INTEGER, REAL, and TEXT types are allowed. + * @param[in] option Additional options. Allows NULL. + * @param[in] listener A listner object to receive the result. Allows NULL. + */ + bool create_table(unsigned int query_id, const char* table_name, const char* columns, const char* option = NULL, db_listener_iface* listener = NULL); + + /** + * @brief Insert a record to a table. Async. + * @param[in] query_id This number will be returned through db_listener_iface::on_insertion_result_received(). + * @param[in] table_name A table name in which the record is inserted. + * @param[in] record A json object containing key, value pairs. + * @param[in] listener A listner object to receive the result. Allows NULL. + */ + bool insert(unsigned int query_id, const char* table_name, json& record, db_listener_iface* listener = NULL); + + /** + * @brief Execute a SQL query. Async. + * @param[in] query_id This number will be returned through db_listener_iface::on_query_result_received(). + * @param[in] query A query to be executed. + * @param[in] listener A listner object to receive the result. + */ + bool execute(unsigned int query_id, const char* query, db_listener_iface* listener); + + /** + * @brief Insert a record to a table. Sync. + * @attention This cannot be used in the main thread. + * @param[in] table_name A table name in which the record is inserted. + * @param[in] record A json object containing key, value pairs. + * @param[out] row_id The row id of the inserted record. If fails, a negative integer. + */ + bool insert_sync(const char* table_name, json& record, int64_t* row_id); + + /** + * @brief Execute a SQL query. Sync. + * @attention This cannot be used in the main thread. + * @param[in] query A query to be executed. + * @param[out] records Query result. + */ + bool execute_sync(const char* query, std::vector* records); + + } /* namespace smr::db_manager */ +} /* namespace smr */ + +#endif /* __SMARTREPLY_DB_MANAGER_H__ */ diff --git a/include/db_mgr_iface.h b/include/db_mgr_iface.h new file mode 100755 index 0000000..e5c6c3e --- /dev/null +++ b/include/db_mgr_iface.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_DB_MANAGER_INTERFACE_H__ +#define __SMARTREPLY_DB_MANAGER_INTERFACE_H__ + +#include + +namespace smr { + /* Forward Declaration */ + class json; + class db_listener_iface; + + class db_manager_iface { + public: + virtual ~db_manager_iface() {} + virtual bool create_table(unsigned int query_id, const char* table_name, const char* columns, const char* option = NULL, db_listener_iface* listener = NULL) = 0; + virtual bool insert(unsigned int query_id, const char* table_name, json& record, db_listener_iface* listener = NULL) = 0; + virtual bool execute(unsigned int query_id, const char* query, db_listener_iface* listener) = 0; + virtual bool insert_sync(const char* table_name, json& record, int64_t* row_id) = 0; + virtual bool execute_sync(const char* query, std::vector* records) = 0; + }; /* class db_manager */ + + namespace db_manager { + void set_instance(db_manager_iface* mgr); + } /* namespace smr::db_manager */ +} /* namespace smr */ + +#endif /* __SMARTREPLY_DB_MANAGER_INTERFACE_H__ */ diff --git a/include/dbus_listener_iface.h b/include/dbus_listener_iface.h new file mode 100755 index 0000000..461a222 --- /dev/null +++ b/include/dbus_listener_iface.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_DBUS_LISTENER_INTERFACE_H__ +#define __SMARTREPLY_DBUS_LISTENER_INTERFACE_H__ + +#include + +namespace smr { + + class dbus_listener_iface { + public: + virtual ~dbus_listener_iface() {} + + /** + * @brief Called when receiving a signal. + * @param[in] sender The unique bus name of the sender of the signal. + * @param[in] path The object path that the signal was emitted on. + * @param[in] iface The name of the interface. + * @param[in] name The name of the signal. + * @param[in] param A GVariant tuple with parameters of the signal. + */ + virtual void on_signal_received(const char* sender, const char* path, const char* iface, const char* name, GVariant* param) = 0; + }; + +} /* namespace smr */ + +#endif /* End of __SMARTREPLY_DBUS_LISTENER_INTERFACE_H__ */ diff --git a/include/dbus_server.h b/include/dbus_server.h new file mode 100755 index 0000000..6d03024 --- /dev/null +++ b/include/dbus_server.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_DBUS_SERVER_H__ +#define __SMARTREPLY_DBUS_SERVER_H__ + +#include + +namespace smr { + /* Forward Declaration */ + class dbus_listener_iface; + + namespace dbus_server { + /** + * @brief Subscribes to signals. + * @param[in] sender Sensor name to match on. NULL to listen from all senders. + * @param[in] path Object path to match on. NULL to match on all object paths. + * @param[in] iface D-Bus interface name to match on. NULL to match on all interfaces. + * @param[in] name D-Bus signal name to match on. NULL to match on all signals. + * @param[in] listener Listener object to receive matching signals. + * @return A subscription identifier that can be used with signal_unsubscribe().@n + * If failed, a negative value. + */ + int64_t signal_subscribe(const char* sender, const char* path, const char* iface, const char* name, dbus_listener_iface* listener); + + /** + * @brief Unsubscribes from signals. + */ + void signal_unsubscribe(int64_t subscription_id); + + } /* namespace smr::dbus_server */ +} /* namespace smr */ + +#endif /* End of __SMARTREPLY_DBUS_SERVER_H__ */ diff --git a/include/dbus_server_iface.h b/include/dbus_server_iface.h new file mode 100755 index 0000000..e1e2779 --- /dev/null +++ b/include/dbus_server_iface.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_DBUS_SERVER_INTERFACE_H__ +#define __SMARTREPLY_DBUS_SERVER_INTERFACE_H__ + +#include + +namespace smr { + /* Forward Declaration */ + class dbus_listener_iface; + + class dbus_server_iface { + public: + virtual ~dbus_server_iface() {} + virtual int64_t signal_subscribe(const char* sender, const char* path, const char* iface, const char* name, dbus_listener_iface* listener) = 0; + virtual void signal_unsubscribe(int64_t subscription_id) = 0; + }; /* class smr::dbus_server */ + + namespace dbus_server { + void set_instance(dbus_server_iface* svr); + } + +} /* namespace smr */ + +#endif /* End of __SMARTREPLY_DBUS_SERVER_INTERFACE_H__ */ + diff --git a/include/event.h b/include/event.h new file mode 100755 index 0000000..698f17b --- /dev/null +++ b/include/event.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef _EVENT_DRIVEN_THREAD_H_ +#define _EVENT_DRIVEN_THREAD_H_ + +#include + +class event_driven_thread { + private: + struct event_message_s { + bool is_stop_signal; + int type; + void* data; + event_message_s() : is_stop_signal(false), type(-1), data(NULL) {} + }; + + struct { + GThread *thread; + gint is_running; + GAsyncQueue *event_queue; + } thread_info; + + static gpointer thread_func_wrapper(gpointer func); + void process_event_queue(); + virtual void on_thread_event_popped(int type, void* data) = 0; + virtual void delete_thread_event(int type, void* data) = 0; + + protected: + event_driven_thread(); + bool push_thread_event(int type, void* data = NULL); + + public: + virtual ~event_driven_thread(); + bool start(); + bool stop(); + bool is_running(); + +}; /* class event_driven_thread */ + +#endif /* _EVENT_DRIVEN_THREAD_H_ */ diff --git a/include/json.h b/include/json.h new file mode 100755 index 0000000..29c444b --- /dev/null +++ b/include/json.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_JSON_H__ +#define __SMARTREPLY_JSON_H__ + +#include +#include +#include +#include +#include + +#define _J(cmt, jobj) \ +do { \ + _SD("%s: %s", (cmt), jobj.str().c_str()); \ +} while(0) + +#define EMPTY_JSON_OBJECT "{}" +#define DEFAULT_PRECISION 3 +#define COMMON_ATTR_CLIENT_APP_ID "_ClientAppId_" + +namespace smr { + + class json { + private: + typedef struct _JsonNode json_node_t; + json_node_t * json_node; + + void parse(const char* s); + void release(); + + /* For json vs json comparison */ + bool get_member_list(json_node_t* node, std::list& list); + bool node_equals(json_node_t* lhs, json_node_t* rhs); + bool value_equals(json_node_t* lhs, json_node_t* rhs); + bool object_equals(json_node_t* lhs, json_node_t* rhs); + bool array_equals(json_node_t* lhs, json_node_t* rhs); + + public: + json(); + json(const char* s); + json(const std::string& s); + + /* This json(const json& j) only copies the reference to the underlying json node. + * Therefore, changes applied to a json object affect the other. + * If you need to create a 'real' copy of a json, which can be manipulated separately, + * utilize the str() function, e.g., smr::json copy(original.str()); + */ + json(const json& j); + + //TODO: Constructor accepting a file descriptor? + + ~json(); + + json& operator=(const char* s); + json& operator=(const std::string& s); + + /* This operator=(const json& j) only copies the reference to the underlying json node. + * Therefore, changes applied to a json object affect the other. + * If you need to create a 'real' copy of a json, which can be manipulated separately, + * utilize the str() function, e.g., smr::json copy = original.str(); + */ + json& operator=(const json& j); + + bool operator==(const json& rhs); + bool operator!=(const json& rhs); + + char* dup_cstr(); + std::string str(); + + bool get_keys(std::list* list); + + bool set(const char* path, const char* key, json& val); + bool set(const char* path, const char* key, int val); + bool set(const char* path, const char* key, int64_t val); + bool set(const char* path, const char* key, double val, int prec = DEFAULT_PRECISION); + bool set(const char* path, const char* key, std::string val); + + bool get(const char* path, const char* key, json* val); + bool get(const char* path, const char* key, int* val); + bool get(const char* path, const char* key, int64_t* val); + bool get(const char* path, const char* key, double* val); + bool get(const char* path, const char* key, std::string* val); + + int array_get_size(const char* path, const char* key); + + bool array_append(const char* path, const char* key, json& val); + bool array_append(const char* path, const char* key, int val); + bool array_append(const char* path, const char* key, int64_t val); + bool array_append(const char* path, const char* key, double val, int prec = DEFAULT_PRECISION); + bool array_append(const char* path, const char* key, std::string val); + + bool array_set_at(const char* path, const char* key, int index, json& val); + bool array_set_at(const char* path, const char* key, int index, int val); + bool array_set_at(const char* path, const char* key, int index, int64_t val); + bool array_set_at(const char* path, const char* key, int index, double val, int prec = DEFAULT_PRECISION); + bool array_set_at(const char* path, const char* key, int index, std::string val); + + bool get_array_elem(const char* path, const char* key, int index, json* val); + bool get_array_elem(const char* path, const char* key, int index, int* val); + bool get_array_elem(const char* path, const char* key, int index, int64_t* val); + bool get_array_elem(const char* path, const char* key, int index, double* val); + bool get_array_elem(const char* path, const char* key, int index, std::string* val); + +#if 0 +//TODO: Implement below helper functions if necessary + bool set_array(const char* path, const char* key, json val[], int size); + bool set_array(const char* path, const char* key, int val[], int size); + bool set_array(const char* path, const char* key, int64_t val[], int size); + bool set_array(const char* path, const char* key, double val[], int size); + bool set_array(const char* path, const char* key, std::string val[], int size); + + bool get_array(const char* path, const char* key, json** val, int* size); + bool get_array(const char* path, const char* key, int** val, int* size); + bool get_array(const char* path, const char* key, int64_t** val, int* size); + bool get_array(const char* path, const char* key, double** val, int* size); + bool get_array(const char* path, const char* key, std::string** val, int* size); +#endif + }; + +} /* namespace smr */ + +#endif // __SMARTREPLY_JSON_H__ + diff --git a/include/request_handler.h b/include/request_handler.h new file mode 100755 index 0000000..f84a8c2 --- /dev/null +++ b/include/request_handler.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_LIB_REQUEST_HANDLER_H__ +#define __SMARTREPLY_LIB_REQUEST_HANDLER_H__ +#include +#include "json.h" + +namespace smr { namespace request_handler { + + typedef void (* subject_response_cb)(const char* subject, int req_id, int error, smr::json response); + + int add_engine(const char* language, int* req_id, std::string* request_result); + + int remove_engine(const char* language, int* req_id); + + typedef void (* get_reply_response_cb)(int req_id, int error, void* ext, smr::json& response); + int get_reply_async(const char* input, const char* sender, int* req_id, void* ext, get_reply_response_cb cb); + + int get_reply(const char* input, const char* sender, int* req_id, smr::json* request_result); + + int send_feedback(const char* app_id, const char* sender, const char* req_message, + const char* replied_str, int* req_id); + + int is_supported(const char* language, int* req_id); + + int is_loaded(const char* language, int* req_id); + + int user_feedback(int* req_id); + + int send_prepare_engine(); + +} } /* namespace smr::request_handler */ + +#endif // __SMARTREPLY_LIB_REQUEST_HANDLER_H__ diff --git a/include/response_handler.h b/include/response_handler.h new file mode 100755 index 0000000..89c9657 --- /dev/null +++ b/include/response_handler.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_LIB_RESPONSE_HANDLER_H__ +#define __SMARTREPLY_LIB_RESPONSE_HANDLER_H__ + +namespace smr { namespace response_handler { + + void deliver(const char* subject, int req_id, int error, const char* data); + +} } /* namespace smr::response_handler */ + +#endif // __SMARTREPLY_LIB_RESPONSE_HANDLER_H__ diff --git a/include/scope_mutex.h b/include/scope_mutex.h new file mode 100755 index 0000000..02d6225 --- /dev/null +++ b/include/scope_mutex.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_SCOPE_MUTEX_H__ +#define __SMARTREPLY_SCOPE_MUTEX_H__ + +#include +#include + +namespace smr { + // RAII Class implementing the mutex helper on the base of GLib mutex, + // which automatically locks mutex during its creation and unlocks while exiting the scope. + class scope_mutex + { + private: + GMutex *mutex; + + public: + scope_mutex(GMutex *m); + ~scope_mutex(); + }; +} /* namespace smr */ + +#endif // __SMARTREPLY_SCOPE_MUTEX_H__ diff --git a/include/smartreply_service.h b/include/smartreply_service.h new file mode 100755 index 0000000..3956ecc --- /dev/null +++ b/include/smartreply_service.h @@ -0,0 +1,204 @@ +/* + * Copyright 2000-2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * PROPRIETARY/CONFIDENTIAL + * + * This software is the confidential and proprietary information of + * SAMSUNG ELECTRONICS ("Confidential Information"). + * You shall not disclose such Confidential Information and shall + * use it only in accordance with the terms of the license agreement + * you entered into with SAMSUNG ELECTRONICS. + * SAMSUNG make no representations or warranties about the suitability + * of the software, either express or implied, including but not + * limited to the implied warranties of merchantability, fitness for + * a particular purpose, or non-infringement. + * SAMSUNG shall not be liable for any damages suffered by licensee as + * a result of using, modifying or distributing this software or its derivatives. + */ + + +#ifndef __SMARTREPLY_SERVICE_H__ +#define __SMARTREPLY_SERVICE_H__ + +#include + +/** + * + * @file smartreply_service.h + * @brief This file contains the top level functions of SmartReply API. + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +///////////////////////////////////////////////////////////////////////////////////////////////// +// +// SmartReply Service + +/** + * @ingroup CAPI_SMARTREPLY_SERVICE_MODULE + * @defgroup CAPI_SMARTREPLY_SERVICE SmartReply Service + * + * @addtogroup CAPI_SMARTREPLY_SERVICE + * @{ + * + */ + +/** + * @brief Enumeration of error codes for the SmartReply service + * @since_tizen 2.3.1 + */ +typedef enum _smartreply_service_e { + SMARTREPLY_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + SMARTREPLY_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission Denied */ + SMARTREPLY_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + SMARTREPLY_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + SMARTREPLY_ERROR_CONNECTION_TIME_OUT = TIZEN_ERROR_CONNECTION_TIME_OUT, /**< Timeout error, no answer */ + SMARTREPLY_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Operation is not valid */ + SMARTREPLY_ERROR_UNKNOWN = TIZEN_ERROR_UNKNOWN, /**< Unknown error */ + SMARTREPLY_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< Requested data does not exist */ + SMARTREPLY_ERROR_NOT_SUPPORTED_LANGUAGE = 2001, /**< Not supported language */ + SMARTREPLY_ERROR_OPERATION_FAILED = 2002, /**< Operation failed */ +} smartreply_service_e; + + +typedef struct smartreply_reply_s* smartreply_reply_h; + +/** + * @brief Checks whether engine supports the specified language + * @since_tizen 2.3.1 + * @param[in] language Language code like 'en_US', 'ko_KR' + * @param[out] is_enable True, if engine supports the language. False, otherwise + * @return 0 on success, otherwise a negative error value + * @retval SMARTREPLY_ERROR_NONE Successful + */ +int smartreply_service_is_language_supported(const char* language, bool* is_enable); + +/** + * @brief Requests Smart Replies to Engine + * @since_tizen 2.3.1 + * @param[in] app_id Unique id of application + * @param[in] sender Sender information (phone number) + * @param[in] message Received message from sender + * @param[out] candidate_list Candidate answer list + * @param[out] count The total number of the replies. + * @return 0 on success, otherwise a negative error value + * @retval SMARTREPLY_ERROR_NONE Successful + * @retval SMARTREPLY_ERROR_NOT_SUPPORTED Specified language is not supported + * @retval SMARTREPLY_ERROR_OPERATION_FAILED Operation failed because of a system error + * @retval SMARTREPLY_ERROR_OUT_OF_MEMORY Out of memory + * @see smartreply_service_get_nth_reply_message() + * @see smartreply_service_destory_list() + */ +int smartreply_service_get_replies(const char* app_id, const char* sender, + const char* message, smartreply_reply_h** candidate_list, int* count); + +/** + * @brief Callback function to get Smart Replies from Engine + * @since_tizen 2.3.1 + * @param[in] request_id Request ID returned by smartreply_service_get_replies_async() + * @param[in] error error code + * SMARTREPLY_ERROR_NONE Successful + * SMARTREPLY_ERROR_NOT_SUPPORTED Specified language is not supported + * SMARTREPLY_ERROR_OPERATION_FAILED Operation failed because of a system error + * SMARTREPLY_ERROR_OUT_OF_MEMORY Out of memory + * @param[in] candidate_list Candidate answer list + * @param[in] count The total number of the replies + * @see smartreply_service_get_nth_reply_message() + * @see smartreply_service_destory_list() + */ +typedef void (*smartreply_service_replies_received_cb)(int request_id, int error, smartreply_reply_h* candidate_list, int count); + +/** + * @brief Request Smart Replies to Engine asynchronously + * @since_tizen 2.3.1 + * @param[in] app_id Unique ID of application + * @param[in] sender Sender information (phone number) + * @param[in] message Received message from sender + * @param[in] callback Callback function + * @return Incremental request ID which will also be passed by the first parameter of callback function + * @see smartreply_service_get_nth_reply_message() + * @see smartreply_service_destory_list() + * @see smartreply_service_replies_received() + */ +int smartreply_service_get_replies_async(const char* app_id, const char* sender, + const char* message, smartreply_service_replies_received_cb callback); +/** + * @brief Get nth reply message + * @since_tizen 2.3.1 + * @param[in] reply_list The list that includes replied messages + * @param[in] index The reply number which you want to get + * @param[out] message The reply message + * @remarks You should free message parameter + * @return 0 on success, otherwise a negative error value + * @retval SMARTREPLY_ERROR_NONE Successful + * @retval SMARTREPLY_ERROR_NO_DATA There is no data. + * @pre smartreply_service_get_replies_async() + * @pre smartreply_service_get_replies() + */ +int smartreply_service_get_nth_reply_message(smartreply_reply_h* reply_list, + int index, char** message); + +/** + * @brief Get nth reply message with type + * @since_tizen 2.3.1 + * @param[in] reply_list The list that includes replied messages + * @param[in] index The reply number which you want to get + * @param[out] type The type of the reply. one of "TEXT", "TIME", "DATE", "DAYOFWEEK", "LOCATION" + * @param[out] message The reply message + * @remarks You should free message and type parameter + * @return 0 on success, otherwise a negative error value + * @retval SMARTREPLY_ERROR_NONE Successful + * @retval SMARTREPLY_ERROR_NO_DATA There is no data. + * @pre smartreply_service_get_replies_async() + * @pre smartreply_service_get_replies() + */ +int smartreply_service_get_nth_reply_message_with_type(smartreply_reply_h* reply_list, + int index, char** type, char** message); +/** + * @brief Deletes reply_list struct + * @since_tizen 2.3.1 + * @param[in] reply_list The list that you want to delete + * @return 0 on success, otherwise a negative error value + * @retval SMARTREPLY_ERROR_NONE Successful + * @retval SMARTREPLY_ERROR_NO_DATA There is no data. + * @pre smartreply_service_get_replies_async() + * @pre smartreply_service_get_replies() + */ +int smartreply_service_destory_list(smartreply_reply_h* reply_list); + +/** + * @brief Records users' reply to history to update future replies + * @since_tizen 2.3.1 + * @param[in] app_id Unique ID of application + * @param[in] sender Sender information (phone number) + * @param[in] received_message The received message from sender + * @param[in] replied_message The replied message + * @return 0 on success, otherwise a negative error value + * @retval SMARTREPLY_ERROR_NONE Successful + * @retval SMARTREPLY_ERROR_NOT_SUPPORTED Specified language is not supported + * @retval SMARTREPLY_ERROR_OPERATION_FAILED Operation failed because of a system error + * @retval SMARTREPLY_ERROR_OUT_OF_MEMORY Out of memory + */ +int smartreply_service_record_user_reply(const char* app_id, +const char* sender, const char* received_message, const char* replied_message); + +/** + * @brief Preload Engines + * @remarks This API preloads engines before finding reply which will reduce delay of getting reply + * @since_tizen 2.3.1 + * @return 0 on success, otherwise a negative error value + * @retval SMARTREPLY_ERROR_NONE Successful + * @retval SMARTREPLY_ERROR_NOT_SUPPORTED Specified language is not supported. + * @retval SMARTREPLY_ERROR_OPERATION_FAILED Operation failed because of a system error + * @retval SMARTREPLY_ERROR_OUT_OF_MEMORY Out of memory + */ +int smartreply_service_prepare_engine(); + +#ifdef __cplusplus +} +#endif + +#endif /* __SMARTREPLY_SERVICE_H__ */ diff --git a/include/smartreply_util.h b/include/smartreply_util.h new file mode 100755 index 0000000..429d6b2 --- /dev/null +++ b/include/smartreply_util.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2014 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. + */ + + +#ifndef __SMARTREPLY_UTIL_H__ +#define __SMARTREPLY_UTIL_H__ + +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "CAPI_SMARTREPLY_SERVICE" + +#ifndef EXPORT_API +#define EXPORT_API __attribute__ ((visibility("default"))) +#endif + + +/* +* Internal Macros +*/ +#define SMARTREPLY_LOGD(fmt,args...) LOGD(fmt, ##args) +#define SMARTREPLY_LOGW(fmt,args...) LOGW(fmt, ##args) +#define SMARTREPLY_LOGI(fmt,args...) LOGI(fmt, ##args) +#define SMARTREPLY_LOGE(fmt,args...) LOGE(fmt, ##args) +#define SMARTREPLY_SECLOG(fmt,args...) SECURE_LOGD(fmt, ##args) + +#define SMARTREPLY_CHECK_CONDITION(condition, error, msg) \ + do { \ + if (condition) { \ + } else { \ + SMARTREPLY_LOGE("%s(0x%08x)", msg, error); \ + return error; \ + } \ + } while (0) + +#define SMARTREPLY_NULL_ARG_CHECK_RETURN_FALSE(arg)\ + do { \ + if(arg != NULL) { \ + } else { \ + SMARTREPLY_LOGE("SMARTREPLY_ERROR_INVALID_PARAMETER"); \ + return false; }; \ + } while (0) + +#define SMARTREPLY_NULL_ARG_CHECK(arg) \ + SMARTREPLY_CHECK_CONDITION(arg != NULL,SMARTREPLY_ERROR_INVALID_PARAMETER,"SMARTREPLY_ERROR_INVALID_PARAMETER") + +#define SMARTREPLY_PRINT_ERROR_CODE_RETURN(code) \ + do{ \ + SMARTREPLY_LOGE("%s(0x%08x)", #code, code); \ + return code; \ + } while (0) + + +///////////////////////////////////////////////////////////////////////////////////////////////// + +#define _S(s) #s + +/* + * @brief Copies one string to another and releases receiver if needed. + * @details This function copies one string to another and releases receiver if needed. + * @since_tizen 2.4 + * + * @param[out] dst The destination string pointer. + * @param[in] src The original string pointer. + * @param[in] max_length The maximum size of bytes to be copied. + * @return 0 on success, otherwise a negative error value. + * @retval #SMARTREPLY_ERROR_NONE Successful + * @retval #SMARTREPLY_ERROR_INVALID_PARAMETER Invalid parameter + */ +int smartreply_set_string(const char *src, const int max_length, char **dst); + +/* + * @brief Copies one string to another. + * @details This function copies one string to another. + * @since_tizen 2.4 + * + * @param[out] dst The destination string pointer. + * @param[in] src The original string pointer. + * @param[in] max_length The maximum size of bytes to be copied. + * @return 0 on success, otherwise a negative error value. + * @retval #SMARTREPLY_ERROR_NONE Successful + * @retval #SMARTREPLY_ERROR_INVALID_PARAMETER Invalid parameter + */ +int smartreply_get_string(const char *src, const int max_length, char **dst); + + +#endif +/* __SMARTREPLY_UTIL_H__ */ diff --git a/include/types_internal.h b/include/types_internal.h new file mode 100755 index 0000000..6b29d7a --- /dev/null +++ b/include/types_internal.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_TYPES_INTERNAL_H__ +#define __SMARTREPLY_TYPES_INTERNAL_H__ + +//#include + +#include +#include +#include +#include + +#define EXTAPI __attribute__ ((visibility("default"))) +#define EMPTY_STRING "" + +/* Internal Error Codes + * Please define the necessary error codes here. + * Note that, these error codes must be aligned with the error enums defined in all API headers. + */ + +/* Logging and Error Handling */ +#define _I SLOGI +#define _D SLOGD +#define _W SLOGW +#define _E SLOGE +#define _SI SECURE_SLOGI +#define _SD SECURE_SLOGD +#define _SW SECURE_LOGW +#define _SE SECURE_SLOGE + +/* Color code for dlog */ +#define RED(X) "\033[1;31m" X "\033[0m" +#define GREEN(X) "\033[1;32m" X "\033[0m" +#define YELLOW(X) "\033[1;33m" X "\033[0m" +#define BLUE(X) "\033[1;34m" X "\033[0m" +#define PURPLE(X) "\033[1;35m" X "\033[0m" +#define CYAN(X) "\033[1;36m" X "\033[0m" + + +#define STR_EQ(X, Y) (g_strcmp0((X), (Y)) == 0) + +#define IF_FAIL_RETURN_TAG(cond, ret, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); return ret; } } while (0) + +#define IF_FAIL_RETURN(cond, ret) \ + do { if (!(cond)) { return ret; } } while (0) + +#define IF_FAIL_VOID_TAG(cond, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); return; } } while (0) + +#define IF_FAIL_VOID(cond) \ + do { if (!(cond)) { return; } } while (0) + +#define IF_FAIL_CATCH_TAG(cond, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); goto CATCH; } } while (0) + +#define IF_FAIL_CATCH(cond) \ + do { if (!(cond)) { goto CATCH; } } while (0) + +#define IS_FAILED(X) ((X) != SMARTREPLY_ERROR_NONE) + +#define ASSERT_ALLOC(X) IF_FAIL_RETURN_TAG(X, SMARTREPLY_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed") +#define ASSERT_NOT_NULL(X) IF_FAIL_RETURN_TAG(X, SMARTREPLY_ERROR_INVALID_PARAMETER, _E, "Parameter null") +#define CHECK_NULL(p) \ + if (NULL == p) { \ + LOGE("[%s] INVALID_PARAMETER(0x%08x) %s is null.", \ + __FUNCTION__, SMARTREPLY_ERROR_INVALID_PARAMETER, #p); \ + return SMARTREPLY_ERROR_INVALID_PARAMETER; \ + } + +#define SMR_MEM_DATA_CPY(dest,src,len,type) \ + do{ \ + if(src!=NULL&&len>0) \ + { \ + dest = (type *) calloc (len+1 , sizeof (type)); \ + assert(dest); \ + memcpy(dest, src, len*sizeof(type)); \ + } \ + } while(0); + + + +#define HANDLE_GERROR(Err) \ + do { if ((Err)) { _E("GError: %s", Err->message); g_error_free(Err); Err = NULL; } } while (0) + + +/* DBus */ +#define DBUS_DEST "org.tizen.smartreply" +#define DBUS_PATH "/org/tizen/smartreply" +#define DBUS_IFACE "org.tizen.smartreply" +#define DBUS_TIMEOUT 3000000 + +#define METHOD_REQUEST "Request" +#define METHOD_RESPOND "Respond" +#define SIGNAL_LAUNCHED "Launched" + +enum request_type { + REQ_ADD_ENGINE = 1, + REQ_REMOVE_ENGINE, + REQ_GET_REPLY, + REQ_FEEDBACK, + REQ_IS_SUPPORTED, + REQ_IS_LOADED, + REQ_PREPARE_ENGINE, +}; + +#define ARG_REQTYPE "type" +#define ARG_COOKIE "cookie" +#define ARG_REQID "req_id" +#define ARG_SUBJECT "subject" +#define ARG_INPUT "input" + +#define ARG_RESULT_ERR "r_err" +#define ARG_RESULT_ADD "r_add" +#define ARG_OUTPUT "output" + + +#endif /* __SMARTREPLY_TYPES_INTERNAL_H__ */ diff --git a/packaging/smartreply.manifest b/packaging/smartreply.manifest new file mode 100755 index 0000000..a76fdba --- /dev/null +++ b/packaging/smartreply.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/smartreply.spec b/packaging/smartreply.spec new file mode 100755 index 0000000..3637e3c --- /dev/null +++ b/packaging/smartreply.spec @@ -0,0 +1,90 @@ +Name: smartreply +Summary: Tizen SmartReply Framework Native API +Version: 1.1.0 +Release: 1 +Group: Framework/system +License: Apache License, Version 2.0 +Source0: %{name}-%{version}.tar.gz + +BuildRequires: cmake +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(bundle) +BuildRequires: pkgconfig(capi-appfw-app-control) +BuildRequires: pkgconfig(pkgmgr-info) +#BuildRequires: pkgconfig(capi-security-privilege-manager) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(json-glib-1.0) +#BuildRequires: pkgconfig(security-server) + + +%ifarch %{arm} +%define ARCH arm +%else +%define ARCH i586 +%endif + +%description +Tizen SmartReply Framework Native API + +%prep +%setup -q + +%build +%if 0%{?sec_build_binary_debug_enable} +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" +%endif + +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` + +export CFLAGS+=" -Wextra -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wswitch-default" +export CXXFLAGS+=" -Wextra -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wswitch-default -Wnon-virtual-dtor -Wno-c++0x-compat" + +export CFLAGS+=" -Wno-unused-parameter -Wno-empty-body" +export CXXFLAGS+=" -Wno-unused-parameter -Wno-empty-body" + +export CFLAGS+=" -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-strict-aliasing -fno-unroll-loops -fsigned-char -fstrict-overflow -fno-common" +export CXXFLAGS+=" -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-strict-aliasing -fno-unroll-loops -fsigned-char -fstrict-overflow" + +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DMAJORVER=${MAJORVER} -DFULLVER=%{version} +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +# Lisence +mkdir -p %{buildroot}/usr/share/license +cp LICENSE %{buildroot}/usr/share/license/%{name} + +%post +/sbin/ldconfig + +%postun +/sbin/ldconfig + +%files +%manifest packaging/%{name}.manifest +%defattr(-,root,root,-) +%{_libdir}/*.so* +%{_datadir}/license/%{name} +#%if %{BINTYPE} == "engineer" +%{_includedir}/smartreply/smartreply_service.h + +#%endif + +%package devel +Summary: Tizen SmartReply Framework Native API (Development) +Group: Framework/system +Requires: %{name} = %{version}-%{release} + +%description devel +Tizen SmartReply Framework Native API (Development) + +%files devel +%defattr(-,root,root,-) +%{_includedir}/smartreply/*.h +%{_libdir}/pkgconfig/%{name}.pc diff --git a/smartreply.pc.in b/smartreply.pc.in new file mode 100755 index 0000000..50edac1 --- /dev/null +++ b/smartreply.pc.in @@ -0,0 +1,13 @@ +#Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=/usr/lib +includedir=@PC_INCLUDE@ + +Name: @PC_NAME@ +Description: @PC_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} diff --git a/src/db_mgr.cpp b/src/db_mgr.cpp new file mode 100755 index 0000000..ca88162 --- /dev/null +++ b/src/db_mgr.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include +#include +#include +#include +#include + +static smr::db_manager_iface *_instance = NULL; + +void smr::db_manager::set_instance(smr::db_manager_iface* mgr) +{ + _instance = mgr; +} + +bool smr::db_manager::create_table(unsigned int query_id, const char* table_name, const char* columns, const char* option, db_listener_iface* listener) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->create_table(query_id, table_name, columns, option, listener); +} + +bool smr::db_manager::insert(unsigned int query_id, const char* table_name, json& record, db_listener_iface* listener) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->insert(query_id, table_name, record, listener); +} + +bool smr::db_manager::execute(unsigned int query_id, const char* query, db_listener_iface* listener) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->execute(query_id, query, listener); +} + +bool smr::db_manager::insert_sync(const char* table_name, json& record, int64_t* row_id) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->insert_sync(table_name, record, row_id); +} + +bool smr::db_manager::execute_sync(const char* query, std::vector* records) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->execute_sync(query, records); +} diff --git a/src/dbus_client.cpp b/src/dbus_client.cpp new file mode 100755 index 0000000..ce09c50 --- /dev/null +++ b/src/dbus_client.cpp @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include +#include +//#include +#include + +#include "json.h" +#include "types_internal.h" +#include "scope_mutex.h" +#include "response_handler.h" +#include "smartreply_service.h" +#include "dbus_client.h" + +using namespace std; + +static GDBusConnection *dbus_connection = NULL; +static GDBusNodeInfo *dbus_node_info = NULL; + +static const gchar introspection_xml[] = + "" + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +static const char* get_security_cookie() +{ + static string s_dummy = ""; + /* + static char *cookie = NULL; + static GMutex cookie_mutex; + smr::scope_mutex sm(&cookie_mutex); + + if (cookie == NULL) { + int raw_size = security_server_get_cookie_size(); + IF_FAIL_RETURN_TAG(raw_size > 0, NULL, _E, "Invalid cookie size"); + + int ret; + char raw_cookie[raw_size]; + + ret = security_server_request_cookie(raw_cookie, raw_size); + IF_FAIL_RETURN_TAG(ret >= 0, NULL, _E, "Failed to get the security cookie"); + + cookie = g_base64_encode(reinterpret_cast(raw_cookie), raw_size); + IF_FAIL_RETURN_TAG(cookie, NULL, _E, "Failed to encode the cookie"); + }*/ + + return s_dummy.c_str(); +} + +static void handle_response(const gchar *sender, GVariant *param, GDBusMethodInvocation *invocation) +{ + gint req_id = 0; + const gchar *subject = NULL; + gint error = 0; + const gchar *data = NULL; + + g_variant_get(param, "(i&si&s)", &req_id, &subject, &error, &data); + +#ifdef SHOW_SENDER_MSG + _I("[Response] ReqId: %d, Subject: %s, Error: %d", req_id, subject, error); + _D("Data: %s", data); +#endif + + smr::response_handler::deliver(subject, req_id, error, data); + + g_dbus_method_invocation_return_value(invocation, NULL); +} + +static void handle_method_call(GDBusConnection *conn, const gchar *sender, + const gchar *obj_path, const gchar *iface, const gchar *method_name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + IF_FAIL_VOID_TAG(STR_EQ(obj_path, DBUS_PATH), _W, "Invalid path: %s", obj_path); + IF_FAIL_VOID_TAG(STR_EQ(iface, DBUS_IFACE), _W, "Invalid interface: %s", obj_path); + + if (STR_EQ(method_name, METHOD_RESPOND)) { + handle_response(sender, param, invocation); + } else { + _W("Invalid method: %s", method_name); + } +} + +smr::dbus_client::dbus_client() +{ +} + +smr::dbus_client::~dbus_client() +{ + release(); +} + +bool smr::dbus_client::init() +{ + static GMutex connection_mutex; + smr::scope_mutex sm(&connection_mutex); + + if (dbus_connection) { + return true; + } + + GError *gerr = NULL; + + dbus_node_info = g_dbus_node_info_new_for_xml(introspection_xml, NULL); + IF_FAIL_RETURN_TAG(dbus_node_info != NULL, false, _E, "Initialization failed"); + + gchar *addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN_TAG(addr != NULL, false, _E, "Getting address failed"); + _SD("Address: %s", addr); + + dbus_connection = g_dbus_connection_new_for_address_sync(addr, + (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, NULL, &gerr); + g_free(addr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN_TAG(dbus_connection != NULL, false, _E, "Connection failed"); + + GDBusInterfaceVTable vtable; + vtable.method_call = handle_method_call; + vtable.get_property = NULL; + vtable.set_property = NULL; + + guint reg_id = g_dbus_connection_register_object(dbus_connection, DBUS_PATH, + dbus_node_info->interfaces[0], &vtable, NULL, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN_TAG(reg_id>0, false, _E, "Object registration failed"); + + _I("Dbus connection established: %s", g_dbus_connection_get_unique_name(dbus_connection)); + return true; +} + +void smr::dbus_client::release() +{ + if (dbus_connection) { + g_dbus_connection_flush_sync(dbus_connection, NULL, NULL); + g_dbus_connection_close_sync(dbus_connection, NULL, NULL); + g_object_unref(dbus_connection); + dbus_connection = NULL; + } + + if (dbus_node_info) { + g_dbus_node_info_unref(dbus_node_info); + dbus_node_info = NULL; + } +} + +namespace { + struct UserData { + smr::dbus_client::dbus_client_request_callback cb; + void* ext; + int req_id; + }; + void g_async_ready_callback(GObject *source_object, + GAsyncResult *res, + gpointer user_data) { + + _I("g_async_ready_callback"); + + GError *err = NULL; + GVariant *response = g_dbus_connection_call_finish(dbus_connection, res, &err); + + HANDLE_GERROR(err); + //IF_FAIL_RETURN_TAG(response, ERR_OPERATION_FAILED, _E, "Method call failed"); + + gint _error = SMARTREPLY_ERROR_OPERATION_FAILED; + const gchar *_req_result = NULL; + const gchar *_data_read = NULL; + + g_variant_get(response, "(i&s&s)", &_error, &_req_result, &_data_read); + + string req(_req_result); + string data(_data_read); + + UserData* ud = (UserData*)user_data; + + ud->cb(ud->req_id, _error, ud->ext, req, data); + delete ud; + g_variant_unref(response); + } +} + +int smr::dbus_client::request_async( + int type, int req_id, const char* subject, const char* input, void* ext, dbus_client_request_callback cb) +{ +#ifdef SHOW_SENDER_MSG + _SI("Requesting: %d, %d, %s, %s", type, req_id, subject, input); +#endif + + if (subject == NULL) { + subject = EMPTY_STRING; + } + + if (input == NULL) { + input = EMPTY_JSON_OBJECT; + } + + const char *cookie = get_security_cookie(); + IF_FAIL_RETURN_TAG(cookie, SMARTREPLY_ERROR_OPERATION_FAILED, _E, "Cookie generation failed"); + + GVariant *param = g_variant_new("(isiss)", type, cookie, req_id, subject, input); + IF_FAIL_RETURN_TAG(param, SMARTREPLY_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + UserData* user = new UserData; + user->req_id = req_id; + user->cb = cb; + user->ext = ext; + + g_dbus_connection_call(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, g_async_ready_callback, (void*)user); + + + return SMARTREPLY_ERROR_NONE; +} + +int smr::dbus_client::request( + int type, int req_id, const char* subject, const char* input, + std::string* req_result, std::string* data_read) +{ + _SI("Requesting: %d, %d, %s, %s", type, req_id, subject, input); + + if (subject == NULL) { + subject = EMPTY_STRING; + } + + if (input == NULL) { + input = EMPTY_JSON_OBJECT; + } + + const char *cookie = get_security_cookie(); + IF_FAIL_RETURN_TAG(cookie, SMARTREPLY_ERROR_OPERATION_FAILED, _E, "Cookie generation failed"); + + GVariant *param = g_variant_new("(isiss)", type, cookie, req_id, subject, input); + IF_FAIL_RETURN_TAG(param, SMARTREPLY_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + GError *err = NULL; + GVariant *response = g_dbus_connection_call_sync(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, &err); + HANDLE_GERROR(err); + IF_FAIL_RETURN_TAG(response, SMARTREPLY_ERROR_OPERATION_FAILED, _E, "Method call failed"); + + gint _error = SMARTREPLY_ERROR_OPERATION_FAILED; + const gchar *_req_result = NULL; + const gchar *_data_read = NULL; + + g_variant_get(response, "(i&s&s)", &_error, &_req_result, &_data_read); + if (req_result) { + *req_result = _req_result; + } + if (data_read) { + *data_read = _data_read; + } + + g_variant_unref(response); + + return _error; +} + +int smr::dbus_client::request_with_no_reply( + int type, int req_id, const char* subject, const char* input) +{ + _SI("Requesting: %d, %d, %s, %s", type, req_id, subject, input); + + if (subject == NULL) { + subject = EMPTY_STRING; + } + + if (input == NULL) { + input = EMPTY_JSON_OBJECT; + } + + const char *cookie = get_security_cookie(); + IF_FAIL_RETURN_TAG(cookie, SMARTREPLY_ERROR_OPERATION_FAILED, _E, "Cookie generation failed"); + + GVariant *param = g_variant_new("(isiss)", type, cookie, req_id, subject, input); + IF_FAIL_RETURN_TAG(param, SMARTREPLY_ERROR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + GError *err = NULL; + g_dbus_connection_call(dbus_connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, NULL, &err); + + if (err) { + HANDLE_GERROR(err); + return SMARTREPLY_ERROR_OPERATION_FAILED; + } + + return SMARTREPLY_ERROR_NONE; +} diff --git a/src/dbus_client.h b/src/dbus_client.h new file mode 100755 index 0000000..baa64cb --- /dev/null +++ b/src/dbus_client.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#ifndef __SMARTREPLY_LIB_DBUS_HANDLER_H__ +#define __SMARTREPLY_LIB_DBUS_HANDLER_H__ + +#include + +namespace smr { + + class dbus_client { + public: + dbus_client(); + ~dbus_client(); + + bool init(); + void release(); + + typedef void (*dbus_client_request_callback)(int req_id, int error, void* ext, const std::string& req_result, const std::string& data_read); + int request_async(int type, int req_id, const char* subject, const char* input, void* ext, dbus_client_request_callback cb); + int request(int type, int req_id, const char* subject, const char* input, std::string* req_result, std::string* data_read); + int request_with_no_reply(int type, int req_id, const char* subject, const char* input); + + }; /* classs smr::dbus_client */ + +} /* namespace smr */ + +#endif // __SMARTREPLY_LIB_DBUS_HANDLER_H__ diff --git a/src/dbus_server.cpp b/src/dbus_server.cpp new file mode 100755 index 0000000..9bc5c2e --- /dev/null +++ b/src/dbus_server.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "types_internal.h" +#include "dbus_server.h" +#include "dbus_server_iface.h" +#include "dbus_listener_iface.h" + +static smr::dbus_server_iface *_instance = NULL; + +void smr::dbus_server::set_instance(dbus_server_iface* svr) +{ + _instance = svr; +} + +int64_t smr::dbus_server::signal_subscribe(const char* sender, const char* path, const char* iface, const char* name, dbus_listener_iface* listener) +{ + IF_FAIL_RETURN_TAG(_instance, false, _E, "Not initialized"); + return _instance->signal_subscribe(sender, path, iface, name, listener); +} + +void smr::dbus_server::signal_unsubscribe(int64_t subscription_id) +{ + IF_FAIL_VOID_TAG(_instance, _E, "Not initialized"); + _instance->signal_unsubscribe(subscription_id); +} diff --git a/src/event.cpp b/src/event.cpp new file mode 100755 index 0000000..c467fb3 --- /dev/null +++ b/src/event.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include +#include "types_internal.h" +#include "event.h" + +event_driven_thread::event_driven_thread() +{ + thread_info.thread = NULL; + thread_info.is_running = 0; + thread_info.event_queue = NULL; +} + +event_driven_thread::~event_driven_thread() +{ + stop(); +} + +bool event_driven_thread::start() +{ + if (!g_atomic_int_get(&thread_info.is_running)) { + thread_info.event_queue = g_async_queue_new(); + g_atomic_int_set(&thread_info.is_running, 1); + thread_info.thread = g_thread_new(NULL, thread_func_wrapper, static_cast(this)); + } + + return true; +} + +bool event_driven_thread::stop() +{ + if (g_atomic_int_get(&thread_info.is_running)) { + event_message_s* event = new(std::nothrow) event_message_s; + IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed"); + + event->is_stop_signal = true; + g_async_queue_push(thread_info.event_queue, event); + g_atomic_int_set(&thread_info.is_running, 0); + + g_thread_join(thread_info.thread); + + // Free the memory allocated for the event queue + while ((event = static_cast(g_async_queue_try_pop(thread_info.event_queue)))) { + if (event->data) { + delete_thread_event(event->type, event->data); + } + delete event; + } + g_async_queue_unref(thread_info.event_queue); + } + + return true; +} + +bool event_driven_thread::is_running() +{ + if (g_atomic_int_get(&thread_info.is_running)) { + return true; + } + return false; +} + +bool event_driven_thread::push_thread_event(int type, void* data) +{ + if (g_atomic_int_get(&thread_info.is_running)) { + event_message_s* event = new(std::nothrow) event_message_s; + IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed"); + + event->type = type; + event->data = data; + g_async_queue_push(thread_info.event_queue, event); + return true; + } else { + // If failed, free the received data object & return false. + delete_thread_event(type, data); + return false; + } +} + +gpointer event_driven_thread::thread_func_wrapper(gpointer func) +{ + static_cast(func)->process_event_queue(); + return NULL; +} + +void event_driven_thread::process_event_queue() +{ + event_message_s *event = NULL; + + while (g_atomic_int_get(&thread_info.is_running)) { + + event = static_cast(g_async_queue_pop(thread_info.event_queue)); + + if (event) { + if (event->is_stop_signal){ + delete event; + break; + } else { + on_thread_event_popped(event->type, event->data); + delete event; + } + } + + } +} diff --git a/src/json.cpp b/src/json.cpp new file mode 100755 index 0000000..aece126 --- /dev/null +++ b/src/json.cpp @@ -0,0 +1,909 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#define PATH_DELIM '.' + +static double string_to_double(const char* in) +{ + // Locale-independent string-to-double conversion + double out; + std::istringstream istr(in); + istr.imbue(std::locale("C")); + istr >> out; + return out; +} + +static std::string double_to_string(double in, int prec) +{ + // Locale-independent double-to-string conversion + std::ostringstream ostr; + ostr.imbue(std::locale("C")); + ostr << std::setprecision(prec) << std::fixed << in; + return ostr.str(); +} + +smr::json::json() +{ + JsonObject *obj = json_object_new(); + IF_FAIL_VOID_TAG(obj, _E, "Json object construction failed"); + + json_node = json_node_new(JSON_NODE_OBJECT); + if (!json_node) { + json_object_unref(obj); + _E("Json object construction failed"); + } + + json_node_set_object(json_node, obj); + json_object_unref(obj); +} + +smr::json::json(const json& j) +{ + json_node = json_node_copy(j.json_node); + IF_FAIL_VOID_TAG(json_node, _E, "Json object construction failed"); +} + +smr::json::json(const char* s) +{ + if (s) { + parse(s); + } else { + parse(EMPTY_JSON_OBJECT); + } +} + +smr::json::json(const std::string& s) +{ + if (s.empty()) { + parse(EMPTY_JSON_OBJECT); + } else { + parse(s.c_str()); + } +} + +smr::json::~json() +{ + release(); +} + +void smr::json::parse(const char* s) +{ + _SD("Parsing %s", s); + + gboolean result; + JsonParser *parser = NULL; + JsonNode *root = NULL; + + parser = json_parser_new(); + IF_FAIL_CATCH_TAG(parser, _E, "Memory allocation failed"); + + result = json_parser_load_from_data(parser, s, -1, NULL); + IF_FAIL_CATCH_TAG(result, _E, "Parsing failed"); + + root = json_parser_get_root(parser); + IF_FAIL_CATCH_TAG(root, _E, "Getting root failed"); + + json_node = json_node_copy(root); + IF_FAIL_CATCH_TAG(json_node, _E, "Copying failed"); + + g_object_unref(parser); + return; + +CATCH: + if (parser) { + g_object_unref(parser); + } +} + +void smr::json::release() +{ + if (json_node) { + json_node_free(json_node); + json_node = NULL; + } +} + +smr::json& smr::json::operator=(const json& j) +{ + release(); + json_node = json_node_copy(j.json_node); + if (!json_node) { + _E("Json object copy failed"); + } + return *this; +} + +smr::json& smr::json::operator=(const char* s) +{ + release(); + parse(s); + return *this; +} + +smr::json& smr::json::operator=(const std::string& s) +{ + release(); + parse(s.c_str()); + return *this; +} + +bool smr::json::operator==(const json& rhs) +{ + return node_equals(json_node, rhs.json_node); +} + +bool smr::json::operator!=(const json& rhs) +{ + return !operator==(rhs); +} + +/* TODO +bool smr::json::contains(const json& subset) const +{ + return false; +} +*/ + +char* smr::json::dup_cstr() +{ + IF_FAIL_RETURN_TAG(json_node, NULL, _E, "Json object not initialized"); + + JsonGenerator *jgen = NULL; + char *output = NULL; + + jgen = json_generator_new(); + IF_FAIL_CATCH(jgen); + + json_generator_set_root(jgen, json_node); + output = json_generator_to_data(jgen, NULL); + IF_FAIL_CATCH(output); + + g_object_unref(jgen); + return output; + +CATCH: + if (jgen) { + g_object_unref(jgen); + } + + _E("Memory allocation failed"); + return NULL; +} + +std::string smr::json::str() +{ + std::string output; + char *_s = dup_cstr(); + IF_FAIL_RETURN(_s, output = EMPTY_JSON_OBJECT); + + output = _s; + g_free(_s); + + return output; +} + +static char** tokenize_path(const char* path, int* length) +{ + //TODO: Re-implement this tokenizer using C++ stuff + char** tokens; + const char* pch; + const char* begin; + int i; + int j; + int len; + + if (path == NULL || strlen(path) == 0) { + *length = 0; + return NULL; + } + + *length = 1; + + for (pch = path; *pch != '\0'; pch++) { + if (*pch == PATH_DELIM) { + *length = *length + 1; + } + } + + tokens = static_cast(g_malloc((*length) * sizeof(char*))); + IF_FAIL_RETURN_TAG(tokens, NULL, _E, "Memory allocation failed"); + + begin = path; + i = 0; + + for (pch = path; ; pch++) { + if (*pch == PATH_DELIM || *pch == '\0') { + len = pch - begin; + tokens[i] = static_cast(g_malloc((len+1) * sizeof(char))); + IF_FAIL_CATCH_TAG(tokens[i], _E, "Memory allocation failed"); + strncpy(tokens[i], begin, len); + tokens[i][len] = '\0'; + i++; + begin = pch + 1; + } + + if (*pch == '\0') { + break; + } + } + + return tokens; + +CATCH: + for (j=0; jjson_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val.json_node, false, _E, "Invalid parameter"); + + JsonObject *jobj = traverse(json_node, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) + json_object_remove_member(jobj, key); + + json_object_set_member(jobj, key, val.json_node); + val.json_node = NULL; + val = json(); + + return true; +} + +bool smr::json::set(const char* path, const char* key, int val) +{ + return set(path, key, static_cast(val)); +} + +bool smr::json::set(const char* path, const char* key, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = traverse(json_node, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) + json_object_remove_member(jobj, key); + + json_object_set_int_member(jobj, key, val); + return true; +} + +bool smr::json::set(const char* path, const char* key, double val, int prec) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = traverse(json_node, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) { + json_object_remove_member(jobj, key); + } + + //NOTE: json-glib causes a precision issue while handling double values + json_object_set_string_member(jobj, key, double_to_string(val, prec).c_str()); + return true; +} + +bool smr::json::set(const char* path, const char* key, std::string val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = traverse(json_node, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) { + json_object_remove_member(jobj, key); + } + + json_object_set_string_member(jobj, key, val.c_str()); + return true; +} + +bool smr::json::get(const char* path, const char* key, json* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonObject *jobj = NULL; + JsonNode *node = NULL; + + jobj = traverse(json_node, path, false); + IF_FAIL_RETURN(jobj && json_object_has_member(jobj, key), false); + + node = json_object_dup_member(jobj, key); + IF_FAIL_RETURN_TAG(node, false, _E, "Memory allocation failed"); + + if (val->json_node) { + json_node_free(val->json_node); + } + val->json_node = node; + + return true; +} + +static JsonNode* search_value_node(JsonNode* jnode, const char* path, const char* key) +{ + JsonNode *node = NULL; + JsonObject *jobj = NULL; + JsonNodeType ntype; + + jobj = traverse(jnode, path, false); + IF_FAIL_RETURN(jobj && json_object_has_member(jobj, key), NULL); + + node = json_object_get_member(jobj, key); + ntype = json_node_get_node_type(node); + IF_FAIL_RETURN(ntype == JSON_NODE_VALUE, NULL); + + return node; +} + +bool smr::json::get(const char* path, const char* key, int* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + int64_t v; + + if (get(path, key, &v)) { + *val = v; + return true; + } + + return false; +} + +bool smr::json::get(const char* path, const char* key, int64_t* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = search_value_node(json_node, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + //TODO: if the string is not a number? + *val = static_cast(string_to_double(json_node_get_string(node))); + } else { + return false; + } + + return true; +} + +bool smr::json::get(const char* path, const char* key, double* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = search_value_node(json_node, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_DOUBLE) { + *val = json_node_get_double(node); + } else if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + //NOTE: json-glib causes a precision issue while handling double values + *val = string_to_double(json_node_get_string(node)); + } else { + return false; + } + + return true; +} + +bool smr::json::get(const char* path, const char* key, std::string* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = search_value_node(json_node, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + IF_FAIL_RETURN(vtype == G_TYPE_STRING, false); + + *val = json_node_get_string(node); + return true; +} + +static JsonArray* search_array(JsonNode* jnode, const char* path, const char* key, bool force) +{ + JsonNode *node = NULL; + JsonArray *arr = NULL; + JsonObject *jobj = NULL; + + jobj = traverse(jnode, path, force); + IF_FAIL_RETURN(jobj, NULL); + + if (!json_object_has_member(jobj, key)) { + if (force) { + arr = json_array_new(); + IF_FAIL_RETURN_TAG(arr, NULL, _E, "Memory allocation failed"); + json_object_set_array_member(jobj, key, arr); + } else { + return NULL; + } + } + node = json_object_get_member(jobj, key); + IF_FAIL_RETURN_TAG(node && json_node_get_node_type(node) == JSON_NODE_ARRAY, + NULL, _E, "Type mismatched: %s", key); + + return json_node_get_array(node); +} + +int smr::json::array_get_size(const char* path, const char* key) +{ + IF_FAIL_RETURN_TAG(this->json_node, -1, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, -1, _E, "Invalid parameter"); + + JsonArray *jarr = search_array(json_node, path, key, false); + IF_FAIL_RETURN_TAG(jarr, -1, _W, "Mismatched data type"); + + return json_array_get_length(jarr); +} + +bool smr::json::array_append(const char* path, const char* key, json& val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val.json_node, false, _E, "Invalid parameter"); + + JsonArray *arr = search_array(json_node, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_element(arr, val.json_node); + val.json_node = NULL; + val = json(); + + return true; +} + +bool smr::json::array_append(const char* path, const char* key, int val) +{ + return array_append(path, key, static_cast(val)); +} + +bool smr::json::array_append(const char* path, const char* key, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = search_array(json_node, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_int_element(arr, val); + return true; +} + +bool smr::json::array_append(const char* path, const char* key, double val, int prec) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = search_array(json_node, path, key, true); + IF_FAIL_RETURN(arr, false); + + //NOTE: json-glib causes a precision issue while handling double values + json_array_add_string_element(arr, double_to_string(val, prec).c_str()); + return true; +} + +bool smr::json::array_append(const char* path, const char* key, std::string val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = search_array(json_node, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_string_element(arr, val.c_str()); + return true; +} + +static JsonNode* search_array_elem(JsonNode* jnode, const char* path, const char* key, int index) +{ + JsonArray *jarr = search_array(jnode, path, key, false); + IF_FAIL_RETURN_TAG(jarr, NULL, _W, "Mismatched data type"); + + int size = json_array_get_length(jarr); + IF_FAIL_RETURN(size > index, NULL); + + JsonNode *node = json_array_get_element(jarr, index); + IF_FAIL_RETURN_TAG(node, NULL, _E, "Failed to get an array element"); + + return node; +} + +bool smr::json::array_set_at(const char* path, const char* key, int index, json& val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(val.json_node && key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_OBJECT, false, _E, "Type mismatched: %s[%d]", key, index); + + JsonObject *obj = json_node_get_object(val.json_node); + IF_FAIL_RETURN_TAG(obj, false, _E, "Getting object failed"); + + json_node_set_object(node, obj); + json_node_free(val.json_node); + val.json_node = NULL; + val = json(); + + return true; +} + +bool smr::json::array_set_at(const char* path, const char* key, int index, int val) +{ + return array_set_at(path, key, index, static_cast(val)); +} + +bool smr::json::array_set_at(const char* path, const char* key, int index, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index); + IF_FAIL_RETURN_TAG(json_node_get_value_type(node) == G_TYPE_INT64, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_int(node, val); + return true; +} + +bool smr::json::array_set_at(const char* path, const char* key, int index, double val, int prec) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index); + IF_FAIL_RETURN_TAG(json_node_get_value_type(node) == G_TYPE_STRING, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_string(node, double_to_string(val, prec).c_str()); + return true; +} + +bool smr::json::array_set_at(const char* path, const char* key, int index, std::string val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index); + IF_FAIL_RETURN_TAG(json_node_get_value_type(node) == G_TYPE_STRING, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_string(node, val.c_str()); + return true; +} + +bool smr::json::get_array_elem(const char* path, const char* key, int index, json* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNode *node_copy = json_node_copy(node); + IF_FAIL_RETURN_TAG(node_copy, false, _E, "Memory allocation failed"); + + if (val->json_node) { + json_node_free(val->json_node); + } + val->json_node = node_copy; + + return true; +} + +bool smr::json::get_array_elem(const char* path, const char* key, int index, int* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + int64_t v; + if (get_array_elem(path, key, index, &v)) { + *val = v; + return true; + } + + return false; +} + +bool smr::json::get_array_elem(const char* path, const char* key, int index, int64_t* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + *val = static_cast(string_to_double(json_node_get_string(node))); + } else { + _E("Type mismatched: %s", key); + return false; + } + + return true; +} + +bool smr::json::get_array_elem(const char* path, const char* key, int index, double* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_DOUBLE) { + *val = json_node_get_double(node); + } else if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + //NOTE: json-glib causes a precision issue while handling double values + *val = string_to_double(json_node_get_string(node)); + } else { + _E("Type mismatched: %s", key); + return false; + } + + return true; +} + +bool smr::json::get_array_elem(const char* path, const char* key, int index, std::string* val) +{ + IF_FAIL_RETURN_TAG(this->json_node, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = search_array_elem(json_node, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + IF_FAIL_RETURN_TAG(vtype == G_TYPE_STRING, false, _E, "Type mismatched: %s", key); + *val = json_node_get_string(node); + + const char * str = json_node_get_string(node); + _SI("1. json string CONVERT TO UTF-8 %s", str); + + /*char * p_dest = NULL; + p_dest = (char *)calloc(1, sizeof(char) * strlen(str)+1); + //(str,len, to_codeset, from_codeset, bytes_read, bytes_written, error) + gsize len = strlen(str) ; + p_dest = g_convert(str, strlen(str), "euc-kr", "utf-8", NULL, &len, NULL); + + std::string return_str(p_dest); + _I(" -> returned %s - %d", return_str.c_str(), len); + val = &return_str; + delete (str);*/ + //free (p_dest);*/ + return true; +} + +bool smr::json::get_member_list(json_node_t* node, std::list& list) +{ + IF_FAIL_RETURN(node, false); + list.clear(); + + JsonObject *jobj = json_node_get_object(node); + IF_FAIL_RETURN_TAG(jobj, false, _E, "Getting json object failed"); + + GList *members = json_object_get_members(jobj); + IF_FAIL_RETURN(members, true); + + for (GList *it = g_list_first(members); it; it = g_list_next(it)) { + const char *key = static_cast(it->data); + if (!key) { + list.clear(); + g_list_free(members); + _E("Member list extraction failed"); + return false; + } + + list.push_back(key); + } + + g_list_free(members); + return true; +} + +bool smr::json::get_keys(std::list* list) +{ + IF_FAIL_RETURN_TAG(list, false, _E, "Invalid parameter"); + return get_member_list(json_node, *list); +} + +bool smr::json::node_equals(json_node_t* lhs, json_node_t* rhs) +{ + IF_FAIL_RETURN(lhs && rhs, false); + + JsonNodeType ltype = json_node_get_node_type(lhs); + JsonNodeType rtype = json_node_get_node_type(rhs); + IF_FAIL_RETURN(ltype == rtype, false); + + switch (ltype) { + case JSON_NODE_VALUE: + IF_FAIL_RETURN(value_equals(lhs, rhs), false); + break; + case JSON_NODE_OBJECT: + IF_FAIL_RETURN(object_equals(lhs, rhs), false); + break; + case JSON_NODE_ARRAY: + IF_FAIL_RETURN(array_equals(lhs, rhs), false); + break; + default: + _W("Unsupported type"); + return false; + } + + return true; +} + +bool smr::json::value_equals(json_node_t* lhs, json_node_t* rhs) +{ + GType ltype = json_node_get_value_type(lhs); + GType rtype = json_node_get_value_type(rhs); + IF_FAIL_RETURN(ltype == rtype, false); + + switch (ltype) { + case G_TYPE_INT64: + return json_node_get_int(lhs) == json_node_get_int(rhs); + case G_TYPE_DOUBLE: + return json_node_get_double(lhs) == json_node_get_double(rhs); + case G_TYPE_STRING: + return STR_EQ(json_node_get_string(lhs), json_node_get_string(rhs)); + default: + _W("Unsupported type"); + return false; + } +} + +bool smr::json::object_equals(json_node_t* lhs, json_node_t* rhs) +{ + std::list lm, rm; + IF_FAIL_RETURN(get_member_list(lhs, lm), false); + IF_FAIL_RETURN(get_member_list(rhs, rm), false); + IF_FAIL_RETURN(lm.size() == rm.size(), false); + + lm.sort(); + rm.sort(); + + std::list::iterator lit, rit; + lit = lm.begin(); + rit = rm.begin(); + + while (lit != lm.end()) { + IF_FAIL_RETURN(*lit == *rit, false); + + json_node_t *lhs_child = json_object_get_member(json_node_get_object(lhs), (*lit).c_str()); + json_node_t *rhs_child = json_object_get_member(json_node_get_object(rhs), (*rit).c_str()); + IF_FAIL_RETURN(node_equals(lhs_child, rhs_child), false); + + ++lit; + ++rit; + } + + return true; +} + +bool smr::json::array_equals(json_node_t* lhs, json_node_t* rhs) +{ + JsonArray *larr = json_node_get_array(lhs); + JsonArray *rarr = json_node_get_array(rhs); + + int size = json_array_get_length(larr); + IF_FAIL_RETURN(size == static_cast(json_array_get_length(rarr)), false); + + for (int i=0; i +#include +#include +#include +#include +#include "types_internal.h" +#include "scope_mutex.h" +#include "smartreply_service.h" +#include "request_handler.h" +#include "response_handler.h" +#include "dbus_client.h" + +using namespace std; + +typedef std::map response_cb_map_t; + +static smr::dbus_client *dbus_handle = NULL; +static response_cb_map_t *response_cb_map = NULL; + +namespace { + class exit_handler { + public: + exit_handler() {} + ~exit_handler() { delete dbus_handle; } + }; +} + +static exit_handler _exit_handler; + +static int generate_req_id() +{ + static GMutex rid_mutex; + static int req_id = 0; + + smr::scope_mutex sm(&rid_mutex); + + // Overflow handling + if (++req_id < 0) { + req_id = 1; + } + + return req_id; +} + +static bool initialize() +{ + static GMutex init_mutex; + smr::scope_mutex sm(&init_mutex); + + if (dbus_handle) { + return true; + } + + response_cb_map = new(std::nothrow) response_cb_map_t; + IF_FAIL_CATCH_TAG(response_cb_map, _E, "Memory allocation failed"); + + dbus_handle = new(std::nothrow) smr::dbus_client(); + IF_FAIL_CATCH_TAG(dbus_handle, _E, "Memory allocation failed"); + IF_FAIL_CATCH_TAG(dbus_handle->init(), _E, "Dbus initialization failed"); + + return true; + +CATCH: + delete dbus_handle; + delete response_cb_map; + dbus_handle = NULL; + response_cb_map = NULL; + return false; +} + +int smr::request_handler::add_engine(const char* language, int* req_id, std::string *request_result) +{ + ASSERT_NOT_NULL(language); + ASSERT_NOT_NULL(req_id); + ASSERT_NOT_NULL(request_result); + + IF_FAIL_RETURN_TAG(initialize(), SMARTREPLY_ERROR_OPERATION_FAILED, _E, "Connection failed"); + *req_id = generate_req_id(); + + std::string result_str; + int error = dbus_handle->request(REQ_ADD_ENGINE, *req_id, language, NULL, &result_str, NULL); + + if (request_result) { + *request_result = result_str; + } + _I("[add_engine():Client Get Result] Error: %#x", error); + _SI("[add_engine():Client Get Result] Result: %s", result_str.c_str()); + + return error; +} + +int smr::request_handler::remove_engine(const char* language, int* req_id) +{ + ASSERT_NOT_NULL(language); + ASSERT_NOT_NULL(req_id); + IF_FAIL_RETURN_TAG(initialize(), SMARTREPLY_ERROR_OPERATION_FAILED, _E, "Connection failed"); + + *req_id = generate_req_id(); + + std::string result_str; + int error = dbus_handle->request(REQ_REMOVE_ENGINE, *req_id, language, NULL, &result_str, NULL); + _I("[remove_engine():Client Get Result] Error: %#x", error); + _SI("[remove_engine():Client Get Result] Result: %s", result_str.c_str()); + return error; + +} + + +namespace { + +struct UserData { + smr::request_handler::get_reply_response_cb cb; + void* ext; +}; +void dbus_callback(int req_id, int error, void* ext, const std::string& req_result, const std::string& data_read) { + + _I("dbus_callback"); + + UserData* ud = (UserData*)ext; + smr::json res = req_result; + + ud->cb(req_id, error, ud->ext, res); + delete ud; +} + +} + +int smr::request_handler::get_reply_async(const char* sender, const char* input, int* req_id, void* ext, get_reply_response_cb cb) +{ + ASSERT_NOT_NULL(input); + ASSERT_NOT_NULL(sender); + ASSERT_NOT_NULL(req_id); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + *req_id = generate_req_id(); + +#ifdef SHOW_SENDER_MSG + _I("[Get Reply] ReqId: %d, Input: [%s]: %s", *req_id, sender, input); +#endif + + std::string result_str; + + UserData* ud = new UserData; + ud->cb = cb; + ud->ext = ext; + + int error = dbus_handle->request_async(REQ_GET_REPLY, *req_id, sender, input, (void*)ud, dbus_callback); + + _I("[get_reply():Client Get Result] Error: %#x", error); + + return error; +} + +int smr::request_handler::get_reply(const char* sender, const char* input, int* req_id, smr::json* request_result) +{ + ASSERT_NOT_NULL(input); + ASSERT_NOT_NULL(sender); + ASSERT_NOT_NULL(req_id); + ASSERT_NOT_NULL(request_result); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + *req_id = generate_req_id(); + _SI("[Get Reply] ReqId: %d, Input: [%s]: %s", *req_id, sender, input); + std::string result_str; + + int error = dbus_handle->request(REQ_GET_REPLY, *req_id, sender, input, &result_str, NULL); + + if (request_result) { + *request_result = result_str; + } + _I("[get_reply():Client Get Result] Error: %#x", error); + _SI("[get_reply():Client Get Result] Result: %s", result_str.c_str()); + + return error; +} + +int smr::request_handler::send_feedback(const char* app_id, const char* sender, const char* req_message, + const char* replied_str, int* req_id) +{ + ASSERT_NOT_NULL(app_id); + ASSERT_NOT_NULL(sender); + ASSERT_NOT_NULL(req_message); + ASSERT_NOT_NULL(replied_str); + ASSERT_NOT_NULL(req_id); + + _I(GREEN("Request_handler - send_feedback")); + + *req_id = generate_req_id(); + //_SI("[User Feedback] ReqId: %d, Pairs : [%s]@[%s]: %s <- %s", *req_id, sender, app_id, req_message, replied_str); + + std::string req_str; + req_str.append(sender); + req_str.append("@"); + req_str.append(app_id); + req_str.append("@"); + req_str.append(req_message); + + int error = dbus_handle->request_with_no_reply(REQ_FEEDBACK, *req_id, replied_str, req_str.c_str()); + + _I("[send_feedback():Client Get Result] Error: %#x", error); + + return error; +} + +int smr::request_handler::send_prepare_engine() +{ + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + int req_id = generate_req_id(); + int error = dbus_handle->request_with_no_reply(REQ_PREPARE_ENGINE, req_id, NULL, NULL); + + + _I("[prepare_engine():Client Get Result] Error: %#x", error); + return error; +} + +int smr::request_handler::is_supported(const char* language, int* req_id) +{ + ASSERT_NOT_NULL(language); + ASSERT_NOT_NULL(req_id); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + *req_id = generate_req_id(); + _SI("[is_supported] ReqId: %d, Language: %s", *req_id, language); + std::string result_str; + int error = dbus_handle->request(REQ_IS_SUPPORTED, *req_id, language, NULL, &result_str, NULL); + _I("[is_supported():Client] Error: %#x", error); + _SI("[is_supported(): Client IS_SURPPOTED] Result: %s", result_str.c_str()); + return error; +} + +int smr::request_handler::is_loaded(const char* language, int* req_id) +{ + ASSERT_NOT_NULL(language); + ASSERT_NOT_NULL(req_id); + IF_FAIL_RETURN_TAG(initialize(), false, _E, "Connection failed"); + + *req_id = generate_req_id(); + _SI("[is_loaded] ReqId: %d, Language: %s", *req_id, language); + std::string result_str; + int error = dbus_handle->request(REQ_IS_LOADED, *req_id, language, NULL, &result_str, NULL); + _I("[is_loaded():Client IS_LOAEDED] Error: %#x", error); + _SI("[is_loaded():Client IS_LOADED] Result: %s", result_str.c_str()); + return error; +} + +void smr::response_handler::deliver(const char* subject, int req_id, int error, const char* data) +{ + response_cb_map_t::iterator it = response_cb_map->find(subject); + IF_FAIL_VOID_TAG(it != response_cb_map->end(), _E, "Unknown subject '%s'", subject); + + it->second(subject, req_id, error, data); +} diff --git a/src/scope_mutex.cpp b/src/scope_mutex.cpp new file mode 100755 index 0000000..ab7ced9 --- /dev/null +++ b/src/scope_mutex.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "scope_mutex.h" + +smr::scope_mutex::scope_mutex(GMutex *m) : mutex(m) +{ + g_mutex_lock(mutex); +} + +smr::scope_mutex::~scope_mutex() +{ + g_mutex_unlock(mutex); +} diff --git a/src/smartreply_service.cpp b/src/smartreply_service.cpp new file mode 100755 index 0000000..4977900 --- /dev/null +++ b/src/smartreply_service.cpp @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2014 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. + */ +#include +#include +#include +#include +#include "request_handler.h" +#include "smartreply_service.h" +#include "smartreply_util.h" +#include +#include + +#define SMR_UNDEFINED_APP_ID_STRING "com.samsung.undefined" +#define SMR_UNDEFINED_APP_ID_LENGTH 22 +#define SMR_UNDEFINED_SENDER_STRING "anonymous" +#define SMR_UNDEFINED_SENDER_LENGTH 10 + +using namespace std; + +typedef struct smartreply_reply_s { + int count; + GList *reply; + //GList *cursor; +} _smartreply_reply_s; + + +typedef struct smartreply_message_s { + char* message; + //int no; +} _smartreply_message_s; + +std::vector &split(const std::string &s, char delim, std::vector &elems) { + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + } + return elems; +} + +std::vector split(const std::string &s, char delim) { + std::vector elems; + split(s, delim, elems); + return elems; +} + +std::string check_null_str(const char* str, const char* def) { + return std::string(str == NULL || (strlen(str) == 0) ? def : str); + +} + +int _list_add_all(smartreply_reply_h** candidate_list, int* length, std::string result_str) +{ + ASSERT_NOT_NULL(candidate_list); + if (result_str.size() == 0) return SMARTREPLY_ERROR_NONE; + + std::vector reply_list = split(result_str, '|'); + int count = reply_list.size(); + _I("Candidate Replies Count: %d", count); + + smartreply_reply_s *s_list = NULL; + smartreply_message_s *s_message = NULL; + + s_list = (smartreply_reply_s*)calloc(1, sizeof(smartreply_reply_s)); + if (s_list == NULL) { + return SMARTREPLY_ERROR_OUT_OF_MEMORY; + } + + for (std::vector::iterator it = reply_list.begin(); it != reply_list.end(); ++it) { + _SI("Smart Reply : %s", it->c_str()); + s_message = (smartreply_message_s*)calloc(1, sizeof(smartreply_message_s)); + if (s_message == NULL) { + free(s_list); + return SMARTREPLY_ERROR_OUT_OF_MEMORY; + } + + SMR_MEM_DATA_CPY(s_message->message, it->c_str(), it->size(), char); + if (NULL == s_message->message) + { + _E("[OUT_OF_MEMORY] Fail to create 's_message->message'."); + free(s_message); + free(s_list); + return SMARTREPLY_ERROR_OUT_OF_MEMORY; + } + + s_list->reply = g_list_append(s_list->reply, s_message); + s_list->count++; + } + + /* if (s_list->count == 0) + s_list->cursor = s_list->reply; + */ + *candidate_list = (smartreply_reply_h*)s_list; + *length = s_list->count; + + return SMARTREPLY_ERROR_NONE; +} + +namespace { + int getTime() { + struct timeval now; + gettimeofday(&now, 0); + return now.tv_sec * 1000 + now.tv_usec / 1000; + } + bool isAction(const string& message) { + return message.find("&") != string::npos; + } + bool splitActionMessage(const string& action_msg, string& action_type, string& message) { + if (isAction(action_msg) == false) { + return false; + } + action_type = action_msg.substr(0, action_msg.find("&")); + message = action_msg.substr(action_msg.find("&") + 1); + return true; + } + +} + +EXPORT_API int smartreply_service_get_replies(const char* app_id, +const char* sender, const char* message, smartreply_reply_h** candidate_list, int* length) +{ + int start = getTime(); + + ASSERT_NOT_NULL(message); + ASSERT_NOT_NULL(candidate_list); + ASSERT_NOT_NULL(length); + int req_id; + int err = -1; + std::string _str(check_null_str(sender, SMR_UNDEFINED_SENDER_STRING)); + _str.append("|"); + _str.append(check_null_str(app_id, SMR_UNDEFINED_APP_ID_STRING)); + + std::string sender_str = _str; + _SI("[%s] %s", sender_str.c_str(), message); + + smr::json replies_str; + err = smr::request_handler::get_reply(sender_str.c_str(), message, &req_id, &replies_str); + IF_FAIL_RETURN_TAG(err == SMARTREPLY_ERROR_NONE, err, _E, "Getting reply list failed"); + _SI("Read server's response: %s", replies_str.str().c_str()); + + std::string reply_str; + replies_str.get(NULL, "replies", &reply_str); + err = _list_add_all(candidate_list, length, reply_str); + + int end = getTime(); + _I("GetReplyTime : %d msec", end - start); + return err; +} + +namespace { + void get_reply_callback2(int req_id, int error, void* ext, smr::json& response) { + _I("get_reply_callback"); + _SI("Read server's response: %s", response.str().c_str()); + + int length = 0; + smartreply_reply_h* candidate_list = NULL; + + std::string reply_str; + response.get(NULL, "replies", &reply_str); + int err = _list_add_all(&candidate_list, &length, reply_str); + + ((smartreply_service_replies_received_cb)ext)(req_id, err, candidate_list, length); + } +} + +EXPORT_API int smartreply_service_get_replies_async(const char* app_id, const char* sender, + const char* message, smartreply_service_replies_received_cb cb) { + + std::string _str(check_null_str(sender, SMR_UNDEFINED_SENDER_STRING)); + _str.append("|"); + _str.append(check_null_str(app_id, SMR_UNDEFINED_APP_ID_STRING)); + + std::string sender_str = _str; + _SI("[%s]", sender_str.c_str()); + std::string msg(message); + + int req_id = 0; + smr::request_handler::get_reply_async(sender_str.c_str(), message, &req_id, (void*)cb, get_reply_callback2); + + return req_id; +} + + +EXPORT_API int smartreply_service_get_nth_reply_message_with_type(smartreply_reply_h *reply_list, int index, char** type, char **reply_str) { + ASSERT_NOT_NULL(reply_list); + ASSERT_NOT_NULL(reply_str); + + GList *cursor = NULL; + smartreply_reply_s *list_s; + list_s = (smartreply_reply_s *)reply_list; + int i, j; + char *temp = NULL; + + for (i=0, j=0, cursor = list_s->reply; cursor; cursor = cursor->next, i++) { + if (j == index) + { + smartreply_message_s * _message; + _message = (smartreply_message_s*)cursor->data; + int len = strlen(_message->message); + + string action_msg = _message->message; + //cout << action_msg << endl; + if (isAction(action_msg)) { + //cout << "action msg" << endl; + string atype, msg; + splitActionMessage(action_msg, atype, msg); + //cout << atype << " " << msg << endl; + SMR_MEM_DATA_CPY(temp, msg.c_str(), msg.length(), char); + *reply_str = temp; + if (type != NULL) { + SMR_MEM_DATA_CPY(temp, atype.c_str(), atype.length(), char); + *type = temp; + } + } + else { + SMR_MEM_DATA_CPY(temp, _message->message, len, char); + *reply_str = temp; + if (type != NULL) { + SMR_MEM_DATA_CPY(temp, "TEXT", strlen("TEXT"), char); + *type = temp; + } + } + return SMARTREPLY_ERROR_NONE; + } + j++; + } + //free(temp); + return SMARTREPLY_ERROR_NO_DATA; +} + +EXPORT_API int smartreply_service_get_nth_reply_message(smartreply_reply_h *reply_list, int index, char **reply_str) { + int res = smartreply_service_get_nth_reply_message_with_type(reply_list, index, NULL, reply_str); + return res; +} +EXPORT_API int smartreply_service_destory_list(smartreply_reply_h *reply_list) { + ASSERT_NOT_NULL(reply_list); + + smartreply_reply_s* _reply; + _reply = (smartreply_reply_s*) reply_list; + + GList *cursor = NULL; + for (cursor = _reply->reply; cursor; cursor = cursor->next) { + free(cursor->data); + } + + g_list_free(_reply->reply); + + free(reply_list); + return SMARTREPLY_ERROR_NONE; +} + +EXPORT_API int smartreply_service_is_language_supported(const char* language, bool *is_enable) { + int req_id; + *is_enable = smr::request_handler::is_supported(language, &req_id); + _I("smartreply_service_is_supported %s : %d", language, is_enable); + return SMARTREPLY_ERROR_NONE; +} + + +EXPORT_API int smartreply_service_record_user_reply(const char* app_id, +const char* sender, const char* received_message, const char* replied_message) +{ + std::string snd(check_null_str(sender, SMR_UNDEFINED_SENDER_STRING)); + std::string aid(check_null_str(app_id, SMR_UNDEFINED_APP_ID_STRING)); + + int req_id; + int err = smr::request_handler::send_feedback(aid.c_str(), snd.c_str(), received_message, replied_message, &req_id); + IF_FAIL_RETURN_TAG(err == SMARTREPLY_ERROR_NONE, err, _E, "Send User Feedback is failed"); + + return err; +} + +EXPORT_API int smartreply_service_prepare_engine() +{ + int err = smr::request_handler::send_prepare_engine(); + return err; +} + + + +// Depreciated +/* +EXPORT_API int smartreply_service_is_supported(const char* language, bool *is_enable) { + return smartreply_service_is_language_supported(language, is_enable); +} + +EXPORT_API int smartreply_service_get_replis(const char* app_id, +const char* sender, const char* message, smartreply_reply_h** candidate_list, int* length) { + return smartreply_service_get_replies(app_id, sender, message, candidate_list, length); +} + +namespace { + void get_reply_callback(int req_id, int error, void* ext, smr::json& response) { + _I("get_reply_callback"); + _I("Read server's response: %s", response.str().c_str()); + + int length = 0; + smartreply_reply_h* candidate_list = NULL; + + std::string reply_str; + response.get(NULL, "replies", &reply_str); + int err = _list_add_all(&candidate_list, &length, reply_str); + + ((get_replis_callback)ext)(req_id, err, candidate_list, length); + } +} + +EXPORT_API int smartreply_service_get_replis_async(const char* app_id, const char* sender, + const char* message, get_replis_callback cb) { + + std::string _str(check_null_str(sender, SMR_UNDEFINED_SENDER_STRING)); + _str.append("|"); + _str.append(check_null_str(app_id, SMR_UNDEFINED_APP_ID_STRING)); + + std::string sender_str = _str; + _I("[%s]", sender_str.c_str()); + std::string msg(message); + + int req_id = 0; + smr::request_handler::get_reply_async(sender_str.c_str(), message, &req_id, (void*)cb, get_reply_callback); + + return req_id; +} + +EXPORT_API int smartreply_service_send_feedback(const char* app_id, +const char* sender, const char* req_message, const char* replied_str) +{ + return smartreply_service_record_user_reply(app_id, sender, req_message, replied_str); +}*/ diff --git a/src/starter.cpp b/src/starter.cpp new file mode 100755 index 0000000..5cdd247 --- /dev/null +++ b/src/starter.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include + +#if !defined(GLIB_VERSION_2_36) +namespace { + class g_type_initializer { + public: + g_type_initializer() { g_type_init(); } + ~g_type_initializer() {} + }; +} /* namespace smr */ + +static g_type_initializer initializer; +#endif -- 2.34.1