From 9ad506423508c44d733ff6a7fcd81e3d267b317d Mon Sep 17 00:00:00 2001
From: webchick <webchick@24967.no-reply.drupal.org>
Date: Fri, 11 Jan 2013 09:42:26 -0800
Subject: [PATCH] Issue #1866858 by linclark, scor: Test RDFa by parsing RDFa
 (add the easyrdf library).

---
 core/composer.json                            |    3 +-
 core/composer.lock                            |   33 +
 core/vendor/composer/autoload_namespaces.php  |    1 +
 core/vendor/njh/easyrdf/lib/EasyRdf.php       |  225 +++
 .../njh/easyrdf/lib/EasyRdf/Exception.php     |   51 +
 .../vendor/njh/easyrdf/lib/EasyRdf/Format.php |  679 +++++++
 core/vendor/njh/easyrdf/lib/EasyRdf/Graph.php | 1627 +++++++++++++++++
 .../njh/easyrdf/lib/EasyRdf/GraphStore.php    |  217 +++
 core/vendor/njh/easyrdf/lib/EasyRdf/Http.php  |   83 +
 .../njh/easyrdf/lib/EasyRdf/Http/Client.php   |  549 ++++++
 .../njh/easyrdf/lib/EasyRdf/Http/Response.php |  361 ++++
 .../njh/easyrdf/lib/EasyRdf/Literal.php       |  315 ++++
 .../easyrdf/lib/EasyRdf/Literal/Boolean.php   |   96 +
 .../njh/easyrdf/lib/EasyRdf/Literal/Date.php  |  134 ++
 .../easyrdf/lib/EasyRdf/Literal/DateTime.php  |  114 ++
 .../easyrdf/lib/EasyRdf/Literal/Decimal.php   |   71 +
 .../njh/easyrdf/lib/EasyRdf/Literal/HTML.php  |   73 +
 .../easyrdf/lib/EasyRdf/Literal/HexBinary.php |   92 +
 .../easyrdf/lib/EasyRdf/Literal/Integer.php   |   71 +
 .../njh/easyrdf/lib/EasyRdf/Literal/XML.php   |   74 +
 .../njh/easyrdf/lib/EasyRdf/Namespace.php     |  349 ++++
 .../njh/easyrdf/lib/EasyRdf/ParsedUri.php     |  341 ++++
 .../vendor/njh/easyrdf/lib/EasyRdf/Parser.php |  150 ++
 .../njh/easyrdf/lib/EasyRdf/Parser/Arc.php    |   97 +
 .../njh/easyrdf/lib/EasyRdf/Parser/Json.php   |  156 ++
 .../easyrdf/lib/EasyRdf/Parser/Ntriples.php   |  199 ++
 .../njh/easyrdf/lib/EasyRdf/Parser/Rapper.php |  103 ++
 .../njh/easyrdf/lib/EasyRdf/Parser/RdfPhp.php |  100 +
 .../njh/easyrdf/lib/EasyRdf/Parser/RdfXml.php |  807 ++++++++
 .../njh/easyrdf/lib/EasyRdf/Parser/Rdfa.php   |  710 +++++++
 .../easyrdf/lib/EasyRdf/Parser/Redland.php    |  247 +++
 .../njh/easyrdf/lib/EasyRdf/Parser/Turtle.php | 1134 ++++++++++++
 .../njh/easyrdf/lib/EasyRdf/Resource.php      |  692 +++++++
 .../njh/easyrdf/lib/EasyRdf/Serialiser.php    |  115 ++
 .../easyrdf/lib/EasyRdf/Serialiser/Arc.php    |   97 +
 .../lib/EasyRdf/Serialiser/GraphViz.php       |  391 ++++
 .../easyrdf/lib/EasyRdf/Serialiser/Json.php   |   70 +
 .../lib/EasyRdf/Serialiser/Ntriples.php       |  209 +++
 .../easyrdf/lib/EasyRdf/Serialiser/Rapper.php |  100 +
 .../easyrdf/lib/EasyRdf/Serialiser/RdfPhp.php |   71 +
 .../easyrdf/lib/EasyRdf/Serialiser/RdfXml.php |  218 +++
 .../easyrdf/lib/EasyRdf/Serialiser/Turtle.php |  266 +++
 .../njh/easyrdf/lib/EasyRdf/Sparql/Client.php |  134 ++
 .../njh/easyrdf/lib/EasyRdf/Sparql/Result.php |  381 ++++
 .../njh/easyrdf/lib/EasyRdf/TypeMapper.php    |  116 ++
 core/vendor/njh/easyrdf/lib/EasyRdf/Utils.php |  276 +++
 46 files changed, 12397 insertions(+), 1 deletion(-)
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Exception.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Format.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Graph.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/GraphStore.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Http.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Http/Client.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Http/Response.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Boolean.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Date.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal/DateTime.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Decimal.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal/HTML.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal/HexBinary.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Integer.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Literal/XML.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Namespace.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/ParsedUri.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Arc.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Json.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Ntriples.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Rapper.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/RdfPhp.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/RdfXml.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Rdfa.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Redland.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Turtle.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Resource.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Arc.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/GraphViz.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Json.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Ntriples.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Rapper.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/RdfPhp.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/RdfXml.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Turtle.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Sparql/Client.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Sparql/Result.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/TypeMapper.php
 create mode 100644 core/vendor/njh/easyrdf/lib/EasyRdf/Utils.php

diff --git a/core/composer.json b/core/composer.json
index 26030b061ede..ab2dc0e3a400 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -15,7 +15,8 @@
     "doctrine/common": "2.3.*@stable",
     "guzzle/http": "*",
     "kriswallsmith/assetic": "1.1.*@alpha",
-    "symfony-cmf/routing": "1.0.*@dev"
+    "symfony-cmf/routing": "1.0.*@dev",
+    "njh/easyrdf": "0.8.*"
   },
   "minimum-stability": "dev"
 }
diff --git a/core/composer.lock b/core/composer.lock
index 9ca06b566793..07d030c8a3ba 100644
--- a/core/composer.lock
+++ b/core/composer.lock
@@ -359,6 +359,39 @@
                 "routing"
             ]
         },
