source: php/trunk/classes/rdfa_Data.php@ 21

Last change on this file since 21 was 21, checked in by cla, 14 years ago

rdfint

  • added unittest rdfa_set and methods stubs & documentation for rdfa::Data::setValue and rdfa::Projection::set
  • Property svn:eol-style set to native
File size: 34.0 KB
Line 
1<?php
2
3/* RDFInt.php - RDF Interfaces for PHP
4 * Copyright 2011 netlabs.org
5 * Author: Christian Langanke, Adrian Gschwend
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20namespace rdfa;
21
22/**
23 * \class Data
24 * \brief This class implements a RDF data class as described in the
25 * RDF API and RDFa API specs of W3C.
26 * \author Christian Langanke
27 * \author Adrian Gschwend
28 * \date 2011
29 */
30
31/*
32 * This class internally uses the ARC triple array format for storing RDF data:
33 *
34 * Array
35 * (
36 * [type] => --- 'triple' --- (others ???)
37 * [s] => --- uri ---
38 * [p] => --- uri ---
39 * [o] => --- uri or bnode or literal ---
40 * [s_type] => --- 'uri' or 'bnode' ---
41 * [p_type] => --- 'uri' --- (others ???)
42 * [o_type] => => --- 'uri' or 'bnode' oder 'literal' ---
43 * [o_datatype] => --- datatype or empty ---
44 * [o_lang] => --- lang code or empty ---
45 * )
46 *
47 */
48
49class Data {
50
51 /**
52 * Version of the class
53 */
54 const version = '1.0.0';
55 /**
56 * Name of the fDebug context
57 */
58 const debugcontext = 'RDFA_DATA';
59
60 private $debugger;
61 private $aTriples;
62 private $aNamespace;
63
64 // ---------------------------------------
65
66 /**
67 * Creates a data class instance.
68 * In order to access data, you have to call rdfa::Data::parse().
69 */
70 public function __construct() {
71
72 // setup debugger
73 $this->debugger = \fDebug::getInstance();
74
75 // initialize some vars
76 $this->aTriples = array();
77 $this->aNamespace = array();
78
79 } // public function __construct
80
81 // ########################################################
82 // private interface
83 // ########################################################
84
85 // debug formatting helpers
86
87 /**
88 * Return string with debug output, representing data from an ARC triple array.
89 * Values not being speciefied (==Null) are not included in the text.
90 * The object or value is enclosed in double quotes, if it is a literal
91 */
92 private function _debug_formatArcTriple( $aTriple) {
93 $subject = $aTriple[ 's'];
94 $predicate = $aTriple[ 'p'];
95 $object = $aTriple[ 'o'];
96 $objecttype = (isset( $aTriple[ 'o_type'])) ? $aTriple[ 'o_type'] : '';
97
98 $litSubject = ($subject == NULL) ? "" : $this->_shrinkFormatted( $subject);
99 $litPredicate = ($predicate == NULL) ? "" : $this->_shrinkFormatted( $predicate);
100
101 if ($object == NULL)
102 $litObject = "";
103 else {
104 if ($objecttype == 'literal')
105 $litObject = '"' . $object . '"';
106 else
107 $litObject = $this->_shrinkFormatted( $object);
108 }
109
110 $result = trim( "$litSubject $litPredicate $litObject");
111 return $result;
112 }
113
114 /**
115 * Return string with debug output, representing data the specified values.
116 * Values not being speciefied (==Null) are not included in the text.
117 * The object or value is enclosed in double quotes, if it is a literal
118 */
119 private function _debug_formatTripleFromParms( $subject, $predicate, $object) {
120 return $this->_debug_formatArcTriple( array( 's' => $subject,
121 'p' => $predicate,
122 'o' => $object));
123 }
124
125 // --------------------------------------------------------
126
127 /**
128 * Filters out requested triples by specified subject/predicate/object
129 * Returns array of matching triples in ARC triple array format
130 */
131 private function _filterTriples( $subject = NULL,
132 $predicate = NULL,
133 $object = NULL,
134 &$debugmessage_result) {
135
136 $searchTriple = array ( 's' => $subject, 'p' => $predicate, 'o' => $object);
137
138 // resolve namespace prefixes
139 $uriSubject = $this->resolve( $subject);
140 $uriPredicate = $this->resolve( $predicate);
141 $uriObject = $this->resolve( $object);
142
143 // resolve method may return NULL, then use original value
144 $uriSubject = ($uriSubject === NULL) ? $subject : $uriSubject;
145 $uriPredicate = ($uriPredicate === NULL) ? $predicate : $uriPredicate;
146 $uriObject = ($uriObject === NULL) ? $object : $uriObject;
147
148 // filter all available triples
149 $aresult = array();
150 foreach ($this->aTriples as $aTriple) {
151
152 // must be triple
153 if ((isset( $aTriple[ 'type'])) &&
154 ($aTriple[ 'type'] != 'triple'))
155 continue;
156
157 // check subject and predicate match if given
158 if (($uriSubject != NULL) && (strcmp( $uriSubject, $aTriple[ 's'])))
159 continue;
160
161 if (($uriPredicate != NULL) && (strcmp( $uriPredicate, $aTriple[ 'p'])))
162 continue;
163
164 // check object if given
165 if ($uriObject != NULL) {
166
167 // check object match
168 if (strcmp( $uriObject, $aTriple[ 'o']))
169 continue;
170
171 } // if ($uriObject != NULL) {
172
173 // store in result array
174 $aresult[] = $aTriple;
175
176 } // foreach ($aTriples as $aTriple)
177
178 // show result in debugger
179 $triplecount = count( $this->aTriples);
180 $resultcount = count( $aresult);
181 if ($resultcount == 0)
182 $debugmessage_result = "No match in $triplecount triples!";
183 else {
184 $debugmessage_result = "Matches in $triplecount triples: \n";
185 foreach ($aresult as $aTriple) {
186 $debugmessage_result .= $this->_debug_formatArcTriple( $aTriple)."\n";
187 }
188 }
189
190 return $aresult;
191
192 } // private function _filterTriples
193
194 // --------------------------------------------------------
195
196 /**
197 * Checks if a given subject exists in the RDF data.
198 */
199 private function _subjectExists( $subject) {
200
201 $uriSubject = $this->shrink( $subject);
202 foreach ($this->aTriples as $aTriple) {
203 if ( $uriSubject == $this->shrink( $aTriple[ 's']))
204 return true;
205 }
206
207 return false;
208
209 } // private function _subjectExists
210
211 // --------------------------------------------------------
212
213 /**
214 * Add mapping to internal namespace list.
215 * This method is called internally, not producing debug output.
216 */
217 private function _addNamespaceMapping( $prefix, $uriNamespace) {
218
219 if ($prefix == '')
220 return false;
221
222 // add colon to prefix as internally req.
223 if (substr( $prefix, -1) != ':')
224 $prefix = "$prefix:";
225
226 if (isset( $this->aNamespace[ $prefix])) {
227 $oldUriNamespace = $this->aNamespace[ $prefix];
228 if ($oldUriNamespace == $uriNamespace)
229 $debugmessage = "Namespace mapping exists: @prefix $prefix <$uriNamespace> .";
230 else
231 $debugmessage = "Namespace mapping overwritten: @prefix $prefix <$uriNamespace> .\n" .
232 "Old mapping was: @prefix $prefix <$oldUriNamespace>";
233 } else {
234 $debugmessage = "Namespace mapping added: @prefix $prefix <$uriNamespace> .";
235 }
236
237 // set URI
238 $this->aNamespace[ $prefix] = $uriNamespace;
239 return $debugmessage;
240
241 } // private function _addNamespaceMapping
242
243 // --------------------------------------------------------
244
245 /**
246 * Shrink URI to CURI, but return <URI> if mapping not successful.
247 */
248 private function _shrinkFormatted( $uri) {
249
250 $curie = $this->shrink( $uri);
251 if ($curie == $uri)
252 $curie = "<$uri>";
253 return $curie;
254
255 } // private function _shrinkFormatted
256
257 // --------------------------------------------------------
258
259 // CURRENTLY NOT FULLY IMPLEMENTED
260
261 // adjust blank node IDs so that same blank nodes of a
262 // triple sets has the same id as in the currently contained
263 // triple set.
264 // NOTE: a blank nodes may not be adjusted if there are
265 // two different values for the same blank node in the two
266 // triple sets, as then the two blank nodes may represent a
267 // multivalue property
268
269 private function _adjustBlankNodes( $aTriplesToAdd) {
270
271
272// foreach ($this->aTriples as $aTriple) {
273// if ($aTriple[ 'o_type'] == 'bnode')
274// echo $aTriple[ 'o']."\n";
275// }
276
277
278 return $aTriplesToAdd;
279
280 }
281
282 // --------------------------------------------------------
283
284 // add an array of ARC triple arrays
285 // to the data hold by the instance
286 private function _addTriples( $aTriples) {
287 if (!is_array( $aTriples))
288 return;
289
290 // adjust blank node IDs first
291 $aTripleAdusted = $this->_adjustBlankNodes( $aTriples);
292
293 // add adjusted triples
294 foreach ($aTripleAdusted as $aTriple) {
295 $this->_addTriple( $aTriple);
296 }
297 } // private function _addTriples
298
299 // --------------------------------------------------------
300
301 // add an ARC triple array
302 // to the data hold by the instance
303 // the triple is only merged if not yet included !
304 private function _addTriple( $aTriple) {
305
306
307 if (!is_array( $aTriple))
308 return;
309 if ((isset( $aTriple['type']) &&
310 ($aTriple['type'] != 'triple')))
311 return;
312
313 // if triple is not contained, add it!
314 if (array_search( $aTriple, $this->aTriples) === false)
315 $this->aTriples[] = $aTriple;
316
317 } // private function _addTriple
318
319 // --------------------------------------------------------
320
321 /**
322 * Checks if callers caller is from own library code.
323 * Helps to reduce unwanted ddebug output
324 */
325 private function _calledFromOwnCode() {
326 // check for own namespace in backtrace
327 $trace = array_slice(debug_backtrace( false), 2, 1);
328 $class = (isset( $trace[0]['class'])) ? $trace[0]['class'] : '';
329 return (strpos( $class, 'rdfa\\') === 0);
330 } // private function _calledFromOwnCode
331
332 // ########################################################
333 // public interface
334 // ########################################################
335
336 /**
337 * \name Mapping API
338 */
339 /**@{ */ /***************** DOXYGEN GROUP START - Mapping APIs */
340
341 /**
342 * Sets short-hand IRI mappings that are used by the API to map URIs to CURIEs.
343 *
344 * \param prefix namespace prefix of the mapping
345 * \param uriNamespace namespace base URI of the mapping
346 */
347 public function setMapping( $prefix, $uriNamespace) {
348 $debugmessage = $this->_addNamespaceMapping( $prefix, $uriNamespace);
349 if ($debugmessage != false)
350 $this->debugger->sendMessage( $debugmessage,
351 self::debugcontext);
352 } // public function setMapping
353
354 // --------------------------------------------------------
355
356 /**
357 * Resolves a CURI to a URI.
358 *
359 * If the prefix is not known then this method will return null.
360 *
361 * \param curie CURIE to be resolved to a URI
362 *
363 * <strong>NOTE: This method is a library specific extension to the RDF API and RDFa API.</strong>
364 */
365 public function resolve( $curie) {
366
367 $replacecount = 1;
368 $uri = NULL;
369 if ($curie != NULL) {
370 if ($this->aNamespace != NULL) {
371 if ((strpos( $uri, ":/") !== false) ||
372 (strpos( $uri, "_:") === 0)) {
373 $uri = $curi;
374 } else {
375 // check for namespaces
376 foreach ($this->aNamespace as $prefix => $uriNamespace) {
377 // check for prefix match
378 $posPrefix = strpos( $curie, $prefix);
379 if ($posPrefix === 0) {
380 // replace prefix and bail out
381 $uri = str_replace( $prefix, $uriNamespace, $curie, $replacecount);
382 break;
383 }
384 } // foreach ($this->aNamespace
385 } // if ((strpos ...
386 } // if ($aNamespace != NULL) {
387 } // if ($uri != NULL) {
388
389 return $uri;
390
391 } // public function resolve
392
393 // --------------------------------------------------------
394
395 /**
396 * Shrinks a URI to a CURIE.
397 *
398 * If no mapping exists for the given URI, the URI is returned.
399 *
400 * \param uri URI to be shrinked to a CURIE
401 *
402 * <strong>NOTE: This method is a library specific extension to the RDF API and RDFa API.</strong>
403 */
404 public function shrink( $uri) {
405
406 $replacecount = 1;
407 if ($uri != NULL) {
408 if ($this->aNamespace != NULL) {
409 if (strpos( $uri, ":/") !== false) {
410 foreach ($this->aNamespace as $prefix => $uriNamespace) {
411 // search namespace URI
412 $posNamespace = strpos( $uri, $uriNamespace);
413 if ($posNamespace === false)
414 continue;
415 // replace namespace URI and bail out
416 $uri = str_replace( $uriNamespace, $prefix, $uri, &$replacecount);
417 break;
418 } // foreach ($aNamespace
419 } // if (strpos( $uri, ":/") !== false)
420 } // if ($aNamespace != NULL) {
421 } // if ($uri != NULL) {
422
423 return $uri;
424
425 } // public function shrink
426
427 /**@} */ /***************** DOXYGEN GROUP ENDS - Mapping APIs */
428
429 // --------------------------------------------------------
430
431 /**
432 * Parses RDF data from a URI.
433 *
434 * \param toparse resource to parse from. This can be a URI or an object of SparqlQuery
435 *
436 * <strong>NOTE:
437 * - This method is defined for the RDF API, but a library specific extension to the RDFa API.
438 * - Parsing from a SPARQL CONSTRUCT query by using a SparqlQuery object, is a library specific
439 * extension to both the RDF API and RDFa API.
440 * </strong>
441 */
442 public function parse( $toparse) {
443
444 // check type to parse
445 if ((is_object( $toparse)) &&
446 ('\\' . get_class( $toparse) == '\\rdfa\\SparqlQuery')) {
447
448 // receive RDF data from raw SPARQL query
449 $query = $toparse;
450 $parseSource = "SPARQL query";
451
452 $statement = $query->getStatement();
453 $debugMessage = "Parsing RDF data from SPARQL query\n" .
454 "Executing statement: \n" . $statement;
455 $this->debugger->sendMessage( $debugMessage, self::debugcontext);
456
457 $index = $query->run();
458 $newTriples = \ARC2::getTriplesFromIndex( $index);
459
460 } else {
461
462 // load RDF data from URI
463 $uri = $toparse;
464 $parseSource = "ARC parser";
465
466 $debugMessage = "Parsing RDF data from: $uri\n";
467 $this->debugger->sendMessage( $debugMessage, self::debugcontext);
468
469 $arcParser = \ARC2::getRDFParser();
470 $arcParser->parse( $uri);
471 $newTriples = $arcParser->getTriples();
472
473 }
474
475 // determine operation mode
476 $fMerge = (count( $this->aTriples) != 0);
477 if ($fMerge)
478 $operation = "merged";
479 else
480 $operation = "loaded";
481
482 // merge new triples into existing data
483 $this->_addTriples( $newTriples);
484
485 $debugMessage = count( $newTriples) . " triple(s) $operation from $parseSource\n";
486 foreach ($newTriples as $aTriple) {
487 $debugMessage .= $this->_debug_formatArcTriple( $aTriple)."\n";
488 }
489 if ($fMerge)
490 $debugMessage .= "\n" . count( $this->aTriples) . " triples total\n";
491 $this->debugger->sendMessage( $debugMessage, self::debugcontext);
492
493 } // public function parse
494
495 // --------------------------------------------------------
496
497 /**
498 * \name Basic API
499 */
500 /**@{ */ /***************** DOXYGEN GROUP START - Basic APIs */
501
502
503 /**
504 * Retrieves a list of all values expressed in the RDF Data that match the given subject and property.
505 *
506 * \param property property that the subject should be linked with
507 * \param value value that the specified property should have
508 *
509 * If no arguments are provided, all values from within the RDF data are returned.
510 */
511 public function getSubjects( $property = Null, $value = NULL) {
512
513 $predicate = $property;
514 $object = $value;
515 $aTriplesResult = $this->_filterTriples( NULL, $predicate, $object,
516 $debugmessage_filterresult);
517 // build result
518 $aresult = false;
519 foreach ($aTriplesResult as $aTriple) {
520 $aresult[]= $this->shrink( $aTriple[ 's']);
521 }
522
523 // make result entries unique
524 if ($aresult !== false)
525 $aresult = array_values( array_unique( $aresult));
526
527 // build debug message
528 if (!$this->_calledFromOwnCode()) {
529 $formattedTriple = $this->_debug_formatTripleFromParms( NULL, $predicate, $object);
530 if (!$aresult)
531 $debugmessage = "No subjects found for: $formattedTriple\n";
532 else {
533 $debugmessage = count( $aresult) . " subjects found";
534 if ($formattedTriple != '')
535 $debugmessage .= " for: $formattedTriple";
536 $debugmessage .= "\n";
537 foreach( $aresult as $result) {
538 $debugmessage .= "$result\n";
539 }
540 }
541 $this->debugger->sendMessage( "$debugmessage\n$debugmessage_filterresult",
542 self::debugcontext);
543
544 } // if (!$this->_calledFromOwnCode())
545
546 return $aresult;
547
548 } // public function getSubjects
549
550 // --------------------------------------------------------
551
552 /**
553 * Retrieves a list of all properties expressed in the RDF data that match the given subject.
554 *
555 * \param subject subject to be searched
556 *
557 * If a subject is not provided, all properties expressed in the RDF data are returned.
558 */
559 public function getProperties( $subject = Null) {
560
561 $aTriplesResult = $this->_filterTriples( $subject, Null, Null,
562 $debugmessage_filterresult);
563
564 // build result
565 $aresult = false;
566 foreach ($aTriplesResult as $aTriple) {
567 $aresult[]= $this->shrink( $aTriple[ 'p']);
568 }
569
570 // make result entries unique
571 if ($aresult !== false)
572 $aresult = array_values( array_unique( $aresult));
573
574 // build debug message
575 if (!$this->_calledFromOwnCode()) {
576 if (!$aresult) {
577 if ( $subject = Null)
578 $debugmessage = "No properties found\n";
579 else
580 $debugmessage = "No properties found for subject: $subject\n";
581 }
582 else {
583
584 $debugmessage = count( $aresult) . " properties found for: $subject\n";
585 foreach( $aresult as $result) {
586 $debugmessage .= "$result\n";
587 }
588 }
589 $this->debugger->sendMessage( "$debugmessage\n$debugmessage_filterresult",
590 self::debugcontext);
591
592 } // if (!$this->_calledFromOwnCode())
593
594 return $aresult;
595
596
597 } // public function getProperties
598
599 // --------------------------------------------------------
600
601 /**
602 * Retrieves an associative list of unique properties with their values expressed in the RDF data
603 * that match the given subject. All non-unique properties are <i>NOT</i> returned !
604 *
605 * \param subject subject to be searched
606 *
607 * If a subject isn't provided, all unique properties expressed in the RDF data are returned.
608 *
609 * <strong>NOTE: This method is a library specific extension to the RDF API and RDFa API.</strong>
610 */
611 public function _getUniqueProperties( $subject = Null) {
612
613 $aTriplesResult = $this->_filterTriples( $subject, Null, Null,
614 $debugmessage_filterresult);
615
616 // build result
617 $aresult = false;
618 $afound = array();
619 foreach ($aTriplesResult as $pos => $aTriple) {
620 // isolate predicate and check if it was already found
621 $thispredicate = $this->shrink( $aTriple[ 'p']);
622 if (isset( $afound[ $thispredicate])) {
623 unset( $aresult[ $thispredicate]);
624 continue;
625 } else {
626 $afound[ $thispredicate] = true;
627 $aresult[ $thispredicate] = $this->shrink( $aTriple[ 'o']);
628 }
629 }
630
631 // build debug message
632 if (!$this->_calledFromOwnCode()) {
633 if (!$aresult) {
634 if ( $subject = Null)
635 $debugmessage = "No unique properties found\n";
636 else
637 $debugmessage = "No unique properties found for subject: $subject\n";
638 }
639 else {
640
641 $debugmessage = count( $aresult) . " unique properties found for: $subject\n";
642 foreach( $aresult as $result) {
643 $debugmessage .= "$result\n";
644 }
645 }
646 $this->debugger->sendMessage( "$debugmessage\n$debugmessage_filterresult",
647 self::debugcontext);
648
649 } // if (!$this->_calledFromOwnCode())
650
651 return $aresult;
652
653
654 } // public function _getUniqueProperties
655
656 // --------------------------------------------------------
657
658 /**
659 * Retrieves a list of all values expressed in the RDF data that match the given subject and property.
660 *
661 * \param subject subject to be searched
662 * \param property property to be searched
663 *
664 * If no arguments are provided, all values expressed in the RDF data are returned.
665 */
666 public function getValues( $subject = Null, $property = Null) {
667
668 $predicate = $property;
669 $aTriplesResult = $this->_filterTriples( $subject, $predicate, Null,
670 $debugmessage_filterresult);
671
672 // build result
673 $aresult = false;
674 foreach ($aTriplesResult as $aTriple) {
675 $aresult[]= $this->shrink( $aTriple[ 'o']);
676 }
677
678 // make result entries unique
679 if ($aresult !== false)
680 $aresult = array_values( array_unique( $aresult));
681
682 // build debug message
683 if (!$this->_calledFromOwnCode()) {
684 $formattedTriple = $this->_debug_formatTripleFromParms( $subject, $predicate, Null);
685 if ($aresult === false) {
686 if ( $subject = Null)
687 $debugmessage = "No values found\n";
688 else
689 $debugmessage = "No values found for subject: $formattedTriple\n";
690 }
691 else {
692
693 $debugmessage = count( $aresult) . " values found for: $formattedTriple\n";
694 foreach( $aresult as $result) {
695 $debugmessage .= "$result\n";
696 }
697 }
698 $this->debugger->sendMessage( "$debugmessage\n$debugmessage_filterresult",
699 self::debugcontext);
700
701 } // if (!$this->_calledFromOwnCode())
702
703 return $aresult;
704
705 } // public function getValues
706
707 // --------------------------------------------------------
708
709 /**
710 * Retrieves the first available value expressed in the RDF data that matches the given subject and property.
711 *
712 * \param subject subject to be searched
713 * \param property property to be searched
714 *
715 * If no arguments are provided, the first value expressed in the RDF data is returned.
716 *
717 * <strong>NOTE: This method is a library specific extension to the RDF API and RDFa API.</strong>
718 */
719 public function _getFirstValue( $subject = Null, $property = Null) {
720
721 $predicate = $property;
722 $aTriplesResult = $this->_filterTriples( $subject, $predicate, Null,
723 $debugmessage_filterresult);
724
725 // build result
726 $result = false;
727 foreach ($aTriplesResult as $aTriple) {
728 $result = $this->shrink( $aTriple[ 'o']);
729 break;
730 }
731
732 // build debug message
733 if (!$this->_calledFromOwnCode()) {
734 $formattedTriple = $this->_debug_formatTripleFromParms( $subject, $predicate, Null);
735 if (!$result) {
736 if ($subject == Null)
737 $debugmessage = "No value found\n";
738 else
739 $debugmessage = "No value found for: $formattedTriple\n";
740 }
741 else {
742 $debugmessage = "Value $result found for: $formattedTriple\n";
743 $triplecount = count( $aTriplesResult);
744 if ($triplecount == 1)
745 $debugmessage .= "One value available";
746 else
747 $debugmessage .= "First of $triplecount values available";
748 }
749 $this->debugger->sendMessage( "$debugmessage\n$debugmessage_filterresult",
750 self::debugcontext);
751
752 } // if (!$this->_calledFromOwnCode())
753
754 return $result;
755
756 } // public function _getFirstValue
757
758 // --------------------------------------------------------
759
760 /**
761 * Sets a property value for a subject.
762 *
763 * \param subject subject to get the property set
764 * \param property property to be added
765 * \param value value to be set for the property
766 * \param type the type of the value, either 'uri', 'literal' or 'bnode'
767 * (case-insensitive). Specifying the first character is sufficient.
768 * If not specified, strings starting with 'http://' are taken as a URI,
769 * otherwise as a literal
770 * \retval true property value set
771 * \retval false subject not found or invalid value type specified
772 *
773 * \see rdfa::Projection::set
774 *
775 * <strong>NOTE:
776 * - This method is a library specific extension to the RDFa API
777 * - The parameter type is a library specific extension to the RDF API
778 * </strong>
779 */
780
781 public function setValue( $subject, $property, $value, $type = NULL) {
782
783 $predicate = $property;
784 $object = $value;
785
786 // insert code here
787 }
788
789 /**@} */ /***************** DOXYGEN GROUP ENDS - Basic APIs */
790
791 // --------------------------------------------------------
792
793 /**
794 * \name Projection API
795 */
796 /**@{ */ /***************** DOXYGEN GROUP START - Projection APIs */
797
798 /**
799 * Retrieves a single Projection given a subject and an optional template.
800 * A template can be provided for the purpose of building the Projection in an application-specific way.
801 *
802 * \param subject subject to be searched
803 * \param template associative array( URI/CURIE => membername) as a template to be applied to the projection object
804 *
805 */
806 public function getProjection( $subject, $template = Null) {
807
808 if ($subject == Null)
809 return false;
810
811 if ((!$template == Null) && (!is_array( $template))) {
812 $this->debugger->sendError( "Invalid type specified as template (must be array) " . get_class() ."::getProjection", self::debugcontext);
813 return false;
814 }
815
816 $fLogMessages = (!$this->_calledFromOwnCode());
817 if (! $this->_subjectExists( $subject)) {
818echo "### no subject \n";
819 if ($fLogMessages) $this->debugger->sendMessage( "Cannot get projection for subject: $subject",
820 self::debugcontext);
821 $result = false;
822 } else {
823 if ($fLogMessages) $this->debugger->sendMessage( "Get projection for subject: $subject",
824 self::debugcontext);
825 $result = new \rdfa\Projection( $this, $subject, $template);
826 }
827
828 return $result;
829
830 } // public function getProjection
831
832 // --------------------------------------------------------
833
834 /**
835 * Retrieves a list of Projections given an optional property and value to match against.
836 * A template can be provided for the purpose of building the Projection in an application-specific way.
837 *
838 * \param property property that the subject of the projections should be linked with
839 * \param value value that the specified property should have
840 * \param template associative array( URI/CURIE => membername) as a template to be applied to the projection object
841 *
842 * If no arguments are provided, projections are created for all subjects from within the RDF data.
843 */
844 public function getProjections( $property = Null, $value = Null, $template = Null) {
845
846 if ((!$template == Null) && (!is_array( $template))) {
847 $this->debugger->sendError( "Invalid type specified as template (must be array) for " . get_class() ."::getProjections", self::debugcontext);
848 return false;
849 }
850
851 // providing log output about call
852 $predicate = $property;
853 $object = $value;
854 $fLogMessages = (!$this->_calledFromOwnCode());
855 $formattedTriple = $this->_debug_formatTripleFromParms( Null, $predicate, $object);
856 if ($formattedTriple != '')
857 $formattedTriple = " for: $formattedTriple";
858
859 $asubjects = $this->getSubjects( $property, $value);
860 if ($asubjects == false) {
861 if ($fLogMessages) $this->debugger->sendMessage( "Cannot get projections $formattedTriple",
862 self::debugcontext);
863 $aprojection = false;
864 } else {
865 $count = count( $asubjects);
866 if ($fLogMessages) $this->debugger->sendMessage( "Getting $count projections $formattedTriple",
867 self::debugcontext);
868 $aprojection = array();
869 foreach ($asubjects as $subject) {
870 $aprojection[] = new \rdfa\Projection( $this, $subject, $template);
871 }
872 }
873
874 return $aprojection;
875
876 } // public function getProjection
877
878 // --------------------------------------------------------
879
880 /**
881 * Retrieves a list of Projections based on a set of selection criteria.
882 * A template can be provided for the purpose of building the Projection in an application-specific way.
883 *
884 * \param query an associative array( URI/CURIE => value) specifying a multiple property filter
885 * \param template associative array( URI/CURIE => membername) as a template to be applied to the projection object
886 *
887 * If no arguments are provided, projections are created for all subjects from within the RDF data.
888 */
889 public function query( $query, $template = Null) {
890
891 if ((!$query == Null) && (!is_array( $query))) {
892 $this->debugger->sendError( "Invalid type specified as query (must be array) for " . get_class() ."::query", self::debugcontext);
893 return false;
894 }
895 if (count( $query) == 0) {
896 $this->debugger->sendError( "Empty query array specified " . get_class() ."::query", self::debugcontext);
897 return false;
898 }
899
900 if ((!$template == Null) && (!is_array( $template))) {
901 $this->debugger->sendError( "Invalid type specified as template (must be array) " . get_class() ."::query", self::debugcontext);
902 return false;
903 }
904
905 // providing log output about query
906 $fLogMessages = (!$this->_calledFromOwnCode());
907 $debugmessage = "Querying for projections\n";
908 foreach ($query as $property => $value) {
909 $debugmessage .= "filter: $property $value\n";
910 }
911 if ($fLogMessages) $this->debugger->sendMessage( "$debugmessage",
912 self::debugcontext);
913
914 // do initial search
915 list( $property, $value) = each( $query);
916 $asubjects = $this->getSubjects( $property, $value);
917 if ($asubjects == false)
918 return false;
919
920 // create projections for examination
921 $aprojection_test = array();
922 $count = count( $asubjects);
923 if ($fLogMessages) $this->debugger->sendMessage( "Getting $count projections for filter test",
924 self::debugcontext);
925 foreach ($asubjects as $subject) {
926 $aprojection_test[] = new \rdfa\Projection( $this, $subject, $template);
927 $debugmessage .= "$subject\n";
928 }
929
930 // determine which projections have to be filtered out
931 $aFilteredSubjects = array();
932 foreach ($aprojection_test as $projection) {
933 $subject = $projection->getSubject();
934 foreach ($query as $property => $value) {
935 $avalues = $projection->getAll( $property);
936 if ($avalues == false) {
937 // filter this projection: property not found
938 $aFilteredSubjects[ $subject] = "Property $property not found";
939 break;
940 } else {
941 if (array_search( $value, $avalues, true) === false) {
942 // filter this projection: specific value not found
943 $aFilteredSubjects[ $subject] = "Property $property does not have value: $value";
944 break;
945 }
946 }
947 }
948 }
949 $count = count( $aFilteredSubjects);
950 if ($count == 0) {
951 $debugmessage = "No projections filtered\n";
952 } else {
953 $debugmessage = "Filtering $count projections\n";
954 foreach ( $aFilteredSubjects as $subject => $reason) {
955 $debugmessage .= "$subject: $reason\n";
956 }
957 }
958
959 if ($fLogMessages) $this->debugger->sendMessage( "$debugmessage",
960 self::debugcontext);
961
962 // take over unfiltered projections
963 $aprojection = array();
964 foreach ($aprojection_test as $projection) {
965 if (array_key_exists( $projection->getSubject(), $aFilteredSubjects) === false) {
966 $aprojection[] = $projection;
967 } else {
968 unset( $projection);
969 }
970 }
971
972 // create log output
973 $count = count( $aprojection);
974 $debugmessage = "Returning $count projections \n";
975 foreach ($aprojection as $projection) {
976 $debugmessage .= "{$projection->getSubject()}\n";
977 }
978 if ($fLogMessages) $this->debugger->sendMessage( "$debugmessage",
979 self::debugcontext);
980 return $aprojection;
981
982 } // public function query
983
984 /**@} */ /***************** DOXYGEN GROUP ENDS - Projection APIs */
985
986 /**
987 * Returns a serialization of the triple data.
988 *
989 * \param type Supported RDF serialization MIME Media Types according to http://www.iana.org/assignments/media-types/index.html
990 *
991 * Currently supported mime type identifiers are:
992 *
993 * - application/rdf+xml
994 * - application/rdfxml
995 * - text/turtle
996 * - application/x-turtle
997 * - text/n3
998 * - application/json
999 *
1000 * In addition to those, the internal type identifiers of this library can be used as well:
1001 * - rdfxml
1002 * - turtle
1003 * - n3
1004 * - json
1005 *
1006 * <strong>NOTE: This method is a library specific extension to the RDF API and RDFa API.</strong>
1007 */
1008 public function _serialize( $type ) {
1009 // set the supported types and shortcut them to the ones we use in there
1010 $validTypes = array( 'application/rdf+xml' => 'rdfxml' ,
1011 'application/rdfxml' => 'rdfxml',
1012 'text/turtle' => 'turtle',
1013 'application/x-turtle' => 'turtle',
1014 'text/n3' => 'n3',
1015 'application/json' => 'json');
1016
1017 // check if explicit mime type is specified
1018 if (isset( $validTypes[ $type])) {
1019 $type = $validTypes[ $type];
1020 } else {
1021 // check if internal type is given
1022 $internalTypes = array_unique( array_flip( $validTypes));
1023 if (!isset( $internalTypes[ $type]))
1024 return false;
1025 }
1026
1027 switch ($type) {
1028
1029 case 'rdfxml':
1030 $ser = \ARC2::getRDFXMLSerializer();
1031 break;
1032
1033 case 'turtle':
1034 $ser = \ARC2::getTurtleSerializer();
1035 break;
1036
1037 case 'n3':
1038 $ser = \ARC2::getNTriplesSerializer();
1039 break;
1040
1041 case 'json':
1042 $ser = \ARC2::getRDFJSONSerializer();
1043 break;
1044
1045 } // switch ($type)
1046
1047 return $ser->getSerializedTriples( $this->aTriples);
1048
1049 } // public function _serialize
1050
1051} // class Data
1052
1053?>
Note: See TracBrowser for help on using the repository browser.