1 | <?php
|
---|
2 | require_once RDFAPI_INCLUDE_DIR . 'model/Model.php';
|
---|
3 | // ----------------------------------------------------------------------------------
|
---|
4 | // Class: MemModel
|
---|
5 | // ----------------------------------------------------------------------------------
|
---|
6 |
|
---|
7 | /**
|
---|
8 | * A MemModel is an RDF Model, which is stored in the main memory.
|
---|
9 | * This class provides methods for manipulating MemModels.
|
---|
10 | *
|
---|
11 | *
|
---|
12 | *
|
---|
13 | * @version $Id: MemModel.php 425 2007-05-01 12:59:18Z cweiske $
|
---|
14 | * @author Chris Bizer <chris@bizer.de>
|
---|
15 | * @author Gunnar AAstrand Grimnes <ggrimnes@csd.abdn.ac.uk>
|
---|
16 | * @author Radoslaw Oldakowski <radol@gmx.de>
|
---|
17 | * @author Daniel Westphal <mail@d-westphal.de>
|
---|
18 | * @author Tobias Gauà <tobias.gauss@web.de>
|
---|
19 | *
|
---|
20 | * @package model
|
---|
21 | * @access public
|
---|
22 | */
|
---|
23 |
|
---|
24 | class MemModel extends Model {
|
---|
25 |
|
---|
26 | /**
|
---|
27 | * Triples of the MemModel
|
---|
28 | * @var array
|
---|
29 | * @access private
|
---|
30 | */
|
---|
31 | var $triples = array();
|
---|
32 |
|
---|
33 | /**
|
---|
34 | * Array containing the search indices
|
---|
35 | * @var array['INDEX_TYPE'][]['label'][]['PosInModel']
|
---|
36 | *
|
---|
37 | * @access private
|
---|
38 | */
|
---|
39 | var $indexArr ;
|
---|
40 |
|
---|
41 |
|
---|
42 | /**
|
---|
43 | * depending on which index is used this variable is -1,0,1,2 or 3
|
---|
44 | *
|
---|
45 | * -1 : no index
|
---|
46 | * 0 : default indices over subject, predicate, object separate
|
---|
47 | * 1 : index over subject+predicate+object
|
---|
48 | * 2 : index over subject+predicate
|
---|
49 | * 3 : index over subject+object
|
---|
50 | *
|
---|
51 | * @var int
|
---|
52 | * @access private
|
---|
53 | */
|
---|
54 | var $indexed;
|
---|
55 |
|
---|
56 |
|
---|
57 |
|
---|
58 | /**
|
---|
59 | * Array of namespaces
|
---|
60 | *
|
---|
61 | * @var array
|
---|
62 | * @access private
|
---|
63 | */
|
---|
64 | var $parsedNamespaces=array();
|
---|
65 |
|
---|
66 |
|
---|
67 |
|
---|
68 | /**
|
---|
69 | * Constructor
|
---|
70 | * You can supply a base_uri
|
---|
71 | *
|
---|
72 | * @param string $baseURI
|
---|
73 | * @access public
|
---|
74 | */
|
---|
75 | function MemModel($baseURI = NULL) {
|
---|
76 | $this->setBaseURI($baseURI);
|
---|
77 | $this->indexed = INDEX_TYPE;
|
---|
78 | }
|
---|
79 |
|
---|
80 | /**
|
---|
81 | * Set a base URI for the MemModel.
|
---|
82 | * Affects creating of new resources and serialization syntax.
|
---|
83 | * If the URI doesn't end with # : or /, then a # is added to the URI.
|
---|
84 | * @param string $uri
|
---|
85 | * @access public
|
---|
86 | */
|
---|
87 | function setBaseURI($uri) {
|
---|
88 |
|
---|
89 | if ($uri != NULL) {
|
---|
90 | $c = substr($uri, strlen($uri)-1 ,1);
|
---|
91 | if (!($c=='#' || $c==':' || $c=='/' || $c=="\\"))
|
---|
92 | $uri .= '#';
|
---|
93 | }
|
---|
94 | $this->baseURI = $uri;
|
---|
95 | }
|
---|
96 |
|
---|
97 |
|
---|
98 | /**
|
---|
99 | * Number of triples in the MemModel
|
---|
100 | *
|
---|
101 | * @return integer
|
---|
102 | * @access public
|
---|
103 | */
|
---|
104 | function size() {
|
---|
105 | return count($this->triples);
|
---|
106 | }
|
---|
107 |
|
---|
108 | /**
|
---|
109 | * Checks if MemModel is empty
|
---|
110 | *
|
---|
111 | * @return boolean
|
---|
112 | * @access public
|
---|
113 | */
|
---|
114 | function isEmpty() {
|
---|
115 | if (count($this->triples) == 0) {
|
---|
116 | return TRUE;
|
---|
117 | } else {
|
---|
118 | return FALSE;
|
---|
119 | };
|
---|
120 | }
|
---|
121 |
|
---|
122 |
|
---|
123 | /**
|
---|
124 | * Adds a new triple to the MemModel without checking if the statement is already in the MemModel.
|
---|
125 | * So if you want a duplicate free MemModel use the addWithoutDuplicates() function (which is slower then add())
|
---|
126 | *
|
---|
127 | * @param object Statement $statement
|
---|
128 | * @access public
|
---|
129 | * @throws PhpError
|
---|
130 | */
|
---|
131 | function add($statement) {
|
---|
132 | if (!is_a($statement, 'Statement')) {
|
---|
133 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: add): Statement expected.';
|
---|
134 | trigger_error($errmsg, E_USER_ERROR);
|
---|
135 | }
|
---|
136 |
|
---|
137 | if($this->indexed != -1){
|
---|
138 | $this->triples[] = $statement;
|
---|
139 | end($this->triples);
|
---|
140 | $k=key($this->triples);
|
---|
141 | if($this->indexed==0){
|
---|
142 | // index over S
|
---|
143 | $this->_indexOpr($statement,$k,4,1);
|
---|
144 | // index over P
|
---|
145 | $this->_indexOpr($statement,$k,5,1);
|
---|
146 | // index over O
|
---|
147 | $this->_indexOpr($statement,$k,6,1);
|
---|
148 | }else{
|
---|
149 | $this->_indexOpr($statement,$k,$this->indexed,1);
|
---|
150 | }
|
---|
151 |
|
---|
152 | }else{
|
---|
153 | $this->triples[] = $statement;
|
---|
154 | }
|
---|
155 | }
|
---|
156 |
|
---|
157 |
|
---|
158 |
|
---|
159 | /**
|
---|
160 | * Checks if a new statement is already in the MemModel and adds the statement, if it is not in the MemModel.
|
---|
161 | * addWithoutDuplicates() is significantly slower then add().
|
---|
162 | * Retruns TRUE if the statement is added.
|
---|
163 | * FALSE otherwise.
|
---|
164 | *
|
---|
165 | * @param object Statement $statement
|
---|
166 | * @return boolean
|
---|
167 | * @access public
|
---|
168 | * @throws PhpError
|
---|
169 | */
|
---|
170 | function addWithoutDuplicates($statement) {
|
---|
171 |
|
---|
172 | if (!is_a($statement, 'Statement')) {
|
---|
173 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: addWithoutDuplicates): Statement expected.';
|
---|
174 | trigger_error($errmsg, E_USER_ERROR);
|
---|
175 | }
|
---|
176 |
|
---|
177 | if (!$this->contains($statement)) {
|
---|
178 | $this->add($statement);
|
---|
179 | return true;
|
---|
180 | }else{
|
---|
181 | return false;
|
---|
182 | }
|
---|
183 | }
|
---|
184 |
|
---|
185 | /**
|
---|
186 | * Removes the triple from the MemModel.
|
---|
187 | * TRUE if the triple is removed.
|
---|
188 | * FALSE otherwise.
|
---|
189 | *
|
---|
190 | * @param object Statement $statement
|
---|
191 | * @return boolean
|
---|
192 | * @access public
|
---|
193 | * @throws PhpError
|
---|
194 | */
|
---|
195 | function remove($statement) {
|
---|
196 |
|
---|
197 | if (!is_a($statement, 'Statement')) {
|
---|
198 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: remove): Statement expected.';
|
---|
199 | trigger_error($errmsg, E_USER_ERROR);
|
---|
200 | }
|
---|
201 | if($this->indexed==-1){
|
---|
202 | $pass=false;
|
---|
203 | foreach($this->triples as $key => $value) {
|
---|
204 | if ($this->matchStatement($value, $statement->subject(), $statement->predicate(), $statement->object())) {
|
---|
205 | unset($this->triples[$key]);
|
---|
206 | $pass= true;
|
---|
207 | }
|
---|
208 | }
|
---|
209 | return $pass;
|
---|
210 | }else{
|
---|
211 | $k= null;
|
---|
212 | if($this->indexed==0){
|
---|
213 | $pass=false;
|
---|
214 | $del=false;
|
---|
215 | while($del!=-1){
|
---|
216 | // index over S
|
---|
217 | $del=$this->_indexOpr($statement,$k,4,0);
|
---|
218 | // index over P
|
---|
219 | $this->_indexOpr($statement,$k,5,0);
|
---|
220 | // index over O
|
---|
221 | $this->_indexOpr($statement,$k,6,0);
|
---|
222 | if($del!=-1){
|
---|
223 | unset($this->triples[$del]);
|
---|
224 | $pass=true;
|
---|
225 | }
|
---|
226 | }
|
---|
227 | return $pass;
|
---|
228 | }else{
|
---|
229 | $pass=false;
|
---|
230 | $del=false;
|
---|
231 | while($del!=-1){
|
---|
232 | $del=$this->_indexOpr($statement,$k,$this->indexed,0);
|
---|
233 | if($del!=-1){
|
---|
234 | unset($this->triples[$del]);
|
---|
235 | $pass=true;
|
---|
236 | }
|
---|
237 | }
|
---|
238 | return $pass;
|
---|
239 | }
|
---|
240 | }
|
---|
241 | }
|
---|
242 |
|
---|
243 | /**
|
---|
244 | * Short Dump of the MemModel.
|
---|
245 | *
|
---|
246 | * @access public
|
---|
247 | * @return string
|
---|
248 | */
|
---|
249 | function toString() {
|
---|
250 | return 'MemModel[baseURI=' . $this->getBaseURI() . '; size=' . $this->size() . ']';
|
---|
251 | }
|
---|
252 |
|
---|
253 | /**
|
---|
254 | * Dumps of the MemModel including all triples.
|
---|
255 | *
|
---|
256 | * @access public
|
---|
257 | * @return string
|
---|
258 | */
|
---|
259 | function toStringIncludingTriples() {
|
---|
260 | $dump = $this->toString() . chr(13);
|
---|
261 | foreach($this->triples as $value) {
|
---|
262 | $dump .= $value->toString() . chr(13);
|
---|
263 | }
|
---|
264 | return $dump;
|
---|
265 | }
|
---|
266 |
|
---|
267 |
|
---|
268 |
|
---|
269 |
|
---|
270 | /**
|
---|
271 | * Writes the RDF serialization of the MemModel as HTML.
|
---|
272 | *
|
---|
273 | * @access public
|
---|
274 | */
|
---|
275 | function writeAsHtml() {
|
---|
276 | require_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
|
---|
277 | $ser = new RdfSerializer();
|
---|
278 | $rdf =& $ser->serialize($this);
|
---|
279 | $rdf = htmlspecialchars($rdf, ENT_QUOTES);
|
---|
280 | $rdf = str_replace(' ', ' ', $rdf);
|
---|
281 | $rdf = nl2br($rdf);
|
---|
282 | echo $rdf;
|
---|
283 | }
|
---|
284 |
|
---|
285 | /**
|
---|
286 | * Writes the RDF serialization of the MemModel as HTML table.
|
---|
287 | *
|
---|
288 | * @access public
|
---|
289 | */
|
---|
290 | function writeAsHtmlTable() {
|
---|
291 | // Import Package Utility
|
---|
292 | include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
|
---|
293 | $rdfUtil = new RDFUtil();
|
---|
294 | $rdfUtil->writeHTMLTable($this);
|
---|
295 | }
|
---|
296 |
|
---|
297 |
|
---|
298 | /**
|
---|
299 | * Writes the RDF serialization of the MemModel as HTML table.
|
---|
300 | *
|
---|
301 | * @access public
|
---|
302 | * @return string
|
---|
303 | */
|
---|
304 | function writeRdfToString() {
|
---|
305 | // Import Package Syntax
|
---|
306 | include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
|
---|
307 | $ser = new RdfSerializer();
|
---|
308 | $rdf =& $ser->serialize($this);
|
---|
309 | return $rdf;
|
---|
310 | }
|
---|
311 |
|
---|
312 |
|
---|
313 | /**
|
---|
314 | * Saves the RDF,N3 or N-Triple serialization of the MemModel to a file.
|
---|
315 | * You can decide to which format the model should be serialized by using a
|
---|
316 | * corresponding suffix-string as $type parameter. If no $type parameter
|
---|
317 | * is placed this method will serialize the model to XML/RDF format.
|
---|
318 | * Returns FALSE if the MemModel couldn't be saved to the file.
|
---|
319 | *
|
---|
320 | * @access public
|
---|
321 | * @param string $filename
|
---|
322 | * @param string $type
|
---|
323 | * @throws PhpError
|
---|
324 | * @return boolean
|
---|
325 | */
|
---|
326 | function saveAs($filename, $type ='rdf') {
|
---|
327 |
|
---|
328 |
|
---|
329 | // get suffix and create a corresponding serializer
|
---|
330 | if ($type=='rdf') {
|
---|
331 | // Import Package Syntax
|
---|
332 | include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_RDF);
|
---|
333 | $ser=new RdfSerializer();
|
---|
334 | }elseif ($type=='nt') {
|
---|
335 | // Import Package Syntax
|
---|
336 | include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
|
---|
337 | $ser=new NTripleSerializer();
|
---|
338 | }elseif ($type=='n3') {
|
---|
339 | // Import Package Syntax
|
---|
340 | include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3);
|
---|
341 | $ser=new N3Serializer();
|
---|
342 | }else {
|
---|
343 | print ('Serializer type not properly defined. Use the strings "rdf","n3" or "nt".');
|
---|
344 | return false;
|
---|
345 | };
|
---|
346 |
|
---|
347 | return $ser->saveAs($this, $filename);
|
---|
348 | }
|
---|
349 |
|
---|
350 |
|
---|
351 | /**
|
---|
352 | * Tests if the MemModel contains the given triple.
|
---|
353 | * TRUE if the triple belongs to the MemModel;
|
---|
354 | * FALSE otherwise.
|
---|
355 | *
|
---|
356 | * @param object Statement &$statement
|
---|
357 | * @return boolean
|
---|
358 | * @access public
|
---|
359 | */
|
---|
360 | function contains(&$statement) {
|
---|
361 |
|
---|
362 | // no index ->linear contains
|
---|
363 | if ($this->indexed==-1){
|
---|
364 | foreach($this->triples as $value) {
|
---|
365 | if ($value->equals($statement)){
|
---|
366 | return TRUE; }
|
---|
367 | }
|
---|
368 | return false;
|
---|
369 | }
|
---|
370 | if ($this->indexed==0){
|
---|
371 | $res = $this->_containsIndex($statement,4);
|
---|
372 | return $res;
|
---|
373 | }else{
|
---|
374 | return $this->_containsIndex($statement,$this->indexed);
|
---|
375 | }
|
---|
376 | }
|
---|
377 |
|
---|
378 |
|
---|
379 | /**
|
---|
380 | * Determine if all of the statements in a model are also contained in this MemModel.
|
---|
381 | * True if all of the statements in $model are also contained in this MemModel and false otherwise.
|
---|
382 | *
|
---|
383 | * @param object Model &$model
|
---|
384 | * @return boolean
|
---|
385 | * @access public
|
---|
386 | */
|
---|
387 | function containsAll(&$model) {
|
---|
388 |
|
---|
389 | if (is_a($model, 'MemModel')) {
|
---|
390 |
|
---|
391 | foreach($model->triples as $statement)
|
---|
392 | if(!$this->contains($statement))
|
---|
393 | return FALSE;
|
---|
394 | return TRUE;
|
---|
395 |
|
---|
396 | }elseif (is_a($model, 'DbModel'))
|
---|
397 |
|
---|
398 | return $model->containsAll($this);
|
---|
399 |
|
---|
400 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: containsAll): Model expected.';
|
---|
401 | trigger_error($errmsg, E_USER_ERROR);
|
---|
402 | }
|
---|
403 |
|
---|
404 | /**
|
---|
405 | * Determine if any of the statements in a model are also contained in this MemModel.
|
---|
406 | * True if any of the statements in $model are also contained in this MemModel and false otherwise.
|
---|
407 | *
|
---|
408 | * @param object Model &$model
|
---|
409 | * @return boolean
|
---|
410 | * @access public
|
---|
411 | */
|
---|
412 | function containsAny(&$model) {
|
---|
413 |
|
---|
414 | if (is_a($model, 'MemModel')) {
|
---|
415 |
|
---|
416 | foreach($model->triples as $modelStatement)
|
---|
417 | if($this->contains($modelStatement))
|
---|
418 | return TRUE;
|
---|
419 | return FALSE;
|
---|
420 |
|
---|
421 | }elseif (is_a($model, 'DbModel'))
|
---|
422 |
|
---|
423 | return $model->containsAny($this);
|
---|
424 |
|
---|
425 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: containsAll): Model expected.';
|
---|
426 | trigger_error($errmsg, E_USER_ERROR);
|
---|
427 | }
|
---|
428 |
|
---|
429 |
|
---|
430 | /**
|
---|
431 | * Builds a search index for the statements in the MemModel.
|
---|
432 | * The index is used by the find(),contains(),add() and remove() functions.
|
---|
433 | * Performance example using a model with 43000 statements on a Linux machine:
|
---|
434 | * Find without index takes 1.7 seconds.
|
---|
435 | * Indexing takes 1.8 seconds.
|
---|
436 | * Find with index takes 0.001 seconds.
|
---|
437 | * So if you want to query a model more then once, build a index first.
|
---|
438 | * The defaultindex is indices over subject, predicate, object seperate.
|
---|
439 | *
|
---|
440 | * mode = 0 : indices over subject,predicate,object (default)
|
---|
441 | * mode = 1 : index over subject+predicate+object
|
---|
442 | * mode = 2 : index over subject+predicate
|
---|
443 | * mode = 3 : index over subject+object
|
---|
444 | *
|
---|
445 | * @param int $mode
|
---|
446 | * @access public
|
---|
447 | */
|
---|
448 | function index($mode) {
|
---|
449 |
|
---|
450 | unset($this->indexArr);
|
---|
451 | $this->indexArr=array();
|
---|
452 | switch($mode){
|
---|
453 | // unset indices
|
---|
454 | case -1:
|
---|
455 | $this->indexed=-1;
|
---|
456 | unset($this->indexArr);
|
---|
457 | break;
|
---|
458 | // index over SPO
|
---|
459 | case 0:
|
---|
460 | $this->indexed=0;
|
---|
461 | foreach($this->triples as $k => $t) {
|
---|
462 | // index over S
|
---|
463 | $this->_indexOpr($t,$k,4,1);
|
---|
464 | // index over P
|
---|
465 | $this->_indexOpr($t,$k,5,1);
|
---|
466 | // index over O
|
---|
467 | $this->_indexOpr($t,$k,6,1);
|
---|
468 | }
|
---|
469 | break;
|
---|
470 | default:
|
---|
471 | $this->indexed=$mode;
|
---|
472 | foreach($this->triples as $k => $t) {
|
---|
473 | $this->_indexOpr($t,$k,$this->indexed,1);
|
---|
474 | }
|
---|
475 | break;
|
---|
476 | }
|
---|
477 | }
|
---|
478 |
|
---|
479 |
|
---|
480 | /**
|
---|
481 | * Returns true if there is an index, false if not.
|
---|
482 | *
|
---|
483 | * @return boolean
|
---|
484 | * @access public
|
---|
485 | */
|
---|
486 | function isIndexed() {
|
---|
487 | if($this->indexed!=-1){
|
---|
488 | return TRUE;
|
---|
489 | }else{
|
---|
490 | return FALSE;
|
---|
491 | }
|
---|
492 | }
|
---|
493 |
|
---|
494 | /**
|
---|
495 | * Returns the indextype:
|
---|
496 | * -1 if there is no index, 0 if there are indices over S,P,O(separate),
|
---|
497 | * 1 if there is an index over SPO, 2 if there is an index over SP and 3 if
|
---|
498 | * there is an index over SO.
|
---|
499 | *
|
---|
500 | * @return int
|
---|
501 | * @access public
|
---|
502 | *
|
---|
503 | */
|
---|
504 | function getIndexType(){
|
---|
505 | return $this->indexed;
|
---|
506 | }
|
---|
507 |
|
---|
508 | /**
|
---|
509 | * General method to search for triples.
|
---|
510 | * NULL input for any parameter will match anything.
|
---|
511 | * Example: $result = $m->find( NULL, NULL, $node );
|
---|
512 | * Finds all triples with $node as object.
|
---|
513 | * Returns an empty MemModel if nothing is found.
|
---|
514 | *
|
---|
515 | * @param object Node $subject
|
---|
516 | * @param object Node $predicate
|
---|
517 | * @param object Node $object
|
---|
518 | * @return object MemModel
|
---|
519 | * @access public
|
---|
520 | * @throws PhpError
|
---|
521 | */
|
---|
522 |
|
---|
523 | function find($subject,$predicate,$object) {
|
---|
524 |
|
---|
525 | if (
|
---|
526 | (!is_a($subject, 'Resource') && $subject != NULL) ||
|
---|
527 | (!is_a($predicate, 'Resource') && $predicate != NULL) ||
|
---|
528 | (!is_a($object, 'Node') && $object != NULL)
|
---|
529 | ) {
|
---|
530 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: find): Parameters must be subclasses of Node or NULL';
|
---|
531 | trigger_error($errmsg, E_USER_ERROR);
|
---|
532 | }
|
---|
533 |
|
---|
534 | $res = new MemModel($this->getBaseURI());
|
---|
535 | $res->indexed=-1;
|
---|
536 |
|
---|
537 | if($this->isEmpty())
|
---|
538 | return $res;
|
---|
539 |
|
---|
540 | if($subject == NULL && $predicate == NULL && $object == NULL)
|
---|
541 | return $this;
|
---|
542 |
|
---|
543 | switch($this->indexed){
|
---|
544 | case 1:
|
---|
545 | if($subject!=NULL && $predicate != NULL && $object != NULL){
|
---|
546 | $pos=$subject->getLabel().$predicate->getLabel().$object->getLabel();
|
---|
547 | return $this->_findInIndex($pos,$subject,$predicate,$object,1);
|
---|
548 | }else{
|
---|
549 | break;
|
---|
550 | }
|
---|
551 |
|
---|
552 | case 2:
|
---|
553 | if($subject!=NULL && $predicate != NULL){
|
---|
554 | $pos=$subject->getLabel().$predicate->getLabel();
|
---|
555 | return $this->_findInIndex($pos,$subject,$predicate,$object,2);
|
---|
556 | }else{
|
---|
557 | break;
|
---|
558 | }
|
---|
559 |
|
---|
560 | case 3:
|
---|
561 | if($subject!=NULL && $object != NULL){
|
---|
562 | $pos=$subject->getLabel().$object->getLabel();
|
---|
563 | return $this->_findInIndex($pos,$subject,$predicate,$object,3);
|
---|
564 | }else{
|
---|
565 | break;
|
---|
566 | }
|
---|
567 | case 0:
|
---|
568 | if($subject!= null){
|
---|
569 | $pos=$subject->getLabel();
|
---|
570 | return $this->_findInIndex($pos,$subject,$predicate,$object,4);
|
---|
571 | }
|
---|
572 | if($predicate!= null){
|
---|
573 | $pos=$predicate->getLabel();
|
---|
574 | return $this->_findInIndex($pos,$subject,$predicate,$object,5);
|
---|
575 | }
|
---|
576 | if($object!= null){
|
---|
577 | $pos=$object->getLabel();
|
---|
578 | return $this->_findInIndex($pos,$subject,$predicate,$object,6);
|
---|
579 | }
|
---|
580 | }
|
---|
581 | // if no index: linear search
|
---|
582 | foreach($this->triples as $value) {
|
---|
583 | if ($this->matchStatement($value, $subject, $predicate, $object))
|
---|
584 | $res->add($value);
|
---|
585 | }
|
---|
586 | return $res;
|
---|
587 |
|
---|
588 | }
|
---|
589 |
|
---|
590 |
|
---|
591 |
|
---|
592 |
|
---|
593 |
|
---|
594 | /**
|
---|
595 | * Method to search for triples using Perl-style regular expressions.
|
---|
596 | * NULL input for any parameter will match anything.
|
---|
597 | * Example: $result = $m->find_regex( NULL, NULL, $regex );
|
---|
598 | * Finds all triples where the label of the object node matches the regular expression.
|
---|
599 | * Returns an empty MemModel if nothing is found.
|
---|
600 | *
|
---|
601 | * @param string $subject_regex
|
---|
602 | * @param string $predicate_regex
|
---|
603 | * @param string $object_regex
|
---|
604 | * @return object MemModel
|
---|
605 | * @access public
|
---|
606 | */
|
---|
607 | function findRegex($subject_regex, $predicate_regex, $object_regex) {
|
---|
608 |
|
---|
609 | $res = new MemModel($this->getBaseURI());
|
---|
610 |
|
---|
611 | if($this->size() == 0)
|
---|
612 | return $res;
|
---|
613 |
|
---|
614 | if($subject_regex == NULL && $predicate_regex == NULL && $object_regex == NULL)
|
---|
615 | return $this;
|
---|
616 |
|
---|
617 | foreach($this->triples as $value) {
|
---|
618 | if (
|
---|
619 | ($subject_regex == NULL || preg_match($subject_regex, $value->subj->getLabel())) &&
|
---|
620 | ($predicate_regex == NULL || preg_match($predicate_regex, $value->pred->getLabel())) &&
|
---|
621 | ($object_regex == NULL || preg_match($object_regex, $value->obj->getLabel()))
|
---|
622 | ) $res->add($value);
|
---|
623 | }
|
---|
624 |
|
---|
625 | return $res;
|
---|
626 |
|
---|
627 | }
|
---|
628 |
|
---|
629 | /**
|
---|
630 | * Returns all tripels of a certain vocabulary.
|
---|
631 | * $vocabulary is the namespace of the vocabulary inluding a # : / char at the end.
|
---|
632 | * e.g. http://www.w3.org/2000/01/rdf-schema#
|
---|
633 | * Returns an empty MemModel if nothing is found.
|
---|
634 | *
|
---|
635 | * @param string $vocabulary
|
---|
636 | * @return object MemModel
|
---|
637 | * @access public
|
---|
638 | */
|
---|
639 | function findVocabulary($vocabulary) {
|
---|
640 |
|
---|
641 | if($this->size() == 0)
|
---|
642 | return new MemModel();
|
---|
643 | if($vocabulary == NULL || $vocabulary == '')
|
---|
644 | return $this;
|
---|
645 |
|
---|
646 | $res = new MemModel($this->getBaseURI());
|
---|
647 | if($this->indexed==0){
|
---|
648 | foreach($this->indexArr[5] as $key => $value){
|
---|
649 | $pos=strpos($key,'#')+1;
|
---|
650 | if(substr($key,0,$pos)==$vocabulary){
|
---|
651 | for($i=1;$i<=$value[0];$i++){
|
---|
652 | $res->add($this->triples[$value[$i]]);
|
---|
653 | }
|
---|
654 | }
|
---|
655 | }
|
---|
656 | return $res;
|
---|
657 | }else{
|
---|
658 | // Import Package Utility
|
---|
659 | include_once(RDFAPI_INCLUDE_DIR.PACKAGE_UTILITY);
|
---|
660 | foreach($this->triples as $value) {
|
---|
661 | if (RDFUtil::getNamespace($value->getPredicate()) == $vocabulary)
|
---|
662 | $res->add($value);
|
---|
663 | }
|
---|
664 | return $res;
|
---|
665 | }
|
---|
666 | }
|
---|
667 |
|
---|
668 | /**
|
---|
669 | * Searches for triples and returns the first matching statement.
|
---|
670 | * NULL input for any parameter will match anything.
|
---|
671 | * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node );
|
---|
672 | * Returns the first statement of the MemModel where the object equals $node.
|
---|
673 | * Returns an NULL if nothing is found.
|
---|
674 | * You can define an offset to search for. Default = 0
|
---|
675 | *
|
---|
676 | * @param object Node $subject
|
---|
677 | * @param object Node $predicate
|
---|
678 | * @param object Node $object
|
---|
679 | * @param integer $offset
|
---|
680 | * @return object Statement
|
---|
681 | * @access public
|
---|
682 | */
|
---|
683 | function findFirstMatchingStatement($subject, $predicate, $object, $offset = 0) {
|
---|
684 |
|
---|
685 | $currentOffset = 0;
|
---|
686 | for($i=0;$i<=$offset;$i++)
|
---|
687 | {
|
---|
688 | $res = $this->findFirstMatchOff($subject, $predicate, $object, $currentOffset);
|
---|
689 | $currentOffset=$res+1;
|
---|
690 | }
|
---|
691 | if ($res != -1) {
|
---|
692 | return $this->triples[$res];
|
---|
693 | } else {
|
---|
694 | return NULL;
|
---|
695 | }
|
---|
696 | }
|
---|
697 |
|
---|
698 |
|
---|
699 |
|
---|
700 |
|
---|
701 | /**
|
---|
702 | * Searches for triples and returns the first matching statement from a given offset.
|
---|
703 | * This method is used by the util/findIterator. NULL input for any parameter will match anything.
|
---|
704 | * Example: $result = $m->findFirstMatchingStatement( NULL, NULL, $node, $off );
|
---|
705 | * Returns the position of the first statement of the MemModel where the object equals $node from the given
|
---|
706 | * offset.
|
---|
707 | * Returns an -1 if nothing is found.
|
---|
708 | *
|
---|
709 | * @param object Node $subject
|
---|
710 | * @param object Node $predicate
|
---|
711 | * @param object Node $object
|
---|
712 | * @param int $off
|
---|
713 | * @return int
|
---|
714 | * @access private
|
---|
715 | */
|
---|
716 | function findFirstMatchOff($subject,$predicate, $object,$off) {
|
---|
717 |
|
---|
718 | if (
|
---|
719 | (!is_a($subject, 'Resource') && $subject != NULL) ||
|
---|
720 | (!is_a($predicate, 'Resource') && $predicate != NULL) ||
|
---|
721 | (!is_a($object, 'Node') && $object != NULL)
|
---|
722 | ) {
|
---|
723 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: find): Parameters must be subclasses of Node or NULL';
|
---|
724 | trigger_error($errmsg, E_USER_ERROR);
|
---|
725 | }
|
---|
726 |
|
---|
727 | $match=-1;
|
---|
728 | $ind=$this->indexed;
|
---|
729 | if($subject == NULL && $predicate == NULL && $object == NULL)
|
---|
730 | {
|
---|
731 | foreach ($this->triples as $key => $statement)
|
---|
732 | {
|
---|
733 | if ($key >= $off)
|
---|
734 | return $key;
|
---|
735 | }
|
---|
736 | return -1;
|
---|
737 | }
|
---|
738 |
|
---|
739 | switch($ind){
|
---|
740 | case 1:
|
---|
741 | if($subject!=NULL && $predicate != NULL && $object != NULL){
|
---|
742 | $pos=$subject->getLabel().$predicate->getLabel().$object->getLabel();
|
---|
743 | return $this->_findMatchIndex($pos,$subject,$predicate,$object,1,$off);
|
---|
744 | }else{
|
---|
745 | break;
|
---|
746 | }
|
---|
747 |
|
---|
748 | case 2:
|
---|
749 | if($subject!=NULL && $predicate != NULL){
|
---|
750 | $pos=$subject->getLabel().$predicate->getLabel();
|
---|
751 | return $this->_findMatchIndex($pos,$subject,$predicate,$object,2,$off);
|
---|
752 | }else{
|
---|
753 | break;
|
---|
754 | }
|
---|
755 |
|
---|
756 | case 3:
|
---|
757 | if($subject!=NULL && $object != NULL){
|
---|
758 | $pos=$subject->getLabel().$object->getLabel();
|
---|
759 | return $this->_findMatchIndex($pos,$subject,$predicate,$object,3,$off);
|
---|
760 | }else{
|
---|
761 | break;
|
---|
762 | }
|
---|
763 | case 0:
|
---|
764 | if($subject!= null){
|
---|
765 | $pos=$subject->getLabel();
|
---|
766 | return $this->_findMatchIndex($pos,$subject,$predicate,$object,4,$off);
|
---|
767 | }
|
---|
768 | if($predicate!= null){
|
---|
769 | $pos=$predicate->getLabel();
|
---|
770 | return $this->_findMatchIndex($pos,$subject,$predicate,$object,5,$off);
|
---|
771 | }
|
---|
772 | if($object!= null){
|
---|
773 | $pos=$object->getLabel();
|
---|
774 | return $this->_findMatchIndex($pos,$subject,$predicate,$object,6,$off);
|
---|
775 | }
|
---|
776 | break;
|
---|
777 | }
|
---|
778 | // if no index: linear search
|
---|
779 | foreach($this->triples as $key => $value){
|
---|
780 | if ($this->matchStatement($value, $subject, $predicate, $object)){
|
---|
781 | if($off<=$key){
|
---|
782 | $match=$key;
|
---|
783 | break;
|
---|
784 | }
|
---|
785 | }
|
---|
786 | }
|
---|
787 | return $match;
|
---|
788 | }
|
---|
789 |
|
---|
790 |
|
---|
791 | /**
|
---|
792 | * Searches for triples and returns the number of matches.
|
---|
793 | * NULL input for any parameter will match anything.
|
---|
794 | * Example: $result = $m->findCount( NULL, NULL, $node );
|
---|
795 | * Finds all triples with $node as object.
|
---|
796 | *
|
---|
797 | * @param object Node $subject
|
---|
798 | * @param object Node $predicate
|
---|
799 | * @param object Node $object
|
---|
800 | * @return integer
|
---|
801 | * @access public
|
---|
802 | */
|
---|
803 | function findCount($subject, $predicate, $object) {
|
---|
804 |
|
---|
805 | $res = $this->find($subject, $predicate, $object);
|
---|
806 | return $res->size();
|
---|
807 |
|
---|
808 | }
|
---|
809 |
|
---|
810 |
|
---|
811 | /**
|
---|
812 | * Perform an RDQL query on this MemModel.
|
---|
813 | * This method returns an associative array of variable bindings.
|
---|
814 | * The values of the query variables can either be RAP's objects (instances of Node)
|
---|
815 | * if $returnNodes set to TRUE, or their string serialization.
|
---|
816 | *
|
---|
817 | * @access public
|
---|
818 | * @param string $queryString
|
---|
819 | * @param boolean $returnNodes
|
---|
820 | * @return array [][?VARNAME] = object Node (if $returnNodes = TRUE)
|
---|
821 | * OR array [][?VARNAME] = string
|
---|
822 | *
|
---|
823 | */
|
---|
824 | function rdqlQuery($queryString, $returnNodes = TRUE) {
|
---|
825 |
|
---|
826 | // Import RDQL Package
|
---|
827 | include_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
|
---|
828 |
|
---|
829 | $parser = new RdqlParser();
|
---|
830 | $parsedQuery =& $parser->parseQuery($queryString);
|
---|
831 |
|
---|
832 | // this method can only query this MemModel
|
---|
833 | // if another model was specified in the from clause throw an error
|
---|
834 | if (isset($parsedQuery['sources'][1])) {
|
---|
835 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: rdqlQuery):';
|
---|
836 | $errmsg .= ' this method can only query this MemModel';
|
---|
837 | trigger_error($errmsg, E_USER_ERROR);
|
---|
838 | }
|
---|
839 |
|
---|
840 | $engine = new RdqlMemEngine();
|
---|
841 | $res =& $engine->queryModel($this, $parsedQuery, $returnNodes);
|
---|
842 |
|
---|
843 | return $res;
|
---|
844 | }
|
---|
845 |
|
---|
846 | /**
|
---|
847 | * Perform an RDQL query on this MemModel.
|
---|
848 | * This method returns an RdqlResultIterator of variable bindings.
|
---|
849 | * The values of the query variables can either be RAP's objects (instances of Node)
|
---|
850 | * if $returnNodes set to TRUE, or their string serialization.
|
---|
851 | *
|
---|
852 | * @access public
|
---|
853 | * @param string $queryString
|
---|
854 | * @param boolean $returnNodes
|
---|
855 | * @return object RdqlResultIterator = with values as object Node (if $returnNodes = TRUE)
|
---|
856 | * OR object RdqlResultIterator = with values as strings if (if $returnNodes = FALSE)
|
---|
857 | *
|
---|
858 | */
|
---|
859 | function rdqlQueryAsIterator($queryString, $returnNodes = TRUE) {
|
---|
860 | // Import RDQL Package
|
---|
861 | include_once(RDFAPI_INCLUDE_DIR.PACKAGE_RDQL);
|
---|
862 | return new RdqlResultIterator($this->rdqlQuery($queryString, $returnNodes));
|
---|
863 | }
|
---|
864 |
|
---|
865 | /**
|
---|
866 | * General method to replace nodes of a MemModel.
|
---|
867 | * NULL input for any parameter will match nothing.
|
---|
868 | * Example: $m->replace($node, NULL, $node, $replacement);
|
---|
869 | * Replaces all $node objects beeing subject or object in
|
---|
870 | * any triple of the MemModel with the $needle node.
|
---|
871 | *
|
---|
872 | * @param object Node $subject
|
---|
873 | * @param object Node $predicate
|
---|
874 | * @param object Node $object
|
---|
875 | * @param object Node $replacement
|
---|
876 | * @access public
|
---|
877 | * @throws PhpError
|
---|
878 | */
|
---|
879 | function replace($subject, $predicate, $object, $replacement) {
|
---|
880 |
|
---|
881 | if (
|
---|
882 | (!is_a($replacement, 'Node')) ||
|
---|
883 | (!is_a($subject, 'Resource') && $subject != NULL) ||
|
---|
884 | (!is_a($predicate, 'Resource') && $predicate != NULL) ||
|
---|
885 | (!is_a($object, 'Node') && $object != NULL)
|
---|
886 | ) {
|
---|
887 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: replace): Parameters must be subclasses of Node or NULL';
|
---|
888 | trigger_error($errmsg, E_USER_ERROR);
|
---|
889 | }
|
---|
890 |
|
---|
891 | if($this->size() == 0)
|
---|
892 | break;
|
---|
893 | foreach($this->triples as $key => $value) {
|
---|
894 | if ($this->triples[$key]->subj->equals($subject)) {
|
---|
895 | $this->triples[$key]->subj = $replacement;
|
---|
896 | }
|
---|
897 | if ($this->triples[$key]->pred->equals($predicate))
|
---|
898 | $this->triples[$key]->pred = $replacement;
|
---|
899 | if ($this->triples[$key]->obj->equals($object))
|
---|
900 | $this->triples[$key]->obj = $replacement;
|
---|
901 |
|
---|
902 | }
|
---|
903 | $this->index($this->indexed);
|
---|
904 | }
|
---|
905 |
|
---|
906 |
|
---|
907 | /**
|
---|
908 | * Internal method that checks, if a statement matches a S, P, O or NULL combination.
|
---|
909 | * NULL input for any parameter will match anything.
|
---|
910 | *
|
---|
911 | * @param object Statement $statement
|
---|
912 | * @param object Node $subject
|
---|
913 | * @param object Node $predicate
|
---|
914 | * @param object Node $object
|
---|
915 | * @return boolean
|
---|
916 | * @access private
|
---|
917 | */
|
---|
918 | function matchStatement($statement, $subject, $predicate, $object) {
|
---|
919 |
|
---|
920 | if(($subject != NULL) AND !($statement->subj->equals($subject)))
|
---|
921 | return false;
|
---|
922 |
|
---|
923 | if($predicate != NULL && !($statement->pred->equals($predicate)))
|
---|
924 | return false;
|
---|
925 |
|
---|
926 | if($object != NULL && !($statement->obj->equals($object)))
|
---|
927 | return false;
|
---|
928 |
|
---|
929 | return true;
|
---|
930 | }
|
---|
931 |
|
---|
932 |
|
---|
933 |
|
---|
934 |
|
---|
935 | /**
|
---|
936 | * Checks if two models are equal.
|
---|
937 | * Two models are equal if and only if the two RDF graphs they represent are isomorphic.
|
---|
938 | *
|
---|
939 | * @access public
|
---|
940 | * @param object model &$that
|
---|
941 | * @throws phpErrpr
|
---|
942 | * @return boolean
|
---|
943 | */
|
---|
944 |
|
---|
945 | function equals(&$that) {
|
---|
946 |
|
---|
947 | if (!is_a($that, 'Model')) {
|
---|
948 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: equals): Model expected.';
|
---|
949 | trigger_error($errmsg, E_USER_ERROR);
|
---|
950 | }
|
---|
951 |
|
---|
952 | if ($this->size() != $that->size())
|
---|
953 | return FALSE;
|
---|
954 | /*
|
---|
955 | if (!$this->containsAll($that))
|
---|
956 | return FALSE;
|
---|
957 | return TRUE;
|
---|
958 | */
|
---|
959 | include_once(RDFAPI_INCLUDE_DIR. "util/ModelComparator.php");
|
---|
960 | return ModelComparator::compare($this,$that);
|
---|
961 | }
|
---|
962 |
|
---|
963 | /**
|
---|
964 | * Returns a new MemModel that is the set-union of the MemModel with another model.
|
---|
965 | * Duplicate statements are removed. If you want to allow duplicates, use addModel() which is much faster.
|
---|
966 | *
|
---|
967 | * The result of taking the set-union of two or more RDF graphs (i.e. sets of triples)
|
---|
968 | * is another graph, which we will call the merge of the graphs.
|
---|
969 | * Each of the original graphs is a subgraph of the merged graph. Notice that when forming
|
---|
970 | * a merged graph, two occurrences of a given uriref or literal as nodes in two different
|
---|
971 | * graphs become a single node in the union graph (since by definition they are the same
|
---|
972 | * uriref or literal) but blank nodes are not 'merged' in this way; and arcs are of course
|
---|
973 | * never merged. In particular, this means that every blank node in a merged graph can be
|
---|
974 | * identified as coming from one particular graph in the original set of graphs.
|
---|
975 | *
|
---|
976 | * Notice that one does not, in general, obtain the merge of a set of graphs by concatenating
|
---|
977 | * their corresponding N-triples documents and constructing the graph described by the merged
|
---|
978 | * document, since if some of the documents use the same node identifiers, the merged document
|
---|
979 | * will describe a graph in which some of the blank nodes have been 'accidentally' merged.
|
---|
980 | * To merge Ntriples documents it is necessary to check if the same nodeID is used in two or
|
---|
981 | * more documents, and to replace it with a distinct nodeID in each of them, before merging the
|
---|
982 | * documents. (Not implemented yet !!!!!!!!!!!)
|
---|
983 | *
|
---|
984 | * @param object Model $model
|
---|
985 | * @return object MemModel
|
---|
986 | * @access public
|
---|
987 | * @throws phpErrpr
|
---|
988 | *
|
---|
989 | */
|
---|
990 | function & unite(&$model) {
|
---|
991 |
|
---|
992 | if (!is_a($model, 'Model')) {
|
---|
993 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: unite): Model expected.';
|
---|
994 | trigger_error($errmsg, E_USER_ERROR);
|
---|
995 | }
|
---|
996 |
|
---|
997 | $res = $this;
|
---|
998 |
|
---|
999 | if (is_a($model, 'MemModel')) {
|
---|
1000 | require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
|
---|
1001 | $stateIt=new StatementIterator($model);
|
---|
1002 | while($statement=$stateIt->next())
|
---|
1003 | {
|
---|
1004 | $res->addWithoutDuplicates($statement);
|
---|
1005 | }
|
---|
1006 | }
|
---|
1007 |
|
---|
1008 | elseif (is_a($model, 'DbModel')) {
|
---|
1009 | $memModel =& $model->getMemModel();
|
---|
1010 | foreach($memModel->triples as $value)
|
---|
1011 | $res->addWithoutDuplicates($value);
|
---|
1012 | }
|
---|
1013 |
|
---|
1014 | return $res;
|
---|
1015 | }
|
---|
1016 |
|
---|
1017 | /**
|
---|
1018 | * Returns a new MemModel that is the subtraction of another model from this MemModel.
|
---|
1019 | *
|
---|
1020 | * @param object Model $model
|
---|
1021 | * @return object MemModel
|
---|
1022 | * @access public
|
---|
1023 | * @throws phpErrpr
|
---|
1024 | */
|
---|
1025 |
|
---|
1026 | function & subtract(&$model) {
|
---|
1027 |
|
---|
1028 | if (!is_a($model, 'Model')) {
|
---|
1029 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: subtract): Model expected.';
|
---|
1030 | trigger_error($errmsg, E_USER_ERROR);
|
---|
1031 | }
|
---|
1032 |
|
---|
1033 | $res = $this;
|
---|
1034 |
|
---|
1035 |
|
---|
1036 | if (is_a($model, 'MemModel'))
|
---|
1037 | {
|
---|
1038 | require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
|
---|
1039 | $stateIt=new StatementIterator($model);
|
---|
1040 | while($statement=$stateIt->next())
|
---|
1041 | {
|
---|
1042 | $res->remove($statement);
|
---|
1043 | }
|
---|
1044 | }
|
---|
1045 | elseif (is_a($model, 'DbModel'))
|
---|
1046 | {
|
---|
1047 | $memModel =& $model->getMemModel();
|
---|
1048 | foreach($memModel->triples as $value)
|
---|
1049 | $res->remove($value);
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 |
|
---|
1053 | return $res;
|
---|
1054 | }
|
---|
1055 |
|
---|
1056 | /**
|
---|
1057 | * Returns a new MemModel containing all the statements which are in both this MemModel and another.
|
---|
1058 | *
|
---|
1059 | * @param object Model $model
|
---|
1060 | * @return object MemModel
|
---|
1061 | * @access public
|
---|
1062 | * @throws phpErrpr
|
---|
1063 | */
|
---|
1064 | function & intersect(&$model) {
|
---|
1065 |
|
---|
1066 | if (!is_a($model, 'Model')) {
|
---|
1067 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: intersect: Model expected.';
|
---|
1068 | trigger_error($errmsg, E_USER_ERROR);
|
---|
1069 | }
|
---|
1070 |
|
---|
1071 | $res = new MemModel($this->getBaseURI());
|
---|
1072 |
|
---|
1073 | if (is_a($model, 'DbModel') || is_a($model, 'RDFSBModel'))
|
---|
1074 | {
|
---|
1075 | $memModel =& $model->getMemModel();
|
---|
1076 | foreach($memModel->triples as $value) {
|
---|
1077 | if ($this->contains($value))
|
---|
1078 | $res->add($value);
|
---|
1079 | }
|
---|
1080 | }
|
---|
1081 |
|
---|
1082 | elseif (is_a($model, 'MemModel'))
|
---|
1083 | {
|
---|
1084 | foreach($model->triples as $value) {
|
---|
1085 | if ($this->contains($value))
|
---|
1086 | $res->add($value);
|
---|
1087 | }
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 |
|
---|
1091 |
|
---|
1092 | return $res;
|
---|
1093 | }
|
---|
1094 |
|
---|
1095 |
|
---|
1096 | /**
|
---|
1097 | * Adds another model to this MemModel.
|
---|
1098 | * Duplicate statements are not removed.
|
---|
1099 | * If you don't want duplicates, use unite().
|
---|
1100 | * If any statement of the model to be added to this model contains a blankNode
|
---|
1101 | * with an identifier already existing in this model, a new blankNode is generated.
|
---|
1102 | *
|
---|
1103 | * @param object Model $model
|
---|
1104 | * @access public
|
---|
1105 | * @throws phpErrpr
|
---|
1106 | *
|
---|
1107 | */
|
---|
1108 | function addModel(&$model) {
|
---|
1109 |
|
---|
1110 | if (!is_a($model, 'Model')) {
|
---|
1111 | $errmsg = RDFAPI_ERROR . '(class: MemModel; method: addModel): Model expected.';
|
---|
1112 | trigger_error($errmsg, E_USER_ERROR);
|
---|
1113 | }
|
---|
1114 |
|
---|
1115 | $blankNodes_tmp = array();
|
---|
1116 |
|
---|
1117 | if (is_a($model, 'MemModel')) {
|
---|
1118 | require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
|
---|
1119 | $stateIt=new StatementIterator($model);
|
---|
1120 | while($statement=$stateIt->next())
|
---|
1121 | {
|
---|
1122 | $this->_addStatementFromAnotherModel($statement, $blankNodes_tmp);
|
---|
1123 | };
|
---|
1124 | $this->addParsedNamespaces($model->getParsedNamespaces());
|
---|
1125 | }
|
---|
1126 |
|
---|
1127 | elseif (is_a($model, 'DbModel')) {
|
---|
1128 | $memModel =& $model->getMemModel();
|
---|
1129 | foreach($memModel->triples as $value)
|
---|
1130 | $this->_addStatementFromAnotherModel($value, $blankNodes_tmp);
|
---|
1131 | }
|
---|
1132 | $this->index($this->indexed);
|
---|
1133 | }
|
---|
1134 |
|
---|
1135 |
|
---|
1136 | /**
|
---|
1137 | * Reifies the MemModel.
|
---|
1138 | * Returns a new MemModel that contains the reifications of all statements of this MemModel.
|
---|
1139 | *
|
---|
1140 | * @access public
|
---|
1141 | * @return object MemModel
|
---|
1142 | */
|
---|
1143 | function & reify() {
|
---|
1144 | $res = new MemModel($this->getBaseURI());
|
---|
1145 |
|
---|
1146 | $stateIt=$this->getStatementIterator();
|
---|
1147 | while($statement=$stateIt->next())
|
---|
1148 | {
|
---|
1149 | $pointer =& $statement->reify($res);
|
---|
1150 | $res->addModel($pointer);
|
---|
1151 | };
|
---|
1152 |
|
---|
1153 | return $res;
|
---|
1154 | }
|
---|
1155 |
|
---|
1156 | /**
|
---|
1157 | * Returns a StatementIterator for traversing the MemModel.
|
---|
1158 | * @access public
|
---|
1159 | * @return object StatementIterator
|
---|
1160 | */
|
---|
1161 | function & getStatementIterator() {
|
---|
1162 | // Import Package Utility
|
---|
1163 | require_once RDFAPI_INCLUDE_DIR . 'util/StatementIterator.php';
|
---|
1164 |
|
---|
1165 | $si = new StatementIterator($this);
|
---|
1166 | return $si;
|
---|
1167 | }
|
---|
1168 |
|
---|
1169 | /**
|
---|
1170 | * Returns a FindIterator for traversing the MemModel.
|
---|
1171 | * @access public
|
---|
1172 | * @return object FindIterator
|
---|
1173 | */
|
---|
1174 | function & findAsIterator($sub=null,$pred=null,$obj=null) {
|
---|
1175 | // Import Package Utility
|
---|
1176 | require_once RDFAPI_INCLUDE_DIR . 'util/FindIterator.php';
|
---|
1177 |
|
---|
1178 | $if = new FindIterator($this,$sub,$pred,$obj);
|
---|
1179 | return $if;
|
---|
1180 | }
|
---|
1181 |
|
---|
1182 | /**
|
---|
1183 | * Returns a FindIterator for traversing the MemModel.
|
---|
1184 | * @access public
|
---|
1185 | * @return object FindIterator
|
---|
1186 | */
|
---|
1187 | function & iterFind($sub=null,$pred=null,$obj=null) {
|
---|
1188 | // Import Package Utility
|
---|
1189 | require_once RDFAPI_INCLUDE_DIR . 'util/IterFind.php';
|
---|
1190 |
|
---|
1191 | $if = new IterFind($this,$sub,$pred,$obj);
|
---|
1192 | return $if;
|
---|
1193 | }
|
---|
1194 |
|
---|
1195 |
|
---|
1196 | /**
|
---|
1197 | * Returns the models namespaces.
|
---|
1198 | *
|
---|
1199 | * @author Tobias Gauᅵ<tobias.gauss@web.de>
|
---|
1200 | * @access public
|
---|
1201 | * @return Array
|
---|
1202 | */
|
---|
1203 | function getParsedNamespaces(){
|
---|
1204 | if(count($this->parsedNamespaces)!=0){
|
---|
1205 | return $this->parsedNamespaces;
|
---|
1206 | }else{
|
---|
1207 | return false;
|
---|
1208 | }
|
---|
1209 | }
|
---|
1210 |
|
---|
1211 |
|
---|
1212 |
|
---|
1213 | /**
|
---|
1214 | * Adds the namespaces to the model. This method is called by
|
---|
1215 | * the parser. !!!! addParsedNamespaces() not overwrites manual
|
---|
1216 | * added namespaces in the model !!!!
|
---|
1217 | *
|
---|
1218 | * @author Tobias Gauᅵ<tobias.gauss@web.de>
|
---|
1219 | * @access public
|
---|
1220 | * @param Array $newNs
|
---|
1221 | */
|
---|
1222 | function addParsedNamespaces($newNs){
|
---|
1223 | if($newNs)
|
---|
1224 | $this->parsedNamespaces = $this->parsedNamespaces + $newNs;
|
---|
1225 | }
|
---|
1226 |
|
---|
1227 |
|
---|
1228 | /**
|
---|
1229 | * Adds a namespace and prefix to the model.
|
---|
1230 | *
|
---|
1231 | * @author Tobias Gauᅵ<tobias.gauss@web.de>
|
---|
1232 | * @access public
|
---|
1233 | * @param String
|
---|
1234 | * @param String
|
---|
1235 | */
|
---|
1236 | function addNamespace($prefix, $nmsp){
|
---|
1237 | $this->parsedNamespaces[$nmsp]=$prefix;
|
---|
1238 | }
|
---|
1239 |
|
---|
1240 | /**
|
---|
1241 | * removes a single namespace from the model
|
---|
1242 | *
|
---|
1243 | * @author Tobias Gauᅵ<tobias.gauss@web.de>
|
---|
1244 | * @access public
|
---|
1245 | * @param String $nmsp
|
---|
1246 | */
|
---|
1247 | function removeNamespace($nmsp){
|
---|
1248 | if(isset($this->parsedNamespaces[$nmsp])){
|
---|
1249 | unset($this->parsedNamespaces[$nmsp]);
|
---|
1250 | return true;
|
---|
1251 | }else{
|
---|
1252 | return false;
|
---|
1253 | }
|
---|
1254 | }
|
---|
1255 |
|
---|
1256 |
|
---|
1257 |
|
---|
1258 | /**
|
---|
1259 | * Close the MemModel and free up resources held.
|
---|
1260 | *
|
---|
1261 | * @access public
|
---|
1262 | */
|
---|
1263 | function close() {
|
---|
1264 | unset( $this->baseURI );
|
---|
1265 | unset( $this->triples );
|
---|
1266 | }
|
---|
1267 |
|
---|
1268 | // =============================================================================
|
---|
1269 | // *************************** helper functions ********************************
|
---|
1270 | // =============================================================================
|
---|
1271 | /**
|
---|
1272 | * Checks if $statement is in index
|
---|
1273 | *
|
---|
1274 | * @param int $ind
|
---|
1275 | * @param Statement &$statement
|
---|
1276 | * @return boolean
|
---|
1277 | * @access private
|
---|
1278 | */
|
---|
1279 | function _containsIndex(&$statement,$ind){
|
---|
1280 | switch($ind){
|
---|
1281 | case 4:
|
---|
1282 | $sub=$statement->getSubject();
|
---|
1283 | $pos=$sub->getLabel();
|
---|
1284 | break;
|
---|
1285 | case 1:
|
---|
1286 | $sub=$statement->getSubject();
|
---|
1287 | $pred=$statement->getPredicate();
|
---|
1288 | $obj=$statement->getObject();
|
---|
1289 | $pos=$sub->getLabel().$pred->getLabel().$obj->getLabel();
|
---|
1290 | break;
|
---|
1291 | case 2:
|
---|
1292 | $sub=$statement->getSubject();
|
---|
1293 | $pred=$statement->getPredicate();
|
---|
1294 | $pos=$sub->getLabel().$pred->getLabel();
|
---|
1295 | break;
|
---|
1296 | case 3:
|
---|
1297 | $sub=$statement->getSubject();
|
---|
1298 | $obj=$statement->getObject();
|
---|
1299 | $pos=$sub->getLabel().$obj->getLabel();
|
---|
1300 | break;
|
---|
1301 | }
|
---|
1302 |
|
---|
1303 | if (!isset($this->indexArr[$ind][$pos]))
|
---|
1304 | return FALSE;
|
---|
1305 | foreach ($this->indexArr[$ind][$pos] as $key => $value) {
|
---|
1306 | $t=$this->triples[$value];
|
---|
1307 | if ($t->equals($statement))
|
---|
1308 | return TRUE;
|
---|
1309 | }
|
---|
1310 | return FALSE;
|
---|
1311 | }
|
---|
1312 |
|
---|
1313 |
|
---|
1314 |
|
---|
1315 |
|
---|
1316 |
|
---|
1317 | /**
|
---|
1318 | * finds a statement in an index. $pos is the Position in the index
|
---|
1319 | * and $ind the adequate searchindex
|
---|
1320 | *
|
---|
1321 | * @param String $pos
|
---|
1322 | * @param Object Subject &$subject
|
---|
1323 | * @param Object Predicate &$predicate
|
---|
1324 | * @param Object Object &$object
|
---|
1325 | * @param int &ind
|
---|
1326 | * @return MemModel $res
|
---|
1327 | * @access private
|
---|
1328 | */
|
---|
1329 | function _findInIndex($pos,&$subject,&$predicate,&$object,$ind){
|
---|
1330 | $res = new MemModel($this->getBaseURI());
|
---|
1331 | $res->indexed=-1;
|
---|
1332 | if (!isset($this->indexArr[$ind][$pos]))
|
---|
1333 | return $res;
|
---|
1334 | foreach($this->indexArr[$ind][$pos] as $key =>$value){
|
---|
1335 | $t=$this->triples[$value];
|
---|
1336 | if ($this->matchStatement($t,$subject,$predicate,$object))
|
---|
1337 | $res->add($t);
|
---|
1338 | }
|
---|
1339 | return $res;
|
---|
1340 | }
|
---|
1341 | /**
|
---|
1342 | * adds/removes a statement into/from an index.
|
---|
1343 | * mode=0 removes the statement from the index;
|
---|
1344 | * mode=1 adds the statement into the index.
|
---|
1345 | * returns the statements position.
|
---|
1346 | *
|
---|
1347 | * @param Object Statement &$statement
|
---|
1348 | * @param int $k
|
---|
1349 | * @param int $ind
|
---|
1350 | * @param int $mode
|
---|
1351 | * @return int $k
|
---|
1352 | * @access private
|
---|
1353 | */
|
---|
1354 | function _indexOpr(&$statement,$k,$ind,$mode){
|
---|
1355 | // determine position in adequate index
|
---|
1356 | switch($ind){
|
---|
1357 | case 1:
|
---|
1358 | $s=$statement->getSubject();
|
---|
1359 | $p=$statement->getPredicate();
|
---|
1360 | $o=$statement->getObject();
|
---|
1361 | $pos=$s->getLabel().$p->getLabel().$o->getLabel();
|
---|
1362 | break;
|
---|
1363 | case 2:
|
---|
1364 | $s=$statement->getSubject();
|
---|
1365 | $p=$statement->getPredicate();
|
---|
1366 | $pos=$s->getLabel().$p->getLabel();
|
---|
1367 | break;
|
---|
1368 | case 3:
|
---|
1369 | $s=$statement->getSubject();
|
---|
1370 | $o=$statement->getObject();
|
---|
1371 | $pos=$s->getLabel().$o->getLabel();
|
---|
1372 | break;
|
---|
1373 | case 4:
|
---|
1374 | $s=$statement->getSubject();
|
---|
1375 | $pos=$s->getLabel();
|
---|
1376 | break;
|
---|
1377 | case 5:
|
---|
1378 | $p=$statement->getPredicate();
|
---|
1379 | $pos=$p->getLabel();
|
---|
1380 | break;
|
---|
1381 | case 6:
|
---|
1382 | $o=$statement->getObject();
|
---|
1383 | $pos=$o->getLabel();
|
---|
1384 | break;
|
---|
1385 | }
|
---|
1386 | switch($mode){
|
---|
1387 | // add in Index
|
---|
1388 | case 1:
|
---|
1389 | if(isset($this->indexArr[$ind][$pos])){
|
---|
1390 | $this->indexArr[$ind][$pos][] = $k;
|
---|
1391 | }else{
|
---|
1392 | $this->indexArr[$ind][$pos][0] = $k;
|
---|
1393 | }
|
---|
1394 | break;
|
---|
1395 | // remove from Index
|
---|
1396 | case 0:
|
---|
1397 | $subject=$statement->getSubject();
|
---|
1398 | $predicate=$statement->getPredicate();
|
---|
1399 | $object=$statement->getObject();
|
---|
1400 | $k=-1;
|
---|
1401 | if(!isset($this->indexArr[$ind][$pos])){
|
---|
1402 | return -1;
|
---|
1403 | }
|
---|
1404 | $num=count($this->indexArr[$ind][$pos]);
|
---|
1405 | foreach($this->indexArr[$ind][$pos] as $key => $value){
|
---|
1406 | $t=$this->triples[$value];
|
---|
1407 | if($this->matchStatement($t,$subject,$predicate,$object)){
|
---|
1408 | $k=$value;
|
---|
1409 | if($num==1){
|
---|
1410 | unset($this->indexArr[$ind][$pos]);
|
---|
1411 | }else{
|
---|
1412 | unset($this->indexArr[$ind][$pos][$key]);
|
---|
1413 | }
|
---|
1414 | return $k;
|
---|
1415 | }
|
---|
1416 | }
|
---|
1417 | break;
|
---|
1418 | }
|
---|
1419 | return $k;
|
---|
1420 | }
|
---|
1421 |
|
---|
1422 |
|
---|
1423 | /**
|
---|
1424 | * finds next or previous matching statement.
|
---|
1425 | * Returns Position in model or -1 if there is no match.
|
---|
1426 | *
|
---|
1427 | *
|
---|
1428 | * @param String
|
---|
1429 | * @param object Subject
|
---|
1430 | * @param object Predicate
|
---|
1431 | * @param object Object
|
---|
1432 | * @param integer
|
---|
1433 | * @param integer
|
---|
1434 | * @return integer
|
---|
1435 | * @access private
|
---|
1436 | */
|
---|
1437 | function _findMatchIndex($pos,&$s,&$p,&$o,$ind,$off){
|
---|
1438 | $match=-1;
|
---|
1439 | if (!isset($this->indexArr[$ind][$pos])) {
|
---|
1440 | return $match;}
|
---|
1441 | foreach($this->indexArr[$ind][$pos] as $key =>$value){
|
---|
1442 | $t=$this->triples[$value];
|
---|
1443 | if ($this->matchStatement($t,$s,$p,$o)){
|
---|
1444 | if($off <= $value){
|
---|
1445 | $match= $value;
|
---|
1446 | return $match;
|
---|
1447 | }
|
---|
1448 | }
|
---|
1449 | }
|
---|
1450 |
|
---|
1451 | return $match;
|
---|
1452 |
|
---|
1453 | }
|
---|
1454 |
|
---|
1455 |
|
---|
1456 |
|
---|
1457 |
|
---|
1458 | } // end: MemModel
|
---|
1459 |
|
---|
1460 |
|
---|
1461 | ?>
|
---|