+        {
+            "name": "njh/easyrdf",
+            "description": "EasyRdf is a PHP library designed to make it easy to consume and produce RDF.",
+            "version": "0.8.0",
+            "type": "library",
+            "keywords": ["RDF", "Semantic Web", "Turtle", "RDFa"],
+            "homepage": "http://www.aelius.com/njh/easyrdf/",
+            "license": "BSD-3-Clause",
+            "authors": [
+                {
+                    "name": "Nicholas Humfrey",
+                    "email": "njh@aelius.com",
+                    "homepage": "http://www.aelius.com/njh/",
+                    "role": "Developer"
+                }
+            ],
+            "support": {
+                "forum": "http://groups.google.com/group/easyrdf/",
+                "issues": "http://github.com/njh/easyrdf/issues"
+            },
+            "require": {
+                "php": ">=5.2.8"
+            },
+            "repositories": [
+                {
+                    "type": "vcs",
+                    "url": "https://github.com/njh/easyrdf"
+                }
+            ],
+            "autoload": {
+                "psr-0": { "EasyRdf": "lib/" }
+            }
+        },
         {
             "name": "symfony/class-loader",
             "version": "dev-master",
diff --git a/core/vendor/composer/autoload_namespaces.php b/core/vendor/composer/autoload_namespaces.php
index ecb4b198634e..4fa7f515bd96 100644
--- a/core/vendor/composer/autoload_namespaces.php
+++ b/core/vendor/composer/autoload_namespaces.php
@@ -23,4 +23,5 @@
     'Guzzle\\Common' => $vendorDir . '/guzzle/common/',
     'Doctrine\\Common' => $vendorDir . '/doctrine/common/lib/',
     'Assetic' => $vendorDir . '/kriswallsmith/assetic/src/',
+    'EasyRdf_' => $vendorDir . '/njh/easyrdf/lib/',
 );
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf.php b/core/vendor/njh/easyrdf/lib/EasyRdf.php
new file mode 100644
index 000000000000..2aaae30d9f78
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf.php
@@ -0,0 +1,225 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * Use this file to load the core of EasyRdf, if you don't have an autoloader.
+ *
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2011 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2011 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * @see EasyRdf_Exception
+ */
+require_once "EasyRdf/Exception.php";
+
+/**
+ * @see EasyRdf_Format
+ */
+require_once "EasyRdf/Format.php";
+
+/**
+ * @see EasyRdf_Graph
+ */
+require_once "EasyRdf/Graph.php";
+
+/**
+ * @see EasyRdf_GraphStore
+ */
+require_once "EasyRdf/GraphStore.php";
+
+/**
+ * @see EasyRdf_Http
+ */
+require_once "EasyRdf/Http.php";
+
+/**
+ * @see EasyRdf_Http_Client
+ */
+require_once "EasyRdf/Http/Client.php";
+
+/**
+ * @see EasyRdf_Http_Response
+ */
+require_once "EasyRdf/Http/Response.php";
+
+/**
+ * @see EasyRdf_Namespace
+ */
+require_once "EasyRdf/Namespace.php";
+
+/**
+ * @see EasyRdf_Literal
+ */
+require_once "EasyRdf/Literal.php";
+
+/**
+ * @see EasyRdf_Literal_Boolean
+ */
+require_once "EasyRdf/Literal/Boolean.php";
+
+/**
+ * @see EasyRdf_Literal_Date
+ */
+require_once "EasyRdf/Literal/Date.php";
+
+/**
+ * @see EasyRdf_Literal_DateTime
+ */
+require_once "EasyRdf/Literal/DateTime.php";
+
+/**
+ * @see EasyRdf_Literal_Decimal
+ */
+require_once "EasyRdf/Literal/Decimal.php";
+
+/**
+ * @see EasyRdf_Literal_HexBinary
+ */
+require_once "EasyRdf/Literal/HexBinary.php";
+
+/**
+ * @see EasyRdf_Literal_HTML
+ */
+require_once "EasyRdf/Literal/HTML.php";
+
+/**
+ * @see EasyRdf_Literal_Integer
+ */
+require_once "EasyRdf/Literal/Integer.php";
+
+/**
+ * @see EasyRdf_Literal_XML
+ */
+require_once "EasyRdf/Literal/XML.php";
+
+/**
+ * @see EasyRdf_ParsedUri
+ */
+require_once "EasyRdf/ParsedUri.php";
+
+/**
+ * @see EasyRdf_Parser
+ */
+require_once "EasyRdf/Parser.php";
+
+/**
+ * @see EasyRdf_Parser_RdfPhp
+ */
+require_once "EasyRdf/Parser/RdfPhp.php";
+
+/**
+ * @see EasyRdf_Parser_Ntriples
+ */
+require_once "EasyRdf/Parser/Ntriples.php";
+
+/**
+ * @see EasyRdf_Parser_Json
+ */
+require_once "EasyRdf/Parser/Json.php";
+
+/**
+ * @see EasyRdf_Parser_Rdfa
+ */
+require_once "EasyRdf/Parser/Rdfa.php";
+
+/**
+ * @see EasyRdf_Parser_RdfXml
+ */
+require_once "EasyRdf/Parser/RdfXml.php";
+
+/**
+ * @see EasyRdf_Parser_Turtle
+ */
+require_once "EasyRdf/Parser/Turtle.php";
+
+/**
+ * @see EasyRdf_Resource
+ */
+require_once "EasyRdf/Resource.php";
+
+/**
+ * @see EasyRdf_Serialiser
+ */
+require_once "EasyRdf/Serialiser.php";
+
+/**
+ * @see EasyRdf_Serialiser_GraphViz
+ */
+require_once "EasyRdf/Serialiser/GraphViz.php";
+
+/**
+ * @see EasyRdf_Serialiser_RdfPhp
+ */
+require_once "EasyRdf/Serialiser/RdfPhp.php";
+
+/**
+ * @see EasyRdf_Serialiser_Ntriples
+ */
+require_once "EasyRdf/Serialiser/Ntriples.php";
+
+/**
+ * @see EasyRdf_Serialiser_Json
+ */
+require_once "EasyRdf/Serialiser/Json.php";
+
+/**
+ * @see EasyRdf_Serialiser_RdfXml
+ */
+require_once "EasyRdf/Serialiser/RdfXml.php";
+
+/**
+ * @see EasyRdf_Serialiser_Turtle
+ */
+require_once "EasyRdf/Serialiser/Turtle.php";
+
+/**
+ * @see EasyRdf_Sparql_Client
+ */
+require_once "EasyRdf/Sparql/Client.php";
+
+/**
+ * @see EasyRdf_Sparql_Result
+ */
+require_once "EasyRdf/Sparql/Result.php";
+
+/**
+ * @see EasyRdf_TypeMapper
+ */
+require_once "EasyRdf/TypeMapper.php";
+
+/**
+ * @see EasyRdf_Utils
+ */
+require_once "EasyRdf/Utils.php";
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Exception.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Exception.php
new file mode 100644
index 000000000000..71530cac2ce5
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Exception.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * EasyRdf Exception class
+ *
+ * All exceptions thrown by EasyRdf are an instance of this class.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Exception extends Exception
+{
+    // Comment to make PHP CodeSniffer happy
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Format.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Format.php
new file mode 100644
index 000000000000..f5bbd5a2a403
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Format.php
@@ -0,0 +1,679 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class the represents an RDF file format.
+ *
+ * For each format, the name, label, URIs and associated MIME Types are
+ * stored. A single parser and serialiser can also be registered to each
+ * format.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Format
+{
+    private static $formats = array();
+
+    private $name = array();
+    private $label = null;
+    private $uri = null;
+    private $mimeTypes = array();
+    private $extensions = array();
+    private $parserClass = null;
+    private $serialiserClass = null;
+
+    /** Get a list of format names
+     *
+     * @return array          An array of formats name
+     */
+    public static function getNames()
+    {
+        return array_keys(self::$formats);
+    }
+
+    /** Get a list of all the registered formats
+     *
+     * @return array          An array of format objects
+     */
+    public static function getFormats()
+    {
+        return self::$formats;
+    }
+
+    /** Generates an HTTP Accept header string
+     *
+     * The string will contain all of the MIME Types that we
+     * are able to parse.
+     *
+     * It is also possible to specify additional MIME types
+     * in the form array('text/plain' => 0.5) where 0.5 is the
+     * q value for that type. The types are sorted by q value
+     * before constructing the string.
+     *
+     * @param array $extraTypes    extra MIME types to add
+     * @return string              list of supported MIME types
+     */
+    public static function getHttpAcceptHeader($extraTypes = array())
+    {
+        $accept = $extraTypes;
+        foreach (self::$formats as $format) {
+            if ($format->parserClass and count($format->mimeTypes) > 0) {
+                $accept = array_merge($accept, $format->mimeTypes);
+            }
+        }
+        arsort($accept, SORT_NUMERIC);
+
+        $acceptStr='';
+        foreach ($accept as $type => $q) {
+            if ($acceptStr) {
+                $acceptStr .= ',';
+            }
+            if ($q == 1.0) {
+                $acceptStr .= $type;
+            } else {
+                $acceptStr .= sprintf("%s;q=%1.1f", $type, $q);
+            }
+        }
+        return $acceptStr;
+    }
+
+    /** Check if a named graph exists
+     *
+     * @param string $name    the name of the format
+     * @return boolean        true if the format exists
+     */
+    public static function formatExists($name)
+    {
+        return array_key_exists($name, self::$formats);
+    }
+
+    /** Get a EasyRdf_Format from a name, uri or mime type
+     *
+     * @param string $query   a query string to search for
+     * @return object         the first EasyRdf_Format that matches the query
+     * @throws EasyRdf_Exception  if no format is found
+     */
+    public static function getFormat($query)
+    {
+        if (!is_string($query) or $query == null or $query == '') {
+            throw new InvalidArgumentException(
+                "\$query should be a string and cannot be null or empty"
+            );
+        }
+
+        foreach (self::$formats as $format) {
+            if ($query == $format->name or
+                $query == $format->uri or
+                array_key_exists($query, $format->mimeTypes) or
+                in_array($query, $format->extensions)) {
+                return $format;
+            }
+        }
+
+        # No match
+        throw new EasyRdf_Exception(
+            "Format is not recognised: $query"
+        );
+    }
+
+    /** Register a new format
+     *
+     * @param  string  $name       The name of the format (e.g. ntriples)
+     * @param  string  $label      The label for the format (e.g. N-Triples)
+     * @param  string  $uri        The URI for the format
+     * @param  string  $mimeTypes  One or more mime types for the format
+     * @param  string  $extensions One or more extensions (file suffix)
+     * @return object              The new EasyRdf_Format object
+     */
+    public static function register(
+        $name,
+        $label = null,
+        $uri = null,
+        $mimeTypes = array(),
+        $extensions = array()
+    ) {
+        if (!is_string($name) or $name == null or $name == '') {
+            throw new InvalidArgumentException(
+                "\$name should be a string and cannot be null or empty"
+            );
+        }
+
+        if (!array_key_exists($name, self::$formats)) {
+            self::$formats[$name] = new EasyRdf_Format($name);
+        }
+
+        self::$formats[$name]->setLabel($label);
+        self::$formats[$name]->setUri($uri);
+        self::$formats[$name]->setMimeTypes($mimeTypes);
+        self::$formats[$name]->setExtensions($extensions);
+        return self::$formats[$name];
+    }
+
+    /** Remove a format from the registry
+     *
+     * @param  string  $name      The name of the format (e.g. ntriples)
+     */
+    public static function unregister($name)
+    {
+        unset(self::$formats[$name]);
+    }
+
+    /** Class method to register a parser class to a format name
+     *
+     * @param  string  $name   The name of the format (e.g. ntriples)
+     * @param  string  $class  The name of the class (e.g. EasyRdf_Parser_Ntriples)
+     */
+    public static function registerParser($name, $class)
+    {
+        if (!self::formatExists($name)) {
+            self::register($name);
+        }
+        self::getFormat($name)->setParserClass($class);
+    }
+
+    /** Class method to register a serialiser class to a format name
+     *
+     * @param  string  $name   The name of the format (e.g. ntriples)
+     * @param  string  $class  The name of the class (e.g. EasyRdf_Serialiser_Ntriples)
+     */
+    public static function registerSerialiser($name, $class)
+    {
+        if (!self::formatExists($name)) {
+            self::register($name);
+        }
+        self::getFormat($name)->setSerialiserClass($class);
+    }
+
+    /** Attempt to guess the document format from some content.
+     *
+     * If $filename is given, then the suffix is first used to guess the format.
+     *
+     * If the document format is not recognised, null is returned.
+     *
+     * @param  string $data     The document data
+     * @param  string $filename Optional filename
+     * @return object EasyRdf_Format The format object
+     */
+    public static function guessFormat($data, $filename = null)
+    {
+        if (is_array($data)) {
+            # Data has already been parsed into RDF/PHP
+            return self::getFormat('php');
+        }
+
+        // First try and identify by the filename
+        if ($filename and preg_match("/\.(\w+)$/", $filename, $matches)) {
+            foreach (self::$formats as $format) {
+                if (in_array($matches[1], $format->extensions)) {
+                    return $format;
+                }
+            }
+        }
+
+        // Then try and guess by the first 255 bytes of content
+        $short = substr($data, 0, 255);
+        if (preg_match("/^\s*\{/", $short)) {
+            return self::getFormat('json');
+        } elseif (preg_match("/<rdf:/i", $short)) {
+            return self::getFormat('rdfxml');
+        } elseif (preg_match("/@prefix\s|@base\s/", $short)) {
+            return self::getFormat('turtle');
+        } elseif (preg_match("/^\s*<.+> <.+>/m", $short)) {
+            return self::getFormat('ntriples');
+        } elseif (preg_match("|http://www.w3.org/2005/sparql-results|", $short)) {
+            return self::getFormat('sparql-xml');
+        } elseif (preg_match("/\WRDFa\W/i", $short)) {
+            return self::getFormat('rdfa');
+        } elseif (preg_match("/<!DOCTYPE html|<html/i", $short)) {
+            # We don't support any other microformats embedded in HTML
+            return self::getFormat('rdfa');
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * This constructor is for internal use only.
+     * To create a new format, use the register method.
+     *
+     * @param  string  $name    The name of the format
+     * @see    EasyRdf_Format::register()
+     * @ignore
+     */
+    public function __construct($name)
+    {
+        $this->name = $name;
+        $this->label = $name;  # Only a default
+    }
+
+    /** Get the name of a format object
+     *
+     * @return string The name of the format (e.g. rdfxml)
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /** Get the label for a format object
+     *
+     * @return string The format label (e.g. RDF/XML)
+     */
+    public function getLabel()
+    {
+        return $this->label;
+    }
+
+    /** Set the label for a format object
+     *
+     * @param  string $label  The new label for the format
+     */
+    public function setLabel($label)
+    {
+        if ($label) {
+            if (!is_string($label)) {
+                throw new InvalidArgumentException(
+                    "\$label should be a string"
+                );
+            }
+            return $this->label = $label;
+        } else {
+            return $this->label = null;
+        }
+    }
+
+    /** Get the URI for a format object
+     *
+     * @return string The format URI
+     */
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
+    /** Set the URI for a format object
+     *
+     * @param string $uri  The new URI for the format
+     */
+    public function setUri($uri)
+    {
+        if ($uri) {
+            if (!is_string($uri)) {
+                throw new InvalidArgumentException(
+                    "\$uri should be a string"
+                );
+            }
+            return $this->uri = $uri;
+        } else {
+            return $this->uri = null;
+        }
+    }
+
+    /** Get the default registered mime type for a format object
+     *
+     * @return string The default mime type as a string.
+     */
+    public function getDefaultMimeType()
+    {
+        $types = array_keys($this->mimeTypes);
+        return $types[0];
+    }
+
+    /** Get all the registered mime types for a format object
+     *
+     * @return array One or more MIME types in an array with
+     *               the mime type as the key and q value as the value
+     */
+    public function getMimeTypes()
+    {
+        return $this->mimeTypes;
+    }
+
+    /** Set the MIME Types for a format object
+     *
+     * @param array $mimeTypes  One or more mime types
+     */
+    public function setMimeTypes($mimeTypes)
+    {
+        if ($mimeTypes) {
+            if (!is_array($mimeTypes)) {
+                $mimeTypes = array($mimeTypes);
+            }
+            $this->mimeTypes = $mimeTypes;
+        } else {
+            $this->mimeTypes = array();
+        }
+    }
+
+    /** Get the default registered file extension (filename suffix) for a format object
+     *
+     * @return string The default extension as a string.
+     */
+    public function getDefaultExtension()
+    {
+        return $this->extensions[0];
+    }
+
+    /** Get all the registered file extensions (filename suffix) for a format object
+     *
+     * @return array One or more extensions as an array
+     */
+    public function getExtensions()
+    {
+        return $this->extensions;
+    }
+
+    /** Set the file format extensions (filename suffix) for a format object
+     *
+     * @param mixed $extensions  One or more file extensions
+     */
+    public function setExtensions($extensions)
+    {
+        if ($extensions) {
+            if (!is_array($extensions)) {
+                $extensions = array($extensions);
+            }
+            $this->extensions = $extensions;
+        } else {
+            $this->extensions = array();
+        }
+    }
+
+    /** Set the parser to use for a format
+     *
+     * @param string $class  The name of the class
+     */
+    public function setParserClass($class)
+    {
+        if ($class) {
+            if (!is_string($class)) {
+                throw new InvalidArgumentException(
+                    "\$class should be a string"
+                );
+            }
+            $this->parserClass = $class;
+        } else {
+            $this->parserClass = null;
+        }
+    }
+
+    /** Get the name of the class to use to parse the format
+     *
+     * @return string The name of the class
+     */
+    public function getParserClass()
+    {
+        return $this->parserClass;
+    }
+
+    /** Create a new parser to parse this format
+     *
+     * @return object The new parser object
+     */
+    public function newParser()
+    {
+        $parserClass = $this->parserClass;
+        if (!$parserClass) {
+            throw new EasyRdf_Exception(
+                "No parser class available for format: ".$this->getName()
+            );
+        }
+        return (new $parserClass());
+    }
+
+    /** Set the serialiser to use for a format
+     *
+     * @param string $class  The name of the class
+     */
+    public function setSerialiserClass($class)
+    {
+        if ($class) {
+            if (!is_string($class)) {
+                throw new InvalidArgumentException(
+                    "\$class should be a string"
+                );
+            }
+            $this->serialiserClass = $class;
+        } else {
+            $this->serialiserClass = null;
+        }
+    }
+
+    /** Get the name of the class to use to serialise the format
+     *
+     * @return string The name of the class
+     */
+    public function getSerialiserClass()
+    {
+        return $this->serialiserClass;
+    }
+
+    /** Create a new serialiser to parse this format
+     *
+     * @return object The new serialiser object
+     */
+    public function newSerialiser()
+    {
+        $serialiserClass = $this->serialiserClass;
+        if (!$serialiserClass) {
+            throw new EasyRdf_Exception(
+                "No serialiser class available for format: ".$this->getName()
+            );
+        }
+        return (new $serialiserClass());
+    }
+
+    /** Magic method to return the name of the format when casted to string
+     *
+     * @return string The name of the format
+     */
+    public function __toString()
+    {
+        return $this->name;
+    }
+}
+
+
+/*
+   Register default set of supported formats
+   NOTE: they are ordered by preference
+*/
+
+EasyRdf_Format::register(
+    'php',
+    'RDF/PHP',
+    'http://n2.talis.com/wiki/RDF_PHP_Specification'
+);
+
+EasyRdf_Format::register(
+    'json',
+    'RDF/JSON Resource-Centric',
+    'http://n2.talis.com/wiki/RDF_JSON_Specification',
+    array(
+        'application/json' => 1.0,
+        'text/json' => 0.9,
+        'application/rdf+json' => 0.9
+    ),
+    array('json')
+);
+
+EasyRdf_Format::register(
+    'ntriples',
+    'N-Triples',
+    'http://www.w3.org/TR/rdf-testcases/#ntriples',
+    array(
+        'text/plain' => 1.0,
+        'text/ntriples' => 0.9,
+        'application/ntriples' => 0.9,
+        'application/x-ntriples' => 0.9
+    ),
+    array('nt')
+);
+
+EasyRdf_Format::register(
+    'turtle',
+    'Turtle Terse RDF Triple Language',
+    'http://www.dajobe.org/2004/01/turtle',
+    array(
+        'text/turtle' => 0.8,
+        'application/turtle' => 0.7,
+        'application/x-turtle' => 0.7
+    ),
+    array('ttl')
+);
+
+EasyRdf_Format::register(
+    'rdfxml',
+    'RDF/XML',
+    'http://www.w3.org/TR/rdf-syntax-grammar',
+    array(
+        'application/rdf+xml' => 0.8
+    ),
+    array('rdf', 'xrdf')
+);
+
+EasyRdf_Format::register(
+    'dot',
+    'Graphviz',
+    'http://www.graphviz.org/doc/info/lang.html',
+    array(
+        'text/vnd.graphviz' => 0.8
+    ),
+    array('gv', 'dot')
+);
+
+EasyRdf_Format::register(
+    'json-triples',
+    'RDF/JSON Triples'
+);
+
+EasyRdf_Format::register(
+    'n3',
+    'Notation3',
+    'http://www.w3.org/2000/10/swap/grammar/n3#',
+    array(
+        'text/n3' => 0.5,
+        'text/rdf+n3' => 0.5
+    ),
+    array('n3')
+);
+
+EasyRdf_Format::register(
+    'rdfa',
+    'RDFa',
+    'http://www.w3.org/TR/rdfa-core/',
+    array(
+        'text/html' => 0.4,
+        'application/xhtml+xml' => 0.4
+    ),
+    array('html')
+);
+
+EasyRdf_Format::register(
+    'sparql-xml',
+    'SPARQL XML Query Results',
+    'http://www.w3.org/TR/rdf-sparql-XMLres/',
+    array(
+        'application/sparql-results+xml' => 1.0
+    )
+);
+
+EasyRdf_Format::register(
+    'sparql-json',
+    'SPARQL JSON Query Results',
+    'http://www.w3.org/TR/rdf-sparql-json-res/',
+    array(
+        'application/sparql-results+json' => 1.0
+    )
+);
+
+EasyRdf_Format::register(
+    'png',
+    'Portable Network Graphics (PNG)',
+    'http://www.w3.org/TR/PNG/',
+    array(
+        'image/png' => 0.3
+    ),
+    array('png')
+);
+
+EasyRdf_Format::register(
+    'gif',
+    'Graphics Interchange Format (GIF)',
+    'http://www.w3.org/Graphics/GIF/spec-gif89a.txt',
+    array(
+        'image/gif' => 0.2
+    ),
+    array('gif')
+);
+
+EasyRdf_Format::register(
+    'svg',
+    'Scalable Vector Graphics (SVG)',
+    'http://www.w3.org/TR/SVG/',
+    array(
+        'image/svg+xml' => 0.3
+    ),
+    array('svg')
+);
+
+
+/*
+   Register default set of parsers and serialisers
+*/
+
+EasyRdf_Format::registerParser('json', 'EasyRdf_Parser_Json');
+EasyRdf_Format::registerParser('ntriples', 'EasyRdf_Parser_Ntriples');
+EasyRdf_Format::registerParser('php', 'EasyRdf_Parser_RdfPhp');
+EasyRdf_Format::registerParser('rdfxml', 'EasyRdf_Parser_RdfXml');
+EasyRdf_Format::registerParser('turtle', 'EasyRdf_Parser_Turtle');
+EasyRdf_Format::registerParser('rdfa', 'EasyRdf_Parser_Rdfa');
+
+EasyRdf_Format::registerSerialiser('json', 'EasyRdf_Serialiser_Json');
+EasyRdf_Format::registerSerialiser('n3', 'EasyRdf_Serialiser_Turtle');
+EasyRdf_Format::registerSerialiser('ntriples', 'EasyRdf_Serialiser_Ntriples');
+EasyRdf_Format::registerSerialiser('php', 'EasyRdf_Serialiser_RdfPhp');
+EasyRdf_Format::registerSerialiser('rdfxml', 'EasyRdf_Serialiser_RdfXml');
+EasyRdf_Format::registerSerialiser('turtle', 'EasyRdf_Serialiser_Turtle');
+
+EasyRdf_Format::registerSerialiser('dot', 'EasyRdf_Serialiser_GraphViz');
+EasyRdf_Format::registerSerialiser('gif', 'EasyRdf_Serialiser_GraphViz');
+EasyRdf_Format::registerSerialiser('png', 'EasyRdf_Serialiser_GraphViz');
+EasyRdf_Format::registerSerialiser('svg', 'EasyRdf_Serialiser_GraphViz');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Graph.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Graph.php
new file mode 100644
index 000000000000..5bb3ab123fb1
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Graph.php
@@ -0,0 +1,1627 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Container for collection of EasyRdf_Resources.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Graph
+{
+    /** The URI of the graph */
+    private $uri = null;
+    private $parsedUri = null;
+
+    /** Array of resources contained in the graph */
+    private $resources = array();
+
+    private $index = array();
+    private $revIndex = array();
+
+    /** Counter for the number of bnodes */
+    private $bNodeCount = 0;
+
+    /** Array of URLs that have been loaded into the graph */
+    private $loaded = array();
+
+    private $maxRedirects = 10;
+
+
+    /**
+     * Constructor
+     *
+     * If no URI is given then an unnamed graph is created.
+     *
+     * The $data parameter is optional and will be parsed into
+     * the graph if given.
+     *
+     * The data format is optional and should be specified if it
+     * can't be guessed by EasyRdf.
+     *
+     * @param  string  $uri     The URI of the graph
+     * @param  string  $data    Data for the graph
+     * @param  string  $format  The document type of the data (e.g. rdfxml)
+     * @return object EasyRdf_Graph
+     */
+    public function __construct($uri = null, $data = null, $format = null)
+    {
+        $this->checkResourceParam($uri, true);
+
+        if ($uri) {
+            $this->uri = $uri;
+            $this->parsedUri = new EasyRdf_ParsedUri($uri);
+            if ($data) {
+                $this->parse($data, $format, $this->uri);
+            }
+        }
+    }
+
+    /**
+     * Create a new graph and load RDF data from a URI into it
+     *
+     * This static function is shorthand for:
+     *     $graph = new EasyRdf_Graph($uri);
+     *     $graph->load($uri, $format);
+     *
+     * The document type is optional but should be specified if it
+     * can't be guessed or got from the HTTP headers.
+     *
+     * @param  string  $uri     The URI of the data to load
+     * @param  string  $format  Optional format of the data (eg. rdfxml)
+     * @return object EasyRdf_Graph    The new the graph object
+     */
+    public static function newAndLoad($uri, $format = null)
+    {
+        $graph = new self($uri);
+        $graph->load($uri, $format);
+        return $graph;
+    }
+
+    /** Get or create a resource stored in a graph
+     *
+     * If the resource did not previously exist, then a new resource will
+     * be created. If you provide an RDF type and that type is registered
+     * with the EasyRdf_TypeMapper, then the resource will be an instance
+     * of the class registered.
+     *
+     * If URI is null, then the URI of the graph is used.
+     *
+     * @param  string  $uri    The URI of the resource
+     * @param  mixed   $types  RDF type of a new resource (e.g. foaf:Person)
+     * @return object EasyRdf_Resource
+     */
+    public function resource($uri = null, $types = array())
+    {
+        $this->checkResourceParam($uri, true);
+        if (!$uri) {
+            throw new InvalidArgumentException(
+                '$uri is null and EasyRdf_Graph object has no URI either.'
+            );
+        }
+
+        // Resolve relative URIs
+        if ($this->parsedUri) {
+            $uri = $this->parsedUri->resolve($uri)->toString();
+        }
+
+        // Add the types
+        $this->addType($uri, $types);
+
+        // Create resource object if it doesn't already exist
+        if (!isset($this->resources[$uri])) {
+            $resClass = $this->classForResource($uri);
+            $this->resources[$uri] = new $resClass($uri, $this);
+        }
+
+        return $this->resources[$uri];
+    }
+
+    /** Work out the class to instantiate a resource as
+     *  @ignore
+     */
+    protected function classForResource($uri)
+    {
+        $resClass = 'EasyRdf_Resource';
+        $rdfType = EasyRdf_Namespace::expand('rdf:type');
+        if (isset($this->index[$uri][$rdfType])) {
+            foreach ($this->index[$uri][$rdfType] as $type) {
+                if ($type['type'] == 'uri' or $type['type'] == 'bnode') {
+                    $class = EasyRdf_TypeMapper::get($type['value']);
+                    if ($class != null) {
+                        $resClass = $class;
+                        break;
+                    }
+                }
+
+            }
+        }
+        return $resClass;
+    }
+
+    /**
+     * Create a new blank node in the graph and return it.
+     *
+     * If you provide an RDF type and that type is registered
+     * with the EasyRdf_TypeMapper, then the resource will be an instance
+     * of the class registered.
+     *
+     * @param  mixed  $types  RDF type of a new blank node (e.g. foaf:Person)
+     * @return object EasyRdf_Resource The new blank node
+     */
+    public function newBNode($types = array())
+    {
+        return $this->resource($this->newBNodeId(), $types);
+    }
+
+    /**
+     * Create a new unique blank node identifier and return it.
+     *
+     * @return string The new blank node identifier (e.g. _:genid1)
+     */
+    public function newBNodeId()
+    {
+        return "_:genid".(++$this->bNodeCount);
+    }
+
+    /**
+     * Parse some RDF data into the graph object.
+     *
+     * @param  string  $data    Data to parse for the graph
+     * @param  string  $format  Optional format of the data
+     * @param  string  $uri     The URI of the data to load
+     * @return integer          The number of triples added to the graph
+     */
+    public function parse($data, $format = null, $uri = null)
+    {
+        $this->checkResourceParam($uri, true);
+
+        if (empty($format) or $format == 'guess') {
+            // Guess the format if it is Unknown
+            $format = EasyRdf_Format::guessFormat($data, $uri);
+        } else {
+            $format = EasyRdf_Format::getFormat($format);
+        }
+
+        if (!$format) {
+            throw new EasyRdf_Exception(
+                "Unable to parse data of an unknown format."
+            );
+        }
+
+        $parser = $format->newParser();
+        return $parser->parse($this, $data, $format, $uri);
+    }
+
+    /**
+     * Parse a file containing RDF data into the graph object.
+     *
+     * @param  string  $filename The path of the file to load
+     * @param  string  $format   Optional format of the file
+     * @param  string  $uri      The URI of the file to load
+     * @return integer           The number of triples added to the graph
+     */
+    public function parseFile($filename, $format = null, $uri = null)
+    {
+        if ($uri === null) {
+            $uri = "file://$filename";
+        }
+
+        return $this->parse(
+            file_get_contents($filename),
+            $format,
+            $uri
+        );
+    }
+
+    /**
+     * Load RDF data into the graph from a URI.
+     *
+     * If no URI is given, then the URI of the graph will be used.
+     *
+     * The document type is optional but should be specified if it
+     * can't be guessed or got from the HTTP headers.
+     *
+     * @param  string  $uri     The URI of the data to load
+     * @param  string  $format  Optional format of the data (eg. rdfxml)
+     * @return integer          The number of triples added to the graph
+     */
+    public function load($uri = null, $format = null)
+    {
+        $this->checkResourceParam($uri, true);
+
+        if (!$uri) {
+            throw new EasyRdf_Exception(
+                "No URI given to load() and the graph does not have a URI."
+            );
+        }
+
+        // Setup the HTTP client
+        $client = EasyRdf_Http::getDefaultHttpClient();
+        $client->resetParameters(true);
+        $client->setConfig(array('maxredirects' => 0));
+        $client->setMethod('GET');
+        $client->setHeaders('Accept', EasyRdf_Format::getHttpAcceptHeader());
+
+        $requestUrl = $uri;
+        $response = null;
+        $redirectCounter = 0;
+        do {
+            // Have we already loaded it into the graph?
+            $requestUrl = EasyRdf_Utils::removeFragmentFromUri($requestUrl);
+            if (in_array($requestUrl, $this->loaded)) {
+                return 0;
+            }
+
+            // Make the HTTP request
+            $client->setHeaders('host', null);
+            $client->setUri($requestUrl);
+            $response = $client->request();
+
+            // Add the URL to the list of URLs loaded
+            $this->loaded[] = $requestUrl;
+
+            if ($response->isRedirect() and $location = $response->getHeader('location')) {
+                // Avoid problems with buggy servers that add whitespace
+                $location = trim($location);
+
+                // Some servers return relative URLs in the location header
+                // resolve it in relation to previous request
+                $baseUri = new EasyRdf_ParsedUri($requestUrl);
+                $requestUrl = $baseUri->resolve($location)->toString();
+                $requestUrl = EasyRdf_Utils::removeFragmentFromUri($requestUrl);
+
+                // If it is a 303 then drop the parameters
+                if ($response->getStatus() == 303) {
+                    $client->resetParameters();
+                }
+
+                ++$redirectCounter;
+            } elseif ($response->isSuccessful()) {
+                // If we didn't get any location, stop redirecting
+                break;
+            } else {
+                throw new EasyRdf_Exception(
+                    "HTTP request for $requestUrl failed: ".$response->getMessage()
+                );
+            }
+        } while ($redirectCounter < $this->maxRedirects);
+
+        if (!$format or $format == 'guess') {
+            list($format, $params) = EasyRdf_Utils::parseMimeType(
+                $response->getHeader('Content-Type')
+            );
+        }
+
+        // Parse the data
+        return $this->parse($response->getBody(), $format, $uri);
+    }
+
+    /** Get an associative array of all the resources stored in the graph.
+     *  The keys of the array is the URI of the EasyRdf_Resource.
+     *
+     * @return array Array of EasyRdf_Resource
+     */
+    public function resources()
+    {
+        foreach ($this->index as $subject => $properties) {
+            $this->resource($subject);
+        }
+
+        foreach ($this->revIndex as $object => $properties) {
+            if (!isset($this->resources[$object])) {
+                $this->resource($object);
+            }
+        }
+
+        return $this->resources;
+    }
+
+    /** Get an arry of resources matching a certain property and optional value.
+     *
+     * For example this routine could be used as a way of getting
+     * everyone who has name:
+     * $people = $graph->resourcesMatching('foaf:name')
+     *
+     * Or everyone who is male:
+     * $people = $graph->resourcesMatching('foaf:gender', 'male');
+     *
+     * Or all homepages:
+     * $people = $graph->resourcesMatching('^foaf:homepage');
+     *
+     * @param  string  $property   The property to check.
+     * @param  mixed   $value      Optional, the value of the propery to check for.
+     * @return array   Array of EasyRdf_Resource
+     */
+    public function resourcesMatching($property, $value = null)
+    {
+        $this->checkSinglePropertyParam($property, $inverse);
+        $this->checkValueParam($value);
+
+        // Use the reverse index if it is an inverse property
+        if ($inverse) {
+            $index = &$this->revIndex;
+        } else {
+            $index = &$this->index;
+        }
+
+        $matched = array();
+        foreach ($index as $subject => $props) {
+            if (isset($index[$subject][$property])) {
+                if (isset($value)) {
+                    foreach ($this->index[$subject][$property] as $v) {
+                        if ($v['type'] == $value['type'] and
+                            $v['value'] == $value['value']) {
+                            $matched[] = $this->resource($subject);
+                            break;
+                        }
+                    }
+                } else {
+                    $matched[] = $this->resource($subject);
+                }
+            }
+        }
+        return $matched;
+    }
+
+    /** Get the URI of the graph
+     *
+     * @return string The URI of the graph
+     */
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
+    /** Check that a URI/resource parameter is valid, and convert it to a string
+     *  @ignore
+     */
+    protected function checkResourceParam(&$resource, $allowNull = false)
+    {
+        if ($allowNull == true) {
+            if ($resource === null) {
+                if ($this->uri) {
+                    $resource = $this->uri;
+                } else {
+                    return;
+                }
+            }
+        } elseif ($resource === null) {
+            throw new InvalidArgumentException(
+                "\$resource cannot be null"
+            );
+        }
+
+        if (is_object($resource) and $resource instanceof EasyRdf_Resource) {
+            $resource = $resource->getUri();
+        } elseif (is_object($resource) and $resource instanceof EasyRdf_ParsedUri) {
+            $resource = strval($resource);
+        } elseif (is_string($resource)) {
+            if ($resource == '') {
+                throw new InvalidArgumentException(
+                    "\$resource cannot be an empty string"
+                );
+            } elseif (preg_match("|^<(.+)>$|", $resource, $matches)) {
+                $resource = $matches[1];
+            } else {
+                $resource = EasyRdf_Namespace::expand($resource);
+            }
+        } else {
+            throw new InvalidArgumentException(
+                "\$resource should be a string or an EasyRdf_Resource"
+            );
+        }
+    }
+
+    /** Check that a single URI/property parameter (not a property path)
+     *  is valid, and expand it if required
+     *  @ignore
+     */
+    protected function checkSinglePropertyParam(&$property, &$inverse)
+    {
+        if (is_object($property) and $property instanceof EasyRdf_Resource) {
+            $property = $property->getUri();
+        } elseif (is_object($property) and $property instanceof EasyRdf_ParsedUri) {
+            $property = strval($property);
+        } elseif (is_string($property)) {
+            if ($property == '') {
+                throw new InvalidArgumentException(
+                    "\$property cannot be an empty string"
+                );
+            } elseif (substr($property, 0, 1) == '^') {
+                $inverse = true;
+                $property = EasyRdf_Namespace::expand(substr($property, 1));
+            } elseif (substr($property, 0, 2) == '_:') {
+                throw new InvalidArgumentException(
+                    "\$property cannot be a blank node"
+                );
+            } else {
+                $inverse = false;
+                $property = EasyRdf_Namespace::expand($property);
+            }
+        }
+
+        if ($property === null or !is_string($property)) {
+            throw new InvalidArgumentException(
+                "\$property should be a string or EasyRdf_Resource and cannot be null"
+            );
+        }
+    }
+
+    /** Check that a value parameter is valid, and convert it to an associative array if needed
+     *  @ignore
+     */
+    protected function checkValueParam(&$value)
+    {
+        if (isset($value)) {
+            if (is_object($value)) {
+                if (method_exists($value, 'toArray')) {
+                    $value = $value->toArray();
+                } else {
+                    throw new InvalidArgumentException(
+                        "\$value should respond to the method toArray()"
+                    );
+                }
+            } elseif (is_array($value)) {
+                if (!isset($value['type'])) {
+                    throw new InvalidArgumentException(
+                        "\$value is missing a 'type' key"
+                    );
+                }
+
+                if (!isset($value['value'])) {
+                    throw new InvalidArgumentException(
+                        "\$value is missing a 'value' key"
+                    );
+                }
+
+                // Fix ordering and remove unknown keys
+                $value = array(
+                    'type' => strval($value['type']),
+                    'value' => strval($value['value']),
+                    'lang' => isset($value['lang']) ? strval($value['lang']) : null,
+                    'datatype' => isset($value['datatype']) ? strval($value['datatype']) : null
+                );
+            } else {
+                $value = array(
+                    'type' => 'literal',
+                    'value' => strval($value),
+                    'datatype' => EasyRdf_Literal::getDatatypeForValue($value)
+                );
+            }
+            if (!in_array($value['type'], array('uri', 'bnode', 'literal'), true)) {
+                throw new InvalidArgumentException(
+                    "\$value does not have a valid type (".$value['type'].")"
+                );
+            }
+            if (empty($value['datatype'])) {
+                unset($value['datatype']);
+            }
+            if (empty($value['lang'])) {
+                unset($value['lang']);
+            }
+            if (isset($value['lang']) and isset($value['datatype'])) {
+                throw new InvalidArgumentException(
+                    "\$value cannot have both and language and a datatype"
+                );
+            }
+        }
+    }
+
+    /** Get a single value for a property of a resource
+     *
+     * If multiple values are set for a property then the value returned
+     * may be arbitrary.
+     *
+     * If $property is an array, then the first item in the array that matches
+     * a property that exists is returned.
+     *
+     * This method will return null if the property does not exist.
+     *
+     * @param  string    $resource       The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string    $propertyPath   A valid property path
+     * @param  string    $type           The type of value to filter by (e.g. literal or resource)
+     * @param  string    $lang           The language to filter by (e.g. en)
+     * @return mixed                     A value associated with the property
+     */
+    public function get($resource, $propertyPath, $type = null, $lang = null)
+    {
+        $this->checkResourceParam($resource);
+
+        if (is_object($propertyPath) and $propertyPath instanceof EasyRdf_Resource) {
+            return $this->getSingleProperty($resource, $propertyPath->getUri(), $type, $lang);
+        } elseif (is_string($propertyPath) and preg_match('|^(\^?)<(.+)>|', $propertyPath, $matches)) {
+            return $this->getSingleProperty($resource, "$matches[1]$matches[2]", $type, $lang);
+        } elseif ($propertyPath === null or !is_string($propertyPath)) {
+            throw new InvalidArgumentException(
+                "\$propertyPath should be a string or EasyRdf_Resource and cannot be null"
+            );
+        } elseif ($propertyPath === '') {
+            throw new InvalidArgumentException(
+                "\$propertyPath cannot be an empty string"
+            );
+        }
+
+        // Loop through each component in the path
+        foreach (explode('/', $propertyPath) as $part) {
+            // Stop if we come to a literal
+            if ($resource instanceof EasyRdf_Literal) {
+                return null;
+            }
+
+            // Try each of the alternative paths
+            foreach (explode('|', $part) as $p) {
+                $res = $this->getSingleProperty($resource, $p, $type, $lang);
+                if ($res) {
+                    break;
+                }
+            }
+
+            // Stop if nothing was found
+            $resource = $res;
+            if (!$resource) {
+                break;
+            }
+        }
+
+        return $resource;
+    }
+
+    /** Get a single value for a property of a resource
+     *
+     * @param  string    $resource The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string    $property The name of the property (e.g. foaf:name)
+     * @param  string    $type     The type of value to filter by (e.g. literal or resource)
+     * @param  string    $lang     The language to filter by (e.g. en)
+     * @return mixed               A value associated with the property
+     *
+     * @ignore
+     */
+    protected function getSingleProperty($resource, $property, $type = null, $lang = null)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+
+        // Get an array of values for the property
+        $values = $this->propertyValuesArray($resource, $property, $inverse);
+        if (!isset($values)) {
+            return null;
+        }
+
+        // Filter the results
+        $result = null;
+        if ($type) {
+            foreach ($values as $value) {
+                if ($type == 'literal' and $value['type'] == 'literal') {
+                    if ($lang == null or (isset($value['lang']) and $value['lang'] == $lang)) {
+                        $result = $value;
+                        break;
+                    }
+                } elseif ($type == 'resource') {
+                    if ($value['type'] == 'uri' or $value['type'] == 'bnode') {
+                        $result = $value;
+                        break;
+                    }
+                }
+            }
+        } else {
+            $result = $values[0];
+        }
+
+        // Convert the internal data structure into a PHP object
+        return $this->arrayToObject($result);
+    }
+
+    /** Get a single literal value for a property of a resource
+     *
+     * If multiple values are set for a property then the value returned
+     * may be arbitrary.
+     *
+     * This method will return null if there is not literal value for the
+     * property.
+     *
+     * @param  string       $resource The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string|array $property The name of the property (e.g. foaf:name)
+     * @param  string       $lang     The language to filter by (e.g. en)
+     * @return object EasyRdf_Literal Literal value associated with the property
+     */
+    public function getLiteral($resource, $property, $lang = null)
+    {
+        return $this->get($resource, $property, 'literal', $lang);
+    }
+
+    /** Get a single resource value for a property of a resource
+     *
+     * If multiple values are set for a property then the value returned
+     * may be arbitrary.
+     *
+     * This method will return null if there is not resource for the
+     * property.
+     *
+     * @param  string       $resource The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string|array $property The name of the property (e.g. foaf:name)
+     * @return object EasyRdf_Resource Resource associated with the property
+     */
+    public function getResource($resource, $property)
+    {
+        return $this->get($resource, $property, 'resource');
+    }
+
+    /** Return all the values for a particular property of a resource
+     *  @ignore
+     */
+    protected function propertyValuesArray($resource, $property, $inverse = false)
+    {
+        // Is an inverse property being requested?
+        if ($inverse) {
+            if (isset($this->revIndex[$resource])) {
+                $properties = &$this->revIndex[$resource];
+            }
+        } else {
+            if (isset($this->index[$resource])) {
+                $properties = &$this->index[$resource];
+            }
+        }
+
+        if (isset($properties[$property])) {
+            return $properties[$property];
+        } else {
+            return null;
+        }
+    }
+
+    /** Get an EasyRdf_Resource or EasyRdf_Literal object from an associative array.
+     *  @ignore
+     */
+    protected function arrayToObject($data)
+    {
+        if ($data) {
+            if ($data['type'] == 'uri' or $data['type'] == 'bnode') {
+                return $this->resource($data['value']);
+            } else {
+                return EasyRdf_Literal::create($data);
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /** Get all values for a property path
+     *
+     * This method will return an empty array if the property does not exist.
+     *
+     * @param  string  $resource      The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string  $propertyPath  A valid property path
+     * @param  string  $type          The type of value to filter by (e.g. literal)
+     * @param  string  $lang          The language to filter by (e.g. en)
+     * @return array                  An array of values associated with the property
+     */
+    public function all($resource, $propertyPath, $type = null, $lang = null)
+    {
+        $this->checkResourceParam($resource);
+
+        if (is_object($propertyPath) and $propertyPath instanceof EasyRdf_Resource) {
+            return $this->allForSingleProperty($resource, $propertyPath->getUri(), $type, $lang);
+        } elseif (is_string($propertyPath) and preg_match('|^(\^?)<(.+)>|', $propertyPath, $matches)) {
+            return $this->allForSingleProperty($resource, "$matches[1]$matches[2]", $type, $lang);
+        } elseif ($propertyPath === null or !is_string($propertyPath)) {
+            throw new InvalidArgumentException(
+                "\$propertyPath should be a string or EasyRdf_Resource and cannot be null"
+            );
+        } elseif ($propertyPath === '') {
+            throw new InvalidArgumentException(
+                "\$propertyPath cannot be an empty string"
+            );
+        }
+
+        $objects = array($resource);
+
+        // Loop through each component in the path
+        foreach (explode('/', $propertyPath) as $part) {
+
+            $results = array();
+            foreach (explode('|', $part) as $p) {
+                foreach ($objects as $o) {
+                    // Ignore literals found earlier in path
+                    if ($o instanceof EasyRdf_Literal) {
+                        continue;
+                    }
+
+                    $results = array_merge(
+                        $results,
+                        $this->allForSingleProperty($o, $p, $type, $lang)
+                    );
+                }
+            }
+
+            // Stop if we don't have anything
+            if (empty($objects)) {
+                break;
+            }
+
+            // Use the results as the input to the next iteration
+            $objects = $results;
+        }
+
+        return $objects;
+    }
+
+    /** Get all values for a single property of a resource
+     *
+     * @param  string  $resource The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  string  $type     The type of value to filter by (e.g. literal)
+     * @param  string  $lang     The language to filter by (e.g. en)
+     * @return array             An array of values associated with the property
+     *
+     * @ignore
+     */
+    protected function allForSingleProperty($resource, $property, $type = null, $lang = null)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+
+        // Get an array of values for the property
+        $values = $this->propertyValuesArray($resource, $property, $inverse);
+        if (!isset($values)) {
+            return array();
+        }
+
+        $objects = array();
+        if ($type) {
+            foreach ($values as $value) {
+                if ($type == 'literal' and $value['type'] == 'literal') {
+                    if ($lang == null or (isset($value['lang']) and $value['lang'] == $lang)) {
+                        $objects[] = $this->arrayToObject($value);
+                    }
+                } elseif ($type == 'resource') {
+                    if ($value['type'] == 'uri' or $value['type'] == 'bnode') {
+                        $objects[] = $this->arrayToObject($value);
+                    }
+                }
+            }
+        } else {
+            foreach ($values as $value) {
+                $objects[] = $this->arrayToObject($value);
+            }
+        }
+        return $objects;
+    }
+
+    /** Get all literal values for a property of a resource
+     *
+     * This method will return an empty array if the resource does not
+     * has any literal values for that property.
+     *
+     * @param  string  $resource The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  string  $lang     The language to filter by (e.g. en)
+     * @return array             An array of values associated with the property
+     */
+    public function allLiterals($resource, $property, $lang = null)
+    {
+        return $this->all($resource, $property, 'literal', $lang);
+    }
+
+    /** Get all resources for a property of a resource
+     *
+     * This method will return an empty array if the resource does not
+     * has any resources for that property.
+     *
+     * @param  string  $resource The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @return array             An array of values associated with the property
+     */
+    public function allResources($resource, $property)
+    {
+        return $this->all($resource, $property, 'resource');
+    }
+
+    /** Get all the resources in the graph of a certain type
+     *
+     * If no resources of the type are available and empty
+     * array is returned.
+     *
+     * @param  string  $type   The type of the resource (e.g. foaf:Person)
+     * @return array The array of resources
+     */
+    public function allOfType($type)
+    {
+        return $this->all($type, '^rdf:type');
+    }
+
+    /** Count all values for a property of a resource
+     *
+     * @param  string  $resource The URI of the resource (e.g. http://example.com/joe#me)
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  string  $type     The type of value to filter by (e.g. literal)
+     * @param  string  $lang     The language to filter by (e.g. en)
+     * @return integer           The number of values for this property
+     */
+    public function count($resource, $property, $type = null, $lang = null)
+    {
+        return count($this->all($resource, $property, $type, $lang));
+    }
+
+    /** Concatenate all values for a property of a resource into a string.
+     *
+     * The default is to join the values together with a space character.
+     * This method will return an empty string if the property does not exist.
+     *
+     * @param  mixed   $resource The resource to get the property on
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  string  $glue     The string to glue the values together with.
+     * @param  string  $lang     The language to filter by (e.g. en)
+     * @return string            Concatenation of all the values.
+     */
+    public function join($resource, $property, $glue = ' ', $lang = null)
+    {
+        return join($glue, $this->all($resource, $property, 'literal', $lang));
+    }
+
+    /** Add data to the graph
+     *
+     * The resource can either be a resource or the URI of a resource.
+     *
+     * Example:
+     *   $graph->add("http://www.example.com", 'dc:title', 'Title of Page');
+     *
+     * @param  mixed $resource   The resource to add data to
+     * @param  mixed $property   The property name
+     * @param  mixed $value      The new value for the property
+     * @return integer           The number of values added (1 or 0)
+     */
+    public function add($resource, $property, $value)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+        $this->checkValueParam($value);
+
+        // No value given?
+        if ($value === null) {
+            return 0;
+        }
+
+        // Check that the value doesn't already exist
+        if (isset($this->index[$resource][$property])) {
+            foreach ($this->index[$resource][$property] as $v) {
+                if ($v == $value) {
+                    return 0;
+                }
+            }
+        }
+        $this->index[$resource][$property][] = $value;
+
+        // Add to the reverse index if it is a resource
+        if ($value['type'] == 'uri' or $value['type'] == 'bnode') {
+            $uri = $value['value'];
+            $this->revIndex[$uri][$property][] = array(
+                'type' => substr($resource, 0, 2) == '_:' ? 'bnode' : 'uri',
+                'value' => $resource
+            );
+        }
+
+        // Success
+        return 1;
+    }
+
+    /** Add a literal value as a property of a resource
+     *
+     * The resource can either be a resource or the URI of a resource.
+     * The value can either be a single value or an array of values.
+     *
+     * Example:
+     *   $graph->add("http://www.example.com", 'dc:title', 'Title of Page');
+     *
+     * @param  mixed  $resource  The resource to add data to
+     * @param  mixed  $property  The property name
+     * @param  mixed  $value     The value or values for the property
+     * @param  string $lang      The language of the literal
+     * @return integer           The number of values added
+     */
+    public function addLiteral($resource, $property, $value, $lang = null)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+
+        if (is_array($value)) {
+            $added = 0;
+            foreach ($value as $v) {
+                $added += $this->addLiteral($resource, $property, $v, $lang);
+            }
+            return $added;
+        } else {
+            if ($lang) {
+                $value = array(
+                    'type' => 'literal',
+                    'value' => $value,
+                    'lang' => $lang
+                );
+            } else {
+                $value = array(
+                    'type' => 'literal',
+                    'value' => $value,
+                    'datatype' => EasyRdf_Literal::getDatatypeForValue($value)
+                );
+                if (empty($value['datatype'])) {
+                    unset($value['datatype']);
+                }
+            }
+            return $this->add($resource, $property, $value);
+        }
+    }
+
+    /** Add a resource as a property of another resource
+     *
+     * The resource can either be a resource or the URI of a resource.
+     *
+     * Example:
+     *   $graph->add("http://example.com/bob", 'foaf:knows', 'http://example.com/alice');
+     *
+     * @param  mixed $resource   The resource to add data to
+     * @param  mixed $property   The property name
+     * @param  mixed $resource2  The resource to be value of the property
+     * @return integer           The number of values added
+     */
+    public function addResource($resource, $property, $resource2)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+        $this->checkResourceParam($resource2);
+
+        return $this->add(
+            $resource,
+            $property,
+            array(
+                'type' => substr($resource2, 0, 2) == '_:' ? 'bnode' : 'uri',
+                'value' => $resource2
+            )
+        );
+    }
+
+    /** Set a value for a property
+     *
+     * The new value will replace the existing values for the property.
+     *
+     * @param  string  $resource The resource to set the property on
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  mixed   $value    The value for the property
+     * @return integer           The number of values added (1 or 0)
+     */
+    public function set($resource, $property, $value)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+        $this->checkValueParam($value);
+
+        // Delete the old values
+        $this->delete($resource, $property);
+
+        // Add the new values
+        return $this->add($resource, $property, $value);
+    }
+
+    /** Delete a property (or optionally just a specific value)
+     *
+     * @param  mixed   $resource The resource to delete the property from
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  mixed   $value The value to delete (null to delete all values)
+     * @return integer The number of values deleted
+     */
+    public function delete($resource, $property, $value = null)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+        $this->checkValueParam($value);
+
+        $count = 0;
+        $property = EasyRdf_Namespace::expand($property);
+        if (isset($this->index[$resource][$property])) {
+            foreach ($this->index[$resource][$property] as $k => $v) {
+                if (!$value or $v == $value) {
+                    unset($this->index[$resource][$property][$k]);
+                    $count++;
+                    if ($v['type'] == 'uri' or $v['type'] == 'bnode') {
+                        $this->deleteInverse($v['value'], $property, $resource);
+                    }
+                }
+            }
+
+            // Clean up the indexes - remove empty properties and resources
+            if ($count) {
+                if (count($this->index[$resource][$property]) == 0) {
+                    unset($this->index[$resource][$property]);
+                }
+                if (count($this->index[$resource]) == 0) {
+                    unset($this->index[$resource]);
+                }
+            }
+        }
+
+        return $count;
+    }
+
+    /** Delete a resource from a property of another resource
+     *
+     * The resource can either be a resource or the URI of a resource.
+     *
+     * Example:
+     *   $graph->delete("http://example.com/bob", 'foaf:knows', 'http://example.com/alice');
+     *
+     * @param  mixed $resource   The resource to delete data from
+     * @param  mixed $property   The property name
+     * @param  mixed $resource2  The resource value of the property to be deleted
+     */
+    public function deleteResource($resource, $property, $resource2)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+        $this->checkResourceParam($resource2);
+
+        return $this->delete(
+            $resource,
+            $property,
+            array(
+                'type' => substr($resource2, 0, 2) == '_:' ? 'bnode' : 'uri',
+                'value' => $resource2
+            )
+        );
+    }
+
+    /** Delete a literal value from a property of a resource
+     *
+     * Example:
+     *   $graph->delete("http://www.example.com", 'dc:title', 'Title of Page');
+     *
+     * @param  mixed  $resource  The resource to add data to
+     * @param  mixed  $property  The property name
+     * @param  mixed  $value     The value of the property
+     * @param  string $lang      The language of the literal
+     */
+    public function deleteLiteral($resource, $property, $value, $lang = null)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+        $this->checkValueParam($value);
+
+        if ($lang) {
+            $value['lang'] = $lang;
+        }
+
+        return $this->delete($resource, $property, $value);
+    }
+
+    /** This function is for internal use only.
+     *
+     * Deletes an inverse property from a resource.
+     *
+     * @ignore
+     */
+    protected function deleteInverse($resource, $property, $value)
+    {
+        if (isset($this->revIndex[$resource])) {
+            foreach ($this->revIndex[$resource][$property] as $k => $v) {
+                if ($v['value'] === $value) {
+                    unset($this->revIndex[$resource][$property][$k]);
+                }
+            }
+            if (count($this->revIndex[$resource][$property]) == 0) {
+                unset($this->revIndex[$resource][$property]);
+            }
+            if (count($this->revIndex[$resource]) == 0) {
+                unset($this->revIndex[$resource]);
+            }
+        }
+    }
+
+    /** Check if the graph contains any statements
+     *
+     * @return boolean True if the graph contains no statements
+     */
+    public function isEmpty()
+    {
+        return count($this->index) == 0;
+    }
+
+    /** Get a list of all the shortened property names (qnames) for a resource.
+     *
+     * This method will return an empty array if the resource has no properties.
+     *
+     * @return array            Array of shortened URIs
+     */
+    public function properties($resource)
+    {
+        $this->checkResourceParam($resource);
+
+        $properties = array();
+        if (isset($this->index[$resource])) {
+            foreach ($this->index[$resource] as $property => $value) {
+                $short = EasyRdf_Namespace::shorten($property);
+                if ($short) {
+                    $properties[] = $short;
+                }
+            }
+        }
+        return $properties;
+    }
+
+    /** Get a list of the full URIs for the properties of a resource.
+     *
+     * This method will return an empty array if the resource has no properties.
+     *
+     * @return array            Array of full URIs
+     */
+    public function propertyUris($resource)
+    {
+        $this->checkResourceParam($resource);
+
+        if (isset($this->index[$resource])) {
+            return array_keys($this->index[$resource]);
+        } else {
+            return array();
+        }
+    }
+
+    /** Get a list of the full URIs for the properties that point to a resource.
+     *
+     * @return array   Array of full property URIs
+     */
+    public function reversePropertyUris($resource)
+    {
+        $this->checkResourceParam($resource);
+
+        if (isset($this->revIndex[$resource])) {
+            return array_keys($this->revIndex[$resource]);
+        } else {
+            return array();
+        }
+    }
+
+    /** Check to see if a property exists for a resource.
+     *
+     * This method will return true if the property exists.
+     * If the value parameter is given, then it will only return true
+     * if the value also exists for that property.
+     *
+     * By providing a value parameter you can use this function to check
+     * to see if a triple exists in the graph.
+     *
+     * @param  mixed   $resource The resource to check
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  mixed   $value    An optional value of the property
+     * @return boolean           True if value the property exists.
+     */
+    public function hasProperty($resource, $property, $value = null)
+    {
+        $this->checkResourceParam($resource);
+        $this->checkSinglePropertyParam($property, $inverse);
+        $this->checkValueParam($value);
+
+        // Use the reverse index if it is an inverse property
+        if ($inverse) {
+            $index = &$this->revIndex;
+        } else {
+            $index = &$this->index;
+        }
+
+        if (isset($index[$resource][$property])) {
+            if (is_null($value)) {
+                return true;
+            } else {
+                foreach ($index[$resource][$property] as $v) {
+                    if ($v == $value) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /** Serialise the graph into RDF
+     *
+     * The $format parameter can be an EasyRdf_Format object, a
+     * format name, a mime type or a file extension.
+     *
+     * Example:
+     *   $turtle = $graph->serialise('turtle');
+     *
+     * @param  mixed  $format  The format to serialise to
+     * @return mixed  The serialised graph
+     */
+    public function serialise($format)
+    {
+        if (!$format instanceof EasyRdf_Format) {
+            $format = EasyRdf_Format::getFormat($format);
+        }
+        $serialiser = $format->newSerialiser();
+        return $serialiser->serialise($this, $format->getName());
+    }
+
+    /** Return a human readable view of all the resources in the graph
+     *
+     * This method is intended to be a debugging aid and will
+     * return a pretty-print view of all the resources and their
+     * properties.
+     *
+     * @param  boolean  $html  Set to true to format the dump using HTML
+     * @return string
+     */
+    public function dump($html = true)
+    {
+        $result = '';
+        if ($html) {
+            $result .= "<div style='font-family:arial; font-weight: bold; padding:0.5em; ".
+                   "color: black; background-color:lightgrey;border:dashed 1px grey;'>".
+                   "Graph: ". $this->uri . "</div>\n";
+        } else {
+            $result .= "Graph: ". $this->uri . "\n";
+        }
+
+        foreach ($this->index as $resource => $properties) {
+            $result .= $this->dumpResource($resource, $html);
+        }
+        return $result;
+    }
+
+    /** Return a human readable view of a resource and its properties
+     *
+     * This method is intended to be a debugging aid and will
+     * print a resource and its properties.
+     *
+     * @param  mixed    $resource  The resource to dump
+     * @param  boolean  $html      Set to true to format the dump using HTML
+     * @return string
+     */
+    public function dumpResource($resource, $html = true)
+    {
+        $this->checkResourceParam($resource, true);
+
+        if (isset($this->index[$resource])) {
+            $properties = $this->index[$resource];
+        } else {
+            return '';
+        }
+
+        $plist = array();
+        foreach ($properties as $property => $values) {
+            $olist = array();
+            foreach ($values as $value) {
+                if ($value['type'] == 'literal') {
+                    $olist []= EasyRdf_Utils::dumpLiteralValue($value, $html, 'black');
+                } else {
+                    $olist []= EasyRdf_Utils::dumpResourceValue($value['value'], $html, 'blue');
+                }
+            }
+
+            $pstr = EasyRdf_Namespace::shorten($property);
+            if ($pstr == null) {
+                $pstr = $property;
+            }
+            if ($html) {
+                $plist []= "<span style='font-size:130%'>&rarr;</span> ".
+                           "<span style='text-decoration:none;color:green'>".
+                           htmlentities($pstr) . "</span> ".
+                           "<span style='font-size:130%'>&rarr;</span> ".
+                           join(", ", $olist);
+            } else {
+                $plist []= "  -> $pstr -> " . join(", ", $olist);
+            }
+        }
+
+        if ($html) {
+            return "<div id='".htmlentities($resource)."' " .
+                   "style='font-family:arial; padding:0.5em; ".
+                   "background-color:lightgrey;border:dashed 1px grey;'>\n".
+                   "<div>".EasyRdf_Utils::dumpResourceValue($resource, true, 'blue')." ".
+                   "<span style='font-size: 0.8em'>(".
+                   $this->classForResource($resource).")</span></div>\n".
+                   "<div style='padding-left: 3em'>\n".
+                   "<div>".join("</div>\n<div>", $plist)."</div>".
+                   "</div></div>\n";
+        } else {
+            return $resource." (".$this->classForResource($resource).")\n" .
+                   join("\n", $plist) . "\n\n";
+        }
+    }
+
+    /** Get the resource type of the graph
+     *
+     * The type will be a shortened URI as a string.
+     * If the graph has multiple types then the type returned
+     * may be arbitrary.
+     * This method will return null if the resource has no type.
+     *
+     * @return string A type assocated with the resource (e.g. foaf:Document)
+     */
+    public function type($resource = null)
+    {
+        $this->checkResourceParam($resource, true);
+
+        if ($resource) {
+            $type = $this->get($resource, 'rdf:type', 'resource');
+            if ($type) {
+                return EasyRdf_Namespace::shorten($type);
+            }
+        }
+
+        return null;
+    }
+
+    /** Get the resource type of the graph as a EasyRdf_Resource
+     *
+     * If the graph has multiple types then the type returned
+     * may be arbitrary.
+     * This method will return null if the resource has no type.
+     *
+     * @return object EasyRdf_Resource  A type assocated with the resource
+     */
+    public function typeAsResource($resource = null)
+    {
+        $this->checkResourceParam($resource, true);
+
+        if ($resource) {
+            return $this->get($resource, 'rdf:type', 'resource');
+        }
+
+        return null;
+    }
+
+    /** Get a list of types for a resource
+     *
+     * The types will each be a shortened URI as a string.
+     * This method will return an empty array if the resource has no types.
+     *
+     * If $resource is null, then it will get the types for the URI of the graph.
+     *
+     * @return array All types assocated with the resource (e.g. foaf:Person)
+     */
+    public function types($resource = null)
+    {
+        $this->checkResourceParam($resource, true);
+
+        $types = array();
+        if ($resource) {
+            foreach ($this->all($resource, 'rdf:type', 'resource') as $type) {
+                $types[] = EasyRdf_Namespace::shorten($type);
+            }
+        }
+
+        return $types;
+    }
+
+    /** Check if a resource is of the specified type
+     *
+     * @param  string  $resource The resource to check the type of
+     * @param  string  $type     The type to check (e.g. foaf:Person)
+     * @return boolean           True if resource is of specified type
+     */
+    public function isA($resource, $type)
+    {
+        $this->checkResourceParam($resource, true);
+
+        $type = EasyRdf_Namespace::expand($type);
+        foreach ($this->all($resource, 'rdf:type', 'resource') as $t) {
+            if ($t->getUri() == $type) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Add one or more rdf:type properties to a resource
+     *
+     * @param  string  $resource The resource to add the type to
+     * @param  string  $types    One or more types to add (e.g. foaf:Person)
+     * @return integer           The number of types added
+     */
+    public function addType($resource, $types)
+    {
+        $this->checkResourceParam($resource, true);
+
+        if (!is_array($types)) {
+            $types = array($types);
+        }
+
+        $count = 0;
+        foreach ($types as $type) {
+            $type = EasyRdf_Namespace::expand($type);
+            $count += $this->add($resource, 'rdf:type', array('type' => 'uri', 'value' => $type));
+        }
+
+        return $count;
+    }
+
+    /** Change the rdf:type property for a resource
+     *
+     * Note that if the resource object has already previously
+     * been created, then the PHP class of the resource will not change.
+     *
+     * @param  string  $resource The resource to change the type of
+     * @param  string  $type     The new type (e.g. foaf:Person)
+     * @return integer           The number of types added
+     */
+    public function setType($resource, $type)
+    {
+        $this->checkResourceParam($resource, true);
+
+        $this->delete($resource, 'rdf:type');
+        return $this->addType($resource, $type);
+    }
+
+    /** Get a human readable label for a resource
+     *
+     * This method will check a number of properties for a resource
+     * (in the order: skos:prefLabel, rdfs:label, foaf:name, dc:title)
+     * and return an approriate first that is available. If no label
+     * is available then it will return null.
+     *
+     * @return string A label for the resource.
+     */
+    public function label($resource = null, $lang = null)
+    {
+        $this->checkResourceParam($resource, true);
+
+        if ($resource) {
+            return $this->get(
+                $resource,
+                'skos:prefLabel|rdfs:label|foaf:name|dc:title|dc11:title',
+                'literal',
+                $lang
+            );
+        } else {
+            return null;
+        }
+    }
+
+    /** Get the primary topic of the graph
+     *
+     * @return EasyRdf_Resource The primary topic of the document.
+     */
+    public function primaryTopic($resource = null)
+    {
+        $this->checkResourceParam($resource, true);
+
+        if ($resource) {
+            return $this->get(
+                $resource,
+                'foaf:primaryTopic|^foaf:isPrimaryTopicOf',
+                'resource'
+            );
+        } else {
+            return null;
+        }
+    }
+
+    /** Returns the graph as a RDF/PHP associative array
+     *
+     * @return array The contents of the graph as an array.
+     */
+    public function toArray()
+    {
+        return $this->index;
+    }
+
+    /** Calculates the number of triples in the graph
+     *
+     * @return integer The number of triples in the graph.
+     */
+    public function countTriples()
+    {
+        $count = 0;
+        foreach ($this->index as $resource) {
+            foreach ($resource as $property => $values) {
+                $count += count($values);
+            }
+        }
+        return $count;
+    }
+
+    /** Magic method to return URI of resource when casted to string
+     *
+     * @return string The URI of the resource
+     */
+    public function __toString()
+    {
+        return $this->uri == null ? '' : $this->uri;
+    }
+
+    /** Magic method to get a property of the graph
+     *
+     * Note that only properties in the default namespace can be accessed in this way.
+     *
+     * Example:
+     *   $value = $graph->title;
+     *
+     * @see EasyRdf_Namespace::setDefault()
+     * @param  string $name The name of the property
+     * @return string       A single value for the named property
+     */
+    public function __get($name)
+    {
+        return $this->get($this->uri, $name);
+    }
+
+    /** Magic method to set the value for a property of the graph
+     *
+     * Note that only properties in the default namespace can be accessed in this way.
+     *
+     * Example:
+     *   $graph->title = 'Title';
+     *
+     * @see EasyRdf_Namespace::setDefault()
+     * @param  string $name The name of the property
+     * @param  string $value The value for the property
+     */
+    public function __set($name, $value)
+    {
+        return $this->set($this->uri, $name, $value);
+    }
+
+    /** Magic method to check if a property exists
+     *
+     * Note that only properties in the default namespace can be accessed in this way.
+     *
+     * Example:
+     *   if (isset($graph->title)) { blah(); }
+     *
+     * @see EasyRdf_Namespace::setDefault()
+     * @param string $name The name of the property
+     */
+    public function __isset($name)
+    {
+        return $this->hasProperty($this->uri, $name);
+    }
+
+    /** Magic method to delete a property of the graph
+     *
+     * Note that only properties in the default namespace can be accessed in this way.
+     *
+     * Example:
+     *   unset($graph->title);
+     *
+     * @see EasyRdf_Namespace::setDefault()
+     * @param string $name The name of the property
+     */
+    public function __unset($name)
+    {
+        return $this->delete($this->uri, $name);
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/GraphStore.php b/core/vendor/njh/easyrdf/lib/EasyRdf/GraphStore.php
new file mode 100644
index 000000000000..3fcc7b433caf
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/GraphStore.php
@@ -0,0 +1,217 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2011 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2011 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * A class for fetching, saving and deleting graphs to a Graph Store.
+ * Implementation of the SPARQL 1.1 Graph Store HTTP Protocol.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2011 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_GraphStore
+{
+    /** The address of the GraphStore endpoint */
+    private $uri = null;
+    private $parsedUri = null;
+
+
+    /** Create a new SPARQL Graph Store client
+     *
+     * @param string $uri The address of the graph store endpoint
+     */
+    public function __construct($uri)
+    {
+        $this->uri = $uri;
+        $this->parsedUri = new EasyRdf_ParsedUri($uri);
+    }
+
+    /** Get the URI of the graph store
+     *
+     * @return string The URI of the graph store
+     */
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
+    /** Fetch a named graph from the graph store
+     *
+     * The URI can either be a full absolute URI or
+     * a URI relative to the URI of the graph store.
+     *
+     * @param string $uriRef The URI of graph desired
+     * @return object EasyRdf_Graph The graph requested
+     */
+    public function get($uriRef)
+    {
+        $graphUri = $this->parsedUri->resolve($uriRef)->toString();
+        $dataUrl = $this->urlForGraph($graphUri);
+        $graph = new EasyRdf_Graph($graphUri);
+        $graph->load($dataUrl);
+        return $graph;
+    }
+
+    /** Send some graph data to the graph store
+     *
+     * This method is used by insert() and replace()
+     *
+     * @ignore
+     */
+    protected function sendGraph($method, $graph, $uriRef, $format)
+    {
+        if (is_object($graph) and $graph instanceof EasyRdf_Graph) {
+            if ($uriRef == null) {
+                $uriRef = $graph->getUri();
+            }
+            $data = $graph->serialise($format);
+        } else {
+            $data = $graph;
+        }
+
+        $formatObj = EasyRdf_Format::getFormat($format);
+        $mimeType = $formatObj->getDefaultMimeType();
+
+        $graphUri = $this->parsedUri->resolve($uriRef)->toString();
+        $dataUrl = $this->urlForGraph($graphUri);
+
+        $client = EasyRdf_Http::getDefaultHttpClient();
+        $client->resetParameters(true);
+        $client->setUri($dataUrl);
+        $client->setMethod($method);
+        $client->setRawData($data);
+        $client->setHeaders('Content-Type', $mimeType);
+        $client->setHeaders('Content-Length', strlen($data));
+        $response = $client->request();
+        if (!$response->isSuccessful()) {
+            throw new EasyRdf_Exception(
+                "HTTP request for $dataUrl failed: ".$response->getMessage()
+            );
+        }
+        return $response;
+    }
+
+    /** Replace the contents of a graph in the graph store with new data
+     *
+     * The $graph parameter is the EasyRdf_Graph object to be sent to the
+     * graph store. Alternatively it can be a string, already serialised.
+     *
+     * The URI can either be a full absolute URI or
+     * a URI relative to the URI of the graph store.
+     *
+     * The $format parameter can be given to specify the serialisation
+     * used to send the graph data to the graph store.
+     *
+     * @param object EasyRdfGraph $graph The URI of graph desired
+     * @param string $uriRef The URI of graph to be replaced
+     * @param string $format The format of the data to send to the graph store
+     * @return object EasyRdf_Http_Response The response from the graph store
+     */
+    public function replace($graph, $uriRef = null, $format = 'ntriples')
+    {
+        return $this->sendGraph('PUT', $graph, $uriRef, $format);
+    }
+
+    /** Add data to a graph in the graph store
+     *
+     * The $graph parameter is the EasyRdf_Graph object to be sent to the
+     * graph store. Alternatively it can be a string, already serialised.
+     *
+     * The URI can either be a full absolute URI or
+     * a URI relative to the URI of the graph store.
+     *
+     * The $format parameter can be given to specify the serialisation
+     * used to send the graph data to the graph store.
+     *
+     * @param object EasyRdfGraph $graph The URI of graph desired
+     * @param string $uriRef The URI of graph to be added to
+     * @param string $format The format of the data to send to the graph store
+     * @return object EasyRdf_Http_Response The response from the graph store
+     */
+    public function insert($graph, $uriRef = null, $format = 'ntriples')
+    {
+        return $this->sendGraph('POST', $graph, $uriRef, $format);
+    }
+
+    /** Delete a graph from the graph store
+     *
+     * The URI can either be a full absolute URI or
+     * a URI relative to the URI of the graph store.
+     *
+     * @param string $uriRef The URI of graph to be added to
+     * @return object EasyRdf_Http_Response The response from the graph store
+     */
+    public function delete($uriRef)
+    {
+        $graphUri = $this->parsedUri->resolve($uriRef)->toString();
+        $dataUrl = $this->urlForGraph($graphUri);
+
+        $client = EasyRdf_Http::getDefaultHttpClient();
+        $client->resetParameters(true);
+        $client->setUri($dataUrl);
+        $client->setMethod('DELETE');
+        $response = $client->request();
+        if (!$response->isSuccessful()) {
+            throw new EasyRdf_Exception(
+                "HTTP request to delete $dataUrl failed: ".$response->getMessage()
+            );
+        }
+        return $response;
+    }
+
+    /** Work out the full URL for a graph store request.
+     *  by checking if if it is a direct or indirect request.
+     *  @ignore
+     */
+    protected function urlForGraph($url)
+    {
+        if (strpos($url, $this->uri) === false) {
+            $url = $this->uri."?graph=".urlencode($url);
+        }
+        return $url;
+    }
+
+    /** Magic method to return URI of the graph store when casted to string
+     *
+     * @return string The URI of the graph store
+     */
+    public function __toString()
+    {
+        return empty($this->uri) ? '' : $this->uri;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Http.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Http.php
new file mode 100644
index 000000000000..c8a1d3dbae86
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Http.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2011 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2011 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+
+/**
+ * Static class to set the HTTP client used by EasyRdf
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2011 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Http
+{
+    /** The default HTTP Client object */
+    private static $defaultHttpClient = null;
+
+    /** Set the HTTP Client object used to fetch RDF data
+     *
+     * @param  object mixed $httpClient The new HTTP client object
+     * @return object mixed The new HTTP client object
+     */
+    public static function setDefaultHttpClient($httpClient)
+    {
+        if (!is_object($httpClient) or
+            !($httpClient instanceof Zend_Http_Client or
+              $httpClient instanceof EasyRdf_Http_Client)) {
+            throw new InvalidArgumentException(
+                "\$httpClient should be an object of class Zend_Http_Client or EasyRdf_Http_Client"
+            );
+        }
+        return self::$defaultHttpClient = $httpClient;
+    }
+
+    /** Get the HTTP Client object used to fetch RDF data
+     *
+     * If no HTTP Client has previously been set, then a new
+     * default (EasyRdf_Http_Client) client will be created.
+     *
+     * @return object mixed The HTTP client object
+     */
+    public static function getDefaultHttpClient()
+    {
+        if (!isset(self::$defaultHttpClient)) {
+            self::$defaultHttpClient = new EasyRdf_Http_Client();
+        }
+        return self::$defaultHttpClient;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Http/Client.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Http/Client.php
new file mode 100644
index 000000000000..57c6fae52399
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Http/Client.php
@@ -0,0 +1,549 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ * Copyright (c) 2005-2009 Zend Technologies USA Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ *             Copyright (c) 2005-2009 Zend Technologies USA Inc.
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * This class is an implemetation of an HTTP client in PHP.
+ * It supports basic HTTP 1.0 and 1.1 requests. For a more complete
+ * implementation try Zend_Http_Client.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Http_Client
+{
+    /**
+     * Configuration array, set using the constructor or using ::setConfig()
+     *
+     * @var array
+     */
+    private $config = array(
+        'maxredirects'    => 5,
+        'useragent'       => 'EasyRdf_Http_Client',
+        'timeout'         => 10
+    );
+
+    /**
+     * Request URI
+     *
+     * @var string
+     */
+    private $uri = null;
+
+    /**
+     * Associative array of request headers
+     *
+     * @var array
+     */
+    private $headers = array();
+
+    /**
+     * HTTP request method
+     *
+     * @var string
+     */
+    private $method = 'GET';
+
+    /**
+     * Associative array of GET parameters
+     *
+     * @var array
+     */
+    private $paramsGet = array();
+
+    /**
+     * The raw post data to send. Could be set by setRawData($data).
+     *
+     * @var string
+     */
+    private $rawPostData = null;
+
+    /**
+     * Redirection counter
+     *
+     * @var int
+     */
+    private $redirectCounter = 0;
+
+    /**
+     * Constructor method. Will create a new HTTP client. Accepts the target
+     * URL and optionally configuration array.
+     *
+     * @param string $uri
+     * @param array $config Configuration key-value pairs.
+     */
+    public function __construct($uri = null, $config = null)
+    {
+        if ($uri !== null) {
+            $this->setUri($uri);
+        }
+        if ($config !== null) {
+            $this->setConfig($config);
+        }
+    }
+
+    /**
+     * Set the URI for the next request
+     *
+     * @param  string $uri
+     * @return EasyRdf_Http_Client
+     */
+    public function setUri($uri)
+    {
+        if (!is_string($uri)) {
+            $uri = strval($uri);
+        }
+
+        if (!preg_match('/^http(s?):/', $uri)) {
+            throw new InvalidArgumentException(
+                "EasyRdf_Http_Client only supports the 'http' and 'https' schemes."
+            );
+        }
+
+        $this->uri = $uri;
+
+        return $this;
+    }
+
+    /**
+     * Get the URI for the next request
+     *
+     * @return string
+     */
+    public function getUri($asString = true)
+    {
+        return $this->uri;
+    }
+
+    /**
+     * Set configuration parameters for this HTTP client
+     *
+     * @param  array $config
+     * @return EasyRdf_Http_Client
+     * @throws InvalidArgumentException
+     */
+    public function setConfig($config = array())
+    {
+        if ($config == null or !is_array($config)) {
+            throw new InvalidArgumentException(
+                "\$config should be an array and cannot be null"
+            );
+        }
+
+        foreach ($config as $k => $v) {
+            $this->config[strtolower($k)] = $v;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set a request header
+     *
+     * @param string $name Header name (e.g. 'Accept')
+     * @param string $value Header value or null
+     * @return EasyRdf_Http_Client
+     */
+    public function setHeaders($name, $value = null)
+    {
+        $normalizedName = strtolower($name);
+
+        // If $value is null or false, unset the header
+        if ($value === null || $value === false) {
+            unset($this->headers[$normalizedName]);
+        } else {
+            // Else, set the header
+            $this->headers[$normalizedName] = array($name, $value);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set the next request's method
+     *
+     * Validated the passed method and sets it.
+     *
+     * @param string $method
+     * @return EasyRdf_Http_Client
+     * @throws InvalidArgumentException
+     */
+    public function setMethod($method)
+    {
+        if (!is_string($method) or !preg_match('/^[A-Z]+$/', $method)) {
+            throw new InvalidArgumentException("Invalid HTTP request method.");
+        }
+
+        $this->method = $method;
+
+        return $this;
+    }
+
+    /**
+     * Get the method for the next request
+     *
+     * @return string
+     */
+    public function getMethod()
+    {
+        return $this->method;
+    }
+
+    /**
+     * Get the value of a specific header
+     *
+     * Note that if the header has more than one value, an array
+     * will be returned.
+     *
+     * @param string $key
+     * @return string|array|null The header value or null if it is not set
+     */
+    public function getHeader($key)
+    {
+        $key = strtolower($key);
+        if (isset($this->headers[$key])) {
+            return $this->headers[$key][1];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Set a GET parameter for the request.
+     *
+     * @param string $name
+     * @param string $value
+     * @return EasyRdf_Http_Client
+     */
+    public function setParameterGet($name, $value = null)
+    {
+        if ($value === null) {
+            if (isset($this->paramsGet[$name])) {
+                unset($this->paramsGet[$name]);
+            }
+        } else {
+            $this->paramsGet[$name] = $value;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get a GET parameter for the request.
+     *
+     * @param string $name
+     * @return string value
+     */
+    public function getParameterGet($name)
+    {
+        if (isset($this->paramsGet[$name])) {
+            return $this->paramsGet[$name];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get all the GET parameters
+     *
+     * @return array
+     */
+    public function getParametersGet()
+    {
+        return $this->paramsGet;
+    }
+
+    /**
+     * Get the number of redirections done on the last request
+     *
+     * @return int
+     */
+    public function getRedirectionsCount()
+    {
+        return $this->redirectCounter;
+    }
+
+    /**
+     * Set the raw (already encoded) POST data.
+     *
+     * This function is here for two reasons:
+     * 1. For advanced user who would like to set their own data, already encoded
+     * 2. For backwards compatibilty: If someone uses the old post($data) method.
+     *    this method will be used to set the encoded data.
+     *
+     * $data can also be stream (such as file) from which the data will be read.
+     *
+     * @param string|resource $data
+     * @return Zend_Http_Client
+     */
+    public function setRawData($data)
+    {
+        $this->rawPostData = $data;
+        return $this;
+    }
+
+    /**
+     * Get the raw (already encoded) POST data.
+     *
+     * @return string
+     */
+    public function getRawData()
+    {
+        return $this->rawPostData;
+    }
+
+    /**
+     * Clear all GET and POST parameters
+     *
+     * Should be used to reset the request parameters if the client is
+     * used for several concurrent requests.
+     *
+     * clearAll parameter controls if we clean just parameters or also
+     * headers
+     *
+     * @param bool $clearAll Should all data be cleared?
+     * @return EasyRdf_Http_Client
+     */
+    public function resetParameters($clearAll = false)
+    {
+        // Reset parameter data
+        $this->paramsGet   = array();
+        $this->rawPostData = null;
+        $this->method      = 'GET';
+
+        if ($clearAll) {
+            $this->headers = array();
+        } else {
+            // Clear outdated headers
+            if (isset($this->headers['content-type'])) {
+                unset($this->headers['content-type']);
+            }
+            if (isset($this->headers['content-length'])) {
+                unset($this->headers['content-length']);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Send the HTTP request and return an HTTP response object
+     *
+     * @return EasyRdf_Http_Response
+     * @throws EasyRdf_Exception
+     */
+    public function request($method = null)
+    {
+        if (!$this->uri) {
+            throw new EasyRdf_Exception(
+                "Set URI before calling EasyRdf_Http_Client->request()"
+            );
+        }
+
+        if ($method) {
+            $this->setMethod($method);
+        }
+        $this->redirectCounter = 0;
+        $response = null;
+
+        // Send the first request. If redirected, continue.
+        do {
+            // Clone the URI and add the additional GET parameters to it
+            $uri = parse_url($this->uri);
+            if ($uri['scheme'] === 'http') {
+                $host = $uri['host'];
+            } elseif ($uri['scheme'] === 'https') {
+                $host = 'ssl://'.$uri['host'];
+            } else {
+                throw new EasyRdf_Exception(
+                    "Unsupported URI scheme: ".$uri['scheme']
+                );
+            }
+
+            if (isset($uri['port'])) {
+                $port = $uri['port'];
+            } else {
+                if ($uri['scheme'] === 'https') {
+                    $port = 443;
+                } else {
+                    $port = 80;
+                }
+            }
+
+            if (!empty($this->paramsGet)) {
+                if (!empty($uri['query'])) {
+                    $uri['query'] .= '&';
+                } else {
+                    $uri['query'] = '';
+                }
+                $uri['query'] .= http_build_query($this->paramsGet, null, '&');
+            }
+
+            $headers = $this->prepareHeaders($uri['host'], $port);
+
+            // Open socket to remote server
+            $socket = @fsockopen($host, $port, $errno, $errstr, $this->config['timeout']);
+            if (!$socket) {
+                throw new EasyRdf_Exception("Unable to connect to $host:$port ($errstr)");
+            }
+
+            // Write the request
+            $path = $uri['path'];
+            if (isset($uri['query'])) {
+                $path .= '?' . $uri['query'];
+            }
+            fwrite($socket, "{$this->method} {$path} HTTP/1.1\r\n");
+            foreach ($headers as $k => $v) {
+                if (is_string($k)) {
+                    $v = ucfirst($k) . ": $v";
+                }
+                fwrite($socket, "$v\r\n");
+            }
+            fwrite($socket, "\r\n");
+
+            // Send the request body, if there is one set
+            if (isset($this->rawPostData)) {
+                fwrite($socket, $this->rawPostData);
+            }
+
+            // Read in the response
+            $content = '';
+            while (!feof($socket)) {
+                $content .= fgets($socket);
+            }
+
+            // FIXME: support HTTP/1.1 100 Continue
+
+            // Close the socket
+            @fclose($socket);
+
+            // Parse the response string
+            $response = EasyRdf_Http_Response::fromString($content);
+
+            // If we got redirected, look for the Location header
+            if ($response->isRedirect() &&
+                   ($location = $response->getHeader('location'))
+               ) {
+
+                // Avoid problems with buggy servers that add whitespace at the
+                // end of some headers (See ZF-11283)
+                $location = trim($location);
+
+                // Some servers return relative URLs in the location header
+                // resolve it in relation to previous request
+                $baseUri = new EasyRdf_ParsedUri($this->uri);
+                $location = $baseUri->resolve($location)->toString();
+
+                // If it is a 303 then drop the parameters and send a GET request
+                if ($response->getStatus() == 303) {
+                    $this->resetParameters();
+                    $this->setMethod('GET');
+                }
+
+                // If we got a well formed absolute URI
+                if (parse_url($location)) {
+                    $this->setHeaders('host', null);
+                    $this->setUri($location);
+                } else {
+                    throw new EasyRdf_Exception(
+                        "Failed to parse Location header returned by ".
+                        $this->uri
+                    );
+                }
+                ++$this->redirectCounter;
+
+            } else {
+                // If we didn't get any location, stop redirecting
+                break;
+            }
+
+
+        } while ($this->redirectCounter < $this->config['maxredirects']);
+
+        return $response;
+    }
+
+    /**
+     * Prepare the request headers
+     *
+     * @ignore
+     * @return array
+     */
+    protected function prepareHeaders($host, $port)
+    {
+        $headers = array();
+
+        // Set the host header
+        if (! isset($this->headers['host'])) {
+            // If the port is not default, add it
+            if ($port !== 80 and $port !== 443) {
+                $host .= ':' . $port;
+            }
+            $headers[] = "Host: {$host}";
+        }
+
+        // Set the connection header
+        if (! isset($this->headers['connection'])) {
+            $headers[] = "Connection: close";
+        }
+
+        // Set the user agent header
+        if (! isset($this->headers['user-agent'])) {
+            $headers[] = "User-Agent: {$this->config['useragent']}";
+        }
+
+        // If we have _rawPostData set, set the content-length header
+        if (isset($this->rawPostData)) {
+            $headers[] = "Content-Length: ".strlen($this->rawPostData);
+        }
+
+        // Add all other user defined headers
+        foreach ($this->headers as $header) {
+            list($name, $value) = $header;
+            if (is_array($value)) {
+                $value = implode(', ', $value);
+            }
+
+            $headers[] = "$name: $value";
+        }
+
+        return $headers;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Http/Response.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Http/Response.php
new file mode 100644
index 000000000000..2abe00aca182
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Http/Response.php
@@ -0,0 +1,361 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.
+ * Copyright (c) 2005-2009 Zend Technologies USA Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc.
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an HTTP 1.0 / 1.1 response message.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ *             Copyright (c) 2005-2009 Zend Technologies USA Inc.
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Http_Response
+{
+
+    /**
+     * The HTTP response status code
+     *
+     * @var int
+     */
+    private $status;
+
+    /**
+     * The HTTP response code as string
+     * (e.g. 'Not Found' for 404 or 'Internal Server Error' for 500)
+     *
+     * @var string
+     */
+    private $message;
+
+    /**
+     * The HTTP response headers array
+     *
+     * @var array
+     */
+    private $headers = array();
+
+    /**
+     * The HTTP response body
+     *
+     * @var string
+     */
+    private $body;
+
+    /**
+     * Constructor.
+     *
+     * @param  int     $status HTTP Status code
+     * @param  array   $headers The HTTP response headers
+     * @param  string  $body The content of the response
+     * @param  string  $version The HTTP Version (1.0 or 1.1)
+     * @param  string  $message The HTTP response Message
+     * @return object  EasyRdf_Http_Response
+     */
+    public function __construct(
+        $status,
+        $headers,
+        $body = null,
+        $version = '1.1',
+        $message = null
+    ) {
+        $this->status = intval($status);
+        $this->body = $body;
+        $this->version = $version;
+        $this->message = $message;
+
+        foreach ($headers as $k => $v) {
+            $k = ucwords(strtolower($k));
+            $this->headers[$k] = $v;
+        }
+    }
+
+    /**
+     * Check whether the response in successful
+     *
+     * @return boolean
+     */
+    public function isSuccessful()
+    {
+        return ($this->status >= 200 && $this->status < 300);
+    }
+
+    /**
+     * Check whether the response is an error
+     *
+     * @return boolean
+     */
+    public function isError()
+    {
+        return ($this->status >= 400 && $this->status < 600);
+    }
+
+    /**
+     * Check whether the response is a redirection
+     *
+     * @return boolean
+     */
+    public function isRedirect()
+    {
+        return ($this->status >= 300 && $this->status < 400);
+    }
+
+    /**
+     * Get the HTTP response status code
+     *
+     * @return int
+     */
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    /**
+     * Return a message describing the HTTP response code
+     * (Eg. "OK", "Not Found", "Moved Permanently")
+     *
+     * @return string
+     */
+    public function getMessage()
+    {
+        return $this->message;
+    }
+
+    /**
+     * Get the response body as string
+     *
+     * @return string
+     */
+    public function getBody()
+    {
+        // Decode the body if it was transfer-encoded
+        switch (strtolower($this->getHeader('transfer-encoding'))) {
+            // Handle chunked body
+            case 'chunked':
+                return self::decodeChunkedBody($this->body);
+                break;
+
+            // No transfer encoding, or unknown encoding extension:
+            // return body as is
+            default:
+                return $this->body;
+                break;
+        }
+    }
+
+    /**
+     * Get the raw response body (as transfered "on wire") as string
+     *
+     * If the body is encoded (with Transfer-Encoding, not content-encoding -
+     * IE "chunked" body), gzip compressed, etc. it will not be decoded.
+     *
+     * @return string
+     */
+    public function getRawBody()
+    {
+        return $this->body;
+    }
+
+    /**
+     * Get the HTTP version of the response
+     *
+     * @return string
+     */
+    public function getVersion()
+    {
+        return $this->version;
+    }
+
+    /**
+     * Get the response headers
+     *
+     * @return array
+     */
+    public function getHeaders()
+    {
+        return $this->headers;
+    }
+
+    /**
+     * Get a specific header as string, or null if it is not set
+     *
+     * @param string$header
+     * @return string|array|null
+     */
+    public function getHeader($header)
+    {
+        $header = ucwords(strtolower($header));
+        if (array_key_exists($header, $this->headers)) {
+            return $this->headers[$header];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get all headers as string
+     *
+     * @param boolean $statusLine Whether to return the first status line (ie "HTTP 200 OK")
+     * @param string  $br         Line breaks (eg. "\n", "\r\n", "<br />")
+     * @return string
+     */
+    public function getHeadersAsString($statusLine = true, $br = "\n")
+    {
+        $str = '';
+
+        if ($statusLine) {
+            $str = "HTTP/{$this->version} {$this->status} {$this->message}{$br}";
+        }
+
+        // Iterate over the headers and stringify them
+        foreach ($this->headers as $name => $value) {
+            if (is_string($value)) {
+                $str .= "{$name}: {$value}{$br}";
+            } elseif (is_array($value)) {
+                foreach ($value as $subval) {
+                    $str .= "{$name}: {$subval}{$br}";
+                }
+            }
+        }
+
+        return $str;
+    }
+
+    /**
+     * Create an EasyRdf_Http_Response object from a HTTP response string
+     *
+     * @param string $responseStr
+     * @return EasyRdf_Http_Response
+     */
+    public static function fromString($responseStr)
+    {
+        // First, split body and headers
+        $matches = preg_split('|(?:\r?\n){2}|m', $responseStr, 2);
+        if ($matches and sizeof($matches) == 2) {
+            list ($headerLines, $body) = $matches;
+        } else {
+            throw new EasyRdf_Exception(
+                "Failed to parse HTTP response."
+            );
+        }
+
+        // Split headers part to lines
+        $headerLines = preg_split('|[\r\n]+|m', $headerLines);
+        $status = array_shift($headerLines);
+        if (preg_match("|^HTTP/([\d\.x]+) (\d+) ([^\r\n]+)|", $status, $m)) {
+            $version = $m[1];
+            $status = $m[2];
+            $message = $m[3];
+        } else {
+            throw new EasyRdf_Exception(
+                "Failed to parse HTTP response status line."
+            );
+        }
+
+        // Process the rest of the header lines
+        $headers = array();
+        foreach ($headerLines as $line) {
+            if (preg_match("|^([\w-]+):\s+(.+)$|", $line, $m)) {
+                $hName = ucwords(strtolower($m[1]));
+                $hValue = $m[2];
+
+                if (isset($headers[$hName])) {
+                    if (! is_array($headers[$hName])) {
+                        $headers[$hName] = array($headers[$hName]);
+                    }
+                    $headers[$hName][] = $hValue;
+                } else {
+                    $headers[$hName] = $hValue;
+                }
+            }
+        }
+
+        return new EasyRdf_Http_Response($status, $headers, $body, $version, $message);
+    }
+
+
+    /**
+     * Decode a "chunked" transfer-encoded body and return the decoded text
+     *
+     * @param string $body
+     * @return string
+     */
+    public static function decodeChunkedBody($body)
+    {
+        $decBody = '';
+
+        while (trim($body)) {
+            if (preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) {
+                $length = hexdec(trim($m[1]));
+                $cut = strlen($m[0]);
+                $decBody .= substr($body, $cut, $length);
+                $body = substr($body, $cut + $length + 2);
+            } else {
+                throw new EasyRdf_Exception(
+                    "Failed to decode chunked body in HTTP response."
+                );
+            }
+        }
+
+        return $decBody;
+    }
+
+
+    /**
+     * Get the entire response as string
+     *
+     * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
+     * @return string
+     */
+    public function asString($br = "\n")
+    {
+        return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody();
+    }
+
+    /**
+     * Implements magic __toString()
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->asString();
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal.php
new file mode 100644
index 000000000000..eadf2a2adf60
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal.php
@@ -0,0 +1,315 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal
+{
+    /** @ignore a mapping from datatype uri to class name */
+    private static $datatypeMap = array();
+
+    /** @ignore A mapping from class name to datatype URI */
+    private static $classMap = array();
+
+    /** @ignore The string value for this literal */
+    protected $value = null;
+
+    /** @ignore The language of the literal (e.g. 'en') */
+    protected $lang = null;
+
+    /** @ignore The datatype URI of the literal */
+    protected $datatype = null;
+
+
+    /** Create a new literal object
+     *
+     * PHP values of type bool, int or float, will automatically be converted
+     * to the corresponding datatype and PHP sub-class.
+     *
+     * If a registered datatype is given, then the registered subclass of EasyRdf_Literal
+     * will instantiated.
+     *
+     * Note that literals are not required to have a language or datatype.
+     * Literals cannot have both a language and a datatype.
+     *
+     * @param  mixed  $value     The value of the literal or an associative array
+     * @param  string $lang      The natural language of the literal or null (e.g. 'en')
+     * @param  string $datatype  The datatype of the literal or null (e.g. 'xsd:integer')
+     * @return object EasyRdf_Literal (or subclass of EasyRdf_Literal)
+     */
+    public static function create($value, $lang = null, $datatype = null)
+    {
+        if (EasyRdf_Utils::isAssociativeArray($value)) {
+            if (isset($value['xml:lang'])) {
+                $lang = $value['xml:lang'];
+            } elseif (isset($value['lang'])) {
+                $lang = $value['lang'];
+            }
+            if (isset($value['datatype'])) {
+                $datatype = $value['datatype'];
+            }
+            $value = isset($value['value']) ? $value['value'] : null;
+        }
+
+        if (empty($datatype)) {
+            if (empty($lang)) {
+                // Automatic datatype selection
+                $datatype = self::getDatatypeForValue($value);
+            }
+        } elseif (is_object($datatype)) {
+            $datatype = strval($datatype);
+        } else {
+            // Expand shortened URIs (qnames)
+            $datatype = EasyRdf_Namespace::expand($datatype);
+        }
+
+        // Work out what class to use for this datatype
+        if (isset(self::$datatypeMap[$datatype])) {
+            $class = self::$datatypeMap[$datatype];
+        } else {
+            $class = 'EasyRdf_Literal';
+        }
+        return new $class($value, $lang, $datatype);
+    }
+
+    /** Register an RDF datatype with a PHP class name
+     *
+     * When parsing registered class will be used whenever the datatype
+     * is seen.
+     *
+     * When serialising a registered class, the mapping will be used to
+     * set the datatype in the RDF.
+     *
+     * Example:
+     * EasyRdf_Literal::registerDatatype('xsd:dateTime', 'My_DateTime_Class');
+     *
+     * @param  string  $datatype   The RDF datatype (e.g. xsd:dateTime)
+     * @param  string  $class      The PHP class name (e.g. My_DateTime_Class)
+     */
+    public static function setDatatypeMapping($datatype, $class)
+    {
+        if (!is_string($datatype) or $datatype == null or $datatype == '') {
+            throw new InvalidArgumentException(
+                "\$datatype should be a string and cannot be null or empty"
+            );
+        }
+
+        if (!is_string($class) or $class == null or $class == '') {
+            throw new InvalidArgumentException(
+                "\$class should be a string and cannot be null or empty"
+            );
+        }
+
+        $datatype = EasyRdf_Namespace::expand($datatype);
+        self::$datatypeMap[$datatype] = $class;
+        self::$classMap[$class] = $datatype;
+    }
+
+    /** Remove the mapping between an RDF datatype and a PHP class name
+     *
+     * @param  string  $datatype   The RDF datatype (e.g. xsd:dateTime)
+     */
+    public static function deleteDatatypeMapping($datatype)
+    {
+        if (!is_string($datatype) or $datatype == null or $datatype == '') {
+            throw new InvalidArgumentException(
+                "\$datatype should be a string and cannot be null or empty"
+            );
+        }
+
+        $datatype = EasyRdf_Namespace::expand($datatype);
+        if (isset(self::$datatypeMap[$datatype])) {
+            $class = self::$datatypeMap[$datatype];
+            unset(self::$datatypeMap[$datatype]);
+            unset(self::$classMap[$class]);
+        }
+    }
+
+    /** Get datatype URI for a PHP value.
+     *
+     * This static function is intended for internal use.
+     * Given a PHP value, it will return an XSD datatype
+     * URI for that value, for example:
+     * http://www.w3.org/2001/XMLSchema#integer
+     *
+     * @return string  A URI for the datatype of $value.
+     */
+    public static function getDatatypeForValue($value)
+    {
+        if (is_float($value)) {
+            return 'http://www.w3.org/2001/XMLSchema#decimal';
+        } elseif (is_int($value)) {
+            return 'http://www.w3.org/2001/XMLSchema#integer';
+        } elseif (is_bool($value)) {
+            return 'http://www.w3.org/2001/XMLSchema#boolean';
+        } elseif (is_object($value) and $value instanceof DateTime) {
+            return 'http://www.w3.org/2001/XMLSchema#dateTime';
+        } else {
+            return null;
+        }
+    }
+
+
+
+    /** Constructor for creating a new literal
+     *
+     * @param  string $value     The value of the literal
+     * @param  string $lang      The natural language of the literal or null (e.g. 'en')
+     * @param  string $datatype  The datatype of the literal or null (e.g. 'xsd:string')
+     * @return object EasyRdf_Literal
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        $this->value = $value;
+        $this->lang = $lang ? $lang : null;
+        $this->datatype = $datatype ? $datatype : null;
+
+        if ($this->datatype) {
+            if (is_object($this->datatype)) {
+                // Convert objects to strings
+                $this->datatype = strval($this->datatype);
+            } else {
+                // Expand shortened URIs (CURIEs)
+                $this->datatype = EasyRdf_Namespace::expand($this->datatype);
+            }
+
+            // Literals can not have both a language and a datatype
+            $this->lang = null;
+        } else {
+            // Set the datatype based on the subclass
+            $class = get_class($this);
+            if (isset(self::$classMap[$class])) {
+                $this->datatype = self::$classMap[$class];
+                $this->lang = null;
+            }
+        }
+
+        // Cast value to string
+        settype($this->value, 'string');
+    }
+
+    /** Returns the value of the literal.
+     *
+     * @return string  Value of this literal.
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /** Returns the full datatype URI of the literal.
+     *
+     * @return string  Datatype URI of this literal.
+     */
+    public function getDatatypeUri()
+    {
+        return $this->datatype;
+    }
+
+    /** Returns the shortened datatype URI of the literal.
+     *
+     * @return string  Datatype of this literal (e.g. xsd:integer).
+     */
+    public function getDatatype()
+    {
+        if ($this->datatype) {
+            return EasyRdf_Namespace::shorten($this->datatype);
+        } else {
+            return null;
+        }
+    }
+
+    /** Returns the language of the literal.
+     *
+     * @return string  Language of this literal.
+     */
+    public function getLang()
+    {
+        return $this->lang;
+    }
+
+    /** Returns the properties of the literal as an associative array
+     *
+     * For example:
+     * array('type' => 'literal', 'value' => 'string value')
+     *
+     * @return array  The properties of the literal
+     */
+    public function toArray()
+    {
+        $array = array(
+            'type' => 'literal',
+            'value' => $this->value
+        );
+
+        if ($this->datatype) {
+            $array['datatype'] = $this->datatype;
+        }
+
+        if ($this->lang) {
+            $array['lang'] = $this->lang;
+        }
+
+        return $array;
+    }
+
+    /** Magic method to return the value of a literal as a string
+     *
+     * @return string The value of the literal
+     */
+    public function __toString()
+    {
+        return isset($this->value) ? $this->value : '';
+    }
+
+    /** Return pretty-print view of the literal
+     *
+     * @param  bool   $html  Set to true to format the dump using HTML
+     * @param  string $color The colour of the text
+     * @return string
+     */
+    public function dumpValue($html = true, $color = 'black')
+    {
+        return EasyRdf_Utils::dumpLiteralValue($this, $html, $color);
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Boolean.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Boolean.php
new file mode 100644
index 000000000000..d43863a99646
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Boolean.php
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal of datatype xsd:boolean
+ *
+ * @package    EasyRdf
+ * @link       http://www.w3.org/TR/xmlschema-2/#boolean
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal_Boolean extends EasyRdf_Literal
+{
+    /** Constructor for creating a new boolean literal
+     *
+     * If the value is not a string, then it will be converted to 'true' or 'false'.
+     *
+     * @param  mixed  $value     The value of the literal
+     * @param  string $lang      Should be null (literals with a datatype can't have a language)
+     * @param  string $datatype  Optional datatype (default 'xsd:boolean')
+     * @return object EasyRdf_Literal_Boolean
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        if (!is_string($value)) {
+            $value = $value ? 'true' : 'false';
+        }
+        parent::__construct($value, null, $datatype);
+    }
+
+    /** Return the value of the literal cast to a PHP bool
+     *
+     * If the value is 'true' or '1' return true, otherwise returns false.
+     *
+     * @return bool
+     */
+    public function getValue()
+    {
+        return strtolower($this->value) === 'true' or $this->value === '1';
+    }
+
+    /** Return true if the value of the literal is 'true' or '1'
+     *
+     * @return bool
+     */
+    public function isTrue()
+    {
+        return strtolower($this->value) === 'true' or $this->value === '1';
+    }
+
+    /** Return true if the value of the literal is 'false' or '0'
+     *
+     * @return bool
+     */
+    public function isFalse()
+    {
+        return strtolower($this->value) === 'false' or $this->value === '0';
+    }
+}
+
+EasyRdf_Literal::setDatatypeMapping('xsd:boolean', 'EasyRdf_Literal_Boolean');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Date.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Date.php
new file mode 100644
index 000000000000..fb1a687b11b9
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Date.php
@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal of datatype xsd:date
+ *
+ * @package    EasyRdf
+ * @link       http://www.w3.org/TR/xmlschema-2/#date
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal_Date extends EasyRdf_Literal
+{
+    /** Constructor for creating a new date literal
+     *
+     * If the value is a DateTime object, then it will be converted to the xsd:date format.
+     *
+     * @see DateTime
+     *
+     * @param  mixed  $value     The value of the literal
+     * @param  string $lang      Should be null (literals with a datatype can't have a language)
+     * @param  string $datatype  Optional datatype (default 'xsd:date')
+     * @return object EasyRdf_Literal_Date
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        // Convert DateTime object into string
+        if ($value instanceof DateTime) {
+            $value = $value->format('Y-m-d');
+        }
+
+        parent::__construct($value, null, $datatype);
+    }
+
+    /** Parses a string using DateTime and creates a new literal
+     *
+     * Example:
+     *   $date = EasyRdf_Literal_Date::parse('1 January 2011');
+     *
+     * @see DateTime
+     * @param string $value The date to parse
+     * @return object EasyRdf_Literal_Date
+     */
+    public static function parse($value)
+    {
+        $value = new DateTime($value);
+        return new EasyRdf_Literal_Date($value);
+    }
+
+    /** Returns the date as a PHP DateTime object
+     *
+     * @see DateTime::format
+     * @return string
+     */
+    public function getValue()
+    {
+        return new DateTime($this->value);
+    }
+
+    /** Returns date formatted according to given format
+     *
+     * @see DateTime::format
+     * @param string $format
+     * @return string
+     */
+    public function format($format)
+    {
+        return $this->getValue()->format($format);
+    }
+
+    /** A full integer representation of the year, 4 digits
+     *
+     * @return integer
+     */
+    public function year()
+    {
+        return (int)$this->format('Y');
+    }
+
+    /** Integer representation of the month
+     *
+     * @return integer
+     */
+    public function month()
+    {
+        return (int)$this->format('m');
+    }
+
+    /** Integer representation of the day of the month
+     *
+     * @return integer
+     */
+    public function day()
+    {
+        return (int)$this->format('d');
+    }
+}
+
+EasyRdf_Literal::setDatatypeMapping('xsd:date', 'EasyRdf_Literal_Date');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/DateTime.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/DateTime.php
new file mode 100644
index 000000000000..577badf2bfdf
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/DateTime.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal of datatype xsd:dateTime
+ *
+ * @package    EasyRdf
+ * @link       http://www.w3.org/TR/xmlschema-2/#date
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal_DateTime extends EasyRdf_Literal_Date
+{
+    /** Constructor for creating a new date and time literal
+     *
+     * If the value is a DateTime object, then it will be converted to the xsd:dateTime format.
+     *
+     * @see DateTime
+     *
+     * @param  mixed  $value     The value of the literal
+     * @param  string $lang      Should be null (literals with a datatype can't have a language)
+     * @param  string $datatype  Optional datatype (default 'xsd:dateTime')
+     * @return object EasyRdf_Literal_DateTime
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        // Convert DateTime objects into string
+        if ($value instanceof DateTime) {
+            $iso = $value->format(DateTime::ISO8601);
+            $value = preg_replace('/[\+\-]00(\:?)00$/', 'Z', $iso);
+        }
+
+        EasyRdf_Literal::__construct($value, null, $datatype);
+    }
+
+    /** Parses a string using DateTime and creates a new literal
+     *
+     * Example:
+     *   $dt = EasyRdf_Literal_DateTime::parse('Mon 18 Jul 2011 18:45:43 BST');
+     *
+     * @see DateTime
+     * @param string $value The date and time to parse
+     * @return object EasyRdf_Literal_DateTime
+     */
+    public static function parse($value)
+    {
+        $value = new DateTime($value);
+        return new EasyRdf_Literal_DateTime($value);
+    }
+
+    /** 24-hour format of the hour as an integer
+     *
+     * @return integer
+     */
+    public function hour()
+    {
+        return (int)$this->format('H');
+    }
+
+    /** The minutes pasts the hour as an integer
+     *
+     * @return integer
+     */
+    public function min()
+    {
+        return (int)$this->format('i');
+    }
+
+    /** The seconds pasts the minute as an integer
+     *
+     * @return integer
+     */
+    public function sec()
+    {
+        return (int)$this->format('s');
+    }
+}
+
+EasyRdf_Literal::setDatatypeMapping('xsd:dateTime', 'EasyRdf_Literal_DateTime');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Decimal.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Decimal.php
new file mode 100644
index 000000000000..680c9781cb92
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Decimal.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal of datatype xsd:decimal
+ *
+ * @package    EasyRdf
+ * @link       http://www.w3.org/TR/xmlschema-2/#decimal
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal_Decimal extends EasyRdf_Literal
+{
+    /** Constructor for creating a new decimal literal
+     *
+     * @param  mixed  $value     The value of the literal
+     * @param  string $lang      Should be null (literals with a datatype can't have a language)
+     * @param  string $datatype  Optional datatype (default 'xsd:decimal')
+     * @return object EasyRdf_Literal_Decimal
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        parent::__construct($value, null, $datatype);
+    }
+
+    /** Return the value of the literal cast to a PHP double
+     *
+     * @return double
+     */
+    public function getValue()
+    {
+        return (double)$this->value;
+    }
+}
+
+EasyRdf_Literal::setDatatypeMapping('xsd:decimal', 'EasyRdf_Literal_Decimal');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/HTML.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/HTML.php
new file mode 100644
index 000000000000..2d0f9381f573
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/HTML.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2013 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2013 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal of datatype rdf:HTML
+ *
+ * @package    EasyRdf
+ * @link       http://www.w3.org/TR/rdf11-concepts/#section-html
+ * @copyright  Copyright (c) 2009-2013 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal_HTML extends EasyRdf_Literal
+{
+    /** Constructor for creating a new rdf:HTML literal
+     *
+     * @param  mixed  $value     The HTML fragment
+     * @param  string $lang      Should be null (literals with a datatype can't have a language)
+     * @param  string $datatype  Optional datatype (default 'rdf:HTML')
+     * @return object EasyRdf_Literal_HTML
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        parent::__construct($value, null, $datatype);
+    }
+
+    /** Strip the HTML tags from the literal
+     *
+     * @link   http://php.net/manual/en/function.strip-tags.php
+     * @param  string $allowableTags  Optional allowed tag, not be be removed
+     * @return string The literal as plain text
+     */
+    public function stripTags($allowableTags = null)
+    {
+        return strip_tags($this->value, $allowableTags);
+    }
+}
+
+EasyRdf_Literal::setDatatypeMapping('rdf:HTML', 'EasyRdf_Literal_HTML');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/HexBinary.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/HexBinary.php
new file mode 100644
index 000000000000..2077a6e5fd77
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/HexBinary.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal of datatype xsd:hexBinary
+ *
+ * @package    EasyRdf
+ * @link       http://www.w3.org/TR/xmlschema-2/#hexBinary
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal_HexBinary extends EasyRdf_Literal
+{
+    /** Constructor for creating a new xsd:hexBinary literal
+     *
+     * @param  mixed  $value     The value of the literal (already encoded as hexadecimal)
+     * @param  string $lang      Should be null (literals with a datatype can't have a language)
+     * @param  string $datatype  Optional datatype (default 'xsd:hexBinary')
+     * @return object EasyRdf_Literal_HexBinary
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        // Normalise the canonical representation, as specified here:
+        // http://www.w3.org/TR/xmlschema-2/#hexBinary-canonical-repr
+        $value = strtoupper($value);
+
+        // Validate the data
+        if (preg_match("/[^A-F0-9]/", $value)) {
+            throw new InvalidArgumentException(
+                "Literal of type xsd:hexBinary contains non-hexadecimal characters"
+            );
+        }
+
+        parent::__construct(strtoupper($value), null, 'xsd:hexBinary');
+    }
+
+    /** Constructor for creating a new literal object from a binary blob
+     *
+     * @param  string $binary  The binary data
+     * @return object EasyRdf_Literal_HexBinary
+     */
+    public static function fromBinary($binary)
+    {
+        return new self( bin2hex($binary) );
+    }
+
+    /** Decode the hexadecimal string into a binary blob
+     *
+     * @return string The binary blob
+     */
+    public function toBinary()
+    {
+        return pack("H*", $this->value);
+    }
+}
+
+EasyRdf_Literal::setDatatypeMapping('xsd:hexBinary', 'EasyRdf_Literal_HexBinary');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Integer.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Integer.php
new file mode 100644
index 000000000000..b12682e084e5
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/Integer.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal of datatype xsd:integer
+ *
+ * @package    EasyRdf
+ * @link       http://www.w3.org/TR/xmlschema-2/#integer
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal_Integer extends EasyRdf_Literal
+{
+    /** Constructor for creating a new integer literal
+     *
+     * @param  mixed  $value     The value of the literal
+     * @param  string $lang      Should be null (literals with a datatype can't have a language)
+     * @param  string $datatype  Optional datatype (default 'xsd:integer')
+     * @return object EasyRdf_Literal_Integer
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        parent::__construct($value, null, $datatype);
+    }
+
+    /** Return the value of the literal cast to a PHP int
+     *
+     * @return double
+     */
+    public function getValue()
+    {
+        return (int)$this->value;
+    }
+}
+
+EasyRdf_Literal::setDatatypeMapping('xsd:integer', 'EasyRdf_Literal_Integer');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/XML.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/XML.php
new file mode 100644
index 000000000000..0a90c32d9748
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Literal/XML.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2013 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2013 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF Literal of datatype rdf:XMLLiteral
+ *
+ * @package    EasyRdf
+ * @link       http://www.w3.org/TR/REC-rdf-syntax/#section-Syntax-XML-literals
+ * @copyright  Copyright (c) 2009-2013 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Literal_XML extends EasyRdf_Literal
+{
+    /** Constructor for creating a new rdf:XMLLiteral literal
+     *
+     * @param  mixed  $value     The XML fragment
+     * @param  string $lang      Should be null (literals with a datatype can't have a language)
+     * @param  string $datatype  Optional datatype (default 'rdf:XMLLiteral')
+     * @return object EasyRdf_Literal_XML
+     */
+    public function __construct($value, $lang = null, $datatype = null)
+    {
+        parent::__construct($value, null, $datatype);
+    }
+
+    /** Parse the XML literal into a DOMDocument
+     *
+     * @link   http://php.net/manual/en/domdocument.loadxml.php
+     * @return object DOMDocument
+     */
+    public function domParse()
+    {
+        $dom = new DOMDocument();
+        $dom->loadXML($this->value);
+        return $dom;
+    }
+}
+
+EasyRdf_Literal::setDatatypeMapping('rdf:XMLLiteral', 'EasyRdf_Literal_XML');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Namespace.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Namespace.php
new file mode 100644
index 000000000000..61437b54b9f6
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Namespace.php
@@ -0,0 +1,349 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * A namespace registry and manipulation class.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Namespace
+{
+    /** Namespace registry
+     *
+     * List of default namespaces come from:
+     *  - http://www.w3.org/2011/rdfa-context/rdfa-1.1
+     *
+     * With a few extras added.
+     *
+     */
+    private static $namespaces = array(
+      'bibo' => 'http://purl.org/ontology/bibo/',
+      'cc' => 'http://creativecommons.org/ns#',
+      'cert' => 'http://www.w3.org/ns/auth/cert#',
+      'ctag' => 'http://commontag.org/ns#',
+      'dc' => 'http://purl.org/dc/terms/',
+      'dc11' => 'http://purl.org/dc/elements/1.1/',
+      'dcterms' => 'http://purl.org/dc/terms/',
+      'doap' => 'http://usefulinc.com/ns/doap#',
+      'exif' => 'http://www.w3.org/2003/12/exif/ns#',
+      'foaf' => 'http://xmlns.com/foaf/0.1/',
+      'geo' => 'http://www.w3.org/2003/01/geo/wgs84_pos#',
+      'gr' => 'http://purl.org/goodrelations/v1#',
+      'grddl' => 'http://www.w3.org/2003/g/data-view#',
+      'ical' => 'http://www.w3.org/2002/12/cal/icaltzd#',
+      'ma' => 'http://www.w3.org/ns/ma-ont#',
+      'og' => 'http://ogp.me/ns#',
+      'owl' => 'http://www.w3.org/2002/07/owl#',
+      'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
+      'rdfa' => 'http://www.w3.org/ns/rdfa#',
+      'rdfs' => 'http://www.w3.org/2000/01/rdf-schema#',
+      'rev' => 'http://purl.org/stuff/rev#',
+      'rif' => 'http://www.w3.org/2007/rif#',
+      'rss' => 'http://purl.org/rss/1.0/',
+      'schema' => 'http://schema.org/',
+      'sioc' => 'http://rdfs.org/sioc/ns#',
+      'skos' => 'http://www.w3.org/2004/02/skos/core#',
+      'skosxl' => 'http://www.w3.org/2008/05/skos-xl#',
+      'synd' => 'http://purl.org/rss/1.0/modules/syndication/',
+      'v' => 'http://rdf.data-vocabulary.org/#',
+      'vcard' => 'http://www.w3.org/2006/vcard/ns#',
+      'void' => 'http://rdfs.org/ns/void#',
+      'wdr' => 'http://www.w3.org/2007/05/powder#',
+      'wdrs' => 'http://www.w3.org/2007/05/powder-s#',
+      'wot' => 'http://xmlns.com/wot/0.1/',
+      'xhv' => 'http://www.w3.org/1999/xhtml/vocab#',
+      'xml' => 'http://www.w3.org/XML/1998/namespace',
+      'xsd' => 'http://www.w3.org/2001/XMLSchema#',
+    );
+
+    private static $default = null;
+
+    /** Counter for numbering anonymous namespaces */
+    private static $anonymousNamespaceCount = 0;
+
+    /**
+      * Return all the namespaces registered
+      *
+      * @return array Associative array of all the namespaces.
+      */
+    public static function namespaces()
+    {
+        return self::$namespaces;
+    }
+
+    /**
+      * Return a namespace given its prefix.
+      *
+      * @param string $prefix The namespace prefix (eg 'foaf')
+      * @return string The namespace URI (eg 'http://xmlns.com/foaf/0.1/')
+      */
+    public static function get($prefix)
+    {
+        if (!is_string($prefix) or $prefix === null or $prefix === '') {
+            throw new InvalidArgumentException(
+                "\$prefix should be a string and cannot be null or empty"
+            );
+        }
+
+        if (preg_match('/\W/', $prefix)) {
+            throw new InvalidArgumentException(
+                "\$prefix should only contain alpha-numeric characters"
+            );
+        }
+
+        $prefix = strtolower($prefix);
+        if (array_key_exists($prefix, self::$namespaces)) {
+            return self::$namespaces[$prefix];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+      * Register a new namespace.
+      *
+      * @param string $prefix The namespace prefix (eg 'foaf')
+      * @param string $long The namespace URI (eg 'http://xmlns.com/foaf/0.1/')
+      */
+    public static function set($prefix, $long)
+    {
+        if (!is_string($prefix) or $prefix === null or $prefix === '') {
+            throw new InvalidArgumentException(
+                "\$prefix should be a string and cannot be null or empty"
+            );
+        }
+
+        if (preg_match('/\W/', $prefix)) {
+            throw new InvalidArgumentException(
+                "\$prefix should only contain alpha-numeric characters"
+            );
+        }
+
+        if (!is_string($long) or $long === null or $long === '') {
+            throw new InvalidArgumentException(
+                "\$long should be a string and cannot be null or empty"
+            );
+        }
+
+        $prefix = strtolower($prefix);
+        self::$namespaces[$prefix] = $long;
+    }
+
+    /**
+      * Get the default namespace
+      *
+      * Returns the URI of the default namespace or null
+      * if no default namespace is defined.
+      *
+      * @return string The URI of the default namespace
+      */
+    public static function getDefault()
+    {
+        return self::$default;
+    }
+
+    /**
+      * Set the default namespace
+      *
+      * Set the default namespace to either a URI or the prefix of
+      * an already defined namespace.
+      *
+      * Example:
+      *   EasyRdf_Namespace::setDefault('http://schema.org/');
+      *
+      * @param string $namespace The URI or prefix of a namespace (eg 'og')
+      */
+    public static function setDefault($namespace)
+    {
+        if (empty($namespace)) {
+            self::$default = null;
+        } elseif (preg_match("/^\w+$/", $namespace)) {
+            if (isset(self::$namespaces[$namespace])) {
+                self::$default = self::$namespaces[$namespace];
+            } else {
+                throw new InvalidArgumentException(
+                    "Unable to set default namespace to unknown prefix: $namespace"
+                );
+            }
+        } else {
+            self::$default = $namespace;
+        }
+    }
+
+    /**
+      * Delete an existing namespace.
+      *
+      * @param string $prefix The namespace prefix (eg 'foaf')
+      */
+    public static function delete($prefix)
+    {
+        if (!is_string($prefix) or $prefix === null or $prefix === '') {
+            throw new InvalidArgumentException(
+                "\$prefix should be a string and cannot be null or empty"
+            );
+        }
+
+        $prefix = strtolower($prefix);
+        if (isset(self::$namespaces[$prefix])) {
+            unset(self::$namespaces[$prefix]);
+        }
+    }
+
+    /**
+      * Delete the anonymous namespaces and reset the counter to 0
+      */
+    public static function reset()
+    {
+        while (self::$anonymousNamespaceCount > 0) {
+            self::delete('ns'.(self::$anonymousNamespaceCount-1));
+            self::$anonymousNamespaceCount--;
+        }
+    }
+
+    /**
+      * Try and breakup a URI into a prefix and local part
+      *
+      * If $createNamespace is true, and the URI isn't part of an existing
+      * namespace, then EasyRdf will attempt to create a new namespace and
+      * return the name of the new prefix (for example 'ns0', 'term').
+      *
+      * If it isn't possible to split the URI, then null will be returned.
+      *
+      * @param string  $uri The full URI (eg 'http://xmlns.com/foaf/0.1/name')
+      * @param bool    $createNamespace If true, a new namespace will be created
+      * @return array  The split URI (eg 'foaf', 'name') or null
+      */
+    public static function splitUri($uri, $createNamespace = false)
+    {
+        if ($uri === null or $uri === '') {
+            throw new InvalidArgumentException(
+                "\$uri cannot be null or empty"
+            );
+        }
+
+        if (is_object($uri) and ($uri instanceof EasyRdf_Resource)) {
+            $uri = $uri->getUri();
+        } elseif (!is_string($uri)) {
+            throw new InvalidArgumentException(
+                "\$uri should be a string or EasyRdf_Resource"
+            );
+        }
+
+        foreach (self::$namespaces as $prefix => $long) {
+            if (substr($uri, 0, strlen($long)) == $long) {
+                return array($prefix, substr($uri, strlen($long)));
+            }
+        }
+
+        if ($createNamespace) {
+            // Try and create a new namespace
+            # FIXME: check the valid characters for an XML element name
+            if (preg_match("/^(.+?)([\w\-]+)$/", $uri, $matches)) {
+                $prefix = "ns".(self::$anonymousNamespaceCount++);
+                self::set($prefix, $matches[1]);
+                return array($prefix, $matches[2]);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+      * Return the prefix namespace that a URI belongs to.
+      *
+      * @param string $uri A full URI (eg 'http://xmlns.com/foaf/0.1/name')
+      * @return string The prefix namespace that it is a part of(eg 'foaf')
+      */
+    public static function prefixOfUri($uri)
+    {
+        if ($parts = self::splitUri($uri)) {
+            return $parts[0];
+        }
+    }
+
+    /**
+      * Shorten a URI by substituting in the namespace prefix.
+      *
+      * If $createNamespace is true, and the URI isn't part of an existing
+      * namespace, then EasyRdf will attempt to create a new namespace and
+      * use that namespace to shorten the URI (for example ns0:term).
+      *
+      * If it isn't possible to shorten the URI, then null will be returned.
+      *
+      * @param string  $uri The full URI (eg 'http://xmlns.com/foaf/0.1/name')
+      * @param bool    $createNamespace If true, a new namespace will be created
+      * @return string The shortened URI (eg 'foaf:name') or null
+      */
+    public static function shorten($uri, $createNamespace = false)
+    {
+        if ($parts = self::splitUri($uri, $createNamespace)) {
+            return implode(':', $parts);
+        }
+    }
+
+    /**
+      * Expand a shortened URI (qname) back into a full URI.
+      *
+      * If it isn't possible to expand the qname, for example if the namespace
+      * isn't registered, then the original string will be returned.
+      *
+      * @param string $shortUri The short URI (eg 'foaf:name')
+      * @return string The full URI (eg 'http://xmlns.com/foaf/0.1/name')
+      */
+    public static function expand($shortUri)
+    {
+        if (!is_string($shortUri) or empty($shortUri)) {
+            throw new InvalidArgumentException(
+                "\$shortUri should be a string and cannot be null or empty"
+            );
+        }
+
+        if (preg_match("/^(\w+?):([\w\-]+)$/", $shortUri, $matches)) {
+            $long = self::get($matches[1]);
+            if ($long) {
+                return $long . $matches[2];
+            }
+        } elseif (preg_match("/^(\w+)$/", $shortUri) and isset(self::$default)) {
+            return self::$default . $shortUri;
+        }
+
+        return $shortUri;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/ParsedUri.php b/core/vendor/njh/easyrdf/lib/EasyRdf/ParsedUri.php
new file mode 100644
index 000000000000..0e9f2456a0b8
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/ParsedUri.php
@@ -0,0 +1,341 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+
+/**
+ * A RFC3986 compliant URI parser
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @link       http://www.ietf.org/rfc/rfc3986.txt
+ */
+class EasyRdf_ParsedUri
+{
+    // For all URIs:
+    private $scheme = null;
+    private $fragment = null;
+
+    // For hierarchical URIs:
+    private $authority = null;
+    private $path = null;
+    private $query = null;
+
+    const URI_REGEX = "|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|";
+
+    /** Constructor for creating a new parsed URI
+     *
+     * The $uri parameter can either be a string or an
+     * associative array with the following keys:
+     * scheme, authority, path, query, fragment
+     *
+     * @param  mixed $uri  The URI as a string or an array
+     * @return object EasyRdf_ParsedUri
+     */
+    public function __construct($uri = null)
+    {
+        if (is_string($uri)) {
+            if (preg_match(self::URI_REGEX, $uri, $matches)) {
+                if (!empty($matches[1])) {
+                    $this->scheme = isset($matches[2]) ? $matches[2] : '';
+                }
+                if (!empty($matches[3])) {
+                    $this->authority = isset($matches[4]) ? $matches[4] : '';
+                }
+                $this->path = isset($matches[5]) ? $matches[5] : '';
+                if (!empty($matches[6])) {
+                    $this->query = isset($matches[7]) ? $matches[7] : '';
+                }
+                if (!empty($matches[8])) {
+                    $this->fragment = isset($matches[9]) ? $matches[9] : '';
+                }
+            }
+        } elseif (is_array($uri)) {
+            $this->scheme = isset($uri['scheme']) ? $uri['scheme'] : null;
+            $this->authority = isset($uri['authority']) ? $uri['authority'] : null;
+            $this->path = isset($uri['path']) ? $uri['path'] : null;
+            $this->query = isset($uri['query']) ? $uri['query'] : null;
+            $this->fragment = isset($uri['fragment']) ? $uri['fragment'] : null;
+        }
+    }
+
+
+    /** Returns true if this is an absolute (complete) URI
+     * @return boolean
+     */
+    public function isAbsolute()
+    {
+        return $this->scheme !== null;
+    }
+
+    /** Returns true if this is an relative (partial) URI
+     * @return boolean
+     */
+    public function isRelative()
+    {
+        return $this->scheme === null;
+    }
+
+    /** Returns the scheme of the URI (e.g. http)
+     * @return string
+     */
+    public function getScheme()
+    {
+        return $this->scheme;
+    }
+
+    /** Sets the scheme of the URI (e.g. http)
+     * @param string $scheme The new value for the scheme of the URI
+     */
+    public function setScheme($scheme)
+    {
+        $this->scheme = $scheme;
+    }
+
+    /** Returns the authority of the URI (e.g. www.example.com:8080)
+     * @return string
+     */
+    public function getAuthority()
+    {
+        return $this->authority;
+    }
+
+    /** Sets the authority of the URI (e.g. www.example.com:8080)
+     * @param string $authority The new value for the authority component of the URI
+     */
+    public function setAuthority($authority)
+    {
+        $this->authority = $authority;
+    }
+
+    /** Returns the path of the URI (e.g. /foo/bar)
+     * @return string
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    /** Set the path of the URI (e.g. /foo/bar)
+     * @param string $path The new value for the path component of the URI
+     */
+    public function setPath($path)
+    {
+        $this->path = $path;
+    }
+
+    /** Returns the query string part of the URI (e.g. foo=bar)
+     * @return string
+     */
+    public function getQuery()
+    {
+        return $this->query;
+    }
+
+    /** Set the query string of the URI (e.g. foo=bar)
+     * @param string $query The new value for the query string component of the URI
+     */
+    public function setQuery($query)
+    {
+        $this->query = $query;
+    }
+
+    /** Returns the fragment part of the URI (i.e. after the #)
+     * @return string
+     */
+    public function getFragment()
+    {
+        return $this->fragment;
+    }
+
+    /** Set the fragment of the URI (i.e. after the #)
+     * @param string $fragment The new value for the fragment component of the URI
+     */
+    public function setFragment($fragment)
+    {
+        $this->fragment = $fragment;
+    }
+
+
+    /**
+     * Normalises the path of this URI if it has one. Normalising a path means
+     * that any unnecessary '.' and '..' segments are removed. For example, the
+     * URI http://example.com/a/b/../c/./d would be normalised to
+     * http://example.com/a/c/d
+     *
+     * @return object EasyRdf_ParsedUri
+     */
+    public function normalise()
+    {
+        if (empty($this->path)) {
+            return $this;
+        }
+
+        // Remove ./ from the start
+        if (substr($this->path, 0, 2) == './') {
+            // Remove both characters
+            $this->path = substr($this->path, 2);
+        }
+
+        // Remove /. from the end
+        if (substr($this->path, -2) == '/.') {
+            // Remove only the last dot, not the slash!
+            $this->path = substr($this->path, 0, -1);
+        }
+
+        if (substr($this->path, -3) == '/..') {
+            $this->path .= '/';
+        }
+
+        // Split the path into its segments
+        $segments = explode('/', $this->path);
+        $newSegments = array();
+
+        // Remove all unnecessary '.' and '..' segments
+        foreach ($segments as $segment) {
+            if ($segment == '..') {
+                // Remove the previous part of the path
+                $count = count($newSegments);
+                if ($count > 0 && $newSegments[$count-1]) {
+                    array_pop($newSegments);
+                }
+            } elseif ($segment == '.') {
+                // Ignore
+                continue;
+            } else {
+                array_push($newSegments, $segment);
+            }
+        }
+
+        // Construct the new normalised path
+        $this->path = implode($newSegments, '/');
+
+        // Allow easy chaining of methods
+        return $this;
+    }
+
+    /**
+     * Resolves a relative URI using this URI as the base URI.
+     */
+    public function resolve($relUri)
+    {
+        // If it is a string, then convert it to a parsed object
+        if (is_string($relUri)) {
+            $relUri = new EasyRdf_ParsedUri($relUri);
+        }
+
+        // This code is based on the pseudocode in section 5.2.2 of RFC3986
+        $target = new EasyRdf_ParsedUri();
+        if ($relUri->scheme) {
+            $target->scheme = $relUri->scheme;
+            $target->authority = $relUri->authority;
+            $target->path = $relUri->path;
+            $target->query = $relUri->query;
+        } else {
+            if ($relUri->authority) {
+                $target->authority = $relUri->authority;
+                $target->path = $relUri->path;
+                $target->query = $relUri->query;
+            } else {
+                if (empty($relUri->path)) {
+                    $target->path = $this->path;
+                    if ($relUri->query) {
+                        $target->query = $relUri->query;
+                    } else {
+                        $target->query = $this->query;
+                    }
+                } else {
+                    if (substr($relUri->path, 0, 1) == '/') {
+                        $target->path = $relUri->path;
+                    } else {
+                        $path = $this->path;
+                        $lastSlash = strrpos($path, '/');
+                        if ($lastSlash !== false) {
+                            $path = substr($path, 0, $lastSlash + 1);
+                        } else {
+                            $path = '/';
+                        }
+
+                        $target->path .= $path . $relUri->path;
+                    }
+                    $target->query = $relUri->query;
+                }
+                $target->authority = $this->authority;
+            }
+            $target->scheme = $this->scheme;
+        }
+
+        $target->fragment = $relUri->fragment;
+
+        $target->normalise();
+
+        return $target;
+    }
+
+    /** Convert the parsed URI back into a string
+     *
+     * @return string The URI as a string
+     */
+    public function toString()
+    {
+        $str = '';
+        if ($this->scheme !== null) {
+            $str .= $this->scheme . ':';
+        }
+        if ($this->authority !== null) {
+            $str .= '//' . $this->authority;
+        }
+        $str .= $this->path;
+        if ($this->query !== null) {
+            $str .= '?' . $this->query;
+        }
+        if ($this->fragment !== null) {
+            $str .= '#' . $this->fragment;
+        }
+        return $str;
+    }
+
+    /** Magic method to convert the URI, when casted, back to a string
+     *
+     * @return string The URI as a string
+     */
+    public function __toString()
+    {
+        return $this->toString();
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser.php
new file mode 100644
index 000000000000..b077847c464a
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser.php
@@ -0,0 +1,150 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Parent class for the EasyRdf parsers
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser
+{
+    /** Mapping from source to graph bnode identifiers */
+    private $bnodeMap = array();
+
+    /** The current graph to insert triples into */
+    protected $graph = null;
+
+    /** The format of the document currently being parsed */
+    protected $format = null;
+
+    /** The base URI for the document currently being parsed */
+    protected $baseUri = null;
+
+    /**
+     * Create a new, unique bnode identifier from a source identifier.
+     * If the source identifier has previously been seen, the
+     * same new bnode identifier is returned.
+     * @ignore
+     */
+    protected function remapBnode($name)
+    {
+        if (!isset($this->bnodeMap[$name])) {
+            $this->bnodeMap[$name] = $this->graph->newBNodeId();
+        }
+        return $this->bnodeMap[$name];
+    }
+
+    /**
+     * Delete the bnode mapping - to be called at the start of a new parse
+     * @ignore
+     */
+    protected function resetBnodeMap()
+    {
+        $this->bnodeMap = array();
+    }
+
+    /**
+     * Check, cleanup parameters and prepare for parsing
+     * @ignore
+     */
+    protected function checkParseParams($graph, $data, $format, $baseUri)
+    {
+        if ($graph == null or !is_object($graph) or
+            !($graph instanceof EasyRdf_Graph)) {
+            throw new InvalidArgumentException(
+                "\$graph should be an EasyRdf_Graph object and cannot be null"
+            );
+        } else {
+            $this->graph = $graph;
+        }
+
+        if ($format == null or $format == '') {
+            throw new InvalidArgumentException(
+                "\$format cannot be null or empty"
+            );
+        } elseif (is_object($format) and $format instanceof EasyRdf_Format) {
+            $this->format = $format = $format->getName();
+        } elseif (!is_string($format)) {
+            throw new InvalidArgumentException(
+                "\$format should be a string or an EasyRdf_Format object"
+            );
+        } else {
+            $this->format = $format;
+        }
+
+        if ($baseUri) {
+            if (!is_string($baseUri)) {
+                throw new InvalidArgumentException(
+                    "\$baseUri should be a string"
+                );
+            } else {
+                $this->baseUri = new EasyRdf_ParsedUri($baseUri);
+            }
+        } else {
+            $this->baseUri = null;
+        }
+
+        // Prepare for parsing
+        $this->resetBnodeMap();
+        $this->tripleCount = 0;
+    }
+
+    /**
+     * Sub-classes must follow this protocol
+     * @ignore
+     */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        throw new EasyRdf_Exception(
+            "This method should be overridden by sub-classes."
+        );
+    }
+
+    /**
+     * Add a triple to the current graph, and keep count of the number of triples
+     * @ignore
+     */
+    protected function addTriple($resource, $property, $value)
+    {
+        $count = $this->graph->add($resource, $property, $value);
+        $this->tripleCount += $count;
+        return $count;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Arc.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Arc.php
new file mode 100644
index 000000000000..e1a4b068d7cc
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Arc.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to parse RDF using the ARC2 library.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_Arc extends EasyRdf_Parser_RdfPhp
+{
+    private static $supportedTypes = array(
+        'rdfxml' => 'RDFXML',
+        'turtle' => 'Turtle',
+        'ntriples' => 'Turtle',
+        'rdfa' => 'SemHTML',
+    );
+
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Parser_Arc
+     */
+    public function __construct()
+    {
+        require_once 'arc/ARC2.php';
+    }
+
+    /**
+      * Parse an RDF document into an EasyRdf_Graph
+      *
+      * @param object EasyRdf_Graph $graph   the graph to load the data into
+      * @param string               $data    the RDF document data
+      * @param string               $format  the format of the input data
+      * @param string               $baseUri the base URI of the data being parsed
+      * @return integer             The number of triples added to the graph
+      */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        parent::checkParseParams($graph, $data, $format, $baseUri);
+
+        if (array_key_exists($format, self::$supportedTypes)) {
+            $className = self::$supportedTypes[$format];
+        } else {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Parser_Arc does not support: $format"
+            );
+        }
+
+        $parser = ARC2::getParser($className);
+        if ($parser) {
+            $parser->parse($baseUri, $data);
+            $rdfphp = $parser->getSimpleIndex(false);
+            return parent::parse($graph, $rdfphp, 'php', $baseUri);
+        } else {
+            throw new EasyRdf_Exception(
+                "ARC2 failed to get a $className parser."
+            );
+        }
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Json.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Json.php
new file mode 100644
index 000000000000..a4a80c98a72f
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Json.php
@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * A pure-php class to parse RDF/JSON with no dependancies.
+ *
+ * http://n2.talis.com/wiki/RDF_JSON_Specification
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_Json extends EasyRdf_Parser_RdfPhp
+{
+    private $jsonLastErrorExists = false;
+
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Parser_Json
+     */
+    public function __construct()
+    {
+        $this->jsonLastErrorExists = function_exists('json_last_error');
+    }
+
+    /** Return the last JSON parser error as a string
+     *
+     * If json_last_error() is not available a generic message will be returned.
+     *
+     * @ignore
+     */
+    protected function jsonLastErrorString()
+    {
+        if ($this->jsonLastErrorExists) {
+            switch (json_last_error()) {
+                case JSON_ERROR_NONE:
+                    return null;
+                case JSON_ERROR_DEPTH:
+                    return "JSON Parse error: the maximum stack depth has been exceeded";
+                case JSON_ERROR_STATE_MISMATCH:
+                    return "JSON Parse error: invalid or malformed JSON";
+                case JSON_ERROR_CTRL_CHAR:
+                    return "JSON Parse error: control character error, possibly incorrectly encoded";
+                case JSON_ERROR_SYNTAX:
+                    return "JSON Parse syntax error";
+                case JSON_ERROR_UTF8:
+                    return "JSON Parse error: malformed UTF-8 characters, possibly incorrectly encoded";
+                default:
+                    return "JSON Parse error: unknown";
+            }
+        } else {
+            return "JSON Parse error";
+        }
+    }
+
+    /** Parse the triple-centric JSON format, as output by libraptor
+     *
+     * http://librdf.org/raptor/api/serializer-json.html
+     *
+     * @ignore
+     */
+    protected function parseJsonTriples($data, $baseUri)
+    {
+        foreach ($data['triples'] as $triple) {
+            if ($triple['subject']['type'] == 'bnode') {
+                $subject = $this->remapBnode($triple['subject']['value']);
+            } else {
+                $subject = $triple['subject']['value'];
+            }
+
+            $predicate = $triple['predicate']['value'];
+
+            if ($triple['object']['type'] == 'bnode') {
+                $object = array(
+                    'type' => 'bnode',
+                    'value' => $this->remapBnode($triple['object']['value'])
+                );
+            } else {
+                $object = $triple['object'];
+            }
+
+            $this->addTriple($subject, $predicate, $object);
+        }
+
+        return $this->tripleCount;
+    }
+
+    /**
+      * Parse RDF/JSON into an EasyRdf_Graph
+      *
+      * @param object EasyRdf_Graph $graph   the graph to load the data into
+      * @param string               $data    the RDF document data
+      * @param string               $format  the format of the input data
+      * @param string               $baseUri the base URI of the data being parsed
+      * @return integer             The number of triples added to the graph
+      */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        $this->checkParseParams($graph, $data, $format, $baseUri);
+
+        if ($format != 'json') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Parser_Json does not support: $format"
+            );
+        }
+
+        $decoded = @json_decode(strval($data), true);
+        if ($decoded === null) {
+            throw new EasyRdf_Exception(
+                $this->jsonLastErrorString()
+            );
+        }
+
+        if (array_key_exists('triples', $decoded)) {
+            return $this->parseJsonTriples($decoded, $baseUri);
+        } else {
+            return parent::parse($graph, $decoded, 'php', $baseUri);
+        }
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Ntriples.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Ntriples.php
new file mode 100644
index 000000000000..af3503ec3dd4
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Ntriples.php
@@ -0,0 +1,199 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * A pure-php class to parse N-Triples with no dependancies.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_Ntriples extends EasyRdf_Parser
+{
+    /**
+     * Decodes an encoded N-Triples string. Any \-escape sequences are substituted
+     * with their decoded value.
+     *
+     * @param  string $str An encoded N-Triples string.
+     * @return The unencoded string.
+     **/
+    protected function unescapeString($str)
+    {
+        if (strpos($str, '\\') === false) {
+            return $str;
+        }
+
+        $mappings = array(
+            't' => chr(0x09),
+            'b' => chr(0x08),
+            'n' => chr(0x0A),
+            'r' => chr(0x0D),
+            'f' => chr(0x0C),
+            '\"' => chr(0x22),
+            '\'' => chr(0x27)
+        );
+        foreach ($mappings as $in => $out) {
+            $str = preg_replace('/\x5c([' . $in . '])/', $out, $str);
+        }
+
+        if (stripos($str, '\u') === false) {
+            return $str;
+        }
+
+        while (preg_match('/\\\(U)([0-9A-F]{8})/', $str, $matches) ||
+               preg_match('/\\\(u)([0-9A-F]{4})/', $str, $matches)) {
+            $no = hexdec($matches[2]);
+            if ($no < 128) {
+                $char = chr($no);
+            } elseif ($no < 2048) {
+                $char = chr(($no >> 6) + 192) .
+                        chr(($no & 63) + 128);
+            } elseif ($no < 65536) {
+                $char = chr(($no >> 12) + 224) .
+                        chr((($no >> 6) & 63) + 128) .
+                        chr(($no & 63) + 128);
+            } elseif ($no < 2097152) {
+                $char = chr(($no >> 18) + 240) .
+                        chr((($no >> 12) & 63) + 128) .
+                        chr((($no >> 6) & 63) + 128) .
+                        chr(($no & 63) + 128);
+            } else {
+                $char = '';
+            }
+            $str = str_replace('\\' . $matches[1] . $matches[2], $char, $str);
+        }
+        return $str;
+    }
+
+    /**
+     * @ignore
+     */
+    protected function parseNtriplesSubject($sub)
+    {
+        if (preg_match('/<([^<>]+)>/', $sub, $matches)) {
+            return $this->unescapeString($matches[1]);
+        } elseif (preg_match('/_:([A-Za-z0-9]*)/', $sub, $matches)) {
+            if (empty($matches[1])) {
+                return $this->graph->newBNodeId();
+            } else {
+                $nodeid = $this->unescapeString($matches[1]);
+                return $this->remapBnode($nodeid);
+            }
+        } else {
+            throw new EasyRdf_Exception(
+                "Failed to parse subject: $sub"
+            );
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    protected function parseNtriplesObject($obj)
+    {
+        if (preg_match('/"(.+)"\^\^<([^<>]+)>/', $obj, $matches)) {
+            return array(
+                'type' => 'literal',
+                'value' => $this->unescapeString($matches[1]),
+                'datatype' => $this->unescapeString($matches[2])
+            );
+        } elseif (preg_match('/"(.+)"@([\w\-]+)/', $obj, $matches)) {
+            return array(
+                'type' => 'literal',
+                'value' => $this->unescapeString($matches[1]),
+                'lang' => $this->unescapeString($matches[2])
+            );
+        } elseif (preg_match('/"(.*)"/', $obj, $matches)) {
+            return array('type' => 'literal', 'value' => $this->unescapeString($matches[1]));
+        } elseif (preg_match('/<([^<>]+)>/', $obj, $matches)) {
+            return array('type' => 'uri', 'value' => $matches[1]);
+        } elseif (preg_match('/_:([A-Za-z0-9]*)/', $obj, $matches)) {
+            if (empty($matches[1])) {
+                return array(
+                    'type' => 'bnode',
+                    'value' => $this->graph->newBNodeId()
+                );
+            } else {
+                $nodeid = $this->unescapeString($matches[1]);
+                return array(
+                    'type' => 'bnode',
+                    'value' => $this->remapBnode($nodeid)
+                );
+            }
+        } else {
+            throw new EasyRdf_Exception(
+                "Failed to parse object: $obj"
+            );
+        }
+    }
+
+    /**
+      * Parse an N-Triples document into an EasyRdf_Graph
+      *
+      * @param object EasyRdf_Graph $graph   the graph to load the data into
+      * @param string               $data    the RDF document data
+      * @param string               $format  the format of the input data
+      * @param string               $baseUri the base URI of the data being parsed
+      * @return integer             The number of triples added to the graph
+      */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        parent::checkParseParams($graph, $data, $format, $baseUri);
+
+        if ($format != 'ntriples') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Parser_Ntriples does not support: $format"
+            );
+        }
+
+        $lines = preg_split("/[\r\n]+/", strval($data));
+        foreach ($lines as $line) {
+            if (preg_match("/^\s*#/", $line)) {
+                continue;
+            } elseif (preg_match("/(.+)\s+<([^<>]+)>\s+(.+)\s*\./", $line, $matches)) {
+                $this->addTriple(
+                    $this->parseNtriplesSubject($matches[1]),
+                    $this->unescapeString($matches[2]),
+                    $this->parseNtriplesObject($matches[3])
+                );
+            }
+        }
+
+        return $this->tripleCount;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Rapper.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Rapper.php
new file mode 100644
index 000000000000..31983b7dfb95
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Rapper.php
@@ -0,0 +1,103 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to parse RDF using the 'rapper' command line tool.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_Rapper extends EasyRdf_Parser_Json
+{
+    private $rapperCmd = null;
+
+    const MINIMUM_RAPPER_VERSION = '1.4.17';
+
+    /**
+     * Constructor
+     *
+     * @param string $rapperCmd Optional path to the rapper command to use.
+     * @return object EasyRdf_Parser_Rapper
+     */
+    public function __construct($rapperCmd = 'rapper')
+    {
+        $result = exec("$rapperCmd --version 2>/dev/null", $output, $status);
+        if ($status != 0) {
+            throw new EasyRdf_Exception(
+                "Failed to execute the command '$rapperCmd': $result"
+            );
+        } elseif (version_compare($result, self::MINIMUM_RAPPER_VERSION) < 0) {
+            throw new EasyRdf_Exception(
+                "Version ".self::MINIMUM_RAPPER_VERSION." or higher of rapper is required."
+            );
+        } else {
+            $this->rapperCmd = $rapperCmd;
+        }
+    }
+
+    /**
+      * Parse an RDF document into an EasyRdf_Graph
+      *
+      * @param object EasyRdf_Graph $graph   the graph to load the data into
+      * @param string               $data    the RDF document data
+      * @param string               $format  the format of the input data
+      * @param string               $baseUri the base URI of the data being parsed
+      * @return integer             The number of triples added to the graph
+      */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        parent::checkParseParams($graph, $data, $format, $baseUri);
+
+        $json = EasyRdf_Utils::execCommandPipe(
+            $this->rapperCmd,
+            array(
+                '--quiet',
+                '--input', $format,
+                '--output', 'json',
+                '--ignore-errors',
+                '--input-uri', $baseUri,
+                '--output-uri', '-', '-'
+            ),
+            $data
+        );
+
+        // Parse in the JSON
+        return parent::parse($graph, $json, 'json', $baseUri);
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/RdfPhp.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/RdfPhp.php
new file mode 100644
index 000000000000..baf92773ebc3
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/RdfPhp.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to parse RDF with no external dependancies.
+ *
+ * http://n2.talis.com/wiki/RDF_PHP_Specification
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_RdfPhp extends EasyRdf_Parser
+{
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Parser_RdfPhp
+     */
+    public function __construct()
+    {
+    }
+
+    /**
+      * Parse RDF/PHP into an EasyRdf_Graph
+      *
+      * @param object EasyRdf_Graph $graph   the graph to load the data into
+      * @param string               $data    the RDF document data
+      * @param string               $format  the format of the input data
+      * @param string               $baseUri the base URI of the data being parsed
+      * @return integer             The number of triples added to the graph
+      */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        $this->checkParseParams($graph, $data, $format, $baseUri);
+
+        if ($format != 'php') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Parser_RdfPhp does not support: $format"
+            );
+        }
+
+        foreach ($data as $subject => $properties) {
+            if (substr($subject, 0, 2) === '_:') {
+                $subject = $this->remapBnode($subject);
+            } elseif (preg_match('/^\w+$/', $subject)) {
+                # Cope with invalid RDF/JSON serialisations that
+                # put the node name in, without the _: prefix
+                # (such as net.fortytwo.sesametools.rdfjson)
+                $subject = $this->remapBnode($subject);
+            }
+
+            foreach ($properties as $property => $objects) {
+                foreach ($objects as $object) {
+                    if ($object['type'] === 'bnode') {
+                        $object['value'] = $this->remapBnode($object['value']);
+                    }
+                    $this->addTriple($subject, $property, $object);
+                }
+            }
+        }
+
+        return $this->tripleCount;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/RdfXml.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/RdfXml.php
new file mode 100644
index 000000000000..06e27cfcd5e3
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/RdfXml.php
@@ -0,0 +1,807 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2010-2011 Nicholas J Humfrey
+ * Copyright (c) 2004-2010 Benjamin Nowack (based on ARC2_RDFXMLParser.php)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+
+/**
+ * A pure-php class to parse RDF/XML.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ *             Copyright (c) 2004-2010 Benjamin Nowack (based on ARC2_RDFXMLParser.php)
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_RdfXml extends EasyRdf_Parser
+{
+    private $state;
+    private $xLang;
+    private $xBase;
+    private $xml;
+    private $rdf;
+    private $nsp;
+    private $sStack;
+    private $sCount;
+
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Parser_RdfXml
+     */
+    public function __construct()
+    {
+    }
+
+    /** @ignore */
+    protected function init($graph, $base)
+    {
+        $this->graph = $graph;
+        $this->state = 0;
+        $this->xLang = null;
+        $this->xBase = new EasyRdf_ParsedUri($base);
+        $this->xml = 'http://www.w3.org/XML/1998/namespace';
+        $this->rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
+        $this->nsp = array($this->xml => 'xml', $this->rdf => 'rdf');
+        $this->sStack = array();
+        $this->sCount = 0;
+    }
+
+    /** @ignore */
+    protected function initXMLParser()
+    {
+        if (!isset($this->xmlParser)) {
+            $parser = xml_parser_create_ns('UTF-8', '');
+            xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
+            xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
+            xml_set_element_handler($parser, 'startElementHandler', 'endElementHandler');
+            xml_set_character_data_handler($parser, 'cdataHandler');
+            xml_set_start_namespace_decl_handler($parser, 'newNamespaceHandler');
+            xml_set_object($parser, $this);
+            $this->xmlParser = $parser;
+        }
+    }
+
+    /** @ignore */
+    protected function pushS(&$s)
+    {
+        $s['pos'] = $this->sCount;
+        $this->sStack[$this->sCount] = $s;
+        $this->sCount++;
+    }
+
+    /** @ignore */
+    protected function popS()
+    {
+        $r = array();
+        $this->sCount--;
+        for ($i = 0, $iMax = $this->sCount; $i < $iMax; $i++) {
+            $r[$i] = $this->sStack[$i];
+        }
+        $this->sStack = $r;
+    }
+
+    /** @ignore */
+    protected function updateS($s)
+    {
+        $this->sStack[$s['pos']] = $s;
+    }
+
+    /** @ignore */
+    protected function getParentS()
+    {
+        if ($this->sCount && isset($this->sStack[$this->sCount - 1])) {
+            return $this->sStack[$this->sCount - 1];
+        } else {
+            return false;
+        }
+    }
+
+    /** @ignore */
+    protected function getParentXBase()
+    {
+        if ($p = $this->getParentS()) {
+            if (isset($p['p_x_base']) && $p['p_x_base']) {
+                return $p['p_x_base'];
+            } elseif (isset($p['x_base'])) {
+                return $p['x_base'];
+            } else {
+                return '';
+            }
+        } else {
+            return $this->xBase;
+        }
+    }
+
+    /** @ignore */
+    protected function getParentXLang()
+    {
+        if ($p = $this->getParentS()) {
+            if (isset($p['p_x_lang']) && $p['p_x_lang']) {
+                return $p['p_x_lang'];
+            } elseif (isset($p['x_lang'])) {
+                return $p['x_lang'];
+            } else {
+                return null;
+            }
+        } else {
+            return $this->xLang;
+        }
+    }
+
+    /** @ignore */
+    protected function splitURI($v)
+    {
+        /* auto-splitting on / or # */
+        if (preg_match('/^(.*[\/\#])([^\/\#]+)$/', $v, $m)) {
+            return array($m[1], $m[2]);
+        }
+        /* auto-splitting on last special char, e.g. urn:foo:bar */
+        if (preg_match('/^(.*[\:\/])([^\:\/]+)$/', $v, $m)) {
+            return array($m[1], $m[2]);
+        }
+        return array($v, '');
+    }
+
+    /** @ignore */
+    protected function add($s, $p, $o, $sType, $oType, $oDatatype = null, $oLang = null)
+    {
+        $this->addTriple(
+            $s,
+            $p,
+            array(
+                'type' => $oType,
+                'value' => $o,
+                'lang' => $oLang,
+                'datatype' => $oDatatype
+            )
+        );
+    }
+
+    /** @ignore */
+    protected function reify($t, $s, $p, $o, $sType, $oType, $oDatatype = null, $oLang = null)
+    {
+        $this->add($t, $this->rdf.'type', $this->rdf.'Statement', 'uri', 'uri');
+        $this->add($t, $this->rdf.'subject', $s, 'uri', $sType);
+        $this->add($t, $this->rdf.'predicate', $p, 'uri', 'uri');
+        $this->add($t, $this->rdf.'object', $o, 'uri', $oType, $oDatatype, $oLang);
+    }
+
+    /** @ignore */
+    protected function startElementHandler($p, $t, $a)
+    {
+        switch($this->state) {
+            case 0:
+                return $this->startState0($t, $a);
+            case 1:
+                return $this->startState1($t, $a);
+            case 2:
+                return $this->startState2($t, $a);
+            case 4:
+                return $this->startState4($t, $a);
+            case 5:
+                return $this->startState5($t, $a);
+            case 6:
+                return $this->startState6($t, $a);
+            default:
+                throw new EasyRdf_Exception(
+                    'startElementHandler() called at state ' . $this->state . ' in '.$t
+                );
+        }
+    }
+
+    /** @ignore */
+    protected function endElementHandler($p, $t)
+    {
+        switch($this->state){
+            case 1:
+                return $this->endState1($t);
+            case 2:
+                return $this->endState2($t);
+            case 3:
+                return $this->endState3($t);
+            case 4:
+                return $this->endState4($t);
+            case 5:
+                return $this->endState5($t);
+            case 6:
+                return $this->endState6($t);
+            default:
+                throw new EasyRdf_Exception(
+                    'endElementHandler() called at state ' . $this->state . ' in '.$t
+                );
+        }
+    }
+
+    /** @ignore */
+    protected function cdataHandler($p, $d)
+    {
+        switch($this->state){
+            case 4:
+                return $this->cdataState4($d);
+            case 6:
+                return $this->cdataState6($d);
+            default:
+                return false;
+        }
+    }
+
+    /** @ignore */
+    protected function newNamespaceHandler($p, $prf, $uri)
+    {
+        $this->nsp[$uri] = isset($this->nsp[$uri]) ? $this->nsp[$uri] : $prf;
+    }
+
+    /** @ignore */
+    protected function startState0($t, $a)
+    {
+        $this->state = 1;
+        if ($t !== $this->rdf.'RDF') {
+            $this->startState1($t, $a);
+        }
+    }
+
+    /** @ignore */
+    protected function startState1($t, $a)
+    {
+        $s = array(
+            'x_base' => $this->getParentXBase(),
+            'x_lang' => $this->getParentXLang(),
+            'li_count' => 0,
+        );
+
+        if (isset($a[$this->xml.'base'])) {
+            $s['x_base'] = $this->xBase->resolve($a[$this->xml.'base']);
+        }
+
+        if (isset($a[$this->xml.'lang'])) {
+            $s['x_lang'] = $a[$this->xml.'lang'];
+        }
+
+        /* ID */
+        if (isset($a[$this->rdf.'ID'])) {
+            $s['type'] = 'uri';
+            $s['value'] = $s['x_base']->resolve('#'.$a[$this->rdf.'ID']);
+            /* about */
+        } elseif (isset($a[$this->rdf.'about'])) {
+            $s['type'] = 'uri';
+            $s['value'] = $s['x_base']->resolve($a[$this->rdf.'about']);
+            /* bnode */
+        } else {
+            $s['type'] = 'bnode';
+            if (isset($a[$this->rdf.'nodeID'])) {
+                $s['value'] = $this->remapBnode($a[$this->rdf.'nodeID']);
+            } else {
+                $s['value'] = $this->graph->newBNodeId();
+            }
+        }
+
+        /* sub-node */
+        if ($this->state === 4) {
+            $supS = $this->getParentS();
+            /* new collection */
+            if (isset($supS['o_is_coll']) && $supS['o_is_coll']) {
+                $coll = array(
+                    'type' => 'bnode',
+                    'value' => $this->graph->newBNodeId(),
+                    'is_coll' => true,
+                    'x_base' => $s['x_base'],
+                    'x_lang' => $s['x_lang']
+                );
+                $this->add($supS['value'], $supS['p'], $coll['value'], $supS['type'], $coll['type']);
+                $this->add($coll['value'], $this->rdf.'first', $s['value'], $coll['type'], $s['type']);
+                $this->pushS($coll);
+
+            } elseif (isset($supS['is_coll']) && $supS['is_coll']) {
+                /* new entry in existing coll */
+                $coll = array(
+                'type' => 'bnode',
+                'value' => $this->graph->newBNodeId(),
+                'is_coll' => true,
+                'x_base' => $s['x_base'],
+                'x_lang' => $s['x_lang']
+                );
+                $this->add($supS['value'], $this->rdf.'rest', $coll['value'], $supS['type'], $coll['type']);
+                $this->add($coll['value'], $this->rdf.'first', $s['value'], $coll['type'], $s['type']);
+                $this->pushS($coll);
+                /* normal sub-node */
+            } elseif (isset($supS['p']) && $supS['p']) {
+                $this->add($supS['value'], $supS['p'], $s['value'], $supS['type'], $s['type']);
+            }
+        }
+        /* typed node */
+        if ($t !== $this->rdf.'Description') {
+            $this->add($s['value'], $this->rdf.'type', $t, $s['type'], 'uri');
+        }
+        /* (additional) typing attr */
+        if (isset($a[$this->rdf.'type'])) {
+            $this->add($s['value'], $this->rdf.'type', $a[$this->rdf.'type'], $s['type'], 'uri');
+        }
+
+        /* Seq|Bag|Alt */
+        // if (in_array($t, array($this->rdf.'Seq', $this->rdf.'Bag', $this->rdf.'Alt'))) {
+        //     # FIXME: what is this?
+        //     $s['is_con'] = true;
+        // }
+
+        /* any other attrs (skip rdf and xml, except rdf:_, rdf:value, rdf:Seq) */
+        foreach ($a as $k => $v) {
+            if (((strpos($k, $this->xml) === false) && (strpos($k, $this->rdf) === false)) ||
+                preg_match('/(\_[0-9]+|value|Seq|Bag|Alt|Statement|Property|List)$/', $k)) {
+                if (strpos($k, ':')) {
+                    $this->add($s['value'], $k, $v, $s['type'], 'literal', null, $s['x_lang']);
+                }
+            }
+        }
+        $this->pushS($s);
+        $this->state = 2;
+    }
+
+    /** @ignore */
+    protected function startState2($t, $a)
+    {
+        $s = $this->getParentS();
+        foreach (array('p_x_base', 'p_x_lang', 'p_id', 'o_is_coll') as $k) {
+            unset($s[$k]);
+        }
+        /* base */
+        if (isset($a[$this->xml.'base'])) {
+            $s['p_x_base'] = $s['x_base']->resolve($a[$this->xml.'base']);
+        }
+        $b = isset($s['p_x_base']) && $s['p_x_base'] ? $s['p_x_base'] : $s['x_base'];
+        /* lang */
+        if (isset($a[$this->xml.'lang'])) {
+            $s['p_x_lang'] = $a[$this->xml.'lang'];
+        }
+        $l = isset($s['p_x_lang']) && $s['p_x_lang'] ? $s['p_x_lang'] : $s['x_lang'];
+        /* adjust li */
+        if ($t === $this->rdf.'li') {
+            $s['li_count']++;
+            $t = $this->rdf.'_'.$s['li_count'];
+        }
+        /* set p */
+        $s['p'] = $t;
+        /* reification */
+        if (isset($a[$this->rdf.'ID'])) {
+            $s['p_id'] = $a[$this->rdf.'ID'];
+        }
+        $o = array('value' => null, 'type' => null, 'x_base' => $b, 'x_lang' => $l);
+        /* resource/rdf:resource */
+        if (isset($a['resource'])) {
+            $a[$this->rdf.'resource'] = $a['resource'];
+            unset($a['resource']);
+        }
+        if (isset($a[$this->rdf.'resource'])) {
+            $o['type'] = 'uri';
+            $o['value'] = $b->resolve($a[$this->rdf.'resource']);
+            $this->add($s['value'], $s['p'], $o['value'], $s['type'], $o['type']);
+            /* type */
+            if (isset($a[$this->rdf.'type'])) {
+                $this->add(
+                    $o['value'],
+                    $this->rdf.'type',
+                    $a[$this->rdf.'type'],
+                    'uri',
+                    'uri'
+                );
+            }
+            /* reification */
+            if (isset($s['p_id'])) {
+                $this->reify(
+                    $b->resolve('#'.$s['p_id']),
+                    $s['value'],
+                    $s['p'],
+                    $o['value'],
+                    $s['type'],
+                    $o['type']
+                );
+                unset($s['p_id']);
+            }
+            $this->state = 3;
+        } elseif (isset($a[$this->rdf.'nodeID'])) {
+            /* named bnode */
+            $o['value'] = $this->remapBnode($a[$this->rdf.'nodeID']);
+            $o['type'] = 'bnode';
+            $this->add($s['value'], $s['p'], $o['value'], $s['type'], $o['type']);
+            $this->state = 3;
+            /* reification */
+            if (isset($s['p_id'])) {
+                $this->reify(
+                    $b->resolve('#'.$s['p_id']),
+                    $s['value'],
+                    $s['p'],
+                    $o['value'],
+                    $s['type'],
+                    $o['type']
+                );
+            }
+            /* parseType */
+        } elseif (isset($a[$this->rdf.'parseType'])) {
+            if ($a[$this->rdf.'parseType'] === 'Literal') {
+                $s['o_xml_level'] = 0;
+                $s['o_xml_data'] = '';
+                $s['p_xml_literal_level'] = 0;
+                $s['ns'] = array();
+                $this->state = 6;
+            } elseif ($a[$this->rdf.'parseType'] === 'Resource') {
+                $o['value'] = $this->graph->newBNodeId();
+                $o['type'] = 'bnode';
+                $o['hasClosingTag'] = 0;
+                $this->add($s['value'], $s['p'], $o['value'], $s['type'], $o['type']);
+                $this->pushS($o);
+                /* reification */
+                if (isset($s['p_id'])) {
+                    $this->reify(
+                        $b->resolve('#'.$s['p_id']),
+                        $s['value'],
+                        $s['p'],
+                        $o['value'],
+                        $s['type'],
+                        $o['type']
+                    );
+                    unset($s['p_id']);
+                }
+                $this->state = 2;
+            } elseif ($a[$this->rdf.'parseType'] === 'Collection') {
+                $s['o_is_coll'] = true;
+                $this->state = 4;
+            }
+        } else {
+            /* sub-node or literal */
+            $s['o_cdata'] = '';
+            if (isset($a[$this->rdf.'datatype'])) {
+                $s['o_datatype'] = $a[$this->rdf.'datatype'];
+            }
+            $this->state = 4;
+        }
+        /* any other attrs (skip rdf and xml) */
+        foreach ($a as $k => $v) {
+            if (((strpos($k, $this->xml) === false) &&
+             (strpos($k, $this->rdf) === false)) ||
+             preg_match('/(\_[0-9]+|value)$/', $k)) {
+                if (strpos($k, ':')) {
+                    if (!$o['value']) {
+                        $o['value'] = $this->graph->newBNodeId();
+                        $o['type'] = 'bnode';
+                        $this->add($s['value'], $s['p'], $o['value'], $s['type'], $o['type']);
+                    }
+                    /* reification */
+                    if (isset($s['p_id'])) {
+                        $this->reify(
+                            $b->resolve('#'.$s['p_id']),
+                            $s['value'],
+                            $s['p'],
+                            $o['value'],
+                            $s['type'],
+                            $o['type']
+                        );
+                        unset($s['p_id']);
+                    }
+                    $this->add($o['value'], $k, $v, $o['type'], 'literal');
+                    $this->state = 3;
+                }
+            }
+        }
+        $this->updateS($s);
+    }
+
+    /** @ignore */
+    protected function startState4($t, $a)
+    {
+        return $this->startState1($t, $a);
+    }
+
+    /** @ignore */
+    protected function startState5($t, $a)
+    {
+        $this->state = 4;
+        return $this->startState4($t, $a);
+    }
+
+    /** @ignore */
+    protected function startState6($t, $a)
+    {
+        $s = $this->getParentS();
+        $data = isset($s['o_xml_data']) ? $s['o_xml_data'] : '';
+        $ns = isset($s['ns']) ? $s['ns'] : array();
+        $parts = $this->splitURI($t);
+        if (count($parts) === 1) {
+            $data .= '<'.$t;
+        } else {
+            $nsUri = $parts[0];
+            $name = $parts[1];
+            if (!isset($this->nsp[$nsUri])) {
+                foreach ($this->nsp as $tmp1 => $tmp2) {
+                    if (strpos($t, $tmp1) === 0) {
+                        $nsUri = $tmp1;
+                        $name = substr($t, strlen($tmp1));
+                        break;
+                    }
+                }
+            }
+
+            $nsp = isset($this->nsp[$nsUri]) ? $this->nsp[$nsUri] : '';
+            $data .= $nsp ? '<' . $nsp . ':' . $name : '<' . $name;
+            /* ns */
+            if (!isset($ns[$nsp.'='.$nsUri]) || !$ns[$nsp.'='.$nsUri]) {
+                $data .= $nsp ? ' xmlns:'.$nsp.'="'.$nsUri.'"' : ' xmlns="'.$nsUri.'"';
+                $ns[$nsp.'='.$nsUri] = true;
+                $s['ns'] = $ns;
+            }
+        }
+        foreach ($a as $k => $v) {
+            $parts = $this->splitURI($k);
+            if (count($parts) === 1) {
+                $data .= ' '.$k.'="'.$v.'"';
+            } else {
+                $nsUri = $parts[0];
+                $name = $parts[1];
+                $nsp = isset($this->nsp[$nsUri]) ? $this->nsp[$nsUri] : '';
+                $data .= $nsp ? ' '.$nsp.':'.$name.'="'.$v.'"' : ' '.$name.'="'.$v.'"' ;
+            }
+        }
+        $data .= '>';
+        $s['o_xml_data'] = $data;
+        $s['o_xml_level'] = isset($s['o_xml_level']) ? $s['o_xml_level'] + 1 : 1;
+        if ($t == $s['p']) {/* xml container prop */
+            $s['p_xml_literal_level'] = isset($s['p_xml_literal_level']) ? $s['p_xml_literal_level'] + 1 : 1;
+        }
+        $this->updateS($s);
+    }
+
+    /** @ignore */
+    protected function endState1($t)
+    {
+        /* end of doc */
+        $this->state = 0;
+    }
+
+    /** @ignore */
+    protected function endState2($t)
+    {
+        /* expecting a prop, getting a close */
+        if ($s = $this->getParentS()) {
+            $hasClosingTag = (isset($s['hasClosingTag']) && !$s['hasClosingTag']) ? 0 : 1;
+            $this->popS();
+            $this->state = 5;
+            if ($s = $this->getParentS()) {
+                /* new s */
+                if (!isset($s['p']) || !$s['p']) {
+                    /* p close after collection|parseType=Resource|node close after p close */
+                    $this->state = $this->sCount ? 4 : 1;
+                    if (!$hasClosingTag) {
+                        $this->state = 2;
+                    }
+                } elseif (!$hasClosingTag) {
+                    $this->state = 2;
+                }
+            }
+        }
+    }
+
+    /** @ignore */
+    protected function endState3($t)
+    {
+        /* p close */
+        $this->state = 2;
+    }
+
+    /** @ignore */
+    protected function endState4($t)
+    {
+        /* empty p | pClose after cdata | pClose after collection */
+        if ($s = $this->getParentS()) {
+            $b = isset($s['p_x_base']) && $s['p_x_base'] ?
+                $s['p_x_base'] : (isset($s['x_base']) ? $s['x_base'] : '');
+            if (isset($s['is_coll']) && $s['is_coll']) {
+                $this->add($s['value'], $this->rdf.'rest', $this->rdf.'nil', $s['type'], 'uri');
+                /* back to collection start */
+                while ((!isset($s['p']) || ($s['p'] != $t))) {
+                    $subS = $s;
+                    $this->popS();
+                    $s = $this->getParentS();
+                }
+                /* reification */
+                if (isset($s['p_id']) && $s['p_id']) {
+                    $this->reify(
+                        $b->resolve('#'.$s['p_id']),
+                        $s['value'],
+                        $s['p'],
+                        $subS['value'],
+                        $s['type'],
+                        $subS['type']
+                    );
+                }
+                unset($s['p']);
+                $this->updateS($s);
+            } else {
+                $dt = isset($s['o_datatype']) ? $s['o_datatype'] : null;
+                $l = isset($s['p_x_lang']) && $s['p_x_lang'] ?
+                     $s['p_x_lang'] : (isset($s['x_lang']) ? $s['x_lang'] : null);
+                $o = array('type' => 'literal', 'value' => $s['o_cdata']);
+                $this->add(
+                    $s['value'],
+                    $s['p'],
+                    $o['value'],
+                    $s['type'],
+                    $o['type'],
+                    $dt,
+                    $l
+                );
+                /* reification */
+                if (isset($s['p_id']) && $s['p_id']) {
+                    $this->reify(
+                        $b->resolve('#'.$s['p_id']),
+                        $s['value'],
+                        $s['p'],
+                        $o['value'],
+                        $s['type'],
+                        $o['type'],
+                        $dt,
+                        $l
+                    );
+                }
+                unset($s['o_cdata']);
+                unset($s['o_datatype']);
+                unset($s['p']);
+                $this->updateS($s);
+            }
+            $this->state = 2;
+        }
+    }
+
+    /** @ignore */
+    protected function endState5($t)
+    {
+        /* p close */
+        if ($s = $this->getParentS()) {
+            unset($s['p']);
+            $this->updateS($s);
+            $this->state = 2;
+        }
+    }
+
+    /** @ignore */
+    protected function endState6($t)
+    {
+        if ($s = $this->getParentS()) {
+            $l = isset($s['p_x_lang']) && $s['p_x_lang'] ?
+                $s['p_x_lang'] :
+                (isset($s['x_lang']) ? $s['x_lang'] : null);
+            $data = $s['o_xml_data'];
+            $level = $s['o_xml_level'];
+            if ($level === 0) {
+                /* pClose */
+                $this->add(
+                    $s['value'],
+                    $s['p'],
+                    trim($data, ' '),
+                    $s['type'],
+                    'literal',
+                    $this->rdf.'XMLLiteral',
+                    $l
+                );
+                unset($s['o_xml_data']);
+                $this->state = 2;
+            } else {
+                $parts = $this->splitURI($t);
+                if (count($parts) == 1) {
+                    $data .= '</'.$t.'>';
+                } else {
+                    $nsUri = $parts[0];
+                    $name = $parts[1];
+                    if (!isset($this->nsp[$nsUri])) {
+                        foreach ($this->nsp as $tmp1 => $tmp2) {
+                            if (strpos($t, $tmp1) === 0) {
+                                $nsUri = $tmp1;
+                                $name = substr($t, strlen($tmp1));
+                                break;
+                            }
+                        }
+                    }
+                    $nsp = isset($this->nsp[$nsUri]) ? $this->nsp[$nsUri] : '';
+                    $data .= $nsp ? '</'.$nsp.':'.$name.'>' : '</'.$name.'>';
+                }
+                $s['o_xml_data'] = $data;
+                $s['o_xml_level'] = $level - 1;
+                if ($t == $s['p']) {
+                    /* xml container prop */
+                    $s['p_xml_literal_level']--;
+                }
+            }
+            $this->updateS($s);
+        }
+    }
+
+    /** @ignore */
+    protected function cdataState4($d)
+    {
+        if ($s = $this->getParentS()) {
+            $s['o_cdata'] = isset($s['o_cdata']) ? $s['o_cdata'] . $d : $d;
+            $this->updateS($s);
+        }
+    }
+
+    /** @ignore */
+    protected function cdataState6($d)
+    {
+        if ($s = $this->getParentS()) {
+            if (isset($s['o_xml_data']) || preg_match("/[\n\r]/", $d) || trim($d)) {
+                $d = htmlspecialchars($d, ENT_NOQUOTES);
+                $s['o_xml_data'] = isset($s['o_xml_data']) ? $s['o_xml_data'] . $d : $d;
+            }
+            $this->updateS($s);
+        }
+    }
+
+    /**
+      * Parse an RDF/XML document into an EasyRdf_Graph
+      *
+      * @param object EasyRdf_Graph $graph   the graph to load the data into
+      * @param string               $data    the RDF document data
+      * @param string               $format  the format of the input data
+      * @param string               $baseUri the base URI of the data being parsed
+      * @return integer             The number of triples added to the graph
+      */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        parent::checkParseParams($graph, $data, $format, $baseUri);
+
+        if ($format != 'rdfxml') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Parser_RdfXml does not support: $format"
+            );
+        }
+
+        $this->init($graph, $baseUri);
+        $this->resetBnodeMap();
+
+        /* xml parser */
+        $this->initXMLParser();
+
+        /* parse */
+        if (!xml_parse($this->xmlParser, $data, false)) {
+            throw new EasyRdf_Exception(
+                'XML error: "' . xml_error_string(xml_get_error_code($this->xmlParser)) .
+                '" at line ' . xml_get_current_line_number($this->xmlParser)
+            );
+        }
+
+        xml_parser_free($this->xmlParser);
+
+        return $this->tripleCount;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Rdfa.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Rdfa.php
new file mode 100644
index 000000000000..9e7902bacd7e
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Rdfa.php
@@ -0,0 +1,710 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2012 Nicholas J Humfrey.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ *             Copyright (c) 1997-2006 Aduna (http://www.aduna-software.com/)
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to parse RDFa 1.1 with no external dependancies.
+ *
+ * http://www.w3.org/TR/rdfa-core/
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_Rdfa extends EasyRdf_Parser
+{
+    const XML_NS = 'http://www.w3.org/XML/1998/namespace';
+    const RDF_XML_LITERAL = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral';
+    const TERM_REGEXP = '/^([a-zA-Z_])([0-9a-zA-Z_\.-]*)$/';
+
+    public $debug = false;
+
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Parser_Rdfa
+     */
+    public function __construct()
+    {
+    }
+
+    protected function addTriple($resource, $property, $value)
+    {
+        if ($this->debug) {
+            print "Adding triple: $resource -> $property -> ".$value['type'].':'.$value['value']."\n";
+        }
+        $count = $this->graph->add($resource, $property, $value);
+        $this->tripleCount += $count;
+        return $count;
+    }
+
+    protected function generateList($subject, $property, $list)
+    {
+        $current = $subject;
+        $prop = $property;
+
+        // Output a blank node for each item in the list
+        foreach ($list as $item) {
+            $newNode = $this->graph->newBNodeId();
+            $this->addTriple($current, $prop, array('type' => 'bnode', 'value' => $newNode));
+            $this->addTriple($newNode, 'rdf:first', $item);
+
+            $current = $newNode;
+            $prop = 'rdf:rest';
+        }
+
+        // Finally, terminate the list
+        $this->addTriple(
+            $current,
+            $prop,
+            array('type' => 'uri', 'value' => EasyRdf_Namespace::expand('rdf:nil'))
+        );
+    }
+
+    protected function addToList($listMapping, $property, $value)
+    {
+        if ($this->debug) {
+            print "Adding to list: $property -> ".$value['type'].':'.$value['value']."\n";
+        }
+
+        // Create property in the list mapping if it doesn't already exist
+        if (!isset($listMapping->$property)) {
+            $listMapping->$property = array();
+        }
+        array_push($listMapping->$property, $value);
+    }
+
+    protected function printNode($node, $depth)
+    {
+        $indent = str_repeat('  ', $depth);
+        print $indent;
+        switch($node->nodeType) {
+            case XML_ELEMENT_NODE:
+                print 'node';
+                break;
+            case XML_ATTRIBUTE_NODE:
+                print 'attr';
+                break;
+            case XML_TEXT_NODE:
+                print 'text';
+                break;
+            case XML_CDATA_SECTION_NODE:
+                print 'cdata';
+                break;
+            case XML_ENTITY_REF_NODE:
+                print 'entref';
+                break;
+            case XML_ENTITY_NODE:
+                print 'entity';
+                break;
+            case XML_PI_NODE:
+                print 'pi';
+                break;
+            case XML_COMMENT_NODE:
+                print 'comment';
+                break;
+            case XML_DOCUMENT_NODE:
+                print 'doc';
+                break;
+            case XML_DOCUMENT_TYPE_NODE:
+                print 'doctype';
+                break;
+            case XML_HTML_DOCUMENT_NODE:
+                print 'html';
+                break;
+            default:
+                throw new EasyRdf_Exception("unknown node type: ".$node->nodeType);
+                break;
+        }
+        print ' '.$node->nodeName."\n";
+
+        if ($node->hasAttributes()) {
+            foreach ($node->attributes as $attr) {
+                print $indent.' '.$attr->nodeName." => ".$attr->nodeValue."\n";
+            }
+        }
+    }
+
+    protected function guessTimeDatatype($value)
+    {
+        if (preg_match("/^-?\d{4}-\d{2}-\d{2}(Z|[\-\+]\d{2}:\d{2})?$/", $value)) {
+            return 'http://www.w3.org/2001/XMLSchema#date';
+        } elseif (preg_match("/^\d{2}:\d{2}:\d{2}(Z|[\-\+]\d{2}:\d{2})?$/", $value)) {
+            return 'http://www.w3.org/2001/XMLSchema#time';
+        } elseif (preg_match("/^-?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|[\-\+]\d{2}:\d{2})?$/", $value)) {
+            return 'http://www.w3.org/2001/XMLSchema#dateTime';
+        } elseif (preg_match("/^P(\d+Y)?(\d+M)?(\d+D)?T?(\d+H)?(\d+M)?(\d+S)?$/", $value)) {
+            return 'http://www.w3.org/2001/XMLSchema#duration';
+        } elseif (preg_match("/^\d{4}$/", $value)) {
+            return 'http://www.w3.org/2001/XMLSchema#gYear';
+        } elseif (preg_match("/^\d{4}-\d{2}$/", $value)) {
+            return 'http://www.w3.org/2001/XMLSchema#gYearMonth';
+        } else {
+            return null;
+        }
+    }
+
+    protected function initialContext()
+    {
+        $context = array(
+            'prefixes' => array(),
+            'vocab' => null,
+            'subject' => $this->baseUri,
+            'property' => null,
+            'object' => null,
+            'terms' => array(),
+            'incompleteRels' => array(),
+            'incompleteRevs' => array(),
+            'listMapping' => null,
+            'lang' => null,
+            'path' => '',
+            'xmlns' => array(),
+        );
+
+        // Set the default prefix
+        $context['prefixes'][''] = 'http://www.w3.org/1999/xhtml/vocab#';
+
+        // RDFa 1.1 default term mapping
+        $context['terms']['describedby'] = 'http://www.w3.org/2007/05/powder-s#describedby';
+        $context['terms']['license'] = 'http://www.w3.org/1999/xhtml/vocab#license';
+        $context['terms']['role'] = 'http://www.w3.org/1999/xhtml/vocab#role';
+
+        return $context;
+    }
+
+    protected function expandCurie($node, &$context, $value)
+    {
+        if (preg_match("/^(\w*?):(.*)$/", $value, $matches)) {
+            list (, $prefix, $local) = $matches;
+            $prefix = strtolower($prefix);
+            if ($prefix === '_') {
+                // It is a bnode
+                return $this->remapBnode(substr($value, 2));
+            } elseif (empty($prefix) and $context['vocab']) {
+                // Empty prefix
+                return $context['vocab'] . $local;
+            } elseif (isset($context['prefixes'][$prefix])) {
+                return $context['prefixes'][$prefix] . $local;
+            } elseif ($uri = $node->lookupNamespaceURI($prefix)) {
+                return $uri . $local;
+            } elseif (!empty($prefix) and $uri = EasyRdf_Namespace::get($prefix)) {
+                // Expand using well-known prefixes
+                return $uri . $local;
+            }
+        }
+    }
+
+    protected function processUri($node, &$context, $value, $isProp = false)
+    {
+        if (preg_match("/^\[(.*)\]$/", $value, $matches)) {
+            // Safe CURIE
+            return $this->expandCurie($node, $context, $matches[1]);
+        } elseif (preg_match(self::TERM_REGEXP, $value) and $isProp) {
+            $term = strtolower($value);
+            if ($context['vocab']) {
+                return $context['vocab'] . $value;
+            } elseif (isset($context['terms'][$term])) {
+                return $context['terms'][$term];
+            }
+        } elseif (substr($value, 0, 2) === '_:' and $isProp) {
+            return null;
+        } else {
+            $uri = $this->expandCurie($node, $context, $value);
+            if ($uri) {
+                return $uri;
+            } else {
+                $parsed = new EasyRdf_ParsedUri($value);
+                if ($parsed->isAbsolute()) {
+                    return $value;
+                } elseif ($isProp) {
+                    // Properties can't be relative URIs
+                    return null;
+                } elseif ($this->baseUri) {
+                    return $this->baseUri->resolve($parsed);
+                }
+            }
+        }
+    }
+
+    protected function processUriList($node, $context, $values)
+    {
+        if (!$values) {
+            return array();
+        }
+
+        $uris = array();
+        foreach (preg_split("/\s+/", $values) as $value) {
+            $uri = $this->processUri($node, $context, $value, true);
+            if ($uri) {
+                array_push($uris, $uri);
+            }
+        }
+        return $uris;
+    }
+
+    protected function getUriAttribute($node, &$context, $attributes)
+    {
+        if (!is_array($attributes)) {
+            $attributes = array($attributes);
+        }
+
+        // Find the first attribute that returns a valid URI
+        foreach ($attributes as $attribute) {
+            if ($node->hasAttribute($attribute)) {
+                $value = $node->getAttribute($attribute);
+                $uri = $this->processUri($node, $context, $value);
+                if ($uri) {
+                    return $uri;
+                }
+            }
+        }
+    }
+
+    protected function processNode($node, &$context, $depth = 1)
+    {
+        if ($this->debug) {
+            $this->printNode($node, $depth);
+        }
+
+        // Step 1: establish local variables
+        $skip = false;
+        $subject = null;
+        $typedResource = null;
+        $object = null;
+        $rels = array();
+        $revs = array();
+        $lang = $context['lang'];
+        $incompleteRels = array();
+        $incompleteRevs = array();
+
+        if ($node->nodeType === XML_ELEMENT_NODE) {
+            $context['path'] .= '/' . $node->nodeName;
+
+            $content = $node->hasAttribute('content') ? $node->getAttribute('content') : null;
+            $datatype = $node->hasAttribute('datatype') ? $node->getAttribute('datatype') : null;
+            $property = $node->getAttribute('property') ? $node->getAttribute('property') : null;
+            $typeof = $node->getAttribute('typeof') ? $node->getAttribute('typeof') : null;
+
+            // Step 2: Default vocabulary
+            if ($node->hasAttribute('vocab')) {
+                $context['vocab'] = $node->getAttribute('vocab');
+                if ($context['vocab']) {
+                    $this->addTriple(
+                        $this->baseUri,
+                        'rdfa:usesVocabulary',
+                        array('type' => 'uri', 'value' => $context['vocab'])
+                    );
+                }
+            }
+
+            // Step 3: Set prefix mappings
+            // Support for deprecated xmlns if present in document
+            foreach ($context['xmlns'] as $prefix => $uri) {
+                if ($node->hasAttribute('xmlns:' . $prefix)) {
+                    $context['prefixes'][$prefix] = $node->getAttribute('xmlns:' . $prefix);
+                    if ($this->debug) {
+                        print "Prefix (xmlns): $prefix => $uri\n";
+                    }
+                }
+            }
+            if ($node->hasAttribute('prefix')) {
+                $mappings = preg_split("/\s+/", $node->getAttribute('prefix'));
+                while (count($mappings)) {
+                    $prefix = strtolower(array_shift($mappings));
+                    $uri = array_shift($mappings);
+
+                    if (substr($prefix, -1) === ':') {
+                        $prefix = substr($prefix, 0, -1);
+                    } else {
+                        continue;
+                    }
+
+                    if ($prefix === '_') {
+                        continue;
+                    } elseif (!empty($prefix)) {
+                        $context['prefixes'][$prefix] = $uri;
+                        if ($this->debug) {
+                            print "Prefix: $prefix => $uri\n";
+                        }
+                    }
+                }
+            }
+
+            // Step 4
+            if ($node->hasAttributeNS(self::XML_NS, 'lang')) {
+                $lang = $node->getAttributeNS(self::XML_NS, 'lang');
+            } elseif ($node->hasAttribute('lang')) {
+                $lang = $node->getAttribute('lang');
+            }
+
+            if (!$node->hasAttribute('rel') and !$node->hasAttribute('rev')) {
+                // Step 5: Establish a new subject if no rel/rev
+                if ($property and is_null($content) and is_null($datatype)) {
+                    $subject = $this->getUriAttribute($node, $context, 'about');
+                    if ($typeof and !$subject) {
+                        $typedResource = $this->getUriAttribute(
+                            $node,
+                            $context,
+                            array('resource', 'href', 'src')
+                        );
+                        if (!$typedResource) {
+                            $typedResource = $this->graph->newBNodeId();
+                        }
+                        $object = $typedResource;
+                    }
+                } else {
+                    $subject = $this->getUriAttribute(
+                        $node,
+                        $context,
+                        array('about', 'resource', 'href', 'src')
+                    );
+                }
+
+                // Establish a subject if there isn't one
+                # FIXME: refactor this
+                if (is_null($subject)) {
+                    if ($context['path'] === '/html/head') {
+                        $subject = $context['object'];
+                    } elseif ($depth <= 2) {
+                        $subject = $this->baseUri;
+                    } elseif ($typeof and !$property) {
+                        $subject = $this->graph->newBNodeId();
+                    } else {
+                        if (!$property) {
+                            $skip = true;
+                        }
+                        $subject = $context['object'];
+                    }
+                }
+
+            } else {
+                // Step 6
+                // If the current element does contain a @rel or @rev attribute, then the next step is to
+                // establish both a value for new subject and a value for current object resource:
+
+                $subject = $this->getUriAttribute($node, $context, 'about');
+
+                $object = $this->getUriAttribute(
+                    $node,
+                    $context,
+                    array('resource', 'href', 'src')
+                );
+
+                if ($typeof) {
+                    if (!$object and !$subject) {
+                        $object = $this->graph->newBNodeId();
+                    }
+                    $typedResource = $subject ? $subject : $object;
+                }
+
+                # FIXME: if the element is the root element of the document
+                # then act as if there is an empty @about present
+                if (!$subject) {
+                    $subject = $context['object'];
+                }
+
+                $rels = $this->processUriList($node, $context, $node->getAttribute('rel'));
+                $revs = $this->processUriList($node, $context, $node->getAttribute('rev'));
+            }
+
+            # FIXME: better place for this?
+            if ($typeof and $subject and !$typedResource) {
+                $typedResource = $subject;
+            }
+
+            // Step 7: Process @typeof if there is a subject
+            if ($typedResource) {
+                foreach ($this->processUriList($node, $context, $typeof) as $type) {
+                    $this->addTriple(
+                        $typedResource,
+                        'rdf:type',
+                        array('type' => 'uri', 'value' => $type)
+                    );
+                }
+            }
+
+            // Step 8: Create new List mapping if the subject has changed
+            if ($subject and $subject !== $context['subject']) {
+                $listMapping = new StdClass();
+            } else {
+                $listMapping = $context['listMapping'];
+            }
+
+            // Step 9: Generate triples with given object
+            if ($subject and $object) {
+                foreach ($rels as $prop) {
+                    $obj = array('type' => 'uri', 'value' => $object);
+                    if ($node->hasAttribute('inlist')) {
+                        $this->addToList($listMapping, $prop, $obj);
+                    } else {
+                        $this->addTriple($subject, $prop, $obj);
+                    }
+                }
+
+                foreach ($revs as $prop) {
+                    $this->addTriple(
+                        $object,
+                        $prop,
+                        array('type' => 'uri', 'value' => $subject)
+                    );
+                }
+            } elseif ($rels or $revs) {
+                // Step 10: Incomplete triples and bnode creation
+                $object = $this->graph->newBNodeId();
+                if ($rels) {
+                    if ($node->hasAttribute('inlist')) {
+                        foreach ($rels as $prop) {
+                            # FIXME: add support for incomplete lists
+                            if (!isset($listMapping->$prop)) {
+                                $listMapping->$prop = array();
+                            }
+                        }
+                    } else {
+                        $incompleteRels = $rels;
+                        if ($this->debug) {
+                            print "Incomplete rels: ".implode(',', $rels)."\n";
+                        }
+                    }
+                }
+
+                if ($revs) {
+                    $incompleteRevs = $revs;
+                    if ($this->debug) {
+                        print "Incomplete revs: ".implode(',', $revs)."\n";
+                    }
+                }
+            }
+
+            // Step 11: establish current property value
+            if ($subject and $property) {
+                $value = array();
+
+                if ($datatype) {
+                    $datatype = $this->processUri($node, $context, $datatype, true);
+                }
+
+                if ($node->nodeName === 'data' and $node->hasAttribute('value')) {
+                    $value['value'] = $node->getAttribute('value');
+                } elseif ($node->hasAttribute('datetime')) {
+                    $value['value'] = $node->getAttribute('datetime');
+                    $datetime = true;
+                } elseif ($datatype === '') {
+                    $value['value'] = $node->textContent;
+                } elseif ($datatype === self::RDF_XML_LITERAL) {
+                    $value['value'] = '';
+                    foreach ($node->childNodes as $child) {
+                        $value['value'] .= $child->C14N();
+                    }
+                } elseif ($content !== null) {
+                    $value['value'] = $content;
+                } elseif (is_null($datatype) and empty($rel) and empty($rev)) {
+                    $value['value'] = $this->getUriAttribute(
+                        $node,
+                        $context,
+                        array('resource', 'href', 'src')
+                    );
+
+                    if ($value['value']) {
+                        $value['type'] = 'uri';
+                    }
+                }
+
+                if (empty($value['value']) and $typedResource and !$node->hasAttribute('about')) {
+                    $value['type'] = 'uri';
+                    $value['value'] = $typedResource;
+                }
+
+                if (empty($value['value'])) {
+                    $value['value'] = $node->textContent;
+                }
+
+                if (empty($value['type'])) {
+                    $value['type'] = 'literal';
+                    if ($datatype) {
+                        $value['datatype'] = $datatype;
+                    } elseif (isset($datetime) or $node->nodeName === 'time') {
+                        $value['datatype'] = $this->guessTimeDatatype($value['value']);
+                    }
+
+                    if (empty($value['datatype']) and $lang) {
+                        $value['lang'] = $lang;
+                    }
+                }
+
+                // Add each of the properties
+                foreach ($this->processUriList($node, $context, $property) as $prop) {
+                    if ($node->hasAttribute('inlist')) {
+                        $this->addToList($listMapping, $prop, $value);
+                    } elseif ($subject) {
+                        $this->addTriple($subject, $prop, $value);
+                    }
+                }
+            }
+
+            // Step 12: Complete the incomplete triples from the evaluation context
+            if (!$skip and $subject and ($context['incompleteRels'] or $context['incompleteRevs'])) {
+                foreach ($context['incompleteRels'] as $prop) {
+                    $this->addTriple(
+                        $context['subject'],
+                        $prop,
+                        array('type' => 'uri', 'value' => $subject)
+                    );
+                }
+
+                foreach ($context['incompleteRevs'] as $prop) {
+                    $this->addTriple(
+                        $subject,
+                        $prop,
+                        array('type' => 'uri', 'value' => $context['subject'])
+                    );
+                }
+            }
+        }
+
+        // Step 13: create a new evaluation context and proceed recursively
+        if ($node->hasChildNodes()) {
+            if ($skip) {
+                $newContext = $context;
+            } else {
+                // Prepare a new evaluation context
+                $newContext = $context;
+                if ($object) {
+                    $newContext['object'] = $object;
+                } elseif ($subject) {
+                    $newContext['object'] = $subject;
+                } else {
+                    $newContext['object'] = $context['subject'];
+                }
+                if ($subject) {
+                    $newContext['subject'] = $subject;
+                }
+                $newContext['incompleteRels'] = $incompleteRels;
+                $newContext['incompleteRevs'] = $incompleteRevs;
+                if (isset($listMapping)) {
+                    $newContext['listMapping'] = $listMapping;
+                }
+            }
+
+            // The language is always updated, even if skip is set
+            $newContext['lang'] = $lang;
+
+            foreach ($node->childNodes as $child) {
+                if ($child->nodeType === XML_ELEMENT_NODE) {
+                    $this->processNode($child, $newContext, $depth+1);
+                }
+            }
+        }
+
+        // Step 14: create triples for lists
+        if (!empty($listMapping)) {
+            foreach ($listMapping as $prop => $list) {
+                if ($context['listMapping'] !== $listMapping) {
+                    if ($this->debug) {
+                        print "Need to create triples for $prop => ".count($list)." items\n";
+                    }
+                    $this->generateList($subject, $prop, $list);
+                }
+            }
+        }
+    }
+
+    /**
+     * Parse RDFa 1.1 into an EasyRdf_Graph
+     *
+     * @param object EasyRdf_Graph $graph   the graph to load the data into
+     * @param string               $data    the RDF document data
+     * @param string               $format  the format of the input data
+     * @param string               $baseUri the base URI of the data being parsed
+     * @return integer             The number of triples added to the graph
+     */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        parent::checkParseParams($graph, $data, $format, $baseUri);
+
+        if ($format != 'rdfa') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Parser_Rdfa does not support: $format"
+            );
+        }
+
+        // Initialise evaluation context.
+        $context = $this->initialContext();
+
+        libxml_use_internal_errors(true);
+
+        // Parse the document into DOM
+        $doc = new DOMDocument();
+        // Attempt to parse the document as strict XML, and fall back to HTML
+        // if XML parsing fails.
+        if ($doc->loadXML($data, LIBXML_NONET)) {
+            if ($this->debug) {
+                print "Document was parsed as XML.";
+            }
+            // Collect all xmlns namespaces defined throughout the document.
+            $sxe = simplexml_import_dom($doc);
+            $context['xmlns'] = $sxe->getDocNamespaces(true);
+            unset($context['xmlns']['']);
+        } else {
+            $doc->loadHTML($data);
+            if ($this->debug) {
+                print "Document was parsed as HTML.";
+            }
+        }
+
+        // Establish the base for both XHTML and HTML documents.
+        $xpath = new DOMXPath($doc);
+        $xpath->registerNamespace('xh', "http://www.w3.org/1999/xhtml");
+        $nodeList = $xpath->query('/xh:html/xh:head/xh:base');
+        if ($node = $nodeList->item(0) and $href = $node->getAttribute('href')) {
+            $this->baseUri = new EasyRdf_ParsedUri($href);
+        }
+        $nodeList = $xpath->query('/html/head/base');
+        if ($node = $nodeList->item(0) and $href = $node->getAttribute('href')) {
+            $this->baseUri = new EasyRdf_ParsedUri($href);
+        }
+
+        // Remove the fragment from the base URI
+        $this->baseUri->setFragment(null);
+
+        // Recursively process XML nodes
+        $this->processNode($doc, $context);
+
+        return $this->tripleCount;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Redland.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Redland.php
new file mode 100644
index 000000000000..c21c02de8653
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Redland.php
@@ -0,0 +1,247 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to parse RDF using Redland (librdf) C library.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_Redland extends EasyRdf_Parser
+{
+    /** Variable set to the librdf world */
+    private $world = null;
+
+    /** Parser feature URI string for getting the error count of last parse. */
+    const LIBRDF_PARSER_FEATURE_ERROR_COUNT =
+        'http://feature.librdf.org/parser-error-count';
+
+    /*
+     *  Types supported by Redland:
+     *
+     *  ntriples: N-Triples
+     *  turtle: Turtle Terse RDF Triple Language
+     *  trig: TriG - Turtle with Named Graphs
+     *  rss-tag-soup: RSS Tag Soup
+     *  grddl: Gleaning Resource Descriptions from Dialects of Languages
+     *  guess: Pick the parser to use using content type and URI
+     *  rdfa: RDF/A via librdfa
+     *  raptor: (null)
+     *  rdfxml: RDF/XML
+     */
+
+
+    /**
+     * Convert a librdf node type into a string
+     * @ignore
+     */
+    protected function nodeTypeString($node)
+    {
+        switch(librdf_node_get_type($node)) {
+            case 1:
+                return 'uri';
+                break;
+            case 2:
+                return 'literal';
+                break;
+            case 4:
+                return 'bnode';
+                break;
+            default:
+                return 'unknown';
+                break;
+        }
+    }
+
+    /**
+     * Convert the URI for a node into a string
+     * @ignore
+     */
+    protected function nodeUriString($node)
+    {
+        $type = EasyRdf_Parser_Redland::nodeTypeString($node);
+        if ($type == 'uri') {
+            $uri = librdf_node_get_uri($node);
+            if (!$uri) {
+                throw new EasyRdf_Exception("Failed to get URI of node");
+            }
+            $str = librdf_uri_to_string($uri);
+            if (!$str) {
+                throw new EasyRdf_Exception(
+                    "Failed to convert librdf_uri to string"
+                );
+            }
+            return $str;
+        } elseif ($type == 'bnode') {
+            return $this->remapBnode(
+                librdf_node_get_blank_identifier($node)
+            );
+        } else {
+            throw new EasyRdf_Exception("Unsupported type: ".$type);
+        }
+    }
+
+    /**
+     * Convert a node into an associate array
+     * @ignore
+     */
+    protected function nodeToArray($node)
+    {
+        $object = array();
+        $object['type'] = EasyRdf_Parser_Redland::nodeTypeString($node);
+        if ($object['type'] == 'uri') {
+            $object['value'] = EasyRdf_Parser_Redland::nodeUriString($node);
+        } elseif ($object['type'] == 'bnode') {
+            $object['value'] = '_:'.librdf_node_get_blank_identifier($node);
+        } elseif ($object['type'] == 'literal') {
+            $object['value'] = librdf_node_get_literal_value($node);
+            $lang = librdf_node_get_literal_value_language($node);
+            if ($lang) {
+                $object['lang'] = $lang;
+            }
+            $datatype = librdf_node_get_literal_value_datatype_uri($node);
+            if ($datatype) {
+                $object['datatype'] = librdf_uri_to_string($datatype);
+            }
+        } else {
+            throw new EasyRdf_Exception("Unsupported type: ".$object['type']);
+        }
+        return $object;
+    }
+
+    /**
+     * Return the number of errors during parsing
+     * @ignore
+     */
+    protected function parserErrorCount($parser)
+    {
+        $errorUri = librdf_new_uri(
+            $this->world,
+            self::LIBRDF_PARSER_FEATURE_ERROR_COUNT
+        );
+        $errorNode = librdf_parser_get_feature($parser, $errorUri);
+        $errorCount = librdf_node_get_literal_value($errorNode);
+        librdf_free_uri($errorUri);
+        return $errorCount;
+    }
+
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Parser_Redland
+     */
+    public function __construct()
+    {
+        if (extension_loaded('redland')) {
+            $this->world = librdf_php_get_world();
+            if (!$this->world) {
+                throw new EasyRdf_Exception(
+                    "Failed to initialise librdf world."
+                );
+            }
+        } else {
+            throw new EasyRdf_Exception(
+                "Redland PHP extension is not available."
+            );
+        }
+    }
+
+    /**
+      * Parse an RDF document into an EasyRdf_Graph
+      *
+      * @param object EasyRdf_Graph $graph   the graph to load the data into
+      * @param string               $data    the RDF document data
+      * @param string               $format  the format of the input data
+      * @param string               $baseUri the base URI of the data being parsed
+      * @return integer             The number of triples added to the graph
+      */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        parent::checkParseParams($graph, $data, $format, $baseUri);
+
+        $parser = librdf_new_parser($this->world, $format, null, null);
+        if (!$parser) {
+            throw new EasyRdf_Exception(
+                "Failed to create librdf_parser of type: $format"
+            );
+        }
+
+        $rdfUri = librdf_new_uri($this->world, $baseUri);
+        if (!$rdfUri) {
+            throw new EasyRdf_Exception(
+                "Failed to create librdf_uri from: $baseUri"
+            );
+        }
+
+        $stream = librdf_parser_parse_string_as_stream($parser, $data, $rdfUri);
+        if (!$stream) {
+            throw new EasyRdf_Exception(
+                "Failed to parse RDF stream for: $rdfUri"
+            );
+        }
+
+        do {
+            $statement = librdf_stream_get_object($stream);
+            if ($statement) {
+                $subject = EasyRdf_Parser_Redland::nodeUriString(
+                    librdf_statement_get_subject($statement)
+                );
+                $predicate = EasyRdf_Parser_Redland::nodeUriString(
+                    librdf_statement_get_predicate($statement)
+                );
+                $object = EasyRdf_Parser_Redland::nodeToArray(
+                    librdf_statement_get_object($statement)
+                );
+
+                $this->addTriple($subject, $predicate, $object);
+            }
+        } while (!librdf_stream_next($stream));
+
+        $errorCount = $this->parserErrorCount($parser);
+        if ($errorCount) {
+            throw new EasyRdf_Exception("$errorCount errors while parsing.");
+        }
+
+        librdf_free_uri($rdfUri);
+        librdf_free_stream($stream);
+        librdf_free_parser($parser);
+
+        return $this->tripleCount;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Turtle.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Turtle.php
new file mode 100644
index 000000000000..bbbec479b1de
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Parser/Turtle.php
@@ -0,0 +1,1134 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.
+ * Copyright (c) 1997-2006 Aduna (http://www.aduna-software.com/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ *             Copyright (c) 1997-2006 Aduna (http://www.aduna-software.com/)
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to parse Turtle with no external dependancies.
+ *
+ * http://www.w3.org/TR/turtle/
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ *             Copyright (c) 1997-2006 Aduna (http://www.aduna-software.com/)
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Parser_Turtle extends EasyRdf_Parser_Ntriples
+{
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Parser_Turtle
+     */
+    public function __construct()
+    {
+    }
+
+    /**
+     * Parse Turtle into an EasyRdf_Graph
+     *
+     * @param object EasyRdf_Graph $graph   the graph to load the data into
+     * @param string               $data    the RDF document data
+     * @param string               $format  the format of the input data
+     * @param string               $baseUri the base URI of the data being parsed
+     * @return integer             The number of triples added to the graph
+     */
+    public function parse($graph, $data, $format, $baseUri)
+    {
+        parent::checkParseParams($graph, $data, $format, $baseUri);
+
+        if ($format != 'turtle') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Parser_Turtle does not support: $format"
+            );
+        }
+
+        $this->data = $data;
+        $this->len = strlen($data);
+        $this->pos = 0;
+
+        $this->namespaces = array();
+        $this->subject = null;
+        $this->predicate = null;
+        $this->object = null;
+
+        $this->resetBnodeMap();
+
+        $c = $this->skipWSC();
+        while ($c != -1) {
+            $this->parseStatement();
+            $c = $this->skipWSC();
+        }
+
+        return $this->tripleCount;
+    }
+
+
+    /**
+     * Parse a statement [2]
+     * @ignore
+     */
+    protected function parseStatement()
+    {
+        $c = $this->peek();
+        if ($c == '@') {
+            $this->parseDirective();
+            $this->skipWSC();
+            $this->verifyCharacter($this->read(), ".");
+        } else {
+            $this->parseTriples();
+            $this->skipWSC();
+            $this->verifyCharacter($this->read(), ".");
+        }
+    }
+
+    /**
+     * Parse a directive [3]
+     * @ignore
+     */
+    protected function parseDirective()
+    {
+        // Verify that the first characters form the string "prefix"
+        $this->verifyCharacter($this->read(), "@");
+
+        $directive = '';
+
+        $c = $this->read();
+        while ($c != -1 && !self::isWhitespace($c)) {
+            $directive .= $c;
+            $c = $this->read();
+        }
+
+        if ($directive == "prefix") {
+            $this->parsePrefixID();
+        } elseif ($directive == "base") {
+            $this->parseBase();
+        } elseif (strlen($directive) == 0) {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: directive name is missing, expected @prefix or @base"
+            );
+        } else {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: unknown directive \"@$directive\""
+            );
+        }
+    }
+
+    /**
+     * Parse a prefixID [4]
+     * @ignore
+     */
+    protected function parsePrefixID()
+    {
+        $this->skipWSC();
+
+        // Read prefix ID (e.g. "rdf:" or ":")
+        $prefixID = '';
+
+        while (true) {
+            $c = $this->read();
+            if ($c == ':') {
+                $this->unread($c);
+                break;
+            } elseif (self::isWhitespace($c)) {
+                break;
+            } elseif ($c == -1) {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: unexpected end of file while reading prefix id"
+                );
+            }
+
+            $prefixID .= $c;
+        }
+
+        $this->skipWSC();
+        $this->verifyCharacter($this->read(), ":");
+        $this->skipWSC();
+
+        // Read the namespace URI
+        $namespace = $this->parseURI();
+
+        // Store local namespace mapping
+        $this->namespaces[$prefixID] = $namespace['value'];
+    }
+
+    /**
+     * Parse base [5]
+     * @ignore
+     */
+    protected function parseBase()
+    {
+        $this->skipWSC();
+
+        $baseUri = $this->parseURI();
+        $this->baseUri = new EasyRdf_ParsedUri($baseUri['value']);
+    }
+
+    /**
+     * Parse triples [6]
+     * @ignore
+     */
+    protected function parseTriples()
+    {
+        $this->parseSubject();
+        $this->skipWSC();
+        $this->parsePredicateObjectList();
+
+        $this->subject = null;
+        $this->predicate = null;
+        $this->object = null;
+    }
+
+    /**
+     * Parse a predicateObjectList [7]
+     * @ignore
+     */
+    protected function parsePredicateObjectList()
+    {
+        $this->predicate = $this->parsePredicate();
+
+        $this->skipWSC();
+        $this->parseObjectList();
+
+        while ($this->skipWSC() == ';') {
+            $this->read();
+
+            $c = $this->skipWSC();
+
+            if ($c == '.' || $c == ']') {
+                break;
+            }
+
+            $this->predicate = $this->parsePredicate();
+
+            $this->skipWSC();
+
+            $this->parseObjectList();
+        }
+    }
+
+    /**
+     * Parse a objectList [8]
+     * @ignore
+     */
+    protected function parseObjectList()
+    {
+        $this->parseObject();
+
+        while ($this->skipWSC() == ',') {
+            $this->read();
+            $this->skipWSC();
+            $this->parseObject();
+        }
+    }
+
+    /**
+     * Parse a subject [10]
+     * @ignore
+     */
+    protected function parseSubject()
+    {
+        $c = $this->peek();
+        if ($c == '(') {
+            $this->subject = $this->parseCollection();
+        } elseif ($c == '[') {
+            $this->subject = $this->parseImplicitBlank();
+        } else {
+            $value = $this->parseValue();
+
+            if ($value['type'] == 'uri' or $value['type'] == 'bnode') {
+                $this->subject = $value;
+            } else {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: illegal subject type: ".$value['type']
+                );
+            }
+        }
+    }
+
+    /**
+     * Parse a predicate [11]
+     * @ignore
+     */
+    protected function parsePredicate()
+    {
+        // Check if the short-cut 'a' is used
+        $c1 = $this->read();
+
+        if ($c1 == 'a') {
+            $c2 = $this->read();
+
+            if (self::isWhitespace($c2)) {
+                // Short-cut is used, return the rdf:type URI
+                return array(
+                    'type' => 'uri',
+                    'value' => EasyRdf_Namespace::get('rdf') . 'type'
+                );
+            }
+
+            // Short-cut is not used, unread all characters
+            $this->unread($c2);
+        }
+        $this->unread($c1);
+
+        // Predicate is a normal resource
+        $predicate = $this->parseValue();
+        if ($predicate['type'] == 'uri') {
+            return $predicate;
+        } else {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: Illegal predicate value: " . $predicate
+            );
+        }
+    }
+
+    /**
+     * Parse a object [12]
+     * @ignore
+     */
+    protected function parseObject()
+    {
+        $c = $this->peek();
+
+        if ($c == '(') {
+            $this->object = $this->parseCollection();
+        } elseif ($c == '[') {
+            $this->object = $this->parseImplicitBlank();
+        } else {
+            $this->object = $this->parseValue();
+        }
+
+        $this->addTriple(
+            $this->subject['value'],
+            $this->predicate['value'],
+            $this->object
+        );
+    }
+
+    /**
+     * Parses a blankNodePropertyList [15]
+     *
+     * This method parses the token []
+     * and predicateObjectLists that are surrounded by square brackets.
+     *
+     * @ignore
+     */
+    protected function parseImplicitBlank()
+    {
+        $this->verifyCharacter($this->read(), "[");
+
+        $bnode = array(
+            'type' => 'bnode',
+            'value' => $this->graph->newBNodeId()
+        );
+
+        $c = $this->read();
+        if ($c != ']') {
+            $this->unread($c);
+
+            // Remember current subject and predicate
+            $oldSubject = $this->subject;
+            $oldPredicate = $this->predicate;
+
+            // generated bNode becomes subject
+            $this->subject = $bnode;
+
+            // Enter recursion with nested predicate-object list
+            $this->skipWSC();
+
+            $this->parsePredicateObjectList();
+
+            $this->skipWSC();
+
+            // Read closing bracket
+            $this->verifyCharacter($this->read(), "]");
+
+            // Restore previous subject and predicate
+            $this->subject = $oldSubject;
+            $this->predicate = $oldPredicate;
+        }
+
+        return $bnode;
+    }
+
+    /**
+     * Parses a collection [16], e.g: ( item1 item2 item3 )
+     * @ignore
+     */
+    protected function parseCollection()
+    {
+        $this->verifyCharacter($this->read(), "(");
+
+        $c = $this->skipWSC();
+        if ($c == ')') {
+            // Empty list
+            $this->read();
+            return array(
+                'type' => 'uri',
+                'value' => EasyRdf_Namespace::get('rdf') . 'nil'
+            );
+        } else {
+            $listRoot = array(
+                'type' => 'bnode',
+                'value' => $this->graph->newBNodeId()
+            );
+
+            // Remember current subject and predicate
+            $oldSubject = $this->subject;
+            $oldPredicate = $this->predicate;
+
+            // generated bNode becomes subject, predicate becomes rdf:first
+            $this->subject = $listRoot;
+            $this->predicate = array(
+                'type' => 'uri',
+                'value' => EasyRdf_Namespace::get('rdf') . 'first'
+            );
+
+            $this->parseObject();
+            $bNode = $listRoot;
+
+            while ($this->skipWSC() != ')') {
+                // Create another list node and link it to the previous
+                $newNode = array(
+                    'type' => 'bnode',
+                    'value' => $this->graph->newBNodeId()
+                );
+
+                $this->addTriple(
+                    $bNode['value'],
+                    EasyRdf_Namespace::get('rdf') . 'rest',
+                    $newNode
+                );
+
+                // New node becomes the current
+                $this->subject = $bNode = $newNode;
+
+                $this->parseObject();
+            }
+
+            // Skip ')'
+            $this->read();
+
+            // Close the list
+            $this->addTriple(
+                $bNode['value'],
+                EasyRdf_Namespace::get('rdf') . 'rest',
+                array(
+                    'type' => 'uri',
+                    'value' => EasyRdf_Namespace::get('rdf') . 'nil'
+                )
+            );
+
+            // Restore previous subject and predicate
+            $this->subject = $oldSubject;
+            $this->predicate = $oldPredicate;
+
+            return $listRoot;
+        }
+    }
+
+    /**
+     * Parses an RDF value. This method parses uriref, qname, node ID, quoted
+     * literal, integer, double and boolean.
+     * @ignore
+     */
+    protected function parseValue()
+    {
+        $c = $this->peek();
+
+        if ($c == '<') {
+            // uriref, e.g. <foo://bar>
+            return $this->parseURI();
+        } elseif ($c == ':' || self::isPrefixStartChar($c)) {
+            // qname or boolean
+            return $this->parseQNameOrBoolean();
+        } elseif ($c == '_') {
+            // node ID, e.g. _:n1
+            return $this->parseNodeID();
+        } elseif ($c == '"' or $c == "'") {
+            // quoted literal, e.g. "foo" or """foo""" or 'foo' or '''foo'''
+            return $this->parseQuotedLiteral($c);
+        } elseif (ctype_digit($c) || $c == '.' || $c == '+' || $c == '-') {
+            // integer or double, e.g. 123 or 1.2e3
+            return $this->parseNumber();
+        } elseif ($c == -1) {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: unexpected end of file while reading value"
+            );
+        } else {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: expected an RDF value here, found '$c'"
+            );
+        }
+    }
+
+    /**
+     * Parses a quoted string, optionally followed by a language tag or datatype.
+     * @param string  $quote  The type of quote to use (either ' or ")
+     * @ignore
+     */
+    protected function parseQuotedLiteral($quote)
+    {
+        $label = $this->parseQuotedString($quote);
+
+        // Check for presence of a language tag or datatype
+        $c = $this->peek();
+
+        if ($c == '@') {
+            $this->read();
+
+            // Read language
+            $lang = '';
+            $c = $this->read();
+            if ($c == -1) {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: unexpected end of file while reading language"
+                );
+            } elseif (!self::isLanguageStartChar($c)) {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: expected a letter, found '$c'"
+                );
+            }
+
+            $lang .= $c;
+
+            $c = $this->read();
+            while (self::isLanguageChar($c)) {
+                $lang .= $c;
+                $c = $this->read();
+            }
+
+            $this->unread($c);
+
+            return array(
+                'type' => 'literal',
+                'value' => $label,
+                'lang' => $lang
+            );
+        } elseif ($c == '^') {
+            $this->read();
+
+            // next character should be another '^'
+            $this->verifyCharacter($this->read(), "^");
+
+            // Read datatype
+            $datatype = $this->parseValue();
+            if ($datatype['type'] == 'uri') {
+                return array(
+                    'type' => 'literal',
+                    'value' => $label,
+                    'datatype' => $datatype['value']
+                );
+            } else {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: illegal datatype value: $datatype"
+                );
+            }
+        } else {
+            return array(
+                'type' => 'literal',
+                'value' => $label
+            );
+        }
+    }
+
+    /**
+     * Parses a quoted string, which is either a "normal string" or a """long string""".
+     * @param string  $quote  The type of quote to use (either ' or ")
+     * @ignore
+     */
+    protected function parseQuotedString($quote)
+    {
+        $result = null;
+
+        // First character should be ' or "
+        $this->verifyCharacter($this->read(), $quote);
+
+        // Check for long-string, which starts and ends with three double quotes
+        $c2 = $this->read();
+        $c3 = $this->read();
+
+        if ($c2 == $quote && $c3 == $quote) {
+            // Long string
+            $result = $this->parseLongString($quote);
+        } else {
+            // Normal string
+            $this->unread($c3);
+            $this->unread($c2);
+
+            $result = $this->parseString($quote);
+        }
+
+        // Unescape any escape sequences
+        return $this->unescapeString($result);
+    }
+
+    /**
+     * Parses a "normal string". This method assumes that the first double quote
+     * has already been parsed.
+     * @param string  $quote  The type of quote to use (either ' or ")
+     * @ignore
+     */
+    protected function parseString($quote)
+    {
+        $str = '';
+
+        while (true) {
+            $c = $this->read();
+
+            if ($c == $quote) {
+                break;
+            } elseif ($c == -1) {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: unexpected end of file while reading string"
+                );
+            }
+
+            $str .= $c;
+
+            if ($c == '\\') {
+                // This escapes the next character, which might be a ' or a "
+                $c = $this->read();
+                if ($c == -1) {
+                    throw new EasyRdf_Exception(
+                        "Turtle Parse Error: unexpected end of file while reading string"
+                    );
+                }
+                $str .= $c;
+            }
+        }
+
+        return $str;
+    }
+
+    /**
+     * Parses a """long string""". This method assumes that the first three
+     * double quotes have already been parsed.
+     * @param string  $quote  The type of quote to use (either ' or ")
+     * @ignore
+     */
+    protected function parseLongString($quote)
+    {
+        $str = '';
+        $doubleQuoteCount = 0;
+
+        while ($doubleQuoteCount < 3) {
+            $c = $this->read();
+
+            if ($c == -1) {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: unexpected end of file while reading long string"
+                );
+            } elseif ($c == $quote) {
+                $doubleQuoteCount++;
+            } else {
+                $doubleQuoteCount = 0;
+            }
+
+            $str .= $c;
+
+            if ($c == '\\') {
+                // This escapes the next character, which might be a ' or "
+                $c = $this->read();
+                if ($c == -1) {
+                    throw new EasyRdf_Exception(
+                        "Turtle Parse Error: unexpected end of file while reading long string"
+                    );
+                }
+                $str .= $c;
+            }
+        }
+
+        return substr($str, 0, -3);
+    }
+
+    /**
+     * Parses a numeric value, either of type integer, decimal or double
+     * @ignore
+     */
+    protected function parseNumber()
+    {
+        $value = '';
+        $datatype = EasyRdf_Namespace::get('xsd').'integer';
+
+        $c = $this->read();
+
+        // read optional sign character
+        if ($c == '+' || $c == '-') {
+            $value .= $c;
+            $c = $this->read();
+        }
+
+        while (ctype_digit($c)) {
+            $value .= $c;
+            $c = $this->read();
+        }
+
+        if ($c == '.' || $c == 'e' || $c == 'E') {
+            // We're parsing a decimal or a double
+            $datatype = EasyRdf_Namespace::get('xsd').'decimal';
+
+            // read optional fractional digits
+            if ($c == '.') {
+                $value .= $c;
+                $c = $this->read();
+                while (ctype_digit($c)) {
+                    $value .= $c;
+                    $c = $this->read();
+                }
+
+                if (strlen($value) == 1) {
+                    // We've only parsed a '.'
+                    throw new EasyRdf_Exception(
+                        "Turtle Parse Error: object for statement missing"
+                    );
+                }
+            } else {
+                if (strlen($value) == 0) {
+                    // We've only parsed an 'e' or 'E'
+                    throw new EasyRdf_Exception(
+                        "Turtle Parse Error: object for statement missing"
+                    );
+                }
+            }
+
+            // read optional exponent
+            if ($c == 'e' || $c == 'E') {
+                $datatype = EasyRdf_Namespace::get('xsd').'double';
+                $value .= $c;
+
+                $c = $this->read();
+                if ($c == '+' || $c == '-') {
+                    $value .= $c;
+                    $c = $this->read();
+                }
+
+                if (!ctype_digit($c)) {
+                    throw new EasyRdf_Exception(
+                        "Turtle Parse Error: Exponent value missing"
+                    );
+                }
+
+                $value .= $c;
+
+                $c = $this->read();
+                while (ctype_digit($c)) {
+                    $value .= $c;
+                    $c = $this->read();
+                }
+            }
+        }
+
+        // Unread last character, it isn't part of the number
+        $this->unread($c);
+
+        // Return result as a typed literal
+        return array(
+            'type' => 'literal',
+            'value' => $value,
+            'datatype' => $datatype
+        );
+    }
+
+    /**
+     * Parses a URI / IRI
+     * @ignore
+     */
+    protected function parseURI()
+    {
+        $uri = '';
+
+        // First character should be '<'
+        $this->verifyCharacter($this->read(), "<");
+
+        // Read up to the next '>' character
+        while (true) {
+            $c = $this->read();
+
+            if ($c == '>') {
+                break;
+            } elseif ($c == -1) {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: unexpected end of file while reading URI"
+                );
+            }
+
+            $uri .= $c;
+
+            if ($c == '\\') {
+                // This escapes the next character, which might be a '>'
+                $c = $this->read();
+                if ($c == -1) {
+                    throw new EasyRdf_Exception(
+                        "Turtle Parse Error: unexpected end of file while reading URI"
+                    );
+                }
+                $uri .= $c;
+            }
+        }
+
+        // Unescape any escape sequences
+        $uri = $this->unescapeString($uri);
+
+        return array(
+            'type' => 'uri',
+            'value' => $this->resolve($uri)
+        );
+    }
+
+    /**
+     * Parses qnames and boolean values, which have equivalent starting
+     * characters.
+     * @ignore
+     */
+    protected function parseQNameOrBoolean()
+    {
+        // First character should be a ':' or a letter
+        $c = $this->read();
+        if ($c == -1) {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: unexpected end of file while readying value"
+            );
+        }
+        if ($c != ':' && !self::isPrefixStartChar($c)) {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: expected a ':' or a letter, found '$c'"
+            );
+        }
+
+        $namespace = null;
+
+        if ($c == ':') {
+            // qname using default namespace
+            $namespace = $this->namespaces[""];
+            if ($namespace == null) {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: default namespace used but not defined"
+                );
+            }
+        } else {
+            // $c is the first letter of the prefix
+            $prefix = $c;
+
+            $c = $this->read();
+            while (self::isPrefixChar($c)) {
+                $prefix .= $c;
+                $c = $this->read();
+            }
+
+            if ($c != ':') {
+                // prefix may actually be a boolean value
+                $value = $prefix;
+
+                if ($value == "true" || $value == "false") {
+                    return array(
+                        'type' => 'literal',
+                        'value' => $value,
+                        'datatype' => EasyRdf_Namespace::get('xsd') . 'boolean'
+                    );
+                }
+            }
+
+            $this->verifyCharacter($c, ":");
+
+            if (isset($this->namespaces[$prefix])) {
+                $namespace = $this->namespaces[$prefix];
+            } else {
+                throw new EasyRdf_Exception(
+                    "Turtle Parse Error: namespace prefix '$prefix' used but not defined"
+                );
+            }
+        }
+
+        // $c == ':', read optional local name
+        $localName = '';
+        $c = $this->read();
+        if (self::isNameStartChar($c)) {
+            $localName .= $c;
+
+            $c = $this->read();
+            while (self::isNameChar($c)) {
+                $localName .= $c;
+                $c = $this->read();
+            }
+        }
+
+        // Unread last character
+        $this->unread($c);
+
+        // Note: namespace has already been resolved
+        return array(
+            'type' => 'uri',
+            'value' => $namespace . $localName
+        );
+    }
+
+    /**
+     * Parses a blank node ID, e.g: _:node1
+     * @ignore
+     */
+    protected function parseNodeID()
+    {
+        // Node ID should start with "_:"
+        $this->verifyCharacter($this->read(), "_");
+        $this->verifyCharacter($this->read(), ":");
+
+        // Read the node ID
+        $c = $this->read();
+        if ($c == -1) {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: unexpected end of file while reading node id"
+            );
+        } elseif (!self::isNameStartChar($c)) {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: expected a letter, found '$c'"
+            );
+        }
+
+        // Read all following letter and numbers, they are part of the name
+        $name = $c;
+        $c = $this->read();
+        while (self::isNameChar($c)) {
+            $name .= $c;
+            $c = $this->read();
+        }
+
+        $this->unread($c);
+
+        return array(
+            'type' => 'bnode',
+            'value' => $this->remapBnode($name)
+        );
+    }
+
+    protected function resolve($uri)
+    {
+        if ($this->baseUri) {
+            return $this->baseUri->resolve($uri)->toString();
+        } else {
+            return $uri;
+        }
+    }
+
+    /**
+     * Verifies that the supplied character $c is one of the expected
+     * characters specified in $expected. This method will throw a
+     * exception if this is not the case.
+     * @ignore
+     */
+    protected function verifyCharacter($c, $expected)
+    {
+        if ($c == -1) {
+            throw new EasyRdf_Exception(
+                "Turtle Parse Error: unexpected end of file"
+            );
+        } elseif (strpbrk($c, $expected) === false) {
+            $msg = 'expected ';
+            for ($i = 0; $i < strlen($expected); $i++) {
+                if ($i > 0) {
+                    $msg .= " or ";
+                }
+                $msg .= '\''.$expected[$i].'\'';
+            }
+            $msg .= ", found '$c'";
+
+            throw new EasyRdf_Exception("Turtle Parse Error: $msg");
+        }
+    }
+
+    /**
+     * Skip through whitespace and comments
+     * @ignore
+     */
+    protected function skipWSC()
+    {
+        $c = $this->read();
+        while (self::isWhitespace($c) || $c == '#') {
+            if ($c == '#') {
+                $this->skipLine();
+            }
+
+            $c = $this->read();
+        }
+
+        $this->unread($c);
+        return $c;
+    }
+
+    /**
+     * Consumes characters from reader until the first EOL has been read.
+     * @ignore
+     */
+    protected function skipLine()
+    {
+        $c = $this->read();
+        while ($c != -1 && $c != "\r" && $c != "\n") {
+            $c = $this->read();
+        }
+
+        // c is equal to -1, \r or \n.
+        // In case c is equal to \r, we should also read a following \n.
+        if ($c == "\r") {
+            $c = $this->read();
+            if ($c != "\n") {
+                $this->unread($c);
+            }
+        }
+    }
+
+    /**
+     * Read a single character from the input buffer.
+     * Returns -1 when the end of the file is reached.
+     * @ignore
+     */
+    protected function read()
+    {
+        if ($this->pos < $this->len) {
+            $c = $this->data[$this->pos];
+            $this->pos++;
+            return $c;
+        } else {
+            return -1;
+        }
+    }
+
+    /**
+     * Gets the next character to be returned by read()
+     * without removing it from the input buffer.
+     * @ignore
+     */
+    protected function peek()
+    {
+        if ($this->pos < $this->len) {
+            return $this->data[$this->pos];
+        } else {
+            return -1;
+        }
+    }
+
+
+    /**
+     * Steps back, restoring the previous character read() to the input buffer
+     * @ignore
+     */
+    protected function unread()
+    {
+        if ($this->pos > 0) {
+            $this->pos--;
+        } else {
+            throw new EasyRdf_Exception("Turtle Parse Error: unread error");
+        }
+    }
+
+    /**
+     * Returns true if $c is a whitespace character
+     * @ignore
+     */
+    public static function isWhitespace($c)
+    {
+        // Whitespace character are space, tab, newline and carriage return:
+        return $c == " " || $c == "\t" || $c == "\r" || $c == "\n";
+    }
+
+    /** @ignore */
+    public static function isPrefixStartChar($c)
+    {
+        $o = ord($c);
+        return
+            $o >= 0x41   && $o <= 0x5a ||     # A-Z
+            $o >= 0x61   && $o <= 0x7a ||     # a-z
+            $o >= 0x00C0 && $o <= 0x00D6 ||
+            $o >= 0x00D8 && $o <= 0x00F6 ||
+            $o >= 0x00F8 && $o <= 0x02FF ||
+            $o >= 0x0370 && $o <= 0x037D ||
+            $o >= 0x037F && $o <= 0x1FFF ||
+            $o >= 0x200C && $o <= 0x200D ||
+            $o >= 0x2070 && $o <= 0x218F ||
+            $o >= 0x2C00 && $o <= 0x2FEF ||
+            $o >= 0x3001 && $o <= 0xD7FF ||
+            $o >= 0xF900 && $o <= 0xFDCF ||
+            $o >= 0xFDF0 && $o <= 0xFFFD ||
+            $o >= 0x10000 && $o <= 0xEFFFF;
+    }
+
+    /** @ignore */
+    public static function isNameStartChar($c)
+    {
+        return $c == '_' || self::isPrefixStartChar($c);
+    }
+
+    /** @ignore */
+    public static function isNameChar($c)
+    {
+        $o = ord($c);
+        return
+            self::isNameStartChar($c) ||
+            $c == '-' ||
+            $o >= 0x30 && $o <= 0x39 ||   # numeric
+            $o == 0x00B7 ||
+            $o >= 0x0300 && $o <= 0x036F ||
+            $o >= 0x203F && $o <= 0x2040;
+    }
+
+    /** @ignore */
+    public static function isPrefixChar($c)
+    {
+        return self::isNameChar($c);
+    }
+
+    /** @ignore */
+    public static function isLanguageStartChar($c)
+    {
+        $o = ord($c);
+        return
+            $o >= 0x41   && $o <= 0x5a ||
+            $o >= 0x61   && $o <= 0x7a;
+    }
+
+    /** @ignore */
+    public static function isLanguageChar($c)
+    {
+        $o = ord($c);
+        return
+            $o >= 0x41   && $o <= 0x5a ||   # A-Z
+            $o >= 0x61   && $o <= 0x7a ||   # a-z
+            $o >= 0x30   && $o <= 0x39 ||   # 0-9
+            $c == '-';
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Resource.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Resource.php
new file mode 100644
index 000000000000..ee99fbc0b4dc
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Resource.php
@@ -0,0 +1,692 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class that represents an RDF resource
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Resource
+{
+    /** The URI for this resource */
+    private $uri = null;
+
+    /** The Graph that this resource belongs to */
+    private $graph = null;
+
+
+    /** Constructor
+     *
+     * * Please do not call new EasyRdf_Resource() directly *
+     *
+     * To create a new resource use the get method in a graph:
+     * $resource = $graph->resource('http://www.example.com/');
+     *
+     */
+    public function __construct($uri, $graph = null)
+    {
+        if (!is_string($uri) or $uri == null or $uri == '') {
+            throw new InvalidArgumentException(
+                "\$uri should be a string and cannot be null or empty"
+            );
+        }
+
+        $this->uri = $uri;
+
+        # Check that $graph is an EasyRdf_Graph object
+        if (is_object($graph) and $graph instanceof EasyRdf_Graph) {
+            $this->graph = $graph;
+        } elseif (!is_null($graph)) {
+            throw new InvalidArgumentException(
+                "\$graph should be an EasyRdf_Graph object"
+            );
+        }
+    }
+
+    /** Returns the URI for the resource.
+     *
+     * @return string  URI of this resource.
+     */
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
+    /** Check to see if a resource is a blank node.
+     *
+     * @return bool True if this resource is a blank node.
+     */
+    public function isBnode()
+    {
+        if (substr($this->uri, 0, 2) == '_:') {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /** Get the identifier for a blank node
+     *
+     * Returns null if the resource is not a blank node.
+     *
+     * @return string The identifer for the bnode
+     */
+    public function getNodeId()
+    {
+        if (substr($this->uri, 0, 2) == '_:') {
+            return substr($this->uri, 2);
+        } else {
+            return null;
+        }
+    }
+
+    /** Get a the prefix of the namespace that this resource is part of
+     *
+     * This method will return null the resource isn't part of any
+     * registered namespace.
+     *
+     * @return string The namespace prefix of the resource (e.g. foaf)
+     */
+    public function prefix()
+    {
+        return EasyRdf_Namespace::prefixOfUri($this->uri);
+    }
+
+    /** Get a shortened version of the resources URI.
+     *
+     * This method will return the full URI if the resource isn't part of any
+     * registered namespace.
+     *
+     * @return string The shortened URI of this resource (e.g. foaf:name)
+     */
+    public function shorten()
+    {
+        return EasyRdf_Namespace::shorten($this->uri);
+    }
+
+    /** Gets the local name of the URI of this resource
+     *
+     * The local name is defined as the part of the URI string
+     * after the last occurrence of the '#', ':' or '/' character.
+     *
+     * @return string The local name
+     */
+    public function localName()
+    {
+        if (preg_match("|([^#:/]+)$|", $this->uri, $matches)) {
+            return $matches[1];
+        }
+    }
+
+    /** Parse the URI of the resource and return as a ParsedUri object
+     *
+     * @return EasyRdf_ParsedUri
+     */
+    public function parseUri()
+    {
+        return new EasyRdf_ParsedUri($this->uri);
+    }
+
+    /** Generates an HTML anchor tag, linking to this resource.
+     *
+     * If no text is given, then the URI also uses as the link text.
+     *
+     * @param  string  $text    Text for the link.
+     * @param  array   $options Associative array of attributes for the anchor tag
+     * @return string  The HTML link string
+     */
+    public function htmlLink($text = null, $options = array())
+    {
+        $options = array_merge(array('href' => $this->uri), $options);
+        if ($text === null) {
+            $text = $this->uri;
+        }
+
+        $html = "<a";
+        foreach ($options as $key => $value) {
+            $html .= " ".htmlspecialchars($key)."=\"".
+                         htmlspecialchars($value)."\"";
+        }
+        $html .= ">".htmlspecialchars($text)."</a>";
+
+        return $html;
+    }
+
+    /** Returns the properties of the resource as an associative array
+     *
+     * For example:
+     * array('type' => 'uri', 'value' => 'http://www.example.com/')
+     *
+     * @return array  The properties of the resource
+     */
+    public function toArray()
+    {
+        if ($this->isBnode()) {
+            return array('type' => 'bnode', 'value' => $this->uri);
+        } else {
+            return array('type' => 'uri', 'value' => $this->uri);
+        }
+    }
+
+    /** Return pretty-print view of the resource
+     *
+     * @param  bool   $html  Set to true to format the dump using HTML
+     * @param  string $color The colour of the text
+     * @return string
+     */
+    public function dumpValue($html = true, $color = 'blue')
+    {
+        return EasyRdf_Utils::dumpResourceValue($this, $html, $color);
+    }
+
+    /** Magic method to return URI of resource when casted to string
+     *
+     * @return string The URI of the resource
+     */
+    public function __toString()
+    {
+        return $this->uri;
+    }
+
+
+
+    /** Throw can exception if the resource does not belong to a graph
+     *  @ignore
+     */
+    protected function checkHasGraph()
+    {
+        if (!$this->graph) {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Resource is not part of a graph."
+            );
+        }
+    }
+
+    /** Perform a load (download of remote URI) of the resource into the graph
+     *
+     * The document type is optional but should be specified if it
+     * can't be guessed or got from the HTTP headers.
+     *
+     * @param  string  $format  Optional format of the data (eg. rdfxml)
+     */
+    public function load($format = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->load($this->uri, $format);
+    }
+
+    /** Delete a property (or optionally just a specific value)
+     *
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  object  $value The value to delete (null to delete all values)
+     * @return null
+     */
+    public function delete($property, $value = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->delete($this->uri, $property, $value);
+    }
+
+    /** Add values to for a property of the resource
+     *
+     * Example:
+     *   $resource->add('prefix:property', 'value');
+     *
+     * @param  mixed $property   The property name
+     * @param  mixed $value      The value for the property
+     * @return integer           The number of values added (1 or 0)
+     */
+    public function add($property, $value)
+    {
+        $this->checkHasGraph();
+        return $this->graph->add($this->uri, $property, $value);
+    }
+
+    /** Add a literal value as a property of the resource
+     *
+     * The value can either be a single value or an array of values.
+     *
+     * Example:
+     *   $resource->add('dc:title', 'Title of Page');
+     *
+     * @param  mixed  $property  The property name
+     * @param  mixed  $values    The value or values for the property
+     * @param  string $lang      The language of the literal
+     * @return integer           The number of values added
+     */
+    public function addLiteral($property, $values, $lang = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->addLiteral($this->uri, $property, $values, $lang);
+    }
+
+    /** Add a resource as a property of the resource
+     *
+     * Example:
+     *   $bob->add('foaf:knows', 'http://example.com/alice');
+     *
+     * @param  mixed $property   The property name
+     * @param  mixed $resource2  The resource to be the value of the property
+     * @return integer           The number of values added (1 or 0)
+     */
+    public function addResource($property, $resource2)
+    {
+        $this->checkHasGraph();
+        return $this->graph->addResource($this->uri, $property, $resource2);
+    }
+
+    /** Set value for a property
+     *
+     * The new value(s) will replace the existing values for the property.
+     * The name of the property should be a string.
+     * If you set a property to null or an empty array, then the property
+     * will be deleted.
+     *
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  mixed   $value    The value for the property.
+     * @return integer           The number of values added (1 or 0)
+     */
+    public function set($property, $value)
+    {
+        $this->checkHasGraph();
+        return $this->graph->set($this->uri, $property, $value);
+    }
+
+    /** Get a single value for a property
+     *
+     * If multiple values are set for a property then the value returned
+     * may be arbitrary.
+     *
+     * If $property is an array, then the first item in the array that matches
+     * a property that exists is returned.
+     *
+     * This method will return null if the property does not exist.
+     *
+     * @param  string|array $property The name of the property (e.g. foaf:name)
+     * @param  string       $type     The type of value to filter by (e.g. literal or resource)
+     * @param  string       $lang     The language to filter by (e.g. en)
+     * @return mixed                  A value associated with the property
+     */
+    public function get($property, $type = null, $lang = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->get($this->uri, $property, $type, $lang);
+    }
+
+    /** Get a single literal value for a property of the resource
+     *
+     * If multiple values are set for a property then the value returned
+     * may be arbitrary.
+     *
+     * This method will return null if there is not literal value for the
+     * property.
+     *
+     * @param  string|array $property The name of the property (e.g. foaf:name)
+     * @param  string       $lang     The language to filter by (e.g. en)
+     * @return object EasyRdf_Literal Literal value associated with the property
+     */
+    public function getLiteral($property, $lang = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->get($this->uri, $property, 'literal', $lang);
+    }
+
+    /** Get a single resource value for a property of the resource
+     *
+     * If multiple values are set for a property then the value returned
+     * may be arbitrary.
+     *
+     * This method will return null if there is not resource for the
+     * property.
+     *
+     * @param  string|array $property The name of the property (e.g. foaf:name)
+     * @return object EasyRdf_Resource Resource associated with the property
+     */
+    public function getResource($property)
+    {
+        $this->checkHasGraph();
+        return $this->graph->get($this->uri, $property, 'resource');
+    }
+
+    /** Get all values for a property
+     *
+     * This method will return an empty array if the property does not exist.
+     *
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  string  $type     The type of value to filter by (e.g. literal)
+     * @param  string  $lang     The language to filter by (e.g. en)
+     * @return array             An array of values associated with the property
+     */
+    public function all($property, $type = null, $lang = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->all($this->uri, $property, $type, $lang);
+    }
+
+    /** Get all literal values for a property of the resource
+     *
+     * This method will return an empty array if the resource does not
+     * has any literal values for that property.
+     *
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  string  $lang     The language to filter by (e.g. en)
+     * @return array             An array of values associated with the property
+     */
+    public function allLiterals($property, $lang = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->all($this->uri, $property, 'literal', $lang);
+    }
+
+    /** Get all resources for a property of the resource
+     *
+     * This method will return an empty array if the resource does not
+     * has any resources for that property.
+     *
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @return array             An array of values associated with the property
+     */
+    public function allResources($property)
+    {
+        $this->checkHasGraph();
+        return $this->graph->all($this->uri, $property, 'resource');
+    }
+
+    /** Count the number of values for a property of a resource
+     *
+     * This method will return 0 if the property does not exist.
+     *
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  string  $type     The type of value to filter by (e.g. literal)
+     * @param  string  $lang     The language to filter by (e.g. en)
+     * @return integer           The number of values associated with the property
+     */
+    public function count($property, $type = null, $lang = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->count($this->uri, $property, $type, $lang);
+    }
+
+    /** Concatenate all values for a property into a string.
+     *
+     * The default is to join the values together with a space character.
+     * This method will return an empty string if the property does not exist.
+     *
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  string  $glue     The string to glue the values together with.
+     * @param  string  $lang     The language to filter by (e.g. en)
+     * @return string            Concatenation of all the values.
+     */
+    public function join($property, $glue = ' ', $lang = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->join($this->uri, $property, $glue, $lang);
+    }
+
+    /** Get a list of the full URIs for the properties of this resource.
+     *
+     * This method will return an empty array if the resource has no properties.
+     *
+     * @return array            Array of full URIs
+     */
+    public function propertyUris()
+    {
+        $this->checkHasGraph();
+        return $this->graph->propertyUris($this->uri);
+    }
+
+    /** Get a list of all the shortened property names (qnames) for a resource.
+     *
+     * This method will return an empty array if the resource has no properties.
+     *
+     * @return array            Array of shortened URIs
+     */
+    public function properties()
+    {
+        $this->checkHasGraph();
+        return $this->graph->properties($this->uri);
+    }
+
+    /** Get a list of the full URIs for the properties that point to this resource.
+     *
+     * @return array   Array of full property URIs
+     */
+    public function reversePropertyUris()
+    {
+        $this->checkHasGraph();
+        return $this->graph->reversePropertyUris($this->uri);
+    }
+
+    /** Check to see if a property exists for this resource.
+     *
+     * This method will return true if the property exists.
+     * If the value parameter is given, then it will only return true
+     * if the value also exists for that property.
+     *
+     * @param  string  $property The name of the property (e.g. foaf:name)
+     * @param  mixed   $value    An optional value of the property
+     * @return bool              True if value the property exists.
+     */
+    public function hasProperty($property, $value = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->hasProperty($this->uri, $property, $value);
+    }
+
+    /** Get a list of types for a resource.
+     *
+     * The types will each be a shortened URI as a string.
+     * This method will return an empty array if the resource has no types.
+     *
+     * @return array All types assocated with the resource (e.g. foaf:Person)
+     */
+    public function types()
+    {
+        $this->checkHasGraph();
+        return $this->graph->types($this->uri);
+    }
+
+    /** Get a single type for a resource.
+     *
+     * The type will be a shortened URI as a string.
+     * If the resource has multiple types then the type returned
+     * may be arbitrary.
+     * This method will return null if the resource has no type.
+     *
+     * @return string A type assocated with the resource (e.g. foaf:Person)
+     */
+    public function type()
+    {
+        $this->checkHasGraph();
+        return $this->graph->type($this->uri);
+    }
+
+    /** Get a single type for a resource, as a resource.
+     *
+     * The type will be returned as an EasyRdf_Resource.
+     * If the resource has multiple types then the type returned
+     * may be arbitrary.
+     * This method will return null if the resource has no type.
+     *
+     * @return EasyRdf_Resource A type assocated with the resource.
+     */
+    public function typeAsResource()
+    {
+        return $this->graph->typeAsResource($this->uri);
+    }
+
+    /** Check if a resource is of the specified type
+     *
+     * @param  string  $type The type to check (e.g. foaf:Person)
+     * @return boolean       True if resource is of specified type.
+     */
+    public function isA($type)
+    {
+        $this->checkHasGraph();
+        return $this->graph->isA($this->uri, $type);
+    }
+
+    /** Add one or more rdf:type properties to the resource
+     *
+     * @param  string  $types    One or more types to add (e.g. foaf:Person)
+     * @return integer           The number of types added
+     */
+    public function addType($types)
+    {
+        $this->checkHasGraph();
+        return $this->graph->addType($this->uri, $types);
+    }
+
+    /** Change the rdf:type property for the resource
+     *
+     * Note that the PHP class of the resource will not change.
+     *
+     * @param  string  $type     The new type (e.g. foaf:Person)
+     * @return integer           The number of types added
+     */
+    public function setType($type)
+    {
+        $this->checkHasGraph();
+        return $this->graph->setType($this->uri, $type);
+    }
+
+    /** Get the primary topic of this resource.
+     *
+     * Returns null if no primary topic is available.
+     *
+     * @return EasyRdf_Resource The primary topic of this resource.
+     */
+    public function primaryTopic()
+    {
+        $this->checkHasGraph();
+        return $this->graph->primaryTopic($this->uri);
+    }
+
+    /** Get a human readable label for this resource
+     *
+     * This method will check a number of properties for the resource
+     * (in the order: skos:prefLabel, rdfs:label, foaf:name, dc:title)
+     * and return an approriate first that is available. If no label
+     * is available then it will return null.
+     *
+     * @return string A label for the resource.
+     */
+    public function label($lang = null)
+    {
+        $this->checkHasGraph();
+        return $this->graph->label($this->uri, $lang);
+    }
+
+    /** Return a human readable view of the resource and its properties
+     *
+     * This method is intended to be a debugging aid and will
+     * print a resource and its properties.
+     *
+     * @param  bool  $html  Set to true to format the dump using HTML
+     * @return string
+     */
+    public function dump($html = true)
+    {
+        $this->checkHasGraph();
+        return $this->graph->dumpResource($this->uri, $html);
+    }
+
+    /** Magic method to get a property of a resource
+     *
+     * Note that only properties in the default namespace can be accessed in this way.
+     *
+     * Example:
+     *   $value = $resource->title;
+     *
+     * @see EasyRdf_Namespace::setDefault()
+     * @param  string $name The name of the property
+     * @return string       A single value for the named property
+     */
+    public function __get($name)
+    {
+        return $this->graph->get($this->uri, $name);
+    }
+
+    /** Magic method to set the value for a property of a resource
+     *
+     * Note that only properties in the default namespace can be accessed in this way.
+     *
+     * Example:
+     *   $resource->title = 'Title';
+     *
+     * @see EasyRdf_Namespace::setDefault()
+     * @param  string $name The name of the property
+     * @param  string $value The value for the property
+     */
+    public function __set($name, $value)
+    {
+        return $this->graph->set($this->uri, $name, $value);
+    }
+
+    /** Magic method to check if a property exists
+     *
+     * Note that only properties in the default namespace can be accessed in this way.
+     *
+     * Example:
+     *   if (isset($resource->title)) { blah(); }
+     *
+     * @see EasyRdf_Namespace::setDefault()
+     * @param string $name The name of the property
+     */
+    public function __isset($name)
+    {
+        return $this->graph->hasProperty($this->uri, $name);
+    }
+
+    /** Magic method to delete a property of the resource
+     *
+     * Note that only properties in the default namespace can be accessed in this way.
+     *
+     * Example:
+     *   unset($resource->title);
+     *
+     * @see EasyRdf_Namespace::setDefault()
+     * @param string $name The name of the property
+     */
+    public function __unset($name)
+    {
+        return $this->graph->delete($this->uri, $name);
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser.php
new file mode 100644
index 000000000000..19467faf7579
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Parent class for the EasyRdf serialiser
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser
+{
+    protected $prefixes = array();
+
+    /**
+     * Keep track of the prefixes used while serialising
+     * @ignore
+     */
+    protected function addPrefix($qname)
+    {
+        list ($prefix) = explode(':', $qname);
+        $this->prefixes[$prefix] = true;
+    }
+
+    /**
+     * Check and cleanup parameters passed to serialise() method
+     * @ignore
+     */
+    protected function checkSerialiseParams(&$graph, &$format)
+    {
+        if ($graph == null or !is_object($graph) or
+            get_class($graph) != 'EasyRdf_Graph') {
+            throw new InvalidArgumentException(
+                "\$graph should be an EasyRdf_Graph object and cannot be null"
+            );
+        }
+
+        if ($format == null or $format == '') {
+            throw new InvalidArgumentException(
+                "\$format cannot be null or empty"
+            );
+        } elseif (is_object($format) and
+                   get_class($format) == 'EasyRdf_Format') {
+            $format = $format->getName();
+        } elseif (!is_string($format)) {
+            throw new InvalidArgumentException(
+                "\$format should be a string or an EasyRdf_Format object"
+            );
+        }
+    }
+
+    /**
+     * Protected method to get the number of reverse properties for a resource
+     * If a resource only has a single property, the number of values for that
+     * property is returned instead.
+     * @ignore
+     */
+    protected function reversePropertyCount($resource)
+    {
+        $properties = $resource->reversePropertyUris();
+        $count = count($properties);
+        if ($count == 1) {
+            $property = $properties[0];
+            return $resource->count("^<$property>");
+        } else {
+            return $count;
+        }
+    }
+
+    /**
+     * Sub-classes must follow this protocol
+     * @ignore
+     */
+    public function serialise($graph, $format)
+    {
+        throw new EasyRdf_Exception(
+            "This method should be overridden by sub-classes."
+        );
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Arc.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Arc.php
new file mode 100644
index 000000000000..fc79eca1a84d
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Arc.php
@@ -0,0 +1,97 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to serialise RDF using the ARC2 library.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser_Arc extends EasyRdf_Serialiser_RdfPhp
+{
+    private static $supportedTypes = array(
+        'rdfxml' => 'RDFXML',
+        'turtle' => 'Turtle',
+        'ntriples' => 'NTriples',
+        'posh' => 'POSHRDF'
+    );
+
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Serialiser_Arc
+     */
+    public function __construct()
+    {
+        require_once 'arc/ARC2.php';
+    }
+
+    /**
+     * Serialise an EasyRdf_Graph into RDF format of choice.
+     *
+     * @param object EasyRdf_Graph $graph   An EasyRdf_Graph object.
+     * @param string               $format  The name of the format to convert to.
+     * @return string              The RDF in the new desired format.
+     */
+    public function serialise($graph, $format)
+    {
+        parent::checkSerialiseParams($graph, $format);
+
+        if (array_key_exists($format, self::$supportedTypes)) {
+            $className = self::$supportedTypes[$format];
+        } else {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Serialiser_Arc does not support: $format"
+            );
+        }
+
+        $serialiser = ARC2::getSer($className);
+        if ($serialiser) {
+            return $serialiser->getSerializedIndex(
+                parent::serialise($graph, 'php')
+            );
+        } else {
+            throw new EasyRdf_Exception(
+                "ARC2 failed to get a $className serialiser."
+            );
+        }
+    }
+}
+
+EasyRdf_Format::register('posh', 'poshRDF');
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/GraphViz.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/GraphViz.php
new file mode 100644
index 000000000000..632f932729d9
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/GraphViz.php
@@ -0,0 +1,391 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to serialise an EasyRdf_Graph to GraphViz
+ *
+ * Depends upon the GraphViz 'dot' command line tools to render images.
+ *
+ * See http://www.graphviz.org/ for more information.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser_GraphViz extends EasyRdf_Serialiser
+{
+    private $dotCommand = 'dot';
+    private $useLabels = false;
+    private $onlyLabelled = false;
+    private $attributes = array('charset' => 'utf-8');
+
+    /**
+     * Constructor
+     *
+     * @return object EasyRdf_Serialiser_GraphViz
+     */
+    public function __construct()
+    {
+    }
+
+    /**
+     * Set the path to the GraphViz 'dot' command
+     *
+     * Default is to search PATH for the command 'dot'.
+     *
+     * @param string $cmd   The path to the 'dot' command.
+     * @return object EasyRdf_Serialiser_GraphViz
+     */
+    public function setDotCommand($cmd)
+    {
+        $this->dotCommand = $cmd;
+        return $this;
+    }
+
+    /**
+     * Get the path to the GraphViz 'dot' command
+     *
+     * The default value is simply 'dot'
+     *
+     * @return string The path to the 'dot' command.
+     */
+    public function getDotCommand()
+    {
+        return $this->dotCommand;
+    }
+
+    /**
+     * Turn on/off the option to display labels instead of URIs.
+     *
+     * When this option is turned on, then labels for resources will
+     * be displayed instead of the full URI of a resource. This makes
+     * it simpler to create friendly diagrams that non-technical people
+     * can understand.
+     *
+     * This option is turned off by default.
+     *
+     * @param bool $useLabels   A boolean value to turn labels on and off
+     * @return object EasyRdf_Serialiser_GraphViz
+     */
+    public function setUseLabels($useLabels)
+    {
+        $this->useLabels = $useLabels;
+        return $this;
+    }
+
+    /**
+     * Get the state of the use labels option
+     *
+     * @return bool The current state of the use labels option
+     */
+    public function getUseLabels()
+    {
+        return $this->useLabels;
+    }
+
+    /**
+     * Turn on/off the option to only display nodes and edges with labels
+     *
+     * When this option is turned on, then only nodes (resources and literals)
+     * and edges (properties) will only be displayed if they have a label. You
+     * can use this option, to create concise, diagrams of your data, rather than
+     * the RDF.
+     *
+     * This option is turned off by default.
+     *
+     * @param bool $onlyLabelled   A boolean value to enable/display only labelled items
+     * @return object EasyRdf_Serialiser_GraphViz
+     */
+    public function setOnlyLabelled($onlyLabelled)
+    {
+        $this->onlyLabelled = $onlyLabelled;
+        return $this;
+    }
+
+    /**
+     * Get the state of the only Only Labelled option
+     *
+     * @return bool The current state of the Only Labelled option
+     */
+    public function getOnlyLabelled()
+    {
+        return $this->onlyLabelled;
+    }
+
+    /**
+     * Set an attribute on the GraphViz graph
+     *
+     * Example:
+     *     $serialiser->setAttribute('rotate', 90);
+     *
+     * See the GraphViz tool documentation for information about the
+     * available attributes.
+     *
+     * @param string $name    The name of the attribute
+     * @param string $value   The value for the attribute
+     * @return object EasyRdf_Serialiser_GraphViz
+     */
+    public function setAttribute($name, $value)
+    {
+        $this->attributes[$name] = $value;
+        return $this;
+    }
+
+    /**
+     * Get an attribute of the GraphViz graph
+     *
+     * @param string $name    Attribute name
+     * @return string The value of the graph attribute
+     */
+    public function getAttribute($name)
+    {
+        return $this->attributes[$name];
+    }
+
+    /**
+     * Convert an EasyRdf object into a GraphViz node identifier
+     *
+     * @ignore
+     */
+    protected function nodeName($entity)
+    {
+        if ($entity instanceof EasyRdf_Resource) {
+            if ($entity->isBnode()) {
+                return "B".$entity->getUri();
+            } else {
+                return "R".$entity->getUri();
+            }
+        } else {
+            return "L".$entity;
+        }
+    }
+
+    /**
+     * Internal function to escape a string into DOT safe syntax
+     *
+     * @ignore
+     */
+    protected function escape($input)
+    {
+        if (preg_match('/^([a-z_][a-z_0-9]*|-?(\.[0-9]+|[0-9]+(\.[0-9]*)?))$/i', $input)) {
+            return $input;
+        } else {
+            return '"'.str_replace(
+                array("\r\n", "\n", "\r", '"'),
+                array('\n',   '\n', '\n', '\"'),
+                $input
+            ).'"';
+        }
+    }
+
+    /**
+     * Internal function to escape an associate array of attributes and
+     * turns it into a DOT notation string
+     *
+     * @ignore
+     */
+    protected function escapeAttributes($array)
+    {
+        $items = '';
+        foreach ($array as $k => $v) {
+            $items[] = $this->escape($k).'='.$this->escape($v);
+        }
+        return '['.implode(',', $items).']';
+    }
+
+    /**
+     * Internal function to create dot syntax line for either a node or an edge
+     *
+     * @ignore
+     */
+    protected function serialiseRow($node1, $node2 = null, $attributes = array())
+    {
+        $result = '  '.$this->escape($node1);
+        if ($node2) {
+            $result .= ' -> '.$this->escape($node2);
+        }
+        if (count($attributes)) {
+            $result .= ' '.$this->escapeAttributes($attributes);
+        }
+        return $result.";\n";
+    }
+
+    /**
+     * Internal function to serialise an EasyRdf_Graph into a DOT formatted string
+     *
+     * @ignore
+     */
+    protected function serialiseDot($graph)
+    {
+        $result = "digraph {\n";
+
+        // Write the graph attributes
+        foreach ($this->attributes as $k => $v) {
+            $result .= '  '.$this->escape($k).'='.$this->escape($v).";\n";
+        }
+
+        // Go through each of the properties and write the edges
+        $nodes = array();
+        $result .= "\n  // Edges\n";
+        foreach ($graph->resources() as $resource) {
+            $name1 = $this->nodeName($resource);
+            foreach ($resource->propertyUris() as $property) {
+                $label = null;
+                if ($this->useLabels) {
+                    $label = $graph->resource($property)->label();
+                }
+                if ($label === null) {
+                    if ($this->onlyLabelled == true) {
+                        continue;
+                    } else {
+                        $label = EasyRdf_Namespace::shorten($property);
+                    }
+                }
+                foreach ($resource->all("<$property>") as $value) {
+                    $name2 = $this->nodeName($value);
+                    $nodes[$name1] = $resource;
+                    $nodes[$name2] = $value;
+                    $result .= $this->serialiseRow(
+                        $name1,
+                        $name2,
+                        array('label' => $label)
+                    );
+                }
+            }
+        }
+
+        ksort($nodes);
+
+        $result .= "\n  // Nodes\n";
+        foreach ($nodes as $name => $node) {
+            $type = substr($name, 0, 1);
+            $label = '';
+            if ($type == 'R') {
+                if ($this->useLabels) {
+                    $label = $node->label();
+                }
+                if (!$label) {
+                    $label = $node->shorten();
+                }
+                if (!$label) {
+                    $label = $node->getURI();
+                }
+                $result .= $this->serialiseRow(
+                    $name,
+                    null,
+                    array(
+                        'URL'   => $node->getURI(),
+                        'label' => $label,
+                        'shape' => 'ellipse',
+                        'color' => 'blue'
+                    )
+                );
+            } elseif ($type == 'B') {
+                if ($this->useLabels) {
+                    $label = $node->label();
+                }
+                $result .= $this->serialiseRow(
+                    $name,
+                    null,
+                    array(
+                        'label' => $label,
+                        'shape' => 'circle',
+                        'color' => 'green'
+                    )
+                );
+            } else {
+                $result .= $this->serialiseRow(
+                    $name,
+                    null,
+                    array(
+                        'label' => strval($node),
+                        'shape' => 'record',
+                    )
+                );
+            }
+
+        }
+
+        $result .= "}\n";
+
+        return $result;
+    }
+
+    /**
+     * Internal function to render a graph into an image
+     *
+     * @ignore
+     */
+    public function renderImage($graph, $format = 'png')
+    {
+        $dot = $this->serialiseDot($graph);
+
+        return EasyRdf_Utils::execCommandPipe(
+            $this->dotCommand,
+            array("-T$format"),
+            $dot
+        );
+    }
+
+    /**
+     * Serialise an EasyRdf_Graph into a GraphViz dot document.
+     *
+     * Supported output format names: dot, gif, png, svg
+     *
+     * @param string $graph An EasyRdf_Graph object.
+     * @param string $format The name of the format to convert to.
+     * @return string The RDF in the new desired format.
+     */
+    public function serialise($graph, $format)
+    {
+        parent::checkSerialiseParams($graph, $format);
+
+        switch($format) {
+            case 'dot':
+                return $this->serialiseDot($graph);
+            case 'png':
+            case 'gif':
+            case 'svg':
+                return $this->renderImage($graph, $format);
+            default:
+                throw new EasyRdf_Exception(
+                    "EasyRdf_Serialiser_GraphViz does not support: $format"
+                );
+        }
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Json.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Json.php
new file mode 100644
index 000000000000..d2bc15ea699e
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Json.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to serialise an EasyRdf_Graph to RDF/JSON
+ * with no external dependancies.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser_Json extends EasyRdf_Serialiser_RdfPhp
+{
+    /**
+     * Method to serialise an EasyRdf_Graph to RDF/JSON
+     *
+     * http://n2.talis.com/wiki/RDF_JSON_Specification
+     *
+     * @param object EasyRdf_Graph $graph   An EasyRdf_Graph object.
+     * @param string  $format               The name of the format to convert to.
+     * @return string                       The RDF in the new desired format.
+     */
+    public function serialise($graph, $format)
+    {
+        parent::checkSerialiseParams($graph, $format);
+
+        if ($format != 'json') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Serialiser_Json does not support: $format"
+            );
+        }
+
+        return json_encode(parent::serialise($graph, 'php'));
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Ntriples.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Ntriples.php
new file mode 100644
index 000000000000..02577511e793
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Ntriples.php
@@ -0,0 +1,209 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to serialise an EasyRdf_Graph to N-Triples
+ * with no external dependancies.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser_Ntriples extends EasyRdf_Serialiser
+{
+    private $escChars = array();   // Character encoding cache
+
+    /**
+     * @ignore
+     */
+    protected function escapeString($str)
+    {
+        if (strpos(utf8_decode(str_replace('?', '', $str)), '?') === false) {
+            $str = utf8_decode($str);
+        }
+
+        $result = '';
+        $strLen = strlen($str);
+        for ($i = 0; $i < $strLen; $i++) {
+            $c = $str[$i];
+            if (!isset($this->escChars[$c])) {
+                $this->escChars[$c] = $this->escapedChar($c);
+            }
+            $result .= $this->escChars[$c];
+        }
+        return $result;
+    }
+
+    /**
+     * @ignore
+     */
+    protected function unicodeCharNo($c)
+    {
+        $cUtf = utf8_encode($c);
+        $bl = strlen($cUtf); /* binary length */
+        $r = 0;
+        switch ($bl) {
+            case 1: /* 0####### (0-127) */
+                $r = ord($cUtf);
+                break;
+            case 2: /* 110##### 10###### = 192+x 128+x */
+                $r = ((ord($cUtf[0]) - 192) * 64) +
+                     (ord($cUtf[1]) - 128);
+                break;
+            case 3: /* 1110#### 10###### 10###### = 224+x 128+x 128+x */
+                $r = ((ord($cUtf[0]) - 224) * 4096) +
+                     ((ord($cUtf[1]) - 128) * 64) +
+                     (ord($cUtf[2]) - 128);
+                break;
+            case 4: /* 1111#### 10###### 10###### 10###### = 240+x 128+x 128+x 128+x */
+                $r = ((ord($cUtf[0]) - 240) * 262144) +
+                     ((ord($cUtf[1]) - 128) * 4096) +
+                     ((ord($cUtf[2]) - 128) * 64) +
+                     (ord($cUtf[3]) - 128);
+                break;
+        }
+        return $r;
+    }
+
+    /**
+     * @ignore
+     */
+    protected function escapedChar($c)
+    {
+        $no = $this->unicodeCharNo($c);
+
+        /* see http://www.w3.org/TR/rdf-testcases/#ntrip_strings */
+        if ($no < 9) {
+            return "\\u" . sprintf('%04X', $no);  /* #x0-#x8 (0-8) */
+        } elseif ($no == 9) {
+            return '\t';                          /* #x9 (9) */
+        } elseif ($no == 10) {
+            return '\n';                          /* #xA (10) */
+        } elseif ($no < 13) {
+            return "\\u" . sprintf('%04X', $no);  /* #xB-#xC (11-12) */
+        } elseif ($no == 13) {
+            return '\r';                          /* #xD (13) */
+        } elseif ($no < 32) {
+            return "\\u" . sprintf('%04X', $no);  /* #xE-#x1F (14-31) */
+        } elseif ($no < 34) {
+            return $c;                            /* #x20-#x21 (32-33) */
+        } elseif ($no == 34) {
+            return '\"';                          /* #x22 (34) */
+        } elseif ($no < 92) {
+            return $c;                            /* #x23-#x5B (35-91) */
+        } elseif ($no == 92) {
+            return '\\';                          /* #x5C (92) */
+        } elseif ($no < 127) {
+            return $c;                            /* #x5D-#x7E (93-126) */
+        } elseif ($no < 65536) {
+            return "\\u" . sprintf('%04X', $no);  /* #x7F-#xFFFF (128-65535) */
+        } elseif ($no < 1114112) {
+            return "\\U" . sprintf('%08X', $no);  /* #x10000-#x10FFFF (65536-1114111) */
+        } else {
+            return '';                            /* not defined => ignore */
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    protected function ntriplesResource($res)
+    {
+        $escaped = $this->escapeString($res);
+        if (substr($res, 0, 2) == '_:') {
+            return $escaped;
+        } else {
+            return "<$escaped>";
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    protected function ntriplesValue($value)
+    {
+        if ($value['type'] == 'uri' or $value['type'] == 'bnode') {
+            return $this->ntriplesResource($value['value']);
+        } elseif ($value['type'] == 'literal') {
+            $escaped = $this->escapeString($value['value']);
+            if (isset($value['lang'])) {
+                $lang = $this->escapeString($value['lang']);
+                return '"' . $escaped . '"' . '@' . $lang;
+            } elseif (isset($value['datatype'])) {
+                $datatype = $this->escapeString($value['datatype']);
+                return '"' . $escaped . '"' . "^^<$datatype>";
+            } else {
+                return '"' . $escaped . '"';
+            }
+        } else {
+            throw new EasyRdf_Exception(
+                "Unable to serialise object to ntriples: ".$value['type']
+            );
+        }
+    }
+
+    /**
+     * Serialise an EasyRdf_Graph into N-Triples
+     *
+     * @param object EasyRdf_Graph $graph   An EasyRdf_Graph object.
+     * @param string  $format               The name of the format to convert to.
+     * @return string                       The RDF in the new desired format.
+     */
+    public function serialise($graph, $format)
+    {
+        parent::checkSerialiseParams($graph, $format);
+
+        if ($format == 'ntriples') {
+            $nt = '';
+            foreach ($graph->toArray() as $resource => $properties) {
+                foreach ($properties as $property => $values) {
+                    foreach ($values as $value) {
+                        $nt .= $this->ntriplesResource($resource)." ";
+                        $nt .= "<" . $this->escapeString($property) . "> ";
+                        $nt .= $this->ntriplesValue($value)." .\n";
+                    }
+                }
+            }
+            return $nt;
+        } else {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Serialiser_Ntriples does not support: $format"
+            );
+        }
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Rapper.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Rapper.php
new file mode 100644
index 000000000000..a23b6c30ed37
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Rapper.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to serialise an EasyRdf_Graph to RDF
+ * using the 'rapper' command line tool.
+ *
+ * Note: the built-in N-Triples serialiser is used to pass data to Rapper.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser_Rapper extends EasyRdf_Serialiser_Ntriples
+{
+    private $rapperCmd = null;
+
+    /**
+     * Constructor
+     *
+     * @param string $rapperCmd Optional path to the rapper command to use.
+     * @return object EasyRdf_Serialiser_Rapper
+     */
+    public function __construct($rapperCmd = 'rapper')
+    {
+        $result = exec("$rapperCmd --version 2>/dev/null", $output, $status);
+        if ($status != 0) {
+            throw new EasyRdf_Exception(
+                "Failed to execute the command '$rapperCmd': $result"
+            );
+        } else {
+            $this->rapperCmd = $rapperCmd;
+        }
+    }
+
+    /**
+     * Serialise an EasyRdf_Graph to the RDF format of choice.
+     *
+     * @param object EasyRdf_Graph $graph   An EasyRdf_Graph object.
+     * @param string  $format               The name of the format to convert to.
+     * @return string                       The RDF in the new desired format.
+     */
+    public function serialise($graph, $format)
+    {
+        parent::checkSerialiseParams($graph, $format);
+
+        $ntriples = parent::serialise($graph, 'ntriples');
+
+        // Hack to produce more concise RDF/XML
+        if ($format == 'rdfxml') {
+            $format = 'rdfxml-abbrev';
+        }
+
+        return EasyRdf_Utils::execCommandPipe(
+            $this->rapperCmd,
+            array(
+                '--quiet',
+                '--input', 'ntriples',
+                '--output', $format,
+                '-', 'unknown://'
+            ),
+            $ntriples
+        );
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/RdfPhp.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/RdfPhp.php
new file mode 100644
index 000000000000..e6a864704b35
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/RdfPhp.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to serialise an EasyRdf_Graph to RDF/PHP
+ * with no external dependancies.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser_RdfPhp extends EasyRdf_Serialiser
+{
+    /**
+     * Method to serialise an EasyRdf_Graph to RDF/PHP
+     *
+     * http://n2.talis.com/wiki/RDF_PHP_Specification
+     *
+     * @param object EasyRdf_Graph $graph   An EasyRdf_Graph object.
+     * @param string  $format               The name of the format to convert to.
+     * @return string                       The RDF in the new desired format.
+     */
+    public function serialise($graph, $format)
+    {
+        parent::checkSerialiseParams($graph, $format);
+
+        if ($format != 'php') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Serialiser_RdfPhp does not support: $format"
+            );
+        }
+
+        // Graph is already stored an RDF/PHP resource-centric array internally within the EasyRdf_Graph object
+        return $graph->toArray();
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/RdfXml.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/RdfXml.php
new file mode 100644
index 000000000000..1936d8f62dc6
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/RdfXml.php
@@ -0,0 +1,218 @@
+<?php
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to serialise an EasyRdf_Graph to RDF/XML
+ * with no external dependancies.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser_RdfXml extends EasyRdf_Serialiser
+{
+    private $outputtedResources = array();
+
+    /** A constant for the RDF Type property URI */
+    const RDF_XML_LITERAL = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral';
+
+    /**
+     * Protected method to serialise an object node into an XML object
+     * @ignore
+     */
+    protected function rdfxmlObject($property, $obj, $depth)
+    {
+        $indent = str_repeat('  ', $depth);
+        if (is_object($obj) and $obj instanceof EasyRdf_Resource) {
+            $pcount = count($obj->propertyUris());
+            $rpcount = $this->reversePropertyCount($obj);
+            $alreadyOutput = isset($this->outputtedResources[$obj->getUri()]);
+
+            $tag = "$indent<$property";
+            if ($obj->isBNode()) {
+                if ($alreadyOutput or $rpcount > 1 or $pcount == 0) {
+                    $tag .= " rdf:nodeID=\"".htmlspecialchars($obj->getNodeId()).'"';
+                }
+            } else {
+                if ($alreadyOutput or $rpcount != 1 or $pcount == 0) {
+                    $tag .= " rdf:resource=\"".htmlspecialchars($obj->getURI()).'"';
+                }
+            }
+
+            if ($alreadyOutput == false and $rpcount == 1 and $pcount > 0) {
+                $xml = $this->rdfxmlResource($obj, false, $depth+1);
+                if ($xml) {
+                    return "$tag>$xml$indent</$property>\n\n";
+                } else {
+                    return '';
+                }
+            } else {
+                return $tag."/>\n";
+            }
+
+        } elseif (is_object($obj) and $obj instanceof EasyRdf_Literal) {
+            $atrributes = "";
+            $datatype = $obj->getDatatypeUri();
+            if ($datatype) {
+                if ($datatype == self::RDF_XML_LITERAL) {
+                    $atrributes .= " rdf:parseType=\"Literal\"";
+                    $value = strval($obj);
+                } else {
+                    $datatype = htmlspecialchars($datatype);
+                    $atrributes .= " rdf:datatype=\"$datatype\"";
+                }
+            } elseif ($obj->getLang()) {
+                $atrributes .= ' xml:lang="'.
+                               htmlspecialchars($obj->getLang()).'"';
+            }
+
+            // Escape the value
+            if (!isset($value)) {
+                $value = htmlspecialchars(strval($obj));
+            }
+
+            return "$indent<$property$atrributes>$value</$property>\n";
+        } else {
+            throw new EasyRdf_Exception(
+                "Unable to serialise object to xml: ".getType($obj)
+            );
+        }
+    }
+
+    /**
+     * Protected method to serialise a whole resource and its properties
+     * @ignore
+     */
+    protected function rdfxmlResource($res, $showNodeId, $depth = 1)
+    {
+        // Keep track of the resources we have already serialised
+        if (isset($this->outputtedResources[$res->getUri()])) {
+            return '';
+        } else {
+            $this->outputtedResources[$res->getUri()] = true;
+        }
+
+        // If the resource has no properties - don't serialise it
+        $properties = $res->propertyUris();
+        if (count($properties) == 0) {
+            return '';
+        }
+
+        $type = $res->type();
+        if ($type) {
+            $this->addPrefix($type);
+        } else {
+            $type = 'rdf:Description';
+        }
+
+        $indent = str_repeat('  ', $depth);
+        $xml = "\n$indent<$type";
+        if ($res->isBNode()) {
+            if ($showNodeId) {
+                $xml .= ' rdf:nodeID="'.htmlspecialchars($res->getNodeId()).'"';
+            }
+        } else {
+            $xml .= ' rdf:about="'.htmlspecialchars($res->getUri()).'"';
+        }
+        $xml .= ">\n";
+
+        foreach ($properties as $property) {
+            $short = EasyRdf_Namespace::shorten($property, true);
+            if ($short) {
+                $this->addPrefix($short);
+                $objects = $res->all("<$property>");
+                if ($short == 'rdf:type') {
+                    array_shift($objects);
+                }
+                foreach ($objects as $object) {
+                    $xml .= $this->rdfxmlObject($short, $object, $depth+1);
+                }
+            } else {
+                throw new EasyRdf_Exception(
+                    "It is not possible to serialse the property ".
+                    "'$property' to RDF/XML."
+                );
+            }
+        }
+        $xml .= "$indent</$type>\n";
+
+        return $xml;
+    }
+
+
+    /**
+     * Method to serialise an EasyRdf_Graph to RDF/XML
+     *
+     * @param object EasyRdf_Graph $graph   An EasyRdf_Graph object.
+     * @param string  $format               The name of the format to convert to.
+     * @return string                       The RDF in the new desired format.
+     */
+    public function serialise($graph, $format)
+    {
+        parent::checkSerialiseParams($graph, $format);
+
+        if ($format != 'rdfxml') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Serialiser_RdfXml does not support: $format"
+            );
+        }
+
+        // store of namespaces to be appended to the rdf:RDF tag
+        $this->prefixes = array('rdf' => true);
+
+        // store of the resource URIs we have serialised
+        $this->outputtedResources = array();
+
+        $xml = '';
+        foreach ($graph->resources() as $resource) {
+            $xml .= $this->rdfxmlResource($resource, true, 1);
+        }
+
+        // iterate through namepsaces array prefix and output a string.
+        $namespaceStr = '';
+        foreach ($this->prefixes as $prefix => $count) {
+            $url = EasyRdf_Namespace::get($prefix);
+            if (strlen($namespaceStr)) {
+                $namespaceStr .= "\n        ";
+            }
+            $namespaceStr .= ' xmlns:'.$prefix.'="'.htmlspecialchars($url).'"';
+        }
+
+        return "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n".
+               "<rdf:RDF". $namespaceStr . ">\n" . $xml . "\n</rdf:RDF>\n";
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Turtle.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Turtle.php
new file mode 100644
index 000000000000..dfc817d9b818
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Serialiser/Turtle.php
@@ -0,0 +1,266 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to serialise an EasyRdf_Graph to Turtle
+ * with no external dependancies.
+ *
+ * http://www.dajobe.org/2004/01/turtle
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Serialiser_Turtle extends EasyRdf_Serialiser
+{
+    private $outputtedBnodes = array();
+
+    /**
+     * @ignore
+     */
+    protected function serialiseResource($resource)
+    {
+        if ($resource->isBnode()) {
+            return $resource->getUri();
+        } else {
+            $short = $resource->shorten();
+            if ($short) {
+                $this->addPrefix($short);
+                return $short;
+            } else {
+                $uri = str_replace('>', '\\>', $resource);
+                return "<$resource>";
+            }
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    protected function quotedString($value)
+    {
+        if (preg_match("/[\t\n\r]/", $value)) {
+            $escaped = str_replace(array('\\', '"""'), array('\\\\', '\\"""'), $value);
+            return '"""'.$escaped.'"""';
+        } else {
+            $escaped = str_replace(array('\\', '"'), array('\\\\', '\\"'), $value);
+            return '"'.$escaped.'"';
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    protected function serialiseObject($object)
+    {
+        if ($object instanceof EasyRdf_Resource) {
+            return $this->serialiseResource($object);
+        } else {
+            $value = strval($object);
+            $quoted = $this->quotedString($value);
+
+            if ($datatype = $object->getDatatypeUri()) {
+                $short = EasyRdf_Namespace::shorten($datatype, true);
+                if ($short) {
+                    $this->addPrefix($short);
+                    if ($short == 'xsd:integer') {
+                        return sprintf('%d', $value);
+                    } elseif ($short == 'xsd:decimal') {
+                        return sprintf('%g', $value);
+                    } elseif ($short == 'xsd:double') {
+                        return sprintf('%e', $value);
+                    } elseif ($short == 'xsd:boolean') {
+                        return sprintf('%s', $value ? 'true' : 'false');
+                    } else {
+                        return sprintf('%s^^%s', $quoted, $short);
+                    }
+                } else {
+                    $datatypeUri = str_replace('>', '\\>', $datatype);
+                    return sprintf('%s^^<%s>', $quoted, $datatypeUri);
+                }
+            } elseif ($lang = $object->getLang()) {
+                return $quoted . '@' . $lang;
+            } else {
+                return $quoted;
+            }
+        }
+    }
+
+    /**
+     * Protected method to serialise the properties of a resource
+     * @ignore
+     */
+    protected function serialiseProperties($res, $depth = 1)
+    {
+        $properties = $res->propertyUris();
+        $indent = str_repeat(' ', ($depth*2)-1);
+
+        $turtle = '';
+        if (count($properties) > 1) {
+            $turtle .= "\n$indent";
+        }
+
+        $pCount = 0;
+        foreach ($properties as $property) {
+            $short = EasyRdf_Namespace::shorten($property, true);
+            if ($short) {
+                if ($short == 'rdf:type') {
+                    $pStr = 'a';
+                } else {
+                    $this->addPrefix($short);
+                    $pStr = $short;
+                }
+            } else {
+                $pStr = '<'.str_replace('>', '\\>', $property).'>';
+            }
+
+            if ($pCount) {
+                $turtle .= " ;\n$indent";
+            }
+
+            $turtle .= ' ' . $pStr;
+
+            $oCount = 0;
+            foreach ($res->all("<$property>") as $object) {
+                if ($oCount) {
+                    $turtle .= ',';
+                }
+
+                if ($object instanceof EasyRdf_Resource and $object->isBnode()) {
+                    $id = $object->getNodeId();
+                    $rpcount = $this->reversePropertyCount($object);
+                    if ($rpcount <= 1 and !isset($this->outputtedBnodes[$id])) {
+                        // Nested unlabelled Blank Node
+                        $this->outputtedBnodes[$id] = true;
+                        $turtle .= ' [';
+                        $turtle .= $this->serialiseProperties($object, $depth+1);
+                        $turtle .= ' ]';
+                    } else {
+                        // Multiple properties pointing to this blank node
+                        $turtle .= ' ' . $this->serialiseObject($object);
+                    }
+                } else {
+                    $turtle .= ' ' . $this->serialiseObject($object);
+                }
+                $oCount++;
+            }
+            $pCount++;
+        }
+
+        if ($depth == 1) {
+            $turtle .= " .";
+            if ($pCount > 1) {
+                $turtle .= "\n";
+            }
+        } elseif ($pCount > 1) {
+            $turtle .= "\n" . str_repeat(' ', (($depth-1)*2)-1);
+        }
+
+        return $turtle;
+    }
+
+    /**
+     * @ignore
+     */
+    protected function serialisePrefixes()
+    {
+        $turtle = '';
+        foreach ($this->prefixes as $prefix => $count) {
+            $url = EasyRdf_Namespace::get($prefix);
+            $turtle .= "@prefix $prefix: <$url> .\n";
+        }
+        return $turtle;
+    }
+
+    /**
+     * Serialise an EasyRdf_Graph to Turtle.
+     *
+     * @param object EasyRdf_Graph $graph   An EasyRdf_Graph object.
+     * @param string  $format               The name of the format to convert to.
+     * @return string                       The RDF in the new desired format.
+     */
+    public function serialise($graph, $format)
+    {
+        parent::checkSerialiseParams($graph, $format);
+
+        if ($format != 'turtle' and $format != 'n3') {
+            throw new EasyRdf_Exception(
+                "EasyRdf_Serialiser_Turtle does not support: $format"
+            );
+        }
+
+        $this->prefixes = array();
+        $this->outputtedBnodes = array();
+
+        $turtle = '';
+        foreach ($graph->resources() as $resource) {
+            // If the resource has no properties - don't serialise it
+            $properties = $resource->propertyUris();
+            if (count($properties) == 0) {
+                continue;
+            }
+
+            if ($resource->isBnode()) {
+                $id = $resource->getNodeId();
+                $rpcount = $this->reversePropertyCount($resource);
+                if (isset($this->outputtedBnodes[$id])) {
+                    // Already been serialised
+                    continue;
+                } else {
+                    $this->outputtedBnodes[$id] = true;
+                    if ($rpcount == 0) {
+                        $turtle .= '[]';
+                    } else {
+                        $turtle .= $this->serialiseResource($resource);
+                    }
+                }
+            } else {
+                $turtle .= $this->serialiseResource($resource);
+            }
+
+            $turtle .= $this->serialiseProperties($resource);
+            $turtle .= "\n";
+        }
+
+        if (count($this->prefixes)) {
+            return $this->serialisePrefixes() . "\n" . $turtle;
+        } else {
+            return $turtle;
+        }
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Sparql/Client.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Sparql/Client.php
new file mode 100644
index 000000000000..35eca3da7231
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Sparql/Client.php
@@ -0,0 +1,134 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class for making SPARQL queries using the SPARQL 1.1 Protocol
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Sparql_Client
+{
+    /** The address of the SPARQL Endpoint */
+    private $uri = null;
+
+    /** Configuration settings */
+    private $config = array();
+
+
+    /** Create a new SPARQL endpoint client
+     *
+     * @param string $uri The address of the SPARQL Endpoint
+     */
+    public function __construct($uri)
+    {
+        $this->uri = $uri;
+    }
+
+    /** Get the URI of the SPARQL endpoint
+     *
+     * @return string The URI of the SPARQL endpoint
+     */
+    public function getUri()
+    {
+        return $this->uri;
+    }
+
+    /** Make a query to the SPARQL endpoint
+     *
+     * SELECT and ASK queries will return an object of type
+     * EasyRdf_Sparql_Result.
+     *
+     * CONSTRUCT and DESCRIBE queries will return an object
+     * of type EasyRdf_Graph.
+     *
+     * @param string $query The query string to be executed
+     * @return object EasyRdf_Sparql_Result|EasyRdf_Graph Result of the query.
+     */
+    public function query($query)
+    {
+        # Add namespaces to the queryString
+        $prefixes = '';
+        foreach (EasyRdf_Namespace::namespaces() as $prefix => $uri) {
+            if (strpos($query, "$prefix:") !== false and
+                strpos($query, "PREFIX $prefix:") === false) {
+                $prefixes .=  "PREFIX $prefix: <$uri>\n";
+            }
+        }
+
+        $client = EasyRdf_Http::getDefaultHttpClient();
+        $client->resetParameters();
+        $client->setUri($this->uri);
+        $client->setMethod('GET');
+
+        $accept = EasyRdf_Format::getHttpAcceptHeader(
+            array(
+              'application/sparql-results+json' => 1.0,
+              'application/sparql-results+xml' => 0.8
+            )
+        );
+        $client->setHeaders('Accept', $accept);
+        $client->setParameterGet('query', $prefixes . $query);
+
+        $response = $client->request();
+        if ($response->isSuccessful()) {
+            list($type, $params) = EasyRdf_Utils::parseMimeType(
+                $response->getHeader('Content-Type')
+            );
+            if (strpos($type, 'application/sparql-results') === 0) {
+                return new EasyRdf_Sparql_Result($response->getBody(), $type);
+            } else {
+                return new EasyRdf_Graph($this->uri, $response->getBody(), $type);
+            }
+        } else {
+            throw new EasyRdf_Exception(
+                "HTTP request for SPARQL query failed: ".$response->getBody()
+            );
+        }
+    }
+
+    /** Magic method to return URI of the SPARQL endpoint when casted to string
+     *
+     * @return string The URI of the SPARQL endpoint
+     */
+    public function __toString()
+    {
+        return $this->uri == null ? '' : $this->uri;
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Sparql/Result.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Sparql/Result.php
new file mode 100644
index 000000000000..6bc7f62aae52
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Sparql/Result.php
@@ -0,0 +1,381 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class for returned for SPARQL SELECT and ASK query responses.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Sparql_Result extends ArrayIterator
+{
+    private $type = null;
+    private $boolean = null;
+
+    private $ordered = null;
+    private $distinct = null;
+    private $fields = array();
+
+    /** A constant for the SPARQL Query Results XML Format namespace */
+    const SPARQL_XML_RESULTS_NS = 'http://www.w3.org/2005/sparql-results#';
+
+    /** Create a new SPARQL Result object
+     *
+     * You should not normally need to create a SPARQL result
+     * object directly - it will be constructed automatically
+     * for you by EasyRdf_Sparql_Client.
+     *
+     * @param string $data      The SPARQL result body
+     * @param string $mimeType  The MIME type of the result
+     */
+    public function __construct($data, $mimeType)
+    {
+        if ($mimeType == 'application/sparql-results+xml') {
+            return $this->parseXml($data);
+        } elseif ($mimeType == 'application/sparql-results+json') {
+            return $this->parseJson($data);
+        } else {
+            throw new EasyRdf_Exception(
+                "Unsupported SPARQL Query Results format: $mimeType"
+            );
+        }
+    }
+
+    /** Get the query result type (boolean/bindings)
+     *
+     * ASK queries return a result of type 'boolean'.
+     * SELECT query return a result of type 'bindings'.
+     *
+     * @return string The query result type.
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /** Return the boolean value of the query result
+     *
+     * If the query was of type boolean then this method will
+     * return either true or false. If the query was of some other
+     * type then this method will return null.
+     *
+     * @return boolean The result of the query.
+     */
+    public function getBoolean()
+    {
+        return $this->boolean;
+    }
+
+    /** Return true if the result of the query was true.
+     *
+     * @return boolean True if the query result was true.
+     */
+    public function isTrue()
+    {
+        return $this->boolean == true;
+    }
+
+    /** Return false if the result of the query was false.
+     *
+     * @return boolean True if the query result was false.
+     */
+    public function isFalse()
+    {
+        return $this->boolean == false;
+    }
+
+    /** Return the number of fields in a query result of type bindings.
+     *
+     * @return integer The number of fields.
+     */
+    public function numFields()
+    {
+        return count($this->fields);
+    }
+
+    /** Return the number of rows in a query result of type bindings.
+     *
+     * @return integer The number of rows.
+     */
+    public function numRows()
+    {
+        return count($this);
+    }
+
+    /** Get the field names in a query result of type bindings.
+     *
+     * @return array The names of the fields in the result.
+     */
+    public function getFields()
+    {
+        return $this->fields;
+    }
+
+    /** Return a human readable view of the query result.
+     *
+     * This method is intended to be a debugging aid and will
+     * return a pretty-print view of the query result.
+     *
+     * @param  bool  $html  Set to true to format the dump using HTML
+     */
+    public function dump($html = true)
+    {
+        if ($this->type == 'bindings') {
+            $result = '';
+            if ($html) {
+                $result .= "<table class='sparql-results' style='border-collapse:collapse'>";
+                $result .= "<tr>";
+                foreach ($this->fields as $field) {
+                    $result .= "<th style='border:solid 1px #000;padding:4px;".
+                               "vertical-align:top;background-color:#eee;'>".
+                               "?$field</th>";
+                }
+                $result .= "</tr>";
+                foreach ($this as $row) {
+                    $result .= "<tr>";
+                    foreach ($this->fields as $field) {
+                        $result .= "<td style='border:solid 1px #000;padding:4px;".
+                                   "vertical-align:top'>".
+                                   $row->$field->dumpValue($html)."</td>";
+                    }
+                    $result .= "</tr>";
+                }
+                $result .= "</table>";
+            } else {
+                // First calculate the width of each comment
+                $colWidths = array();
+                foreach ($this->fields as $field) {
+                    $colWidths[$field] = strlen($field);
+                }
+
+                $textData = array();
+                foreach ($this as $row) {
+                    $textRow = array();
+                    foreach ($row as $k => $v) {
+                        $textRow[$k] = $v->dumpValue(false);
+                        $width = strlen($textRow[$k]);
+                        if ($colWidths[$k] < $width) {
+                            $colWidths[$k] = $width;
+                        }
+                    }
+                    $textData[] = $textRow;
+                }
+
+                // Create a horizontal rule
+                $hr = "+";
+                foreach ($colWidths as $k => $v) {
+                    $hr .= "-".str_repeat('-', $v).'-+';
+                }
+
+                // Output the field names
+                $result .= "$hr\n|";
+                foreach ($this->fields as $field) {
+                    $result .= ' '.str_pad("?$field", $colWidths[$field]).' |';
+                }
+
+                // Output each of the rows
+                $result .= "\n$hr\n";
+                foreach ($textData as $textRow) {
+                    $result .= '|';
+                    foreach ($textRow as $k => $v) {
+                        $result .= ' '.str_pad($v, $colWidths[$k]).' |';
+                    }
+                    $result .= "\n";
+                }
+                $result .= "$hr\n";
+
+            }
+            return $result;
+        } elseif ($this->type == 'boolean') {
+            $str = ($this->boolean ? 'true' : 'false');
+            if ($html) {
+                return "<p>Result: <span style='font-weight:bold'>$str</span></p>";
+            } else {
+                return "Result: $str";
+            }
+        } else {
+            throw new EasyRdf_Exception(
+                "Failed to dump SPARQL Query Results format, unknown type: ". $this->type
+            );
+        }
+    }
+
+    /** Create a new EasyRdf_Resource or EasyRdf_Literal depending
+     *  on the type of data passed in.
+     *
+     * @ignore
+     */
+    protected function newTerm($data)
+    {
+        switch($data['type']) {
+            case 'bnode':
+                return new EasyRdf_Resource('_:'.$data['value']);
+            case 'uri':
+                return new EasyRdf_Resource($data['value']);
+            case 'literal':
+            case 'typed-literal':
+                return EasyRdf_Literal::create($data);
+            default:
+                throw new EasyRdf_Exception(
+                    "Failed to parse SPARQL Query Results format, unknown term type: ".
+                    $data['type']
+                );
+        }
+    }
+
+    /** Parse a SPARQL result in the XML format into the object.
+     *
+     * @ignore
+     */
+    protected function parseXml($data)
+    {
+        $doc = new DOMDocument();
+        $doc->loadXML($data);
+
+        # Check for valid root node.
+        if ($doc->hasChildNodes() == false or
+            $doc->childNodes->length != 1 or
+            $doc->firstChild->nodeName != 'sparql' or
+            $doc->firstChild->namespaceURI != self::SPARQL_XML_RESULTS_NS) {
+            throw new EasyRdf_Exception(
+                "Incorrect root node in SPARQL XML Query Results format"
+            );
+        }
+
+        # Is it the result of an ASK query?
+        $boolean = $doc->getElementsByTagName('boolean');
+        if ($boolean->length) {
+            $this->type = 'boolean';
+            $value = $boolean->item(0)->nodeValue;
+            $this->boolean = $value == 'true' ? true : false;
+            return;
+        }
+
+        # Get a list of variables from the header
+        $head = $doc->getElementsByTagName('head');
+        if ($head->length) {
+            $variables = $head->item(0)->getElementsByTagName('variable');
+            foreach ($variables as $variable) {
+                $this->fields[] = $variable->getAttribute('name');
+            }
+        }
+
+        # Is it the result of a SELECT query?
+        $resultstag = $doc->getElementsByTagName('results');
+        if ($resultstag->length) {
+            $this->type = 'bindings';
+            $results = $resultstag->item(0)->getElementsByTagName('result');
+            foreach ($results as $result) {
+                $bindings = $result->getElementsByTagName('binding');
+                $t = new stdClass();
+                foreach ($bindings as $binding) {
+                    $key = $binding->getAttribute('name');
+                    foreach ($binding->childNodes as $node) {
+                        if ($node->nodeType != XML_ELEMENT_NODE) {
+                            continue;
+                        }
+                        $t->$key = $this->newTerm(
+                            array(
+                                'type' => $node->nodeName,
+                                'value' => $node->nodeValue,
+                                'lang' => $node->getAttribute('xml:lang'),
+                                'datatype' => $node->getAttribute('datatype')
+                            )
+                        );
+                        break;
+                    }
+                }
+                $this[] = $t;
+            }
+            return $this;
+        }
+
+        throw new EasyRdf_Exception(
+            "Failed to parse SPARQL XML Query Results format"
+        );
+    }
+
+    /** Parse a SPARQL result in the JSON format into the object.
+     *
+     * @ignore
+     */
+    protected function parseJson($data)
+    {
+        // Decode JSON to an array
+        $data = json_decode($data, true);
+
+        if (isset($data['boolean'])) {
+            $this->type = 'boolean';
+            $this->boolean = $data['boolean'];
+        } elseif (isset($data['results'])) {
+            $this->type = 'bindings';
+            if (isset($data['head']['vars'])) {
+                $this->fields = $data['head']['vars'];
+            }
+
+            foreach ($data['results']['bindings'] as $row) {
+                $t = new stdClass();
+                foreach ($row as $key => $value) {
+                    $t->$key = $this->newTerm($value);
+                }
+                $this[] = $t;
+            }
+        } else {
+            throw new EasyRdf_Exception(
+                "Failed to parse SPARQL JSON Query Results format"
+            );
+        }
+    }
+
+    /** Magic method to return value of the result to string
+     *
+     * If this is a boolean result then it will return 'true' or 'false'.
+     * If it is a bindings type, then it will dump as a text based table.
+     *
+     * @return string A string representation of the result.
+     */
+    public function __toString()
+    {
+        if ($this->type == 'boolean') {
+            return $this->boolean ? 'true' : 'false';
+        } else {
+            return $this->dump(false);
+        }
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/TypeMapper.php b/core/vendor/njh/easyrdf/lib/EasyRdf/TypeMapper.php
new file mode 100644
index 000000000000..b2deaf074993
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/TypeMapper.php
@@ -0,0 +1,116 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2010 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+/**
+ * Class to map between RDF Types and PHP Classes
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_TypeMapper
+{
+    /** The type map registry */
+    private static $map = array();
+
+    /** Get the registered class for an RDF type
+     *
+     * If a type is not registered, then this method will return null.
+     *
+     * @param  string  $type   The RDF type (e.g. foaf:Person)
+     * @return string          The class name (e.g. Model_Foaf_Name)
+     */
+    public static function get($type)
+    {
+        if (!is_string($type) or $type == null or $type == '') {
+            throw new InvalidArgumentException(
+                "\$type should be a string and cannot be null or empty"
+            );
+        }
+
+        $type = EasyRdf_Namespace::expand($type);
+        if (array_key_exists($type, self::$map)) {
+            return self::$map[$type];
+        } else {
+            return null;
+        }
+    }
+
+    /** Register an RDF type with a PHP Class name
+     *
+     * @param  string  $type   The RDF type (e.g. foaf:Person)
+     * @param  string  $class  The PHP class name (e.g. Model_Foaf_Name)
+     * @return string          The PHP class name
+     */
+    public static function set($type, $class)
+    {
+        if (!is_string($type) or $type == null or $type == '') {
+            throw new InvalidArgumentException(
+                "\$type should be a string and cannot be null or empty"
+            );
+        }
+
+        if (!is_string($class) or $class == null or $class == '') {
+            throw new InvalidArgumentException(
+                "\$class should be a string and cannot be null or empty"
+            );
+        }
+
+        $type = EasyRdf_Namespace::expand($type);
+        return self::$map[$type] = $class;
+    }
+
+    /**
+      * Delete an existing RDF type mapping.
+      *
+      * @param  string  $type   The RDF type (e.g. foaf:Person)
+      */
+    public static function delete($type)
+    {
+        if (!is_string($type) or $type == null or $type == '') {
+            throw new InvalidArgumentException(
+                "\$type should be a string and cannot be null or empty"
+            );
+        }
+
+        $type = EasyRdf_Namespace::expand($type);
+        if (isset(self::$map[$type])) {
+            unset(self::$map[$type]);
+        }
+    }
+}
diff --git a/core/vendor/njh/easyrdf/lib/EasyRdf/Utils.php b/core/vendor/njh/easyrdf/lib/EasyRdf/Utils.php
new file mode 100644
index 000000000000..a48686b7cf58
--- /dev/null
+++ b/core/vendor/njh/easyrdf/lib/EasyRdf/Utils.php
@@ -0,0 +1,276 @@
+<?php
+
+/**
+ * EasyRdf
+ *
+ * LICENSE
+ *
+ * Copyright (c) 2009-2012 Nicholas J Humfrey.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author 'Nicholas J Humfrey" may be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2012 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ * @version    $Id$
+ */
+
+
+/**
+ * Class containing static utility functions
+ *
+ * @package    EasyRdf
+ * @copyright  Copyright (c) 2009-2010 Nicholas J Humfrey
+ * @license    http://www.opensource.org/licenses/bsd-license.php
+ */
+class EasyRdf_Utils
+{
+
+    /**
+     * Convert a string into CamelCase
+     *
+     * A capital letter is inserted for any non-letter (including userscore).
+     * For example:
+     * 'hello world' becomes HelloWorld
+     * 'rss-tag-soup' becomes RssTagSoup
+     * 'FOO//BAR' becomes FooBar
+     *
+     * @param string The input string
+     * @return string The input string converted to CamelCase
+     */
+    public static function camelise($str)
+    {
+        $cc = '';
+        foreach (preg_split("/[\W_]+/", $str) as $part) {
+            $cc .= ucfirst(strtolower($part));
+        }
+        return $cc;
+    }
+
+    /**
+     * Check if something is an associative array
+     *
+     * Note: this method only checks the key of the first value in the array.
+     *
+     * @param mixed $param The variable to check
+     * @return bool true if the variable is an associative array
+     */
+    public static function isAssociativeArray($param)
+    {
+        if (is_array($param)) {
+            $keys = array_keys($param);
+            if ($keys[0] === 0) {
+                return false;
+            } else {
+                return true;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Remove the fragment from a URI (if it has one)
+     *
+     * @param mixed $uri A URI
+     * @return string The same URI with the fragment removed
+     */
+    public static function removeFragmentFromUri($uri)
+    {
+        $pos = strpos($uri, '#');
+        if ($pos === false) {
+            return $uri;
+        } else {
+            return substr($uri, 0, $pos);
+        }
+    }
+
+    /** Return pretty-print view of a resource URI
+     *
+     * This method is mainly intended for internal use and is used by
+     * EasyRdf_Graph and EasyRdf_Sparql_Result to format a resource
+     * for display.
+     *
+     * @param  mixed $resource An EasyRdf_Resource object or an associative array
+     * @param  bool  $html     Set to true to format the dump using HTML
+     * @param  string $color   The colour of the text
+     * @return string
+     */
+    public static function dumpResourceValue($resource, $html = true, $color = 'blue')
+    {
+        if (is_object($resource)) {
+            $resource = strval($resource);
+        } elseif (is_array($resource)) {
+            $resource = $resource['value'];
+        }
+
+        $short = EasyRdf_Namespace::shorten($resource);
+        if ($html) {
+            $escaped = htmlentities($resource);
+            if (substr($resource, 0, 2) == '_:') {
+                $href = '#' . $escaped;
+            } else {
+                $href = $escaped;
+            }
+            if ($short) {
+                return "<a href='$href' style='text-decoration:none;color:$color'>$short</a>";
+            } else {
+                return "<a href='$href' style='text-decoration:none;color:$color'>$escaped</a>";
+            }
+        } else {
+            if ($short) {
+                return $short;
+            } else {
+                return $resource;
+            }
+        }
+    }
+
+    /** Return pretty-print view of a literal
+     *
+     * This method is mainly intended for internal use and is used by
+     * EasyRdf_Graph and EasyRdf_Sparql_Result to format a literal
+     * for display.
+     *
+     * @param  mixed $literal  An EasyRdf_Literal object or an associative array
+     * @param  bool  $html     Set to true to format the dump using HTML
+     * @param  string $color   The colour of the text
+     * @return string
+     */
+    public static function dumpLiteralValue($literal, $html = true, $color = 'black')
+    {
+        if (is_object($literal)) {
+            $literal = $literal->toArray();
+        } elseif (!is_array($literal)) {
+            $literal = array('value' => $literal);
+        }
+
+        $text = '"'.$literal['value'].'"';
+        if (isset($literal['lang'])) {
+            $text .= '@' . $literal['lang'];
+        }
+        if (isset($literal['datatype'])) {
+            $datatype = EasyRdf_Namespace::shorten($literal['datatype']);
+            $text .= "^^$datatype";
+        }
+
+        if ($html) {
+            return "<span style='color:$color'>".
+                   htmlentities($text, ENT_COMPAT, "UTF-8").
+                   "</span>";
+        } else {
+            return $text;
+        }
+    }
+
+    /** Clean up and split a mime-type up into its parts
+     *
+     * @param  string $mimeType   A MIME Type, optionally with parameters
+     * @return array  $type, $parameters
+     */
+    public static function parseMimeType($mimeType)
+    {
+        $parts = explode(';', strtolower($mimeType));
+        $type = trim(array_shift($parts));
+        $params = array();
+        foreach ($parts as $part) {
+            if (preg_match("/^\s*(\w+)\s*=\s*(.+?)\s*$/", $part, $matches)) {
+                $params[$matches[1]] = $matches[2];
+            }
+        }
+        return array($type, $params);
+    }
+
+    /** Execute a command as a pipe
+     *
+     * The proc_open() function is used to open a pipe to a
+     * a command line process, writing $input to STDIN, returning STDOUT
+     * and throwing an exception if anything is written to STDERR or the
+     * process returns non-zero.
+     *
+     * @param  string $command   The command to execute
+     * @param  array  $args      Optional list of arguments to pass to the command
+     * @param  string $input     Optional buffer to send to the command
+     * @param  string $dir       Path to directory to run command in (defaults to /tmp)
+     * @return string The result of the command, printed to STDOUT
+     */
+    public static function execCommandPipe($command, $args = null, $input = null, $dir = null)
+    {
+        $descriptorspec = array(
+            0 => array('pipe', 'r'),
+            1 => array('pipe', 'w'),
+            2 => array('pipe', 'w')
+        );
+
+        // Use the system tmp directory by default
+        if (!$dir) {
+            $dir = sys_get_temp_dir();
+        }
+
+        if (is_array($args)) {
+            $fullCommand = implode(
+                ' ',
+                array_map('escapeshellcmd', array_merge(array($command), $args))
+            );
+        } else {
+            $fullCommand = escapeshellcmd($command);
+            if ($args) {
+                $fullCommand .= ' '.escapeshellcmd($args);
+            }
+        }
+
+        $process = proc_open($fullCommand, $descriptorspec, $pipes, $dir);
+        if (is_resource($process)) {
+            // $pipes now looks like this:
+            // 0 => writeable handle connected to child stdin
+            // 1 => readable handle connected to child stdout
+            // 2 => readable handle connected to child stderr
+
+            if ($input) {
+                fwrite($pipes[0], $input);
+            }
+            fclose($pipes[0]);
+
+            $output = stream_get_contents($pipes[1]);
+            fclose($pipes[1]);
+            $error = stream_get_contents($pipes[2]);
+            fclose($pipes[2]);
+
+            // It is important that you close any pipes before calling
+            // proc_close in order to avoid a deadlock
+            $returnValue = proc_close($process);
+            if ($returnValue) {
+                throw new EasyRdf_Exception(
+                    "Error while executing command $command: ".$error
+                );
+            }
+        } else {
+            throw new EasyRdf_Exception(
+                "Failed to execute command $command"
+            );
+        }
+
+        return $output;
+    }
+}
-- 
GitLab