PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/moriarty/moriarty/sparqlservicebase.class.php

https://github.com/kwijibo/trafficscotland-linkeddata
PHP | 394 lines | 249 code | 45 blank | 100 comment | 99 complexity | 0ef2188b16c4c56d9523eeb299ceca94 MD5 | raw file
  1. <?php
  2. require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'moriarty.inc.php';
  3. require_once MORIARTY_ARC_DIR . DIRECTORY_SEPARATOR . "ARC2.php";
  4. /**
  5. * Represents the base class for various sparql services.
  6. */
  7. class SparqlServiceBase {
  8. /**
  9. * @access private
  10. */
  11. var $uri;
  12. /**
  13. * @access private
  14. */
  15. var $request_factory;
  16. /**
  17. * @access private
  18. */
  19. var $credentials;
  20. /**
  21. * Create a new instance of this class
  22. * @param string uri URI of the sparql service
  23. * @param Credentials credentials the credentials to use for authenticated requests (optional)
  24. */
  25. function __construct($uri, $credentials = null, $request_factory = null) {
  26. $this->uri = $uri;
  27. $this->credentials = $credentials;
  28. $this->request_factory = $request_factory;
  29. }
  30. /**
  31. * Obtain a bounded description of a given resource. Various types of description are supported:
  32. * <ul>
  33. * <li><em>cbd</em> - concise bounded description</li>
  34. * <li><em>scbd</em> - symmetric bounded description</li>
  35. * <li><em>lcbd</em> - labelled bounded description</li>
  36. * <li><em>slcbd</em> - symmetric labelled bounded description</li>
  37. * </ul>
  38. * See http://n2.talis.com/wiki/Bounded_Descriptions_in_RDF for more information on these types of description
  39. * Only cbd type is supported for arrays of URIs
  40. * @param mixed uri the URI of the resource to be described or an array of URIs
  41. * @param string type the type of bounded description to be obtained (optional)
  42. * @param string output the format of the RDF to return - one of rdf, turtle, ntriples or json (optional)
  43. * @return HttpResponse
  44. */
  45. function describe( $uri, $type = 'cbd', $output = OUTPUT_TYPE_RDF ) {
  46. if ( is_array( $uri ) ) {
  47. $query="DESCRIBE <" . implode('> <' , $uri) . ">";
  48. }
  49. else {
  50. if ($type == 'scbd') {
  51. $query = "CONSTRUCT {<$uri> ?p ?o . ?s ?p2 <$uri> .} WHERE { {<$uri> ?p ?o .} UNION {?s ?p2 <$uri> .} }";
  52. }
  53. else if ($type == 'lcbd') {
  54. // $query = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> CONSTRUCT {<$uri> ?p ?o . ?o rdfs:label ?label . ?o rdfs:comment ?comment . ?o rdfs:seeAlso ?seealso.} WHERE {<$uri> ?p ?o . OPTIONAL { ?o rdfs:label ?label .} OPTIONAL {?o rdfs:comment ?comment . } OPTIONAL {?o rdfs:seeAlso ?seealso.}}";
  55. $query = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> CONSTRUCT {<$uri> ?p ?o . ?o rdfs:label ?label . ?o rdfs:comment ?comment . ?o <http://www.w3.org/2004/02/skos/core#prefLabel> ?plabel . ?o rdfs:seeAlso ?seealso.} WHERE {<$uri> ?p ?o . OPTIONAL { ?o rdfs:label ?label .} OPTIONAL {?o <http://www.w3.org/2004/02/skos/core#prefLabel> ?plabel . } OPTIONAL {?o rdfs:comment ?comment . } OPTIONAL {?o rdfs:seeAlso ?seealso.}}";
  56. }
  57. else if ($type == 'slcbd') {
  58. $query = "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> CONSTRUCT {<$uri> ?p ?o . ?o rdfs:label ?label . ?o rdfs:comment ?comment . ?o rdfs:seeAlso ?seealso. ?s ?p2 <$uri> . ?s rdfs:label ?label . ?s rdfs:comment ?comment . ?s rdfs:seeAlso ?seealso.} WHERE { { <$uri> ?p ?o . OPTIONAL {?o rdfs:label ?label .} OPTIONAL {?o rdfs:comment ?comment .} OPTIONAL {?o rdfs:seeAlso ?seealso.} } UNION {?s ?p2 <$uri> . OPTIONAL {?s rdfs:label ?label .} OPTIONAL {?s rdfs:comment ?comment .} OPTIONAL {?s rdfs:seeAlso ?seealso.} } }";
  59. }
  60. else {
  61. $query="DESCRIBE <$uri>";
  62. }
  63. }
  64. return $this->graph($query, $output);
  65. }
  66. /**
  67. * @deprecated triple lists are deprecated
  68. */
  69. function describe_to_triple_list( $uri ) {
  70. $triples = array();
  71. $response = $this->describe( $uri );
  72. $parser_args=array(
  73. "bnode_prefix"=>"genid",
  74. "base"=> $this->uri
  75. );
  76. $parser = ARC2::getRDFXMLParser($parser_args);
  77. if ( $response->body ) {
  78. $parser->parse($this->uri, $response->body );
  79. $triples = $parser->getTriples();
  80. }
  81. return $triples;
  82. }
  83. /**
  84. * Obtain a bounded description of a given resource as a SimpleGraph. An empty SimpleGraph is returned if any HTTP errors occur.
  85. * @param mixed uri the URI of the resource to be described or an array of URIs
  86. * @return SimpleGraph
  87. */
  88. function describe_to_simple_graph( $uri, $type='cbd' ) {
  89. $graph = new SimpleGraph();
  90. $response = $this->describe( $uri, $type, OUTPUT_TYPE_JSON );
  91. if ( $response->is_success() ) {
  92. $graph->from_json( $response->body );
  93. }
  94. return $graph;
  95. }
  96. /**
  97. * Execute an arbitrary query on the sparql service. Will use GET for short queries to enhance cacheability.
  98. * @param string query the query to execute
  99. * @param string mime the media type of the expected response or the short name as listed at http://n2.talis.com/wiki/Store_Sparql_Service#Output_Formats (optional, defaults to RDF/XML and SPARQL results XML)
  100. * @return HttpResponse
  101. */
  102. function query($query, $mime=''){
  103. if (empty( $this->request_factory) ) {
  104. $this->request_factory = new HttpRequestFactory();
  105. }
  106. $get_uri = $this->get_query_uri($query, $mime);
  107. if (strlen($get_uri) <= $this->get_max_uri_length()) {
  108. $request = $this->request_factory->make( 'GET', $get_uri, $this->credentials );
  109. if ( empty($mime) || strstr($mime, '/') === FALSE) $mime = '*/*'; // In this case the mime arg has already been added as an output parameter
  110. $request->set_accept($mime);
  111. }
  112. else {
  113. $request = $this->request_factory->make( 'POST', $this->uri, $this->credentials );
  114. if(empty($mime)) $mime = '*/*';
  115. if ( empty($mime) || strstr($mime, '/') === FALSE) $mime = '*/*'; // In this case the mime arg has already been added as an output parameter
  116. $request->set_accept($mime);
  117. $request->set_content_type(MIME_FORMENCODED);
  118. $request->set_body( $this->get_query_params($query, $mime) );
  119. }
  120. return $request->execute();
  121. }
  122. function get_max_uri_length() {
  123. return 1024;
  124. }
  125. function get_query_params($query, $mime = '') {
  126. $params = 'query=' . urlencode($query);
  127. if ( !empty($mime) && strstr($mime, '/') === FALSE) {
  128. $params .= '&output=' . $mime;
  129. $mime = '*/*';
  130. }
  131. return $params;
  132. }
  133. function get_query_uri($query, $mime = '') {
  134. return $this->uri . '?' . $this->get_query_params($query, $mime);
  135. }
  136. /**
  137. * Execute a graph type sparql query, i.e. a describe or a construct
  138. * @param string query the describe or construct query to execute
  139. * @return HttpResponse
  140. */
  141. function graph( $query, $output = 'rdf' ) {
  142. return $this->query($query, $output);
  143. }
  144. /**
  145. * @deprecated triple lists are deprecated
  146. */
  147. function graph_to_triple_list($query ) {
  148. $triples = array();
  149. $response = $this->graph( $query );
  150. $parser_args=array(
  151. "bnode_prefix"=>"genid",
  152. "base"=> $this->uri
  153. );
  154. $parser = ARC2::getRDFXMLParser($parser_args);
  155. if ( $response->body ) {
  156. $parser->parse($this->uri, $response->body );
  157. $triples = $parser->getTriples();
  158. }
  159. return $triples;
  160. }
  161. /**
  162. * @deprecated triple lists are deprecated
  163. */
  164. function construct_to_triple_list($query ) {
  165. return $this->graph_to_triple_list($query );
  166. }
  167. /**
  168. * Execute a graph type sparql query and obtain the result as a SimpleGraph. An empty SimpleGraph is returned if any HTTP errors occur.
  169. * @param string query the describe or construct query to execute
  170. * @return SimpleGraph
  171. */
  172. function graph_to_simple_graph( $query ) {
  173. $graph = new SimpleGraph();
  174. $response = $this->graph( $query );
  175. if ( $response->is_success() ) {
  176. $graph->from_rdfxml( $response->body );
  177. }
  178. return $graph;
  179. }
  180. /**
  181. * @deprecated use graph_to_simple_graph
  182. */
  183. function construct_to_simple_graph( $query ) {
  184. return $this->graph_to_simple_graph($query);
  185. }
  186. /**
  187. * Execute a select sparql query
  188. * @param string query the select query to execute
  189. * @return HttpResponse
  190. */
  191. function select( $query ) {
  192. return $this->query($query, MIME_SPARQLRESULTS);
  193. }
  194. /**
  195. * Execute a select sparql query and return the results as an array. An empty array is returned if any HTTP errors occur.
  196. * @param string query the select query to execute
  197. * @return array parsed results in format returned by parse_select_results method
  198. */
  199. function select_to_array( $query ) {
  200. $results = array();
  201. $response = $this->select( $query );
  202. if ( $response->is_success() ) {
  203. $results = $this->parse_select_results( $response->body );
  204. }
  205. return $results;
  206. }
  207. /**
  208. * Parse the SPARQL XML results format into an array. The array consist of one element per result.
  209. * Each element is an associative array where the keys correspond to the variable name and the values are
  210. * another associative array with the following keys:
  211. * <ul>
  212. * <li><em>type</em> => the type of the result binding, one of 'uri', 'literal' or 'bnode'</li>
  213. * <li><em>value</em> => the value of the result binding</li>
  214. * <li><em>lang</em> => the language code (if any) of the result binding</li>
  215. * <li><em>datatype</em> => the datatype uri (if any) of the result binding</li>
  216. * </ul>
  217. * For example: $results[2]['foo']['value'] will obtain the value of the foo variable for the third result
  218. * @param string xml the results XML to parse
  219. * @return array
  220. */
  221. function parse_select_results( $xml ) {
  222. $results = array();
  223. $reader = new XMLReader();
  224. $reader->XML($xml);
  225. $result = array();
  226. $bindingName = null;
  227. $binding = array();
  228. while ($reader->read()) {
  229. if ( $reader->name == 'result') {
  230. if ( $reader->nodeType == XMLReader::ELEMENT) {
  231. $result = array();
  232. }
  233. elseif ( $reader->nodeType == XMLReader::END_ELEMENT) {
  234. array_push( $results, $result);
  235. $result = array();
  236. }
  237. }
  238. elseif ( $reader->name == 'binding') {
  239. if ( $reader->nodeType == XMLReader::ELEMENT) {
  240. $bindingName = $reader->getAttribute("name");
  241. $binding = array();
  242. }
  243. elseif ( $reader->nodeType == XMLReader::END_ELEMENT) {
  244. $result[ $bindingName ] = $binding;
  245. $bindingName = null;
  246. $binding = array();
  247. }
  248. }
  249. elseif ( $reader->name == 'uri' && $reader->nodeType == XMLReader::ELEMENT) {
  250. $binding['type'] = 'uri';
  251. $value = '';
  252. while ($reader->read()) {
  253. if ($reader->nodeType == XMLReader::TEXT
  254. || $reader->nodeType == XMLReader::CDATA
  255. || $reader->nodeType == XMLReader::WHITESPACE
  256. || $reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE) {
  257. $value .= $reader->value;
  258. }
  259. else if ($reader->nodeType == XMLReader::END_ELEMENT) {
  260. break;
  261. }
  262. }
  263. $binding['value'] = $value;
  264. }
  265. elseif ( $reader->name == 'literal' && $reader->nodeType == XMLReader::ELEMENT) {
  266. $binding['type'] = 'literal';
  267. $datatype = $reader->getAttribute("datatype");
  268. if ( $datatype ) {
  269. $binding['datatype'] = $datatype;
  270. }
  271. $lang = $reader->getAttribute("xml:lang");
  272. if ( $lang ) {
  273. $binding['lang'] = $lang;
  274. }
  275. $value = '';
  276. while ($reader->read()) {
  277. if ($reader->nodeType == XMLReader::TEXT
  278. || $reader->nodeType == XMLReader::CDATA
  279. || $reader->nodeType == XMLReader::WHITESPACE
  280. || $reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE) {
  281. $value .= $reader->value;
  282. }
  283. else if ($reader->nodeType == XMLReader::END_ELEMENT) {
  284. break;
  285. }
  286. }
  287. $binding['value'] = $value;
  288. }
  289. elseif ( $reader->name == 'bnode' && $reader->nodeType == XMLReader::ELEMENT) {
  290. $binding['type'] = 'bnode';
  291. $value = '';
  292. while ($reader->read()) {
  293. if ($reader->nodeType == XMLReader::TEXT
  294. || $reader->nodeType == XMLReader::CDATA
  295. || $reader->nodeType == XMLReader::WHITESPACE
  296. || $reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE) {
  297. $value .= $reader->value;
  298. }
  299. else if ($reader->nodeType == XMLReader::END_ELEMENT) {
  300. break;
  301. }
  302. }
  303. $binding['value'] = $value;
  304. }
  305. }
  306. $reader->close();
  307. return $results;
  308. }
  309. /**
  310. * Execute an ask sparql query
  311. * @param string query the ask query to execute
  312. * @return HttpResponse
  313. */
  314. function ask( $query ) {
  315. return $this->query($query, MIME_SPARQLRESULTS);
  316. }
  317. /**
  318. * Parse the SPARQL XML results format from an ask query.
  319. * @param string xml the results XML to parse
  320. * @return array true if the query result was true, false otherwise
  321. */
  322. function parse_ask_results( $xml ) {
  323. $reader = new XMLReader();
  324. $reader->XML($xml);
  325. $result = false;
  326. $bindingName = null;
  327. $binding = array();
  328. while ($reader->read()) {
  329. if ( $reader->name == 'boolean') {
  330. $value = '';
  331. while ($reader->read()) {
  332. if ($reader->nodeType == XMLReader::TEXT
  333. || $reader->nodeType == XMLReader::CDATA
  334. || $reader->nodeType == XMLReader::WHITESPACE
  335. || $reader->nodeType == XMLReader::SIGNIFICANT_WHITESPACE) {
  336. $value .= $reader->value;
  337. }
  338. else if ($reader->nodeType == XMLReader::END_ELEMENT) {
  339. break;
  340. }
  341. }
  342. $reader->close();
  343. return ( strtolower(trim($value)) == 'true' );
  344. }
  345. }
  346. return false;
  347. }
  348. }
  349. ?>