source: Dev/trunk/rdfapi/sparql/SparqlEngineDb/QuerySimplifier.php @ 12

Last change on this file since 12 was 12, checked in by basvannuland, 14 years ago

Added RAP RDF API
Added RDF reader writer for save and load survey

File size: 4.9 KB
Line 
1<?php
2
3/**
4*   Simplifies ("flattens") Query objects that have graph
5*   patterns which are subpatterns of other patterns.
6*
7*   Example:
8*      ?g ?h ?i .
9*      {
10*        {?person <some://typ/e> 'asd'}
11*        UNION
12*        {?person3 <some://typ/es2> 'three'}
13*      }
14*    is represented internally as three graph patterns, the latter
15*    two referencing the first to be their pattern (they are subpatternOf).
16*    Now this can be flattened to this which is the same:
17*      {?g ?h ?i . ?person <some://typ/e> 'asd'}
18*      UNION
19*      {?g ?h ?i .?person3 <some://typ/es2> 'three'}
20*
21*   This class does this.
22*
23*   @author Christian Weiske <cweiske@cweiske.de>
24*   @license http://www.gnu.org/licenses/lgpl.html LGPL
25*/
26class SparqlEngineDb_QuerySimplifier
27{
28
29    /**
30    *   Simplify the query by flattening out subqueries.
31    *   Modifies the passed query object directly.
32    */
33    public function simplify(Query $query)
34    {
35        $arPatterns = $query->getResultPart();
36        self::dropEmpty($arPatterns);
37        $arPlan     = $this->createPlan($arPatterns);
38        if (count($arPlan) == 0) {
39            $query->setResultPart($arPatterns);
40            return 0;
41        }
42
43        $this->executePlan($arPatterns, $arPlan);
44        $query->setResultPart($arPatterns);
45    }//public function simplify(Query $query)
46
47
48
49    /**
50    *   Creates a plan what to do.
51    *
52    *   @return array Array of arrays. Key is the parent pattern id,
53    *               value is an array of subpatterns that belong to
54    *               that parental pattern.
55    */
56    protected function createPlan(&$arPatterns)
57    {
58        $arNumbers = $this->getNumbers($arPatterns);
59        if (count($arNumbers) == 0) {
60            return array();
61        }
62
63        $arPlan    = array();
64
65        foreach ($arNumbers as $nId => $nPatternCount) {
66            $nParent = $arPatterns[$nId]->getSubpatternOf();
67            $arPlan[$nParent][$nId] = true;
68        }
69
70        return $arPlan;
71    }//protected function createPlan(&$arPatterns)
72
73
74
75    /**
76    *   Executes the plan
77    *
78    *   @param array $arPatterns  Array of GraphPatterns
79    *   @param array $arPlan      Plan array as returned by createPlan()
80    */
81    protected function executePlan(&$arPatterns, &$arPlan)
82    {
83        foreach ($arPlan as $nParent => $arChildren) {
84            $base        = $arPatterns[$nParent];
85            $grandParent = $base->getSubpatternOf();
86            $nNextId     = $nParent;
87            foreach ($arChildren as $nChild => $null) {
88                $new = clone $base;
89                $new->addTriplePatterns($arPatterns[$nChild]->getTriplePatterns());
90                $new->addConstraints(   $arPatterns[$nChild]->getConstraints());
91                $new->setId($nNextId);
92                if ($nParent != $nNextId) {
93                    $new->setUnion($nParent);
94                }
95                $arPatterns[$nNextId] = $new;
96
97                if ($grandParent !== null) {
98                    //dynamically adjust plan
99                    $arPlan[$grandParent][$nNextId] = true;
100                }
101
102                $nNextId = $nChild;
103            }
104            //last one is not not needed anymore
105            unset($arPatterns[$nNextId]);
106        }
107    }//protected function executePlan(&$arPatterns, &$arPlan)
108
109
110
111    /**
112    *   Returns an array of id-value pairs determining
113    *   which pattern IDs (array id) are deepest nested
114    *   (higher value).
115    *   Array is sorted in reverse order, highest values
116    *   first.
117    *
118    *   @param array $arPatterns    Array with GraphPatterns
119    *   @return array Array with key-value pairs
120    */
121    protected function getNumbers(&$arPatterns)
122    {
123        $arNumbers = array();
124        foreach ($arPatterns as $nId => &$pattern) {
125            $nParent = $pattern->getSubpatternOf();
126            if ($nParent !== null) {
127                $arNumbers[$nId] = $arNumbers[$nParent] + 1;
128            } else {
129                $arNumbers[$nId] = 0;
130            }
131        }
132        //remove the not so interesting ones
133        foreach ($arNumbers as $nId => $nNumber) {
134            if ($nNumber == 0) {
135                unset($arNumbers[$nId]);
136            }
137        }
138
139        arsort($arNumbers);
140
141        return $arNumbers;
142    }//protected function getNumbers(&$arPatterns)
143
144
145
146    /**
147    *   Removes all empty graph patterns from the array.
148    *   Modifies it directly.
149    */
150    protected static function dropEmpty(&$arPatterns)
151    {
152        foreach ($arPatterns as $nId => &$pattern) {
153            if ($pattern->isEmpty()) {
154                unset($arPatterns[$nId]);
155            }
156        }
157
158        foreach ($arPatterns as $nId => &$pattern) {
159            $nParent = $pattern->getSubpatternOf();
160            if (!isset($arPatterns[$nParent])) {
161                $arPatterns[$nId]->setSubpatternOf(null);
162            }
163        }
164        //FIXME: continued indexes?
165    }//protected static function dropEmpty(&$arPatterns)
166
167}//class SparqlEngineDb_QuerySimplifier
168
169?>
Note: See TracBrowser for help on using the repository browser.