Mercurial > hg > piper-cpp
comparison vamp-support/RdfTypes.h @ 229:d54dab075247
Implement RDF type lookup
| author | Chris Cannam <cannam@all-day-breakfast.com> | 
|---|---|
| date | Mon, 12 Jun 2017 10:20:25 +0100 | 
| parents | c6aed932318d | 
| children | 
   comparison
  equal
  deleted
  inserted
  replaced
| 228:691b0daad1c6 | 229:d54dab075247 | 
|---|---|
| 45 | 45 | 
| 46 #include <mutex> | 46 #include <mutex> | 
| 47 | 47 | 
| 48 namespace piper_vamp { | 48 namespace piper_vamp { | 
| 49 | 49 | 
| 50 //!!! todo: better (+ optional) error reporting; check whether file | |
| 51 //!!! exists before parsing it to avoid spurious error messages; | |
| 52 //!!! refactoring | |
| 53 | |
| 50 class RdfTypes | 54 class RdfTypes | 
| 51 { | 55 { | 
| 52 public: | 56 public: | 
| 53 RdfTypes() : | 57 RdfTypes() : | 
| 54 m_world(sord_world_new()) | 58 m_world(sord_world_new()) | 
| 96 SerdReader *reader = sord_new_reader(targetModel, env, SERD_TURTLE, 0); | 100 SerdReader *reader = sord_new_reader(targetModel, env, SERD_TURTLE, 0); | 
| 97 SerdStatus rv = serd_reader_read_file | 101 SerdStatus rv = serd_reader_read_file | 
| 98 (reader, (const uint8_t *)filename.c_str()); | 102 (reader, (const uint8_t *)filename.c_str()); | 
| 99 bool success = (rv == SERD_SUCCESS); | 103 bool success = (rv == SERD_SUCCESS); | 
| 100 if (!success) { | 104 if (!success) { | 
| 101 std::cerr << "Failed to import RDF from " << filename << std::endl; | 105 // We are asking Serd to parse the file without having | 
| 102 } else { | 106 // checked whether it actually exists or not (in order to | 
| 103 std::cerr << "Imported RDF from " << filename << std::endl; | 107 // avoid duplicating ugly platform/encoding-specific stuff | 
| 108 // in this file). So don't bleat if the file is simply not | |
| 109 // found, but only if there's a real parse error | |
| 110 if (rv != SERD_ERR_NOT_FOUND && | |
| 111 rv != SERD_ERR_UNKNOWN) { | |
| 112 std::cerr << "Failed to import RDF from " << filename | |
| 113 << ": " << serd_strerror(rv) << std::endl; | |
| 114 } | |
| 104 } | 115 } | 
| 105 serd_reader_free(reader); | 116 serd_reader_free(reader); | 
| 106 serd_env_free(env); | 117 serd_env_free(env); | 
| 107 return success; | 118 return success; | 
| 108 } | 119 } | 
| 115 | 126 | 
| 116 auto li = library.rfind('.'); | 127 auto li = library.rfind('.'); | 
| 117 if (li == std::string::npos) return {}; | 128 if (li == std::string::npos) return {}; | 
| 118 auto withoutSuffix = library.substr(0, li); | 129 auto withoutSuffix = library.substr(0, li); | 
| 119 | 130 | 
| 120 std::vector<std::string> suffixes { "ttl", "TTL", "n3", "N3" }; | 131 std::vector<std::string> suffixes { "n3", "N3", "ttl", "TTL" }; | 
| 121 std::vector<std::string> candidates; | 132 std::vector<std::string> candidates; | 
| 122 | 133 | 
| 123 for (auto suffix : suffixes) { | 134 for (auto suffix : suffixes) { | 
| 124 candidates.push_back(withoutSuffix + "." + suffix); | 135 candidates.push_back(withoutSuffix + "." + suffix); | 
| 125 } | 136 } | 
| 126 | 137 | 
| 127 return candidates; | 138 return candidates; | 
| 128 } | 139 } | 
| 129 | 140 | 
| 130 void | 141 void | 
| 131 loadStaticOutputInfoFromModel(SordModel *model, std::string pluginKey, | 142 loadStaticOutputInfoFromModel(SordModel *model, | 
| 143 std::string pluginKey, | |
| 132 StaticOutputInfo &info) { | 144 StaticOutputInfo &info) { | 
| 145 | |
| 133 // we want to find a graph like | 146 // we want to find a graph like | 
| 147 // | |
| 134 // :plugin a vamp:Plugin | 148 // :plugin a vamp:Plugin | 
| 135 // :plugin vamp:identifier "pluginId" | 149 // :plugin vamp:identifier "pluginId" | 
| 136 // :library vamp:available_plugin :plugin | 150 // :library vamp:available_plugin :plugin | 
| 137 // :library vamp:identifier "libraryId" | 151 // :library vamp:identifier "libraryId" | 
| 138 // :plugin vamp:output :output1 | 152 // :plugin vamp:output :output1 | 
| 139 // :plugin vamp:output :output2 | 153 // :plugin vamp:output :output2 | 
| 140 // :plugin vamp:output :output3 | 154 // :plugin vamp:output :output3 | 
| 141 // :output1 vamp:computes_event_type :event | 155 // :output1 vamp:computes_event_type :event | 
| 142 // :output2 vamp:computes_feature :feature | 156 // :output2 vamp:computes_feature :feature | 
| 143 // :output3 vamp:computes_signal_type :signal | 157 // :output3 vamp:computes_signal_type :signal | 
| 144 // and where pluginKey == libraryId + ":" + pluginId | 158 // | 
| 145 | 159 // in which pluginKey == libraryId + ":" + pluginId | 
| 146 // Although, since we know we just loaded an RDF file | |
| 147 // associated with one particular plugin library, we could in | |
| 148 // theory skip the library bits. We'd still have most of the | |
| 149 // rest though since each library can have multiple plugins | |
| 150 // with output names that could conflict | |
| 151 | 160 | 
| 152 std::string libraryId, pluginId; | 161 std::string libraryId, pluginId; | 
| 153 decomposePluginKey(pluginKey, libraryId, pluginId); | 162 decomposePluginKey(pluginKey, libraryId, pluginId); | 
| 154 | 163 | 
| 155 //!!! | 164 typedef const uint8_t *S; | 
| 165 | |
| 166 SordNode *a = sord_new_uri | |
| 167 (m_world, S("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")); | |
| 168 | |
| 169 SordNode *pluginType = sord_new_uri | |
| 170 (m_world, S("http://purl.org/ontology/vamp/Plugin")); | |
| 171 | |
| 172 SordNode *identProp = sord_new_uri | |
| 173 (m_world, S("http://purl.org/ontology/vamp/identifier")); | |
| 174 SordNode *availProp = sord_new_uri | |
| 175 (m_world, S("http://purl.org/ontology/vamp/available_plugin")); | |
| 176 SordNode *outputProp = sord_new_uri | |
| 177 (m_world, S("http://purl.org/ontology/vamp/output")); | |
| 178 | |
| 179 SordNode *computesEventProp = sord_new_uri | |
| 180 (m_world, S("http://purl.org/ontology/vamp/computes_event_type")); | |
| 181 SordNode *computesFeatureProp = sord_new_uri | |
| 182 (m_world, S("http://purl.org/ontology/vamp/computes_feature")); | |
| 183 SordNode *computesSignalProp = sord_new_uri | |
| 184 (m_world, S("http://purl.org/ontology/vamp/computes_signal_type")); | |
| 185 | |
| 186 SordIter *pluginItr = 0; | |
| 187 | |
| 188 for (pluginItr = sord_search(model, 0, a, pluginType, 0); | |
| 189 !sord_iter_end(pluginItr); | |
| 190 sord_iter_next(pluginItr)) { | |
| 191 | |
| 192 const SordNode *pluginNode = | |
| 193 sord_iter_get_node(pluginItr, SORD_SUBJECT); | |
| 194 | |
| 195 SordNode *pluginIdNode = | |
| 196 sord_get(model, pluginNode, identProp, 0, 0); | |
| 197 | |
| 198 if (!pluginIdNode || | |
| 199 sord_node_get_type(pluginIdNode) != SORD_LITERAL || | |
| 200 (const char *)sord_node_get_string(pluginIdNode) != pluginId) { | |
| 201 // This is a plugin node, but it's not the plugin node | |
| 202 // we're looking for. (We have to check both the type | |
| 203 // property, vamp:Plugin, and the identifier, | |
| 204 // vamp:identifier, because the identifier is just a | |
| 205 // string and it's possible it could be used for an | |
| 206 // output or parameter rather than just a plugin.) | |
| 207 continue; | |
| 208 } | |
| 209 | |
| 210 SordNode *libraryNode = | |
| 211 sord_get(model, 0, availProp, pluginNode, 0); | |
| 212 | |
| 213 if (!libraryNode) { | |
| 214 std::cerr << "Plugin is not listed as being in a library, " | |
| 215 << "skipping library id check" << std::endl; | |
| 216 } else { | |
| 217 SordNode *libIdNode = | |
| 218 sord_get(model, libraryNode, identProp, 0, 0); | |
| 219 if (!libIdNode || | |
| 220 sord_node_get_type(libIdNode) != SORD_LITERAL || | |
| 221 (const char *)sord_node_get_string(libIdNode) != libraryId) { | |
| 222 std::cerr << "Ignoring plugin in wrong library" << std::endl; | |
| 223 continue; | |
| 224 } | |
| 225 } | |
| 226 | |
| 227 SordIter *outputItr = 0; | |
| 228 | |
| 229 for (outputItr = sord_search(model, pluginNode, outputProp, 0, 0); | |
| 230 !sord_iter_end(outputItr); | |
| 231 sord_iter_next(outputItr)) { | |
| 232 | |
| 233 const SordNode *outputNode = | |
| 234 sord_iter_get_node(outputItr, SORD_OBJECT); | |
| 235 | |
| 236 SordNode *outputIdNode = | |
| 237 sord_get(model, outputNode, identProp, 0, 0); | |
| 238 | |
| 239 if (!outputIdNode || | |
| 240 sord_node_get_type(outputIdNode) != SORD_LITERAL || | |
| 241 !sord_node_get_string(outputIdNode)) { | |
| 242 std::cerr << "Ignoring output with no id" << std::endl; | |
| 243 continue; | |
| 244 } | |
| 245 | |
| 246 std::string outputId = | |
| 247 (const char *)sord_node_get_string(outputIdNode); | |
| 248 | |
| 249 SordIter *propItr = 0; | |
| 250 | |
| 251 for (propItr = sord_search(model, outputNode, 0, 0, 0); | |
| 252 !sord_iter_end(propItr); | |
| 253 sord_iter_next(propItr)) { | |
| 254 | |
| 255 const SordNode *propNode = | |
| 256 sord_iter_get_node(propItr, SORD_PREDICATE); | |
| 257 | |
| 258 if (sord_node_equals(propNode, computesEventProp) || | |
| 259 sord_node_equals(propNode, computesFeatureProp) || | |
| 260 sord_node_equals(propNode, computesSignalProp)) { | |
| 261 | |
| 262 const SordNode *computesNode = | |
| 263 sord_iter_get_node(propItr, SORD_OBJECT); | |
| 264 | |
| 265 if (sord_node_get_type(computesNode) != SORD_URI || | |
| 266 !sord_node_get_string(computesNode)) { | |
| 267 std::cerr << "Ignoring non-URI computes node" | |
| 268 << std::endl; | |
| 269 continue; | |
| 270 } | |
| 271 | |
| 272 std::string typeURI = | |
| 273 (const char *)sord_node_get_string(computesNode); | |
| 274 | |
| 275 std::cerr << "Found type <" << typeURI | |
| 276 << "> for output \"" << outputId | |
| 277 << "\" of plugin \"" << pluginId | |
| 278 << "\" in library " << libraryId | |
| 279 << std::endl; | |
| 280 | |
| 281 StaticOutputDescriptor desc; | |
| 282 desc.typeURI = typeURI; | |
| 283 info[outputId] = desc; | |
| 284 | |
| 285 break; // only interested in one "computes" property | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 sord_iter_free(propItr); | |
| 290 } | |
| 291 | |
| 292 sord_iter_free(outputItr); | |
| 293 } | |
| 294 | |
| 295 sord_iter_free(pluginItr); | |
| 156 } | 296 } | 
| 157 | 297 | 
| 158 bool decomposePluginKey(std::string pluginKey, | 298 bool decomposePluginKey(std::string pluginKey, | 
| 159 std::string &libraryId, | 299 std::string &libraryId, | 
| 160 std::string &pluginId) { | 300 std::string &pluginId) { | 
