source: Dev/branches/rest-dojo-ui/server/rdfapi/sparql/Query.php @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 14.8 KB
Line 
1<?php
2require_once RDFAPI_INCLUDE_DIR . 'sparql/GraphPattern.php';
3
4/**
5* The Class Query represents a SPARQL query.
6*
7*
8* @author  Tobias Gauss <tobias.gauss@web.de>
9* @version $Id$
10* @license http://www.gnu.org/licenses/lgpl.html LGPL
11*
12* @package sparql
13*/
14class Query extends Object
15{
16    /**
17    * The BASE part of the SPARQL query.
18    * @var string
19    */
20    protected $base;
21
22    /**
23    * Original SPARQL query string
24    * @var string
25    */
26    protected $queryString = null;
27
28    /**
29    * Array that contains used prefixes and namespaces.
30    * Key is the prefix, value the namespace.
31    *
32    * @example
33    * array(8) {
34    *  ["rdf"] => string(43) "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
35    *  ["rdfs"]=> string(37) "http://www.w3.org/2000/01/rdf-schema#"
36    * }
37    *
38    * @var array
39    */
40    public $prefixes = array();
41
42    /**
43    * Array of result variables that shall be returned.
44    * E.g. "?name", "?mbox"
45    *
46    * @var array
47    */
48    protected $resultVars = array();
49
50    /**
51    * What form/type of result should be returned.
52    *
53    * One of:
54    * - "ask"
55    * - "count"
56    * - "construct"
57    * - "describe"
58    * - "select"
59    * - "select distinct"
60    *
61    * @var string
62    * @see http://www.w3.org/TR/rdf-sparql-query/#QueryForms
63    */
64    protected $resultForm = null;
65
66    /**
67    * Contains the result part of the SPARQL query.
68    * Array of GraphPattern
69    *
70    * @var array
71    */
72    protected $resultPart = array();
73
74    /**
75    *  Contains the FROM part of the SPARQL query.
76    * @var array
77    */
78    protected $fromPart = array();
79
80    /**
81    * Contains the FROM NAMED part of the SPARQL query.
82    * @var array
83    */
84    protected $fromNamedPart = array();
85
86    /**
87    * Optional solution modifier of the query.
88    * Array with three keys:
89    *  "order by", "limit", "offset"
90    * If they are not set, their value is null
91    *
92    * "order by" can be an array with subarrays, each of those
93    *  subarrays having two keys: "val" and "type".
94    *  "val" determines the variable ("?mbox"), "type" is
95    *  "asc" or "desc"
96    *
97    * @var array
98    */
99    protected $solutionModifier = array();
100
101    /**
102    *  Blanknode counter.
103    * How many blank nodes are in $resultPart
104    *
105    * @var int
106    */
107    protected $bnodeCounter = 0;
108
109    /**
110    * GraphPattern counter.
111    * How many GraphPattern are in $resultPart
112    *
113    * @var int
114    */
115    public $graphPatternCounter = 0;
116
117    /**
118    * List of all vars used in the query.
119    * Key is the variable (e.g. "?x"), value
120    * is boolean true
121    *
122    * @var array
123    */
124    public $usedVars = array();
125
126    /**
127    * If the query type is CONSTRUCT this variable contains the
128    * CONSTRUCT graph pattern.
129    */
130    protected $constructPattern = null;
131
132    /**
133    * TRUE if the query is empty FALSE if not.
134    *
135    * @var boolean
136    */
137    public $isEmpty = null;
138
139    /**
140    *   Language of variables. NULL if the variable has no
141    *   language tag (e.g. @en) set.
142    *   $varname => $language tag
143    *   @var array
144    */
145    public $varLanguages = array();
146
147    /**
148    *   Datatype of variables. NULL if the variable has no
149    *   data type (e.g. ^^xsd::integer) set.
150    *   $varname => $datatype
151    *   @var array
152    */
153    public $varDatatypes = array();
154
155
156
157    /**
158    * Constructor
159    */
160    public function Query(){
161        $this->resultForm = null;
162        $this->solutionModifier['order by'] = null;
163        $this->solutionModifier['limit']    = null;
164        $this->solutionModifier['offset']   = null;
165        $this->bnodeCounter = 0;
166        $this->graphPatternCounter = 0;
167
168    }
169
170    /**
171    * Returns the BASE part of the query.
172    *
173    * @return String
174    */
175    public function getBase(){
176        return $this->base;
177    }
178
179    /**
180    * Returns the prefix map of the query.
181    *
182    * @return Array
183    */
184    public function getPrefixes(){
185        return $this->prefixes;
186    }
187   
188    /**
189    * Returns a list containing the result vars.
190    *
191    * @return Array
192    */
193    public function getResultVar($strName) {
194        foreach ($this->resultVars as $var) {
195            if ($var->getVariable() == $strName) {
196                return $var;
197            }
198        }
199        return false;
200    }
201
202    /**
203    * Returns a list containing the result vars.
204    *
205    * @return Array
206    */
207    public function getResultVars(){
208        return $this->resultVars;
209    }
210
211    /**
212    * Returns the type the result shall have.
213    * E.g. "select", "select distinct", "ask", ...
214    *
215    * @see $resultForm
216    *
217    * @return string
218    */
219    public function getResultForm(){
220        return $this->resultForm;
221    }
222
223    /**
224    * Returns a list containing the graph patterns of the query.
225    *
226    * @return Array
227    */
228    public function getResultPart(){
229        return $this->resultPart;
230    }
231
232    /**
233    * Returns the FROM clause of the query.
234    *
235    * @return String
236    */
237    public function getFromPart(){
238        return $this->fromPart;
239    }
240
241    /**
242    * Returns the FROM NAMED clause of the query.
243    *
244    * @return Array
245    */
246    public function getFromNamedPart(){
247        return $this->fromNamedPart;
248    }
249
250    /**
251    * Returns $isEmpty variable
252    * @return boolean
253    */
254    public function isEmpty() {
255        return $this->isEmpty;
256    }
257
258    /**
259    * Returns an unused Bnode label.
260    *
261    * @return String
262    */
263    public function getBlanknodeLabel(){
264        return "_:bN".$this->bnodeCounter++;
265    }
266
267
268    /**
269    * Sets the base part.
270    *
271    * @param String $base
272    * @return void
273    */
274    public function setBase($base){
275        $this->base = $base;
276    }
277
278
279    /**
280    * Adds a prefix to the list of prefixes.
281    *
282    * @param  String $prefix
283    * @param  String $label
284    * @return void
285    */
286    public function addPrefix($prefix, $label){
287        $this->prefixes[$prefix]= $label;
288    }
289
290    /**
291    * Adds a variable to the list of result variables.
292    *
293    * @param  String $var
294    * @return void
295    */
296    public function addResultVar($var){
297        $this->resultVars[] = $var;
298        $var->setDatatype($this->getDatatype($var));
299
300        $this->varLanguages[$var->getId()] = self::getLanguageTag($var);
301        $this->varDatatypes[$var->getId()] = $this->getDatatype($var);
302    }
303
304
305    /**
306    * Sets the result form.
307    *
308    * @param  String $form
309    * @return void
310    */
311    public function setResultForm($form){
312        $this->resultForm = strtolower($form);
313    }
314
315
316    /**
317    * Sets the result part.
318    *
319    * @param  array Array of graph patterns
320    */
321    public function setResultPart($resultPart) {
322        $this->resultPart = $resultPart;
323    }
324
325    /**
326    * Adds a graph pattern to the result part.
327    *
328    * @param  GraphPattern $pattern
329    * @return void
330    */
331    public function addGraphPattern($pattern){
332        $pattern->setId($this->graphPatternCounter);
333        $this->resultPart[] = $pattern;
334        $this->graphPatternCounter++;
335    }
336
337    /**
338    * Adds a construct graph pattern to the query.
339    *
340    * @param  GraphPattern $pattern
341    * @return void
342    */
343    public function addConstructGraphPattern($pattern){
344        $this->constructPattern = $pattern;
345    }
346
347
348    /**
349    * Adds a graphuri to the from part.
350    *
351    * @param  String $graphURI
352    * @return void
353    */
354    public function addFrom($graphURI){
355        $this->fromPart[] = $graphURI;
356    }
357
358    /**
359    * Adds a graphuri to the from named part.
360    *
361    * @param  String $graphURI
362    * @return void
363    */
364    public function addFromNamed($graphURI){
365        $this->fromNamedPart[] = $graphURI;
366    }
367
368    /**
369    * Sets a solution modifier.
370    *
371    * @param  String $name
372    * @param  Value  $value
373    * @return void
374    */
375    public function setSolutionModifier($name, $value){
376        $this->solutionModifier[$name] = $value;
377    }
378
379
380    /**
381    * Generates a new GraphPattern. If it is a CONSTRUCT graph pattern
382    * $constr has to set to TRUE, FALSE if not.
383    *
384    * @param  boolean $constr
385    * @return GraphPattern
386    */
387    public function getNewPattern($constr = false){
388        $pattern = new GraphPattern();
389        if ($constr) {
390            $this->addConstructGraphPattern($pattern);
391        } else {
392            $this->addGraphPattern($pattern);
393        }
394        return $pattern;
395    }
396
397    /**
398    * Adds a new variable to the variable list.
399    *
400    * @param  String $var
401    * @return void
402    */
403    public function addUsedVar($var){
404        $this->usedVars[$var]=true;
405    }
406
407    /**
408    * Returns a list with all used variables.
409    *
410    * @return Array
411    */
412    public function getAllVars(){
413        return array_keys($this->usedVars);
414    }
415
416    /**
417    * Gets the solution modifiers of the query.
418    * $solutionModifier['order by'] = value
419    *                  ['limit']    = vlaue
420    *                  ['offset']   = value
421    *
422    *
423    * @return Array
424    */
425    public function getSolutionModifier(){
426        return $this->solutionModifier;
427    }
428
429
430    /**
431    * Returns the construvtGraphPattern of the query if there is one.
432    *
433    * @return GraphPattern
434    */
435    public function getConstructPattern(){
436        return $this->constructPattern;
437    }
438
439
440
441    /**
442    *   Returns a list of variables used in the construct patterns.
443    *
444    *   @return array Array of variable names, unique.
445    */
446    public function getConstructPatternVariables()
447    {
448        $arVars = array();
449/*
450        if (count($this->resultPart) > 0) {
451            foreach ($this->resultPart as $pattern) {
452                $arVars = array_merge($arVars, $pattern->getVariables());
453            }
454        }
455*/
456        if ($this->constructPattern) {
457            $arVars = array_merge($arVars, $this->constructPattern->getVariables());
458        }
459
460        return array_unique($arVars);
461    }//public function getConstructPatternVariables()
462
463
464
465    /**
466    *   Returns the language of a variable if the tag is set (e.g. @en)
467    *   Returns NULL if no language is set.
468    *
469    *   @param string Sparql variable name
470    *   @return mixed NULL or language tag
471    */
472    public static function getLanguageTag($var)
473    {
474        $nAt = strpos($var, '@');
475        if ($nAt === false) {
476            return null;
477        }
478        //in case @ and ^^ are combined
479        $nHatHat = strpos($var, '^^', $nAt + 1);
480        if ($nHatHat === false) {
481            $tag = substr($var, $nAt + 1);
482        } else {
483            $tag = substr($var, $nAt + 1, $nHatHat - $nAt - 1);
484        }
485        return $tag;
486    }//public static function getLanguageTag($var)
487
488
489
490    /**
491    *   Returns the datatype of a variable if it is set.
492    *
493    *   @param string Sparql variable name
494    *   @return mixed NULL or datatype
495    */
496    public function getDatatype($var)
497    {
498        $nHatHat = strpos($var, '^^');
499        if ($nHatHat === false) {
500            return null;
501        }
502        $nAt = strpos($var, '@', $nHatHat + 2);
503        if ($nAt === false) {
504            $type = substr($var, $nHatHat + 2);
505        } else {
506            $type = substr($var, $nHatHat + 2, $nAt - $nHatHat - 2);
507        }
508
509        $fullUri = $this->getFullUri($type);
510        if ($fullUri === false) {
511            $fullUri = $type;
512            if ($fullUri[0] == '<' && substr($fullUri, -1) == '>') {
513                $fullUri = substr($fullUri, 1, -1);
514            }
515        }
516
517        return $fullUri;
518    }//public function getDatatype($var)
519
520
521
522    /**
523    * Gets the full URI of a qname token.
524    *
525    * @param  string $token
526    * @return string The complete URI of a given token, false if $token is not
527    *                a qname or the prefix is not defined
528    */
529    public function getFullUri($token)
530    {
531        $pattern="/^([^:]*):([^:]*)$/";
532        if (preg_match($pattern, $token, $hits) > 0) {
533
534            if (isset($this->prefixes{$hits{1}})) {
535                return substr($this->base, 1, -1)
536                     . $this->prefixes{$hits{1}}
537                     . $hits{2};
538            }
539            if ($hits{1}=='_') {
540                return "_".$hits{2};
541            }
542        }
543
544        return false;
545    }
546
547
548
549    /**
550    *   Checks if the query is complete
551    *   (so that querying is possible)
552    *
553    *   @return boolean true if the query is complete
554    */
555    public function isComplete()
556    {
557        if ($this->resultForm === null) {
558            return false;
559        }
560        //TODO: maybe check selected vars and construct pattern depending
561        // on the resultform
562        return true;
563    }//public function isIncomplete()
564
565
566
567    /**
568    * Sets the orignal query string
569    *
570    * @param string $queryString SPARQL query string
571    */
572    public function setQueryString($queryString)
573    {
574        $this->queryString = $queryString;
575    }//public function setQueryString($queryString)
576
577
578
579    /**
580    * Returns the orignal query string
581    *
582    * @return string SPARQL query string
583    */
584    public function getQueryString()
585    {
586        return $this->queryString;
587    }//public function getQueryString()
588
589}// end class: Query.php
590
591
592
593class Query_ResultVariable
594{
595    public $variable = null;
596    public $datatype = null;
597    public $language = null;
598    public $alias    = null;
599    public $func     = null;
600
601
602    public function __construct($variable)
603    {
604        $this->variable = $variable;
605        $this->language = Query::getLanguageTag($variable);
606    }
607
608
609
610    public function setAlias($alias)
611    {
612        $this->alias = $alias;
613    }
614
615
616
617    public function setFunc($func)
618    {
619        $this->func = $func;
620    }
621
622
623
624    public function setDatatype($datatype)
625    {
626        $this->datatype = $datatype;
627    }
628
629
630
631    public function getId()
632    {
633        //FIXME
634        return $this->variable;
635    }
636
637
638
639    public function getFunc()
640    {
641        return $this->func;
642    }
643
644
645
646    public function getLanguage()
647    {
648        return $this->language;
649    }
650
651
652
653    public function getDatatype()
654    {
655        return $this->datatype;
656    }
657
658
659
660    public function getName()
661    {
662        if ($this->alias !== null) {
663            return $this->alias;
664        }
665        //FIXME: support for nested(functions())
666        return $this->variable;
667    }
668
669
670
671    public function getVariable()
672    {
673        return $this->variable;
674    }
675
676
677
678    public function __toString()
679    {
680        return $this->getName();
681    }
682
683}//class Query_ResultVariable
684
685?>
Note: See TracBrowser for help on using the repository browser.