PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/model/semantics/RDFMapper.class.php

https://github.com/lievenjanssen/The-DataTank
PHP | 361 lines | 169 code | 53 blank | 139 comment | 36 complexity | 417f091bf5802fe718fbcbd8290e1cb9 MD5 | raw file
  1. <?php
  2. /**
  3. * This class RDFMapper maps resources from a package to RDF classes. It auto generates mapping schemes and handles modifications from the user,
  4. *
  5. * @package The-Datatank/model/semantics
  6. * @copyright (C) 2011 by iRail vzw/asbl
  7. * @license AGPLv3
  8. * @author Miel Vander Sande
  9. */
  10. include_once('RDFConstants.php');
  11. class RDFMapper {
  12. /**
  13. * Method called for updating the mapping model. This method responds to a POST request on a specific resource.
  14. *
  15. * @param string $tdt_package The name of the package containing the resource
  16. * @param string $tdt_resource The path of the resource
  17. * @param array $content Array containing POST variables
  18. * @return ResModel
  19. * @access public
  20. */
  21. public function update($tdt_package, $tdt_resource, $content) {
  22. if (isset($content['rdf_mapping_method'])) {
  23. //If rdf_mapping_bash is set, user wants to map multiple related resources instead of only this resource
  24. if (isset($content['rdf_mapping_bash'])) {
  25. //Call method stripResourcePath to get the base url
  26. $tdt_resource = $this->stripResourcePath($tdt_resource);
  27. //Append new indexes or * to the resource path
  28. if ($content['rdf_mapping_bash'] == '*') {
  29. $this->executeMethod($tdt_package, $tdt_resource . '*', $content);
  30. } else if (is_numeric($content['rdf_mapping_bash'])) {
  31. //Just one index is specified
  32. $this->executeMethod($tdt_package, $tdt_resource . $content['rdf_mapping_bash'], $content);
  33. } else if (strpos($content['rdf_mapping_bash'], ',')) {
  34. //Multiple indexes are specified
  35. $indexes = explode(',', $content['rdf_mapping_bash']);
  36. foreach ($indexes as $value) {
  37. $this->executeMethod($tdt_package, $tdt_resource . $value, $content);
  38. }
  39. } else {
  40. throw new RdfTDTException('Value of rdf_mapping_bash is not correct');
  41. }
  42. } else {
  43. $this->executeMethod($tdt_package, $tdt_resource, $content);
  44. }
  45. } else {
  46. throw new RdfTDTException('Mapping method not specified');
  47. }
  48. }
  49. /**
  50. * Removes the last rest parameter
  51. *
  52. * @param string $tdt_resource URI of the resource
  53. * @return string URI without trailing slash
  54. */
  55. private function stripResourcePath($tdt_resource) {
  56. //We need to rewrite the resource url to add the right mapping
  57. //Find position of last slash
  58. $pos = strripos($tdt_resource, '/');
  59. //Check if the url ends on a slash. If so, remove the slash en check position of last slash again.
  60. if ($pos == strlen($tdt_resource) - 1)
  61. $pos = strripos(substr($tdt_resource, 0, strlen($tdt_resource) - 1), '/');
  62. //remove everything behind the slash to get base URI and return
  63. return substr($tdt_resource, 0, $pos + 1);
  64. }
  65. /**
  66. * Executes the right operation on the mapping model, specified in .
  67. *
  68. * @param string $tdt_package The name of the package containing the resource
  69. * @param string $tdt_resource The path of the resource
  70. * @param array $content Array containing POST variables
  71. * @return ResModel
  72. * @access private
  73. */
  74. private function executeMethod($tdt_package, $tdt_resource, $content) {
  75. switch ($content['rdf_mapping_method']) {
  76. case RDFConstants::$MAPPING_UPDATE :
  77. if (isset($content['rdf_mapping_nmsp']))
  78. $this->addMappingStatement($tdt_package, $tdt_resource, $content['rdf_mapping_class'], $content['rdf_mapping_nmsp']);
  79. else
  80. $this->addMappingStatement($tdt_package, $tdt_resource, $content['rdf_mapping_class']);
  81. break;
  82. case RDFConstants::$MAPPING_DELETE :
  83. $this->removeMappingStatement($tdt_package, $tdt_resource);
  84. break;
  85. case RDFConstants::$MAPPING_EQUALS :
  86. $this->equalMappingStatement($tdt_package, $tdt_resource, $content['rdf_mapping_class']);
  87. break;
  88. default:
  89. throw new RdfTDTException('Mapping method does not exist');
  90. }
  91. }
  92. /**
  93. * Gets the current URI of the mapping model
  94. *
  95. * @param string $tdt_package
  96. * @return string
  97. */
  98. private function getMappingURI($tdt_package) {
  99. return $mapURI = Config::$HOSTNAME . Config::$SUBDIR . $tdt_package . '/';
  100. }
  101. /**
  102. * Method called for updating the mapping model. This method responds to a POST request on a specific resource.
  103. *
  104. * @param ResModel $model The model containing the mapping
  105. * @param string $tdt_resource The path of the resource
  106. * @param array $content Array containing POST variables
  107. * @return ResModel
  108. * @access public
  109. */
  110. private function buildNewMapping(&$model, $tdt_package) {
  111. $model->addNamespace("tdtml", RDFConstants::$TDML_NS);
  112. $model->addNamespace("owl", OWL_NS);
  113. // Using the Resource-Centric method
  114. // Create the resources
  115. $package_res = $model->createResource($this->getMappingURI($tdt_package));
  116. $tdtpackage_res = $model->createResource(RDFConstants::$TDML_NS . "TDTPackage");
  117. $tdtresource_res = $model->createResource(RDFConstants::$TDML_NS . "TDTResource");
  118. $tdtproperty_res = $model->createResource(RDFConstants::$TDML_NS . "TDTProperty");
  119. //creating TDTML property resources
  120. $name_prop = $model->createProperty(RDFConstants::$TDML_NS . "name");
  121. $has_resources_prop = $model->createProperty(RDFConstants::$TDML_NS . "has_resources");
  122. $maps_prop = $model->createProperty(RDFConstants::$TDML_NS . "maps");
  123. //Creating literal
  124. $package_name_lit = $model->createTypedLiteral($tdt_package, "datatype:STRING");
  125. // Add the properties
  126. $package_res->addProperty(RDF_RES::TYPE(), $tdtpackage_res);
  127. $package_res->addProperty($name_prop, $package_name_lit);
  128. $resources_list = $model->createList();
  129. $package_res->addProperty($has_resources_prop, $resources_list);
  130. $package_res->addProperty($maps_prop, RDF_RES::DESCRIPTION());
  131. //Get all resources in package
  132. $doc = ResourcesModel::getInstance()->getAllDoc();
  133. //limit the rources to the required package
  134. $allresources = get_object_vars($doc);
  135. foreach ($allresources[$tdt_package] as $resource => $val) {
  136. $resource_res = $model->createResource($this->getMappingURI($tdt_package) . $resource);
  137. $resources_list->add($resource_res);
  138. $resource_name_lit = $model->createTypedLiteral($resource, "datatype:STRING");
  139. $resource_res->addProperty($name_prop, $resource_name_lit);
  140. $resource_res->addProperty(RDF_RES::TYPE(), $tdtresource_res);
  141. $resource_res->addProperty($maps_prop, RDF_RES::DESCRIPTION());
  142. }
  143. }
  144. /**
  145. * Gets the ResModel object containing the mapping file for a package.
  146. *
  147. * @param string $tdt_package The name of the package
  148. * @return ResModel
  149. * @access public
  150. */
  151. public function getMappingModel($tdt_package) {
  152. $store = RbModelFactory::getRbStore();
  153. //gets the model if it exist, else make a new one. Either way, it's the right one.
  154. //Gets a ResModel containing an RbModel, which doesn't store statements in memory, only in db.
  155. $model = RbModelFactory::getResModel(RBMODEL, $this->getMappingURI($tdt_package));
  156. //If the model has no statements, give it a basic mapping structure
  157. if ($model->isEmpty())
  158. $this->buildNewMapping($model, $tdt_package);
  159. return $model;
  160. }
  161. /**
  162. * Adds a mapping between TDT Resource and a resource. If a mapping already exists for this resource, it gets updated.
  163. * The class is known internally or described in suplied onthology namespace.
  164. *
  165. * @param string $tdt_package The name of the package containing the resource
  166. * @param string $tdt_resource The path of the resource
  167. * @param string $class The name of the class to map the resource to.
  168. * @param string $nmsp OPTIONAL The namespace where the class belongs to.
  169. * @access private
  170. */
  171. private function addMappingStatement($tdt_package, $tdt_resource, $class, $nmsp = null) {
  172. if (!(isset($tdt_package) && isset($tdt_resource) && isset($class)))
  173. throw new RdfTDTException('Package, Resource or Mapping class unknown ');
  174. $model = $this->getMappingModel($tdt_package);
  175. $resource = $model->createResource($tdt_resource);
  176. $property = $model->createProperty(RDFConstants::$TDML_NS . "maps");
  177. //adding the class to the mapping
  178. //Implements:
  179. // - namespace+classname as $class
  180. // - prefix:classname only if prefix of internally known library
  181. // - namespace,classname seperate
  182. // - short:classname, namespace both available
  183. // Add a new namespace to the model!!
  184. $prefix = '';
  185. if (stripos($class, ":")) {
  186. $explode = explode(":", $class);
  187. $prefix = $explode[0];
  188. $class = $explode[1];
  189. }
  190. //retrieve the right namespace and class
  191. if (is_null($nmsp)) {
  192. if (!(array_key_exists($prefix, RDFConstants::$VOCABULARIES)))
  193. throw new RdfTDTException('Namespace ' . $prefix . ' is unknown. Specify namespace URI in rdf_mapping_nmsp POST variable.');
  194. $nmsp = RDFConstants::$VOCABULARIES[$prefix];
  195. } else {
  196. if ($prefix == '')
  197. $prefix = array_search($nmsp, RDFConstants::$VOCABULARIES);
  198. }
  199. $object = new ResResource($nmsp . $class);
  200. //add the namespace to the model
  201. $model->addNamespace($prefix, $nmsp);
  202. //Does this resource already have a mapping?
  203. if ($resource->hasProperty($property)) {
  204. //remove existing mapping first
  205. $resource->removeAll($property);
  206. }
  207. $resource->addProperty($property, $object);
  208. }
  209. /**
  210. * Maps a TDT resource to another, but equal TDT resource.
  211. *
  212. * @param string $tdt_package The name of the package containing the resource
  213. * @param string $tdt_resource The path of the resource
  214. * @return bool Returns true if mapping is renovedcorrectly.
  215. * @access private
  216. */
  217. private function equalMappingStatement($tdt_package, $tdt_resource, $equal_resource) {
  218. if (!(isset($tdt_package) && isset($tdt_resource) && isset($equal_resource)))
  219. throw new RdfTDTException('Package, Resource or Equal resource unknown ');
  220. $model = $this->getMappingModel($tdt_package);
  221. $resource = $model->createResource($this->getMappingURI($tdt_package) . $tdt_resource);
  222. $object = $model->createResource($equal_resource);
  223. $equals_prop = $model->createProperty(OWL_RES::SAME_AS());
  224. $maps_prop = $model->createProperty(RDFConstants::$TDML_NS . "maps");
  225. $resource->addProperty($equals_prop, $object);
  226. $object->addProperty($equals_prop, $resource);
  227. //$map = $object->getProperty($maps_prop);
  228. //$resource->addProperty($maps_prop, $map);
  229. }
  230. /**
  231. * Removes a mapping between TDT Resource and a resource.
  232. *
  233. * @param string $tdt_package The name of the package containing the resource
  234. * @param string $tdt_resource The path of the resource
  235. * @return bool Returns true if mapping is removed correctly.
  236. * @access private
  237. */
  238. private function removeMappingStatement($tdt_package, $tdt_resource) {
  239. if (!(isset($tdt_package) && isset($tdt_resource)))
  240. throw new RdfTDTException('Package or Resource unknown ');
  241. $model = $this->getMappingModel($tdt_package);
  242. $subject = $model->createResource($this->getMappingURI($tdt_package) . $tdt_resource);
  243. $statements = $model->find($subject, RDFConstants::$TDML_NS . 'maps', null);
  244. foreach ($statements as $statement) {
  245. if (!$model->remove($statement))
  246. throw new RdfTDTException('Mapping statement of ' . $statement->getSubject()->toString() . ' was not deleted');
  247. }
  248. }
  249. public function getMappingNamespaces($tdt_package){
  250. $model = $this->getMappingModel($tdt_package);
  251. $namespaces = $model->getParsedNamespaces();
  252. unset($namespaces[RDFConstants::$TDML_NS]);
  253. return $namespaces;
  254. }
  255. /**
  256. * Returns a ResResource containing the mapped resource of a TDT resource.
  257. *
  258. * @param string $tdt_package The name of the package containing the resource
  259. * @param string $tdt_resource The path of the resource
  260. * @return ResResoure
  261. * @access public
  262. */
  263. public function getResourceMapping($tdt_package, $tdt_resource) {
  264. if (!(isset($tdt_package) && isset($tdt_resource)))
  265. throw new RdfTDTException('Package or Resource unknown ');
  266. //Retrieve mapping model from db.
  267. $model = $this->getMappingModel($tdt_package);
  268. $mapping = $this->lookupMapping($model, $tdt_resource);
  269. //If no mapping is found, check if there is a generic mapping
  270. if (is_null($mapping)) {
  271. //rewrite URI to generic
  272. $tdt_resource = $this->stripResourcePath($tdt_resource) . '*';
  273. $mapping = $this->lookupMapping($model, $tdt_resource);
  274. }
  275. if (is_null($mapping))
  276. return null;
  277. else
  278. //Object of the triple is the needed class
  279. return $mapping->getObject();
  280. }
  281. /**
  282. * Look up resource that is mapped to this resource
  283. *
  284. * @param ResModel $model
  285. * @param string $tdt_resource
  286. * @return ResResource
  287. */
  288. private function lookupMapping($model, $tdt_resource) {
  289. $resource_res = $model->createResource($tdt_resource);
  290. $maps_prop = $model->createProperty(RDFConstants::$TDML_NS . "maps");
  291. //Looks for the first triple statement where the resource has the TDML maps property.
  292. $mapping = $model->findFirstMatchingStatement($resource_res, $maps_prop, null);
  293. return $mapping;
  294. }
  295. /**
  296. * Look up resources that are equal to this resource
  297. *
  298. * @param ResModel $model
  299. * @param string $tdt_resource
  300. * @return array Array of Statement objects containing equal resources
  301. */
  302. private function lookupEquals($model, $tdt_resource) {
  303. $resource_res = $model->createResource($tdt_resource);
  304. $equals_prop = $model->createProperty(OWL_RES::SAME_AS());
  305. return $resource_res->listProperties($equals_prop);
  306. }
  307. }
  308. ?>