8 * Copyright (c) 2009-2013 Nicholas J Humfrey. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
17 * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
18 * promote products derived from this software without specific prior
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 * @copyright Copyright (c) 2009-2013 Nicholas J Humfrey
35 * @license http://www.opensource.org/licenses/bsd-license.php
39 * Class the represents an RDF file format.
41 * For each format, the name, label, URIs and associated MIME Types are
42 * stored. A single parser and serialiser can also be registered to each
46 * @copyright Copyright (c) 2009-2013 Nicholas J Humfrey
47 * @license http://www.opensource.org/licenses/bsd-license.php
51 private static $formats = array();
53 private $name = array();
54 private $label = null;
56 private $mimeTypes = array();
57 private $extensions = array();
58 private $parserClass = null;
59 private $serialiserClass = null;
61 /** Get a list of format names
63 * @return array An array of formats name
65 public static function getNames()
67 return array_keys(self::$formats);
70 /** Get a list of all the registered formats
72 * @return array An array of format objects
74 public static function getFormats()
76 return self::$formats;
79 /** Generates an HTTP Accept header string
81 * The string will contain all of the MIME Types that we
84 * It is also possible to specify additional MIME types
85 * in the form array('text/plain' => 0.5) where 0.5 is the
86 * q value for that type. The types are sorted by q value
87 * before constructing the string.
89 * @param array $extraTypes extra MIME types to add
90 * @return string list of supported MIME types
92 public static function getHttpAcceptHeader($extraTypes = array())
94 $accept = $extraTypes;
95 foreach (self::$formats as $format) {
96 if ($format->parserClass and count($format->mimeTypes) > 0) {
97 $accept = array_merge($accept, $format->mimeTypes);
100 arsort($accept, SORT_NUMERIC);
103 foreach ($accept as $type => $q) {
110 $acceptStr .= sprintf("%s;q=%1.1F", $type, $q);
116 /** Check if a named graph exists
118 * @param string $name the name of the format
119 * @return boolean true if the format exists
121 public static function formatExists($name)
123 return array_key_exists($name, self::$formats);
126 /** Get a EasyRdf_Format from a name, uri or mime type
128 * @param string $query a query string to search for
129 * @return object the first EasyRdf_Format that matches the query
130 * @throws EasyRdf_Exception if no format is found
132 public static function getFormat($query)
134 if (!is_string($query) or $query == null or $query == '') {
135 throw new InvalidArgumentException(
136 "\$query should be a string and cannot be null or empty"
140 foreach (self::$formats as $format) {
141 if ($query == $format->name or
142 $query == $format->uri or
143 array_key_exists($query, $format->mimeTypes) or
144 in_array($query, $format->extensions)) {
150 throw new EasyRdf_Exception(
151 "Format is not recognised: $query"
155 /** Register a new format
157 * @param string $name The name of the format (e.g. ntriples)
158 * @param string $label The label for the format (e.g. N-Triples)
159 * @param string $uri The URI for the format
160 * @param string $mimeTypes One or more mime types for the format
161 * @param string $extensions One or more extensions (file suffix)
162 * @return object The new EasyRdf_Format object
164 public static function register(
168 $mimeTypes = array(),
169 $extensions = array()
171 if (!is_string($name) or $name == null or $name == '') {
172 throw new InvalidArgumentException(
173 "\$name should be a string and cannot be null or empty"
177 if (!array_key_exists($name, self::$formats)) {
178 self::$formats[$name] = new EasyRdf_Format($name);
181 self::$formats[$name]->setLabel($label);
182 self::$formats[$name]->setUri($uri);
183 self::$formats[$name]->setMimeTypes($mimeTypes);
184 self::$formats[$name]->setExtensions($extensions);
185 return self::$formats[$name];
188 /** Remove a format from the registry
190 * @param string $name The name of the format (e.g. ntriples)
192 public static function unregister($name)
194 unset(self::$formats[$name]);
197 /** Class method to register a parser class to a format name
199 * @param string $name The name of the format (e.g. ntriples)
200 * @param string $class The name of the class (e.g. EasyRdf_Parser_Ntriples)
202 public static function registerParser($name, $class)
204 if (!self::formatExists($name)) {
205 self::register($name);
207 self::getFormat($name)->setParserClass($class);
210 /** Class method to register a serialiser class to a format name
212 * @param string $name The name of the format (e.g. ntriples)
213 * @param string $class The name of the class (e.g. EasyRdf_Serialiser_Ntriples)
215 public static function registerSerialiser($name, $class)
217 if (!self::formatExists($name)) {
218 self::register($name);
220 self::getFormat($name)->setSerialiserClass($class);
223 /** Attempt to guess the document format from some content.
225 * If $filename is given, then the suffix is first used to guess the format.
227 * If the document format is not recognised, null is returned.
229 * @param string $data The document data
230 * @param string $filename Optional filename
231 * @return object EasyRdf_Format The format object
233 public static function guessFormat($data, $filename = null)
235 if (is_array($data)) {
236 # Data has already been parsed into RDF/PHP
237 return self::getFormat('php');
240 // First try and identify by the filename
241 if ($filename and preg_match('/\.(\w+)$/', $filename, $matches)) {
242 foreach (self::$formats as $format) {
243 if (in_array($matches[1], $format->extensions)) {
249 // Then try and guess by the first 1024 bytes of content
250 $short = substr($data, 0, 1024);
251 if (preg_match('/^\s*\{/', $short)) {
252 return self::getFormat('json');
253 } elseif (preg_match('/<rdf:/i', $short)) {
254 return self::getFormat('rdfxml');
255 } elseif (preg_match('|http://www.w3.org/2005/sparql-results|', $short)) {
256 return self::getFormat('sparql-xml');
257 } elseif (preg_match('/\WRDFa\W/i', $short)) {
258 return self::getFormat('rdfa');
259 } elseif (preg_match('/<!DOCTYPE html|<html/i', $short)) {
260 # We don't support any other microformats embedded in HTML
261 return self::getFormat('rdfa');
262 } elseif (preg_match('/@prefix\s|@base\s/', $short)) {
263 return self::getFormat('turtle');
264 } elseif (preg_match('/^\s*<.+> <.+>/m', $short)) {
265 return self::getFormat('ntriples');
272 * This constructor is for internal use only.
273 * To create a new format, use the register method.
275 * @param string $name The name of the format
276 * @see EasyRdf_Format::register()
279 public function __construct($name)
282 $this->label = $name; # Only a default
285 /** Get the name of a format object
287 * @return string The name of the format (e.g. rdfxml)
289 public function getName()
294 /** Get the label for a format object
296 * @return string The format label (e.g. RDF/XML)
298 public function getLabel()
303 /** Set the label for a format object
305 * @param string $label The new label for the format
307 public function setLabel($label)
310 if (!is_string($label)) {
311 throw new InvalidArgumentException(
312 "\$label should be a string"
315 return $this->label = $label;
317 return $this->label = null;
321 /** Get the URI for a format object
323 * @return string The format URI
325 public function getUri()
330 /** Set the URI for a format object
332 * @param string $uri The new URI for the format
334 public function setUri($uri)
337 if (!is_string($uri)) {
338 throw new InvalidArgumentException(
339 "\$uri should be a string"
342 return $this->uri = $uri;
344 return $this->uri = null;
348 /** Get the default registered mime type for a format object
350 * @return string The default mime type as a string.
352 public function getDefaultMimeType()
354 $types = array_keys($this->mimeTypes);
355 if (isset($types[0])) {
360 /** Get all the registered mime types for a format object
362 * @return array One or more MIME types in an array with
363 * the mime type as the key and q value as the value
365 public function getMimeTypes()
367 return $this->mimeTypes;
370 /** Set the MIME Types for a format object
372 * @param array $mimeTypes One or more mime types
374 public function setMimeTypes($mimeTypes)
377 if (!is_array($mimeTypes)) {
378 $mimeTypes = array($mimeTypes);
380 $this->mimeTypes = $mimeTypes;
382 $this->mimeTypes = array();
386 /** Get the default registered file extension (filename suffix) for a format object
388 * @return string The default extension as a string.
390 public function getDefaultExtension()
392 if (isset($this->extensions[0])) {
393 return $this->extensions[0];
397 /** Get all the registered file extensions (filename suffix) for a format object
399 * @return array One or more extensions as an array
401 public function getExtensions()
403 return $this->extensions;
406 /** Set the file format extensions (filename suffix) for a format object
408 * @param mixed $extensions One or more file extensions
410 public function setExtensions($extensions)
413 if (!is_array($extensions)) {
414 $extensions = array($extensions);
416 $this->extensions = $extensions;
418 $this->extensions = array();
422 /** Set the parser to use for a format
424 * @param string $class The name of the class
426 public function setParserClass($class)
429 if (!is_string($class)) {
430 throw new InvalidArgumentException(
431 "\$class should be a string"
434 $this->parserClass = $class;
436 $this->parserClass = null;
440 /** Get the name of the class to use to parse the format
442 * @return string The name of the class
444 public function getParserClass()
446 return $this->parserClass;
449 /** Create a new parser to parse this format
451 * @return object The new parser object
453 public function newParser()
455 $parserClass = $this->parserClass;
457 throw new EasyRdf_Exception(
458 "No parser class available for format: ".$this->getName()
461 return (new $parserClass());
464 /** Set the serialiser to use for a format
466 * @param string $class The name of the class
468 public function setSerialiserClass($class)
471 if (!is_string($class)) {
472 throw new InvalidArgumentException(
473 "\$class should be a string"
476 $this->serialiserClass = $class;
478 $this->serialiserClass = null;
482 /** Get the name of the class to use to serialise the format
484 * @return string The name of the class
486 public function getSerialiserClass()
488 return $this->serialiserClass;
491 /** Create a new serialiser to parse this format
493 * @return object The new serialiser object
495 public function newSerialiser()
497 $serialiserClass = $this->serialiserClass;
498 if (!$serialiserClass) {
499 throw new EasyRdf_Exception(
500 "No serialiser class available for format: ".$this->getName()
503 return (new $serialiserClass());
506 /** Magic method to return the name of the format when casted to string
508 * @return string The name of the format
510 public function __toString()
518 Register default set of supported formats
519 NOTE: they are ordered by preference
522 EasyRdf_Format::register(
525 'http://n2.talis.com/wiki/RDF_PHP_Specification',
527 'application/x-httpd-php-source' => 1.0
532 EasyRdf_Format::register(
534 'RDF/JSON Resource-Centric',
535 'http://n2.talis.com/wiki/RDF_JSON_Specification',
537 'application/json' => 1.0,
539 'application/rdf+json' => 0.9
544 EasyRdf_Format::register(
547 'http://www.w3.org/TR/json-ld/',
549 'application/ld+json' => 1.0
554 EasyRdf_Format::register(
557 'http://www.w3.org/TR/n-triples/',
559 'application/n-triples' => 1.0,
561 'text/ntriples' => 0.9,
562 'application/ntriples' => 0.9,
563 'application/x-ntriples' => 0.9
568 EasyRdf_Format::register(
570 'Turtle Terse RDF Triple Language',
571 'http://www.dajobe.org/2004/01/turtle',
573 'text/turtle' => 0.8,
574 'application/turtle' => 0.7,
575 'application/x-turtle' => 0.7
580 EasyRdf_Format::register(
583 'http://www.w3.org/TR/rdf-syntax-grammar',
585 'application/rdf+xml' => 0.8
590 EasyRdf_Format::register(
593 'http://www.graphviz.org/doc/info/lang.html',
595 'text/vnd.graphviz' => 0.8
600 EasyRdf_Format::register(
605 EasyRdf_Format::register(
608 'http://www.w3.org/2000/10/swap/grammar/n3#',
616 EasyRdf_Format::register(
619 'http://www.w3.org/TR/rdfa-core/',
622 'application/xhtml+xml' => 0.4
627 EasyRdf_Format::register(
629 'SPARQL XML Query Results',
630 'http://www.w3.org/TR/rdf-sparql-XMLres/',
632 'application/sparql-results+xml' => 1.0
636 EasyRdf_Format::register(
638 'SPARQL JSON Query Results',
639 'http://www.w3.org/TR/rdf-sparql-json-res/',
641 'application/sparql-results+json' => 1.0
645 EasyRdf_Format::register(
647 'Portable Network Graphics (PNG)',
648 'http://www.w3.org/TR/PNG/',
655 EasyRdf_Format::register(
657 'Graphics Interchange Format (GIF)',
658 'http://www.w3.org/Graphics/GIF/spec-gif89a.txt',
665 EasyRdf_Format::register(
667 'Scalable Vector Graphics (SVG)',
668 'http://www.w3.org/TR/SVG/',
670 'image/svg+xml' => 0.3
677 Register default set of parsers and serialisers
680 EasyRdf_Format::registerParser('json', 'EasyRdf_Parser_Json');
681 EasyRdf_Format::registerParser('jsonld', 'EasyRdf_Parser_JsonLd');
682 EasyRdf_Format::registerParser('ntriples', 'EasyRdf_Parser_Ntriples');
683 EasyRdf_Format::registerParser('php', 'EasyRdf_Parser_RdfPhp');
684 EasyRdf_Format::registerParser('rdfxml', 'EasyRdf_Parser_RdfXml');
685 EasyRdf_Format::registerParser('turtle', 'EasyRdf_Parser_Turtle');
686 EasyRdf_Format::registerParser('rdfa', 'EasyRdf_Parser_Rdfa');
688 EasyRdf_Format::registerSerialiser('json', 'EasyRdf_Serialiser_Json');
689 EasyRdf_Format::registerSerialiser('jsonld', 'EasyRdf_Serialiser_JsonLd');
690 EasyRdf_Format::registerSerialiser('n3', 'EasyRdf_Serialiser_Turtle');
691 EasyRdf_Format::registerSerialiser('ntriples', 'EasyRdf_Serialiser_Ntriples');
692 EasyRdf_Format::registerSerialiser('php', 'EasyRdf_Serialiser_RdfPhp');
693 EasyRdf_Format::registerSerialiser('rdfxml', 'EasyRdf_Serialiser_RdfXml');
694 EasyRdf_Format::registerSerialiser('turtle', 'EasyRdf_Serialiser_Turtle');
696 EasyRdf_Format::registerSerialiser('dot', 'EasyRdf_Serialiser_GraphViz');
697 EasyRdf_Format::registerSerialiser('gif', 'EasyRdf_Serialiser_GraphViz');
698 EasyRdf_Format::registerSerialiser('png', 'EasyRdf_Serialiser_GraphViz');
699 EasyRdf_Format::registerSerialiser('svg', 'EasyRdf_Serialiser_GraphViz');