Salome HOME
ProfilesService
authorCédric Aguerre <cedric.aguerre@edf.fr>
Mon, 31 Aug 2015 14:45:01 +0000 (16:45 +0200)
committerCédric Aguerre <cedric.aguerre@edf.fr>
Mon, 31 Aug 2015 14:45:01 +0000 (16:45 +0200)
13 files changed:
projects/GDE_API_CPP/api/src/AttributesService.cpp
projects/GDE_API_CPP/api/src/CMakeLists.txt
projects/GDE_API_CPP/api/src/GDESession.cpp
projects/GDE_API_CPP/api/src/GDESession.hpp
projects/GDE_API_CPP/api/src/JsonFormatter.cpp
projects/GDE_API_CPP/api/src/JsonFormatter.hpp
projects/GDE_API_CPP/api/src/Profile.hpp [new file with mode: 0644]
projects/GDE_API_CPP/api/src/ProfileAttribute.cpp [new file with mode: 0644]
projects/GDE_API_CPP/api/src/ProfileAttribute.hpp [new file with mode: 0644]
projects/GDE_API_CPP/api/src/ProfilesService.cpp [new file with mode: 0644]
projects/GDE_API_CPP/api/src/ProfilesService.hpp [new file with mode: 0644]
projects/GDE_API_CPP/api/tests/ProfilesTest.cpp [new file with mode: 0644]
projects/GDE_API_CPP/api/tests/ProfilesTest.hpp [new file with mode: 0644]

index 924b682d29ef042bc36b3056b6fc9c02b419d52e..95bbe7d206bb650abbdbd674623b01b2f96d7069 100644 (file)
@@ -123,7 +123,7 @@ gde::AttributesService::createAttributeGroup(const AttributeGroup& attributeGrou
   {
     Poco::JSON::Object::Ptr object = JsonFormatter::parse(crto.getData());
     int id = JsonFormatter::extract<int>(object, "id");
-    std::vector<gde::Attribute> attributes = JsonFormatter::extractVector(object, "attributeCollection");
+    std::vector<gde::Attribute> attributes = JsonFormatter::extractVector<gde::Attribute>(object, "attributeCollection");
     return gde::AttributeGroup(id, attributes);
   }
 }
@@ -154,7 +154,7 @@ gde::AttributesService::updateAttributeGroup(const gde::AttributeGroup& attribut
   {
     Poco::JSON::Object::Ptr object = JsonFormatter::parse(crto.getData());
     int id = JsonFormatter::extract<int>(object, "id");
-    std::vector<Attribute> attributes = JsonFormatter::extractVector(object, "attributeCollection");
+    std::vector<Attribute> attributes = JsonFormatter::extractVector<gde::Attribute>(object, "attributeCollection");
     return gde::AttributeGroup(id, attributes);
   }
 }
@@ -173,7 +173,7 @@ gde::AttributesService::readAttributeGroup(int attributeGroupId)
   {
     Poco::JSON::Object::Ptr object = JsonFormatter::parse(crto.getData());
     int id = JsonFormatter::extract<int>(object, "id");
-    std::vector<Attribute> attributes = JsonFormatter::extractVector(object, "attributeCollection");
+    std::vector<Attribute> attributes = JsonFormatter::extractVector<gde::Attribute>(object, "attributeCollection");
     return gde::AttributeGroup(id, attributes);
   }
 }
