PageRenderTime 60ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/Erfurt/Sparql/EngineDb/ResultRenderer/Plain.php

http://github.com/AKSW/Erfurt
PHP | 513 lines | 343 code | 62 blank | 108 comment | 61 complexity | 92b98396ca24481470da938304638ea2 MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the {@link http://aksw.org/Projects/Erfurt Erfurt} project.
  4. *
  5. * @copyright Copyright (c) 2012, {@link http://aksw.org AKSW}
  6. * @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
  7. */
  8. require_once 'Erfurt/Sparql/EngineDb/ResultRenderer.php';
  9. /**
  10. * Result renderer that creates a text array
  11. *
  12. * This class was originally adopted from rdfapi-php (@link http://sourceforge.net/projects/rdfapi-php/).
  13. * It was modified and extended in order to fit into Erfurt.
  14. *
  15. * @package Erfurt_Sparql_EngineDb_ResultRenderer
  16. * @author Christian Weiske <cweiske@cweiske.de>
  17. * @author Philipp Frischmuth <pfrischmuth@googlemail.com>
  18. * @license http://www.gnu.org/licenses/lgpl.html LGPL
  19. */
  20. class Erfurt_Sparql_EngineDb_ResultRenderer_Plain implements Erfurt_Sparql_EngineDb_ResultRenderer
  21. {
  22. // ------------------------------------------------------------------------
  23. // --- Protected properties -----------------------------------------------
  24. // ------------------------------------------------------------------------
  25. protected $uriValues = array();
  26. protected $literalValues = array();
  27. protected $_vars = null;
  28. // ------------------------------------------------------------------------
  29. // --- Public methods -----------------------------------------------------
  30. // ------------------------------------------------------------------------
  31. /**
  32. * Converts the database results into the desired output format
  33. * and returns the result.
  34. *
  35. * @param array $arRecordSets Array of (possibly several) SQL query results.
  36. * @param Erfurt_Sparql_Query $query SPARQL query object
  37. * @param $engine Sparql Engine to query the database
  38. * @return array
  39. */
  40. public function convertFromDbResults($arRecordSets, Erfurt_Sparql_Query $query, $engine, $vars)
  41. {
  42. $this->query = $query;
  43. $this->engine = $engine;
  44. $this->_vars = $vars;
  45. $strResultForm = $this->query->getResultForm();
  46. switch ($strResultForm) {
  47. case 'construct':
  48. case 'select':
  49. case 'select distinct':
  50. switch ($strResultForm) {
  51. case 'construct':
  52. $arResult = $this->_getVariableArrayFromRecordSets($arRecordSets, $strResultForm, true);
  53. break;
  54. default:
  55. $arResult = $this->_getVariableArrayFromRecordSets($arRecordSets, $strResultForm, false);
  56. if (count($this->uriValues) > 0 || count($this->literalValues) > 0) {
  57. // If the query contains a ORDER BY wen need to reorder the result
  58. $sm = $query->getSolutionModifier();
  59. if (null !== $sm['order by']) {
  60. foreach ($sm['order by'] as $order) {
  61. $n = count($arResult);
  62. $id = ltrim($order['val'], '?$');
  63. while (true) {
  64. $hasChanged = false;
  65. for ($i=0; $i<$n-1; ++$i) {
  66. switch ($order['type']) {
  67. case 'desc':
  68. if ($arResult[$i][$id] < $arResult[($i+1)][$id]) {
  69. $dummy = $arResult[$i][$id];
  70. $arResult[$i][$id] = $arResult[($i+1)][$id];
  71. $arResult[($i+1)][$id] = $dummy;
  72. $hasChanged = true;
  73. }
  74. break;
  75. case 'asc':
  76. default:
  77. if ($arResult[$i][$id] > $arResult[($i+1)][$id]) {
  78. $dummy = $arResult[$i][$id];
  79. $arResult[$i][$id] = $arResult[($i+1)][$id];
  80. $arResult[($i+1)][$id] = $dummy;
  81. $hasChanged = true;
  82. }
  83. break;
  84. }
  85. }
  86. $n--;
  87. if (!$hasChanged && ($n === 0)) {
  88. break;
  89. }
  90. }
  91. }
  92. }
  93. }
  94. }
  95. //some result forms need more modification
  96. switch ($strResultForm) {
  97. case 'construct';
  98. $arResult = $this->_constructGraph(
  99. $arResult,
  100. $this->query->getConstructPattern()
  101. );
  102. break;
  103. case 'describe';
  104. $arResult = $this->describeGraph($arResult);
  105. break;
  106. }
  107. return $arResult;
  108. break;
  109. case 'count':
  110. case 'count-distinct':
  111. case 'ask':
  112. if (count($arRecordSets) > 1) {
  113. require_once 'Erfurt/Exception.php';
  114. throw new Erfurt_Exception('More than one result set for a ' . $strResultForm . ' query!');
  115. }
  116. $nCount = 0;
  117. foreach ($arRecordSets[0] as $row) {
  118. $nCount += intval($row['count']);
  119. break;
  120. }
  121. if ($strResultForm == 'ask') {
  122. return ($nCount > 0) ? true : false;
  123. } else {
  124. return $nCount;
  125. }
  126. break;
  127. case 'describe':
  128. default:
  129. throw new Exception('Yet not supported: ' . $strResultForm);
  130. }
  131. }
  132. // ------------------------------------------------------------------------
  133. // --- Protected methods --------------------------------------------------
  134. // ------------------------------------------------------------------------
  135. /**
  136. * Constructs a result graph.
  137. *
  138. * @param array $arVartable A table containing the result vars and their bindings.
  139. * @param Erfurt_Sparql_GraphPattern $constructPattern The CONSTRUCT pattern.
  140. * @return array
  141. */
  142. protected function _constructGraph($arVartable, $constructPattern)
  143. {
  144. $resultGraph = array();
  145. if (!$arVartable) {
  146. return $resultGraph;
  147. }
  148. $tp = $constructPattern->getTriplePatterns();
  149. $bnode = 0;
  150. foreach ($arVartable as $value) {
  151. foreach ($tp as $triple) {
  152. $subVar = substr($triple->getSubject(), 1);
  153. $predVar = substr($triple->getPredicate(), 1);
  154. $objVar = substr($triple->getObject(), 1);
  155. $sub = $value["$subVar"]['value'];
  156. $pred = $value["$predVar"]['value'];
  157. $obj = $value["$objVar"];
  158. if (!isset($resultGraph["$sub"])) {
  159. $resultGraph["$sub"] = array();
  160. }
  161. if (!isset($resultGraph["$sub"]["$pred"])) {
  162. $resultGraph["$sub"]["$pred"] = array();
  163. }
  164. $resultGraph["$sub"]["$pred"][] = $obj;
  165. }
  166. }
  167. return $resultGraph;
  168. }
  169. protected function _createBlankNode($id)
  170. {
  171. return array(
  172. 'type' => 'bnode',
  173. 'value' => $id
  174. );
  175. }
  176. protected function _createLiteral($value, $language, $datatype)
  177. {
  178. $retVal = array(
  179. 'type' => 'literal',
  180. 'value' => $value
  181. );
  182. if ((null !== $language)) {
  183. $retVal['lang'] = $language;
  184. } else if ((null !== $datatype)) {
  185. $retVal['datatype'] = $datatype;
  186. }
  187. return $retVal;
  188. }
  189. /**
  190. * Creates an RDF object object contained in the given $dbRecordSet object.
  191. *
  192. * @see convertFromDbResult() to understand $strVarBase necessity
  193. *
  194. * @param array $dbRecordSet
  195. * @param string $strVarBase Prefix of the columns the recordset fields have.
  196. * @return string RDF triple object resource object.
  197. */
  198. protected function _createObjectFromDbRecordSetPart($row, $strVarBase, $strVar, $asArray = false)
  199. {
  200. $strVarName = (string)$strVar;
  201. if ($row[$this->_vars[$strVarName]['sql_value']] === null) {
  202. return '';
  203. }
  204. $result = null;
  205. switch ($row[$this->_vars[$strVarName]['sql_is']]) {
  206. case 0:
  207. if ($row[$this->_vars[$strVarName]['sql_ref']] === null) {
  208. $result = $this->_createResource($row[$this->_vars[$strVarName]['sql_value']]);
  209. } else {
  210. $result = $this->_createResource(
  211. $this->uriValues[$row[$this->_vars[$strVarName]['sql_ref']]]);
  212. }
  213. break;
  214. case 1:
  215. if ($row[$this->_vars[$strVarName]['sql_ref']] === null) {
  216. $result = $this->_createBlankNode($row[$this->_vars[$strVarName]['sql_value']]);
  217. } else {
  218. $result = $this->_createBlankNode(
  219. $this->uriValues[$row[$this->_vars[$strVarName]['sql_ref']]]);
  220. }
  221. break;
  222. default:
  223. if ($row[$this->_vars[$strVarName]['sql_ref']] === null) {
  224. $result = $this->_createLiteral(
  225. $row[$this->_vars[$strVarName]['sql_value']], null, null);
  226. #if ($row[$this->_vars[$strVarName]['sql_dt_ref']] === null) {
  227. # $result = $this->_createLiteral(
  228. # $row[$this->_vars[$strVarName]['sql_value']],
  229. # $row[$this->_vars[$strVarName]['sql_lang']],
  230. # $row[$this->_vars[$strVarName]['sql_type']]
  231. # );
  232. #} else {
  233. # $result = $this->_createLiteral(
  234. # $row[$this->_vars[$strVarName]['sql_value']],
  235. # $row[$this->_vars[$strVarName]['sql_lang']],
  236. # $this->uriValues[$row[$this->_vars[$strVarName]['sql_dt_ref']]]
  237. # );
  238. #}
  239. } else {
  240. $result = $this->_createLiteral(
  241. $this->literalValues[$row[$this->_vars[$strVarName]['sql_ref']]], null, null);
  242. #if ($row[$this->_vars[$strVarName]['sql_dt_ref']] === null) {
  243. # $result = $this->_createLiteral(
  244. # $this->literalValues[$row[$this->_vars[$strVarName]['sql_ref']]],
  245. # $row[$this->_vars[$strVarName]['sql_lang']],
  246. # $row[$this->_vars[$strVarName]['sql_type']]
  247. # );
  248. #} else {
  249. # $result = $this->_createLiteral(
  250. # $this->literalValues[$row[$this->_vars[$strVarName]['sql_ref']]],
  251. # $row[$this->_vars[$strVarName]['sql_lang']],
  252. # $this->uriValues[$row[$this->_vars[$strVarName]['sql_dt_ref']]]
  253. # );
  254. #}
  255. }
  256. }
  257. if ($asArray) {
  258. return $result;
  259. } else {
  260. return $result['value'];
  261. }
  262. }
  263. /**
  264. * Creates an RDF predicate object contained in the given $dbRecordSet object.
  265. *
  266. * @see convertFromDbResult() to understand $strVarBase necessity
  267. *
  268. * @param array $dbRecordSet
  269. * @param string $strVarBase Prefix of the columns the recordset fields have.
  270. * @return string RDF triple predicate resource object.
  271. */
  272. protected function _createPredicateFromDbRecordSetPart($row, $strVarBase, $strVar, $asArray = false)
  273. {
  274. $strVarName = (string)$strVar;
  275. if ($row[$this->_vars[$strVarName]['sql_value']] === null) {
  276. return '';
  277. }
  278. $result = null;
  279. if ($row[$this->_vars[$strVarName]['sql_ref']] === null) {
  280. $result = $this->_createResource($row[$this->_vars[$strVarName]['sql_value']]);
  281. } else {
  282. $result = $this->_createResource($this->uriValues[$row[$this->_vars[$strVarName]['sql_ref']]]);
  283. }
  284. if ($asArray) {
  285. return $result;
  286. } else {
  287. return $result['value'];
  288. }
  289. }
  290. protected function _createResource($uri)
  291. {
  292. return array(
  293. 'type' => 'uri',
  294. 'value' => $uri
  295. );
  296. }
  297. /**
  298. * Creates an RDF subject object contained in the given $dbRecordSet object.
  299. *
  300. * @see convertFromDbResult() to understand $strVarBase necessity
  301. *
  302. * @param array $dbRecordSet
  303. * @param string $strVarBase Prefix of the columns the recordset fields have.
  304. * @return string RDF triple subject resource object.
  305. */
  306. protected function _createSubjectFromDbRecordSetPart($row, $strVarBase, $strVar, $asArray = false)
  307. {
  308. $strVarName = (string)$strVar;
  309. if ($row[$this->_vars[$strVarName]['sql_value']] === null) {
  310. return '';
  311. }
  312. $result = null;
  313. if ($row[$this->_vars[$strVarName]['sql_is']] === 0) {
  314. if ($row[$this->_vars[$strVarName]['sql_ref']] === null) {
  315. $result = $this->_createResource($row[$this->_vars[$strVarName]['sql_value']]);
  316. } else {
  317. $result = $this->_createResource($this->uriValues[$row[$this->_vars[$strVarName]['sql_ref']]]);
  318. }
  319. } else {
  320. if ($row[$this->_vars[$strVarName]['sql_ref']] === null) {
  321. $result = $this->_createBlankNode($row[$this->_vars[$strVarName]['sql_value']]);
  322. } else {
  323. $result = $this->_createBlankNode(
  324. $this->uriValues[$row[$this->_vars[$strVarName]['sql_ref']]]);
  325. }
  326. }
  327. if ($asArray) {
  328. return $result;
  329. } else {
  330. return $result['value'];
  331. }
  332. }
  333. /**
  334. * Converts a result set array into an array of "rows" that
  335. * are subarrays of variable => value pairs.
  336. *
  337. * @param $dbRecordSet
  338. * @param $strResultForm
  339. * @return array
  340. */
  341. protected function _getVariableArrayFromRecordSet($dbRecordSet, $strResultForm, $asArray = false)
  342. {
  343. $arResult = array();
  344. switch ($strResultForm) {
  345. case 'construct':
  346. $arResultVars = $this->query->getConstructPatternVariables();
  347. break;
  348. default:
  349. $arResultVars = $this->query->getResultVars();
  350. break;
  351. }
  352. if (in_array('*', $arResultVars)) {
  353. $arResultVars = array_keys($this->_vars);
  354. }
  355. foreach ($dbRecordSet as $row) {
  356. $arResultRow = array();
  357. foreach ($arResultVars as $strVar) {
  358. $strVarName = (string)$strVar;
  359. $strVarId = ltrim($strVar, '?$');
  360. if (!isset($this->_vars[$strVarName])) {
  361. //variable is in select, but not in result (test: q-select-2)
  362. $arResultRow[$strVarId] = '';
  363. } else {
  364. $arVarSettings = $this->_vars[$strVarName];
  365. // Contains whether variable is s, p or o.
  366. switch ($arVarSettings[1]) {
  367. case 's':
  368. $arResultRow[$strVarId] = $this->_createSubjectFromDbRecordSetPart(
  369. $row, $arVarSettings[0], $strVar, $asArray);
  370. break;
  371. case 'p':
  372. $arResultRow[$strVarId] = $this->_createPredicateFromDbRecordSetPart(
  373. $row, $arVarSettings[0], $strVar, $asArray);
  374. break;
  375. case 'o':
  376. $arResultRow[$strVarId] = $this->_createObjectFromDbRecordSetPart(
  377. $row, $arVarSettings[0], $strVar, $asArray);
  378. break;
  379. default:
  380. require_once 'Erfurt/Exception.php';
  381. throw new Erfurt_Exception('Variable has to be s, p or o.');
  382. }
  383. }
  384. }
  385. $arResult[] = $arResultRow;
  386. }
  387. return $arResult;
  388. }
  389. protected function _getVariableArrayFromRecordSets($arRecordSets, $strResultForm, $asArray = false)
  390. {
  391. // First, we need to check, whether there is a need to dereference some values
  392. $refVariableNamesUri = array();
  393. $refVariableNamesLit = array();
  394. foreach ($this->_vars as $var) {
  395. if ($var[1] === 'o') {
  396. if (isset($var['sql_ref'])) {
  397. $refVariableNamesLit[] = $var['sql_ref'];
  398. $refVariableNamesUri[] = $var['sql_ref'];
  399. }
  400. if (isset($var['sql_dt_ref'])) {
  401. $refVariableNamesUri[] = $var['sql_dt_ref'];
  402. }
  403. } else {
  404. if (isset($var['sql_ref'])) {
  405. $refVariableNamesUri[] = $var['sql_ref'];
  406. }
  407. }
  408. }
  409. ;
  410. $refVariableNamesUri = array_unique($refVariableNamesUri);
  411. $refVariableNamesLit = array_unique($refVariableNamesLit);
  412. $refIdsUri = array();
  413. $refIdsLit = array();
  414. foreach ($arRecordSets as $dbRecordSet) {
  415. foreach ($dbRecordSet as $row) {
  416. foreach ($refVariableNamesUri as $name) {
  417. if ($row["$name"] !== null) {
  418. $refIdsUri[] = $row["$name"];
  419. }
  420. }
  421. foreach ($refVariableNamesLit as $name) {
  422. if ($row["$name"] !== null) {
  423. $refIdsLit[] = $row["$name"];
  424. }
  425. }
  426. }
  427. }
  428. if (count($refIdsUri) > 0) {
  429. $sql = 'SELECT id, v FROM ef_uri WHERE id IN (' . implode(',', $refIdsUri) . ')';
  430. $result = $this->engine->sqlQuery($sql);
  431. foreach ($result as $row) {
  432. $this->uriValues[$row['id']] = $row['v'];
  433. }
  434. }
  435. if (count($refIdsLit) > 0) {
  436. $sql = 'SELECT id, v FROM ef_lit WHERE id IN (' . implode(',', $refIdsLit) . ')';
  437. $result = $this->engine->sqlQuery($sql);
  438. foreach ($result as $row) {
  439. $this->literalValues[$row['id']] = $row['v'];
  440. }
  441. }
  442. $arResult = array();
  443. foreach ($arRecordSets as $dbRecordSet) {
  444. $arResult = array_merge(
  445. $arResult,
  446. $this->_getVariableArrayFromRecordSet($dbRecordSet, $strResultForm, $asArray)
  447. );
  448. }
  449. return $arResult;
  450. }
  451. }