source: Dev/branches/rest-dojo-ui/jQueryUI/server/rdfapi/model/DbModel.php @ 312

Last change on this file since 312 was 312, checked in by jkraaijeveld, 13 years ago
File size: 35.6 KB
Line 
1<?php
2require_once RDFAPI_INCLUDE_DIR . 'model/Model.php';
3require_once RDFAPI_INCLUDE_DIR . 'model/Blanknode.php';
4require_once RDFAPI_INCLUDE_DIR . 'model/Statement.php';
5
6// ----------------------------------------------------------------------------------
7// Class: DbModel
8// ----------------------------------------------------------------------------------
9
10/**
11* This class provides methods for manipulating DbModels from DbStore.
12* A DbModel is an RDF Model, which is persistently stored in a relational database.
13* This Class uses the ADOdb Database Abstraction Library for PHP (http://adodb.sourceforge.net/).
14*
15*
16* @version  $Id: DbModel.php 533 2007-08-16 09:32:03Z cweiske $
17* @author   Radoslaw Oldakowski <radol@gmx.de>
18*
19* @package model
20* @access       public
21*/
22
23
24class DbModel extends Model{
25
26        /**
27        * Database connection object.
28        *
29        * @var     object ADOConnection
30        * @access       private
31        */
32        var $dbConn;
33
34        /**
35        * Unique model URI.
36        * Used to identify the DbModel.
37        *
38        * @var     string
39        * @access       private
40        */
41        var $modelURI;
42
43
44        /**
45        * Database internal modelID.
46        * Used to avoid JOINs.
47        *
48        * @var     string
49        * @access       private
50        */
51        var $modelID;
52
53
54
55
56        /**
57        * Constructor
58        * Do not call this directly.
59        * Use the method getModel,getNewModel or putModel of the Class DbStore instead.
60        *
61        * @param   object ADOConnection  &$dbConnection
62        * @param   string   $modelURI
63        * @param   string   $modelID
64        * @param   string   $baseURI
65        * @access       public
66        */
67        function DbModel(&$dbConnection, $modelURI, $modelID, $baseURI=NULL) {
68
69                $this->dbConn =& $dbConnection;
70                $this->modelURI = $modelURI;
71                $this->modelID = $modelID;
72                $this->baseURI = $this->_checkBaseURI($baseURI);
73        }
74
75
76        /**
77        * Set a base URI for the DbModel.
78        * Affects creating of new resources and serialization syntax.
79        *
80        * @param        string  $uri
81        * @throws  SqlError
82        * @access       public
83        */
84        function setBaseURI($uri) {
85
86                $this->baseURI = $this->_checkBaseURI($uri);
87
88                $rs = $this->dbConn->execute("UPDATE models SET baseURI='" .$this->baseURI ."'
89                                 WHERE modelID=" .$this->modelID);
90                if (!$rs)
91                $this->dbConn->errorMsg();
92        }
93
94
95        /**
96        * Return the number of statements in this DbModel.
97        *
98        * @return       integer
99        * @access       public
100        */
101        function size() {
102
103                $count =& $this->dbConn->getOne('SELECT COUNT(modelID) FROM statements
104                                    WHERE modelID = ' .$this->modelID);
105                return $count;
106        }
107
108
109        /**
110        * Check if this DbModel is empty.
111        *
112        * @return       boolean
113        * @access       public
114        */
115        function isEmpty() {
116
117                if ($this->size() == 0)
118                        return TRUE;
119                return FALSE;
120        }
121
122
123        /**
124        * Add a new triple to this DbModel.
125        *
126        * @param        object Statement        &$statement
127        * @throws       PhpError
128        * @throws  SqlError
129        * @access       public
130        * @return mixed   true on success, false if the statement is already in the model,
131        *                 error message (string) on failure
132        */
133        function add(&$statement) {
134
135                if (!is_a($statement, 'Statement')) {
136                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: add): Statement expected.';
137                        trigger_error($errmsg, E_USER_ERROR);
138                }
139
140                if (!$this->contains($statement)) {
141
142                        $subject_is = $this->_getNodeFlag($statement->subject());
143                        $sql = "INSERT INTO statements
144                                (modelID, subject, predicate, object, l_language, l_datatype, subject_is, object_is)
145                                VALUES
146                    (" .$this->modelID .","
147                        . $this->dbConn->qstr($statement->getLabelSubject()) .","
148                        . $this->dbConn->qstr($statement->getLabelPredicate()) .",";
149
150                        if (is_a($statement->object(), 'Literal')) {
151                                $quotedLiteral = $this->dbConn->qstr($statement->obj->getLabel());
152                                $sql .=        $quotedLiteral .","
153                                ."'" .$statement->obj->getLanguage() ."',"
154                                ."'" .$statement->obj->getDatatype() ."',"
155                                ."'" .$subject_is ."',"
156                                ."'l')";
157                        }else{
158                                $object_is = $this->_getNodeFlag($statement->object());
159                                $sql .=   $this->dbConn->qstr($statement->obj->getLabel()) .","
160                                ."'',"
161                                ."'',"
162                                ."'" .$subject_is ."',"
163                                ."'" .$object_is ."')";
164                        }
165                        $rs =& $this->dbConn->execute($sql);
166                        if (!$rs) {
167                                return $this->dbConn->errorMsg();
168            } else {
169                return true;
170            }
171                } else {
172                        return false;
173                }
174        }
175
176
177        /**
178        * Alias for the method add().
179        *
180        * @param        object Statement        &$statement
181        * @throws       PhpError
182        * @throws  SqlError
183        * @access       public
184        */
185        function addWithoutDuplicates(&$statement) {
186
187                $this->add($statement);
188        }
189
190
191        /**
192        * Remove the given triple from this DbModel.
193        *
194        * @param        object Statement        &$statement
195        * @throws       PhpError
196        * @throws  SqlError
197        * @access       public
198        */
199        function remove(&$statement) {
200
201                if (!is_a($statement, 'Statement')) {
202                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: remove): Statement expected.';
203                        trigger_error($errmsg, E_USER_ERROR);
204                }
205
206                $sql = 'DELETE FROM statements
207           WHERE modelID=' .$this->modelID;
208                $sql .= $this->_createDynSqlPart_SPO ($statement->subj, $statement->pred, $statement->obj);
209
210                $rs =& $this->dbConn->execute($sql);
211                if (!$rs)
212                $this->dbConn->errorMsg();
213        }
214
215
216        /**
217        * Short dump of the DbModel.
218        *
219        * @return       string
220        * @access       public
221        */
222        function toString() {
223
224                return 'DbModel[modelURI=' .$this->modelURI .'; baseURI=' .$this->getBaseURI() .';  size=' .$this->size() .']';
225        }
226
227
228        /**
229        * Dump of the DbModel including all triples.
230        *
231        * @return       string
232        * @access       public
233        */
234        function toStringIncludingTriples() {
235
236                $memModel =& $this->getMemModel();
237                return $memModel->toStringIncludingTriples();
238        }
239
240
241
242        /**
243        * Create a MemModel containing all the triples of the current DbModel.
244        *
245        * @return object MemModel
246        * @access public
247        */
248        function & getMemModel() {
249
250                $recordSet = $this->_getRecordSet($this);
251                $m = $this->_convertRecordSetToMemModel($recordSet);
252                return $m;
253        }
254
255
256
257    /**
258    * Returns the model id
259    *
260    * @return int Model id number
261    * @access public
262    */
263    function getModelID()
264    {
265        return $this->modelID;
266    }
267
268
269
270    /**
271    * Returns the database connection object
272    *
273    * @return ADOdb Database object
274    * @access public
275    */
276    function &getDbConn()
277    {
278        return $this->dbConn;
279    }
280
281
282
283        /**
284        * Write the RDF serialization of the _DbModel as HTML.
285        *
286        * @access       public
287        */
288        function writeAsHtml() {
289
290                $memModel =& $this->getMemModel();
291                $memModel->writeAsHtml();
292        }
293
294
295        /**
296        * Write the RDF serialization of the DbModel as HTML table.
297        *
298        * @access       public
299        */
300        function writeAsHtmlTable() {
301                include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
302                $memModel =& $this->getMemModel();
303                $rdfUtil = new RDFUtil();
304                $rdfUtil->writeHTMLTable($memModel);
305        }
306
307
308        /**
309        * Write the RDF serialization of the DbModel to string.
310        *
311        * @return       string
312        * @access       public
313        */
314        function writeRdfToString() {
315
316                $memModel =& $this->getMemModel();
317                return $memModel->writeRdfToString();
318        }
319
320
321        /**
322        * Saves the RDF,N3 or N-Triple serialization of the DbModel to a file.
323        * You can decide to which format the model should be serialized by using a
324        * corresponding suffix-string as $type parameter. If no $type parameter
325        * is placed this method will serialize the model to XML/RDF format.
326        * Returns FALSE if the DbModel couldn't be saved to the file.
327        *
328        * @access       public
329        * @param        string  $filename
330        * @param        string  $type
331        * @throws   PhpError
332        * @return       boolean
333        */
334        function saveAs($filename, $type ='rdf') {
335
336                $memModel = $this->getMemModel();
337                $memModel->saveAs($filename, $type);
338
339        }
340
341
342        /**
343        * Check if the DbModel contains the given statement.
344        *
345        * @param object Statement  &$statement
346        * @return       boolean
347        * @access       public
348        */
349        function contains(&$statement) {
350
351                $sql = 'SELECT modelID FROM statements
352           WHERE modelID = ' .$this->modelID;
353                $sql .= $this->_createDynSqlPart_SPO($statement->subj, $statement->pred, $statement->obj);
354
355                $res =& $this->dbConn->getOne($sql);
356
357                if (!$res)
358                        return FALSE;
359                return TRUE;
360        }
361
362
363        /**
364        * Determine if all of the statements in the given model are also contained in this DbModel.
365        *
366        * @param        object Model    &$model
367        * @return       boolean
368        * @access       public
369        */
370        function containsAll(&$model) {
371
372                if (is_a($model, 'MemModel')) {
373
374                        foreach($model->triples as $statement)
375                        if(!$this->contains($statement))
376                                return FALSE;
377                        return TRUE;
378                }
379
380                elseif (is_a($model, 'DbModel')) {
381
382                        $recordSet =& $this->_getRecordSet($model);
383                        while (!$recordSet->EOF) {
384                                if (!$this->_containsRow($recordSet->fields))
385                                        return FALSE;
386                                $recordSet->moveNext();
387                        }
388                        return TRUE;
389                }
390
391                $errmsg = RDFAPI_ERROR . '(class: DbModel; method: containsAll): Model expected.';
392                trigger_error($errmsg, E_USER_ERROR);
393        }
394
395
396        /**
397        * Determine if any of the statements in the given model are also contained in this DbModel.
398        *
399        * @param        object Model    &$model
400        * @return       boolean
401        * @access       public
402        */
403        function containsAny(&$model) {
404
405                if (is_a($model, 'MemModel')) {
406
407                        foreach($model->triples as $statement)
408                        if($this->contains($statement))
409                                return TRUE;
410                        return FALSE;
411                }
412
413                elseif (is_a($model, 'DbModel')) {
414
415                        $recordSet =& $this->_getRecordSet($model);
416                        while (!$recordSet->EOF) {
417                                if ($this->_containsRow($recordSet->fields))
418                                        return TRUE;
419                                $recordSet->moveNext();
420                        }
421                        return FALSE;
422                }
423
424                $errmsg = RDFAPI_ERROR . '(class: DbModel; method: containsAny): Model expected.';
425                trigger_error($errmsg, E_USER_ERROR);
426        }
427
428
429        /**
430        * General method to search for triples in the DbModel.
431        * NULL input for any parameter will match anything.
432        * Example:  $result = $m->find( NULL, NULL, $node );
433        *           Finds all triples with $node as object.
434        *
435        * @param        object Resource $subject
436        * @param        object Resource $predicate
437        * @param        object Node     $object
438        * @return       object MemModel
439        * @throws       PhpError
440        * @throws  SqlError
441        * @access       public
442        */
443        function find($subject, $predicate, $object) {
444
445                if ((!is_a($subject, 'Resource') && $subject != NULL) ||
446                (!is_a($predicate, 'Resource') && $predicate != NULL) ||
447                (!is_a($object, 'Node') && $object != NULL)) {
448
449                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
450                        trigger_error($errmsg, E_USER_ERROR);
451                }
452
453                // static part of the sql statement
454                $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
455           FROM statements
456           WHERE modelID = ' .$this->modelID;
457
458                // dynamic part of the sql statement
459                $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
460
461                // execute the query
462                $recordSet =& $this->dbConn->execute($sql);
463
464                if (!$recordSet)
465                        echo $this->dbConn->errorMsg();
466
467                // write the recordSet into memory Model
468                else
469                        return $this->_convertRecordSetToMemModel($recordSet);
470        }
471
472
473        /**
474        * Method to search for triples using Perl-style regular expressions.
475        * NULL input for any parameter will match anything.
476        * Example:  $result = $m->find_regex( NULL, NULL, $regex );
477        *           Finds all triples where the label of the object node matches
478        *the regular expression.
479        * Return an empty MemModel if nothing is found.
480        * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
481        * WARNING: Mhis method loads a DbModel into memory and performs the search
482        *          on a MemModel, which can be slow with large models.
483        * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
484        *
485        * @param        string  $subject_regex
486        * @param        string  $predicate_regex
487        * @param        string  $object_regex
488        * @return       object MemModel
489        * @throws       PhpError
490        * @throws  SqlError
491        * @access       public
492        */
493        function findRegex($subject_regex, $predicate_regex, $object_regex) {
494
495                $mm =& $this->getMemModel();
496
497                return $mm->findRegex($subject_regex, $predicate_regex, $object_regex);
498        }
499
500
501        /**
502        * Return all tripels of a certain vocabulary.
503        * $vocabulary is the namespace of the vocabulary inluding a # : / char at the end.
504        * e.g. http://www.w3.org/2000/01/rdf-schema#
505        * Return an empty model if nothing is found.
506        *
507        * @param        string  $vocabulary
508        * @return       object MemModel
509        * @throws       PhpError
510        * @throws  SqlError
511        * @access       public
512        */
513        function findVocabulary($vocabulary) {
514
515                $sql = "SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
516           FROM statements
517           WHERE modelID = " .$this->modelID ."
518           AND predicate LIKE '" .$vocabulary ."%'";
519
520                $recordSet =& $this->dbConn->execute($sql);
521
522                if (!$recordSet)
523                echo $this->dbConn->errorMsg();
524
525                // write the recordSet into memory Model
526                else
527                return $this->_convertRecordSetToMemModel($recordSet);
528        }
529
530
531        /**
532        * Search for triples and return the first matching statement.
533        * NULL input for any parameter will match anything.
534        * Return an NULL if nothing is found.
535        * You can set an search offset with $offset.
536        *
537        * @param        object Resource $subject
538        * @param        object Resource $predicate
539        * @param        object Node     $object
540        * @param        integer $offset
541        * @return       object Statement
542        * @throws  PhpError
543        * @throws  SqlError
544        * @access       public
545        */
546        function findFirstMatchingStatement($subject, $predicate, $object, $offset = -1) {
547
548                if ((!is_a($subject, 'Resource') && $subject != NULL) ||
549                (!is_a($predicate, 'Resource') && $predicate != NULL) ||
550                (!is_a($object, 'Node') && $object != NULL)) {
551
552                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
553                        trigger_error($errmsg, E_USER_ERROR);
554                }
555
556                // static part of the sql statement
557                $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
558           FROM statements
559           WHERE modelID = ' .$this->modelID;
560
561                // dynamic part of the sql statement
562                $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
563
564                // execute the query
565                $recordSet =& $this->dbConn->selectLimit($sql,1,($offset));
566
567                if (!$recordSet)
568                echo $this->dbConn->errorMsg();
569                else {
570                        if (!$recordSet->fields)
571                        return NULL;
572                        else {
573                                $memModel = $this->_convertRecordSetToMemModel($recordSet);
574                                return $memModel->triples[0];
575                        }
576                }
577        }
578
579
580        /**
581        * Search for triples and return the number of matches.
582        * NULL input for any parameter will match anything.
583        *
584        * @param        object Resource $subject
585        * @param        object Resource $predicate
586        * @param        object Node     $object
587        * @return       integer
588        * @throws       PhpError
589        * @throws  SqlError
590        * @access       public
591        */
592        function findCount($subject, $predicate, $object) {
593
594                if ((!is_a($subject, 'Resource') && $subject != NULL) ||
595                (!is_a($predicate, 'Resource') && $predicate != NULL) ||
596                (!is_a($object, 'Node') && $object != NULL)) {
597
598                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameters must be subclasses of Node or NULL';
599                        trigger_error($errmsg, E_USER_ERROR);
600                }
601
602                // static part of the sql statement
603                $sql = 'SELECT COUNT(*)
604           FROM statements
605           WHERE modelID = ' .$this->modelID;
606
607                // dynamic part of the sql statement
608                $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
609
610                // execute the query
611                $recordSet =& $this->dbConn->execute($sql);
612
613                if (!$recordSet)
614                        echo $this->dbConn->errorMsg();
615                else
616                        return $recordSet->fields[0];
617        }
618
619
620        /**
621        * Perform an RDQL query on this DbModel.
622        * This method returns an associative array of variable bindings.
623        * The values of the query variables can either be RAP's objects (instances of Node)
624        * if $returnNodes set to TRUE, or their string serialization.
625        *
626        * @access       public
627        * @param string $queryString
628        * @param boolean $returnNodes
629        * @return  array   [][?VARNAME] = object Node  (if $returnNodes = TRUE)
630        *      OR  array   [][?VARNAME] = string
631        *
632        */
633        function rdqlQuery($queryString, $returnNodes = TRUE) {
634                require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
635                $parser = new RdqlParser();
636                $parsedQuery =& $parser->parseQuery($queryString);
637
638                // this method can only query this DbModel
639                // if another model was specified in the from clause throw an error
640                if (isset($parsedQuery['sources'][0]))
641                if($parsedQuery['sources'][0] != $this->modelURI) {
642                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: rdqlQuery):';
643                        $errmsg .= ' this method can only query this DbModel';
644                        trigger_error($errmsg, E_USER_ERROR);
645                }
646
647                $engine = new RdqlDbEngine();
648                $res =& $engine->queryModel($this, $parsedQuery, $returnNodes);
649
650                return $res;
651        }
652
653
654        /**
655        * Perform an RDQL query on this DBModel.
656        * This method returns an RdqlResultIterator of variable bindings.
657        * The values of the query variables can either be RAP's objects (instances of Node)
658        * if $returnNodes set to TRUE, or their string serialization.
659        *
660        * @access       public
661        * @param string $queryString
662        * @param boolean $returnNodes
663        * @return  object RdqlResultIterator = with values as object Node  (if $returnNodes = TRUE)
664        *      OR  object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
665        *
666        */
667        function rdqlQueryAsIterator($queryString, $returnNodes = TRUE) {
668                require_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
669                return new RdqlResultIterator($this->rdqlQuery($queryString, $returnNodes));
670        }
671
672        /**
673        * General method to replace nodes of a DbModel.
674        * NULL input for any parameter will match nothing.
675        * Example:  $m->replace($resource, NULL, $node, $replacement);
676        *           Replaces all $node objects beeing subject or object in
677        *           any triple of the model with the $replacement node.
678        * Throw an error in case of a paramter mismatch.
679        *
680        * @param        object Resource $subject
681        * @param        object Resource $predicate
682        * @param        object Node     $object
683        * @param        object Node     $replacement
684        * @throws       PhpError
685        * @throws  SqlError
686        * @access       public
687        */
688        function replace($subject, $predicate, $object, $replacement) {
689
690                // check the correctness of the passed parameters
691                if ( ((!is_a($subject, 'Resource') && $subject != NULL) ||
692                (!is_a($predicate, 'Resource') && $predicate != NULL) ||
693                (!is_a($object, 'Node') && $object != NULL)) ||
694                (($subject != NULL && is_a($replacement, 'Literal')) ||
695                ($predicate != NULL && (is_a($replacement, 'Literal') ||
696                is_a($replacement, 'BlankNode')))) )
697                {
698                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: find): Parameter mismatch';
699                        trigger_error($errmsg, E_USER_ERROR);
700                }
701
702                if (!(!$subject && !$predicate && !$object)) {
703
704                        // create an update sql statement
705                        $comma = '';
706                        $sql = 'UPDATE statements
707             SET ';
708                        if ($subject) {
709                                $sql .= " subject ='" .$replacement->getLabel() ."', "
710                                ." subject_is='" .$this->_getNodeFlag($replacement) ."' ";
711                                $comma = ',';
712                        }
713                        if ($predicate) {
714                                $sql .= $comma ." predicate='" .$replacement->getLabel() ."' ";
715                                $comma = ',';
716                        }
717                        if ($object) {
718                                $quotedObject = $this->dbConn->qstr($replacement->getLabel());
719                                $sql .= $comma .' object=' .$quotedObject
720                                .", object_is='" .$this->_getNodeFlag($replacement) ."' ";
721                                if (is_a($replacement, 'Literal')) {
722                                        $sql .= ", l_language='" .$replacement->getLanguage() ."' "
723                                        .", l_datatype='" .$replacement->getDataType() ."' ";
724                                }
725                        }
726                        $sql .= 'WHERE modelID = ' .$this->modelID;
727                        $sql .= $this->_createDynSqlPart_SPO($subject, $predicate, $object);
728
729                        // execute the query
730                        $rs =& $this->dbConn->execute($sql);
731
732                        if (!$rs)
733                        echo $this->dbConn->errorMsg();
734                }
735        }
736
737
738        /**
739        * Check if two models are equal.
740        * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
741        *
742        * Warning: This method doesn't work correct with models where the same blank node has different
743        * identifiers in the two models. We will correct this in a future version.
744        *
745        * @param        object  model &$that
746        * @return       boolean
747        * @throws  PhpError
748        * @access       public
749        */
750
751        function equals(&$that)  {
752
753                if (!is_a($that, 'Model')) {
754                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: equals): Model expected.';
755                        trigger_error($errmsg, E_USER_ERROR);
756                }
757
758                if ($this->size() != $that->size())
759                return FALSE;
760
761                include_once(RDFAPI_INCLUDE_DIR. "util/ModelComparator.php");
762                return ModelComparator::compare($this,$that);
763        }
764
765
766        /**
767        * Return a new MemModel that is the set-union the model with another model.
768        *
769        * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
770        * is another graph, which we will call the merge of the graphs.
771        * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
772        * a merged graph, two occurrences of a given uriref or literal as nodes in two different
773        * graphs become a single node in the union graph (since by definition they are the same
774        * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
775        * never merged. In particular, this means that every blank node in a merged graph can be
776        * identified as coming from one particular graph in the original set of graphs.
777        *
778        * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
779        * their corresponding N-triples documents and constructing the graph described by the merged
780        * document, since if some of the documents use the same node identifiers, the merged document
781        * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
782        * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
783        * more documents, and to replace it with a distinct nodeID in each of them, before merging the
784        * documents. (Not implemented yet !!!!!!!!!!!)
785        *
786        * @param        object Model    $model
787        * @return       object MemModel
788        * @throws PhpError
789        * @access       public
790        *
791        */
792        function & unite(&$model)  {
793
794                if (!is_a($model, 'Model')) {
795                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: unite): Model expected.';
796                        trigger_error($errmsg, E_USER_ERROR);
797                }
798
799                if (is_a($model, 'MemModel')) {
800
801                        $thisModel =& $this->getMemModel();
802                        return $thisModel->unite($model);
803                }
804
805                elseif (is_a($model, 'DbModel')) {
806
807                        $thisModel =& $this->getMemModel();
808                        $thatModel =& $model->getMemModel();
809                        return $thisModel->unite($thatModel);
810                }
811        }
812
813
814        /**
815        * Return a new MemModel that is the subtraction of another model from this DbModel.
816        *
817        * @param        object Model    $model
818        * @return       object MemModel
819        * @throws PhpError
820        * @access       public
821        */
822
823        function & subtract(&$model)  {
824
825                if (!is_a($model, 'Model')) {
826                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: subtract): Model expected.';
827                        trigger_error($errmsg, E_USER_ERROR);
828                }
829
830                if (is_a($model, 'MemModel')) {
831
832                        $thisModel =& $this->getMemModel();
833                        return $thisModel->subtract($model);
834                }
835
836                elseif (is_a($model, 'DbModel')) {
837
838                        $thisModel =& $this->getMemModel();
839                        $thatModel =& $model->getMemModel();
840                        return $thisModel->subtract($thatModel);
841                }
842        }
843
844
845        /**
846        * Return a new MemModel containing all the statements which are in both
847        * this model and the given model.
848        *
849        * @param        object Model    $model
850        * @return       object MemModel
851        * @throws  PhpError
852        * @access       public
853        */
854        function & intersect(&$model)  {
855
856                if (is_a($model, 'MemModel')) {
857
858                        $thisModel =& $this->getMemModel();
859                        return $thisModel->intersect($model);
860                }
861
862                elseif (is_a($model, 'DbModel')) {
863
864                        $thisModel =& $this->getMemModel();
865                        $thatModel =& $model->getMemModel();
866                        return $thisModel->intersect($thatModel);
867                }
868
869                $errmsg = RDFAPI_ERROR . '(class: DbModel; method: intersect: Model expected.';
870                trigger_error($errmsg, E_USER_ERROR);
871        }
872
873
874        /**
875        * Add the given model to this DbModel.
876        * This function monitors for SQL errors, and will commit if no errors have occured,
877        * otherwise it will rollback.
878        * If any statement of the model to be added to this model contains a blankNode
879        * with an identifier already existing in this model, a new blankNode is generated.
880        *
881        * @param        object Model    $model
882        * @throws  PhpError
883        * @access       public
884        */
885        function addModel(&$model)  {
886
887                if (!is_a($model, 'Model')) {
888                        $errmsg = RDFAPI_ERROR . '(class: DbModel; method: addModel): Model expected.';
889                        trigger_error($errmsg, E_USER_ERROR);
890                }
891
892                $blankNodes_tmp = array();
893
894                if (is_a($model, 'MemModel')) {
895
896                        $this->dbConn->startTrans();
897                        foreach ($model->triples as $statement)
898                        $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
899                        $this->addParsedNamespaces($model->getParsedNamespaces());
900
901                        $this->dbConn->completeTrans();
902                }
903
904                elseif (is_a($model, 'DbModel')) {
905
906                        $this->dbConn->startTrans();
907                        $memModel =& $model->getMemModel();
908                        foreach($memModel->triples as $statement)
909                                $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
910                        $this->addParsedNamespaces($model->getParsedNamespaces());
911                        $this->dbConn->completeTrans();
912                }
913        }
914
915
916        /**
917        * Reify the DbModel.
918        * Return a new MemModel that contains the reifications of all statements of this DbModel.
919        *
920        * @return       object  MemModel
921        * @access       public
922        */
923        function & reify() {
924
925                $memModel =& $this->getMemModel();
926                return $memModel->reify();
927        }
928
929        /**
930        * Remove this DbModel from database and clean up.
931        * This function monitors for SQL errors, and will commit if no errors have occured,
932        * otherwise it will rollback.
933        *
934        * @throws  SqlError
935        * @access       public
936        */
937        function delete() {
938
939                $this->dbConn->startTrans();
940                $this->dbConn->execute('DELETE FROM models
941                                  WHERE modelID=' .$this->modelID);
942                $this->dbConn->execute('DELETE FROM statements
943                                  WHERE modelID=' .$this->modelID);
944                $this->dbConn->execute('DELETE FROM namespaces
945                                  WHERE modelID=' .$this->modelID);
946
947                if (!$this->dbConn->completeTrans())
948                        echo $this->dbConn->errorMsg();
949                else
950                        $this->close();
951        }
952
953
954        /**
955        * Close this DbModel
956        *
957        * @access       public
958        */
959        function close() {
960
961                unset($this);
962        }
963
964
965        // =============================================================================
966        // **************************** private methods ********************************
967        // =============================================================================
968
969
970
971
972
973        /**
974        * If the URI doesn't end with # : or /, then a # is added to the URI.
975        * Used at setting the baseURI of this DbModel.
976        *
977        * @param   string  $uri
978        * @return  string
979        * @access       private
980        */
981        function _checkBaseURI($uri)  {
982
983                if ($uri != NULL) {
984                        $c = substr($uri, strlen($uri)-1 ,1);
985                        if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
986                        $uri .= '#';
987                }
988                return $uri;
989        }
990
991
992        /**'
993        * Return the flag of the Node object.
994        * r - Resource, b - BlankNode, l - Literal
995        *
996        * @param   object Node $object
997        * @return  string
998        * @access       private
999        */
1000        function _getNodeFlag($object)  {
1001
1002                return is_a($object,'BlankNode')?'b':(is_a($object,'Resource')?'r':'l');
1003        }
1004
1005
1006        /**
1007        * Convert an ADORecordSet to a memory Model.
1008        *
1009        * Every successful database query returns an ADORecordSet object which is actually
1010        * a cursor that holds the current row in the array fields[].
1011        * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1012        * !!! This method can only be applied to a RecordSet with array fields[]
1013        * !!! containing a representation of the database table: statements,
1014        * !!! with an index corresponding to following table columns:
1015        * !!! [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
1016        * !!! [4] - l_datatype, [5] - subject_is, [6] - object_is
1017        * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1018        *
1019        * @param   object  ADORecordSet
1020        * @return  object  MemModel
1021        * @access       private
1022        */
1023        function _convertRecordSetToMemModel(&$recordSet)  {
1024
1025                $res = new MemModel($this->baseURI);
1026                while (!$recordSet->EOF) {
1027
1028                        // subject
1029                        if ($recordSet->fields[5] == 'r')
1030                                $sub = new Resource($recordSet->fields[0]);
1031                        else
1032                                $sub = new BlankNode($recordSet->fields[0]);
1033
1034                        // predicate
1035                        $pred = new Resource($recordSet->fields[1]);
1036
1037                        // object
1038                        if ($recordSet->fields[6] == 'r')
1039                                $obj = new Resource($recordSet->fields[2]);
1040                        elseif ($recordSet->fields[6] == 'b')
1041                                $obj = new BlankNode($recordSet->fields[2]);
1042                        else {
1043                                $obj = new Literal($recordSet->fields[2], $recordSet->fields[3]);
1044                                if ($recordSet->fields[4])
1045                                $obj->setDatatype($recordSet->fields[4]);
1046                        }
1047
1048                        $statement = new Statement($sub, $pred, $obj);
1049                        $res->add($statement);
1050
1051                        $recordSet->moveNext();
1052                }
1053                $res->addParsedNamespaces($this->getParsedNamespaces());
1054                return $res;
1055        }
1056
1057
1058        /**
1059        * Create the dynamic part of an sql statement selecting triples with the
1060        * given parameters ($subject, $predicate, $object).
1061        *
1062        * @param        object Resource $subject
1063        * @param        object Resource $predicate
1064        * @param        object Node     $object
1065        * @return  string
1066        * @access       private
1067        */
1068        function _createDynSqlPart_SPO($subject, $predicate, $object) {
1069
1070                // conditions derived from the parameters passed to the function
1071
1072                $subject_is=is_a($subject,'BlankNode')?'b':(is_a($subject,'Resource')?'r':'l');
1073                $sql='';
1074                if ($subject != NULL)
1075                        $sql .= " AND subject='" .$subject->getLabel() ."'
1076                AND subject_is='" .$subject_is ."'";
1077                if ($predicate != NULL)
1078                        $sql .= " AND predicate='" .$predicate->getLabel() ."'";
1079                if ($object != NULL) {
1080                        $object_is = is_a($object,'BlankNode')?'b':(is_a($object,'Resource')?'r':'l');
1081                        if (is_a($object, 'Resource'))
1082                                $sql .= " AND object='" .$object->getLabel() ."'
1083                   AND object_is ='" .$object_is ."'";
1084                        else  {
1085                                $quotedLiteral = $this->dbConn->qstr($object->getLabel());
1086                                $sql .= " AND object=" .$quotedLiteral ."
1087                   AND l_language='" .$object->getLanguage() ."'
1088                   AND l_datatype='" .$object->getDataType() ."'
1089                   AND object_is ='" .$object_is ."'";
1090                        }
1091                }
1092                return $sql;
1093        }
1094
1095
1096        /**
1097        * Get an ADORecordSet with array fields[] containing a representation of
1098        * the given DbModel stored in the table: statements, with an index corresponding
1099        * to following table columns:
1100        * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
1101        * [4] - l_datatype, [5] - subject_is, [6] - object_is
1102        * (This method operates on data from a DbModel without loading it into a memory model
1103        *  in order to save resources and improve speed).
1104        *
1105        * @param        object DbModel  $DbModel
1106        * @return  object ADORecordSet
1107        * @access       private
1108        */
1109        function _getRecordSet (&$dbModel) {
1110
1111                $sql = 'SELECT subject, predicate, object, l_language, l_datatype, subject_is, object_is
1112           FROM statements
1113           WHERE modelID = ' .$dbModel->modelID;
1114
1115                return $recordSet =& $this->dbConn->execute($sql);
1116        }
1117
1118
1119        /**
1120        * Check if this DbModel contains the given row from the array fields[] of an ADORecordSet
1121        * The array index corresponds to following table columns:
1122        * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
1123        * [4] - l_datatype, [5] - subject_is, [6] - object_is
1124        *
1125        * @param   array  $row
1126        * @return  boolean
1127        * @access       private
1128        */
1129        function _containsRow ($row) {
1130
1131                $sql = "SELECT modelID FROM statements
1132           WHERE modelID = " .$this->modelID ."
1133           AND subject ="   .$this->dbConn->qstr($row[0]) ."
1134           AND predicate =" .$this->dbConn->qstr($row[1]) ."
1135           AND object ="    .$this->dbConn->qstr($row[2]) ."
1136           AND l_language=" .$this->dbConn->qstr($row[3]) ."
1137           AND l_datatype=" .$this->dbConn->qstr($row[4]) ."
1138           AND subject_is=" .$this->dbConn->qstr($row[5]) ."
1139           AND object_is="  .$this->dbConn->qstr($row[6]);
1140
1141                $res =& $this->dbConn->getOne($sql);
1142
1143                if (!$res)
1144                  return FALSE;
1145                return TRUE;
1146        }
1147
1148
1149
1150
1151
1152        /**
1153        * Returns the models namespaces.
1154        *
1155        * @author   Tobias Gauss <tobias.gauss@web.de>
1156        * @return mixed Array of key-value pairs. Namespace is the key,
1157        *               prefix the value. If no namespaces are found,
1158        *               boolean false is returned.
1159        *
1160        * @access   public
1161        */
1162        function getParsedNamespaces(){
1163                $sql = "SELECT * FROM namespaces
1164           WHERE modelID = " .$this->modelID;
1165                $temp = false;
1166                $res  = $this->dbConn->execute($sql);
1167                if($res){
1168                        while (!$res->EOF) {
1169                                $temp[$res->fields[1]]=$res->fields[2];
1170                                $res->moveNext();
1171                        }
1172                }
1173                return $temp;
1174        }
1175
1176
1177
1178        /**
1179        * Adds the namespaces to the model. This method is called by
1180        * the parser. !!!! addParsedNamespaces() not overwrites manual
1181        * added namespaces in the model !!!!
1182        *
1183        * @author Tobias Gauss <tobias.gauss@web.de>
1184        * @param array $newNs Array of namespace => prefix assignments
1185        *
1186        * @access   public
1187        */
1188        function addParsedNamespaces($newNs){
1189                if($newNs)
1190                foreach($newNs as $namespace => $prefix){
1191                        $this->addNamespace($prefix, $namespace);
1192                }
1193        }
1194
1195
1196        /**
1197        * Adds a namespace and prefix to the model.
1198        *
1199        * @author   Tobias Gauss <tobias.gauss@web.de>
1200        * @param string $prefix Prefix
1201        * @param string $nmsp   Namespace URI
1202    *
1203        * @access   public
1204        */
1205        function addNamespace($prefix,$nmsp){
1206
1207                if($nmsp != '' && $prefix !=''){
1208                        if($this->_checkNamespace($nmsp)){
1209                                $sql = "UPDATE namespaces SET prefix=".$this->dbConn->qstr($prefix)." WHERE
1210                                modelID=".$this->modelID." AND namespace=".$this->dbConn->qstr($nmsp);
1211                        }else{
1212                                $sql = "INSERT INTO namespaces
1213                    (modelID, namespace, prefix)
1214                    VALUES
1215                    (" .$this->modelID .','
1216                                . $this->dbConn->qstr($nmsp)   . ','
1217                                . $this->dbConn->qstr($prefix) . ')';
1218                        }
1219
1220                        $rs =& $this->dbConn->execute($sql);
1221                        if (!$rs)
1222                        $this->dbConn->errorMsg();
1223                }
1224        }
1225
1226        /**
1227        * checks if a namespace is already in the model.
1228        *
1229        * @author   Tobias Gauᅵ<tobias.gauss@web.de>
1230        * @access   private
1231        * @param    Array $newNs
1232        */
1233        function _checkNamespace($nmsp){
1234                $res = true;
1235                $sql = "SELECT * FROM namespaces
1236                 WHERE modelID = " .$this->modelID." AND
1237                        namespace=" . $this->dbConn->qstr($nmsp);
1238                $rs =& $this->dbConn->execute($sql);
1239                if (!$rs){
1240                        $this->dbConn->errorMsg();
1241                }else{
1242                        if($rs->fields == false)
1243                        $res = false;
1244                }
1245                return $res;
1246
1247
1248        }
1249
1250        /**
1251        * Returns a FindIterator for traversing the MemModel.
1252        * @access       public
1253        * @return       object  FindIterator
1254        */
1255        function & iterFind($sub=null,$pred=null,$obj=null) {
1256                // Import Package Utility
1257                include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
1258
1259                $if = new IterFind($this,$sub,$pred,$obj);
1260                return $if;
1261        }
1262
1263        /**
1264        * Removes a single namespace from the model
1265        *
1266        * @author Tobias Gauss <tobias.gauss@web.de>
1267        * @param string $nmsp Namespace URI
1268        *
1269        * @return mixed True if all went well, error message otherwise
1270        *
1271        * @access   public
1272        */
1273        function removeNamespace($nmsp){
1274
1275        $sql = 'DELETE FROM namespaces
1276           WHERE modelID=' .$this->modelID." AND namespace=". $this->dbConn->qstr($nmsp);
1277
1278        $rs =& $this->dbConn->execute($sql);
1279        if (!$rs)
1280            return $this->dbConn->errorMsg();
1281        else {
1282            return true;
1283        }
1284        }
1285
1286
1287
1288
1289        /**
1290        * Add the given row from the array fields[] of an ADORecordSet to this DbModel
1291        * The array index corresponds to following table columns:
1292        * [0] - subject, [1] - predicate, [2] - object, [3] - l_language,
1293        * [4] - l_datatype, [5] - subject_is, [6] - object_is
1294        *
1295        * @param   array  $row
1296        * @throws  SqlError
1297        * @access       private
1298        *
1299        function _insertRow ($row) {
1300
1301        $quotedObject = $this->dbConn->qstr($row[2]);
1302        $sql = "INSERT INTO statements VALUES
1303        (" .$this->modelID .","
1304        ."'" .$row[0] ."',"
1305        ."'" .$row[1] ."',"
1306        .""  .$quotedObject .","
1307        ."'" .$row[3] ."',"
1308        ."'" .$row[4] ."',"
1309        ."'" .$row[5] ."',"
1310        ."'" .$row[6] ."')";
1311
1312        $rs =& $this->dbConn->execute($sql);
1313        if (!$rs)
1314        $this->dbConn->errorMsg();
1315        }
1316        */
1317
1318} // end: Class DbModel
1319?>
Note: See TracBrowser for help on using the repository browser.