Salome HOME
add StudyService
authorCédric Aguerre <cedric.aguerre@edf.fr>
Thu, 27 Aug 2015 13:48:07 +0000 (15:48 +0200)
committerCédric Aguerre <cedric.aguerre@edf.fr>
Thu, 27 Aug 2015 13:48:07 +0000 (15:48 +0200)
12 files changed:
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/Study.hpp [new file with mode: 0644]
projects/GDE_API_CPP/api/src/StudyService.cpp [new file with mode: 0644]
projects/GDE_API_CPP/api/src/StudyService.hpp [new file with mode: 0644]
projects/GDE_API_CPP/api/tests/StudyTest.cpp [new file with mode: 0644]
projects/GDE_API_CPP/api/tests/StudyTest.hpp [new file with mode: 0644]
projects/GDE_API_CPP/api/tests/TestUtilities.hpp
projects/GDE_App/GDE-war/src/java/com/edf/gde/services/BaseService.java

index 10d44a4d9c3f90031201203b9525c0b64942fdc2..477a3e44128ddab2497b414dfa445014cd343796 100644 (file)
@@ -22,6 +22,8 @@ SET(gde_api_cpp_HEADERS
   Group.hpp
   HttpConnection.hpp
   JsonFormatter.hpp
+  Study.hpp
+  StudyService.hpp
   User.hpp
   UserService.hpp
 )
@@ -33,6 +35,7 @@ SET(gde_api_cpp_SOURCES
   GDESession.cpp
   HttpConnection.cpp
   JsonFormatter.cpp
+  StudyService.cpp
   UserService.cpp
 )
 
index 81956e8a3ed735bac90d904d2c1564c84dcacb36..eadcb52c2fdae666d9de39dc01eb718d2435fad3 100644 (file)
@@ -1,5 +1,6 @@
 #include "GDESession.hpp"
 #include "UserService.hpp"
+#include "StudyService.hpp"
 
 std::string
 gde::GDESession::getServiceURI(const std::string& serviceName) const
@@ -16,6 +17,8 @@ gde::GDESession::getServiceURI(const std::string& serviceName) const
   return uri;
 }
 
