Skip to content
Snippets Groups Projects
Commit 8d425356 authored by Lennart Puck's avatar Lennart Puck
Browse files

updated find instance to proxy instead of pointer

parent 3119378a
No related branches found
No related tags found
1 merge request!3WIP: Dmp components refactoring
This commit is part of merge request !3. Comments created here will be created in the context of that merge request.
...@@ -104,8 +104,10 @@ DMPInstanceBasePrx DMPComponent::instantiateDMP(const std::string& DMPType, cons ...@@ -104,8 +104,10 @@ DMPInstanceBasePrx DMPComponent::instantiateDMP(const std::string& DMPType, cons
Ice::ObjectPrx obj = adapter->addWithUUID(inst); Ice::ObjectPrx obj = adapter->addWithUUID(inst);
// save obj intovirtual void instantiateDMP(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) // save obj intovirtual void instantiateDMP(const ::std::string&, const ::Ice::Current& = ::Ice::Current())
//obj->ice_getIdentity().name; // use this to identify instance in map //obj->ice_getIdentity().name; // use this to identify instance in map
dmpInstances[obj->ice_getIdentity().name] = inst; DMPInstanceBasePrx instprx = DMPInstanceBasePrx::uncheckedCast(obj);
return DMPInstanceBasePrx::uncheckedCast(obj); std::pair<DMPInstancePtr, DMPInstanceBasePrx> dmpPair(inst, instprx);
dmpInstances[instprx->ice_getIdentity().name] = dmpPair;
return instprx;
} }
void DMPComponent::removeInstance(const DMPInstanceBasePrx& instanceProxy, const Ice::Current&) void DMPComponent::removeInstance(const DMPInstanceBasePrx& instanceProxy, const Ice::Current&)
...@@ -122,18 +124,34 @@ void DMPComponent::removeInstance(const DMPInstanceBasePrx& instanceProxy, const ...@@ -122,18 +124,34 @@ void DMPComponent::removeInstance(const DMPInstanceBasePrx& instanceProxy, const
} }
} }
DMPInstancePtr DMPComponent::findInstance(std::string name) DMPInstanceBasePrx DMPComponent::findInstance(std::string name)
{ {
std::pair<DMPInstancePtr, DMPInstanceBasePrx> dmpPair = dmpInstances.find(name)->second;
DMPInstanceBasePrx result = dmpPair.second;
if (result)
{
return result;
}
else
{
ARMARX_INFO << "DMP not found.";
return DMPInstanceBasePrx();
}
}
DMPInstancePtr result = dmpInstances.find(name)->second; DMPInstancePtr DMPComponent::findInstancePointer(string name)
{
std::pair<DMPInstancePtr, DMPInstanceBasePrx> dmpPair = dmpInstances.find(name)->second;
DMPInstancePtr result = dmpPair.first;
if (result) if (result)
{ {
return result; return result;
} }
else else
{ {
//TODO Correct?
ARMARX_INFO << "DMP not found."; ARMARX_INFO << "DMP not found.";
return DMPInstancePtr(); return nullptr;
} }
} }
...@@ -143,19 +161,21 @@ DMPInstancePtr DMPComponent::findInstance(std::string name) ...@@ -143,19 +161,21 @@ DMPInstancePtr DMPComponent::findInstance(std::string name)
void DMPComponent::storeDMPInDatabase(const std::string& name, const std::string& dmpName, const ::Ice::Current&) void DMPComponent::storeDMPInDatabase(const std::string& name, const std::string& dmpName, const ::Ice::Current&)
{ {
DMPInstancePtr dmpInst = findInstance(dmpName); DMPInstanceBasePrx dmpInst = findInstance(dmpName);
DMPInstancePtr dmpInstPointer = findInstancePointer(dmpName);
if (!dmpInst) if (!dmpInst)
{ {
ARMARX_ERROR << "DMP not found"; ARMARX_ERROR << "DMP not found";
return; return;
} }
DMP::DMPInterfacePtr dmp = dmpInst->getDmp(); DMP::DMPInterfacePtr dmp = dmpInstPointer->getDmp();
ARMARX_INFO << "storing DMP in the database"; ARMARX_INFO << "storing DMP in the database";
memoryx::DMPEntityPtr dmpEntity = new memoryx::DMPEntity(name); memoryx::DMPEntityPtr dmpEntity = new memoryx::DMPEntity(name);
dmpEntity->setDMPType(dmpInst->getDmpType()); dmpEntity->setDMPType(dmpInstPointer->getDmpType());
dmpEntity->setDMPName(name); dmpEntity->setDMPName(name);
//dmpEntity->set3rdOrder(is3rdOrder); //dmpEntity->set3rdOrder(is3rdOrder);
...@@ -233,7 +253,9 @@ DMPInstanceBasePrx DMPComponent::getDMPFromDB(memoryx::DMPEntityPtr dmpEntity) ...@@ -233,7 +253,9 @@ DMPInstanceBasePrx DMPComponent::getDMPFromDB(memoryx::DMPEntityPtr dmpEntity)
Ice::ObjectPrx obj = adapter->addWithUUID(inst); Ice::ObjectPrx obj = adapter->addWithUUID(inst);
// save obj intovirtual void instantiateDMP(const ::std::string&, const ::Ice::Current& = ::Ice::Current()) // save obj intovirtual void instantiateDMP(const ::std::string&, const ::Ice::Current& = ::Ice::Current())
//obj->ice_getIdentity().name; // use this to identify instance in map //obj->ice_getIdentity().name; // use this to identify instance in map
dmpInstances[obj->ice_getIdentity().name] = inst; std::pair<DMPInstancePtr, DMPInstanceBasePrx> dmpPair(inst, DMPInstanceBasePrx::uncheckedCast(obj));
// dmpInstances[obj->ice_getIdentity().name] = inst;
dmpInstances[obj->ice_getIdentity().name] = dmpPair;
ARMARX_INFO << "successfully got dmp from database."; ARMARX_INFO << "successfully got dmp from database.";
...@@ -244,8 +266,9 @@ DMPInstanceBasePrx DMPComponent::getDMPFromDB(memoryx::DMPEntityPtr dmpEntity) ...@@ -244,8 +266,9 @@ DMPInstanceBasePrx DMPComponent::getDMPFromDB(memoryx::DMPEntityPtr dmpEntity)
void DMPComponent::trainDMP(const std::string& dmpName, const DMPConfigMap& configuration, const ::Ice::Current&) void DMPComponent::trainDMP(const std::string& dmpName, const DMPConfigMap& configuration, const ::Ice::Current&)
{ {
DMPInstancePtr dmpInst = findInstance(dmpName); DMPInstanceBasePrx dmpInst = findInstance(dmpName);
DMP::DMPInterfacePtr dmp = dmpInst->getDmp(); DMPInstancePtr dmpInstPointer = findInstancePointer(dmpName);
DMP::DMPInterfacePtr dmp = dmpInstPointer->getDmp();
if (!dmp) if (!dmp)
{ {
ARMARX_ERROR << "DMP not found"; ARMARX_ERROR << "DMP not found";
...@@ -364,7 +387,22 @@ void DMPComponent::removeDMPFromDatabaseById(const std::string& dbId, const Ice: ...@@ -364,7 +387,22 @@ void DMPComponent::removeDMPFromDatabaseById(const std::string& dbId, const Ice:
} }
} }
std::map<std::string, DMPInstancePtr> DMPComponent::getDMPInstances() DMPInstanceBasePrx DMPComponent::findByIceIdentity(const string& ident, const Ice::Current&)
{
std::pair<DMPInstancePtr, DMPInstanceBasePrx> dmpPair = dmpInstances.find(ident)->second;
DMPInstanceBasePrx result = dmpPair.second;
if (result)
{
return result;
}
else
{
ARMARX_INFO << "DMP not found.";
return DMPInstanceBasePrx();
}
}
std::map<std::string, std::pair<DMPInstancePtr, DMPInstanceBasePrx> > DMPComponent::getDMPInstances()
{ {
return dmpInstances; return dmpInstances;
} }
......
...@@ -43,18 +43,18 @@ ...@@ -43,18 +43,18 @@
#include <dmp/representation/dmp/dmpregistration.h> #include <dmp/representation/dmp/dmpregistration.h>
#include <ArmarXCore/core/Component.h> #include <ArmarXCore/core/Component.h>
#include "dmp/representation/dmp/dmpinterface.h" //#include "dmp/representation/dmp/dmpinterface.h"
#include "dmp/representation/dmp/basicdmp.h" //#include "dmp/representation/dmp/basicdmp.h"
#include "dmp/representation/dmp/dmp3rdorder.h" //#include "dmp/representation/dmp/dmp3rdorder.h"
#include "dmp/representation/dmp/quaterniondmp.h" //#include "dmp/representation/dmp/quaterniondmp.h"
#include "dmp/representation/dmp/endvelodmp.h" //#include "dmp/representation/dmp/endvelodmp.h"
#include "dmp/representation/dmp/dmp3rdorderforcefield.h" //#include "dmp/representation/dmp/dmp3rdorderforcefield.h"
#include "dmp/representation/dmp/forcefielddmp.h" //#include "dmp/representation/dmp/forcefielddmp.h"
#include "dmp/representation/dmp/adaptive3rdorderdmp.h" //#include "dmp/representation/dmp/adaptive3rdorderdmp.h"
#include "dmp/representation/dmp/simpleendvelodmp.h" //#include "dmp/representation/dmp/simpleendvelodmp.h"
//#include "dmp/representation/dmp/endveloforcefielddmp.h" ////#include "dmp/representation/dmp/endveloforcefielddmp.h"
//#include "dmp/representation/dmp/endveloforcefieldwithobjrepulsiondmp.h" ////#include "dmp/representation/dmp/endveloforcefieldwithobjrepulsiondmp.h"
#include "dmp/representation/dmp/periodictransientdmp.h" //#include "dmp/representation/dmp/periodictransientdmp.h"
#include "DMPInstance.h" #include "DMPInstance.h"
...@@ -92,11 +92,19 @@ namespace armarx ...@@ -92,11 +92,19 @@ namespace armarx
* This class manages the DMP Component. It wields the possibilty to create new instances of different DMPs, these can be trained * This class manages the DMP Component. It wields the possibilty to create new instances of different DMPs, these can be trained
* with Trajectories. Furthermore they can be managed in a Database (saving, loading, removing). The class can mange multiple instances of DMPs. * with Trajectories. Furthermore they can be managed in a Database (saving, loading, removing). The class can mange multiple instances of DMPs.
* *
* A possible workflow would be: * @snippet RobotComponents/components/DMPComponent/test/DMPComponentTest.cpp DMPComponentDocumentation Environment
* Creating a new Instance of a DMP *
* Loading a Trajectory from file * @snippet RobotComponents/components/DMPComponent/test/DMPComponentTest.cpp DMPComponentDocumentation Initalization
* Training the DMP with a Trajectory *
* Storing the DMP in the Database * @snippet RobotComponents/components/DMPComponent/test/DMPComponentTest.cpp DMPComponentDocumentation Remove
*
* @snippet RobotComponents/components/DMPComponent/test/DMPComponentTest.cpp DMPComponentDocumentation StoreRetrieve
*
* @snippet RobotComponents/components/DMPComponent/test/DMPComponentTest.cpp DMPComponentDocumentation Train
*
* @snippet RobotComponents/components/DMPComponent/test/DMPComponentTest.cpp DMPComponentDocumentation CalculateTrajectory
*
*
*/ */
class DMPComponent : class DMPComponent :
virtual public Component, virtual public Component,
...@@ -225,11 +233,13 @@ namespace armarx ...@@ -225,11 +233,13 @@ namespace armarx
*/ */
virtual void removeDMPFromDatabaseById(const std::string& dbId, const ::Ice::Current& = ::Ice::Current()); virtual void removeDMPFromDatabaseById(const std::string& dbId, const ::Ice::Current& = ::Ice::Current());
virtual DMPInstanceBasePrx findByIceIdentity(const ::std::string& ident, const ::Ice::Current& = ::Ice::Current());
/** /**
* @brief getDMPInstances return a Map of all DMPs intanciated * @brief getDMPInstances return a Map of all DMPs intanciated
* @return List of DMPs * @return List of DMPs
*/ */
std::map<std::string, DMPInstancePtr> getDMPInstances(); std::map<std::string, std::pair<DMPInstancePtr, DMPInstanceBasePrx>> getDMPInstances();
/** /**
...@@ -237,12 +247,14 @@ namespace armarx ...@@ -237,12 +247,14 @@ namespace armarx
* @param name of the DMP * @param name of the DMP
* @return Pointer to the found DMP * @return Pointer to the found DMP
*/ */
DMPInstancePtr findInstance(std::string name); DMPInstanceBasePrx findInstance(std::string name);
DMPInstancePtr findInstancePointer(std::string name);
protected: protected:
std::vector<int> usedDimensions; std::vector<int> usedDimensions;
std::map<std::string, DMPInstancePtr> dmpInstances; std::map<std::string, std::pair<DMPInstancePtr, DMPInstanceBasePrx>> dmpInstances;
DMP::Vec<DMP::SampledTrajectoryV2> trajs; DMP::Vec<DMP::SampledTrajectoryV2> trajs;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <ArmarXCore/core/Component.h> #include <ArmarXCore/core/Component.h>
#include <ArmarXCore/core/logging/Logging.h> #include <ArmarXCore/core/logging/Logging.h>
//#include <dmp/representation/dmp/dmpregistration.h>
#include "dmp/representation/dmp/dmpinterface.h" #include "dmp/representation/dmp/dmpinterface.h"
#include "dmp/representation/dmp/basicdmp.h" #include "dmp/representation/dmp/basicdmp.h"
#include "dmp/representation/dmp/dmp3rdorder.h" #include "dmp/representation/dmp/dmp3rdorder.h"
...@@ -39,9 +40,9 @@ ...@@ -39,9 +40,9 @@
#include "dmp/representation/dmp/forcefielddmp.h" #include "dmp/representation/dmp/forcefielddmp.h"
#include "dmp/representation/dmp/adaptive3rdorderdmp.h" #include "dmp/representation/dmp/adaptive3rdorderdmp.h"
#include "dmp/representation/dmp/simpleendvelodmp.h" #include "dmp/representation/dmp/simpleendvelodmp.h"
//#include "dmp/representation/dmp/endveloforcefielddmp.h" #include "dmp/representation/dmp/endveloforcefielddmp.h"
//#include "dmp/representation/dmp/endveloforcefieldwithobjrepulsiondmp.h" #include "dmp/representation/dmp/endveloforcefieldwithobjrepulsiondmp.h"
//#include "dmp/representation/dmp/periodictransientdmp.h" #include "dmp/representation/dmp/periodictransientdmp.h"
namespace armarx namespace armarx
......
...@@ -139,14 +139,18 @@ BOOST_AUTO_TEST_CASE(test2) ...@@ -139,14 +139,18 @@ BOOST_AUTO_TEST_CASE(test2)
// std::cout << "Start Test2 ..." << std::endl; // std::cout << "Start Test2 ..." << std::endl;
// DMP::Vec<DMP::DMPState> res; // DMP::Vec<DMP::DMPState> res;
//! [DMPComponentDocumentation Environment]
DMPEnviroment env("dmpenv"); DMPEnviroment env("dmpenv");
DMPComponentPtr dmpComponent = Component::create < DMPComponent > (); DMPComponentPtr dmpComponent = Component::create < DMPComponent > ();
env.manager->addObject(dmpComponent); env.manager->addObject(dmpComponent);
BOOST_CHECK(dmpComponent->getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted, 10000)); BOOST_CHECK(dmpComponent->getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted, 10000));
//! [DMPComponentDocumentation Environment]
// instance.instantiateDMP("test"); // instance.instantiateDMP("test");
// instance.instantiateDMP(boost::serialization::guid<DMP::BasicDMP>()); // instance.instantiateDMP(boost::serialization::guid<DMP::BasicDMP>());
//! [DMPComponentDocumentation Instantiation]
DMPInstanceBasePrx dmp = dmpComponent->instantiateDMP(ARMARX_DMPTYPE_BASICDMP_GUID); DMPInstanceBasePrx dmp = dmpComponent->instantiateDMP(ARMARX_DMPTYPE_BASICDMP_GUID);
//! [DMPComponentDocumentation Instantiation]
DMPInstanceBasePrx dmp2 = dmpComponent->instantiateDMP(ARMARX_DMPTYPE_DMP3RDORDER_GUID); DMPInstanceBasePrx dmp2 = dmpComponent->instantiateDMP(ARMARX_DMPTYPE_DMP3RDORDER_GUID);
DMPInstanceBasePrx dmp3 = dmpComponent->instantiateDMP(ARMARX_DMPTYPE_SIMPLEENDVELODMP_GUID); DMPInstanceBasePrx dmp3 = dmpComponent->instantiateDMP(ARMARX_DMPTYPE_SIMPLEENDVELODMP_GUID);
...@@ -154,42 +158,47 @@ BOOST_AUTO_TEST_CASE(test2) ...@@ -154,42 +158,47 @@ BOOST_AUTO_TEST_CASE(test2)
BOOST_CHECK(dmp2); BOOST_CHECK(dmp2);
BOOST_CHECK(dmp3); BOOST_CHECK(dmp3);
std::map<std::string, DMPInstancePtr> instances = dmpComponent->getDMPInstances(); std::map<std::string, std::pair<DMPInstancePtr, DMPInstanceBasePrx>> instances = dmpComponent->getDMPInstances();
for (std::map<std::string, DMPInstancePtr>::iterator it = instances.begin(); it != instances.end(); ++it) for (std::map<std::string, std::pair<DMPInstancePtr, DMPInstanceBasePrx>>::iterator it = instances.begin(); it != instances.end(); ++it)
{ {
std::cout << "DMP: " << it->first << "\n"; std::cout << "DMP: " << it->first << "\n";
std::cout << it->second->getDmpType() << "\n"; std::cout << it->second.first->getDmpType() << "\n";
} }
std::cout << "PART 2: REMOVE \n"; std::cout << "PART 2: REMOVE \n";
dmpComponent->removeInstance(dmp3); //! [DMPComponentDocumentation Remove]
dmpComponent->removeInstance(dmp2);
//! [DMPComponentDocumentation Remove]
instances = dmpComponent->getDMPInstances(); instances = dmpComponent->getDMPInstances();
for (std::map<std::string, DMPInstancePtr>::iterator it = instances.begin(); it != instances.end(); ++it) for (std::map<std::string, std::pair<DMPInstancePtr, DMPInstanceBasePrx>>::iterator it = instances.begin(); it != instances.end(); ++it)
{ {
std::cout << "DMP: " << it->first << "\n"; std::cout << "DMP: " << it->first << "\n";
std::cout << it->second->getDmpType() << "\n"; std::cout << it->second.first->getDmpType() << "\n";
} }
std::cout << "PART 3: STORE \n"; std::cout << "PART 3: STORE \n";
//! [DMPComponentDocumentation StoreRetrieve]
std::string name = "theThirdDMP \n" ; std::string name = "theThirdDMP \n" ;
dmpComponent->storeDMPInDatabase(name, dmp->ice_getIdentity().name); dmpComponent->storeDMPInDatabase(name, dmp->ice_getIdentity().name);
DMPInstanceBasePrx dmp5 = dmpComponent->getFirstDMPFromDatabaseByName(name);
//! [DMPComponentDocumentation StoreRetrieve]
//dmpComponent->removeInstance(dmp3); //dmpComponent->removeInstance(dmp3);
instances = dmpComponent->getDMPInstances(); instances = dmpComponent->getDMPInstances();
for (std::map<std::string, DMPInstancePtr>::iterator it = instances.begin(); it != instances.end(); ++it) for (std::map<std::string, std::pair<DMPInstancePtr, DMPInstanceBasePrx>>::iterator it = instances.begin(); it != instances.end(); ++it)
{ {
std::cout << "DMP: " << it->first << "\n"; std::cout << "DMP: " << it->first << "\n";
std::cout << it->second->getDmpType() << "\n"; std::cout << it->second.first->getDmpType() << "\n";
} }
std::cout << "PART 4: RETRIEVE \n"; std::cout << "PART 4: RETRIEVE \n";
...@@ -200,11 +209,11 @@ BOOST_AUTO_TEST_CASE(test2) ...@@ -200,11 +209,11 @@ BOOST_AUTO_TEST_CASE(test2)
instances = dmpComponent->getDMPInstances(); instances = dmpComponent->getDMPInstances();
for (std::map<std::string, DMPInstancePtr>::iterator it = instances.begin(); it != instances.end(); ++it) for (std::map<std::string, std::pair<DMPInstancePtr, DMPInstanceBasePrx>>::iterator it = instances.begin(); it != instances.end(); ++it)
{ {
std::cout << "retrieved DMP: " << it->first << "\n"; std::cout << "retrieved DMP: " << it->first << "\n";
std::cout << it->second->getDmpType() << "\n"; std::cout << it->second.first->getDmpType() << "\n";
} }
...@@ -315,7 +324,10 @@ BOOST_AUTO_TEST_CASE(test2) ...@@ -315,7 +324,10 @@ BOOST_AUTO_TEST_CASE(test2)
std::cout << v2 << std::endl; std::cout << v2 << std::endl;
//! [DMPComponentDocumentation CalculateTrajecotry]
Vec2D v3 = dmp->calcTrajectory(timestamps, goals, initStates, canonicalValues, 1.f); Vec2D v3 = dmp->calcTrajectory(timestamps, goals, initStates, canonicalValues, 1.f);
//! [DMPComponentDocumentation CalculateTrajecotry]
// instance.readTrajectoryFromFile("/home/yzhou/motions/sampletraj.csv"); // instance.readTrajectoryFromFile("/home/yzhou/motions/sampletraj.csv");
// instance.trainDMP(); // instance.trainDMP();
...@@ -388,9 +400,12 @@ BOOST_AUTO_TEST_CASE(test_3rdOrderDMP) ...@@ -388,9 +400,12 @@ BOOST_AUTO_TEST_CASE(test_3rdOrderDMP)
MMM::MotionPtr motion = motionreader.loadMotion(file); MMM::MotionPtr motion = motionreader.loadMotion(file);
traj = DMP::MMMConverter::fromMMMJoints(motion); traj = DMP::MMMConverter::fromMMMJoints(motion);
DMPConfigMap confs;
//! [DMPComponentDocumentation Train]
dmpComponent->readTrajectoryFromFile(file); dmpComponent->readTrajectoryFromFile(file);
// dmpComponent->trainDMP(dmp2->ice_getIdentity().name); dmpComponent->trainDMP(dmp2->ice_getIdentity().name, confs);
//! [DMPComponentDocumentation Train]
DMP::DVec2d initialStates; DMP::DVec2d initialStates;
......
...@@ -57,6 +57,7 @@ module armarx ...@@ -57,6 +57,7 @@ module armarx
void setStartPosition(Ice::DoubleSeq value) throws InvalidArgumentException; void setStartPosition(Ice::DoubleSeq value) throws InvalidArgumentException;
void setTimeStamps(Ice::DoubleSeq value) throws InvalidArgumentException; void setTimeStamps(Ice::DoubleSeq value) throws InvalidArgumentException;
void setConfigurationMap(DMPConfigMap value) throws InvalidArgumentException; void setConfigurationMap(DMPConfigMap value) throws InvalidArgumentException;
}; };
["cpp:virtual"] ["cpp:virtual"]
...@@ -66,6 +67,7 @@ module armarx ...@@ -66,6 +67,7 @@ module armarx
DMPInstanceBase* getFirstDMPFromDatabaseByName(string dmpName) throws InvalidArgumentException; DMPInstanceBase* getFirstDMPFromDatabaseByName(string dmpName) throws InvalidArgumentException;
DMPInstanceBase* getDMPFromDatabaseById(string dbId) throws InvalidArgumentException; DMPInstanceBase* getDMPFromDatabaseById(string dbId) throws InvalidArgumentException;
DMPInstanceBase* instantiateDMP(string dmptype) throws InvalidArgumentException; DMPInstanceBase* instantiateDMP(string dmptype) throws InvalidArgumentException;
DMPInstanceBase* findByIceIdentity(string dmpIceId) throws InvalidArgumentException;
void removeInstance(DMPInstanceBase* instanceProxy) throws InvalidArgumentException; void removeInstance(DMPInstanceBase* instanceProxy) throws InvalidArgumentException;
void trainDMP(string dmpname, DMPConfigMap dmpConfiguration) throws InvalidArgumentException; void trainDMP(string dmpname, DMPConfigMap dmpConfiguration) throws InvalidArgumentException;
void storeDMPInDatabase(string cname, string dmpname) throws InvalidArgumentException; void storeDMPInDatabase(string cname, string dmpname) throws InvalidArgumentException;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment