PageRenderTime 51ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/s3db3.5.10/s3dbcore/sparql_read.php

https://github.com/drobbins/s3db
PHP | 1759 lines | 1042 code | 446 blank | 271 comment | 197 complexity | 45be3820313144aa5dc3ae963679a452 MD5 | raw file
  1. <?php
  2. /**
  3. * @author Helena F Deus <helenadeus@gmail.com>
  4. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
  5. * @package S3DB http://www.s3db.org
  6. */
  7. ########################################################
  8. ##Debug box
  9. #echo '<pre>';print_r($outputData);exit;
  10. #$timer ->display();
  11. #$timer->stop();$profiling = $timer->getProfiling();
  12. #echo $profiling[count($profiling)-1]['total'].' sec';exit;
  13. ########################################################
  14. function sparql($I)
  15. {
  16. ##Parse the query and build the dataset
  17. #global $timer;
  18. if(is_file(S3DB_SERVER_ROOT.'/pearlib/Benchmark/Timer.php')){
  19. require_once S3DB_SERVER_ROOT.'/pearlib/Benchmark/Timer.php';
  20. $timer = new Benchmark_Timer();
  21. $timer->start();
  22. }
  23. extract($I);
  24. ##To use SPARQL with ARC library, we will need it to work with a remote endpoint. That means that we do not want to configure ARC as a datastore, but rather to retrieve the data from s3db deployments, convert it to RDF and then use ARC to run the query on it
  25. /* ARC2 static class inclusion */
  26. ini_set("include_path", S3DB_SERVER_ROOT."/pearlib/arc". PATH_SEPARATOR. ini_get("include_path"));
  27. include_once("ARC2.php");
  28. $s3ql['url'] = ($in['url']!='')?$in['url']:$default_uri;
  29. $s3ql['key'] = ($in['key']!='')?$in['key']:get_user_key($user_id, $db);
  30. $q = $in['query'];
  31. list($query, $triples, $prefixes) = parse_sparql_query($q, $s3ql);
  32. $bq .= "PREFIX ".implode("\n PREFIX ", $query['prefix'])."\n ";
  33. $bq .= "SELECT ".$query['select'][0]."\n ";
  34. $bq .= "FROM".implode(" FROM ", $query['from'])."\n ";
  35. $bq .= "WHERE ".$query['where'][0]."\n ";
  36. preg_match_all('(\?[A-Za-z0-9]+) ', $bq, $vars);
  37. if($vars[0]) {
  38. $vars = array_unique($vars[0]);
  39. $sparql_vars = implode(" ",$vars);
  40. }
  41. if($query['select'][0]!="" && $query['select'][0]!="*"){
  42. $outputCols = explode(" ", trim($query['select'][0]));
  43. $outputCols = array_filter($outputCols);
  44. $outputCols = array_intersect($vars, $outputCols);
  45. }
  46. $sparql=ereg_replace("FROM(.*)WHERE", "WHERE",$bq);
  47. #lets preprocess the order by which the must be queries must be performed to optimize speedness
  48. list($iterations, $scrambled) = iterationOrder($triples,$prefixes, true);
  49. ##$rdf_results will contain the totality of triples retrieved from s3db;
  50. ##Start a rdf-api model
  51. $iterations = array_values($iterations);
  52. $rdf = S3DB_URI_BASE.'/s3dbcore/model.n3';#base s3db rdf model
  53. $filename = md5($rdf);
  54. $file_place = $GLOBALS['uploads'].'/';
  55. #$queryModel = rdf2php($rdf);
  56. #$data = $queryModel->sparqlQuery($sparql);
  57. #echo '<pre>';print_r($data);exit;
  58. if($timer) $timer->setMarker('Core model read into results');
  59. $rdf_results = array();
  60. $performedQueries = array();
  61. $r=0;
  62. foreach ($iterations as $it=>$triples2query) {
  63. $S3QL=array();
  64. $S3QLfinal = array();
  65. foreach ($triples2query as $i=>$tripleInd) {
  66. $tripleString = $tripleInd;
  67. list($subject, $predicate, $object) = explode(' ',trim($tripleString));
  68. $subject = ereg_replace('^<|>$','',$subject);
  69. $predicate = ereg_replace('^<|>$','',$predicate);
  70. $object = ereg_replace('^<|>$','',$object);
  71. $triple = compact('subject','predicate','object');
  72. #sparql triple is used to calculate the values of the variables in the triple
  73. #$sparql_triple = $sparql_prefixes_default.' SELECT * WHERE { '.ltrim($tripleString).' . }';
  74. #now lets interpret the triple to explore the space of possible queries on S3QL
  75. $pack = compact('triple', 's3ql','user_id', 'db','prefixes','varType','discoveredData','it','varTypeWhere','collected_data','performedQueries');
  76. $sp = sparql_navigator($pack);
  77. extract($sp);
  78. # if($timer) $timer->setMarker('Built query '.$i);
  79. ##Remove queries that were already performed
  80. if($S3QL[0]){
  81. foreach ($S3QL as $s=>$q) {
  82. $S3QLfinal[] =$q;
  83. $queried_elements[] = $element[$s];
  84. }
  85. $localQueries[$tripleString] = $localQueries[0];
  86. $remoteQueries[$tripleString] = $remoteQueries[0];
  87. $localQueries = array_filter($localQueries);
  88. $remoteQueries = array_filter($remoteQueries);
  89. }
  90. }
  91. $S3QL = $S3QLfinal;
  92. ##Remove repeated queries
  93. $S3QL=array_unique($S3QL);
  94. #if only the s3ql is requested, we can return it now
  95. if($in['output']=='S3QL')
  96. {
  97. foreach ($localQueries as $sparqlVersion=>$s3qlVersion) {
  98. $Q[]['S3QL'] = S3QLQuery($s3qlVersion);
  99. }
  100. foreach ($remoteQueries as $rq) {
  101. $Q[]['S3QL'] = $rq;
  102. }
  103. $root = 's3ql';#root is just the word that xml should parse as the root for each entry
  104. $data = $Q;
  105. $cols = array('S3QL');
  106. $format = ($in['format']=='')?'html':$in['format'];
  107. $z = compact('data','cols','format','root');
  108. $out=outputFormat($z);
  109. return array(true,$out);
  110. }
  111. #If paralel library is activated, use it for the data. Otherwise use the custom version
  112. #$query_answers_file = 'sparql_query_ans'.rand(100,200); $a=fopen($query_answers_file, 'a');
  113. if(!empty($S3QL)){
  114. if(extension_loaded ('curl') && $goparallel){
  115. // Create cURL handlers
  116. if($timer) $timer->setMarker('Starting queries from group '.$it);
  117. foreach ($S3QL as $k=>$url) {
  118. $qURL = $url;
  119. $ch[$k] = curl_init();
  120. // Set options
  121. curl_setopt($ch[$k], CURLOPT_URL, $qURL.'&format=php');
  122. curl_setopt($ch[$k], CURLOPT_RETURNTRANSFER, 1);
  123. }
  124. $mh = curl_multi_init();
  125. foreach ($S3QL as $k=>$url) {
  126. curl_multi_add_handle($mh,$ch[$k]);
  127. }
  128. $running=null;
  129. do {
  130. curl_multi_exec($mh,$running);
  131. if($timer) $timer->setMarker('Query '.$k.' of group '.$it.' executed');
  132. } while ($running > 0);
  133. foreach ($S3QL as $k=>$url) {
  134. $answer[$k] = curl_multi_getcontent($ch[$k]);
  135. if(!empty($answer[$k]))
  136. {
  137. #@fwrite($a, $answer[$k]);
  138. ##This is what takes the longest after the query, can it be replaced?
  139. $ans = unserialize($answer[$k]);
  140. $letter = $queried_elements[$r][0];
  141. if(empty($ans)){
  142. ##is this query part is not optional, then the result will be null
  143. ##TO BE DEVELOPED SOON
  144. }
  145. else {
  146. $rdf_results[$letter][] = $ans;
  147. }
  148. $r++;
  149. ##Add the triples to already existing triples
  150. #Line up the answer with the model
  151. if($timer) $timer->setMarker('Query '.$it.'=>'.$k.' converted to php ');
  152. }
  153. }
  154. curl_multi_close($mh);
  155. ####Time count
  156. #$time_end = microtime(true);
  157. #$time = $time_end - $time_start;
  158. #echo "Query took ".$time." seconds\n";exit;
  159. ###
  160. }
  161. else
  162. {
  163. #Now solve the remaining triples with the constants found in this one
  164. if(is_array($localQueries) && !empty($localQueries)) {
  165. foreach ($localQueries as $sparql_triple=>$s3ql) {
  166. $s3ql=array_filter(array_diff_key($s3ql,array('url'=>'')));
  167. $answer = localQ($s3ql);
  168. if(!empty($answer))
  169. {
  170. $rdfanswer = rdf2php($answer);
  171. #Line up the answer with the model
  172. $queryModel->addModel($rdfanswer);
  173. #Now perform the query on the small model to find a constant for the remaining queries
  174. #list($data,$discovered, $discoveredData,$queryModel) = executeQuery($queryModel,$sparql_triple,$discovered,$format);
  175. }
  176. }
  177. }
  178. if(is_array($remoteQueries) && !empty($remoteQueries)) {
  179. foreach ($remoteQueries as $remoteQuery) {
  180. $answer = remoteQ($remoteQuery);
  181. if(!empty($answer))
  182. {
  183. $rdfanswer = rdf2php($answer);
  184. #Line up the answer with the model
  185. $queryModel->addModel($rdfanswer);
  186. #Now perform the query on the small model to find a constant for the remaining queries
  187. #list($data,$discovered, $discoveredData,$queryModel) = executeQuery($queryModel,$sparql_triple,$discovered,$format);
  188. }
  189. }
  190. }
  191. }
  192. }
  193. }
  194. ##Get the data from the file
  195. ##Now, add the dictionary data
  196. if($complete){
  197. include_once(S3DB_SERVER_ROOT.'/s3dbcore/dictionary.php');
  198. $s3qlN=compact('user_id','db');
  199. $s3qlN['from']='link';
  200. $s3qlN['format'] = 'php';
  201. $links = query_user_dictionaries($s3qlN,$db,$user_id);
  202. $links = unserialize($links);
  203. $rdf_results['E'][0] = $links;
  204. $s3qlN=compact('user_id','db');
  205. $s3qlN['from']='namespaces';
  206. $s3qlN['format'] = 'php';
  207. $ns = query_user_dictionaries($s3qlN,$db,$user_id);
  208. $ns = unserialize($ns);
  209. if($timer) $timer->setMarker('Dictionary links retrieved');
  210. }
  211. ##Convert the result into an RDF file
  212. $data_triples = array();
  213. if(is_array($rdf_results)){
  214. foreach ($rdf_results as $letter=>$results2rdfize) {
  215. $dont_skip_core_name = false;
  216. $dont_skip_serialized=true;
  217. if(ereg('S', $letter)) $dont_skip_serialized=false;
  218. if(ereg('C|R|P', $letter)) $dont_skip_core_name = true;
  219. foreach ($results2rdfize as $k=>$data) {
  220. $tmp_triples = rdf_encode($data,$letter, 'array', $s3ql['db'],$ns,$collected_data,$dont_skip_serialized,$dont_skip_core_name);
  221. if(is_array($tmp_triples))
  222. $data_triples=array_merge($data_triples, $tmp_triples);
  223. }
  224. }
  225. }
  226. if(!empty($data_triples)){
  227. $tmp['ns'] = $prefixes;
  228. /*
  229. #this one for turtle
  230. $parser = ARC2::getComponent('TurtleParser', $a);
  231. $index = ARC2::getSimpleIndex($triples, false) ; # false -> non-flat version
  232. $rdf_doc = $parser->toTurtle($index,$prefixes);
  233. */
  234. $parser = ARC2::getComponent('RDFXMLParser', $tmp);
  235. $index = ARC2::getSimpleIndex($data_triples, false) ; /* false -> non-flat version */
  236. $rdf_doc = $parser->toRDFXML($index,$prefixes);
  237. $filename = S3DB_SERVER_ROOT.'/tmp/'.random_string(15).'.rdf';
  238. $rr= fopen($filename, 'a+');
  239. fwrite($rr, $rdf_doc);
  240. fclose($rr);
  241. if($timer) $timer->setMarker(count($data_triples).' triples written to file '.$filename);
  242. ##The better strategy would be to let the client cpu resolve the query; return the graphs with the rdf so that a sparql on the client can handle it
  243. if($return_file_name){
  244. if(filesize($filename)>0){
  245. return (array(true,$filename));
  246. }
  247. else {
  248. return (array(false));
  249. }
  250. exit;
  251. }
  252. if($redirect){
  253. ##And now use an external service ( I gave up with ARC) to parse the query
  254. $url2search = str_replace(S3DB_SERVER_ROOT, S3DB_URI_BASE, $filename);
  255. ##Giving up on ARC, surrender to sparql.com
  256. $remote_endpoint = "http://sparql.org/sparql?query=";
  257. $bq=ereg_replace("FROM <.*>", "FROM <".$url2search.">", $bq);
  258. $bq = urlencode($bq);
  259. $remote_endpoint .= $bq.'&default-graph-uri=&stylesheet=/xml-to-html.xsl';
  260. return (array(true, $remote_endpoint));
  261. }
  262. #echo $filename;exit;
  263. #And finally perform the query on the model.
  264. $queryModel = rdf2php($filename);
  265. $format = ($in['format']!='')?$in['format']:'html';
  266. unlink($filename);
  267. if($timer) $timer->setMarker('Data converted to a model the rdf-api can query');
  268. if(eregi('^(sparql-xml|sparql-html)$', $format)){
  269. switch ($format) {
  270. case 'sparql-xml':
  271. $result = $queryModel->sparqlQuery($sparql, 'XML');
  272. break;
  273. case 'sparql-html':
  274. $result = $queryModel->sparqlQuery($sparql, 'HTML');
  275. if($_REQUEST['su3d']){
  276. $timer->stop();$profiling = $timer->getProfiling();
  277. echo "Query took ".$profiling[count($profiling)-1]['total'].' sec';
  278. }
  279. break;
  280. }
  281. if($result){
  282. return array(true,$result);
  283. }
  284. else {
  285. return (false);
  286. }
  287. }
  288. elseif($format=='html.form'){
  289. $form .= '
  290. <html>
  291. <head>
  292. </head><body>
  293. <form method="GET" action="sparql.php" id="sparqlform">
  294. <h5>Target Deployment(s)</h5>
  295. <input type="hidden" name="key" value="'.$s3ql['key'].'"/>
  296. <input type="hidden" name="format" value="'.$_REQUEST['format'].'"/>
  297. <input type = "text" id="url" size = "100%" value="'.$GLOBALS['url'].'" name="url">
  298. <h5>SPARQL <a href="http://www.w3.org/TR/rdf-sparql-query/" target="_blank">(help!!)</a></h5>
  299. <br />
  300. <textarea cols="100" id="sparql" rows="10" name = "query">'.stripslashes($sparql).'</textarea><br />
  301. <input type="submit" value="SPARQL this!" id="submitsparql"></body>
  302. </form>
  303. ';
  304. $form .= '<br />'.count($data)." rows";
  305. $form .= '<br />Query took '.(strtotime(date('His'))-$start).' sec';
  306. if(count($data)>0){
  307. return (array(true, $form));
  308. }
  309. else {
  310. return (array(false));
  311. }
  312. }
  313. else {
  314. #and output the result according to requested format
  315. $data = $queryModel->sparqlQuery($sparql);
  316. if($timer) $timer->setMarker('Query on SPARQL data executed by rdf-api.');
  317. if(is_array($outputCols) && !empty($outputCols)){
  318. ##only this one are to be shown in the final result
  319. $vars = $outputCols;
  320. }
  321. $cleanCols = array();
  322. foreach ($vars as $varname) {
  323. $cleanCols[] = ereg_replace('^\?','', $varname);
  324. }
  325. $outputData = array();
  326. if(is_array($data))
  327. foreach ($data as $s=>$sparql_line) {
  328. foreach ($sparql_line as $sparql_var=>$sparql_var_value) {
  329. if($sparql_var_value->uri!=''){
  330. $outputData[$s][ereg_replace('^\?','', $sparql_var)] = $sparql_var_value->uri;
  331. }
  332. elseif($sparql_var_value->label!='') {
  333. $outputData[$s][ereg_replace('^\?','', $sparql_var)] = $sparql_var_value->label;
  334. }
  335. else {
  336. $outputData[$s][ereg_replace('^\?','', $sparql_var)] = "";
  337. }
  338. }
  339. }
  340. if($timer) $timer->setMarker('Data converted in a format that fun outputformat can read');
  341. #$timer ->display();
  342. #root is just the word that xml should parse as the root for each entry
  343. $root = 'sparql';
  344. if($timer) $timer->setMarker('All variables fitted into their places to represent in the final output');
  345. $data = $outputData;
  346. $cols = $cleanCols;
  347. if($_REQUEST['su3d']){
  348. $timer->stop();$profiling = $timer->getProfiling();
  349. echo "Query took ".$profiling[count($profiling)-1]['total'].' sec<br>';
  350. }
  351. $z = compact('data','cols','format','root');
  352. $out=outputFormat($z);
  353. echo $out;exit;
  354. if(count($data)>0){
  355. return (array(true, $out));
  356. }
  357. else {
  358. return (array(false));
  359. }
  360. }
  361. }
  362. else {
  363. return (array(false));
  364. }
  365. #else {
  366. #$out= formatReturn($GLOBALS['error_codes']['no_results'], 'Your query did not return any results.', $format,'');
  367. #}
  368. }
  369. function isSPARQLVar($e){
  370. if($e->uri!='')
  371. return (False);
  372. elseif($e->label!='')
  373. return (False);
  374. elseif (ereg('^\?', $e)) {
  375. return (true);
  376. }
  377. else {
  378. return (false);
  379. }
  380. }
  381. function isS3DBCore($e, $call=false,$format='rdf')
  382. {
  383. ##First slip into url + finalization; check if url is s3db's
  384. if(!ereg('^(http.*)/(D|G|U|P|C|R|I|S)([0-9]+)$', $e, $uri_out))
  385. return (False);
  386. else {
  387. $s3dbquery = $uri_out[1].'/URI.php?format='.$format.'&uid='.$uri_out[2].$uri_out[3].'&key='.$GLOBALS['key'];
  388. if($call){
  389. $uri_dat = stream_get_contents(fopen($s3dbquery,'r'));
  390. if($format=='rdf')
  391. {$model[$e] = rdf2php($uri_dat); }
  392. else {
  393. if($format=='php')
  394. {
  395. $model[$e] = unserialize($uri_dat);
  396. }
  397. }
  398. }
  399. #$msg=html2cell($uri_dat);$msg = $msg[2];
  400. #if(is_array($model[$e]->triples))
  401. #{
  402. #echo $uri_out[2]; echo '<pre>';print_r($GLOBALS['s3dbCore'][$uri_out[2]]);
  403. #$next=(!is_array($GLOBALS['s3dbCore'][$uri_out[2]]))?0:count($GLOBALS['s3dbCore'][$uri_out[2]]+1);
  404. #$GLOBALS['s3dbQueries'][count($GLOBALS['s3dbQueries'])+1] = $s3dbquery;
  405. #$GLOBALS['s3dbCore'][$uri_out[2]][$next] = $uri_out[2].$uri_out[3];
  406. #$GLOBALS['s3dbURI'][count($GLOBALS['s3dbURI'])+1]=$uri_out[2].$uri_out[3];
  407. return (array('query'=>$s3dbquery, 'url'=>$uri_out[1],'letter'=>$uri_out[2], 'value'=>$uri_out[3], 'data'=>$model[$e]));
  408. }
  409. #else {
  410. # return (False);
  411. #}
  412. #}
  413. }
  414. function switchFromCore($E)
  415. {
  416. return ($GLOBALS['s3codes'][$E]);
  417. }
  418. function switchToCore($E)
  419. {
  420. return ($GLOBALS['s3codesInv'][$E]);
  421. }
  422. function sparql_navigator($c)
  423. {global $timer;
  424. extract($c);
  425. ##
  426. #React to the triples individually.
  427. #
  428. $crew = array('subject','predicate','object');
  429. #
  430. #no answer just yet
  431. #
  432. $ans=array();
  433. $triple_vars = array();
  434. $q='';
  435. $fromSpace = array_map('switchToCore', array_keys($GLOBALS['COREids']));
  436. $whereSpace = array_combine(array('D','G','U','P','C','R','I','S'), $GLOBALS['queriable']);
  437. $selectSpace = $GLOBALS['queriable'];
  438. #
  439. #first we'll try to answer the question with the captain himself - the subject has the most chances of winning the game; the subject can answer the question totally or partially. In case it is partially, predicate and object will complete it.
  440. #
  441. $from = $fromSpace;
  442. foreach ($crew as $crew_member) {
  443. ##if any of the triples is just 'a', replace by rdf:type
  444. if($triple[$crew_member]=='a'){
  445. $triple[$crew_member] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';
  446. }
  447. $isCore=false;
  448. $isCore =isS3DBCore($triple[$crew_member],true,'php');
  449. if($isCore){
  450. $collected_data[$isCore['letter'].$isCore['value']] = $isCore['data']; ##save it for later
  451. }
  452. switch ($crew_member) {
  453. case 'subject':
  454. #
  455. #subject can tells us for sure where the query should target; relationships associated with this core member can be retrieved.
  456. #
  457. if($isCore)
  458. {
  459. #
  460. #Because the core allows only collections and items as subjects
  461. #
  462. list($from, $where) = trimBasedOnSub(compact('from','isCore','where','triple','fromSpace'));
  463. ##Where cannot be determined yet, but we can constrain the where space
  464. $whereSpace = array_intersect_key($whereSpace, array_flip(array_map('switchToCore',$from)));
  465. }
  466. elseif(isSPARQLVar($triple[$crew_member]))#is subj var?
  467. {
  468. #If ?var was not found already, assign it to empty vars
  469. array_push($triple_vars, $triple[$crew_member]);
  470. }
  471. elseif($triple[$crew_member]) {
  472. if (isCoreOntology($triple[$crew_member])) {
  473. #The query is to be oriented towards the core. Since the core is already part of the model.n3, we need to leave the form and where empty. Model reamians as was an query is porformed on top of it.
  474. $from = array();
  475. $where = array();
  476. }
  477. }
  478. else {
  479. #the only time subject is not in the core is if the rdf comes from external sources. These will be left to the sparql enggine
  480. }
  481. ##P and O can be used to trim the answer if they are constants; otherwise they can be dicovered
  482. if($timer) $timer->setMarker('subject '.$triple[$crew_member].' interpreted');
  483. break;
  484. case 'predicate':
  485. #Which in the core? Predicate can now choose between rule or item, otherwise it does not make sense within the core
  486. if($isCore)
  487. {
  488. list($from, $where, $varType, $varTypeWhere) = trimBasedOnPred(compact('isCore','where', 'triple','varType','varTypeWhere'));
  489. }
  490. elseif(isSPARQLVar($triple[$crew_member]))#is pred var?
  491. {
  492. array_push($triple_vars, $triple[$crew_member]);
  493. }
  494. elseif(ereg('^http',$triple[$crew_member])) {
  495. #When the predicate is a known property, "from" can be trimmed to involve those that do have that property.
  496. #try to translate which property if being requested via uri:
  497. $tmp = $triple[$crew_member];
  498. if ($tmp=='http://www.w3.org/1999/02/22-rdf-syntax-ns#type') {
  499. ##When predicate is "type" something, query can be either on core or on a particular collections
  500. $objectIsCore =isS3DBCore($triple['object']);
  501. if($objectIsCore)
  502. switch ($objectIsCore['letter']) {
  503. case 'C':
  504. $from = array_intersect($from, array('I'));
  505. ##Where will be resolved when we look at the object
  506. #if(!is_array($where['I'])) $where['I'] = array();
  507. #array_push($where['I'], array('collection_id'=>$objectIsCore['value']));
  508. $varType[$triple['subject']][] = 'I';
  509. $varTypeWhere[$triple['subject']][] = 'C'.$objectIsCore['value'];
  510. break;
  511. case 'P':
  512. $varType[$triple['subject']][] = 'P';
  513. $varTypeWhere[$triple['subject']][] = 'P'.$objectIsCore['value'];
  514. break;
  515. }
  516. $objectIsEntity =isCoreOntology($triple['object']);
  517. if($objectIsEntity){
  518. $varType[$triple['subject']][] = letter($objectIsEntity);
  519. }
  520. }
  521. elseif($tmp=='http://www.w3.org/2000/01/rdf-schema#subClassOf'){
  522. $from = array_intersect($from, array('C','R','P','U','G'));
  523. $objectIsCore =isS3DBCore($triple['object']);
  524. $objectDiscovered = WasDiscovered($triple['object'],$varType);
  525. $subjectType = WasDiscovered($triple['subject'],$varType);
  526. if($objectIsCore)
  527. {switch ($objectIsCore['letter']) {
  528. case 'P':
  529. $from = array_intersect($from, array('C','R'));
  530. $varTypeWhere[$triple['subject']][] = 'P'.$objectIsCore['value'];
  531. #if(!is_array($where['I'])) $where['I'] = array();
  532. #array_push($where['I'], array('collection_id'=>$objectIsCore['value']));
  533. break;
  534. case 'D':
  535. $from = array_intersect($from, array('P','U', 'G'));
  536. break;
  537. case 'G':
  538. $from = array_intersect($from, array('U'));
  539. break;
  540. }
  541. }
  542. elseif($objectType) {
  543. foreach ($objectType as $gold) {
  544. $isObjectCore = isS3DBCore($gold);
  545. if($isObjectCore){
  546. list($from, $where) = trimBasedOnObj(array('from'=>$from,'isCore'=>$isObjectCore,'where'=>$where));
  547. }
  548. }
  549. }
  550. }
  551. #elseif($tmp==rdfs.'label' || $tmp==rdfs.'comment'){
  552. elseif(in_array($tmp, $GLOBALS['not_uid_specific'])){
  553. #is subject found?
  554. $subjDiscovered = WasDiscovered($triple['subject'],$varType, $varTypeWhere);
  555. #how about object?
  556. $objDiscovered = WasDiscovered($triple['object'],$varType,$varTypeWhere);
  557. #$subjDataDiscovered = $discoveredData[$triple['subject']];
  558. if($subjDiscovered)
  559. {
  560. #echo 'ola';exit;
  561. #$from = array();
  562. $where = array();
  563. foreach ($subjDiscovered as $g=>$gold) {
  564. $isSubjectCore = isS3DBCore($gold);
  565. if($isSubjectCore){
  566. list($from, $where) = trimBasedOnSub(array('fromSpace'=>$fromSpace,'from'=>$from,'isCore'=>$isSubjectCore,'where'=>$where));
  567. }
  568. elseif(in_array($gold, array('P','C','R','I','S') ))
  569. {
  570. $from = array_intersect($from, array($gold));
  571. if($varTypeWhere[$triple['subject']][$g]){
  572. if(!is_array($where[$gold])) $where[$gold] = array();
  573. $eid = $GLOBALS['COREletterInv'][letter($varTypeWhere[$triple['subject']][$g])];
  574. array_push($where[$gold], array($eid=>substr($varTypeWhere[$triple['subject']][$g], 1,strlen($varTypeWhere[$triple['subject']][$g]))));
  575. }
  576. }
  577. }
  578. #echo '<pre>';print_r($from);
  579. #echo '<pre>';print_r($where);
  580. #exit;
  581. }
  582. #echo '<pre>';print_r($from);echo '<pre>';print_r($where);exit;
  583. }
  584. else
  585. {
  586. foreach ($from as $E) {
  587. if(in_array($tmp, $GLOBALS['propertyURI'][$E]))
  588. {
  589. $fromSubSpace[] = $E;
  590. #
  591. #The object's help here will matter, as it will encapsulate the value to be read into the query
  592. #
  593. $objectIsCore =isS3DBCore($triple['object']);
  594. if(!is_array($where[$E])) $where[$E] = array();
  595. if($triple['object'])
  596. array_push($where[$E], array(array_search($tmp,$GLOBALS['propertyURI'][$E]) => $triple['object']));
  597. elseif($objectIsCore)
  598. array_push($where[$E], array(array_search($tmp,$GLOBALS['propertyURI'][$E]) => $objectIsCore['value']));
  599. }
  600. #$from = array_intersect($from,$fromSubSpace);
  601. }
  602. if(count($from)==8 || empty($where)) ##all entities will be queried, not a good move; this can be a query for the dictionary
  603. {$from=array();
  604. }
  605. }
  606. #echo '<pre>';print_r($from);
  607. #echo '<pre>';print_r($where);exit;
  608. }
  609. elseif($triple[$crew_member]) {
  610. }
  611. else {
  612. }
  613. break;
  614. case 'object':
  615. #echo '<pre>';print_r($where);exit;
  616. if($isCore) {
  617. ##Who can be connected to an element of the core? The object can eliminate some "from" options by discarding those that,according to the core, cannot be connected to this property as object
  618. #attr is always the same: it i sthe ID of the core element specified. For example, if it is rule, then attr is rule_id, etc.
  619. ##Where can finally be retrieved;
  620. switch ($isCore['letter']){
  621. case 'D':
  622. $subSpace = array('P','U','G','D');
  623. $from = array_intersect($from, $subSpace);
  624. break;
  625. case 'P':
  626. #$subSpace = array('R','C','U','G','P');
  627. $subSpace = array('R','C','P');
  628. $from = array_intersect($from, $subSpace);
  629. foreach ($from as $e) {
  630. if(!is_array($where[$e])) $where[$e]=array();
  631. array_push($where[$e], array('project_id' => $isCore['value']));
  632. }
  633. break;
  634. case 'R':
  635. #$subSpace = array('U','G','R');
  636. $subSpace = array('R');
  637. $from = array_intersect($from, $subSpace);
  638. foreach ($from as $e) {
  639. array_push($where[$e], array('rule_id' => $isCore['value']));
  640. }
  641. break;
  642. case 'C':
  643. #$subSpace =array('I','R','U','G','C');
  644. $subSpace =array('I','R','C');
  645. $from = array_intersect($from, $subSpace);
  646. foreach ($from as $e) {
  647. switch ($e) {
  648. case 'R':
  649. if(!is_array($where[$e])) $where[$e]=array();
  650. array_push($where[$e], array('object_id' => $isCore['value']));
  651. #$where['R'][end+1]['object_id'] = $isCore['value'];
  652. break;
  653. default:
  654. if(!is_array($where[$e])) $where[$e]=array();
  655. array_push($where[$e], array('collection_id' => $isCore['value']));
  656. break;
  657. }
  658. #if(!is_array($where[$e])) $where[$e]=array();
  659. #array_push($where[$e], array('collection_id' => $isCore['value']));
  660. }
  661. break;
  662. case 'I':
  663. #$subSpace=array('S','R','U','G','I');
  664. $subSpace=array('S','R','I');
  665. $from = array_intersect($from, $subSpace);
  666. foreach ($from as $e) {
  667. switch ($e) {
  668. case 'S':
  669. array_push($where['S'], array('value' => $isCore['value']));
  670. break;
  671. case 'R':
  672. array_push($where['R'], array('verb_id' => $isCore['value']));
  673. break;
  674. default :
  675. array_push($where[$e], array('item_id' => $isCore['value']));
  676. break;
  677. }
  678. }
  679. break;
  680. case 'S':
  681. #$subSpace=array('S','U','G');
  682. $subSpace=array('S');
  683. $from = array_intersect($from, $subSpace);
  684. foreach ($from as $e) {
  685. array_push($where[$e], array('statement_id' => $isCore['value']));
  686. }
  687. break;
  688. }
  689. #$from = array_intersect($from, $subSpace);
  690. }
  691. elseif(isSPARQLVar($triple[$crew_member]))#is subj var?
  692. {
  693. array_push($triple_vars, $triple[$crew_member]);
  694. }
  695. elseif(ereg('^http',$triple[$crew_member])) {
  696. #Is this an element of the CoreOntology
  697. $isOnt = isCoreOntology($triple[$crew_member]);
  698. if($isOnt)
  699. {
  700. $from = array($GLOBALS['s3codesInv'][strtolower($isOnt)]);
  701. $where[$GLOBALS['s3codesInv'][strtolower($isOnt)]]=array();
  702. }
  703. else {
  704. #to be parsed by SPARQL algebra;
  705. }
  706. }
  707. elseif(!ereg('^http',$triple[$crew_member])) {
  708. $ob = $triple[$crew_member];
  709. ereg('"(.*)"', $ob, $ob_parts);
  710. if($ob_parts) $ob=$ob_parts[1];
  711. foreach ($from as $e) {
  712. switch ($e) {
  713. case 'S':
  714. if(!is_array($where[$e])) $where[$e] =array('value'=>$ob);
  715. else {
  716. $where[$e][max(array_keys($where[$e]))]['value']=$ob;
  717. }
  718. #this is one of the few cases when we do want the object to be inthe same query as that for the predicate
  719. break;
  720. case 'R':
  721. #$where[$e][end]['object']=$triple[$crew_member]->label;
  722. break;
  723. }
  724. }
  725. }
  726. break;
  727. }
  728. }
  729. ##Once we go through all the triples, we should have reached a from and a where space; It's time to build the queries necessary for assigning values to variables; constraining the query space
  730. #fisrt thing first: let's think about efficiency? Is it the local deployment that is being queries? if so, let's call S3QLaction right here.
  731. if($s3ql['url']==S3DB_URI_BASE || $s3ql['url']==S3DB_URI_BASE.'/')
  732. {
  733. $s3ql['user_id']=$user_id;
  734. $s3ql['db']=$db;
  735. $remote=0;
  736. }
  737. else {
  738. $s3ql['user_id']=S3DB_URI_BASE.'/U'.$user_id;
  739. $remote=1;
  740. }
  741. $bQ=buildQuery(compact('s3ql','from','where','remote','performedQueries','it'));
  742. extract($bQ);
  743. return(compact('remoteQueries','localQueries','S3QL','varType','varTypeWhere', 'element','collected_data','performedQueries'));
  744. }
  745. function buildQuery($bQ)
  746. {
  747. extract($bQ);
  748. global $timer;
  749. $element=array();
  750. $select_fields = array('P'=>'name', 'C'=>'collection_id,project_id,name','R'=>'rule_id,project_id,subject_id,verb_id,object_id,object', 'I'=>'item_id,collection_id,notes','S'=>'statement_id,rule_id,item_id,value');
  751. foreach ($from as $e) {
  752. $tri_s3ql = $s3ql;
  753. ##Let's only select a few fields, as the more triples there are, the more has to be outputed
  754. $tri_s3ql['select']=$select_fields[$e];
  755. $tri_s3ql['from']=switchFromCore($e);
  756. array_push($element, $e);
  757. if(!is_array($where[$e]) || empty($where[$e])) {
  758. if(!$remote)
  759. $tri_s3ql = array_filter(array_diff_key($tri_s3ql, array('user_id'=>'')));
  760. $query = S3QLQuery($tri_s3ql);
  761. $S3QL[] = $query;
  762. if($remote){
  763. $tri_s3ql['format'] = 'php';
  764. $remoteQueries[] = $query;
  765. }
  766. else {
  767. $start = strtotime('His');
  768. $localQueries[] = $tri_s3ql;
  769. }
  770. array_push($performedQueries, $e);
  771. }
  772. else {
  773. for ($i=0; $i < count($where[$e]); $i++) {
  774. $tmp = $where[$e][$i];
  775. $ind= $i;
  776. if($tmp)
  777. $tri_s3ql['where']=$tmp;
  778. #again... efficiency
  779. if($remote){
  780. $tri_s3ql['format'] = 'php';
  781. $remoteQueries[] = $query;
  782. $query = S3QLQuery($tri_s3ql);
  783. }
  784. else {
  785. $start = strtotime('His');
  786. $localQueries[] = $tri_s3ql;
  787. $tri_s3ql = array_filter(array_diff_key($tri_s3ql, array('user_id'=>'')));
  788. $query = S3QLQuery($tri_s3ql);
  789. }
  790. #now stringize the query such that we can check if it has been built
  791. foreach ($tri_s3ql['where'] as $w_name=>$w_value) {
  792. if($stringized_query!="") $stringized_query .="&&";
  793. else $stringized_query .="(";
  794. $stringized_query .= $w_name.'='.$w_value;
  795. }
  796. if($stringized_query!="") $stringized_query .=")";
  797. if(in_array($e.$stringized_query, $performedQueries)){
  798. ##Do NOT perform this query again, it was already seen
  799. $repeated = true;
  800. }
  801. else {
  802. array_push($performedQueries, $e.$stringized_query);
  803. $S3QL[] = $query;
  804. }
  805. }
  806. }
  807. }
  808. return (compact('remoteQueries','localQueries', 'S3QL', 'element','performedQueries'));
  809. }
  810. function buildAndExecuteQ($b)
  811. {
  812. extract($b);
  813. $q = array();
  814. $ans = array();
  815. $queryModel = $model;
  816. foreach ($from as $e) {
  817. $tri_s3ql = $s3ql;
  818. $tri_s3ql['select']='*';
  819. $tri_s3ql['from']=switchFromCore($e);
  820. if(!is_array($where[$e]) || empty($where[$e])) {
  821. if($tri_s3ql['url']){
  822. $tri_s3ql['format'] = 'rdf';
  823. $query = S3QLQuery($tri_s3ql);
  824. $rQ[] = $query;
  825. }
  826. else {
  827. $start = strtotime('His');
  828. $lQ[] = $tri_s3ql;
  829. }
  830. }
  831. else {
  832. for ($i=0; $i < count($where[$e]); $i++) {
  833. $tmp = $where[$e][$i];
  834. $ind= $i;
  835. if($tmp)
  836. $tri_s3ql['where']=$tmp;
  837. #again... efficiency
  838. if($tri_s3ql['url']){
  839. $tri_s3ql['format'] = 'rdf';
  840. $query = S3QLQuery($tri_s3ql);
  841. $rQ[] = $query;
  842. }
  843. else {
  844. $start = strtotime('His');
  845. $lQ[] = $tri_s3ql;
  846. }
  847. }
  848. }
  849. }
  850. if(is_array($lQ))
  851. foreach ($lQ as $localQuery) {
  852. $answer = localQ($tri_s3ql);
  853. if(!empty($answer))
  854. {
  855. $rdfanswer = rdf2php($answer);
  856. #Line up the answer with the model
  857. $queryModel->addModel($rdfanswer);
  858. }
  859. }
  860. if(is_array($rQ))
  861. foreach ($rQ as $remoteQuery) {
  862. $answer = remoteQ($q);
  863. if(!empty($answer))
  864. {
  865. $rdfanswer = rdf2php($answer);
  866. #Line up the answer with the model
  867. $queryModel->addModel($rdfanswer);
  868. }
  869. }
  870. return $queryModel;#$t is the array with the vars that were discovered in this triple
  871. }
  872. function scrubSPARQLVar($a,$b)
  873. {
  874. $c = ($a[$b]->uri!='')?$a[$b]->uri:$a[$b]->label;
  875. return ($c);
  876. }
  877. function isDiscovered($v, $ans)
  878. {
  879. if(is_array($ans) && in_array($v, array_keys($ans)))
  880. return ($ans[$v]);
  881. else {
  882. return (False);
  883. }
  884. }
  885. function trimBasedOnObj($z)
  886. {extract($z);
  887. switch ($isCore['letter']) {
  888. case 'P':
  889. $from = array_intersect($from, array('C','R'));
  890. foreach ($from as $e) {
  891. if(!is_array($where[$e])) $where[$e]=array();
  892. array_push($where[$e], array('project_id'=> $isCore['value']));
  893. }
  894. break;
  895. case 'D':
  896. $from = array_intersect($from, array('P','U', 'G'));
  897. foreach ($from as $e) {
  898. if(!is_array($where[$e])) $where[$e]=array();
  899. array_push($where[$e], array('deployment_id'=> $isCore['value']));
  900. }
  901. break;
  902. case 'G':
  903. $from = array_intersect($from, array('U'));
  904. foreach ($from as $e) {
  905. if(!is_array($where[$e])) $where[$e]=array();
  906. array_push($where[$e], array('group_id'=> $isCore['value']));
  907. }
  908. break;
  909. }
  910. return (array($from, $where));
  911. }
  912. function trimBasedOnPred($z)
  913. {extract($z);
  914. switch ($isCore['letter']){
  915. case 'R':
  916. #echo '<pre>';print_r($isCore['data']);exit;
  917. $from=array('S');
  918. if(!is_array($where['S'])) $where['S']=array();
  919. array_push($where['S'], array('rule_id'=>$isCore['value']));
  920. if($triple['object']->label!='')
  921. {
  922. $where['S'][max(array_keys($where['S']))]['value']=$triple['object']->label;#this is one of the few cases when we want the predicate and the object to work together int he same query
  923. }
  924. ##We can infer the "type" of subject to use in further queries by looking at the "from" part of the query
  925. $varType[$triple['subject']][] = 'I';
  926. $varType[$triple['predicate']][] = 'R';
  927. $varType[$triple['object']][] = 'I';
  928. ##in some cases, we can even know which collection/rule the item/statement belongs to
  929. if($isCore['data'][0]['subject_id']){
  930. $varTypeWhere[$triple['subject']][] = 'C'.$isCore['data'][0]['subject_id'];
  931. }
  932. if($isCore['data'][0]['object_id']){
  933. $varTypeWhere[$triple['object']][] = 'C'.$isCore['data'][0]['object_id'];
  934. }
  935. break;
  936. case 'I':
  937. $from=array('I');
  938. if(!is_array($where['R'])) $where['R']=array();
  939. array_push($where['R'], array('verb_id'=>$isCore['value']));
  940. ##We can infer the "type" of subject to use in further queries by looking at the "from" part of the query
  941. $varType[$triple['subject']][] = 'C';
  942. $varType[$triple['predicate']][] = 'I';
  943. $varType[$triple['object']][] = 'C';
  944. break;
  945. }
  946. return (array($from, $where,$varType,$varTypeWhere));
  947. }
  948. function trimBasedOnSub($s)
  949. {extract($s);
  950. $from = array_intersect($fromSpace, array($isCore['letter']));
  951. if(!is_array($where[$isCore['letter']]))
  952. $where[$isCore['letter']] = array();
  953. switch ($isCore['letter']) {
  954. case 'P':
  955. array_push($where['P'], array('project_id' => $isCore['value']));
  956. break;
  957. case 'C':
  958. #collection cen be the subject of a rule
  959. array_push($from, 'R');
  960. array_push($where['R'], array('subject_id' => $isCore['value']));
  961. break;
  962. case 'I':
  963. #item can be the subject of a statemnet
  964. array_push($from, 'S');
  965. if(!is_array($where['S']))
  966. $where['S'] = array();
  967. array_push($where['S'], array('item_id'=>$isCore['value']));
  968. array_push($where['I'], array('item_id'=>$isCore['value']));
  969. break;
  970. break;
  971. }
  972. return (array($from, $where));
  973. }
  974. function isCoreOntology($uri)
  975. {
  976. if(ereg('^http://www.s3db.org/core.owl#s3db(.*)', $uri,$ont))
  977. {return ($ont[1]);
  978. }
  979. else {
  980. return False;
  981. }
  982. }
  983. function hasNotation($uri,$qname,$prefixes)
  984. { $url = $prefixes[$qname];
  985. if(ereg('<'.$url.'(.*)>', $uri,$ont))
  986. {return ($ont[1]);
  987. }
  988. else {
  989. return False;
  990. }
  991. }
  992. function executeQuery($queryModel,$sparql_triple,$discovered,$format)
  993. {global $timer;
  994. $tripleData = $queryModel->sparqlQuery($sparql_triple);
  995. if(!empty($tripleData)){
  996. foreach ($tripleData as $datakey=>$datavar) {
  997. foreach ($datavar as $valName=>$varVal) {
  998. if(is_object($datavar[$valName]))
  999. {
  1000. if($format!='xml')
  1001. {
  1002. $tripleData[$datakey][$valName] = (($tripleData[$datakey][$valName]->uri!='')?$tripleData[$datakey][$valName]->uri:$tripleData[$datakey][$valName]->label);
  1003. $discoveredData[$valName][] = $queryModel;
  1004. $discovered[$valName][] = $tripleData[$datakey][$valName];
  1005. }
  1006. else
  1007. {$newVarName = ereg_replace('^\?', '', $valName);$oldVarName = $valName;
  1008. $tripleData[$datakey][$newVarName]=($tripleData[$datakey][$valName]->uri!='')?$tripleData[$datakey][$valName]->uri:$data[$datakey][$valName]->label;
  1009. $tripleData[$datakey][$oldVarName]='';
  1010. $tripleData[$datakey]=array_filter($tripleData[$datakey]);
  1011. $discovered[$valName][] = $tripleData[$datakey];
  1012. $discoveredData[$valName][] = $tripleData;
  1013. }
  1014. }
  1015. }
  1016. }
  1017. $data[] = $tripleData;
  1018. }
  1019. return (array($data,$discovered, $discoveredData,$queryModel));
  1020. }
  1021. function remoteQ($q){
  1022. $b = strtotime(date('His'));
  1023. $c = fopen($q, 'r');
  1024. $answer = stream_get_contents($c);
  1025. return ($answer);
  1026. }
  1027. function localQ($tri_s3ql){
  1028. $query = S3QLAction($tri_s3ql);
  1029. ##Now force the RDF output
  1030. $format=$tri_s3ql['format'];
  1031. $data = $query;
  1032. $db=$tri_s3ql['db'];
  1033. if(is_array($query[0])){
  1034. $cols = array_keys($query[0]);
  1035. $letter = letter($tri_s3ql['from']);
  1036. $z = compact('data','cols','format', 'db','letter');
  1037. $answer = outputFormat($z);
  1038. }
  1039. else {
  1040. $answer = array();
  1041. }
  1042. return ($answer);
  1043. }
  1044. function iterationOrder($triples,$pref=array(),$return_order=false)
  1045. {
  1046. /**
  1047. * @author Helena F Deus <helenadeus@gmail.com>
  1048. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
  1049. * @package S3DB http://www.s3db.org
  1050. */
  1051. #Find triple order is based on the premisse that the more contsnts the system has, the more likely it is to trim down the query. So this simple function scores the number of constants in each triple and re-sorts them as each triple is being solved and providing constants for the remaining triples
  1052. #break and reorder the triples; retaining the original order will be important
  1053. if(count($triples)>=1){
  1054. for ($i=0;$i<count($triples);$i++) {
  1055. #before multisored
  1056. $unscrambled[$triples[$i]]=$i;
  1057. $triple = trim($triples[$i]);
  1058. $solver = explode(' ',$triple);
  1059. list($s,$p,$o) = $solver;
  1060. $puzzle = array(!ereg('^\?',$s),!ereg('^\?',$p),!ereg('^\?',$o));
  1061. #If all are constant, then it is not an S3QL query
  1062. if(array_sum($puzzle)==3){
  1063. #$triples[$i]='';
  1064. #$s="";$p="";$o="";#delete also s, p, o to use next
  1065. $score[$i] = 0;
  1066. $s="";$p="";$o="";
  1067. }
  1068. else{
  1069. $score[$i] = array_sum($puzzle);
  1070. }
  1071. ##Queries on items of collections that do not have results make it unnecessary to query the attributes of those. Score higher those that query collections
  1072. #Find if the obj is collection
  1073. $ob ="";$pr="";
  1074. ereg("<(.*)>",$o,$ob);
  1075. if($ob[1]) $o=$ob[1];
  1076. $obj = isS3DBCore($o, false);
  1077. #Find if predicate is type
  1078. $Pterm=hasNotation($p,'rdf',$pref);
  1079. if($Pterm=='type' && ereg('I|C|S|R|P',$obj['letter'])){
  1080. $score[$i] = $score[$i]+1; ##Queries get 1 point for being faster
  1081. }
  1082. ##triples that are a subclass of something are faster, get 1 extra point
  1083. if($p=='http://www.w3.org/2000/01/rdf-schema#subClassOf' && ereg('C|P',$obj['letter'])){
  1084. $score[$i] = $score[$i]+1;
  1085. }
  1086. #Some predicates, such as label comment, etc, appear in any entity, therefore they are non specific and do not help in building a query - lose 1 point
  1087. $pr="";
  1088. ereg("<(.*)>",$p,$pr);
  1089. if($pr) $p=$pr[1];
  1090. if(in_array($p,$GLOBALS['not_uid_specific']) && $score[$i]==1){#the constant part is not specific and there is only this one constant
  1091. $score[$i]=$score[$i]-1;
  1092. }
  1093. }
  1094. ##This will basically assign the triple to a subgroup of queries to be performed simulataneously, according to its order
  1095. array_multisort($score, SORT_NUMERIC, SORT_DESC,$triples); ##Because I don't want to lose the index relationship between the ttriples and the order
  1096. ##Now separate the triples into groups
  1097. $groups = array();
  1098. foreach ($score as $i=>$s) {
  1099. $j=max($score)-$s;
  1100. if(!is_array($groups[$j])) $groups[$j] = array();
  1101. array_push($groups[$j], $triples[$i]);
  1102. }
  1103. #$order = findTripleOrder($triples,array(),0,$pref);
  1104. #if(is_array($order))
  1105. #foreach ($order as $tripleInd=>$iteration) {
  1106. #$createThis[$iteration][]=$tripleInd;
  1107. #}
  1108. }
  1109. if(!$return_order)
  1110. return ($groups);
  1111. else {
  1112. return (array($groups, $unscrambled));
  1113. }
  1114. }
  1115. function findTripleOrder($triples, $firsts=array(),$or=0,$pref=array())
  1116. {global $timer;
  1117. /**
  1118. * @author Helena F Deus <helenadeus@gmail.com>
  1119. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
  1120. * @package S3DB http://www.s3db.org
  1121. */
  1122. #Find triple order is based on the premisse that the more contsnts the system has, the more likely it is to trim down the query. So this simple function scores the number of constants in each triple and re-sorts them as each triple is being solved and providing constants for the remaining triples
  1123. #break the triples
  1124. if(count($triples)>1){
  1125. for ($i=0;$i<count($triples);$i++) {
  1126. $triple = trim($triples[$i]);
  1127. $solver = explode(' ',$triple);
  1128. list($s,$p,$o) = $solver;
  1129. $puzzle = array(!ereg('^\?',$s),!ereg('^\?',$p),!ereg('^\?',$o));
  1130. #If all are constant, then it is not an S3QL query
  1131. if(array_sum($puzzle)==3){
  1132. #$triples[$i]='';
  1133. #$s="";$p="";$o="";#delete also s, p, o to use next
  1134. $score[$i] = 0;
  1135. $s="";$p="";$o="";
  1136. }
  1137. else{
  1138. $score[$i] = array_sum($puzzle);
  1139. }
  1140. ##Queries on items of collections that do not have results make it unnecessary to query the attributes of those. Score higher those that query collections
  1141. #Find if the obj is collection
  1142. $ob ="";$pr="";
  1143. ereg("<(.*)>",$o,$ob);
  1144. $obj = isS3DBCore($ob[1], false);
  1145. #Find if predicate is type
  1146. $Pterm=hasNotation($p,'rdf',$pref);
  1147. if($Pterm=='type' && ereg('I|C|S|R|P',$obj['letter'])){
  1148. $score[$i] = $score[$i]+1; ##Queries get 1 point for being faster
  1149. }
  1150. ##triples that are a subclass of something are faster, get 1 extra point
  1151. if($p=='http://www.w3.org/2000/01/rdf-schema#subClassOf' && ereg('C|P',$obj['letter'])){
  1152. $score[$i] = $score[$i]+1;
  1153. }
  1154. #Some predicates, such as label comment, etc, appear in any entity, therefore they are non specific and do not help in building a query - lose 1 point
  1155. $pr="";
  1156. ereg("<(.*)>",$p,$pr);
  1157. if(in_array($pr[1],$GLOBALS['not_uid_specific']) && $score[$i]==1){#the constant part is not specific and there is only this one constant
  1158. $score[$i]=$score[$i]-1;
  1159. }
  1160. }
  1161. ##This will basically assign the triple to a subgroup of queries to be performed simulataneously, according to its order
  1162. array_multisort($score, SORT_NUMERIC, SORT_DESC,$triples); ##Because I don't want to lose the index relationship between the ttriples and the order
  1163. ##Now separate the triples into groups
  1164. $groups = array();
  1165. foreach ($score as $i=>$s) {
  1166. $j=max($score)-$s;
  1167. if(!is_array($groups[$j])) $groups[$j] = array();
  1168. array_push($groups[$j], $triples[$i]);
  1169. }
  1170. /*for ($j=0; $j < count($score) ; $j++) {
  1171. #now, the first line to solve will be the one socres the highest but not equal to 3
  1172. #if($score[$j]==2)
  1173. if($score[$j]==max($score))
  1174. {
  1175. $firsts[$j] = $or;
  1176. #now eliminate the solved triple from the other triples
  1177. #$tick = array_search(0, $puzzle);
  1178. $tmp=split(' ',$triples[$j]);
  1179. $tick='';
  1180. foreach ($tmp as $t) {
  1181. if(ereg('^\?',$t))
  1182. $tick = $t;
  1183. }
  1184. #if(ereg('(\?[A-Za-z0-9_]) ', $triples[$j],$tmp)){
  1185. if($tick!=''){
  1186. $triplesSolved=array();
  1187. foreach ($triples as $tmp) {
  1188. $triplesSolved[] = str_replace($tick,substr($tick, 1, strlen($tick)), $tmp);
  1189. }
  1190. $triples = $triplesSolved;
  1191. }
  1192. #$score[$j]=0;##since it was already added, we want a new score max
  1193. }
  1194. else {
  1195. $firsts[$j]=0;
  1196. }
  1197. }
  1198. */
  1199. #ok, we're done, let's go back to the beginning
  1200. /*if($triplesSolved)
  1201. {
  1202. $triplesSolved = array_filter($triplesSolved);
  1203. $or++;
  1204. $firsts = findTripleOrder($triples,$firsts,$or,$pred);
  1205. }
  1206. }
  1207. else {
  1208. $firsts = array(0=>0);
  1209. }
  1210. */
  1211. }
  1212. return ($groups);
  1213. }
  1214. function WasDiscovered($object,$discovered, $varTypeWhere=array())
  1215. {
  1216. if(is_array($discovered))
  1217. if(in_array($object, array_keys($discovered)))
  1218. {
  1219. $objectType = $discovered[$object];
  1220. return ($objectType);
  1221. }
  1222. else {
  1223. return (False);
  1224. }
  1225. }
  1226. function microtime_float()
  1227. {
  1228. list($usec, $sec) = explode(" ", microtime());
  1229. return ((float)$usec + (float)$sec);
  1230. }
  1231. function interpret_literal_object($object)
  1232. {
  1233. if(!eregi("REGEX", $object))#Boa, we have something to put in the "value" part
  1234. {
  1235. $whereToQuery = array('value'=>$object);
  1236. }
  1237. else {
  1238. ##to be completed
  1239. }
  1240. return ($whereToQuery);
  1241. }
  1242. function parse_sparql_query($q, $s3ql)
  1243. {
  1244. ##Does this sparql have the "Select" and "prefix" part or is it just the triple patenrs
  1245. preg_match_all("(PREFIX|SELECT|FROM|WHERE)", $q,$tmp);
  1246. $sp = array();
  1247. if(is_array($tmp)){
  1248. $tmp=$tmp[0];
  1249. $rest = $q;
  1250. foreach ($tmp as $k=>$sp_part) {
  1251. ##ALL LOWERCASE
  1252. $sp_part = strtolower($sp_part);
  1253. ##Find the next part
  1254. $pos=stripos($rest, $sp_part);
  1255. $this_till_end = substr($rest, $pos+strlen($sp_part), strlen($rest)-$pos);
  1256. if($tmp[$k+1]){
  1257. $next = stripos($this_till_end, $tmp[$k+1]);
  1258. $this_portion = substr($rest, $pos+strlen($sp_part),$next);
  1259. $rest = substr($rest, $next, strlen($rest));
  1260. }
  1261. else {
  1262. $this_portion = substr($rest, $pos+strlen($sp_part),strlen($rest));
  1263. $rest = substr($rest, $pos+strlen($sp_part), strlen($rest));
  1264. }
  1265. if(!$sp[$sp_part]) $sp[$sp_part] = array();
  1266. array_push($sp[$sp_part], $this_portion);
  1267. }
  1268. }
  1269. if(!in_array("prefix", array_keys($sp))){
  1270. $sp['prefix'] = array("rdfs: <http://www.w3.org/2000/01/rdf-schema#>", "rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>", "s3db: <http://www.s3db.org/core.owl#>", ': <'.$s3ql['url'].((substr($s3ql['url'], strlen($s3ql['url'])-1, 1)=='/')?'':'/').'>');
  1271. }
  1272. ##Now fix the prefixes such that they are in the format qname=>url
  1273. $qnames = array();$url_qnames = array();
  1274. foreach ($sp['prefix'] as $pref) {
  1275. eregi('(.*:) *<(.*)>', $pref, $x);
  1276. if($x)
  1277. {array_push($qnames, " ".trim($x[1]));
  1278. array_push($url_qnames, " ".trim($x[2]));
  1279. }
  1280. }
  1281. if(!in_array("select", array_keys($sp))){
  1282. $sp['select'] = array("distinct *");
  1283. }
  1284. if(!in_array("from", array_keys($sp))){
  1285. $sp['from'] = array(" <".$s3ql['url'].">");
  1286. }
  1287. if(!in_array("where", array_keys($sp))){
  1288. $sp['where'] = array(" { ".$q." } ");
  1289. }
  1290. ##Now that the query is parsed, based on the "where" portion of the query, interpred the S3QL needed to obtain the data requested on the triples
  1291. $where