+/* UserService */
+
 const gde::User
 gde::GDESession::createUser(const std::string& name, const std::string& password)
 {
@@ -63,3 +66,29 @@ gde::GDESession::removeFromGroup(const gde::Group& group, const gde::User& user)
 {
   return gde::UserService(*this).removeFromGroup(group, user);
 }
+
+/* StudyService */
+
+const gde::Study
+gde::GDESession::createStudy(const std::string& name)
+{
+  return gde::StudyService(*this).createStudy(name);
+}
+
+bool
+gde::GDESession::deleteStudy(const gde::Study& study)
+{
+  return gde::StudyService(*this).deleteStudy(study);
+}
+
+bool
+gde::GDESession::setStudyState(const gde::Study& study, int lock)
+{
+  return gde::StudyService(*this).setStudyState(study, lock);
+}
+
+const gde::Study
+gde::GDESession::readStudy(int studyId)
+{
+  return gde::StudyService(*this).readStudy(studyId);
+}
index e07efead0a788d8ddb7ccb8360b76fdb02b16542..c8abbb22223a079a335c80273dd786b243d63362 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef GDE_SESSION_HPP
 #define GDE_SESSION_HPP
 
+#include "Credentials.hpp"
 #include "User.hpp"
 #include "Group.hpp"
-#include "Credentials.hpp"
+#include "Study.hpp"
 
 #include <string>
 
@@ -29,6 +30,8 @@ namespace gde {
 
     std::string getServiceURI(const std::string& serviceName) const;
 
+    /* UserService */
+
     const User createUser(const std::string& name, const std::string& password);
     bool deleteUser(const User&);
     const User findUser(const std::string& name);
@@ -40,6 +43,14 @@ namespace gde {
     bool addToGroup(const Group&, const User&);
     bool removeFromGroup(const Group&, const User&);
 
+    /* StudyService */
+
+    const Study createStudy(const std::string& name);
+    bool deleteStudy(const Study&);
+
+    bool setStudyState(const Study&, int);
+    const Study readStudy(int);
+
   private:
     std::string _serverAddress;
     Credentials _credentials;
index 33d64511e65ad4fe4abd25e33cce0bb322320fef..8e3dfd036e8d684454c84b8b3d575313e4769cd8 100644 (file)
@@ -1,6 +1,8 @@
 #include "JsonFormatter.hpp"
 
 #include <Poco/JSON/Parser.h>
+#include <Poco/DateTime.h>
+#include <Poco/DateTimeParser.h>
 
 #include <sstream>
 
@@ -27,6 +29,23 @@ gde::JsonFormatter::extract(Poco::JSON::Object::Ptr object, const std::string& v
   }
 }
 
+Poco::Timestamp
+gde::JsonFormatter::extract(Poco::JSON::Object::Ptr object, const std::string& varName)
+{
+  try {
+    Poco::Dynamic::Var v = object->get(varName);
+    std::string formattedDate = v.convert<std::string>();
+
+    Poco::DateTime dt;
+    int tzd;
+    Poco::DateTimeParser::parse(formattedDate, dt, tzd);
+    return dt.timestamp();
+  } catch (Poco::InvalidAccessException& e) {
+    // This exception is raised if Var v is empty
+    return Poco::Timestamp(); // Return current time; not so good, should return nil object
+  }
+}
+
 std::string
 gde::JsonFormatter::stringify(const Poco::JSON::Object& object) {
   std::ostringstream jsonStream;
@@ -35,5 +54,6 @@ gde::JsonFormatter::stringify(const Poco::JSON::Object& object) {
 }
 
 // Declare methods for the supported template type parameters
-template int gde::JsonFormatter::extract<int>(Poco::JSON::Object::Ptr object, const std::string& varName);
-template std::string gde::JsonFormatter::extract<std::string>(Poco::JSON::Object::Ptr object, const std::string& varName);
+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&);
index 395bbcb8dbb2cdbed904e7eefef208c8fe083388..96856cf224a2dc17bdd7100b758ecf6349661f15 100644 (file)
@@ -1,9 +1,10 @@
-#ifndef JSON_FORMATTER_HPP
-#define JSON_FORMATTER_HPP
+#ifndef GDE_JSON_FORMATTER_HPP
+#define GDE_JSON_FORMATTER_HPP
 
 #include <string>
 
 #include <Poco/JSON/Object.h>
+#include <Poco/Timestamp.h>
 
 namespace gde {
 
@@ -11,7 +12,9 @@ namespace gde {
   public:
 
     static Poco::JSON::Object::Ptr parse(const std::string&);
+
     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::string stringify(const Poco::JSON::Object&);
   };
diff --git a/projects/GDE_API_CPP/api/src/Study.hpp b/projects/GDE_API_CPP/api/src/Study.hpp
new file mode 100644 (file)
index 0000000..1085191
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef GDE_STUDY_HPP
+#define GDE_STUDY_HPP
+
+#include <Poco/Timestamp.h>
+
+#include <string>
+
+namespace gde {
+
+  class Study {
+    friend class StudyService;
+    friend class GDESession;
+
+  public:
+    ~Study() {}
+
+    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 Poco::Timestamp getCreationDate() const { return _creationDate; }
+    inline void setCreationDate(const Poco::Timestamp& creationDate) { this->_creationDate = creationDate; }
+
+    inline Poco::Timestamp getUpdateDate() const { return _updateDate; }
+    inline void setUpdateDate(const Poco::Timestamp& updateDate) { this->_updateDate = updateDate; }
+
+    inline bool getValid() const { return _valid; }
+    inline void setValid(bool valid) { this->_valid = valid; }
+
+    inline bool getDeleted() const { return _deleted; }
+    inline void setDeleted(bool deleted) { this->_deleted = deleted; }
+
+    inline Poco::Timestamp getDeletionDate() const { return _deletionDate; }
+    inline void setDeletionDate(const Poco::Timestamp& deletionDate) { this->_deletionDate = deletionDate; }
+
+    inline int getAttributeGroupId() const { return _attributeGroupId; }
+    inline void setAttributeGroupId(int attributeGroupId) { this->_attributeGroupId = attributeGroupId; }
+
+    inline int getProfileId() const { return _profileId; }
+    inline void setProfileId(int profileId) { this->_profileId = profileId; }
+
+    inline bool getLocked() const { return _locked; }
+    inline void setLocked(bool locked) { this->_locked = locked; }
+
+    inline int getLockOwner() const { return _lockOwner; }
+    inline void setLockOwner(int lockOwner) { this->_lockOwner = lockOwner; }
+
+  private:
+    Study(int id=-1,
+          const std::string& name="",
+          const Poco::Timestamp& creationDate=Poco::Timestamp(),
+          const Poco::Timestamp& updateDate=Poco::Timestamp(),
+          bool valid = false,
+          bool deleted = false,
+          const Poco::Timestamp& deletionDate=Poco::Timestamp(),
+          int attributeGroupId=-1,
+          int profileId=-1,
+          bool locked = false,
+          int lockOwner=-1
+          )
+      : _id(id), _name(name), _creationDate(creationDate), _updateDate(updateDate), _valid(valid), _deleted(deleted), _deletionDate(deletionDate), _attributeGroupId(attributeGroupId), _profileId(profileId), _locked(locked), _lockOwner(lockOwner)
+    {}
+    Study(const Study&); // non copyable
+    Study& operator=(const Study&); // non copyable
+
+  private:
+    int _id;
+    std::string _name;
+    Poco::Timestamp _creationDate;
+    Poco::Timestamp _updateDate;
+    bool _valid;
+    bool _deleted;
+    Poco::Timestamp _deletionDate;
+    int _attributeGroupId;
+    int _profileId;
+    bool _locked;
+    int _lockOwner;
+  };
+
+};
+
+#endif
diff --git a/projects/GDE_API_CPP/api/src/StudyService.cpp b/projects/GDE_API_CPP/api/src/StudyService.cpp
new file mode 100644 (file)
index 0000000..7be2f74
--- /dev/null
@@ -0,0 +1,110 @@
+#include "StudyService.hpp"
+#include "HttpConnection.hpp"
+#include "CommandTO.hpp"
+#include "CommandResultTO.hpp"
+#include "JsonFormatter.hpp"
+#include "Credentials.hpp"
+
+#include <Poco/DateTimeFormatter.h>
+#include <Poco/Timestamp.h>
+#include <Poco/DateTimeFormat.h>
+
+/*
+ * WARNING: keep enum values synchronized to WEB API (StudyService)
+ */
+enum {
+  CREATE_STUDY = 1,
+  SET_STUDY_SATE,
+  READ_STUDY,
+  DELETE_STUDY
+};
+
+std::string gde::StudyService::_servletName = "StudyService";
+
+const gde::Study
+gde::StudyService::createStudy(const std::string& name)
+{
+  // build JSON string for CommandTO data
+  Poco::JSON::Object obj;
+  obj.set("name", Poco::Dynamic::Var(name));
+  std::string creationDate = Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::SORTABLE_FORMAT);
+  obj.set("creationDate", Poco::Dynamic::Var(creationDate));
+  std::string data = JsonFormatter::stringify(obj);
+
+  CommandTO cto(CREATE_STUDY, data);
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+
+  // build Study 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");
+    Poco::Timestamp creationDate = JsonFormatter::extract(object, "creationDate");
+    Poco::Timestamp updateDate = JsonFormatter::extract(object, "updateDate");
+    bool valid = JsonFormatter::extract<bool>(object, "valid");
+    bool deleted = JsonFormatter::extract<bool>(object, "deleted");
+    Poco::Timestamp deletionDate = JsonFormatter::extract(object, "deletionDate");
+    int attributeGroupId = JsonFormatter::extract<int>(object, "attributeGroupId");
+    int profileId = JsonFormatter::extract<int>(object, "profileId");
+    bool locked = JsonFormatter::extract<bool>(object, "locked");
+    int lockOwner = JsonFormatter::extract<int>(object, "lockOwner");
+
+    return gde::Study(id, name, creationDate, updateDate, valid, deleted, deletionDate, attributeGroupId, profileId, locked, lockOwner);
+  }
+}
+
+bool
+gde::StudyService::deleteStudy(const Study& study)
+{
+  CommandTO cto(DELETE_STUDY);
+  cto.setParameter("studyId", study.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;
+}
+
+bool
+gde::StudyService::setStudyState(const Study& study, int lock)
+{
+  CommandTO cto(SET_STUDY_SATE);
+  cto.setParameter("studyId", study.getId());
+  cto.setParameter("lock", lock);
+
+  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::Study
+gde::StudyService::readStudy(int studyId)
+{
+  CommandTO cto(READ_STUDY);
+  cto.setParameter("studyId", studyId);
+
+  const Credentials& credentials = _session.getCredentials();
+  std::string uri = _session.getServiceURI(_servletName);
+  CommandResultTO crto = gde::HttpConnection(Poco::URI(uri), credentials).doPost(cto);
+
+  // build Study 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");
+    Poco::Timestamp creationDate = JsonFormatter::extract(object, "creationDate");
+    Poco::Timestamp updateDate = JsonFormatter::extract(object, "updateDate");
+    bool valid = JsonFormatter::extract<bool>(object, "valid");
+    bool deleted = JsonFormatter::extract<bool>(object, "deleted");
+    Poco::Timestamp deletionDate = JsonFormatter::extract(object, "deletionDate");
+    int attributeGroupId = JsonFormatter::extract<int>(object, "attributeGroupId");
+    int profileId = JsonFormatter::extract<int>(object, "profileId");
+    bool locked = JsonFormatter::extract<bool>(object, "locked");
+    int lockOwner = JsonFormatter::extract<int>(object, "lockOwner");
+
+    return gde::Study(id, name, creationDate, updateDate, valid, deleted, deletionDate, attributeGroupId, profileId, locked, lockOwner);
+  }
+}
diff --git a/projects/GDE_API_CPP/api/src/StudyService.hpp b/projects/GDE_API_CPP/api/src/StudyService.hpp
new file mode 100644 (file)
index 0000000..bfaffab
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef GDE_STUDY_SERVICE_HPP
+#define GDE_STUDY_SERVICE_HPP
+
+#include "Study.hpp"
+#include "GDESession.hpp"
+
+#include <string>
+
+namespace gde {
+
+  class StudyService {
+    friend class GDESession;
+
+  public:
+    const Study createStudy(const std::string& name);
+    bool deleteStudy(const Study&);
+
+    bool setStudyState(const Study&, int lock);
+    const Study readStudy(int studyId);
+
+  private:
+    StudyService(const GDESession& session) : _session(session) {}
+    ~StudyService() {}
+    StudyService(const StudyService&); // non copyable
+    StudyService& operator=(const StudyService&); // non copyable
+
+  private:
+    static std::string _servletName;
+    const GDESession& _session;
+
+  };
+
+};
+
+#endif
diff --git a/projects/GDE_API_CPP/api/tests/StudyTest.cpp b/projects/GDE_API_CPP/api/tests/StudyTest.cpp
new file mode 100644 (file)
index 0000000..1cfff75
--- /dev/null
@@ -0,0 +1,55 @@
+#include <iostream>
+
+#include <TestUtilities.hpp>
+#include <Study.hpp>
+#include <GDESession.hpp>
+#include <StudyTest.hpp>
+
+void
+StudyTest::testCreateDeleteStudy()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  const gde::Study& study = session.createStudy("myStudy");
+  CPPUNIT_ASSERT(study.getName() == "myStudy");
+  CPPUNIT_ASSERT(study.getId() > 0);
+
+  CPPUNIT_ASSERT(session.deleteStudy(study));
+}
+
+void
+StudyTest::testReadStudy()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  const gde::Study& study = session.createStudy("myStudy");
+  CPPUNIT_ASSERT(study.getId() > 0);
+
+  {
+    const gde::Study& myStudy = session.readStudy(study.getId());
+    CPPUNIT_ASSERT(myStudy.getName() == "myStudy");
+    CPPUNIT_ASSERT(myStudy.getId() > 0);
+  }
+
+  CPPUNIT_ASSERT(session.deleteStudy(study));
+  /*
+  // Will raise an exception: study does not exist anymore
+  {
+    const gde::Study& myStudy = session.readStudy(study.getId());
+  }
+  */
+}
+
+void
+StudyTest::testSetStudySate()
+{
+  gde::GDESession session(serverAddress, credentials);
+
+  const gde::Study& study = session.createStudy("myStudy");
+  CPPUNIT_ASSERT(study.getId() > 0);
+
+  CPPUNIT_ASSERT(session.setStudyState(study, 1));
+  CPPUNIT_ASSERT(session.setStudyState(study, 0));
+
+  CPPUNIT_ASSERT(session.deleteStudy(study));
+}
diff --git a/projects/GDE_API_CPP/api/tests/StudyTest.hpp b/projects/GDE_API_CPP/api/tests/StudyTest.hpp
new file mode 100644 (file)
index 0000000..f222950
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef GDE_STUDY_TEST_HPP
+#define GDE_STUDY_TEST_HPP
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class StudyTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE(StudyTest);
+  CPPUNIT_TEST(testCreateDeleteStudy);
+  CPPUNIT_TEST(testReadStudy);
+  CPPUNIT_TEST(testSetStudySate);
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void testCreateDeleteStudy();
+  void testReadStudy();
+  void testSetStudySate();
+};
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(StudyTest, "StudyTest");
+
+#endif
index fa5b2bed77628116e11770a9d804b69448bec1ce..d2107762b31b43054f7a204315a00996736c5a8d 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <string>
 