index f8e038aba5ed157fa7728cb9d5e306e4c4e698cf..e80baf66a161e7940a6312fcd1651ec219f120d6 100644 (file)
@@ -25,6 +25,8 @@ SET(gde_api_cpp_HEADERS
   Group.hpp
   HttpConnection.hpp
   JsonFormatter.hpp
+  Profile.hpp
+  ProfileAttribute.hpp
   Study.hpp
   StudyService.hpp
   User.hpp
@@ -40,6 +42,8 @@ SET(gde_api_cpp_SOURCES
   GDESession.cpp
   HttpConnection.cpp
   JsonFormatter.cpp
+  ProfileAttribute.cpp
+  ProfilesService.cpp
   StudyService.cpp
   UserService.cpp
 )
index 0376c7b244e147b6da7a17869a47529e686ce375..7abdf9dc2f9aae3b4e2a343944225b8dfa3d5e0d 100644 (file)
@@ -2,6 +2,7 @@
 #include "UserService.hpp"
 #include "StudyService.hpp"
 #include "AttributesService.hpp"
+#include "ProfilesService.hpp"
 
 std::string
 gde::GDESession::getServiceURI(const std::string& serviceName) const
@@ -137,3 +138,52 @@ gde::GDESession::readAttributeGroup(int attributeGroupId)
 {
   return gde::AttributesService(*this).readAttributeGroup(attributeGroupId);
 }
+
+    /* ProfilesService */
+const gde::Profile
+gde::GDESession::createProfile(const gde::Profile& profile)
+{
+  return gde::ProfilesService(*this).createProfile(profile);
+}
+
+bool
+gde::GDESession::deleteProfile(const gde::Profile& profile)
+{
+  return gde::ProfilesService(*this).deleteProfile(profile);
+}
+
+const gde::Profile
+gde::GDESession::readProfile(int profileId)
+{
+  return gde::ProfilesService(*this).readProfile(profileId);
+}
+
+const gde::Profile
+gde::GDESession::updateProfile(const gde::Profile& profile)
+{
+  return gde::ProfilesService(*this).updateProfile(profile);
+}
+
+const gde::ProfileAttribute
+gde::GDESession::createProfileAttribute(const std::string& name, const std::string& type, int profileId, bool mandatory)
+{
+  return gde::ProfilesService(*this).createProfileAttribute(name, type, profileId, mandatory);
+}
+
+bool
+gde::GDESession::deleteProfileAttribute(const gde::ProfileAttribute& attribute)
+{
+  return gde::ProfilesService(*this).deleteProfileAttribute(attribute);
+}
+
+const gde::ProfileAttribute
+gde::GDESession::readProfileAttribute(int attributeId)
+{
+  return gde::ProfilesService(*this).readProfileAttribute(attributeId);
+}
+
+const gde::ProfileAttribute
+gde::GDESession::updateProfileAttribute(const gde::ProfileAttribute& attribute)
+{
+  return gde::ProfilesService(*this).updateProfileAttribute(attribute);
+}
index 9571ad0c0eb2a9e6e494b578bffcbd524dd50d4a..0ed8c347c61e0ba84a34d0a5325241ea70bc12fd 100644 (file)
@@ -7,6 +7,8 @@
 #include "Study.hpp"
 #include "Attribute.hpp"
 #include "AttributeGroup.hpp"
+#include "Profile.hpp"
+#include "ProfileAttribute.hpp"
 
 #include <string>
 #include <vector>
@@ -65,6 +67,18 @@ namespace gde {
     const AttributeGroup updateAttributeGroup(const AttributeGroup&);
     const AttributeGroup readAttributeGroup(int);
 
+    /* ProfilesService */
+
+    const Profile createProfile(const Profile&);
+    bool deleteProfile(const Profile&);
+    const Profile readProfile(int);
+    const Profile updateProfile(const Profile&);
+
+    const ProfileAttribute createProfileAttribute(const std::string& name, const std::string& type, int profileId, bool mandatory);
+    bool deleteProfileAttribute(const ProfileAttribute&);
+    const ProfileAttribute readProfileAttribute(int);
+    const ProfileAttribute updateProfileAttribute(const ProfileAttribute&);
+
   private:
     std::string _serverAddress;
     Credentials _credentials;
index 8f17dfadfaebc7592f2f4a0785a2b62973d8c5f7..c30a7b6e88882165f3e5fa785b01b2c0c41e66a8 100644 (file)
@@ -1,4 +1,6 @@
 #include "JsonFormatter.hpp"
+#include "Attribute.hpp"
+#include "ProfileAttribute.hpp"
 
 #include <Poco/JSON/Parser.h>
 #include <Poco/DateTime.h>
@@ -29,23 +31,24 @@ gde::JsonFormatter::extract(Poco::JSON::Object::Ptr object, const std::string& v
   }
 }
 
-std::vector<gde::Attribute>
+template <typename T>
+std::vector<T>
 gde::JsonFormatter::extractVector(Poco::JSON::Object::Ptr object, const std::string& varName)
 {
   try {
-    std::vector<gde::Attribute> result;
+    std::vector<T> result;
     Poco::JSON::Array::Ptr array = object->getArray(varName);
     typedef Poco::JSON::Array::ConstIterator ArrayIterator;
 
     for (ArrayIterator itr = array->begin(); itr != array->end(); ++itr) {
       std::string json = itr->toString(); // { var:value, ... }
-      result.push_back(Attribute::fromJson(json));
+      result.push_back(T::fromJson(json));
     }
 
     return result;
   } catch (Poco::InvalidAccessException& e) {
     // This exception is raised if Var v is empty
-    return std::vector<gde::Attribute>();
+    return std::vector<T>();
   }
 }
 
@@ -99,3 +102,6 @@ gde::JsonFormatter::format(const std::string txt, bool value)
 template int gde::JsonFormatter::extract<int>(Poco::JSON::Object::Ptr, const std::string&);
 template bool gde::JsonFormatter::extract<bool>(Poco::JSON::Object::Ptr, const std::string&);
 template std::string gde::JsonFormatter::extract<std::string>(Poco::JSON::Object::Ptr, const std::string&);
+
+template std::vector<gde::Attribute> gde::JsonFormatter::extractVector<gde::Attribute>(Poco::JSON::Object::Ptr, const std::string&);
+template std::vector<gde::ProfileAttribute> gde::JsonFormatter::extractVector<gde::ProfileAttribute>(Poco::JSON::Object::Ptr, const std::string&);
index fcafbecf83e0a3cbdfca576eb9f3c7f14a8ea336..5b082c4a4a976a4402130f9fd962b263c4154245 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef GDE_JSON_FORMATTER_HPP
 #define GDE_JSON_FORMATTER_HPP
 
-#include "Attribute.hpp"
-
 #include <string>
 #include <vector>
 
@@ -19,7 +17,7 @@ namespace gde {
     template <typename T> static T extract(Poco::JSON::Object::Ptr, const std::string&);
     static Poco::Timestamp extract(Poco::JSON::Object::Ptr, const std::string&);
 
-    static std::vector<gde::Attribute> extractVector(Poco::JSON::Object::Ptr, const std::string&);
+    template <typename T> static std::vector<T> extractVector(Poco::JSON::Object::Ptr, const std::string&);
 
     static std::string stringify(const Poco::JSON::Object&);
 
diff --git a/projects/GDE_API_CPP/api/src/Profile.hpp b/projects/GDE_API_CPP/api/src/Profile.hpp
new file mode 100644 (file)
index 0000000..fa23eed
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef GDE_PROFILE_HPP
+#define GDE_PROFILE_HPP
+
+#include "ProfileAttribute.hpp"
+
+#include <string>
+#include <vector>
+
+namespace gde {
+
+  class Profile {
+    friend class ProfilesService;
+    friend class GDESession;
+
+  public:
+    Profile(const std::string& name, const std::vector<ProfileAttribute>& attributes=std::vector<ProfileAttribute>())
+      : _id(0), _name(name), _attributes(attributes)
+    {}
+    ~Profile() {}
+
+    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 const std::vector<ProfileAttribute>& getAttributes() const { return _attributes; }
+    inline void setAttributes(const std::vector<ProfileAttribute>& attributes) { this->_attributes = attributes; }
+
+  private:
+    Profile(int id, const std::string& name, const std::vector<ProfileAttribute>& attributes)
+      : _id(id), _name(name), _attributes(attributes)
+    {}
+    //Profile(const Profile&); // non copyable
+    //Profile& operator=(const Profile&); // non copyable
+
+  private:
+    int _id;
+    std::string _name;
+    std::vector<ProfileAttribute> _attributes;
+  };
+
+};
+
+#endif
diff --git a/projects/GDE_API_CPP/api/src/ProfileAttribute.cpp b/projects/GDE_API_CPP/api/src/ProfileAttribute.cpp
new file mode 100644 (file)
index 0000000..fc7b9f7
--- /dev/null
@@ -0,0 +1,29 @@
+#include "ProfileAttribute.hpp"
+#include "JsonFormatter.hpp"
+
+const std::string
+gde::ProfileAttribute::toJson() const
+{
+  std::string json = "{";
+  json += JsonFormatter::format("\"id\":", getId());
+  json += JsonFormatter::format(",\"name\":", getName());
+  json += JsonFormatter::format(",\"type\":", getType());
+  json += JsonFormatter::format(",\"profileId\":", getProfileId());
+  json += JsonFormatter::format(",\"mandatory\":", getMandatory());
+  json += "}";
+  return json;
+}
+
+gde::ProfileAttribute
+gde::ProfileAttribute::fromJson(const std::string& json)
+{
+  Poco::JSON::Object::Ptr object = JsonFormatter::parse(json);
+
+  int id = JsonFormatter::extract<int>(object, "id");
+  std::string name = JsonFormatter::extract<std::string>(object, "name");
+  std::string type = JsonFormatter::extract<std::string>(object, "type");
+  int profileId = JsonFormatter::extract<int>(object, "profileId");
+  bool mandatory = JsonFormatter::extract<bool>(object, "mandatory");
+
+  return gde::ProfileAttribute(id, name, type, profileId, mandatory);
+}
diff --git a/projects/GDE_API_CPP/api/src/ProfileAttribute.hpp b/projects/GDE_API_CPP/api/src/ProfileAttribute.hpp
new file mode 100644 (file)
index 0000000..46e55ad
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef GDE_PROFILE_ATTRIBUTE_HPP
+#define GDE_PROFILE_ATTRIBUTE_HPP
+
+#include <string>
+
+namespace gde {
+
+  class ProfileAttribute {
+    friend class ProfilesService;
+    friend class GDESession;
+
+  public:
+    ProfileAttribute(const std::string& name, const std::string& type, bool mandatory)
+      : _id(0), _name(name), _type(type), _profileId(0), _mandatory(mandatory)
+    {}
+    ~ProfileAttribute() {}
+
+    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 getType() const { return _type; }
+    inline void setType(const std::string& type) { this->_type = type; }
+
+    inline int getProfileId() const { return _profileId; }
+    inline void setProfileId(int profileId) { this->_profileId = profileId; }
+
+    inline bool getMandatory() const { return _mandatory; }
+    inline void setMandatory(bool mandatory) { this->_mandatory = mandatory; }
+
+    const std::string toJson() const;
+    static ProfileAttribute fromJson(const std::string& json);
+
+  private:
+    ProfileAttribute(int id=0, const std::string& name="", const std::string& type="", int profileId=0, bool mandatory=false)
+      : _id(id), _name(name), _type(type), _profileId(profileId), _mandatory(mandatory)
+    {}
+    //ProfileAttribute(const ProfileAttribute&); // non copyable
+    //ProfileAttribute& operator=(const ProfileAttribute&); // non copyable
+
+  private:
+    int _id;
+    std::string _name;
+    std::string _type;
+    int _profileId;
+    bool _mandatory;
+  };
+
+};
+
+#endif
diff --git a/projects/GDE_API_CPP/api/src/ProfilesService.cpp b/projects/GDE_API_CPP/api/src/ProfilesService.cpp
new file mode 100644 (file)
index 0000000..e91912a
--- /dev/null
@@ -0,0 +1,210 @@
+#include "ProfilesService.hpp"
+#include "HttpConnection.hpp"
+#include "CommandTO.hpp"
+#include "CommandResultTO.hpp"
+#include "JsonFormatter.hpp"
+#include "Credentials.hpp"
+
+#include <vector>
+#include <typeinfo>
+
+/*
+ * WARNING: keep enum values synchronized to WEB API (AttributesService)
+ */
+enum {
+  CREATE_PROFILE = 1,
+  DELETE_PROFILE,
+  READ_PROFILE,
+  UPDATE_PROFILE,
+  CREATE_PROFILE_ATTRIBUTE,
+  DELETE_PROFILE_ATTRIBUTE,
+  READ_PROFILE_ATTRIBUTE,
+  UPDATE_PROFILE_ATTRIBUTE
+};
+
+std::string gde::ProfilesService::_servletName = "ProfilesService";
+
+std::string
+_buildAttributesJsonString(const gde::Profile& profile)
+{
+  // Solution here is not very smart. Have tried using Poco to stringify attributes,
+  // but stringification is too recursive, for example it produces:
+  // "attributes":"[ { \"id\" : 0, \"name\" : \"myAttribute\",...
+  // instead of:
+  // "attributes":[{"id":0,"name":"myAttribute",...
+  const std::vector<gde::ProfileAttribute>& attributes = profile.getAttributes();
+  std::string data = "{";
+  data += gde::JsonFormatter::format("\"id\":", profile.getId());
+  data += gde::JsonFormatter::format(", \"name\":", profile.getName());
+  data += ", \"attributes\":[";
+  for (std::vector<gde::ProfileAttribute>::const_iterator itr = attributes.begin(); itr != attributes.end(); ++itr) {
+    if (itr != attributes.begin())
+      data += ",";
+    data += itr->toJson();
+  }
+  data += "]}";
+  return data;
+}
+
+const gde::Profile
+gde::ProfilesService::createProfile(const gde::Profile& profile)
+{
+  std::string data = _buildAttributesJsonString(profile);
+  CommandTO cto(CREATE_PROFILE, data);
+
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+
+  // build Profile 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::vector<gde::ProfileAttribute> attributes = JsonFormatter::extractVector<gde::ProfileAttribute>(object, "attributes");
+    return gde::Profile(id, name, attributes);
+  }
+}
+
+bool
+gde::ProfilesService::deleteProfile(const gde::Profile& profile)
+{
+  CommandTO cto(DELETE_PROFILE);
+  cto.setParameter("profileId", profile.getId());
+
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+  return crto.getCode() == CommandResultTO::OK;
+}
+
+const gde::Profile
+gde::ProfilesService::readProfile(int profileId)
+{
+  CommandTO cto(READ_PROFILE);
+  cto.setParameter("profileId", profileId);
+
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+
+  // build Profile 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::vector<gde::ProfileAttribute> attributes = JsonFormatter::extractVector<gde::ProfileAttribute>(object, "attributes");
+    return gde::Profile(id, name, attributes);
+  }
+}
+
+const gde::Profile
+gde::ProfilesService::updateProfile(const gde::Profile& profile)
+{
+  std::string data = _buildAttributesJsonString(profile);
+  CommandTO cto(UPDATE_PROFILE, data);
+
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+
+  // build Profile 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::vector<gde::ProfileAttribute> attributes = JsonFormatter::extractVector<gde::ProfileAttribute>(object, "attributes");
+    return gde::Profile(id, name, attributes);
+  }
+}
+
+const gde::ProfileAttribute
+gde::ProfilesService::createProfileAttribute(const std::string& name, const std::string& type, int profileId, bool mandatory)
+{
+  // build JSON string for CommandTO data
+  Poco::JSON::Object obj;
+  obj.set("name", Poco::Dynamic::Var(name));
+  obj.set("type", Poco::Dynamic::Var(type));
+  obj.set("profileId", Poco::Dynamic::Var(profileId));
+  obj.set("mandatory", Poco::Dynamic::Var(mandatory));
+  std::string data = JsonFormatter::stringify(obj);
+
+  CommandTO cto(CREATE_PROFILE_ATTRIBUTE, data);
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+
+  // build ProfileAttribute 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 type = JsonFormatter::extract<std::string>(object, "type");
+    int profileId = JsonFormatter::extract<int>(object, "profileId");
+    bool mandatory = JsonFormatter::extract<bool>(object, "mandatory");
+    return gde::ProfileAttribute(id, name, type, profileId, mandatory);
+  }
+}
+
+bool
+gde::ProfilesService::deleteProfileAttribute(const gde::ProfileAttribute& attribute)
+{
+  CommandTO cto(DELETE_PROFILE_ATTRIBUTE);
+  cto.setParameter("profileAttributeId", attribute.getId());
+
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+  return crto.getCode() == CommandResultTO::OK;
+}
+
+const gde::ProfileAttribute
+gde::ProfilesService::readProfileAttribute(int attributeId)
+{
+  CommandTO cto(READ_PROFILE_ATTRIBUTE);
+  cto.setParameter("profileAttributeId", attributeId);
+
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+
+  // build ProfileAttribute 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 type = JsonFormatter::extract<std::string>(object, "type");
+    int profileId = JsonFormatter::extract<int>(object, "profileId");
+    bool mandatory = JsonFormatter::extract<bool>(object, "mandatory");
+    return gde::ProfileAttribute(id, name, type, profileId, mandatory);
+  }
+}
+
+const gde::ProfileAttribute
+gde::ProfilesService::updateProfileAttribute(const gde::ProfileAttribute& attribute)
+{
+  // build JSON string for CommandTO data
+  Poco::JSON::Object obj;
+  obj.set("id", Poco::Dynamic::Var(attribute.getId()));
+  obj.set("name", Poco::Dynamic::Var(attribute.getName()));
+  obj.set("type", Poco::Dynamic::Var(attribute.getType()));
+  obj.set("profileId", Poco::Dynamic::Var(attribute.getProfileId()));
+  obj.set("mandatory", Poco::Dynamic::Var(attribute.getMandatory()));
+  std::string data = JsonFormatter::stringify(obj);
+  CommandTO cto(UPDATE_PROFILE_ATTRIBUTE, data);
+
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+
+  // build ProfileAttribute 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 type = JsonFormatter::extract<std::string>(object, "type");
+    int profileId = JsonFormatter::extract<int>(object, "profileId");
+    bool mandatory = JsonFormatter::extract<bool>(object, "mandatory");
+    return gde::ProfileAttribute(id, name, type, profileId, mandatory);
+  }
+}
diff --git a/projects/GDE_API_CPP/api/src/ProfilesService.hpp b/projects/GDE_API_CPP/api/src/ProfilesService.hpp
new file mode 100644 (file)
index 0000000..30be4fb
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef GDE_PROFILES_SERVICE_HPP
+#define GDE_PROFILES_SERVICE_HPP
+
+#include "Profile.hpp"
+#include "ProfileAttribute.hpp"
+#include "GDESession.hpp"
+
+#include <string>
+#include <vector>
+
+namespace gde {
+
+  class ProfilesService {
+    friend class GDESession;
+
+  public:
+    const Profile createProfile(const Profile&);
+    bool deleteProfile(const Profile&);
+    const Profile readProfile(int);
+    const Profile updateProfile(const Profile&);
+
+    const ProfileAttribute createProfileAttribute(const std::string& name, const std::string& type, int profileId, bool mandatory);
+    bool deleteProfileAttribute(const ProfileAttribute&);
+    const ProfileAttribute readProfileAttribute(int);
+    const ProfileAttribute updateProfileAttribute(const ProfileAttribute&);
+
+  private:
+    ProfilesService(const GDESession& session) : _session(session) {}
+    ~ProfilesService() {}
+    ProfilesService(const ProfilesService&); // non copyable
+    ProfilesService& operator=(const ProfilesService&); // non copyable
+
+  private:
+    static std::string _servletName;
+    const GDESession& _session;
+
+  };
+
+};
+
+#endif
diff --git a/projects/GDE_API_CPP/api/tests/ProfilesTest.cpp b/projects/GDE_API_CPP/api/tests/ProfilesTest.cpp
new file mode 100644 (file)
index 0000000..178a2d1
--- /dev/null
@@ -0,0 +1,126 @@
+#include <TestUtilities.hpp>
+#include <Profile.hpp>
+#include <GDESession.hpp>
+#include <ProfilesTest.hpp>
+
+void
+ProfilesTest::testCreateDeleteProfile()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  gde::Profile myProfile("myProfile");
+  CPPUNIT_ASSERT(myProfile.getId() == 0);
+  gde::Profile profile = session.createProfile(myProfile);
+  CPPUNIT_ASSERT(profile.getId() > 0);
+  CPPUNIT_ASSERT(profile.getName() == myProfile.getName());
+
+  CPPUNIT_ASSERT(session.deleteProfile(profile));
+}
+
+void
+ProfilesTest::testReadProfile()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  gde::Profile myProfile("myProfile");
+  CPPUNIT_ASSERT(myProfile.getId() == 0);
+  gde::Profile profile = session.createProfile(myProfile);
+  CPPUNIT_ASSERT(profile.getId() > 0);
+
+  {
+    const gde::Profile& prf = session.readProfile(profile.getId());
+    CPPUNIT_ASSERT(prf.getName() == myProfile.getName());
+    CPPUNIT_ASSERT(prf.getId() > 0);
+  }
+
+  CPPUNIT_ASSERT(session.deleteProfile(profile));
+}
+
+void
+ProfilesTest::testUpdateProfile()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  gde::Profile myProfile("myProfile");
+  CPPUNIT_ASSERT(myProfile.getId() == 0);
+  gde::Profile profile = session.createProfile(myProfile);
+  CPPUNIT_ASSERT(profile.getId() > 0);
+  CPPUNIT_ASSERT(profile.getName() == "myProfile");
+  profile.setName("myProfile2");
+
+  {
+    const gde::Profile& prf = session.updateProfile(profile);
+    CPPUNIT_ASSERT(prf.getName() == profile.getName());
+    CPPUNIT_ASSERT(prf.getId() == profile.getId());
+  }
+
+  CPPUNIT_ASSERT(session.deleteProfile(profile));
+}
+
+void
+ProfilesTest::testCreateDeleteProfileAttribute()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  gde::Profile profile = session.createProfile(gde::Profile("myProfile"));
+  CPPUNIT_ASSERT(profile.getId() > 0);
+
+  gde::ProfileAttribute myAttribute = session.createProfileAttribute("myAttribute", "float", profile.getId(), true);
+
+  CPPUNIT_ASSERT(myAttribute.getId() > 0);
+  CPPUNIT_ASSERT(myAttribute.getName() == "myAttribute");
+  CPPUNIT_ASSERT(myAttribute.getType() == "float");
+  CPPUNIT_ASSERT(myAttribute.getMandatory());
+
+  CPPUNIT_ASSERT(session.deleteProfile(profile));
+}
+
+void
+ProfilesTest::testUpdateProfileAttribute()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  gde::Profile profile = session.createProfile(gde::Profile("myProfile"));
+  CPPUNIT_ASSERT(profile.getId() > 0);
+
+  gde::ProfileAttribute myAttribute = session.createProfileAttribute("myAttribute", "float", profile.getId(), true);
+
+  CPPUNIT_ASSERT(myAttribute.getId() > 0);
+  CPPUNIT_ASSERT(myAttribute.getName() == "myAttribute");
+  CPPUNIT_ASSERT(myAttribute.getType() == "float");
+  CPPUNIT_ASSERT(myAttribute.getMandatory());
+
+  myAttribute.setType("std::string");
+
+  {
+    const gde::ProfileAttribute& attr = session.updateProfileAttribute(myAttribute);
+    CPPUNIT_ASSERT(attr.getId() == myAttribute.getId());
+    CPPUNIT_ASSERT(attr.getName() == "myAttribute");
+    CPPUNIT_ASSERT(attr.getType() == "std::string");
+    CPPUNIT_ASSERT(attr.getMandatory());
+  }
+
+  CPPUNIT_ASSERT(session.deleteProfile(profile));
+}
+
+void
+ProfilesTest::testReadProfileAttribute()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  gde::Profile profile = session.createProfile(gde::Profile("myProfile"));
+  CPPUNIT_ASSERT(profile.getId() > 0);
+
+  gde::ProfileAttribute myAttribute = session.createProfileAttribute("myAttribute", "float", profile.getId(), true);
+  CPPUNIT_ASSERT(myAttribute.getId() > 0);
+
+  {
+    const gde::ProfileAttribute& attr = session.readProfileAttribute(myAttribute.getId());
+    CPPUNIT_ASSERT(attr.getId() == myAttribute.getId());
+    CPPUNIT_ASSERT(attr.getName() == myAttribute.getName());
+    CPPUNIT_ASSERT(attr.getType() == myAttribute.getType());
+    CPPUNIT_ASSERT(attr.getMandatory() == myAttribute.getMandatory());
+  }
+
+  CPPUNIT_ASSERT(session.deleteProfile(profile));
+}
diff --git a/projects/GDE_API_CPP/api/tests/ProfilesTest.hpp b/projects/GDE_API_CPP/api/tests/ProfilesTest.hpp
new file mode 100644 (file)
index 0000000..c3bc9d6
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef GDE_PROFILES_TEST_HPP
+#define GDE_PROFILES_TEST_HPP
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class ProfilesTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE(ProfilesTest);
+  CPPUNIT_TEST(testCreateDeleteProfile);
+  CPPUNIT_TEST(testReadProfile);
+  CPPUNIT_TEST(testUpdateProfile);
+
+  CPPUNIT_TEST(testCreateDeleteProfileAttribute);
+  CPPUNIT_TEST(testUpdateProfileAttribute);
+  CPPUNIT_TEST(testReadProfileAttribute);
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void testCreateDeleteProfile();
+  void testReadProfile();
+  void testUpdateProfile();
+
+  void testCreateDeleteProfileAttribute();
+  void testUpdateProfileAttribute();
+  void testReadProfileAttribute();
+};
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ProfilesTest, "ProfilesTest");
+
+#endif