19using namespace Kernel;
21using Types::Core::DateAndTime;
25Logger
g_log(
"ICat4Catalog");
40 const std::string &endpoint,
const std::string &facility) {
44 m_session = std::make_shared<API::CatalogSession>(
"", facility, endpoint);
60 if (endpoint.find(
"sns") != std::string::npos) {
61 plugin = std::string(
"ldap");
63 plugin = std::string(
"uows");
65 login.plugin = &plugin;
68 std::string userName(username);
69 std::string passWord(password);
71 std::string usernameKey(
"username");
72 std::string passwordKey(
"password");
76 std::vector<_ns1__login_credentials_entry> entries;
77 login.credentials.entry = &entries;
80 entry.
key = &usernameKey;
81 entry.
value = &userName;
82 entries.emplace_back(entry);
84 entry.
key = &passwordKey;
85 entry.
value = &passWord;
86 entries.emplace_back(entry);
88 int result = icat.
login(&
login, &loginResponse);
109 std::string sessionID =
m_session->getSessionId();
112 int result = icat.
logout(&request, &response);
129 std::vector<std::string> whereClause, joinClause;
137 whereClause.emplace_back(
"inves.startDate >= '" + startDate +
"'");
142 whereClause.emplace_back(
"inves.endDate <= '" + endDate +
"'");
147 whereClause.emplace_back(
"inves.startDate BETWEEN '" + startDate +
"' AND '" + endDate +
"'");
162 joinClause.emplace_back(
"JOIN inves.type itype");
168 joinClause.emplace_back(
"JOIN inves.investigationInstruments invInst");
169 joinClause.emplace_back(
"JOIN invInst.instrument inst");
170 whereClause.emplace_back(
"inst.fullName = '" + inputs.
getInstrument() +
"'");
175 joinClause.emplace_back(
"JOIN inves.keywords keywords");
176 whereClause.emplace_back(
"keywords.name IN ('" + inputs.
getKeywords() +
"')");
181 joinClause.emplace_back(
"JOIN inves.samples sample");
182 whereClause.emplace_back(
"sample.name LIKE '%" + inputs.
getSampleName() +
"%'");
189 joinClause.emplace_back(
"JOIN inves.investigationUsers users");
190 joinClause.emplace_back(
"JOIN users.user user");
191 whereClause.emplace_back(
"user.name = :user");
197 joinClause.emplace_back(
"JOIN inves.investigationUsers usrs");
198 joinClause.emplace_back(
"JOIN usrs.user usr");
205 joinClause.emplace_back(
"JOIN inves.datasets dataset");
206 joinClause.emplace_back(
"JOIN dataset.datafiles datafile");
209 whereClause.emplace_back(
"datafile.name LIKE '%" + inputs.
getDatafileName() +
"%'");
213 joinClause.emplace_back(
"JOIN datafile.parameters datafileparameters");
214 joinClause.emplace_back(
"JOIN datafileparameters.type dtype");
215 whereClause.emplace_back(
"dtype.name='run_number' AND "
216 "datafileparameters.numericValue BETWEEN " +
226 if (!whereClause.empty() || !joinClause.empty()) {
227 std::string from, join, where, orderBy, includes;
229 from =
" FROM Investigation inves ";
230 join =
Strings::join(joinClause.begin(), joinClause.end(),
" ");
231 where =
Strings::join(whereClause.begin(), whereClause.end(),
" AND ");
232 orderBy =
" ORDER BY inves.id DESC";
233 includes =
" INCLUDE inves.facility, "
234 "inves.investigationInstruments.instrument, inves.parameters";
238 where.insert(0,
" WHERE ");
240 query = from + join + where + orderBy + includes;
255 const int &offset,
const int &limit) {
260 throw std::runtime_error(
"You have not input any terms to search for.");
263 query.insert(0,
"SELECT DISTINCT inves");
283 throw std::runtime_error(
"You have not input any terms to search for.");
284 query.insert(0,
"SELECT COUNT(DISTINCT inves)");
287 auto numRes =
dynamic_cast<xsd__long *
>(searchResults.at(0));
290 g_log.
debug() <<
"The number of paging results returned in "
291 "ICat4Catalog::getNumberOfSearchResults is: "
292 << numRes->__item <<
"\n";
293 return numRes->__item;
306 std::string query =
"SELECT DISTINCT inves "
307 "FROM Investigation inves "
308 "JOIN inves.investigationUsers users "
309 "JOIN users.user user "
310 "WHERE user.name = :user "
311 "ORDER BY inves.id DESC "
312 "INCLUDE inves.facility, inves.investigationInstruments.instrument, "
325 if (outputws->getColumnNames().empty()) {
327 outputws->addColumn(
"long64",
"DatabaseID");
328 outputws->addColumn(
"str",
"InvestigationID");
329 outputws->addColumn(
"str",
"Facility");
330 outputws->addColumn(
"str",
"Title");
331 outputws->addColumn(
"str",
"Instrument");
332 outputws->addColumn(
"str",
"Run range");
333 outputws->addColumn(
"str",
"Start date");
334 outputws->addColumn(
"str",
"End date");
335 outputws->addColumn(
"str",
"SessionID");
339 std::vector<xsd__anyType *>::const_iterator iter;
340 for (iter = response.begin(); iter != response.end(); ++iter) {
346 std::string emptyCell;
358 if (!investigation->parameters.empty()) {
366 if (investigation->startDate) {
367 std::string startDate =
formatDateTime(*investigation->startDate,
"%Y-%m-%d");
373 if (investigation->endDate) {
374 std::string endDate =
formatDateTime(*investigation->endDate,
"%Y-%m-%d");
379 std::string sessionID =
m_session->getSessionId();
382 throw std::runtime_error(
"ICat4Catalog::saveInvestigations expected an "
383 "investigation. Please contact the Mantid "
384 "development team.");
398 auto searchResults =
performSearch(icat,
"Dataset INCLUDE DatasetType, Datafile, "
399 "Investigation <-> Investigation[name = '" +
400 investigationId +
"']");
411 if (outputws->getColumnNames().empty()) {
413 outputws->addColumn(
"long64",
"ID");
414 outputws->addColumn(
"str",
"Name");
415 outputws->addColumn(
"str",
"Description");
416 outputws->addColumn(
"str",
"Type");
417 outputws->addColumn(
"str",
"Related investigation ID");
418 outputws->addColumn(
"size_t",
"Number of datafiles");
421 std::string emptyCell;
422 for (
auto &iter : response) {
430 if (dataset->description)
440 if (dataset->investigation)
445 size_t datafileCount = dataset->datafiles.size();
448 throw std::runtime_error(
"ICat4Catalog::saveDataSets expected a dataset. "
449 "Please contact the Mantid development team.");
463 auto searchResults =
performSearch(icat,
"Datafile <-> Dataset <-> Investigation[name = '" + investigationId +
"']");
473 if (outputws->getColumnNames().empty()) {
475 outputws->addColumn(
"str",
"Name");
476 outputws->addColumn(
"str",
"Location");
477 outputws->addColumn(
"str",
"Create Time");
478 outputws->addColumn(
"long64",
"Id");
479 outputws->addColumn(
"long64",
"File size(bytes)");
480 outputws->addColumn(
"str",
"File size");
481 outputws->addColumn(
"str",
"Description");
484 std::vector<xsd__anyType *>::const_iterator iter;
485 for (iter = response.begin(); iter != response.end(); ++iter) {
493 std::string createDate =
formatDateTime(*datafile->createTime,
"%Y-%m-%d %H:%M:%S");
502 if (datafile->description)
505 throw std::runtime_error(
"ICat4Catalog::saveDataFiles expected a "
506 "datafile. Please contact the Mantid "
507 "development team.");
520 auto searchResults =
performSearch(icat,
"Instrument.fullName ORDER BY fullName");
522 for (
auto &searchResult : searchResults) {
523 auto instrument =
dynamic_cast<xsd__string *
>(searchResult);
525 instruments.emplace_back(instrument->__item);
537 auto searchResults =
performSearch(icat,
"InvestigationType.name ORDER BY name");
539 for (
auto &searchResult : searchResults) {
540 auto investigationType =
dynamic_cast<xsd__string *
>(searchResult);
541 if (investigationType)
542 invstTypes.emplace_back(investigationType->__item);
556 auto datafile =
dynamic_cast<ns1__datafile *
>(searchResults.at(0));
558 if (datafile && datafile->location)
559 return *(datafile->location);
574 std::string session =
"sessionId=" +
m_session->getSessionId();
579 url += (
"getData?" + session + datafile + outname +
"&zip=false");
580 g_log.
debug() <<
"The download URL in ICat4Catalog::getDownloadURL is: " << url <<
'\n';
593 const std::string &dataFileDescription) {
598 std::string session =
"sessionId=" +
m_session->getSessionId();
599 std::string name =
"&name=" + createFileName;
601 std::string description =
"&description=" + dataFileDescription;
604 url += (
"put?" + session + name + datasetId + description +
"&datafileFormatId=1");
605 g_log.
debug() <<
"The upload URL in ICat4Catalog::getUploadURL is: " << url <<
'\n';
626 for (
int row =
static_cast<int>(ws->rowCount()) - 1; row >= 0; --row) {
631 int64_t datasetID =
getMantidDatasetId(ws->getRef<std::string>(
"InvestigationID", row));
632 std::string datafileName =
"tempName.nxs";
634 dataset.
id = &datasetID;
635 datafile.
name = &datafileName;
655 std::string sessionID =
m_session->getSessionId();
658 int result = icat.
refresh(&request, &response);
669 if (soap_ssl_client_context(&icat, SOAP_SSL_CLIENT,
690 std::string
error(buf);
691 std::string begmsg(
"<message>");
692 std::string endmsg(
"</message>");
694 std::basic_string<char>::size_type start =
error.find(begmsg);
695 std::basic_string<char>::size_type end =
error.find(endmsg);
696 std::string exception;
698 if (start != std::string::npos && end != std::string::npos) {
699 exception =
error.substr(start + begmsg.length(), end - (start + begmsg.length()));
702 if (exception.empty())
703 exception =
"ICAT appears to be offline. Please check your connection or "
704 "report this issue.";
706 throw std::runtime_error(exception);
714 const char *args[] = {
"B",
"KB",
"MB",
"GB"};
715 std::vector<std::string> units(args, args + 4);
719 while (fileSize >= 1024 && order + 1 < units.size()) {
721 fileSize = fileSize / 1024;
734 auto dateTime = DateAndTime(boost::posix_time::from_time_t(timestamp));
735 return (dateTime.toFormattedString(format));
749 auto searchResults =
performSearch(icat,
"Dataset <-> Investigation[name = '" + investigationID +
"']");
751 int64_t datasetID = -1;
752 for (
auto &searchResult : searchResults) {
753 auto dataset =
dynamic_cast<ns1__dataset *
>(searchResult);
754 if (dataset && *(dataset->name) ==
"mantid")
755 datasetID = *(dataset->id);
760 g_log.
debug() <<
"The dataset ID of the mantid dataset was: " << datasetID <<
"\n";
777 auto datasetTypeSearch =
performSearch(icat,
"DatasetType[name ='analyzed']");
778 auto datasetType =
dynamic_cast<ns1__datasetType *
>(datasetTypeSearch.at(0));
780 auto investigationSearch =
performSearch(icat,
"Investigation[name = '" + investigationID +
"']");
784 std::string datasetName =
"mantidTempNotDuplicate";
786 dataset.
name = &datasetName;
788 dataset.
type = datasetType;
791 int64_t datasetID = -1;
799 std::string mantidName =
"mantid";
800 dataset.
name = &mantidName;
802 std::string sessionID =
m_session->getSessionId();
804 createRequest.
bean = &dataset;
806 if (icat.
create(&createRequest, &createResponse) == SOAP_OK) {
807 g_log.
debug() <<
"Creating a new dataset named: " << *(dataset.
name) <<
" with investigationID "
808 << investigationID <<
"\n";
809 datasetID = createResponse.
return_;
815 g_log.
debug() <<
"The dataset ID returned from ICat4Catalog::createMantidDataset was: " << datasetID <<
"\n";
827 if (
m_session->getSoapEndpoint().empty())
847 std::string sessionID =
m_session->getSessionId();
849 request.
query = &query;
851 g_log.
debug() <<
"The search query sent to ICAT was: \n" << query <<
'\n';
853 std::vector<xsd__anyType *> searchResults;
855 if (icat.
search(&request, &response) == SOAP_OK) {
856 searchResults = response.
return_;
861 return searchResults;
878 std::string sessionID =
m_session->getSessionId();
885 request.
bean = &bean;
#define DECLARE_CATALOG(classname)
virtual int isAccessAllowed(ns1__isAccessAllowed *ns1__isAccessAllowed_, ns1__isAccessAllowedResponse *ns1__isAccessAllowedResponse_)
Web service operation 'isAccessAllowed' (returns error code or SOAP_OK)
virtual int refresh(ns1__refresh *ns1__refresh_, ns1__refreshResponse *ns1__refreshResponse_)
Web service operation 'refresh' (returns error code or SOAP_OK)
virtual char * soap_sprint_fault(char *buf, size_t len)
Put fault into buffer.
const char * soap_endpoint
Endpoint URL of service 'ICATPortBindingProxy' (change as needed)
virtual int logout(ns1__logout *ns1__logout_, ns1__logoutResponse *ns1__logoutResponse_)
Web service operation 'logout' (returns error code or SOAP_OK)
virtual int create(ns1__create *ns1__create_, ns1__createResponse *ns1__createResponse_)
Web service operation 'create' (returns error code or SOAP_OK)
virtual int search(ns1__search *ns1__search_, ns1__searchResponse *ns1__searchResponse_)
Web service operation 'search' (returns error code or SOAP_OK)
virtual int login(ns1__login *ns1__login_, ns1__loginResponse *ns1__loginResponse_)
Web service operation 'login' (returns error code or SOAP_OK)
enum ns1__accessType __item
ns1__entityBaseBean * bean
ns1__investigation * investigation
enum ns1__accessType * accessType
ns1__entityBaseBean * bean
std::vector< xsd__anyType * > return_
TableRow represents a row in a TableWorkspace.
This class is used in Catalog Search service to set/get all the inputs to search for.
const std::string & getInvestigationName() const
Get the name of the investigation to search for.
const double & getRunStart() const
Get the start run from user input.
const std::string & getSampleName() const
Get the sample name.
const std::string & getInvestigatorSurName() const
Get the investigators name.
const std::string & getInvestigationId() const
Get the investigation id.
const time_t & getStartDate() const
Get the investigation start date.
const time_t & getEndDate() const
Get the investigation end date.
const std::string & getDatafileName() const
Get the datafile name.
const std::string & getInstrument() const
Get the instrument name.
const std::string & getKeywords() const
Get the keywords to search investigations for.
const std::string & getInvestigationType() const
Get the investigation type.
const double & getRunEnd() const
Get the end run.
bool getMyData() const
Get the "my data only" flag.
This class is responsible for the implementation of ICat4 version based information catalogs.
const std::string getFileLocation(const long long &fileID) override
Get the file location string(s) from archive.
std::string buildSearchQuery(const CatalogSearchParam &inputs)
Creates a search query string based on inputs provided by the user.
void listInvestigationTypes(std::vector< std::string > &invstTypes) override
Get investigationtypes list.
std::vector< ICat4::xsd__anyType * > performSearch(ICat4::ICATPortBindingProxy &icat, std::string query)
Returns the results of a search against ICAT for a given query.
int64_t getNumberOfSearchResults(const CatalogSearchParam &inputs) override
Obtain the number of results returned by the search method.
void saveInvestigations(std::vector< ICat4::xsd__anyType * > response, API::ITableWorkspace_sptr &outputws)
Saves investigations to a table workspace.
void setSSLContext(ICat4::ICATPortBindingProxy &icat)
Defines the SSL authentication scheme.
bool isAccessAllowed(ICat4::ns1__accessType accessType, T &bean)
Is the specified access type allowed for a specific bean?
void keepAlive() override
Keep current session alive.
void getDataFiles(const std::string &investigationId, Mantid::API::ITableWorkspace_sptr &outputws) override
Get datafiles.
void logout() override
Log the user out of the catalog system.
void savetoTableWorkspace(T *input, Mantid::API::TableRow &table)
Template method to save data to table workspace.
void saveDataFiles(std::vector< ICat4::xsd__anyType * > response, API::ITableWorkspace_sptr &outputws)
Saves result from "getDataFiles" to workspace.
void saveDataSets(const std::vector< ICat4::xsd__anyType * > &response, API::ITableWorkspace_sptr &outputws)
Loops through the response vector and saves the datasets details to a table workspace.
std::string bytesToString(int64_t &fileSize)
Convert a file size to human readable file format.
API::CatalogSession_sptr m_session
void myData(Mantid::API::ITableWorkspace_sptr &outputws) override
Show the logged in user's investigations search results.
int64_t createMantidDataset(const std::string &investigationID)
Creates a dataset for an investigation (based on ID) named 'mantid' if it does not already exist.
std::string formatDateTime(const time_t ×tamp, const std::string &format)
Formats a given timestamp to human readable datetime.
void listInstruments(std::vector< std::string > &instruments) override
Get instruments list.
void setICATProxySettings(ICat4::ICATPortBindingProxy &icat)
Sets the soap-endpoint & SSL context for the given ICAT proxy.
void search(const CatalogSearchParam &inputs, Mantid::API::ITableWorkspace_sptr &outputws, const int &offset, const int &limit) override
Search the catalog for data.
const std::string getDownloadURL(const long long &fileID) override
Get the url(s) based on the fileID.
void getDataSets(const std::string &investigationId, Mantid::API::ITableWorkspace_sptr &outputws) override
Get datasets.
API::ITableWorkspace_sptr getPublishInvestigations() override
Obtains the investigations that the user can publish to and saves related information to a workspace.
API::CatalogSession_sptr login(const std::string &username, const std::string &password, const std::string &endpoint, const std::string &facility) override
Log the user into the catalog system.
const std::string getUploadURL(const std::string &investigationID, const std::string &createFileName, const std::string &dataFileDescription) override
get URL of where to PUT (publish) files.
void throwErrorMessage(ICat4::ICATPortBindingProxy &icat)
Throws an error message (returned by gsoap) to Mantid upper layer.
int64_t getMantidDatasetId(const std::string &investigationID)
Search the archive & obtain the "mantid" dataset ID for a specific investigation if it exists.
void debug(const std::string &msg)
Logs at debug level.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
@ ns1__accessType__CREATE
std::shared_ptr< CatalogSession > CatalogSession_sptr
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
Kernel::Logger g_log("ExperimentInfo")
static logger object
DLLExport std::string join(ITERATOR_TYPE begin, ITERATOR_TYPE end, const std::string &separator, typename std::enable_if<!(std::is_same< typename std::iterator_traits< ITERATOR_TYPE >::iterator_category, std::random_access_iterator_tag >::value)>::type *=nullptr)
Join a set or vector of (something that turns into a string) together into one string,...
std::string toString(const T &value)
Convert a number to a string.
std::string to_string(const wide_integer< Bits, Signed > &n)