-std::string serverAddress = "http://localhost:8080/GDE-war";
-gde::Credentials credentials("admin", "edf123");
+static std::string serverAddress = "http://localhost:8080/GDE-war";
+static gde::Credentials credentials("admin", "edf123");
 
 #endif
index af303b549cfd679935dfc264270f4489969d0fe1..a5a50d93b0301ef0caa1a10d3b1c9e2c776f2351 100644 (file)
@@ -5,13 +5,13 @@ import com.edf.gde.tools.Base64;
 
 import com.edf.gde.transferables.CommandTO;
 import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.StringTokenizer;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -24,9 +24,11 @@ public abstract class BaseService extends HttpServlet {
 
     public abstract void processRequest(HttpServletRequest request, HttpServletResponse response);
 
+    private String dateFormat = "yyyy-MM-dd HH:mm:ss";
+            
     protected <T> T read(HttpServletRequest request, Class<T> classOf) {
         try {
-            Gson gson = new Gson();
+            Gson gson = new GsonBuilder().setDateFormat(dateFormat).create();
             return gson.fromJson(request.getReader(), classOf);
         } catch (IOException ex) {
             Logger.getLogger(BaseService.class.getName()).log(Level.SEVERE, null, ex);
@@ -35,18 +37,18 @@ public abstract class BaseService extends HttpServlet {
     }
 
     protected <T> T fromJson(String json, Class<T> classOf) {
-        Gson gson = new Gson();
+        Gson gson = new GsonBuilder().setDateFormat(dateFormat).create();
         return gson.fromJson(json, classOf);
     }
 
     protected String toJson(Object object) {
-        Gson gson = new Gson();
+        Gson gson = new GsonBuilder().setDateFormat(dateFormat).create();
         return gson.toJson(object);
     }
 
     protected void send(Object object, HttpServletResponse out) {
         try {
-            Gson gson = new Gson();
+            Gson gson = new GsonBuilder().setDateFormat(dateFormat).create();
             gson.toJson(object, out.getWriter());
         } catch (IOException ex) {
             throw new RuntimeException(ex);