Source for file SparqlEngine.php
Documentation is available at SparqlEngine.php
require_once RDFAPI_INCLUDE_DIR .
'util/Object.php';
require_once RDFAPI_INCLUDE_DIR .
'sparql/FilterFunctions.php';
require_once RDFAPI_INCLUDE_DIR .
'sparql/SparqlEngine/ResultConverter.php';
// ----------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------
* This engine executes SPARQL queries against an RDF Datatset.
* @version $Id: fsource_sparql__sparqlSparqlEngine.php.html 443 2007-06-01 16:25:38Z cax $
* @author Tobias Gauß <tobias.gauss@web.de>
* Use SparqlEngine::factory() instead of this
//protected to prevent direct instantiation
* Creates a new instance of the SparqlEngine, depending on the
* given model. For example, if you pass a DbModel, you will
* get a SparqlEngine specialized on databases.
* @param Model $model RDF model that uses the engine
public function factory($model =
null)
if ($model !==
null &&
$model instanceof
DbModel) {
require_once RDFAPI_INCLUDE_DIR .
'sparql/SparqlEngineDb.php';
* The query engine's main method.
* @param Dataset $dataset the RDF Dataset
* @param mixed $query the parsed SPARQL query
* @param String $resultform the result form. If set to 'xml' the result will be
* SPARQL Query Results XML Format as described in http://www.w3.org/TR/rdf-sparql-XMLres/ .
* @return Array/String Type of the result depends on $resultform.
public function queryModel($dataset, Query $query, $resultform =
false)
$vartable[0]['patternResult'] =
null;
/// match graph patterns against the RDF Dataset
// filter results- apply inner filters
// filter results- apply outer filters
if ($vartable[0]['patternResult'] !=
null) {
// sort vars (ORDER BY, LIMIT, OFFSET)
$vartable =
$this->sortVars($vartable[0]['patternResult']);
if ($qrf ==
'select' ||
$qrf ==
'select distinct') {
if ($qrf ==
'select distinct') {
}//public function queryModel($dataset, Query $query, $resultform = false)
* Matches all graph Patterns against the dataset and generates an array which
* contains the result sets for every given GraphPattern.
* @param Array $graphlist the graphlist which contains the names of the named
* graphs which has to be queried.
// get the result part from the query
// for each GrapPattern in the result part
foreach($resultPart as $graphPattern){
$this->matchPattern($patternlist, $graphlist, $graphPattern);
* Finds tuples that match one graph pattern.
* @param Array $patternlist list that contains the graphPatterns
* @param array $graphlist the graphlist
* @param GraphPattern $graphPattern the pattern which has to be matched
protected function matchPattern(&$patternlist, $graphlist, &$graphPattern) {
// generate an empty result set
// if the GraphPattern has triple patterns
if($graphPattern->getTriplePattern()>
0){
// check if the pattern has a GRAPH clause and if this Iri is in $graphlist
$newGraphList =
$this->_checkGraphs($graphPattern,$graphlist);
$qt =
$graphPattern->getTriplePattern();
for ($i=
1; $i<
count($qt); $i++
) {
$finalRes =
$this->joinTuples($finalRes,$resultSet);
// dependencies between pattern results
$patternlist[$graphPattern->getId()]['hasOptional'] =
0;
$patternlist[$graphPattern->getId()]['hasUnion'] =
0;
$patternlist[$graphPattern->getId()]['patternResult'] =
$finalRes;
$op =
$graphPattern->getOptional();
$un =
$graphPattern->getUnion();
$patternlist[$graphPattern->getId()]['optionalTo'] =
$op;
$patternlist[$op]['hasOptional']++
;
$patternlist[$graphPattern->getId()]['unionWith'] =
$un;
$patternlist[$un]['hasUnion']++
;
$constraint =
$graphPattern->getConstraint();
foreach($constraint as $constr){
if($constr->isOuterFilter()){
$patternlist[$graphPattern->getId()]['outerFilter'][] =
$constr;
$patternlist[$graphPattern->getId()]['innerFilter'][] =
null;
$patternlist[$graphPattern->getId()]['innerFilter'][] =
$constr;
$patternlist[$graphPattern->getId()]['outerFilter'][] =
null;
$patternlist[$graphPattern->getId()]['innerFilter'] =
null;
$patternlist[$graphPattern->getId()]['outerFilter'] =
null;
* Finds Tuples matching one TriplePattern.
* @param TriplePattern $pattern
* @param Array $graphlist
$sub =
$pattern->getSubject();
$pred =
$pattern->getPredicate();
$obj =
$pattern->getObject();
// search in named graphs
if($graphlist['var'][0] !=
null||
$graphlist['list'][0] !=
null){
foreach($graphlist['list'] as $key =>
$graphnode){
$it =
$this->dataset->findInNamedGraphs($graphnode,$sub,$pred,$obj,false);
// add statements to the result list
$element =
$it->current()->getStatement();
$grname =
$it->current()->getGraphname();
if($it->current() instanceof
Quad)
$element =
$it->current()->getStatement();
$element =
$it->current();
$resmodel['trip'][$k] =
$element;
$resmodel['graph'][$k] =
$grname;
// $resmodel['graphvar'][$k] = $graphlist['var'][$key];
$resmodel['graphvar'][$k] =
$graphlist['var'][0];
// search in the default graph
if($graphlist['list'][0] ==
null &&
$graphlist['var'][0] ==
null){
$gr =
$this->dataset->getDefaultGraph();
$res =
$gr->find($sub,$pred,$obj);
foreach($res->triples as $innerkey =>
$element){
$resmodel['trip'][$k] =
$element;
$resmodel['graph'][$k] =
null;
$resmodel['graphvar'][$k] =
$graphlist['var'][$key];
* Checks it there are internal bindings between variables.
* @param Array $intBindings
if($trip->subj !=
$trip->pred)
if(is_a($trip->obj,'Literal'))
if($trip->subj !=
$trip->obj)
if(is_a($trip->obj,'Literal'))
if($trip->pred !=
$trip->obj)
if(is_a($trip->obj,'Literal'))
if($trip->pred !=
$trip->obj ||
$trip->pred !=
$trip->subj )
* Perform an SQL-like inner join on two resultSets.
* @param Array &$finalRes
protected function joinTuples(&$finalRes, &$res) {
// find joint variables and new variables to be added to $finalRes
foreach ($res[$k] as $varname =>
$node) {
// eliminate rows of $finalRes in which the values of $jointVars do not have
// a corresponding row in $res.
foreach ($finalRes as $n =>
$fRes) {
foreach ($res as $i =>
$r) {
foreach ($jointVars as $j_varname)
if ($r[$j_varname] !=
$fRes[$j_varname]) {
// join $res and $finalRes
foreach ($finalRes as $n =>
$fRes) {
foreach ($jointVars as $j_varname)
if ($r[$j_varname] !=
$fRes[$j_varname]) {
$joinedRow =
$finalRes[$n];
foreach($newVars as $n_varname)
$joinedRow[$n_varname] =
$r[$n_varname];
$joinedRes[] =
$joinedRow;
* Joins OPTIONAL pattern results.
* @param Array &$finalRes
* @return Array the joined Array
// find joint variables and new variables to be added to $finalRes
foreach ($res[$k] as $varname =>
$node) {
foreach($finalRes as $i =>
$fRes){
foreach($res as $n =>
$r){
foreach($jointVars as $j_varname){
if($r[$j_varname]==
$fRes[$j_varname]){
foreach($newVars as $n_varname)
$result[$joinc][$n_varname] =
$r[$n_varname];
foreach($res as $k =>
$val){
$result[$count] =
$finalRes[0];
foreach($result[$count] as $varname =>
$varVal){
$result[$count][$varname]=
'';
foreach($val as $varname2 =>
$varVal2){
$result[$count][$varname2]=
$varVal2;
* Looks in from and from named part of the query and
* adds the graphs to the graphlist.
* Evaluates the GRPAH clause if there is one. Checks if
* the GRAPH clause contains an IRI, variable or nothing.
* Returns an array which contains the graphs that has to be matched.
* @param GraphPattern $pattern
* @param Array $graphlist
$gr =
$pattern->getGraphname();
if($graphlist[0]==
null ||
in_array($gr,$graphlist)){
$newGraphList['list'][] =
$gr;
$newGraphList['var'][] =
null;
$newGraphList['list'] =
$graphlist;
$newGraphList['var'][] =
$gr;
$newGraphList['list'] =
$graphlist;
$newGraphList['var'][] =
null;
* Marks triples with internal bindings.
* int bindings -1 :none 0:sub=pred 1:sub=obj 2:pred=obj 3:sub=pred=obj.
if($var['sub'] ==
$var['pred'])
if($var['sub'] ==
$var['obj']){
if($var['pred']==
$var['obj']&&
$intBindings!=
3)
* @param GraphPattern $pattern
// determine variables and their corresponding values
foreach($resmodel['trip'] as $key =>
$triple){
if(isset
($resmodel['graphvar'][$key]))
$result[$n][$resmodel['graphvar'][$key]] =
$resmodel['graph'][$key];
$result[$n++
][$pattern->getSubject()] =
$triple->subj;
foreach($resmodel['trip'] as $key =>
$triple){
if(isset
($resmodel['graphvar'][$key]))
$result[$n][$resmodel['graphvar'][$key]] =
$resmodel['graph'][$key];
$result[$n++
][$pattern->getPredicate()] =
$triple->pred;
foreach($resmodel['trip'] as $key =>
$triple){
if(isset
($resmodel['graphvar'][$key]))
$result[$n][$resmodel['graphvar'][$key]] =
$resmodel['graph'][$key];
$result[$n++
][$pattern->getObject()] =
$triple->obj;
* Selects the result variables and builds a result table.
* @param Array $table the result table
* @param Array $vars the result variables
$resTable[$hits][$var]=
$val[$var];
$resTable[$hits][$var]=
"";
* Joins the results of the different Graphpatterns.
* @param Array $patternlist
$joined[0]['patternResult'] =
null;
$joined[0]['outerFilter'] =
null;
while(count($patternlist)>
0){
foreach($patternlist as $key =>
$pattern){
if($pattern['hasOptional'] ==
0 &&
$pattern['hasUnion'] ==
0){
if(is_int($pattern['optionalTo'])){
$patternlist[$pattern['optionalTo']]['hasOptional']--
;
$patternlist[$pattern['optionalTo']]['patternResult'] =
$this->joinOptionalTuples($pattern['patternResult'],$patternlist[$pattern['optionalTo']]['patternResult']);
unset
($patternlist[$key]);
else if(is_int($pattern['unionWith'])){
$patternlist[$pattern['unionWith']]['hasUnion']--
;
foreach($pattern['patternResult'] as $value)
array_push($patternlist[$pattern['unionWith']]['patternResult'],$value);
unset
($patternlist[$key]);
if($joined[0]['patternResult'] ==
null){
$joined[0]['patternResult'] =
$pattern['patternResult'];
if($joined[0]['outerFilter'] ==
null )
$joined[0]['outerFilter'] =
$pattern['outerFilter'];
unset
($patternlist[$key]);
// if($pattern['patternResult'] !=null ){
$joined[0]['patternResult'] =
$this->joinTuples($joined[0]['patternResult'],$pattern['patternResult']);
$joined[0]['outerFilter'] =
$pattern['outerFilter'];
unset
($patternlist[$key]);
* Filters the pattern results.
* @param Array $patternlist list containing the results of the GraphPatterns
* @param boolean $outer TRUE if its an outer filter FALSE if not
* @return Array the filtered patternlist
foreach($patternlist as $patkey =>
$pattern){
$constraint =
$pattern[$filter];
if(count($constraint)>
0){
foreach($constraint as $constr){
// extract Vars and function calls
$evalString =
$constr->getExpression();
preg_match_all("/isLiteral\((.[^\)]*)\)/i",$evalString,$isLiteralcalls);
preg_match_all("/datatype\((.[^\)]*)\)/i",$evalString,$datatypecalls);
if(count($boundcalls[1])>
0)
$function['bound'] =
$boundcalls[1];
$function['bound'] =
false;
if(count($isUricalls[1])>
0)
$function['isUri'] =
$isUricalls[1];
$function['isUri'] =
false;
if(count($isBlankcalls[1])>
0)
$function['isBlank'] =
$isBlankcalls[1];
$function['isBlank'] =
false;
if(count($isLiteralcalls[1])>
0)
$function['isLiteral'] =
$isLiteralcalls[1];
$function['isLiteral'] =
false;
if(count($langcalls[1])>
0)
$function['lang'] =
$langcalls[1];
$function['lang'] =
false;
if(count($datatypecalls[1])>
0)
$function['datatype'] =
$datatypecalls[1];
$function['datatype'] =
false;
if(count($stringcalls[1])>
0)
$function['string'] =
$stringcalls[1];
$function['string'] =
false;
foreach($pattern['patternResult'] as $key =>
$res){
$evalString =
'$result =('.
$evalString.
');';
unset
($patternlist[$patkey]['patternResult'][$key]);
* Builds an evaluation string to determine wether the result passes
* the filter or not. This string is evaluatet by the php buildin eval() function
* @param Array $vars a list which contains the used variables
* @param Array $res the result part which have to be evaluated
* @param Constraint $constraint the Constrain object
* @param Array $function an Array which contains the used functions
$evalString =
$constraint->getExpression();
$pattern1 =
"/\".[^\"]*\"[^\^\@]/";
$pattern2 =
"/\'.[^\']*\'[^\^\@]/";
foreach($hits1[0] as $k =>
$val){
$evalString =
preg_replace('/\".[^\"]*\"[^\^]/','_REPLACED1_'.
$k++
,$evalString,1);
foreach($hits2[0] as $k =>
$val){
$evalString =
preg_replace('/\".[^\"]*\"[^\^]/','_REPLACED2_'.
$k++
,$evalString,1);
foreach($prefs as $key =>
$val){
$evalString =
preg_replace("/^(".
$key.
"\:)(.[^\s]*)|([\s\(]?[^\^])(".
$key.
"\:)(.[^\s\)]*)([\s\)]?)/","$3'<".
$val.
"$2$5>'$6",$evalString);
$evalString =
preg_replace("/(\^)(".
$key.
"\:)(.[^\s]*)/","$1<".
$val.
"$3>",$evalString);
$xsd =
"http\:\/\/www.w3.org\/2001\/XMLSchema\#";
foreach($function['bound'] as $var){
if(isset
($res[$var]) &&
$res[$var]!==
"")
$evalString =
preg_replace("/bound\(\\".
$var.
"\)/i",$replacement,$evalString);
// evaluate isBlank calls
if($function['isBlank']){
foreach($function['isBlank'] as $var){
if(isset
($res[$var]) &&
$res[$var]!==
"" &&
$res[$var] instanceof
BlankNode )
$evalString =
preg_replace("/isBlank\(\\".
$var.
"\)/i",$replacement,$evalString);
// evaluate isLiteral calls
if($function['isLiteral']){
foreach($function['isLiteral'] as $var){
if(isset
($res[$var]) &&
$res[$var]!==
"" &&
$res[$var] instanceof
Literal )
$evalString =
preg_replace("/isLiteral\(\\".
$var.
"\)/i",$replacement,$evalString);
foreach($function['isUri'] as $var){
if(isset
($res[$var]) &&
$res[$var]!==
"" &&
$res[$var] instanceof
Resource &&
$res[$var]->getUri() &&
!$res[$var] instanceof
BlankNode )
$evalString =
preg_replace("/isUri\(\\".
$var.
"\)/i",$replacement,$evalString);
foreach($function['lang'] as $var){
if(isset
($res[$var]) &&
$res[$var]!==
"" &&
$res[$var] instanceof
Literal &&
$res[$var]->getLanguage() )
$replacement =
'"'.
$res[$var]->getLanguage().
'"';
$evalString =
preg_replace("/lang\(\\".
$var.
"\)/i",$replacement,$evalString);
// evaluate datatype calls
if($function['datatype']){
foreach($function['datatype'] as $var){
if(isset
($res[$var]) &&
$res[$var]!==
"" &&
$res[$var] instanceof
Literal &&
$res[$var]->getDatatype() )
$replacement =
'\'<'.
$res[$var]->getDatatype().
'>\'';
$evalString =
preg_replace("/datatype\(\\".
$var.
"\)/i",$replacement,$evalString);
foreach($function['string'] as $var){
if($var{0}==
'?' ||
$var{0}==
'$'){
if(isset
($res[$var]) &&
$res[$var]!==
""){
$replacement =
"'str_".
$res[$var]->getLabel().
"'";
$evalString =
preg_replace("/str\(\\".
$var.
"\)/i",$replacement,$evalString);
$evalString =
preg_replace("/str\(\s*\<(.[^\>]*)\>\s*\)/i","'str_$1'",$evalString);
$evalString =
preg_replace("/str\(\s*\"(.[^\>]*)\"\@[a-z]*\s*\)/i","'str_$1'",$evalString);
foreach($vars[0] as $var){
if(isset
($res[$var])&&
$res[$var]!==
""){
//$replacement = "'".$res[$var]->getLabel()."'";
if($res[$var]->getDatatype()!=
null){
if($res[$var]->getDatatype() ==
XML_SCHEMA.
'boolean')
$replacement =
$res[$var]->getLabel();
if($res[$var]->getDatatype() ==
XML_SCHEMA.
'double')
$replacement =
$res[$var]->getLabel();
if($res[$var]->getDatatype() ==
XML_SCHEMA.
'integer')
$replacement =
$res[$var]->getLabel();
if($res[$var]->getDatatype() ==
XML_SCHEMA.
'dateTime')
$replacement =
strtotime($res[$var]->getLabel());
if($res[$var]->getLabel()==
"")
$replacement =
"'str_".
$res[$var]->getLabel().
"'";
$replacement =
"'<".
$res[$var]->getLabel().
">'";
$evalString =
preg_replace("/\\".
$var.
"/",$replacement,$evalString);
// problem with PHP: false < 13 is true
$evalString =
preg_replace("/\\".
$var.
"/","false",$evalString);
$evalString =
preg_replace("/\\".
$var.
"/","false",$evalString);
$evalString =
preg_replace("/(.[^\=])(\=)(.[^\=])/","$1==$3",$evalString);
foreach($hits1[0] as $k =>
$val){
$pattern =
'/_REPLACED1_'.
$k.
'/';
$evalString =
preg_replace($pattern,$hits1[0][$k],$evalString,1);
foreach($hits2[0] as $k =>
$val){
$pattern =
'/_REPLACED2_'.
$k.
'/';
$evalString =
preg_replace($pattern,$hits2[0][$k],$evalString,1);
// replace xsd:boolean expressions
$pattern =
$pattern =
'/\"\s?true\s?\"\^\^\<'.
$xsd.
'boolean\>|\'\s?true\s?\'\^\^xsd:boolean/';
$pattern =
$pattern =
'/\"\s?false\s?\"\^\^\<'.
$xsd.
'boolean\>|\'\s?false\s?\'\^\^xsd:boolean/';
// replace xsd:date expressions
$pattern =
"/\"(.[^\"]*)\"\^\^".
$xsd.
"dateTime/";
foreach($hits[1] as $dummy)
$evalString =
preg_replace("/(\'\<".
$xsd.
"dateTime\()(.[^\)]*\))\>\'/","dateTime($2",$evalString);
$evalString =
preg_replace("/(\'\<".
$xsd.
"integer\()(.[^\)]*\))\>\'/","integer($2",$evalString);
$evalString =
preg_replace("/\"(.[^\"]*)\"([^\^])|\"(.[^\"]*)\"$/","'str_$1$3'$2",$evalString);
* @param Array $vartable List containing the unsorted result vars
* @return Array List containing the sorted result vars
// if no ORDER BY solution modifier return vartable
if($mod['order by']!=
null){
$order =
$mod['order by'];
$newTable[] =
$vartable[$val];
if($mod['offset'] !=
null){
if($mod['limit'] !=
null){
* Sorts the result table.
* @param String $order (ASC/DESC)
* @param Array $vartable the vartable
* @return Array A map that contains the new order of the result vars
foreach($order as $variable)
$num_var[$variable['val']] =
0;
foreach($vartable as $k =>
$x){
foreach($order as $value){
// if the value is a typed Literal try to determine if it
if($x[$value['val']] instanceof
Literal){
$dtype =
$x[$value['val']]->getDatatype();
$num_var[$value['val']]++
;
$num_var[$value['val']]++
;
if($x[$value['val']]instanceof
Literal){
if($x[$value['val']]instanceof
Resource){
$result[$value['val']][$n] =
$pref.
$x[$value['val']]->getLabel();
$result[$value['val']][$n] =
"";
$result['oldKey'][$n] =
$k;
foreach($order as $value){
if($num_var[$value['val']] ==
$n)
if($value['type'] ==
'asc')
$sortString =
$sortString.
'$result["'.
$value['val'].
'"],'.
$type.
','.
$sort.
',';
$sortString =
"array_multisort(".
$sortString.
'$result["oldKey"]);';
return $result['oldKey'];
* Eliminates duplicate results.
* @param Array $vartable a table that contains the result vars and their bindings
* @return Array the result table without duplicate results
foreach($vartable as $key =>
$value){
foreach($value as $k =>
$v)
$key_index =
$key_index.
$k.
$v->toString();
if(isset
($index[$key_index]))
* Prints a query result as HTML table.
* You can change the colors in the configuration file.
* @param array $queryResult [][?VARNAME] = object Node
// Import Package Utility
if ( $queryResult[0] ==
null) {
if ( $queryResult ==
'false') {
echo
'boolean: false<br>';
if ( $queryResult ==
'true') {
echo
'boolean: true<br>';
echo
'<table border="1" cellpadding="3" cellspacing="0"><tr><td><b>No.</b></td>';
foreach ($queryResult[0] as $varName =>
$value)
echo
"<td align='center'><b>$varName</b></td>";
foreach ($queryResult as $n =>
$var) {
echo
'<tr><td width="20" align="right">' .
($n +
1) .
'.</td>';
foreach ($var as $varName =>
$value) {
if (is_a($value, 'Literal')) {
if ($value->getLanguage() !=
NULL)
$lang =
' <b>(xml:lang="' .
$value->getLanguage() .
'") </b> ';
if ($value->getDatatype() !=
NULL)
$dtype =
' <b>(rdf:datatype="' .
$value->getDatatype() .
'") </b> ';
echo
RDFUtil::getNodeTypeName($value) .
$value->getLabel() .
$lang .
$dtype .
'</p>';
echo
"<td bgcolor='white'>unbound";
}//public function getQuery()
}//public function getDataset()
} // end: Class SparqlEngine
Documentation generated on Fri, 1 Jun 2007 16:52:05 +0200 by phpDocumentor 1.3.2