knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
DataSource.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of KnowRob, please consult
3  * https://github.com/knowrob/knowrob for license details.
4  */
5 
6 #include <utility>
7 #include <filesystem>
8 #include <boost/spirit/include/qi.hpp>
9 #include <boost/spirit/include/phoenix_operator.hpp>
10 #include "knowrob/integration/python/utils.h"
11 #include "knowrob/DataSource.h"
12 #include "knowrob/semweb/OntologyLanguage.h"
13 #include "knowrob/semweb/OntologyFile.h"
14 #include "knowrob/semweb/SPARQLService.h"
15 #include "knowrob/semweb/GraphSelector.h"
16 
17 #define DATA_SOURCE_SETTING_FORMAT "format"
18 #define DATA_SOURCE_SETTING_LANG "language"
19 #define DATA_SOURCE_SETTING_TYPE "type"
20 #define DATA_SOURCE_SETTING_FRAME "frame"
21 
22 #define DATA_SOURCE_TYPE_SPARQL "sparql"
23 #define DATA_SOURCE_TYPE_ONTOLOGY "ontology"
24 
25 using namespace knowrob;
26 namespace fs = std::filesystem;
27 namespace qi = boost::spirit::qi;
28 namespace ascii = boost::spirit::ascii;
29 
30 DataSource::DataSource(URI uri, std::string_view format, DataSourceType dataSourceType)
31  : dataSourceType_(dataSourceType),
32  format_(format),
33  uri_(std::move(uri)) {
34 }
35 
37  return fs::path(uriString).stem();
38 }
39 
40 template<typename TP>
41 std::time_t to_time_t(TP tp) {
42  // needed to convert file modification time to string
43  using namespace std::chrono;
44  auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now() + system_clock::now());
45  return system_clock::to_time_t(sctp);
46 }
47 
49  fs::path p(uriString);
50 
51  // check if it is a local existing file and use file modification time
52  // as version in this case.
53  if (exists(p)) {
54  std::ostringstream oss;
55  auto stamp = last_write_time(p);
56  auto tt = to_time_t(stamp);
57  auto tm = *std::localtime(&tt);
58  oss << std::put_time(&tm, "%c");
59  return oss.str();
60  }
61 
62  // try to extract version from URI
63  auto versionString = p.parent_path().filename();
64  if (isVersionString(versionString)) {
65  return versionString;
66  }
67 
68  // fallback to use the current day as version, thus causing
69  // a reload each day.
70  {
71  std::ostringstream oss;
72  auto t = std::time(nullptr);
73  auto tm = *std::localtime(&t);
74  oss << std::put_time(&tm, "%d-%m-%Y");
75  return oss.str();
76  }
77 }
78 
79 bool DataSource::isVersionString(const std::string &versionString) {
80  // parser rules
81  qi::rule<std::string::const_iterator> numbers = (
82  (+qi::digit >> '.' >> +qi::digit >> '.' >> +qi::digit) |
83  (+qi::digit >> '.' >> +qi::digit));
84  // parse input
85  auto first = versionString.begin();
86  auto last = versionString.end();
87  bool r = qi::phrase_parse(first,
88  last,
89  (('v' >> numbers) | numbers),
90  ascii::space);
91  // return true if parser succeeded
92  return (first == last && r);
93 }
94 
95 static bool isOntologySourceType(
96  const std::string &format,
97  const boost::optional<std::string> &language,
98  const boost::optional<std::string> &type) {
99  if (type && (type.value() == DATA_SOURCE_TYPE_ONTOLOGY || type.value() == DATA_SOURCE_TYPE_SPARQL)) return true;
100  if (language && semweb::isOntologyLanguageString(language.value())) return true;
101  if (semweb::isTripleFormatString(format)) return true;
102  return false;
103 }
104 
105 DataSourcePtr DataSource::create(const VocabularyPtr &vocabulary, const boost::property_tree::ptree &config) {
106  static const std::string formatDefault = {};
107 
108  // read data source settings
109  URI dataSourceURI(config);
110  auto dataSourceFormat = config.get(DATA_SOURCE_SETTING_FORMAT, formatDefault);
111  auto o_dataSourceLanguage = config.get_optional<std::string>(DATA_SOURCE_SETTING_LANG);
112  auto o_type = config.get_optional<std::string>(DATA_SOURCE_SETTING_TYPE);
113  auto isOntology = isOntologySourceType(dataSourceFormat, o_dataSourceLanguage, o_type);
114  // an optional frame can be applied to all triples in a data source
115  auto o_tripleFrame = config.get_child_optional(DATA_SOURCE_SETTING_FRAME);
116  std::shared_ptr<GraphSelector> tripleFrame;
117  if (o_tripleFrame) {
118  tripleFrame = std::make_shared<GraphSelector>();
119  tripleFrame->set(*o_tripleFrame);
120  }
121 
122  if (isOntology && o_type && o_type.value() == DATA_SOURCE_TYPE_SPARQL) {
123  auto sparqlService = std::make_shared<SPARQLService>(dataSourceURI, dataSourceFormat);
124  if (tripleFrame) {
125  sparqlService->setFrame(tripleFrame);
126  }
127  return sparqlService;
128  } else if (isOntology) {
129  auto ontoFile = std::make_shared<OntologyFile>(vocabulary, dataSourceURI, dataSourceFormat);
130  if (o_dataSourceLanguage.has_value()) {
131  ontoFile->setOntologyLanguage(semweb::ontologyLanguageFromString(o_dataSourceLanguage.value()));
132  }
133  if (tripleFrame) {
134  ontoFile->setFrame(tripleFrame);
135  }
136  return ontoFile;
137  } else {
138  return std::make_shared<DataSource>(dataSourceURI, dataSourceFormat, DataSourceType::UNSPECIFIED);
139  }
140 }
141 
142 namespace knowrob::py {
143  template<>
145  using namespace boost::python;
146  class_<DataSource, std::shared_ptr<DataSource>>
147  ("DataSource", no_init)
148  .def("format", &DataSource::format, return_value_policy<copy_const_reference>())
149  .def("uri", &DataSource::uri, return_value_policy<copy_const_reference>())
150  .def("path", &DataSource::path, return_value_policy<copy_const_reference>())
151  .def("version", &DataSource::version)
152  .def("name", &DataSource::name)
153  .def("dataSourceType", &DataSource::dataSourceType)
154  .def("isVersionString", &DataSource::isVersionString)
155  .staticmethod("isVersionString")
156  .def("getNameFromURI", &DataSource::getNameFromURI)
157  .staticmethod("getNameFromURI")
158  .def("getVersionFromURI", &DataSource::getVersionFromURI)
159  .staticmethod("getVersionFromURI")
160  .def("create", &DataSource::create)
161  .staticmethod("create");
162  }
163 }
#define DATA_SOURCE_SETTING_LANG
Definition: DataSource.cpp:18
#define DATA_SOURCE_SETTING_TYPE
Definition: DataSource.cpp:19
#define DATA_SOURCE_TYPE_ONTOLOGY
Definition: DataSource.cpp:23
#define DATA_SOURCE_SETTING_FORMAT
Definition: DataSource.cpp:17
#define DATA_SOURCE_TYPE_SPARQL
Definition: DataSource.cpp:22
#define DATA_SOURCE_SETTING_FRAME
Definition: DataSource.cpp:20
std::time_t to_time_t(TP tp)
Definition: DataSource.cpp:41
DataSource(URI uri, std::string_view format, DataSourceType dataSourceType)
Definition: DataSource.cpp:30
static std::string getNameFromURI(const std::string &uriString)
Definition: DataSource.cpp:36
static std::string getVersionFromURI(const std::string &uriString)
Definition: DataSource.cpp:48
const auto & path() const
Definition: DataSource.h:44
auto name() const
Definition: DataSource.h:59
const auto & format() const
Definition: DataSource.h:49
const auto & uri() const
Definition: DataSource.h:39
auto version() const
Definition: DataSource.h:64
DataSourceType dataSourceType() const
Definition: DataSource.h:54
static bool isVersionString(const std::string &versionString)
Definition: DataSource.cpp:79
static std::shared_ptr< DataSource > create(const VocabularyPtr &vocabulary, const boost::property_tree::ptree &config)
Definition: DataSource.cpp:105
TermRule & string()
Definition: terms.cpp:63
void createType< DataSource >()
Definition: DataSource.cpp:144
const IRIAtomPtr type
Definition: rdf.h:15
bool isTripleFormatString(std::string_view format)
bool isOntologyLanguageString(std::string_view format)
OntologyLanguage ontologyLanguageFromString(std::string_view format)
TimePoint now()
Definition: TimePoint.cpp:12
DataSourceType
Definition: DataSource.h:17
std::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:107
std::shared_ptr< Vocabulary > VocabularyPtr
Definition: Vocabulary.h:233