--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(GdeApiCpp C CXX)
+
+# Ensure a proper linker behavior:
+CMAKE_POLICY(SET CMP0003 NEW)
+
+LIST(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake_files")
+FIND_PACKAGE(POCO REQUIRED)
+INCLUDE_DIRECTORIES(${Poco_INCLUDE_DIRS})
+
+ADD_SUBDIRECTORY(src)
--- /dev/null
+# - Find the Poco includes and libraries.
+# The following variables are set if Poco is found. If Poco is not
+# found, Poco_FOUND is set to false.
+# Poco_FOUND - True when the Poco include directory is found.
+# Poco_INCLUDE_DIRS - the path to where the poco include files are.
+# Poco_LIBRARY_DIRS - The path to where the poco library files are.
+# Poco_BINARY_DIRS - The path to where the poco dlls are.
+
+# ----------------------------------------------------------------------------
+# If you have installed Poco in a non-standard location.
+# Then you have three options.
+# In the following comments, it is assumed that <Your Path>
+# points to the root directory of the include directory of Poco. e.g
+# If you have put poco in C:\development\Poco then <Your Path> is
+# "C:/development/Poco" and in this directory there will be two
+# directories called "include" and "lib".
+# 1) After CMake runs, set Poco_INCLUDE_DIR to <Your Path>/poco<-version>
+# 2) Use CMAKE_INCLUDE_PATH to set a path to <Your Path>/poco<-version>. This will allow find_path()
+# to locate Poco_INCLUDE_DIR by utilizing the PATH_SUFFIXES option. e.g.
+# set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "<Your Path>/include")
+# 3) Set an environment variable called ${POCO_ROOT} that points to the root of where you have
+# installed Poco, e.g. <Your Path>. It is assumed that there is at least a subdirectory called
+# Foundation/include/Poco in this path.
+#
+# Note:
+# 1) If you are just using the poco headers, then you do not need to use
+# Poco_LIBRARY_DIR in your CMakeLists.txt file.
+# 2) If Poco has not been installed, then when setting Poco_LIBRARY_DIR
+# the script will look for /lib first and, if this fails, then for /stage/lib.
+#
+# Usage:
+# In your CMakeLists.txt file do something like this:
+# ...
+# # Poco
+# find_package(Poco)
+# ...
+# include_directories(${Poco_INCLUDE_DIRS})
+# link_directories(${Poco_LIBRARY_DIR})
+#
+# In Windows, we make the assumption that, if the Poco files are installed, the default directory
+# will be C:\poco or C:\Program Files\Poco or C:\Programme\Poco.
+
+set(POCO_INCLUDE_PATH_DESCRIPTION "top-level directory containing the poco include directories.")
+set(POCO_INCLUDE_DIR_MESSAGE "Set the Poco_INCLUDE_DIR cmake cache entry to the ${POCO_INCLUDE_PATH_DESCRIPTION}")
+set(POCO_LIBRARY_PATH_DESCRIPTION "directory containing the poco libraries:")
+
+
+set(POCO_DIR_SEARCH $ENV{POCO_ROOT})
+if(POCO_DIR_SEARCH)
+ file(TO_CMAKE_PATH ${POCO_DIR_SEARCH} POCO_DIR_SEARCH)
+endif(POCO_DIR_SEARCH)
+list(APPEND POCO_DIR_SEARCH ${Poco_DIR})
+
+if(WIN32)
+ set(POCO_DIR_SEARCH
+ ${POCO_DIR_SEARCH}
+ C:/poco
+ D:/poco
+ "C:/Program Files/poco"
+ "C:/Programme/poco"
+ "D:/Program Files/poco"
+ "D:/Programme/poco"
+ )
+endif(WIN32)
+
+# Add in some path suffixes. These will have to be updated whenever a new Poco version comes out.
+set(SUFFIX_FOR_INCLUDE_PATH
+ include
+)
+
+set(SUFFIX_FOR_LIBRARY_PATH
+ lib
+ bin
+)
+
+#
+# Look for an installation.
+#
+find_path(Poco_INCLUDE_DIR NAMES Poco/Poco.h PATH_SUFFIXES ${SUFFIX_FOR_INCLUDE_PATH} PATHS
+
+ # Look in other places.
+ ${POCO_DIR_SEARCH}
+
+ # Help the user find it if we cannot.
+ DOC "The ${POCO_INCLUDE_PATH_DESCRIPTION}"
+)
+
+if(NOT Poco_INCLUDE_DIR)
+
+ # Look for standard unix include paths
+ find_path(Poco_INCLUDE_DIR Poco/Poco.h DOC "The ${POCO_INCLUDE_PATH_DESCRIPTION}")
+
+endif(NOT Poco_INCLUDE_DIR)
+
+# Assume we didn't find it.
+set(Poco_FOUND 0)
+
+set(Poco_LIBRARIES )
+set(Poco_LIBRARY_DIRS )
+
+# Now try to get the include and library path.
+# Find all libraries, store debug and release separately
+foreach(lib
+ Crypto
+ Data
+ DataMySQL
+ DataSQLite
+ Foundation
+ JSON
+ MongoDB
+ Net
+ NetSSL
+ PDF
+ Util
+ XML
+ Zip
+ )
+
+ # Find Release libraries
+ find_library(Poco_${lib}_LIBRARY_RELEASE
+ NAMES Poco${lib}
+ PATH_SUFFIXES ${SUFFIX_FOR_LIBRARY_PATH}
+ PATHS ${POCO_DIR_SEARCH}
+ DOC "The ${POCO_LIBRARY_PATH_DESCRIPTION} Poco${lib}"
+ )
+
+ # Find Debug libraries
+ find_library(Poco_${lib}_LIBRARY_DEBUG
+ NAMES Poco${lib}d
+ PATH_SUFFIXES ${SUFFIX_FOR_LIBRARY_PATH}
+ PATHS ${POCO_DIR_SEARCH}
+ DOC "The ${POCO_LIBRARY_PATH_DESCRIPTION} Poco${lib}d"
+ )
+
+ mark_as_advanced(Poco_${lib}_LIBRARY_RELEASE)
+ mark_as_advanced(Poco_${lib}_LIBRARY_DEBUG)
+
+ # Add libraries to variable according to build type
+ set(Poco_${lib}_LIBRARY)
+ if(Poco_${lib}_LIBRARY_RELEASE)
+ list(APPEND Poco_LIBRARIES optimized ${Poco_${lib}_LIBRARY_RELEASE})
+ list(APPEND Poco_${lib}_LIBRARY optimized ${Poco_${lib}_LIBRARY_RELEASE})
+ get_filename_component(lib_dir ${Poco_${lib}_LIBRARY_RELEASE} PATH)
+ list(APPEND Poco_LIBRARY_DIRS ${lib_dir})
+ endif()
+
+ if(Poco_${lib}_LIBRARY_DEBUG)
+ list(APPEND Poco_LIBRARIES debug ${Poco_${lib}_LIBRARY_DEBUG})
+ list(APPEND Poco_${lib}_LIBRARY debug ${Poco_${lib}_LIBRARY_DEBUG})
+ get_filename_component(lib_dir ${Poco_${lib}_LIBRARY_RELEASE} PATH)
+ list(APPEND Poco_LIBRARY_DIRS ${lib_dir})
+ endif()
+
+endforeach()
+
+if(Poco_LIBRARY_DIRS)
+ list(REMOVE_DUPLICATES Poco_LIBRARY_DIRS)
+endif()
+
+set(Poco_INCLUDE_DIRS ${Poco_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Poco DEFAULT_MSG
+ Poco_INCLUDE_DIRS
+ Poco_Foundation_LIBRARY
+ Poco_LIBRARIES
+ )
--- /dev/null
+
+INCLUDE_DIRECTORIES(
+ ${Poco_INCLUDE_DIRS}
+)
+
+LINK_DIRECTORIES(
+ ${Poco_LIBRARY_DIRS}
+ )
+
+SET(_link_LIBRARIES
+# ${Poco_LIBRARIES} # all packages
+ PocoFoundation
+ PocoNet
+ PocoJSON
+)
+
+SET(gde_api_cpp_HEADERS
+ CommandResultTO.hpp
+ CommandTO.hpp
+ HttpConnection.hpp
+ JsonFormatter.hpp
+ User.hpp
+ UserService.hpp
+)
+
+SET(gde_api_cpp_SOURCES
+ CommandResultTO.cpp
+ CommandTO.cpp
+ HttpConnection.cpp
+ JsonFormatter.cpp
+ UserService.cpp
+)
+
+ADD_LIBRARY(GdeApiCpp SHARED ${gde_api_cpp_SOURCES})
+TARGET_LINK_LIBRARIES(GdeApiCpp ${_link_LIBRARIES} )
+INSTALL(TARGETS GdeApiCpp EXPORT ${PROJECT_NAME}TargetGroup DESTINATION lib)
+
+INSTALL(FILES ${gde_api_cpp_HEADERS} DESTINATION include)
--- /dev/null
+#include "CommandResultTO.hpp"
+#include "JsonFormatter.hpp"
+
+gde::CommandResultTO::CommandResultTO(const CommandResultTO& cto)
+ : _code(cto._code), _message(cto._message), _data(cto._data)
+{
+}
+
+gde::CommandResultTO
+gde::CommandResultTO::fromJson(std::string json)
+{
+ Poco::JSON::Object::Ptr object = JsonFormatter::parse(json);
+ int code = JsonFormatter::extract<int>(object, "code");
+ std::string message = JsonFormatter::extract<std::string>(object, "message");
+ std::string data = JsonFormatter::extract<std::string>(object, "data");
+ return CommandResultTO(code, message, data);
+}
+
+std::string
+gde::CommandResultTO::toJson()
+{
+ Poco::JSON::Object obj;
+ obj.set("code", Poco::Dynamic::Var(_code));
+ obj.set("message", Poco::Dynamic::Var(_message));
+ obj.set("data", Poco::Dynamic::Var(_data));
+
+ return JsonFormatter::stringify(obj);
+}
--- /dev/null
+#ifndef GDE_COMMAND_RESULT_TO_HPP
+#define GDE_COMMAND_RESULT_TO_HPP
+
+#include <string>
+#include <map>
+
+namespace gde {
+
+ class CommandResultTO {
+
+ public :
+ // WARNING: keep enum values synchronized to WEB API (CommandResultTO)
+ enum { OK = 1, ERROR = 2};
+
+ public:
+ CommandResultTO(int code = -1,
+ std::string message = std::string(),
+ std::string data = std::string())
+ : _code(code), _message(message), _data(data) {}
+ CommandResultTO(const CommandResultTO&);
+ ~CommandResultTO() {}
+
+ inline std::string getMessage() const { return _message; }
+ inline void setMessage(std::string message) { this->_message = message; }
+
+ inline std::string getData() const { return _data; }
+ inline void setData(std::string data) { this->_data = data; }
+
+ inline int getCode() const { return _code; }
+ inline void setCode(int code) { this->_code = code; }
+
+ static CommandResultTO fromJson(std::string json);
+ std::string toJson();
+
+ private:
+ int _code;
+ std::string _message; // JSON format
+ std::string _data; // JSON format
+ };
+
+};
+
+#endif
--- /dev/null
+#include "CommandTO.hpp"
+#include "JsonFormatter.hpp"
+
+#include <iostream>
+#include <sstream>
+
+template <typename T>
+std::string
+toString(const T& value)
+{
+ std::ostringstream oss;
+ oss << value;
+ return oss.str();
+}
+
+template <typename T>
+T
+fromString(const std::string& valueString)
+{
+ std::istringstream iss(valueString);
+ T value;
+ return iss >> value ? value : 0;
+}
+
+
+gde::CommandTO::CommandTO(const CommandTO& cto)
+ : _method(cto._method), _data(cto._data), _parameters(cto._parameters)
+{
+}
+
+template <typename T>
+T
+gde::CommandTO::getParameter(std::string name)
+{
+ if (_parameters.find(name) == _parameters.end()) {
+ std::cerr << "Unknown parameter: " << name << std::endl;
+ return 0;
+ }
+ else {
+ return fromString<T>(_parameters[name]);
+ }
+}
+
+template <typename T>
+void
+gde::CommandTO::setParameter(std::string name, const T& value, bool replaceIfExist)
+{
+ if (replaceIfExist) {
+ _parameters[name] = toString(value);
+ }
+ else {
+ if (_parameters.find(name) != _parameters.end()) {
+ std::cerr << "Parameter already exists: " << name << std::endl;
+ }
+ }
+}
+
+gde::CommandTO
+gde::CommandTO::fromJson(std::string json)
+{
+ Poco::JSON::Object::Ptr object = JsonFormatter::parse(json);
+ int method = JsonFormatter::extract<int>(object, "method");
+ std::string data = JsonFormatter::extract<std::string>(object, "data");
+
+ ParametersMap parameters;
+ Poco::JSON::Object::Ptr objParameters = JsonFormatter::extract<Poco::JSON::Object::Ptr>(object, "parameters");
+ for (Poco::JSON::Object::ConstIterator itr = objParameters->begin(); itr != objParameters->end(); ++itr) {
+ std::string paramName = itr->first;
+ std::string paramValue = itr->second;
+ parameters[paramName] = paramValue;
+ }
+
+ return CommandTO(method, data, parameters);
+}
+
+std::string
+gde::CommandTO::toJson()
+{
+ Poco::JSON::Object obj;
+ obj.set("method", Poco::Dynamic::Var(_method));
+ obj.set("data", Poco::Dynamic::Var(_data));
+
+ Poco::JSON::Object::Ptr objParameters = new Poco::JSON::Object(true);
+ typedef std::map<std::string, std::string>::iterator MapIterator;
+ for (MapIterator itr = _parameters.begin(); itr != _parameters.end(); ++itr) {
+ objParameters->set(itr->first, itr->second);
+ }
+ obj.set("parameters", objParameters);
+
+ return JsonFormatter::stringify(obj);
+}
--- /dev/null
+#ifndef GDE_COMMAND_TO_HPP
+#define GDE_COMMAND_TO_HPP
+
+#include <string>
+#include <map>
+
+namespace gde {
+
+ class CommandTO {
+
+ typedef std::map<std::string, std::string> ParametersMap;
+
+ public:
+ CommandTO(int method = -1,
+ std::string data = std::string(),
+ const ParametersMap& parameters=ParametersMap())
+ : _method(method), _data(data), _parameters(parameters) {}
+ CommandTO(const CommandTO&);
+ ~CommandTO() {}
+
+ inline std::string getData() const { return _data; }
+ inline void setData(std::string data) { this->_data = data; }
+
+ inline int getMethod() const { return _method; }
+ inline void setMethod(int method) { this->_method = method; }
+
+ template <typename T> T getParameter(std::string name);
+ template <typename T> void setParameter(std::string name, const T& value, bool replaceIfExist=true);
+
+ static CommandTO fromJson(std::string json);
+ std::string toJson();
+
+ private:
+ int _method;
+ std::string _data; // JSON format
+ ParametersMap _parameters;
+ };
+
+};
+
+#endif
--- /dev/null
+#include "HttpConnection.hpp"
+#include "JsonFormatter.hpp"
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+#include <Poco/StreamCopier.h>
+#include <Poco/Net/HTTPResponse.h>
+
+using namespace Poco::Net;
+
+gde::HttpConnection::HttpConnection(Poco::URI uri)
+ : _path("/")
+{
+ try {
+ _session.setHost(uri.getHost());
+ _session.setPort(uri.getPort());
+ //_session.setProxy(machine, port);
+ } catch (Poco::Exception& e) {
+ std::cerr << e.displayText() << std::endl;
+ return;
+ }
+
+ _path = uri.getPathAndQuery();
+ if (_path.empty())
+ _path = "/";
+}
+
+gde::HttpConnection::~HttpConnection()
+{
+}
+
+// Workflow:
+// 1. request (json) --> CommandTO object
+// 2. command data (json) from CommandTO --> <something>TO
+// 3. call DAO with <something>TO and obtain another <something>TO
+// 4. latter <something>TO --> (json) CommandResultTO data
+// 5. set CommandResultTO code
+// 6. CommandResultTO --> (json) response
+
+gde::CommandResultTO
+gde::HttpConnection::_processRequest(const HTTPRequest& request,
+ const std::string& requestBody)
+{
+ int code = CommandResultTO::OK;
+ std::string message = "";
+ std::string data = "";
+
+ try {
+ std::ostream& os = _session.sendRequest((HTTPRequest&)request);
+ // Send request body, if any
+ if (!requestBody.empty()) {
+ std::istringstream iss(requestBody);
+ Poco::StreamCopier::copyStream((std::istream&)iss, os);
+ }
+
+ // Get response
+ HTTPResponse response;
+ std::istream& rs = _session.receiveResponse(response);
+ //std::cout << response.getStatus() << " " << response.getReason() << endl;
+ std::ostringstream responseBody;
+ Poco::StreamCopier::copyStream(rs, responseBody);
+ // responseBody contains a CommandResultTO in json format
+ return CommandResultTO::fromJson(responseBody.str());
+ } catch (Poco::Exception& e) {
+ std::cerr << e.displayText() << std::endl;
+ return CommandResultTO(CommandResultTO::ERROR);
+ }
+}
+
+gde::CommandResultTO
+gde::HttpConnection::doGet(const CommandTO& cto)
+{
+ HTTPRequest request(HTTPRequest::HTTP_GET, _path, HTTPMessage::HTTP_1_1);
+ return _processRequest(request, cto.getData());
+}
+
+gde::CommandResultTO
+gde::HttpConnection::doPost(const CommandTO& cto)
+{
+ HTTPRequest request(HTTPRequest::HTTP_PUT, _path, HTTPMessage::HTTP_1_1);
+ return _processRequest(request, cto.getData());
+}
--- /dev/null
+#ifndef GDE_HTTP_CONNECTION_HPP
+#define GDE_HTTP_CONNECTION_HPP
+
+#include "CommandTO.hpp"
+#include "CommandResultTO.hpp"
+
+#include <string>
+
+#include <Poco/URI.h>
+#include <Poco/Net/HTTPClientSession.h>
+#include <Poco/Net/HTTPRequest.h>
+
+namespace gde {
+
+ class HttpConnection {
+
+ public:
+ HttpConnection(Poco::URI);
+ ~HttpConnection();
+
+ CommandResultTO doGet(const CommandTO&);
+ CommandResultTO doPost(const CommandTO&);
+
+ private:
+ gde::CommandResultTO _processRequest(const Poco::Net::HTTPRequest&,
+ const std::string& requestBody);
+
+ private:
+ Poco::Net::HTTPClientSession _session;
+ std::string _path;
+ };
+
+};
+
+#endif
--- /dev/null
+#include "JsonFormatter.hpp"
+
+#include <Poco/JSON/Parser.h>
+
+#include <sstream>
+
+Poco::JSON::Object::Ptr
+gde::JsonFormatter::parse(const std::string& json)
+{
+ Poco::JSON::Parser parser;
+ Poco::Dynamic::Var result = parser.parse(json);
+ // use pointers to avoid copying
+ Poco::JSON::Object::Ptr object = result.extract<Poco::JSON::Object::Ptr>();
+ return object;
+}
+
+template <typename T>
+T
+gde::JsonFormatter::extract(Poco::JSON::Object::Ptr object, const std::string& varName)
+{
+ Poco::Dynamic::Var v = object->get(varName);
+ return v.convert<T>();
+}
+
+std::string
+gde::JsonFormatter::stringify(const Poco::JSON::Object& object) {
+ std::ostringstream jsonStream;
+ object.stringify(jsonStream);
+ return jsonStream.str();
+}
--- /dev/null
+#ifndef JSON_FORMATTER_HPP
+#define JSON_FORMATTER_HPP
+
+#include <string>
+
+#include <Poco/JSON/Object.h>
+
+namespace gde {
+
+ class JsonFormatter {
+ public:
+
+ static Poco::JSON::Object::Ptr parse(const std::string&);
+ template <typename T> static T extract(Poco::JSON::Object::Ptr, const std::string&);
+
+ static std::string stringify(const Poco::JSON::Object&);
+ };
+
+};
+
+#endif
--- /dev/null
+#ifndef GDE_USER_HPP
+#define GDE_USER_HPP
+
+#include <string>
+
+namespace gde {
+
+ class User {
+ friend class UserService;
+
+ public:
+ inline int getId() const { return _id; }
+ inline void setId(int id) { this->_id = id; }
+
+ inline std::string getName() const { return _name; }
+ inline void setName(const std::string& name) { this->_name = name; }
+
+ inline std::string getPassword() const { return _password; }
+ inline void setPassword(const std::string& password) { this->_password = password; }
+
+ private:
+ User(int id=-1, std::string name="", std::string password="")
+ : _id(id), _name(name), _password(password) {}
+ ~User() {}
+ User(const User&); // non copyable
+ User& operator=(const User&); // non copyable
+
+ private:
+ int _id;
+ std::string _name;
+ std::string _password;
+ };
+
+};
+
+#endif
--- /dev/null
+#include "UserService.hpp"
+#include "HttpConnection.hpp"
+#include "CommandTO.hpp"
+#include "CommandResultTO.hpp"
+#include "JsonFormatter.hpp"
+
+#include <iostream>
+#include <sstream>
+
+/*
+ * WARNING: keep enum values synchronized to WEB API (UserService)
+ */
+enum {
+ CREATE_USER = 1,
+ DELETE_USER,
+ ADD_TO_GROUP,
+ REMOVE_FROM_GROUP,
+ CREATE_GROUP,
+ DELETE_GROUP,
+ FIND_USER
+};
+
+gde::UserService::UserService()
+ : _servletName("/UserService")
+{
+}
+
+gde::UserService::~UserService()
+{
+}
+
+gde::User
+gde::UserService::createUser(std::string name, std::string password)
+{
+ // build JSON string for CommandTO data
+ Poco::JSON::Object obj;
+ obj.set("name", Poco::Dynamic::Var(name));
+ obj.set("password", Poco::Dynamic::Var(password));
+ std::string data = JsonFormatter::stringify(obj);
+
+ CommandTO cto(CREATE_USER, data);
+ CommandResultTO crto = gde::HttpConnection(Poco::URI(_servletName)).doPost(cto);
+
+ std::cout << "createUser command:\n";
+ std::cout << "\tStatus code (OK=1, ERROR=2): " << crto.getCode() << std::endl;
+
+ // build User object from CommandResultTO data (json format)
+ {
+ Poco::JSON::Object::Ptr object = JsonFormatter::parse(crto.getData());
+ int id = JsonFormatter::extract<int>(object, "id");
+ std::string name = JsonFormatter::extract<std::string>(object, "name");
+ std::string password = JsonFormatter::extract<std::string>(object, "password");
+ return gde::User(id, name, password);
+ }
+}
--- /dev/null
+#ifndef GDE_USER_SERVICE_HPP
+#define GDE_USER_SERVICE_HPP
+
+#include "User.hpp"
+
+#include <string>
+
+namespace gde {
+
+ class UserService {
+
+ public:
+ User createUser(std::string name, std::string password);
+
+ void createUser();
+ void deleteUser();
+ void findUser();
+
+ void createGroup();
+ void deleteGroup();
+
+ void addToGroup();
+ void removeFromGroup();
+
+ private:
+ UserService();
+ ~UserService();
+ UserService(const UserService&); // non copyable
+ UserService& operator=(const UserService&); // non copyable
+
+ private:
+ std::string _servletName;
+ };
+
+};
+
+#endif