r32804 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r32803‎ | r32804 | r32805 >
Date:08:43, 5 April 2008
Author:vrandezo
Status:old
Tags:
Comment:
Patch by Felix Kratzer for making RAP store binding actually run
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_RAPStore.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_RAPStore.php
@@ -5,36 +5,42 @@
66 * the store with calls to a RAP store, so it keeps in parallel a second
77 * store with all the semantic data. This allows for a SPARQL endpoint.
88 *
9 - * @author Denny Vrandecic
 9+ * @author Denny Vrandecic (V. 0.1)
 10+ * @author Felix Kratzer (V. 0.2)
1011 */
1112
1213 if( !defined( 'MEDIAWIKI' ) ) {
1314 die( 'Not an entry point.' );
1415 }
1516
16 -global $smwgIP;
 17+global $smwgIP,$smwgRAPPath;
1718 require_once( "$smwgIP/includes/storage/SMW_Store.php" );
1819 require_once( "$smwgIP/includes/storage/SMW_SQLStore.php" );
1920 require_once( "$smwgIP/includes/SMW_DataValueFactory.php" );
2021
 22+define('RDFAPI_INCLUDE_DIR',$smwgRAPPath);
 23+require_once( "$smwgRAPPath/RdfAPI.php");
 24+
2125 /**
2226 * Storage access class for using RAP as a triple store.
2327 * Most of the functions are simply forwarded to the SQL store.
2428 */
25 -class SMWRAPStore extends SMWStore {
 29+class SMWRAPStore extends SMWSQLStore {
2630 protected $sqlstore;
2731 protected $rapstore;
2832 protected $modeluri;
2933 protected $baseuri;
 34+
3035
 36+ /**
 37+ * TODO: maybe find a better nomenclatur for the model
 38+ **/
3139 public function SMWRAPStore() {
32 - global $smwgRAPPath;
33 - define("RDFAPI_INCLUDE_DIR", $smwgRAPPath);
34 - include(RDFAPI_INCLUDE_DIR . "RDFAPI.php");
35 - $this->sqlstore = new SMWSQLStore();
36 -
37 - $this->modeluri = "http://example.org/model/"; // TODO needs some value
38 - $this->baseuri = "http://example.org/id/"; // TODO needs some value
 40+ global $smwgRAPPath,$wgServer;
 41+
 42+
 43+ $this->modeluri = SMWExporter::expandURI($wgServer."/model");
 44+ $this->baseuri = SMWExporter::expandURI($wgServer."/id");
3945 }
4046
4147 ///// Writing methods /////
@@ -46,72 +52,111 @@
4753 * data.
4854 */
4955 function deleteSubject(Title $subject) {
 56+
 57+ // Translate SMWSemanticData to a RAP Model
5058 $rdfmodel = $this->getRAPModel();
51 - $this->closeRAP();
52 - // TODO Implement
53 - return $this->sqlstore->deleteSubject($subject);
 59+
 60+ $rapsub = new Resource(SMWExporter::expandURI($this->getURI($subject)));
 61+ $this->removeSubjectFromRAP($rdfmodel, $rapsub);
 62+
 63+ return parent::deleteSubject($subject);
5464 }
55 -
 65+
 66+
5667 /**
5768 * Update the semantic data stored for some individual. The data is given
5869 * as a SMWSemData object, which contains all semantic data for one particular
5970 * subject. The boolean $newpage specifies whether the page is stored for the
6071 * first time or not.
6172 */
62 - function updateData(SMWSemanticData $data, $newpage) {
63 - if ($data->hasProperties()) {
64 - // Create a local memmodel
65 - $model = ModelFactory::getDefaultModel();
 73+ function updateData(SMWSemanticData $data, $newpage){
 74+ // Create a local memmodel
 75+ $model = ModelFactory::getDefaultModel();
 76+
 77+ // Get DB-Model
 78+ $rdfmodel = $this->getRAPModel();
 79+
 80+ $ed = SMWExporter::makeExportData($data); //ExpData
 81+
 82+ // Delete all we know about the subject!
 83+ $rapsub = new Resource(SMWExporter::expandURI($ed->getSubject()->getName()));
 84+ $this->removeSubjectFromRAP($rdfmodel, $rapsub);
 85+
 86+ $tl = $ed->getTripleList(); // list of tenary arrays
 87+
 88+ // Temporary List of all Blank Nodes in this dataobject
 89+ $blankNodes = array();
 90+
 91+ foreach ($tl as $triple) {
 92+ $s = $triple[0]->getName(); // Subject
 93+ $p = $triple[1]->getName(); // Predicate
 94+ $o = $triple[2]->getName(); // Object
6695
67 - // Translate SMWSemanticData to a RAP Model
68 - $rapsub = new Resource($this->getURI($data->getSubject()));
69 - $properties = $data->getProperties();
70 - foreach ($properties as $prop) {
71 - if (is_int($prop)) continue;
72 - $rapprop = new Resource($this->getURI($prop));
73 - $values = $data->getPropertyValues($prop);
74 - foreach ($values as $val) {
75 - if ($val->getTypeID() == "_wpg") {
76 - $rapval = new Resource($this->getURI($val->getTitle()));
77 - $statement = new Statement($rapsub, $rapprop, $rapval);
78 - $model->add($statement);
79 - } else {
80 - // TODO Save as literal
81 - }
 96+
 97+ // -------------------------------------------------------------------
 98+ // Subject
 99+ // -------------------------------------------------------------------
 100+ $rap_subj = new Resource(SMWExporter::expandURI($triple[0]->getName()));
 101+ if($triple[0] instanceof SMWExpLiteral){ } // Should NEVER happen
 102+ elseif($triple[0] instanceof SMWExpResource){ } // Nothing to do
 103+ else{
 104+ // Is this a blank node??
 105+ if(substr($triple[0]->getName(),0,1) === "_"){
 106+ // We need to create our own unique IDs as we cannot load the whole model into mem every time
 107+ // The exporter generates Numbers inside the page so $triple[0]->getName() is unique on the page
 108+ // $ed->getSubject()->getName() is unique for the wiki
 109+ // we use md5 to get a nicer number, but we could use any other hashing method!
 110+ //
 111+ // Denny thinks this might be a bug of RAP... We leave it this way till we know better!
 112+ //
 113+ $bNodeId = '_' . md5($ed->getSubject()->getName() . $triple[0]->getName());
 114+ $rap_subj = $blankNodes[$bNodeId];
82115 }
83116 }
84 - // TODO Save all other data pertaining to a specific subject,
85 - // i.e. n-aries, longstrings, specials, subproperties, ...
86 - // For an example see the SMW_SQLStore::updateData function
87117
88 - // Now add the local model to the DB model
89 - $rdfmodel = $this->getRAPModel();
90 - // First delete existing statements about subject
91 - $oldmodel = $rdfmodel->find($rapsub, null, null);
92 - $i = $oldmodel->getStatementIterator();
93 - $i->moveFirst();
94 - while ($i->current() != null) {
95 - $rdfmodel->remove($i->current());
96 - $i->next();
 118+ // -------------------------------------------------------------------
 119+ // Predicate
 120+ // -------------------------------------------------------------------
 121+ $rap_pred = new Resource(SMWExporter::expandURI($triple[1]->getName()));
 122+
 123+ // -------------------------------------------------------------------
 124+ // Object
 125+ // -------------------------------------------------------------------
 126+ $rap_obj = new Resource(SMWExporter::expandURI($triple[2]->getName()));
 127+ if($triple[2] instanceof SMWExpLiteral){
 128+ // This is a literal so get the correct type
 129+ $rap_obj = new Literal($triple[2]->getName());
 130+ $rap_obj->setDatatype($triple[2]->getDatatype());
97131 }
98 - // TODO Also remove in the other tables (longstring etc.) from above
99 - $rdfmodel->addModel($model);
100 - $rdfmodel->close();
101 - $model->close();
 132+ elseif($triple[2] instanceof SMWExpResource){ } // Nothing else to do
 133+ else{
 134+ // Is this a blank node??
 135+ if(substr($triple[2]->getName(),0,1) === "_"){
 136+ // See comment @Subject part about IDs
 137+ $bNodeId = '_' . md5($ed->getSubject()->getName().$triple[2]->getName());
 138+ $rap_obj = new BlankNode($bNodeId);
 139+ $blankNodes[$bNodeId] = $rap_obj;
 140+ }
 141+ }
102142
103 - $this->closeRAP();
 143+ // now add the new Statement
 144+ $statement = new Statement($rap_subj, $rap_pred, $rap_obj);
 145+ $model->add($statement);
104146 }
105 - return $this->sqlstore->updateData($data, $newpage);
 147+
 148+ // Add the mem-model to the store
 149+ $rdfmodel->addModel($model);
 150+
 151+
 152+ // Close connections
 153+ $model->close();
 154+ $rdfmodel->close();
 155+ $this->closeRAP();
 156+
 157+
 158+ return parent::updateData($data, $newpage);
106159 }
107160
108 - /**
109 - * Having a title of a page, what is the URI that is described by that page?
110 - */
111 - protected function getURI(Title $title) {
112 - global $smwgIP;
113 - include_once("$smwgIP/specials/ExportRDF/SMW_SpecialExportRDF.php");
114 - return ExportRDF::makeURIfromTitle($title);
115 - }
116161
117162 /**
118163 * Update the store to reflect a renaming of some article. The old and new title objects
@@ -120,11 +165,31 @@
121166 * If $keepid is true, the old and new id of the title is the id of $newtitle, and not the
122167 * id of $oldtitle.
123168 */
124 - function changeTitle(Title $oldtitle, Title $newtitle, $keepid = true) {
 169+ function changeTitle(Title $oldtitle, Title $newtitle, $pageid, $redirid=0) {
 170+
 171+ // Save it in parent store now!
 172+ // We need that so we get all information correctly!
 173+ $result = parent::changeTitle($oldtitle, $newtitle, $pageid, $redirid);
 174+
 175+ // Delete the old stuff
 176+ $nameOld = SMWExporter::expandURI($this->getURI($oldtitle));
125177 $rdfmodel = $this->getRAPModel();
126 - $this->closeRAP();
127 - // TODO Implement
128 - return $this->sqlstore->changeTitle($oldtitle, $newtitle, $keepid);
 178+ $rapsubold = new Resource($nameOld);
 179+ $this->removeSubjectFromRAP($rdfmodel, $rapsubold);
 180+
 181+
 182+ $newpage = SMWDataValueFactory::newTypeIDValue('_wpg');
 183+ $newpage->setValues($newtitle->getDBKey(), $newtitle->getNamespace(), $pageid);
 184+ $semdata = $this->getSemanticData($newpage);
 185+ $this->updateData($semdata,false);
 186+
 187+ // Save the old page
 188+ $oldpage = SMWDataValueFactory::newTypeIDValue('_wpg');
 189+ $oldpage->setValues($oldtitle->getDBKey(), $oldtitle->getNamespace(), $redirid);
 190+ $semdata = $this->getSemanticData($oldpage);
 191+ $this->updateData($semdata,false);
 192+
 193+ return $result;
129194 }
130195
131196 ///// Setup store /////
@@ -161,14 +226,14 @@
162227 }
163228 $this->closeRAP();
164229 $this->reportProgress("RAP setup finished. Handing over to SQL store setup.\n\n",$verbose);
165 - return $this->sqlstore->setup($verbose);
 230+ return parent::setup($verbose);
166231 }
167232
168233 function drop($verbose = true) {
169234 /// TODO: undo all DB changes introduced by setup()
170235 /// Well, not all, just delete the created model. The database tables must retain, since
171236 /// there are only one set of tables for several models.
172 - return $this->sqlstore->drop();
 237+ return parent::drop();
173238 }
174239
175240 /**
@@ -179,8 +244,8 @@
180245 // TODO only for MySQL, check for other databases!
181246 // Also, RAP ignores prefixes for tables. Bad RAP. Need to check with
182247 // the RAP developers to change that.
183 - global $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword;
184 - $this->rapstore = ModelFactory::getDbStore('MySQL', $wgDBserver, $wgDBname, $wgDBuser, $wgDBpassword);
 248+ global $smwgRapDBserver, $smwgRapDBname, $smwgRapDBuser, $smwgRapDBpassword;
 249+ $this->rapstore = ModelFactory::getDbStore('MySQL', $smwgRapDBserver, $smwgRapDBname, $smwgRapDBuser, $smwgRapDBpassword);
185250 return $this->rapstore;
186251 }
187252
@@ -203,46 +268,53 @@
204269
205270 ///// Reading methods -- All forwarded /////
206271 function getSpecialValues(Title $subject, $specialprop, $requestoptions = NULL) {
207 - return $this->sqlstore->getSpecialValues($subject, $specialprop, $requestoptions);
 272+ return parent::getSpecialValues($subject, $specialprop, $requestoptions);
208273 }
209274 function getSpecialSubjects($specialprop, $value, $requestoptions = NULL) {
210 - return $this->sqlstore->getSpecialSubjects($specialprop, $value, $requestoptions);
 275+ return parent::getSpecialSubjects($specialprop, $value, $requestoptions);
211276 }
212 - function getPropertyValues(Title $subject, Title $property, $requestoptions = NULL, $outputformat = '') {
213 - return $this->sqlstore->getPropertyValues($subject, $property, $requestoptions, $outputformat);
 277+
 278+ function getPropertyValues($subject, $property, $requestoptions = NULL, $outputformat = '') {
 279+ return parent::getPropertyValues($subject, $property, $requestoptions, $outputformat);
214280 }
215281 function getPropertySubjects(Title $property, SMWDataValue $value, $requestoptions = NULL) {
216 - return $this->sqlstore->getPropertySubjects($property, $value, $requestoptions);
 282+ return parent::getPropertySubjects($property, $value, $requestoptions);
217283 }
218284 function getAllPropertySubjects(Title $property, $requestoptions = NULL) {
219 - return $this->sqlstore->getAllPropertySubjects($property, $requestoptions);
 285+ return parent::getAllPropertySubjects($property, $requestoptions);
220286 }
221287 function getProperties(Title $subject, $requestoptions = NULL) {
222 - return $this->sqlstore->getProperties($subject, $requestoptions);
 288+ return parent::getProperties($subject, $requestoptions);
223289 }
224290 function getInProperties(SMWDataValue $object, $requestoptions = NULL) {
225 - return $this->sqlstore->getInProperties($object, $requestoptions);
 291+ return parent::getInProperties($object, $requestoptions);
226292 }
 293+ /**
 294+ * This one returns semantic data from the parent store (RAP is only made for writing, reading is ALL handles by the SQL store)
 295+ **/
 296+ function getSemanticData($subject, $filter = false){
 297+ return parent::getSemanticData($subject, $filter);
 298+ }
227299
228300 ///// Query answering -- all forwarded /////
229301
230302 function getQueryResult(SMWQuery $query) {
231 - return $this->sqlstore->getQueryResult($query);
 303+ return parent::getQueryResult($query);
232304 }
233305
234306 ///// Special page functions -- all forwarded /////
235307
236308 function getPropertiesSpecial($requestoptions = NULL) {
237 - return $this->sqlstore->getPropertiesSpecial($requestoptions);
 309+ return parent::getPropertiesSpecial($requestoptions);
238310 }
239311 function getUnusedPropertiesSpecial($requestoptions = NULL) {
240 - return $this->sqlstore->getUnusedPropertiesSpecial($requestoptions);
 312+ return parent::getUnusedPropertiesSpecial($requestoptions);
241313 }
242314 function getWantedPropertiesSpecial($requestoptions = NULL) {
243 - return $this->sqlstore->getWantedPropertiesSpecial($requestoptions);
 315+ return parent::getWantedPropertiesSpecial($requestoptions);
244316 }
245317 function getStatistics() {
246 - return $this->sqlstore->getStatistics();
 318+ return parent::getStatistics();
247319 }
248320
249321 /**
@@ -261,5 +333,50 @@
262334 ob_flush();
263335 flush();
264336 }
 337+
 338+///// Additional helpers
 339+ /**
 340+ * Deletes all relations for the given subject from RAP.
 341+ * This especially also handles n-ary relations recursevly as we would lose them
 342+ **/
 343+ protected function removeSubjectFromRAP($rdfmodel, Resource $subject){
 344+ $oldmodel = $rdfmodel->find($subject, null, null);
 345+ $i = $oldmodel->getStatementIterator();
 346+ $i->moveFirst();
 347+ while ($i->current() != null) {
 348+ $stmt = $i->current();
 349+
 350+ $rdfmodel->remove($stmt);
 351+
 352+ $obj = $stmt->object();
 353+ if($obj instanceof BlankNode){
 354+ // It's a blank node in the object, this means a n-ary relation has been saved
 355+ // So delete everything for this blank node as well!
 356+ $this->removeSubjectFromRAP($rdfmodel, $obj);
 357+ }
 358+
 359+ $i->next();
 360+ }
 361+ // TODO Delete More Stuff, if we save more stuff
 362+ }
 363+
 364+ /**
 365+ * Having a title of a page, what is the URI that is described by that page?
 366+ *
 367+ * The result still requires expandURI()
 368+ */
 369+ protected function getURI($title) {
 370+ $uri = "";
 371+ if($title instanceof Title){
 372+ $dv = SMWDataValueFactory::newTypeIDValue('_wpg');
 373+ $dv->setValues($title->getDBKey(), $title->getNamespace());
 374+ $exp = $dv->getExportData();
 375+ $uri = $exp->getSubject()->getName();
 376+ }else{
 377+ // There could be other types as well that we do NOT handle here
 378+ }
 379+
 380+ return $uri; // still requires expandURI()
 381+ }
265382 }
266383

Status & tagging log