--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/spec/latest/json-ld-api/alternate2.html Mon Feb 04 12:32:02 2013 -0500
@@ -0,0 +1,4904 @@
+<html>
+<head>
+<title>JSON-LD 1.0 Processing Algorithms and API</title>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+<!--
+ === NOTA BENE ===
+ For the three scripts below, if your spec resides on dev.w3 you can check them
+ out in the same tree and use relative links so that they'll work offline,
+ -->
+<script type="text/javascript" src="../respec-w3c-common.js" class="remove"></script>
+<script type="text/javascript" src="../respec-w3c-extensions.js" class="remove"></script>
+<script type="text/javascript" class="remove">
+//<![CDATA[
+ var respecConfig = {
+ // extend the bibliography entries
+ "localBiblio": localBibliography,
+
+ doRDFa: "1.1",
+ // specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
+ specStatus: "ED",
+ // if you wish the publication date to be other than today, set this
+ //publishDate: "2012-12-25",
+ copyrightStart: "2010",
+
+ // the specification's short name, as in http://www.w3.org/TR/short-name/
+ shortName: "json-ld-api",
+
+ // if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
+ // and its maturity status
+ previousPublishDate: "2012-09-30",
+ previousMaturity: "ED",
+ previousURI: "http://dvcs.w3.org/hg/json-ld/raw-file/66d980964784/spec/ED/json-ld-api/20120930/index.html",
+
+ // if there a publicly available Editor's Draft, this is the link
+ edDraftURI: "http://json-ld.org/spec/latest/json-ld-api/index.html",
+
+ testSuiteURI: "http://json-ld.org/test-suite/",
+
+ // if this is a LCWD, uncomment and set the end of its review period
+ // lcEnd: "2009-08-05",
+
+ // if you want to have extra CSS, append them to this list
+ // it is recommended that the respec.css stylesheet be kept
+ // extraCSS: [],
+
+ issueBase: "https://github.com/json-ld/json-ld.org/issues/",
+
+ // editors, add as many as you like
+ // only "name" is required
+ editors: [
+ { name: "Markus Lanthaler", url: "http://www.markus-lanthaler.com/",
+ company: "Graz University of Technology", companyURL: "http://www.tugraz.at/" },
+ { name: "Gregg Kellogg", url: "http://greggkellogg.net/",
+ company: "Kellogg Associates", companyURL: "http://kellogg-assoc.com/" },
+ { name: "Manu Sporny", url: "http://manu.sporny.org/",
+ company: "Digital Bazaar", companyURL: "http://digitalbazaar.com/" },
+ { name: "Dave Longley", url: "http://digitalbazaar.com/",
+ company: "Digital Bazaar", companyURL: "http://digitalbazaar.com/"}
+ ],
+
+ // authors, add as many as you like.
+ // This is optional, uncomment if you have authors as well as editors.
+ // only "name" is required. Same format as editors.
+
+ authors: [
+ { name: "Dave Longley", url: "http://digitalbazaar.com/",
+ company: "Digital Bazaar", companyURL: "http://digitalbazaar.com/"},
+ { name: "Gregg Kellogg", url: "http://greggkellogg.net/",
+ company: "Kellogg Associates", companyURL: "http://kellogg-assoc.com/" },
+ { name: "Markus Lanthaler", url: "http://www.markus-lanthaler.com/",
+ company: "Graz University of Technology", companyURL: "http://www.tugraz.at/" },
+ { name: "Manu Sporny", url: "http://manu.sporny.org/",
+ company: "Digital Bazaar", companyURL: "http://digitalbazaar.com/" }
+ ],
+
+ // name of the WG
+ wg: "RDF Working Group",
+
+ // URI of the public WG page
+ wgURI: "http://www.w3.org/2011/rdf-wg/",
+
+ // name (with the @w3c.org) of the public mailing to which comments are due
+ wgPublicList: "public-rdf-comments",
+
+ // URI of the patent status for this WG, for Rec-track documents
+ // !!!! IMPORTANT !!!!
+ // This is important for Rec-track documents, do not copy a patent URI from a random
+ // document unless you know what you're doing. If in doubt ask your friendly neighbourhood
+ // Team Contact.
+ wgPatentURI: "http://www.w3.org/2004/01/pp-impl/46168/status",
+ maxTocLevel: 3,
+ preProcess: [ preProc ],
+ alternateFormats: [ {uri: "diff-20120930.html", label: "diff to previous version"} ],
+ };
+//]]>
+</script>
+<style type="text/css">
+ .diff { font-weight:bold; color:#0a3; }
+</style>
+</head>
+
+<body>
+<section id="abstract">
+
+<p>
+JSON [[!RFC4627]] has proven to be a highly useful object serialization and
+messaging format. JSON-LD [[!JSON-LD]] harmonizes the representation of
+Linked Data in JSON by outlining a common JSON representation format for
+expressing directed graphs, mixing both Linked Data and non-Linked Data in
+a single document. This document outlines an Application Programming
+Interface and a set of algorithms for programmatically transforming
+JSON-LD documents to make them easier to work with in programming
+environments like those that use JavaScript, Python, and Ruby.
+</p>
+
+</section>
+
+<section id="sotd">
+
+<p>
+This document has been under development for over 18 months in the
+JSON for Linking Data Community Group. The document has recently been
+transferred to the RDF Working Group for review, improvement, and publication
+along the Recommendation track. The specification has undergone significant
+development, review, and changes during the course of the last 18 months.
+</p>
+<p>
+There are several independent
+<a href="http://json-ld.org/#impl">interoperable implementations</a> of
+this specification. There is
+a <a href="https://github.com/json-ld/json-ld.org/tree/master/test-suite">fairly complete test suite</a>
+and a <a href="http://json-ld.org/playground/">live JSON-LD editor</a>
+that is capable of demonstrating the features described in
+this document. While there will be continuous development on implementations,
+the test suite, and the live editor, they are believed to be mature enough
+to be integrated into a non-production system at this point in time. There
+is an expectation that they could be used in a production system within the
+year.
+</p>
+<p class="issue">
+It is important for readers to understand that the scope of this document is
+currently under debate and new features may be added to the specification.
+Existing features may be modified heavily or removed entirely from the
+specification upon further review and feedback from the broader community.
+This is a work in progress and publication as a Working Draft
+does not require that all Working Group members agree on the content of the
+document.
+</p>
+
+<p>
+There are a number of ways that you may participate in the development of
+this specification:
+</p>
+
+<ul>
+ <li>If you want to make sure that your feedback is formally addressed by
+ the RDF Working Group, you should send it to public-rdf-comments:
+ <a href="http://lists.w3.org/Archives/Public/public-rdf-comments/">public-rdf-comments@w3.org</a></li>
+
+ <li>Ad-hoc technical discussion primarily occurs on the public community mailing list:
+ <a href="http://lists.w3.org/Archives/Public/public-linked-json/">public-linked-json@w3.org</a></li>
+
+ <li><a href="http://json-ld.org/minutes/">Public JSON-LD Community Group teleconferences</a>
+ are held on Tuesdays at 1500UTC every week. Participation is open to the
+ public.</li>
+
+ <li>RDF Working Group teleconferences are held on Wednesdays at 1500UTC
+ every week. Participation is limited to RDF Working Group members.</li>
+
+ <li>Specification bugs and issues should be reported in the
+ <a href="https://github.com/json-ld/json-ld.org/issues">issue tracker</a>
+ if you do not want to send an email to the public-rdf-comments mailing
+ list.</li>
+
+ <li><a href="https://github.com/json-ld/json-ld.org/tree/master/spec">Source code</a>
+ for the specification can be found on Github.</li>
+
+ <li>The <a href="http://webchat.freenode.net/?channels=json-ld">#json-ld</a>
+ IRC channel is available for real-time discussion on irc.freenode.net.</li>
+</ul>
+
+</section>
+
+<section class="informative">
+<h2>Introduction</h2>
+
+<p>
+This document is a detailed specification for an Application Programming
+Interface for the JSON-LD Syntax. The document is primarily intended for
+the following audiences:
+</p>
+
+<ul>
+ <li>Web authors and developers that want a very detailed view of how
+ a JSON-LD processor and the API operates.</li>
+ <li>Software developers that want to implement processors and APIs for
+ JSON-LD documents.</li>
+</ul>
+
+<p>
+To understand the basics in this specification you must first be familiar with
+JSON, which is detailed in [[!RFC4627]]. You must also understand the
+JSON-LD Syntax [[!JSON-LD]], which is the base syntax used by all of the
+algorithms in this document. To understand the API and how it is
+intended to operate in a programming environment, it is useful to have working
+knowledge of the JavaScript programming language [[ECMA-262]] and
+WebIDL [[!WEBIDL]]. To understand how JSON-LD maps to RDF, it is helpful to be
+familiar with the basic RDF concepts [[!RDF-CONCEPTS]].
+</p>
+
+</section>
+
+<section class="informative">
+<h1>Features</h1>
+
+<p>
+The JSON-LD Syntax specification [[!JSON-LD]] outlines a syntax that may be
+used to express Linked Data in JSON. Because there is more than one way to
+express Linked Data using this syntax, it is often useful to be able to
+transform JSON-LD documents so that they may be more easily consumed by
+specific applications.
+</p>
+
+<p>
+There are four major types of transformation that are discussed in this
+document: expansion, compaction, flattening, and RDF conversion.
+</p>
+
+<section class="informative">
+<h2>Expansion</h2>
+
+<p>
+JSON-LD allows <tref>context</tref> to be applied to JSON data. Applying
+<tref>context</tref> to JSON data allows it to be expressed in a way that
+is specifically tailored to a particular person or application. If an
+application or person wants to use data that was created using a different
+<tref>context</tref> than they are programmed against or used to, it
+would be very convenient if it were possible to transform the data to
+their own <tref>context</tref>. Instead of requiring JSON-LD
+processors to write specific code for every imaginable <tref>context</tref>
+switching scenario, it is much easier to write a single
+algorithm that can remove any <tref>context</tref> (and another that
+can subsequently apply any <tref>context</tref>). The algorithm that
+removes <tref>context</tref> is called <tdef>expansion</tref>.
+</p>
+
+<p>
+To get an idea of how context and data structuring affects the same data,
+here is an example of JSON-LD that uses only <tref title="term">terms</tref>
+and is fairly compact:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Sample JSON-LD document">
+<!--
+{
+ "@context": {
+ "name": "http://schema.org/name",
+ "homepage": {
+ "@id": "http://schema.org/url",
+ "@type": "@id"
+ }
+ },
+ "@id": "http://me.markus-lanthaler.com/",
+ "name": "Markus Lanthaler",
+ "homepage": "http://www.markus-lanthaler.com/"
+}
+-->
+</pre>
+
+<p>
+The next input example uses one <tref>IRI</tref> to express a property
+and <tref title="array">array</tref> to encapsulate another, but
+leaves the rest of the information untouched.
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Sample JSON-LD document using a IRI instead of a term to express a property">
+<!--
+{
+ "@context": {
+ "homepage": {
+ "@id": "http://schema.org/url",
+ "@type": "@id"
+ }
+ },
+ "@id": "http://me.markus-lanthaler.com/",
+ "****http://schema.org/name****": "Markus Lanthaler",
+ "homepage": ****[****"http://www.markus-lanthaler.com/"****]****
+}
+-->
+</pre>
+
+<p>
+Note that both inputs are valid JSON-LD and both represent the same
+information. The difference is in their <tref>context</tref> information
+and in the data structures used. A JSON-LD processor can remove
+<tref>context</tref> and ensure that the data is more regular by employing
+<tref>expansion</tref>.
+</p>
+
+<p>
+<tdef>Expansion</tdef> has two important goals: ensuring all values
+are represented in a regular form, and removing any contextual information
+from the document. These goals are accomplished by expanding all properties
+to <tref title="absolute IRI">absolute IRIs</tref> and by expressing all
+values in <tref title="array">arrays</tref> in
+<tref>expanded form</tref>. <tref>Expanded form</tref> is the most verbose
+and regular way of expressing of values in JSON-LD; all contextual
+information from the document is instead stored locally with each value.
+Running the <a href="#expansion-algorithm">Expansion algorithm</a> against
+the examples provided above results in the following output:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Expanded sample document">
+<!--
+[
+ {
+ "@id": "http://me.markus-lanthaler.com/",
+ "http://schema.org/name": [
+ { "@value": "Markus Lanthaler" }
+ ],
+ "http://schema.org/url": [
+ { "@id": "http://www.markus-lanthaler.com/" }
+ ]
+ }
+]
+-->
+</pre>
+
+<p>
+Note that in the output above all <tref>context</tref> definitions have
+been removed, all <tref title="term">terms</tref> and
+<tref title="compact IRI">compact IRIs</tref> have been expanded to absolute
+<tref title="IRI">IRIs</tref>, and all
+<tref title="JSON-LD value">JSON-LD values</tref> are expressed in
+<tref title="array">arrays</tref> in <tref>expanded form</tref>. While the
+output is more verbose and difficult for a human to read, it establishes a
+baseline that makes JSON-LD processing easier because of its very regular
+structure.
+</p>
+
+</section>
+
+<section class="informative">
+<h2>Compaction</h2>
+
+<p>
+While <tref>expansion</tref> removes <tref>context</tref> from a given
+input, <tref title="compaction">compaction's</tref> primary function is to
+perform the opposite operation: to express a given input according to
+a particular <tref>context</tref>. <tdef>Compaction</tdef> applies a
+<tref>context</tref> that specifically tailors the way information is
+expressed for a particular person or application. This simplifies applications
+that consume JSON or JSON-LD by expressing the data in application-specific
+terms, and it makes the data easier to read by humans.
+
+<tref>Compaction</tref> uses a developer-supplied <tref>context</tref> to
+shorten <tref title="IRI">IRIs</tref> to <tref title="term">terms</tref> or
+<tref title="compact IRI">compact IRIs</tref> and
+<tref title="JSON-LD value">JSON-LD values</tref>
+expressed in <tref>expanded form</tref> to simple values such as
+<tref title="string">strings</tref> or
+<tref title="number">numbers</tref>.
+</p>
+
+<p>
+For example, assume the following expanded JSON-LD input document:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Expanded sample document">
+<!--
+[
+ {
+ "@id": "http://me.markus-lanthaler.com/",
+ "http://schema.org/name": [
+ { "@value": "Markus Lanthaler" }
+ ],
+ "http://schema.org/url": [
+ { "@id": "http://www.markus-lanthaler.com/" }
+ ]
+ }
+]
+-->
+</pre>
+
+<p>
+Additionally, assume the following developer-supplied JSON-LD <tref>context</tref>:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="JSON-LD context">
+<!--
+{
+ "@context": {
+ "name": "http://schema.org/name",
+ "homepage": {
+ "@id": "http://schema.org/url",
+ "@type": "@id"
+ }
+ }
+}
+-->
+</pre>
+
+<p>
+Running the <a href="#compaction-algorithm">Compaction Algorithm</a> given
+the context supplied above against the JSON-LD input document provided above
+would result in the following output:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Compacted sample document">
+<!--
+{
+ "@context": {
+ "name": "http://schema.org/name",
+ "homepage": {
+ "@id": "http://schema.org/url",
+ "@type": "@id"
+ }
+ },
+ "@id": "http://me.markus-lanthaler.com/",
+ "name": "Markus Lanthaler",
+ "homepage": "http://www.markus-lanthaler.com/"
+}
+-->
+</pre>
+
+<p>
+Note that all <tref title="IRI">IRIs</tref> have been compacted to
+<tref title="term">terms</tref> as specified in the <tref>context</tref>,
+which has been injected into the output. While compacted output is
+useful to humans, it is also used to generate structures that are easy to
+program against. Compaction enables developers to map any expanded document
+into an application-specific compacted document. While the context provided
+above mapped <code>http://schema.org/name</code> to <code>name</code>, it
+could also have been mapped to any other term provided by the developer.
+</p>
+
+</section>
+
+<section class="informative">
+<h2>Flattening</h2>
+
+<p>
+While expansion ensures that a document is in a uniform structure,
+flattening goes a step further to ensure that the shape of the data
+is deterministic. In expanded documents, the properties of a single
+properties of a single <tref>node</tref> may be spread across a number of
+different <tref title="JSON object">JSON objects</tref>. By flattening a
+document, all properties of a <tref>node</tref> are collected in a single
+<tref>JSON object</tref>. This may drastically simplify the code required
+to process JSON-LD data in certain applications.
+</p>
+
+<p>
+For example, assume the following JSON-LD input document:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Sample JSON-LD document">
+<!--
+{
+ "@context": {
+ "name": "http://schema.org/name",
+ "knows": "http://schema.org/knows"
+ },
+ "@id": "http://digitalbazaar.com/people/dlongley",
+ ****"knows"****: {
+ "@id": "http://digitalbazaar.com/people/msporny",
+ "name": "Manu Sporny",
+ "knows": {
+ "@id": "http://digitalbazaar.com/people/dlongley",
+ ****"name"****: "Dave Longley"
+ }
+ }
+}
+-->
+</pre>
+
+<p>
+Running the <a href="#flattening-algorithm">Flattening Algorithm</a>
+with a context set to <tref>null</tref> to prevent compaction returns
+the following document:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Flattened sample document in expanded form">
+<!--
+[
+ ****{****
+ "@id": "http://digitalbazaar.com/people/dlongley",
+ ****"http://schema.org/name"****: [
+ { "@value": "Dave Longley" }
+ ],
+ ****"http://schema.org/knows"****: [
+ { "@id": "http://digitalbazaar.com/people/msporny" }
+ ]
+ ****}****,
+ {
+ "@id": "http://digitalbazaar.com/people/msporny",
+ "http://schema.org/name": [
+ { "@value": "Manu Sporny" }
+ ],
+ "http://schema.org/knows": [
+ { "@id": "http://digitalbazaar.com/people/dlongley" }
+ ]
+ }
+]
+-->
+</pre>
+
+<p>
+Note how in the output above all properties of a <tref>node</tref> are
+collected in a single <tref>JSON object</tref>.
+</p>
+
+<p>
+To make it easier for humans to read or for certain applications to
+process it, a flattened document can be compacted by passing a context. Using
+the same context as the input document, the flattened and compacted document
+looks as follows:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Flattened and compacted sample document">
+<!--
+{
+ "@context": {
+ "name": "http://schema.org/name",
+ "knows": "http://schema.org/knows"
+ },
+ "@graph": [
+ ****{****
+ "@id": "http://digitalbazaar.com/people/dlongley",
+ ****"name"****: "Dave Longley",
+ ****"knows"****: [
+ { "@id": "http://digitalbazaar.com/people/msporny" }
+ ]
+ ****}****,
+ {
+ "@id": "http://digitalbazaar.com/people/msporny",
+ "name": "Manu Sporny",
+ "knows": {
+ "@id": "http://digitalbazaar.com/people/dlongley"
+ }
+ }
+ ]
+}
+-->
+</pre>
+
+<p>
+Please note that the flattened and compacted result will explicitly
+designate the default graph by the <code>@graph</code> member in the
+top-level <tref>JSON object</tref>, except if its value contains just
+one item.
+</p>
+
+</section>
+
+<section class="informative">
+<h2>RDF Conversion</h2>
+
+<p>
+JSON-LD can be used to serialize data expressed in RDF as described in
+[[RDF-CONCEPTS]]. This ensures that data can be round-tripped to and from
+any RDF syntax without any loss in fidelity.
+</p>
+
+<p>
+For example, assume the following RDF input serialized in Turtle [[TURTLE-TR]]:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Sample Turtle document">
+<!--
+<http://me.markus-lanthaler.com/> <http://schema.org/name> "Markus Lanthaler" .
+<http://me.markus-lanthaler.com/> <http://schema.org/url> <http://www.markus-lanthaler.com/> .
+-->
+</pre>
+
+<p>
+Using the <a href="#convert-from-rdf-algorithm">Convert from RDF Algorithm</a>
+a developer could transform this document into expanded JSON-LD:
+</p>
+
+<pre class="example" data-transform="updateExample"
+ title="Sample Turtle document converted to JSON-LD">
+<!--
+[
+ {
+ "@id": "http://me.markus-lanthaler.com/",
+ "http://schema.org/name": [
+ {
+ "@value": "Markus Lanthaler"
+ }
+ ],
+ "http://schema.org/url": [
+ {
+ "@id": "http://www.markus-lanthaler.com/"
+ }
+ ]
+ }
+]
+-->
+</pre>
+
+<p>
+Note that the output above could easily be compacted using the technique
+outlined in the previous section. It is also possible to transform the
+JSON-LD document back to RDF using the
+<a href="#convert-to-rdf-algorithm">Convert to RDF Algorithm</a>.
+</p>
+
+</section>
+
+<!-- end of Features -->
+</section>
+
+<section>
+<h1>Conformance</h1>
+
+<p>
+All examples and notes as well as sections marked as non-normative in this
+specification are non-normative. Everything else in this specification is
+normative.
+</p>
+
+<p>
+The keywords MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED,
+MAY, and OPTIONAL in this specification are to be interpreted as described
+in [[!RFC2119]].
+</p>
+
+<p>
+There are two classes of products that can claim conformance to this
+specification: <tref title="JSON-LD Implementation">JSON-LD Implementations</tref>
+and <tref title="JSON-LD Processor">JSON-LD Processors</tref>.
+</p>
+
+<p>
+A conforming <tdef>JSON-LD Implementation</tdef> is a system capable of
+transforming JSON-LD documents according the algorithms defined in this
+specification.
+</p>
+
+<p>
+A conforming <tdef>JSON-LD Processor</tdef> is a conforming
+<tref>JSON-LD Implementation</tref> that exposes the Application Programming
+Interface (API) defined in this specification.</p>
+
+<p>
+The algorithms in this specification are generally written with more concern
+for clarity than efficiency. Thus, JSON-LD Implementations and Processors
+may implement the algorithms given in this specification in any way desired,
+so long as the end result is indistinguishable from the result that would be
+obtained by the specification's algorithms.
+</p>
+
+<p>
+This specification does not define how JSON-LD Implementations or Processors
+handle non-conforming input documents. This implies that JSON-LD Implementations
+or Processors MUST NOT attempt to correct malformed <tref title="IRI">IRIs</tref>
+or language tags; however, they MAY issue validation warnings. IRIs are not
+modified other than converted between <tref title="relative IRI">relative</tref>
+and <tref title="absolute IRI">absolute IRIs</tref>.
+</p>
+
+<p class="note">
+Implementers can partially check their level of conformance to this
+specification by successfully passing the test cases of the JSON-LD test
+suite [[JSON-LD-TESTS]]. Note, however, that passing all the tests in the test
+suite does not imply complete conformance to this specification. It only
+implies that the implementation conforms to aspects tested by the test suite.
+</p>
+
+</section>
+
+<section>
+<h1>General Terminology</h1>
+
+<p>
+This document uses the following terms as defined in JSON [[!RFC4627]]. Refer
+to the <em>JSON Grammar</em> section in [[!RFC4627]] for formal definitions.</p>
+
+<dl>
+ <dt><tdef>JSON object</tdef></dt>
+ <dd>An object structure is represented as a pair of curly brackets
+ surrounding zero or more key-value pairs. A key is a
+ <tref>string</tref>. A single colon comes after each key, separating the
+ key from the value. A single comma separates a value from a following
+ key.</dd>
+ <dt><tdef>array</tdef></dt>
+ <dd>An array structure is represented as square brackets surrounding zero
+ or more values (or elements). Elements are separated by commas.
+ In JSON, an array is an <em>ordered</em> sequence of zero or more values.
+ While JSON-LD uses the same array representation as JSON,
+ the collection is <em>unordered</em> by default. While order is
+ preserved in regular JSON arrays, it is not in regular JSON-LD arrays
+ unless specific markup is provided (see <a href="#sets-and-lists"></a>).</dd>
+ <dt><tdef>string</tdef></dt>
+ <dd>A string is a sequence of zero or more Unicode characters,
+ wrapped in double quotes, using backslash escapes (if necessary). A
+ character is represented as a single character string.</dd>
+ <dt><tdef>number</tdef></dt>
+ <dd>A number is similar to that used in most programming languages, except
+ that the octal and hexadecimal formats are not used and that leading
+ zeros are not allowed.</dd>
+ <dt><tdef>true</tdef> and <tdef>false</tdef></dt>
+ <dd>Values that are used to express one of two possible boolean states.</dd>
+ <dt><tdef>null</tdef></dt>
+ <dd>The <tref>null</tref> value. A key-value pair in the
+ <code>@context</code> where the value, or the <code>@id</code> of the
+ value, is <tref>null</tref> explicitly decouples a term's association
+ with an IRI. A key-value pair in the body of a JSON-LD document whose
+ value is <tref>null</tref> has the same meaning as if the key-value pair
+ was not defined. If <code>@value</code>, <code>@list</code>, or
+ <code>@set</code> is set to <tref>null</tref> in expanded form, then
+ the entire <tref>JSON object</tref> is ignored.</dd>
+</dl>
+
+<p>Furthermore, the following terminology is used throughout this document:</p>
+
+<dl>
+ <dt><tdef>keyword</tdef></dt>
+ <dd>A JSON key that is specific to JSON-LD, specified in the JSON-LD Syntax specification [[!JSON-LD]]
+ in the section titled <cite><a href="../json-ld-syntax/#syntax-tokens-and-keywords">Syntax Tokens and Keywords</a></cite>.</dd>
+ <dt><tdef>context</tdef></dt>
+ <dd>A a set of rules for interpreting a JSON-LD document as specified in
+ <cite><a href="../json-ld-syntax/#the-context">The Context</a></cite> of the [[JSON-LD]] specification.</dd>
+ <dt><tdef>JSON-LD document</tdef></dt>
+ <dd>A <tref>JSON-LD document</tref> is a serialization of a collection of
+ <tref title="JSON-LD graph">JSON-LD graphs</tref> and comprises exactly one
+ <tref>default graph</tref> and zero or more <tref title="named graph">named graphs</tref>.</dd>
+ <dt><tdef>named graph</tdef></dt>
+ <dd>A named graph is a pair consisting of an <tref>IRI</tref> or <tref>blank node</tref>
+ (the <tdef>graph name</tdef>) and a <tref>JSON-LD graph</tref>.</dd>
+ <dt><tdef>default graph</tdef></dt>
+ <dd>The default graph is the only graph in a JSON-LD document which has no <tref>graph name</tref>.</dd>
+ <dt><tdef>JSON-LD graph</tdef></dt>
+ <dd>A labeled directed graph, i.e., a set of <tref title="node">nodes</tref> connected by <tref title="edge">edges</tref>,
+ as specified in the <cite><a href="../json-ld-syntax/#data-model">Data Model</a></cite> section of the JSON-LD syntax
+ specification [[!JSON-LD]].</dd>
+ <dt><tdef>edge</tdef></dt>
+ <dd>Every <tref>edge</tref> has a direction associated with it and is labeled with
+ an <tref>IRI</tref> or a <tref>blank node identifier</tref>. Within the JSON-LD syntax
+ these edge labels are called <tdef title="property">properties</tdef>. Whenever possible, an
+ <tref>edge</tref> SHOULD be labeled with an <tref>IRI</tref>.</dd>
+ <dt><tdef>node</tdef></dt>
+ <dd>Every <tref>node</tref> is an <tref>IRI</tref>, a <tref>blank node</tref>,
+ a <tref>JSON-LD value</tref>, or a <tref>list</tref>.</dd>
+ <dt><tdef><abbr title="Internationalized Resource Identifier">IRI</abbr></tdef></dt>
+ <dd>An <tref>IRI</tref> (Internationalized Resource Identifier) is a string that conforms to the syntax
+ defined in [[RFC3987]].</dd>
+ <dt><tdef>absolute IRI</tdef></dt>
+ <dd>An absolute IRI is defined in [[!RFC3987]] containing a <em>scheme</em> along with a <em>path</em> and
+ optional <em>query</em> and fragment segments.</dd>
+ <dt><tdef>relative IRI</tdef></dt>
+ <dd>A relative IRI is an IRI that is relative some other <tref>absolute IRI</tref>;
+ in the case of JSON-LD this is the base location of the document.</dd>
+ <dt><tdef>blank node</tdef></dt>
+ <dd>A <tref>node</tref> in a <tref>JSON-LD graph</tref> that does not contain a de-referenceable
+ identifier because it is either ephemeral in nature or does not contain information that needs to be
+ linked to from outside of the JSON-LD graph.</dd>
+ <dt><tdef>blank node identifier</tdef></dt>
+ <dd>A blank node identifier is a string that can be used as an identifier for a <tref>blank node</tref> within
+ the scope of a JSON-LD document. Blank node identifiers begin with <code>_:</code>.</dd>
+ <dt><tdef>JSON-LD value</tdef></dt>
+ <dd>A <tref>JSON-LD value</tref> is a <tref>string</tref>, a <tref>number</tref>,
+ <tref>true</tref> or <tref>false</tref>, a <tref>typed value</tref>, or a
+ <tref>language-tagged string</tref>.</dd>
+ <dt><tdef>typed value</tdef></dt>
+ <dd>A <tref>typed value</tref> consists of a value, which is a string, and a type, which is an <tref>IRI</tref>.</dd>
+ <dt><tdef>language-tagged string</tdef></dt>
+ <dd>A <tref>language-tagged string</tref> consists of a string and a non-empty language
+ tag as defined by [[BCP47]]. The language tag must be well-formed according to section
+ <a href="http://tools.ietf.org/html/bcp47#section-2.2.9">2.2.9</a> of [[BCP47]], and MUST
+ be normalized to lowercase.</dd>
+ <dt><tdef>list</tdef></dt>
+ <dd>A <tref>list</tref> is an ordered sequence of <tref title="IRI">IRIs</tref>,
+ <tref title="blank node">blank nodes</tref>, and
+ <tref title="JSON-LD value">JSON-LD values</tref>.</dd>
+</dl>
+
+</section>
+
+<section>
+<h1>Algorithms</h1>
+
+<p>
+All algorithms described in this section are intended to operate on
+language-native data structures. That is, the serialization to a text-based
+JSON document isn't required as input or output to any of these algorithms and
+language-native data structures MUST be used where applicable.
+</p>
+
+<section>
+<h2>Algorithm Terms</h2>
+
+<dl>
+ <dt><tdef>active graph</tdef></dt>
+ <dd>The name of the currently active graph that the processor should use when
+ processing.</dd>
+ <dt><tdef>active subject</tdef></dt>
+ <dd>The currently active subject that the processor should use when
+ processing.</dd>
+ <dt><tdef>active property</tdef></dt>
+ <dd>The currently active property that the processor should use when
+ processing. The active property is represented in the original lexical form, which
+ is used for finding type mappings in the <tref>active context</tref>.</dd>
+ <dt><tdef>active object</tdef></dt>
+ <dd>The currently active object that the processor should use when
+ processing.</dd>
+ <dt><tdef>active context</tdef></dt>
+ <dd>A context that is used to resolve <tref title="term">terms</tref> while
+ the processing algorithm is running.</dd>
+ <dt><tdef>local context</tdef></dt>
+ <dd>A context that is specified within a <tref>JSON object</tref>,
+ specified via the <code>@context</code> <tref>keyword</tref>.</dd>
+ <dt><tdef>JSON-LD input</tdef></dt>
+ <dd>The JSON-LD data structure that is provided as input to the algorithm.</dd>
+ <dt><tdef>JSON-LD output</tdef></dt>
+ <dd>The JSON-LD data structure that is produced as output by the algorithm.</dd>
+ <dt><tdef>term</tdef></dt>
+ <dd>A <tref>term</tref> is a short word defined in a context that MAY be expanded to an <tref>IRI</tref></dd>
+ <dt><tdef>compact IRI</tdef></dt>
+ <dd>A compact IRI is has the form of <tdef>prefix</tdef>:<em>suffix</em> and is used as a way
+ of expressing an IRI without needing to define separate <tref>term</tref> definitions for
+ each IRI contained within a common vocabulary identified by <tref>prefix</tref>.</dd>
+ <dt><tdef>node object</tdef></dt>
+ <dd>A <tref>node object</tref> represents zero or more properties of a
+ <tref>node</tref> in the <tref>JSON-LD graph</tref> serialized by the
+ JSON-LD document. A <tref>JSON object</tref> is a <tref>node object</tref>
+ if it exists outside of the JSON-LD <tref>context</tref> and:
+ <ul>
+ <li>it does not contain the <code>@value</code>, <code>@list</code>,
+ or <code>@set</code> keywords, or</li>
+ <li>it is not the top-level <tref>JSON object</tref> in the JSON-LD document containing
+ the <code>@graph</code> keyword.</li>
+ </ul>
+ </dd>
+ <dt><tdef>list object</tdef></dt>
+ <dd>A <tref>list object</tref> is a <tref>JSON object</tref> that has an <code>@list</code>
+ member.</dd>
+ <dt><tdef>scalar</tdef></dt>
+ <dd>A scalar is either a JSON <tref>string</tref>, <tref>number</tref>, <tref>true</tref>,
+ or <tref>false</tref>.</dd>
+ <dt><tdef>quad</tdef></dt>
+ <dd>An <em>RDF triple</em> as specified by [[RDF-CONCEPTS]] augmented with
+ a fourth component, a <tref>graph name</tref>.</dd>
+ <dt><tdef>RDF subject</tdef></dt>
+ <dd>A <em>subject</em> as specified by [[RDF-CONCEPTS]].</dd>
+ <dt><tdef>RDF predicate</tdef></dt>
+ <dd>A <em>predicate</em> as specified by [[RDF-CONCEPTS]].</dd>
+ <dt><tdef>RDF object</tdef></dt>
+ <dd>An <em>object</em> as specified by [[RDF-CONCEPTS]].</dd>
+</dl>
+
+</section>
+
+<section>
+<h2 id="remote-context">Remote Context Resolution</h2>
+
+<section>
+<h3>Problem</h3>
+
+<p>
+A JSON-LD document may contain remote <tref title="context">contexts</tref>.
+These <tref title="context">contexts</tref> must be dereferenced before they
+can be processed.
+</p>
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+Dereferencing remote <tref title="context">contexts</tref> can be performed
+either inline with the other JSON-LD algorithms or as a separate, prior step.
+This solution opts to dereference them first, in a prior step, to both
+separate concerns and to better enable <tref>active context</tref> caching.
+By separating concerns, the other JSON-LD algorithms can be described more
+simply. Implementations may also be either simplified or made more efficient
+because there is no need to block or respond to events when remote
+<tref title="context">contexts</tref> are dereferenced over the network. This
+is particularly important for simplifying implementations in asynchronous
+programming environments. Of course, choosing this approach is not a
+requirement.
+</p>
+
+<p>
+The JSON-LD document is searched for remote <tref title="context">contexts</tref>
+recursively, starting with its root <em>element</em>. If the <em>element</em>
+contains an <code>@context</code> key, its value is searched for
+<tref title="string">strings</tref>. The result represents a remote
+<tref>context</tref>, which we add to a map that will ensure we don't
+dereference an already dereferenced remote
+<tref>context</tref> for a given <tref>IRI</tref>.
+</p>
+
+<p>
+When we have finished searching, we dereference each remote
+<tref>context</tref> (or get its already-dereferenced value from our map).
+Each time we dereference a remote <tref>context</tref>, we store its result
+in our map and then recursively search it for more remote
+<tref title="IRI">contexts</tref> as above, checking to ensure there is no
+cyclical reference, which is an error.
+</p>
+
+<p>
+Once all of the remote <tref title="IRI">contexts</tref> have been
+dereferenced, we replace all of their associated <tref>context</tref>
+<tref title="IRI">IRIs</tref> in the JSON-LD document with the
+results from our map.
+</p>
+
+</section>
+
+<!-- end of Remote Context Resolution -->
+</section>
+
+<section>
+<h2 id="context-processing">Context Processing</h2>
+
+<p>
+When processing a JSON-LD data structure, each processing rule is applied
+using information provided by the <tref>active context</tref>. This
+section describes how to produce an <tref>active context</tref>.
+</p>
+
+<p>
+The <tref>active context</tref> contains the active
+<tdef title="term definition">term definitions</tdef> which specify how
+properties and values have to be interpreted as well as the current
+<tdef>vocabulary mapping</tdef> and the <tdef>default language</tdef>. Each
+<tref>term definition</tref> consists of an <tdef>IRI mapping</tdef> and
+optionally a <tdef>type mapping</tdef> from terms to datatypes or
+<tdef>language mapping</tdef> from terms to language codes, and a
+<tdef>container mapping</tdef>. If an <tref>IRI mapping</tref> maps a term
+to multiple <tref="IRI">IRIs</tref> it is said to be a
+<tdef>property generator</tdef>. The <tref>active context</tref> also
+keeps track of <tref>keyword</tref> aliases.
+</p>
+
+<p>
+When processing, the <tref>active context</tref> is initialized
+without any <tref title="term definition">term definitions</tref>,
+<tref>vocabulary mapping</tref>, or <tref>default language</tref>.
+If a <tref>local context</tref> is encountered during processing, a new
+<tref>active context</tref> is created by cloning the existing
+<tref>active context</tref>. Then the information from the
+<tref>local context</tref> is merged into the new <tref>active context</tref>.
+A <tref>local context</tref> is identified within a <tref>JSON object</tref>
+by the value of the <code>@context</code> key, which MUST be a
+<tref>string</tref>, an <tref>array</tref>, or a <tref>JSON object</tref>.
+</p>
+
+<section>
+<h3>Problem</h3>
+
+<p>
+A <tref>local context</tref> needs to be transformed into an
+<tref>active context</tref> so that the <tref>active context</tref> can be
+used when executing other JSON-LD algorithms such as
+<a href="#expansion-algorithm">Expansion</a> or
+<a href="#compaction-algorithm">Compaction</a>. Any remote
+<tref title="context">contexts</tref> in the <tref>local context</tref>
+have already been dereferenced.
+</p>
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+First we prepare a new <tref>active context</tref> <em>result</em> by cloning
+the current <tref>active context</tref>. Next we update the
+<tref>vocabulary mapping</tref> and <tref>default language</tref> by
+processing two specific keywords: <code>@vocab</code> and <code>@language</code>.
+These are handled before any other keys in the <tref>local context</tref> because
+they affect how the other keys are processed.
+</p>
+
+<p>
+Then, for every other key in <tref>local context</tref>, we update
+the <tref>term definition</tref> in <em>result</em>.
+</p>
+
+<p>
+Since <tref title="context">context</tref> values in a
+<tref>local context</tref> may themselves contain
+<tref title="compact IRI">compact IRIs</tref>, we may need to recurse to
+define a <tref>prefix</tref>. When doing so, we must ensure that there is
+no cyclical dependency, which is an error. After we have processed any
+<tref title="term definition">term definition</tref> dependencies, we update
+the current <tref title="term definition">term definition</tref>, which may be
+a keyword alias or consist of <code>@id</code>, <code>@language</code>,
+<code>@type</code>, or <code>@container</code> mappings.
+</p>
+
+<p>
+Finally, we return <em>result</em> as the new <tref>active context</tref>.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+This algorithm specifies how a new <tref>active context</tref> is updated
+with a <tref>local context</tref>. The algorithm takes two input variables:
+an <tref>active context</tref> and a <tref>local context</tref>.
+
+<ol class="algorithm">
+ <li>
+ Initialize <em>result</em> to the result of cloning
+ <tref>active context</tref>.
+ </li>
+ <li>
+ If <tref>local context</tref> is not an <tref>array</tref>, then
+ set it equal to an <tref>array</tref> containing only
+ <tref>local context</tref>.
+ </li>
+ <li>
+ For each item <em>context</em> in <tref>local context</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>context</em> equals <tref>null</tref>, then set <em>result</em>
+ to a newly-initialized <tref>active context</tref> and continue to the
+ next <em>context</em>.
+ </li>
+ <li>
+ At this point, <em>context</em> MUST be a <tref>JSON object</tref>
+ because all remote <tref title="context">contexts</tref> have already
+ been dereferenced. Otherwise, an invalid value has been detected,
+ which is an error.
+ </li>
+ <li>
+ Create a <tref>JSON object</tref> <em>defined</em> to use to keep
+ track of whether or not a <tref>term</tref> has already been defined
+ or currently being defined during recursion.
+ </li>
+ <li>
+ If <em>context</em> has an <code>@vocab</code> key:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>value</em> to the value associated with the
+ <code>@vocab</code> key.
+ </li>
+ <li>
+ If <em>value</em> equals <tref>null</tref>, then remove
+ any <tref>vocabulary mapping</tref> from <em>result</em>.
+ </li>
+ <li>
+ Otherwise, <em>value</em> MUST be an <tref>absolute IRI</tref>.
+ Otherwise, an invalid value has been detected, which is an error.
+ Set <em>result</em>'s <tref>vocabulary mapping</tref> to
+ <em>value</em>.
+ </li>
+ <li>
+ Set <em>defined</em>'s <code>@vocab</code> key to
+ <tref>true</tref>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>context</em> has an <code>@language</code> key:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>value</em> to the value associated with the
+ <code>@language</code> key.
+ </li>
+ <li>
+ If <em>value</em> equals <tref>null</tref>, then remove
+ any <tref>default language</tref> from <em>result</em>.
+ </li>
+ <li>
+ Otherwise, <em>value</em> MUST be a <tref>string</tref>.
+ Otherwise, an invalid value has been detected, which is an error.
+ Set <em>result</em>'s <tref>default language</tref> to
+ lowercased <em>value</em>.
+ </li>
+ <li>
+ Set <em>defined</em>'s <code>@language</code> key to
+ <tref>true</tref>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ For each <em>key</em>-<em>value</em> pair in <em>context</em> invoke
+ the <a href="#create-term-definition">Create Term Definition</a>
+ subalgorithm, passing <em>result</em> for <tref>active context</tref>,
+ <em>context</em> for <tref>local context</tref>, <em>key</em>,
+ and <em>defined</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Return <em>result</em>.
+ </li>
+</ol>
+
+</section>
+
+<!-- end of Context Processing algorithm -->
+</section>
+
+<section>
+<h2 id="create-term-definition">Create Term Definition Subalgorithm</h2>
+
+<p>
+This algorithm is called from the
+<a href="#context-processing">Context Processing</a> algorithm to create
+<tref title="term definition">term definitions</tref> in a new
+<tref>active context</tref>.
+</p>
+
+<section>
+<h3>Problem</h3>
+
+A <tref>term definition</tref> must be created for the given
+<tref>term</tref>.
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+<tref title="term definition">Term definitions</tref> are created by
+parsing the information in the given <tref>local context</tref> for the
+given <tref>term</tref>. If the given <tref>term</tref> is a
+<tref>compact IRI</tref> with a <tref>prefix</tref> that is a key in the
+<tref>local context</tref>, then that <tref>prefix</tref> is considered
+a dependency with its own <tref>term definition</tref> that must first
+be created, through recursion, before continuing. Because a
+<tref>term definition</tref> can depend on other
+<tref title="term definition">term definitions</tref>, a mechanism must
+be used to detect cyclical dependencies. The solution employed here
+uses a map, <em>defined</em>, that keeps track of whether or not a
+<tref>term</tref> has been defined or is currently in the process of
+being defined. This map is checked before any recursion is attempted.
+</p>
+
+<p>
+After all dependencies have been defined, the rest of the information
+in the <tref>local context</tref> for the given <tref>term</tref> is
+taken into account, creating the appropriate <tref>IRI mapping</tref>,
+<tref>container mapping</tref>, and <tref>type mapping</tref> or
+<tref>language mapping</tref> for the <tref>term</tref>.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+The algorithm has four required inputs which are:
+an <tref>active context</tref>, a <tref>local context</tref>,
+a <em>term</em>, and a map <em>defined</em>.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>defined</em> contains the key <em>term</em>, then the associated
+ value MUST be <tref>true</tref>, indicating that the
+ <tref>term definition</tref> has already been created, so return.
+ Otherwise, a cyclical <tref>term definition</tref> has been detected,
+ which is an error.
+ </li>
+ <li>
+ Set the value associated with <em>defined</em>'s <em>term</em> key to
+ <tref>false</tref>. This indicates that the <tref>term definition</tref>
+ is now being created but is not yet complete.
+ </li>
+ <li>
+ If <em>term</em> is a <tref>compact IRI</tref> with a <tref>prefix</tref>
+ that is a key in <tref>local context</tref> then a dependency has been
+ found. Use this algorithm recursively passing <tref>active context</tref>,
+ <tref>local context</tref>, the <tref>prefix</tref> as <em>term</em>,
+ and <em>defined</em>.
+ </li>
+ <li>
+ Since <tref title="keyword">keywords</tref> cannot be overridden,
+ <em>term</em> MUST NOT be a <tref>keyword</tref>. Otherwise, an
+ invalid value has been detected, which is an error.
+ </li>
+ <li>
+ If <em>term</em> is a <tref>keyword</tref> alias in
+ <tref>active context</tref>, remove it.
+ </li>
+ <li>
+ Initialize <em>value</em> to the value associated with the key
+ <em>term</em> in <tref>local context</tref>.
+ </li>
+ <li>
+ If <em>value</em> equals <tref>null</tref> or <em>value</em>
+ is a <tref>JSON object</tref> containing the key-value pair
+ (<code>@id</code>-<tref>null</tref>), then set the
+ <tref>term definition</tref> in <tref>active context</tref> to
+ <tref>null</tref>, set the value associated with <em>defined</em>'s
+ key <em>term</em> to <tref>true</tref>, and return.
+ </li>
+ <li>
+ Otherwise, if <em>value</em> is a <tref>string</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>value</em> is a <tref>keyword</tref>, then <em>value</em>
+ MUST NOT be equal to <code>@context</code> or <code>@preserve</code>.
+ Otherwise an invalid keyword alias has been detected, which is an
+ error. Add <em>term</em> to <tref>active context</tref> as a
+ <tref>keyword</tref> alias for <em>value</em>. If there is more
+ than one <tref>keyword</tref> alias for <em>value</em>, then
+ store its aliases as an <tref>array</tref>, sorted by length,
+ breaking ties lexicographically.
+ </li>
+ <li>
+ Otherwise, expand <em>value</em> by setting it to the result of
+ using the <a href="#iri-expansion">IRI Expansion</a> algorithm,
+ passing <tref>active context</tref>, <em>value</em>,
+ <tref>true</tref> for <em>documentRelative</em>,
+ <tref>local context</tref>, and <em>defined</em>.
+ </li>
+ <li>
+ Set the <tref>IRI mapping</tref> for the <tref>term definition</tref>
+ for <em>term</em> in <tref>active context</tref> to <em>value</em>,
+ set the value associated with <em>defined</em>'s key <em>term</em> to
+ <tref>true</tref>, and return.
+ <li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, <em>value</em> MUST be a <tref>JSON object</tref>, otherwise
+ an invalid value has been detected, which is an error.
+ </li>
+ <li>
+ Create a new <tref>JSON object</tref>, <em>definition</em>.
+ </li>
+ <li>
+ If <em>term</em> is a <tref>compact IRI</tref> and its
+ <tref>prefix</tref> has a <tref>term definition</tref> in
+ <tref>active context</tref>, set <em>definition</em> to a copy of it.
+ </li>
+ <li>
+ If <em>value</em> contains the key <code>@id</code>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>id</em> to the value associated with the
+ <code>@id</code> key.
+ </li>
+ <li>
+ If <em>id</em> is an <tref>array</tref>, then the
+ <tref>term definition</tref> is for a <tref>property generator</tref>:
+ <ol class="algorithm">
+ <li>
+ Create an empty <tref>array</tref> <em>property generator</em>.
+ <li>
+ For each item <em>iri</em> in <em>id</em>:
+ <ol class="algorithm">
+ <li>
+ <em>iri</em> MUST be a <tref>string</tref>, otherwise an
+ invalid value has been detected, which is an error.
+ </li>
+ <li>
+ If <em>iri</em> does not equal <code>@type</code> then
+ set it equal to the result of using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ <tref>active context</tref>, <em>iri</em> for <em>value</em>,
+ <tref>true</tref> for <em>documentRelative</em>,
+ <tref>local context</tref>, and <em>defined</em>.
+ </li>
+ <li>
+ Append <em>iri</em> to <em>property generator</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Set the <tref>property generator</tref> <tref>IRI mapping</tref>
+ for <em>definition</em> to <em>property generator</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise <em>id</em> MUST be a <tref>string</tref>, otherwise
+ an invalid value has been detected, which is an error. If <em>id</em>
+ does not equal <code>@type</code> then set it equal to the result of using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ <tref>active context</tref>, <em>id</em> for <em>value</em>,
+ <tref>true</tref> for <em>documentRelative</em>,
+ <tref>local context</tref>, and <em>defined</em>. Set the
+ <tref>IRI mapping</tref> for <em>definition</em> to <em>id</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>term</em> is not a <tref>compact IRI</tref>,
+ then <tref>active context</tref> MUST have a
+ <tref>vocabulary mapping</tref>, otherwise an invalid value has
+ been detected, which is an error. Set the <tref>IRI mapping</tref>
+ for <em>definition</em> to the result of concatenating the value
+ associated with the <tref>vocabulary mapping</tref> and <em>term</em>.
+ </li>
+ <li>
+ Otherwise, if <em>term</em>'s <tref>prefix</tref> has a
+ <tref>term definition</tref> in <tref>active context</tref>, set
+ the <tref>IRI mapping</tref> for <em>definition</em> to the result of
+ concatenating the value associated with the <tref>prefix</tref>'s
+ <tref>IRI mapping</tref> and the <em>term</em>'s <em>suffix</em>.
+ </li>
+ <li>
+ Otherwise, <em>term</em> is an <tref>absolute IRI</tref>. Set the
+ <tref>IRI mapping</tref> for <em>definition</em> to <em>term</em>.
+ </li>
+ <li>
+ If <em>value</em> contains the key <code>@type</code>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>type</em> equal to the value associated with the
+ <code>@type</code> key, which MUST be a <tref>string</tref>.
+ Otherwise, an invalid value has been detected, which is an error.
+ </li>
+ <li>
+ If <em>type</em> does not equal <code>@id</code> then set it to
+ the result of using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ <tref>active context</tref>, <em>type</em> for <em>value</em>,
+ <tref>true</tref> for <em>vocabRelative</em>,
+ <tref>true</tref> for <em>documentRelative</em>,
+ <tref>local context</tref>, and <em>defined</em>. Set the
+ <tref>type mapping</tref> for <em>definition</em> to <em>type</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>value</em> contains the key <code>@container</code>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>container</em> equal to the value associated with the
+ <code>@container</code> key, which MUST be either:
+ <code>@list</code>, <code>@set</code>, <code>@annotation</code>,
+ or <code>@language</code>. Otherwise, an invalid value has been
+ detected, which is an error.
+ </li>
+ <li>
+ Set the <tref>container mapping</tref> for <em>definition</em> to
+ <em>container</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>value</em> contains the key <code>@language</code> and
+ does not contain the key <code>@type</code>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>language</em> equal to the value associated with the
+ <code>@language</code> key, which MUST be either <tref>null</tref>
+ or a <tref>string</tref>. Otherwise, an invalid value has been
+ detected, which is an error.
+ </li>
+ <li>
+ If <em>language</em> is a <tref>string</tref> set it to
+ lowercased <em>language</em>. Set the <tref>language mapping</tref>
+ for <em>definition</em> to <em>language</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Set the <tref>term definition</tref> for <em>term</em> in
+ <tref>active context</tref> to <em>definition</em> and set the value
+ associated with <em>defined</em>'s key <em>term</em> to
+ <tref>true</tref>.
+ </li>
+</ol>
+
+</section>
+
+<!-- end of Term Creation subalgorithm -->
+</section>
+
+<section>
+<h2>Expansion Algorithm</h2>
+
+<section>
+<h3>Problem</h3>
+
+<p>
+A JSON-LD document needs to be expanded, such that all <tref>context</tref>
+definitions have been removed, all <tref title="term">terms</tref> and
+<tref title="compact IRI">compact IRIs</tref> have been expanded to absolute
+<tref title="IRI">IRIs</tref>, and all
+<tref title="JSON-LD value">JSON-LD values</tref> are expressed in
+<tref title="array">arrays</tref> in <tref>expanded form</tref>.
+</p>
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+Starting with its root <em>element</em>, we can process the
+JSON-LD document recursively, until we have a fully
+<tref title="expansion">expanded</tref> <em>result</em>. When
+<tref title="expansion">expanding</tref> an <em>element</em>, we can treat
+each one differently according to its type, in order to break down the
+problem:
+</p>
+
+<ol>
+ <li>
+ If the <em>element</em> is <tref>null</tref>, there is nothing
+ to expand.
+ </li>
+ <li>
+ If the <em>element</em> is an <tref>array</tref>, then we expand
+ each of its items recursively and return them in a new
+ <tref>array</tref>.
+ </li>
+ <li>
+ If the <em>element</em> is a <tref>JSON object</tref>,
+ then we expand each of its keys, adding them to our <em>result</em>,
+ and then we expand each value for each key recursively. Some of the keys
+ will be
+ <tref title="term">terms</tref> or
+ <tref title="compact IRI">compact IRIs</tref> and others will be
+ <tref title="keyword">keywords</tref> or simply ignored because
+ they do not have definitions in the <tref>context</tref>. Any
+ <tref title="IRI">IRIs</tref> will be expanded using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm.
+ </li>
+ <li>
+ Otherwise, the <em>element</em> is a <tref>scalar</tref>, which
+ we expand according to the <a href="#value-expansion">Value Expansion</a>
+ subalgorithm.
+ </li>
+</ol>
+
+<p>
+Finally, after ensuring <em>result</em> is in an <tref>array</tref>,
+we return <em>result</em>.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+The algorithm takes four input variables: an <tref>active context</tref>,
+an <tref>active property</tref>, an <em>element</em> to be expanded, and
+an <em>insideList</em> flag. To begin, the <tref>active context</tref> is set
+to the result of performing, <a
+href="#context-processing">Context Processing</a> on the passed
+<code class="idlMemberName"><a href="#widl-JsonLdOptions-expandContext">expandContext</a></code>,
+or empty if <code class="idlMemberName"><a href="#widl-JsonLdOptions-expandContext">expandContext</a></code>
+is <tref>null</tref>, <tref>active property</tref> is set to <tref>null</tref>,
+<em>element</em> is set to the <tref>JSON-LD input</tref>, and <em>insideList</em>
+is set to <tref>false</tref>. This algorithm expects the
+<tref>JSON-LD input</tref> to be a well-formed JSON-LD document as defined in
+[[!JSON-LD]].
+
+The algorithm outputs the result of expanding <em>element</em>.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>element</em> is <tref>null</tref>, return <tref>null</tref>.
+ </li>
+ <li>If <em>element</em> is an <tref>array</tref>,
+ <ol class="algorithm">
+ <li>
+ Initialize an empty array, <em>result</em>.
+ </li>
+ <li>For each <em>item</em> in <em>element</em>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>expanded item</em> to the result of using this
+ algorithm recursively, passing <tref>active context</tref>,
+ <tref>active property</tref>, <em>item</em> as <em>element</em>,
+ and <em>insideList</em>.
+ </li>
+ <li>
+ If <em>insideList</em> equals <tref>true</tref> then
+ <em>expanded item</em> MUST NOT be an <tref>array</tref> or a
+ <tref>list object</tref>, otherwise a list of lists has been
+ detected, which is an error.
+ </li>
+ <li>
+ If <em>expanded item</em> is an <tref>array</tref>, append each
+ of its items to <em>result</em>. Otherwise, if
+ <em>expanded item</em> is not null, append it to <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Return <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>If <em>element</em> is a <tref>JSON object</tref>,
+ <ol class="algorithm">
+ <li>
+ If <em>element</em> contains the key <code>@context</code>, set
+ <tref>active context</tref> equal to the result of the
+ <a href="#context-processing">Context Processing</a> algorithm,
+ passing <tref>active context</tref> and the value of the
+ <code>@context</code> key as <tref>local context</tref>.
+ </li>
+ <li>
+ Initialize <em>expanded active property</em> to the result of the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ <tref>active context</tref> and <tref>active property</tref> for
+ <em>value</em>.
+ <li>
+ Initialize an empty <tref>JSON object</tref>, <em>result</em>.
+ </li>
+ <li>
+ For each <em>key</em> and <em>value</em> in <em>element</em>,
+ ordered lexicographically by <em>key</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>key</em> is mapped to a <tref>property generator</tref>
+ in <tref>active context</tref>, set <em>expanded property</em>
+ to an array containing its <tref title="IRI">IRIs</tref>.
+ Otherwise, set <em>expanded property</em> to the result of
+ using the <a href="#iri-expansion">IRI Expansion</a> algorithm,
+ passing <tref>active context</tref>, <em>key</em> for
+ <em>value</em>, and <tref>true</tref> for <em>vocabRelative</em>.
+ </li>
+ <li>
+ If <em>expanded property</em> is either <tref>null</tref> or
+ is: not an <tref>array</tref>, an <tref>absolute IRI</tref> or
+ a <tref>keyword</tref>, then drop <em>key</em> by
+ continuing to the next <em>key</em>.
+ </li>
+ <li>
+ Validate <em>expanded property</em> against <em>value</em>
+ as follows:
+ <ol class="algorithm">
+ <li>
+ If <em>expanded property</em> is <code>@id</code> then
+ <em>value</em> MUST be a <tref>string</tref>, otherwise
+ an invalid value has been detected, which is an error.
+ </li>
+ <li>
+ If <em>expanded property</em> is <code>@type</code> then
+ <em>value</em> MUST be a <tref>string</tref> or an <tref>array</tref>
+ of strings, otherwise an invalid value has been detected, which
+ is an error.
+ </li>
+ <li>
+ If <em>expanded property</em> is <code>@graph</code> then
+ <em>value</em> MUST be a <tref>JSON object</tref> or an
+ <tref>array</tref>, otherwise an invalid value has been
+ detected, which is an error.
+ </li>
+ <li>
+ If <em>expanded property</em> is <code>@value</code> then
+ <em>value</em> MUST NOT be a <tref>JSON object</tref> or
+ an <tref>array</tref>, otherwise an invalid value has been
+ detected, which is an error.
+ </li>
+ <li>
+ If <em>expanded property</em> is <code>@language</code> then
+ <em>value</em> MUST be a <tref>string</tref>, otherwise an
+ invalid value has been detected, which is an error. Set
+ <em>expanded value</em> to lowercased <em>value</em>.
+ </li>
+ <li>
+ If <em>expanded property</em> is <code>@annotation</code>
+ then <em>value</em> MUST be a <tref>string</tref>, otherwise an
+ invalid value has been detected, which is an error.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>key</em>'s <tref>container mapping</tref> in
+ <tref>active context</tref> is <code>@language</code> and
+ <em>value</em> is a <tref>JSON object</tref> then <em>value</em>
+ is expanded from a <tref>language map</tref> as follows:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>expanded value</em> to an empty
+ <tref>array</tref>.
+ </li>
+ <li>
+ For each key <em>language</em> and value <em>language value</em>
+ in <em>value</em>, ordered lexicographically by
+ <em>language</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>language value</em> is not an <tref>array</tref>
+ set it to an <tref>array</tref> containing only
+ <em>language value</em>.
+ </li>
+ <li>
+ For each <em>item</em> in <em>language value</em>:
+ <ol class="algorithm">
+ <li>
+ <em>item</em> MUST be a <tref>string</tref>,
+ otherwise an invalid value has been detected,
+ which is an error.
+ </li>
+ <li>
+ Append a <tref>JSON object</tref> to
+ <em>expanded value</em> that consists of two
+ key-value pairs: (<code>@value</code>-<em>item</em>)
+ and (<code>@language</code>-lowercased
+ <em>language</em>).
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>key</em>'s <tref>container mapping</tref> in
+ <tref>active context</tref> is <code>@annotation</code> and
+ <em>value</em> is a <tref>JSON object</tref> then <em>value</em>
+ is expanded from an annotation map as follows:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>expanded value</em> to an empty
+ <tref>array</tref>.
+ </li>
+ <li>
+ For each key <em>annotation</em> and value
+ <em>annotation value</em> in <em>value</em>, ordered
+ lexicographically by <em>annotation</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>annotation value</em> is not an <tref>array</tref>
+ set it to an <tref>array</tref> containing only
+ <em>annotation value</em>.
+ </li>
+ <li>
+ Initialize <em>annotation value</em> to the result of
+ using this algorithm recursively, passing
+ <tref>active context</tref>, <tref>active property</tref>,
+ <em>annotation value</em> as <em>element</em>, and
+ <tref>false</tref> for <em>insideList</em>.
+ <li>
+ For each <em>item</em> in <em>annotation value</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>item</em> does not have the key
+ <code>@annotation</code>, add the key-value pair
+ (<code>@annotation</code>-<em>annotation</em>) to
+ <em>item</em>.
+ </li>
+ <li>
+ Append <em>item</em> to <em>expanded value</em>.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>expanded property</em> equals <code>@list</code>
+ or <code>@set</code>, initialize <em>expanded value</em> to the
+ result of using this algorithm recursively passing
+ <tref>active context</tref>, <tref>null</tref> for
+ <tref>active property</tref> if <em>expanded property</em> equals
+ <code>@list</code> and <em>expanded active property</em> equals
+ <code>@graph</code> otherwise <tref>active property</tref>,
+ <em>value</em> for <em>element</em>, and <tref>true</tref>
+ for <em>insideList</em> if <em>expanded property</em> equals
+ <code>@list</code> otherwise <tref>false</tref>.
+ If <em>expanded property</em> equals <code>@list</code>
+ then <em>expanded value</em> MUST NOT be a
+ <tref>list object</tref>, otherwise a list of lists has been
+ detected, which is an error.
+ </li>
+ <li>
+ Otherwise, initialize <em>expanded value</em> to the result of
+ using this algorithm recursively, passing
+ <tref>active context</tref>, <em>key</em> for
+ <tref>active property</tref>, <em>value</em>
+ for <em>element</em>, and <tref>false</tref> for
+ <em>insideList</em>.
+ </li>
+ <li>
+ If <em>expanded value</em> equals <tref>null</tref> and
+ <em>expanded property</em> is not <code>@value</code> then
+ drop <em>key</em> by continuing to the next key.
+ </li>
+ <li>
+ If <em>expanded property</em> is not <code>@list</code> and
+ <em>expanded value</em> is not a <tref>list object</tref> and
+ <em>key</em>'s <tref>container mapping</tref> in
+ <tref>active context</tref> is <code>@list</code> then convert
+ <em>expanded value</em> to a <tref>list object</tref> by first
+ setting it to an <tref>array</tref> containing only
+ <em>expanded value</em> if it is not already an
+ <tref>array</tref>, and then by setting it to a
+ <tref>JSON object</tref> containing the key-value pair
+ (<code>@list</code>-<em>expanded value</em>).
+ </li>
+ <li>
+ If <em>expanded property</em> is an <tref>array</tref>:
+ <ol class="algorithm">
+ <li>
+ Invoke the
+ <a href="#label-blank-nodes-algorithm">Label Blank Nodes</a>
+ subalgorithm, passing <tref>active context</tref> and
+ <em>expanded value</em> as <em>element</em>.
+ </li>
+ <li>
+ For each item <em>iri</em> in <em>expanded property</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>result</em> does not have the key <em>iri</em>,
+ set this key's value in <em>result</em> to an empty
+ <tref>array</tref>. Append a copy of
+ <em>expanded value</em> to the <tref>array</tref> value
+ associated with <em>result</em>'s <em>iri</em> key.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>expanded property</em> is
+ <code>@annotation</code>, <code>@id</code>, <code>@type</code>,
+ <code>@value</code>, or <code>@language</code>, then
+ set key <em>expanded property</em>'s value to
+ <em>expanded value</em> in <em>result</em>.
+ </li>
+ <li>
+ Otherwise, if <em>result</em> does not have the key
+ <em>expanded property</em>, set this key's value in <em>result</em>
+ to an empty <tref>array</tref>. Append <em>expanded value</em>
+ to the <tref>array</tref> value associated with <em>result</em>'s
+ <em>expanded property</em> key.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>result</em> contains the key <code>@value</code>:
+ <ol class="algorithm">
+ <li>
+ The <em>result</em> MUST NOT contain any keys other than
+ <code>@value</code>, <code>@language</code>, <code>@type</code>,
+ and <code>@annotation</code>. It MUST NOT contain both the
+ <code>@language</code> key and the <code>@type</code> key.
+ Otherwise, an invalid value has been detected, which is an error.
+ </li>
+ <li>
+ If the value of <em>result</em>'s <code>@value</code> key is
+ <tref>null</tref>, then set <em>result</em> to <tref>null</tref>.
+ </li>
+ <li>
+ Otherwise, if <em>result</em> contains the key
+ <code>@language</code> and the value of <em>result</em>'s
+ <code>@value</code> key is not a <tref>string</tref>, then remove
+ the <code>@language</code> key from <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>result</em> contains the key <code>@type</code>
+ and its associated value is not an <tref>array</tref>, set it to
+ an <tref>array</tref> containing only the associated value.
+ </li>
+ <li>
+ Otherwise, if <em>result</em> contains the key <code>@set</code>
+ or <code>@list</code>:
+ <ol class="algorithm">
+ <li>
+ The <em>result</em> MUST contain at most one other key and that
+ key MUST be <code>@annotation</code>. Otherwise, an invalid
+ value has been detected, which is an error.
+ </li>
+ <li>
+ If <em>result</em> contains the key <code>@set</code>, then
+ set <em>result</em> to the key's associated value.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>result</em> contains only the key
+ <code>@language</code>, set <em>result</em> to <tref>null</tref>.
+ </li>
+ <li>
+ If <em>insideList</em> equals false and either
+ <tref>active property</tref> equals <tref>null</tref> or
+ <em>expanded active property</em> equals <code>@graph</code>, then
+ drop free-floating values as follows:
+ <ol class="algorithm">
+ <li>
+ If <em>result</em> contains no keys or contains the key
+ <code>@value</code>, setting <em>result</em> to
+ <tref>null</tref>.
+ <li>
+ Otherwise, if <em>result</em>'s keys are only keywords and none
+ of the keys are <code>@graph</code>, <code>@type</code>, or
+ <code>@list</code> then set <em>result</em> to <tref>null</tref>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Return <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, <em>element</em> must be a <tref>scalar</tref>,
+ <ol class="algorithm">
+ <li>
+ If <em>insideList</em> equals <tref>false</tref> and
+ either <tref>active property</tref> equals <tref>null</tref> or
+ the result of expanding <tref>active property</tref> using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm is
+ <code>@graph</code>, then drop the top-level
+ <tref>scalar</tref> by returning <tref>null</tref>.
+ </li>
+ <li>
+ Return the result of the
+ <a href="#value-expansion">Value Expansion</a> algorithm, passing the
+ <tref>active context</tref>, <tref>active property</tref>, and
+ <em>element</em> as <em>value</em>.
+ </li>
+ </ol>
+ </li>
+</ol>
+
+<p>
+If, after the above algorithm is run, the result is a
+<tref>JSON object</tref> that contains only an <code>@graph</code> key, set the
+result to the value of <code>@graph</code>'s value. Otherwise, if the result
+is <tref>null</tref>, set it to an empty <tref>array</tref>. Finally, if
+the result is not an <tref>array</tref>, then set the result to an
+<tref>array</tref> containing only the result.
+</p>
+
+</section>
+
+<!-- end of Expansion Algorithm -->
+</section>
+
+<section>
+<h2>IRI Expansion</h2>
+
+<p>
+In JSON-LD documents, some keys and values may represent
+<tref title="IRI">IRIs</tref>. This section defines an algorithm for
+transforming a <tref>string</tref> that represents an <tref>IRI</tref> into
+an <tref>absolute IRI</tref>. It also covers transforming <tref>keyword</tref>
+aliases into <tref title="keyword">keywords</tref>.
+</p>
+
+<p>
+<tref>IRI</tref> expansion may occur during context processing or during
+any of the other JSON-LD algorithms. If IRI expansion occurs during context
+processing, then the <tref>local context</tref> and its related
+<em>defined</em> map from the
+<a href="#context-processing">Context Processing</a> algorithm are passed
+to this algorithm. This allows for <tref>term definition</tref> dependencies
+to be processed via the context processing subalgorithm,
+<a href="#create-term-definition">Create Term Definition</a>.
+</p>
+
+<p>
+After application of this algorithm, values processed by this algorithm are
+said to be in <tdef>expanded IRI form</tdef> (Advanced note: this form
+may also include
+<tref title="blank node identifier">blank node identifiers</tref> and
+JSON-LD <tref title="keyword">keywords</tref>).
+</p>
+
+<section>
+<h3>Problem</h3>
+
+We have a value that needs to be expanded to an <tref>absolute IRI</tref>
+or a <tref>keyword</tref>, if it can be and if it is not already one. The
+given value may be <tref>null</tref>, a <tref>term</tref>, a
+<tref>keyword</tref> alias, a <tref>compact IRI</tref>,
+a <tref>relative IRI</tref>, or an <tref>absolute IRI</tref>.
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+In order to expand <em>value</em> to an <tref>absolute IRI</tref>, we must
+first determine if it is <tref>null</tref>, a <tref>term</tref>, a
+<tref>keyword</tref>, or some form of <tref>IRI</tref>. While inspecting
+<em>value</em> we may also find that we need to create
+<tref>term definition</tref> dependencies because we're running this
+algorithm during <a href="#context-processing">Context Processing</a>. We can
+tell whether or not we're running during
+<a href="#context-processing">Context Processing</a> by checking
+<tref>local context</tref> against <tref>null</tref>.
+We know we need to create a <tref>term definition</tref> in the
+<tref>active context</tref> when <em>value</em> is
+a key in the <tref>local context</tref> and the <em>defined</em> map
+does not have a key for <em>value</em> with an associated value of
+<tref>true</tref>. The <em>defined</em> map is used during
+<a href="#context-processing">Context Processing</a> to keep track of
+which <tref title="term">terms</tref> have already been defined or are
+in the process of being defined. We create a
+<tref>term definition</tref> by using the
+<a href="#create-term-definition">Create Term Definition</a> subalgorithm.
+</p>
+
+<p>
+To begin, we handle the simplest case, where <em>value</em> is
+<tref>null</tref>. Here all we do is return <tref>null</tref> as there is
+nothing to expand.
+</p>
+
+<p>
+Next, we create a <tref>term definition</tref> for <em>value</em> if
+we need to. This ensures that when we look in the <tref>active context</tref>,
+any information associated with <em>value</em> will be ready.
+</p>
+
+<p>
+Now we initialize our <em>result</em> to <em>value</em> and then we
+look in the <tref>active context</tref> for <em>value</em>:
+
+<ol>
+ <li>
+ If it indicates that <em>value</em> is explicitly mapped to
+ <tref>null</tref>, then we return <tref>null</tref> which has the effect
+ of dropping the <em>value</em> from our expanded output.
+ </li>
+ <li>
+ If it indicates that <em>value</em> is a <tref>keyword</tref> alias,
+ then we return the associated <tref>keyword</tref>.
+ </li>
+ <li>
+ If it has a <tref>term definition</tref> that is a
+ <tref>property generator</tref> when the <tref>local context</tref> is
+ not <tref>null</tref>, then we trigger an error because a
+ <tref>term definition</tref> cannot have a
+ <tref>property generator</tref> as a dependency.
+ </li>
+ <li>
+ Otherwise, if it has <tref>term definition</tref> that is not a
+ <tref>property generator</tref> we update <em>result</em> by setting
+ it to the associated <tref>IRI mapping</tref>. If this is the case
+ then we also know that <em>result</em> is now an
+ <tref>absolute IRI</tref> (or a <tref>blank node identifier</tref>).
+ </li>
+</ol>
+
+</p>
+
+<p>
+At this point, if we know that <em>result</em> is not an
+<tref>absolute IRI</tref> or <tref>blank node identifier</tref>, then it
+may be a <tref>compact IRI</tref>. If it has a colon (<code>:</code>) in it
+then we parse it into <tref>prefix</tref>:<em>suffix</em>. If the resulting
+<tref>prefix</tref> is <code>_</code> or the <em>suffix</em>
+is <code>//</code>, then <em>result</em> is already an
+<tref>absolute IRI</tref>. Otherwise, if the <tref>prefix</tref> is a key in
+the <tref>local context</tref>, and we need to create a
+<tref>term definition</tref>, then we do so. If the
+<tref>term definition</tref> for the <tref>prefix</tref> in the
+<tref>active context</tref> is not a <tref>property generator</tref>, then
+we replace <em>result</em> with the concatenation of the associated
+<tref>IRI mapping</tref> and <em>suffix</em>.
+</p>
+
+<p>
+Finally, if <em>result</em> is now a <tref>blank node identifier</tref>,
+we relabel it by setting it to the result of the
+<a href="#generate-blank-node-identifier">Generate Blank Node Identifier</a>
+algorithm. Otherwise, if it is not an <tref>absolute IRI</tref>, we resolve
+it against either the <tref title="active context">active context's</tref>
+<tref>vocabulary mapping</tref> or the document base, given the
+<em>vocabRelative</em> and <em>documentRelative</em> flag values and
+the existence of a <tref>vocabulary mapping</tref>. Then we return
+<em>result</em>.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+The algorithm takes two required and four optional input variables. The
+required inputs are an <tref>active context</tref> and a <em>value</em>
+to be expanded. The optional inputs are two flags,
+<em>documentRelative</em> and <em>vocabRelative</em>, that specifying
+whether <em>value</em> can be interpreted as a <tref>relative IRI</tref>
+against the document's base <tref>IRI</tref> or the
+<tref title="active context">active context's</tref>
+<tref>vocabulary mapping</tref>, respectively, and
+a <tref>local context</tref> and map <em>defined</em> to be used when
+this algorithm is used during
+<a href="#context-processing">Context Processing</a>. If not passed, the
+two flags are set to <code>false</code> and <tref>local context</tref> and
+<em>defined</em> are initialized to <tref>null</tref>.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>value</em> equals <tref>null</tref>, then return <tref>null</tref>.
+ </li>
+ <li>
+ If <tref>local context</tref> is not <tref>null</tref>, it contains
+ a key that equals <em>value</em>, and the value associated with the key
+ that equals <em>value</em> in <em>defined</em> is not <tref>true</tref>,
+ then invoke the
+ <a href="#create-term-definition">Create Term Definition</a>
+ subalgorithm, passing <tref>active context</tref>,
+ <tref>local context</tref>, <em>value</em> as <em>term</em>, and
+ <em>defined</em>. This will ensure that a <tref>term definition</tref>
+ is created for <em>value</em> in <tref>active context</tref> during
+ <a href="#context-processing">Context Processing</a>.
+ </li>
+ <li>
+ If <tref>local context</tref> is not <tref>null</tref> then
+ <tref>active context</tref> MUST NOT have a <tref>term definition</tref>
+ for <em>value</em> that is a <tref>property generator</tref>.
+ Otherwise, an invalid error has been detected, which is an error.
+ </li>
+ <li>
+ If <em>value</em> has a <tref>null</tref> mapping in
+ <tref>active context</tref>, then explicitly ignore <em>value</em>
+ by returning <tref>null</tref>.
+ </li>
+ <li>
+ If <tref>active context</tref> indicates that <em>value</em> is a
+ <tref>keyword</tref> alias then return the associated
+ <tref>keyword</tref>.
+ </li>
+ <li>
+ Initialize <em>result</em> to <em>value</em> and <em>isAbsoluteIri</em>
+ to <tref>false</tref>.
+ </li>
+ <li>
+ If <tref>active context</tref> has a <tref>term definition</tref> for
+ <em>value</em>, then set <em>result</em> to the associated
+ <tref>IRI mapping</tref> and <em>isAbsoluteIri</em> to <tref>true</tref>.
+ </li>
+ <li>
+ If <em>isAbsoluteIri</em> equals <tref>false</tref> and <em>result</em>
+ contains a colon (<code>:</code>), then it is either an
+ <tref>absolute IRI</tref> or a <tref>compact IRI</tref>:
+ <ol class="algorithm">
+ <li>
+ Split <em>result</em> into a <tref>prefix</tref> and <em>suffix</em>
+ at the first occurence of a colon (<code>:</code>).
+ </li>
+ <li>
+ If <tref>prefix</tref> does not equal underscore (<code>_</code>)
+ and <em>suffix</em> does not begin with double-forward-slash
+ (<code>//</code>), then it may be a <tref>compact IRI</tref>:
+ <ol class="algorithm">
+ <li>
+ If <tref>local context</tref> is not <tref>null</tref>, it
+ contains a key that equals <tref>prefix</tref>, and the value
+ associated with the key that equals <tref>prefix</tref> in
+ <em>defined</em> is not <tref>true</tref>, then invoke the
+ <a href="#create-term-definition">Create Term Definition</a>
+ subalgorithm, passing <tref>active context</tref>,
+ <tref>local context</tref>, <em>prefix</em> as <em>term</em>,
+ and <em>defined</em>. This will ensure that a
+ <tref>term definition</tref> is created for <tref>prefix</tref>
+ in <tref>active context</tref> during
+ <a href="#context-processing">Context Processing</a>.
+ </li>
+ <li>
+ If <tref>active context</tref> contains a
+ <tref>term definition</tref> for <tref>prefix</tref> that is
+ not a <tref>property generator</tref> then set <em>result</em>
+ to the result of concatenating the value associated with the
+ <tref>prefix</tref>'s <tref>IRI mapping</tref> and
+ <em>suffix</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Set <em>isAbsoluteIri</em> to <tref>true</tref>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>isAbsoluteIri</em> equals <tref>true</tref>:
+ <ol class="algorithm">
+ <li>
+ If <tref>local context</tref> equals <tref>null</tref> and
+ <em>result</em> begins with and underscore and colon
+ (<code>_:</code>) then <em>result</em> is a
+ <tref>blank node identifier</tref>. Set <em>result</em> to the
+ result of the
+ <a href="#generate-blank-node-identifier">Generate Blank Node Identifier</a>
+ algorithm, passing <tref>active context</tref> and <em>result</em>
+ for <em>identifier</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>vocabRelative</em> equals <tref>true</tref> and
+ <tref>active context</tref> has a <tref>vocabulary mapping</tref>,
+ then set <em>result</em> to the result of concatenating the
+ <tref>vocabulary mapping</tref> with <em>result</em>.
+ </li>
+ <li>
+ Otherwise, if <em>documentRelative</em> equals <tref>true</tref>,
+ set <em>result</em> to the result of resolving <em>result</em> against
+ the document base as per [RFC3986]. Only the basic algorithm in
+ section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization
+ nor Scheme-Based Normalization (as described in sections 6.2.2 and
+ 6.2.3 of [RFC3986]) are performed. Characters additionally allowed in
+ IRI references are treated in the same way that unreserved characters
+ are treated in URI references, per section 6.5 of [RFC3987].
+ </li>
+ <li>
+ If <tref>local context</tref> is not <tref>null</tref> then
+ <em>result</em> MUST be an <tref>absolute IRI</tref>. Otherwise,
+ an invalid context value has been detected, which is an error. Return
+ <em>result</em>.
+ </li>
+</li>
+
+</section>
+
+<!-- end of IRI Expansion -->
+</section>
+
+<section>
+<h2>Value Expansion</h2>
+
+<p>
+Some values in JSON-LD can be expressed in a <tref>compacted form</tref>.
+These values are required to be <tref title="expansion">expanded</tref> at
+times when processing JSON-LD documents. A value is said to be in
+<tdef>expanded form</tdef> after the application of this algorithm.
+</p>
+
+<section>
+<h3>Problem</h3>
+
+A <em>value</em> associated with an <tref>active property</tref> must
+be <tref title="expansion">expanded</tref> to <tref>expanded form</tref>.
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+Other than the simple case where <em>value</em> is <tref>null</tref>, for
+which we return <tref>null</tref>, we must primarily look at <em>value</em>'s
+associated <tref>active property</tref> to determine how to expand it.
+</p>
+
+<p>
+First we <tref title="expansion">expand</tref> the
+<tref>active property</tref> itself, so that we can resolve
+<tref>keyword</tref> aliases. Then, for certain
+<tref title="keyword">keywords</tref> like <code>@id</code> and
+<code>@type</code>, we simply expand <em>value</em>
+using the <a href="#iri-expansion">IRI Expansion</a> algorithm and return
+the result.
+</p>
+
+<p>
+Next, we check to see if <tref>active property</tref> has a
+<tref>type mapping</tref> in the <tref>active context</tref> that would alter
+what we return. If it has one that is <code>@type</code> or if the
+<em>expanded property</em> is <code>@graph</code> then we return
+a <tref>JSON object</tref> with a single key-pair of <code>@id</code>
+and the result of using the <a href="#iri-expansion">IRI Expansion</a>
+algorithm on <em>value</em>.
+</p>
+
+<p>
+If we haven't returned yet and the <em>expanded property</em> is a
+<tref>keyword</tref>, then there is no special <tref>expansion</tref> to be
+performed on the <em>value</em>, so we return it as is.
+</p>
+
+<p>
+Otherwise, we'll our result will be a <tref>JSON object</tref> containing
+the key <code>@value</code> with the value the <em>value</em>. Additionally,
+a <code>@type</code> key-value pair will be included if there is a
+<tref>type mapping</tref> associated with the <tref>active property</tref>
+or a <code>@language</code> key-value pair if <em>value</em> is a
+<tref>string</tref> and there is <tref>language mapping</tref>.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+The algorithm takes three required inputs: an <tref>active context</tref>,
+an <tref>active property</tref>, and a <em>value</em> to expand.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>value</em> equals <tref>null</tref>, then return <tref>null</tref>.
+ </li>
+ <li>
+ Initialize <em>expanded property</em> to the result of using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ <tref>active context</tref>, <tref>active property</tref> for
+ <em>value</em>, and <tref>true</tref> for <em>vocabRelative</em>.
+ </li>
+ <li>
+ If <em>expanded property</em> equals <code>@id</code> then return
+ the result of using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ <tref>active context</tref>, <em>value</em>, and <tref>true</tref>
+ for <em>documentRelative</em>.
+ </li>
+ <li>
+ If <em>expanded property</em> equals <code>@type</code> then
+ return the result of using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ <tref>active context</tref>, <em>value</em>, <tref>true</tref> for
+ <em>vocabRelative</em>, and <tref>true</tref> for
+ <em>documentRelative</em>.
+ </li>
+ <li>
+ Initialize <em>type</em> to <tref>null</tref>.
+ </li>
+ <li>
+ If <tref>active property</tref> has a <tref>type mapping</tref> in
+ <tref>active context</tref> that is <code>@id</code> or if
+ <em>expanded property</em> equals <code>@graph</code>, then return
+ a new <tref>JSON object</tref> containing a single key-value pair
+ where the key is <code>@id</code> and the value is the result of
+ using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ <tref>active context</tref>, <em>value</em>, and <tref>true</tref> for
+ <em>documentRelative</em>.
+ </li>
+ <li>
+ If <em>expanded property</em> is a <tref>keyword</tref> return
+ <em>value</em> as is.
+ </li>
+ <li>
+ Otherwise, initialize <em>result</em> to an empty
+ <tref>JSON object</tref>.
+ </li>
+ <li>
+ If <tref>active property</tref> has a <tref>type mapping</tref> in
+ <tref>active context</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>type</em> to the value associated with the
+ <tref>type mapping</tref>.
+ </li>
+ <li>
+ If <em>type</em> is a <tref>blank node identifier</tref> (it
+ begins with <code>_:</code>), then set it to the result of the
+ <a href="#generate-blank-node-identifier">Generate Blank Node Identifier</a>
+ algorithm, passing <tref>active context</tref> and <em>type</em> for
+ <em>identifier</em>.
+ </li>
+ <li>
+ Add the key-value pair, (<code>@type</code>-<em>type</em>), to
+ <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>value</em> is a <tref>string</tref> and
+ <tref>active property</tref> has a <tref>language mapping</tref> in
+ <tref>active context</tref> that is not <tref>null</tref>, then
+ add a key-value pair to <em>result</em> where the key is
+ <code>@language</code> and the value is the value associated with
+ the <tref>language mapping</tref>.
+ </li>
+ <li>
+ Finally, add the key-value pair, (<code>@value</code>-<em>value</em>), to
+ <em>result</em> and return <em>result</em>.
+ </li>
+</ol>
+
+</section>
+
+<!-- end of Value Expansion -->
+</section>
+
+<section>
+<h2>Label Blank Nodes Subalgorithm</h2>
+
+<p>
+During <tref>expansion</tref>, it is sometimes necessary to ensure
+all <tref title="blank node">blank nodes</tref> have been labeled. This
+occurs when a <tref>property generator</tref> is used to copy a single
+property's values across multiple properties. This step is necessary to
+ensure that these duplicated values can be later
+<tref title="compaction">recompacted</tref>. Because new labels will
+be assigned to <tref title="blank node">blank nodes</tref>, it is
+important to relabel any existing <tref title="blank node">blank nodes</tref>
+to avoid conflicting names.
+</p>
+
+<p>
+The algorithm takes two required inputs and one optional input. The
+required inputs are: an <tref>active context</tref>,
+and an <em>element</em> to be labeled with
+<tref title="blank node identifier">blank node identifiers</tref>. The
+optional input is a flag <em>isId</em> that indicates whether or not
+<em>element</em> represents a value that is either an <tref>IRI</tref> or
+a <tref>blank node identifier</tref>. The <em>isId</em> flag defaults to
+<tref>false</tref>.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>element</em> is an <tref>array</tref>, then for each
+ <em>item</em> in <em>element</em>:
+ <ol class="algorithm">
+ <li>
+ Replace <em>item</em> with the result of using this algorithm
+ recursively, passing <tref>active context</tref>, <em>item</em>
+ for <em>element</em>, and <em>isId</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>element</em> is a <tref>list object</tref>, then
+ replace the value of the <code>@list</code> key in <em>element</em>
+ with the result of using this algorithm recursively, passing
+ <tref>active context</tref>, the value of the <code>@list</code> key
+ for <em>element</em>, and <em>isId</em>.
+ </li>
+ <li>
+ Otherwise, if <em>element</em> is a <tref>JSON object</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>element</em> is a <em>blank node</em>, then set the value
+ of its <code>@id</code> key to the result of using the
+ <a href="#generate-blank-node-identifier">Generate Blank Node Identifier</a>
+ algorithm, passing the value for <em>identifier</em>, using
+ <tref>null</tref> instead if <em>element</em> has no key
+ <code>@id</code>.
+ </li>
+ <li>
+ For each <em>key</em>-<em>value</em> pair ordered lexicographically
+ by <em>key</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>key</em> does not equal <code>@id</code>, then replace
+ <em>value</em> in <em>element</em> with the result of using
+ this algorithm recursively, passing <tref>active context</tref>,
+ <em>value</em> for <em>element</em>, and <tref>true</tref>
+ for <em>isId</em> if <em>key</em> equals <code>@type</code>,
+ otherwise <tref>false</tref> for <em>isId</em>.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>element</em> is a <tref>string</tref> and <em>isId</em>
+ equals <tref>true</tref>, and <em>element</em> is a
+ <tref>blank node identifier</tref>, then set <em>element</em> to
+ the result of using the
+ <a href="#generate-blank-node-identifier">Generate Blank Node Identifier</a>
+ algorithm, passing <em>element</em> for <em>identifier</em>.
+ </li>
+ <li>
+ Return <em>element</em>.
+ </li>
+</ol>
+
+</section>
+
+<section>
+<h2>Generate Blank Node Identifier</h2>
+
+<p>
+This algorithm is used to generate new
+<tref title="blank node identifier">blank node identifiers</tref> or to
+relabel an existing
+<tref>blank node identifier</tref> to avoid collision by the introduction
+of new ones. It needs to keep an <em>identifier map</em>, a <em>counter</em>,
+and a <em>prefix</em> between its executions to be able to generate new
+<tref title="blank node identifier">blank node identifiers</tref>. Note
+that it may be most convenient to keep this state information in the
+<tref>active context</tref>, so long as it is preserved (shared) when the
+<tref>active context</tref> is cloned during
+<a href="#context-processing">Context Processing</a>. The <em>counter</em> is
+initialized to <code>0</code> and <em>prefix</em> is set to <code>_:t</code>
+by default.
+</p>
+
+<p>
+The algorithm takes a single input variable <em>identifier</em> which may
+be <tref>null</tref>.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If the <em>identifier</em> is not <tref>null</tref> and is in the
+ <em>identifier map</em>, return the mapped identifier.
+ </li>
+ <li>
+ Otherwise, generate a new <em>blankNodeIdentifier</em> by concatenating
+ <em>prefix</em> and <em>counter</em>.
+ </li>
+ <li>
+ Increment <em>counter</em> by <code>1</code>.
+ </li>
+ <li>
+ If <em>identifier</em> is not <tref>null</tref>, create a new entry in
+ <em>identifier map</em> set to <em>blankNodeIdentifer</em>.
+ </li>
+ <li>
+ Return <em>blankNodeIdentifier</em>.
+ </li>
+</ol>
+
+</section>
+
+<section>
+<h2>Compaction Algorithm</h2>
+
+<section>
+<h3>Problem</h3>
+
+<p>
+A JSON-LD document needs to be compacted, such that the given
+<tref>context</tref> is applied. This must result in shortening
+any applicable <tref title="IRI">IRIs</tref> to
+<tref title="term">terms</tref> or
+<tref title="compact IRI">compact IRIs</tref> and
+any applicable <tref title="JSON-LD value">JSON-LD values</tref>
+expressed in <tref>expanded form</tref> to simple values such as
+<tref title="string">strings</tref> or
+<tref title="number">numbers</tref>.
+</p>
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+Starting with its root <em>element</em>, we can process the
+JSON-LD document recursively, until we have a fully
+<tref title="compaction">compacted</tref> <em>result</em>. When
+<tref title="compaction">compacting</tref> an <em>element</em>, we can treat
+each one differently according to its type, in order to break down the
+problem:
+</p>
+
+<ol>
+ <li>
+ If the <em>element</em> is an <tref>array</tref>, then we compact
+ each of its items recursively and return them in a new
+ <tref>array</tref>.
+ </li>
+ <li>
+ If the <em>element</em> is a <tref>JSON object</tref>,
+ then we start by creating a shallow copy of it and each of its
+ key's <tref>array</tref> values. This is done so that if any key
+ is compacted to a <tref>property generator</tref> <tref>term</tref>,
+ we can remove duplicate values without modifying the original
+ <em>element</em>. Then, we compact each value in the shallow copy
+ for each key recursively. Some of the keys will be
+ compacted, using the
+ <a href="#iri-compaction">IRI Compaction</a> algorithm,
+ to <tref title="term">terms</tref> or
+ <tref title="compact IRI">compact IRIs</tref> and others will be
+ compacted from <tref title="keyword">keywords</tref> to
+ <tref>keyword</tref> aliases or simply left unchanged because
+ they do not have definitions in the <tref>context</tref>. Values will
+ be converted to <tref>compacted form</tref> via the
+ <a href="#value-compaction">Value Compaction</a> algorithm. Some data
+ will be reshaped based on
+ <tref title="container mapping">container mappings</tref> specified
+ in the context such as <code>@annotation</code> or <code>@language</code>
+ maps.
+ </li>
+ <li>
+ Otherwise, the <em>element</em> is a <tref>scalar</tref>, it is
+ already in <tref>compacted form</tref>, so we simply return.
+ </li>
+</ol>
+
+<p>
+The final output is a <tref>JSON object</tref> with a <code>@context</code>
+key, if a <tref>context</tref> was given, where the <tref>JSON object</tref>
+is either <em>result</em> or a wrapper for it where <em>result</em> appears
+as the value of an aliased <code>@graph</code> key because <em>result</em>
+contained two or more items in an <tref>array</tref>. If no
+<tref>context</tref> was given, the <em>result</em> is only simplified
+from an <tref>array</tref> to a <tref>JSON object</tref> if it has one or
+fewer items.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+The algorithm takes four required input variables: an
+<tref>active context</tref>, an <tref>active property</tref>, and an
+<em>element</em> to be compacted. To begin, the <tref>active context</tref>
+is set to the result of performing
+<a href="#context-processing">Context Processing</a> on the passed
+<em>context</em>, the <tref>active property</tref> is set to
+<tref>null</tref>, and <em>element</em> is set to the result of performing
+the <a href="#expansion-algorithm">Expansion Algorithm</a> on the
+<tref>JSON-LD input</tref>.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>element</em> is an <tref>array</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>result</em> to an empty <tref>array</tref>.
+ </li>
+ <li>
+ For each <em>item</em> in <em>element</em>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>compacted item</em> to the result of using this
+ algorithm recursively, passing <tref>active context</tref>,
+ <tref>active property</tref>, and <em>item</em> for
+ <em>element</em>.
+ </li>
+ <li>
+ If <em>compacted item</em> is not <tref>null</tref>, then append
+ it to <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>result</em> contains only one item (it has a length of
+ <code>1</code>) and <tref>active property</tref> has no
+ <tref>container mapping</tref> in <tref>active context</tref>,
+ then set <em>result</em> to its only item.
+ </li>
+ <li>
+ Return <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>element</em> is an <tref>JSON object</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>element</em> contains the key <code>@value</code> or
+ if it contains only one key and that key is <code>@id</code>,
+ then return the result of using the
+ <a href="#value-compaction">Value Compaction</a> algorithm,
+ passing <tref>active context</tref>, <tref>active property</tref>,
+ and <em>element</em> as <em>value</em>.
+ </li>
+ <li>
+ Create a shallow copy of <em>element</em> and each <tref>array</tref>
+ associated with its keys so that duplicate values can be removed
+ during <tref>property generator</tref> <tref>compaction</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>shallow</em> to an empty <tref>JSON object</tref>.
+ </li>
+ <li>
+ For each <em>key</em>-<em>value</em> pair in <em>element</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>value</em> is an <tref>array</tref>, then add
+ a key-value pair to <em>shallow</em> where the key
+ is <em>key</em> and the value is a shallow copy of
+ <em>value</em>.
+ </li>
+ <li>
+ Otherwise, add the key-value pair, <em>key</em>-<em>value</em>
+ to <em>shallow</em>.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ Initialize <em>result</em> to an empty <tref>JSON object</tref>.
+ </li>
+ <li>
+ Initialize <em>keys</em> to an <tref>array</tref> containing
+ all of the keys in <em>element</em>, ordered lexicographically.
+ </li>
+ <li>
+ For each key <em>expanded property</em> in <em>keys</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>shallow</em> does not contain a key that equals
+ <em>expanded property</em>, then continue to the next
+ <em>expanded property</em>.
+ </li>
+ <li>
+ Initialize <em>expanded value</em> to the value associated
+ with the key that equals <em>expanded property</em> in
+ <em>shallow</em>.
+ </li>
+ <li>
+ If <em>expanded property</em> equals <code>@id</code> or
+ <code>@type</code>:
+ <ol class="algorithm">
+ <li>
+ If <em>expanded value</em> is a <tref>string</tref>,
+ then initialize <em>compacted value</em> to the result
+ of using the
+ <a href="#iri-compaction-algorithm">IRI Compaction</a>
+ algorithm, passing <tref>active context</tref>,
+ <em>expanded value</em> for <em>iri</em>,
+ <tref>true</tref> for <em>vocabRelative</em> if
+ <em>expanded property</em> equals <code>@type</code>,
+ <tref>false</tref> otherwise, and <tref>true</tref>
+ for <em>documentRelative</em>.
+ </li>
+ <li>
+ Otherwise, <em>expanded value</em> must be a
+ <code>@type</code> <tref>array</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>compacted value</em> to an empty
+ <tref>array</tref>.
+ </li>
+ <li>
+ For each item <em>expanded type</em> in
+ <em>expanded value</em>, append the result of
+ of using the
+ <a href="#iri-compaction-algorithm">IRI Compaction</a>
+ algorithm, passing <tref>active context</tref>,
+ <em>expanded type</em> for <em>iri</em>,
+ <tref>true</tref> for <em>vocabRelative</em>,
+ and <tref>true</tref> for <em>documentRelative</em>,
+ to <em>compacted value</em>.
+ </li>
+ <li>
+ If <em>compacted value</em> contains only one
+ item (it has a length of <code>1</code>), then
+ set <em>compacted value</em> to its only item.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Initialize <em>alias</em> to the result of using the
+ <a href="#iri-compaction-algorithm">IRI Compaction</a>
+ algorithm, passing <tref>active context</tref> and
+ <em>expanded property</em> for <em>iri</em>.
+ </li>
+ <li>
+ Add the key-value pair,
+ (<em>alias</em>-<em>compacted value</em>) to
+ <em>result</em> and continue to the next
+ <em>expanded property</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>expanded property</em> equals <code>@annotation</code>:
+ <ol class="algorithm">
+ <li>
+ If <tref>active property</tref> has a
+ <tref>container mapping</tref> in <tref>active context</tref>
+ that equals <code>@annotation</code>, then the compacted
+ result will be inside of an <code>@annotation</code>
+ container, so simply drop the <code>@annotation</code>
+ property by continuing to the next
+ <em>expanded property</em>.
+ </li>
+ <li>
+ Otherwise, initialize <em>alias</em> to the result of using
+ the <a href="#iri-compaction-algorithm">IRI Compaction</a>
+ algorithm, passing <tref>active context</tref> and
+ <em>expanded property</em> for <em>iri</em>.
+ </li>
+ <li>
+ Add the key-value pair,
+ (<em>alias</em>-<em>expanded value</em>) to
+ <em>result</em> and continue to the next
+ <em>expanded property</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>expanded value</em> is an empty <tref>array</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>activeProperty</em> to the result of using
+ the <a href="#iri-compaction-algorithm">IRI Compaction</a>
+ algorithm, passing <tref>active context</tref>,
+ <em>expanded property</em> for <em>iri</em>,
+ <tref>true</tref> for <em>vocabRelative</em>, and
+ <em>shallow</em> for <em>parent</em>.
+ </li>
+ <li>
+ If <em>result</em> does not have the key that equals
+ <em>activeProperty</em>, set this key's value in <em>result</em>
+ to an empty <tref>array</tref>. Otherwise, if the key's value
+ is not an <tref>array</tref>, then set it equal to one
+ containing only the value.
+ </li>
+ </ol>
+ </li>
+ <li>
+ At this point, <em>expanded value</em> must be an
+ <tref>array</tref> due to the
+ <a href="#expansion-algorithm">Expansion algorithm</a>.
+ For each item <em>expanded item</em> in <em>expanded value</em>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>activeProperty</em> to the result of using
+ the <a href="#iri-compaction-algorithm">IRI Compaction</a>
+ algorithm, passing <tref>active context</tref>,
+ <em>expanded property</em> for <em>iri</em>,
+ <em>expanded item</em> for <em>value</em>,
+ <tref>true</tref> for <em>vocabRelative</em>, and
+ <em>shallow</em> for <em>parent</em>.
+ </li>
+ <li>
+ Initialize <em>container</em> to <tref>null</tref>. If there
+ is a <tref>container mapping</tref> for
+ <em>activeProperty</em> in <tref>active context</tref>,
+ set <em>container</em> to its value.
+ </li>
+ <li>
+ If there is a <tref>term definition</tref> for
+ <em>activeProperty</em> in <tref>active context</tref> that
+ is a <tref>property generator</tref>, then invoke the
+ <a href="#find-and-remove-property-generator-duplicates">Find and Remove Property Generator Duplicates</a>
+ algorithm, passing <tref>active context</tref>,
+ <em>shallow</em> for <em>element</em>,
+ <em>expanded property</em>, <em>expanded item</em> for
+ <em>value</em>, and <em>activeProperty</em>.
+ </li>
+ <li>
+ Initialize <em>compacted item</em> to the result of using
+ this algorithm recursively, passing
+ <tref>active context</tref>, <em>activeProperty</em>,
+ <em>expanded item</em> for <em>element</em> if it does
+ not contain the key <code>@list</code>, otherwise pass
+ the key's associated value for <em>element</em>.
+ </li>
+ <li>
+ If <em>expanded item</em> is a <tref>list object</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>compacted item</em> is not an <tref>array</tref>,
+ then set it to an <tref>array</tref> containing only
+ <em>compacted item</em>.
+ </li>
+ <li>
+ If <em>container</em> does not equal <code>@list</code>:
+ <ol class="algorithm">
+ <li>
+ Convert <em>compacted item</em> to a
+ <tref>list object</tref> by setting it to a
+ <tref>JSON object</tref> containing key-value pair
+ where the key is the result of the
+ <a href="#iri-compaction-algorithm">IRI Compaction</a>
+ algorithm, passing <tref>active context</tref> and
+ <code>@list</code> for <em>iri</em>, and the
+ value is <em>compacted item</em>.
+ </li>
+ <li>
+ If <em>expanded item</em> contains the key
+ <code>@annotation</code>, then add a key-value pair
+ to <em>compacted item</em> where the key is the
+ result of the
+ <a href="#iri-compaction-algorithm">IRI Compaction</a>
+ algorithm, passing <tref>active context</tref> and
+ <code>@annotation</code> for <em>iri</em>, and the
+ value is the value associated with the
+ <code>@annotation</code> key in
+ <em>expanded item</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, <tref>active property</tref> MUST NOT be a key
+ in <em>result</em> because there cannot be two
+ <tref title="list object">list objects</tref> associated
+ with an <tref>active property</tref> that has a
+ <tref>container mapping</tref>; this is an error.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>container</em> equals <code>@language</code> or
+ <code>@annotation</code>:
+ <ol class="algorithm">
+ <li>
+ If <em>active property</em> is a key in <em>result</em>,
+ then initialize <em>map object</em> to its associated
+ value, otherwise initialize it to an empty
+ <tref>JSON object</tref>.
+ </li>
+ <li>
+ If <em>container</em> is <code>@language</code> and
+ <em>compacted item</em> contains the key
+ <code>@value</code>, then set <em>compacted item</em>
+ to the value associated with its <code>@value</code> key.
+ </li>
+ <li>
+ Initialize <em>map key</em> to the value associated with
+ with the key that equals <em>container</em> in
+ <em>expanded item</em>.
+ </li>
+ <li>
+ If <em>map key</em> is not a key in <em>map object</em>,
+ then set this key's value in <em>map object</em>
+ to <em>compacted item</em>. Otherwise, if the value
+ is not an <tref>array</tref>, then set it equal to one
+ containing only the value and then append
+ <em>compacted item</em> to it.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise,
+ <ol class="algorithm">
+ <li>
+ Initialize <em>useArray</em> to <tref>false</tref>. If
+ <em>container</em> equals <code>@set</code> or
+ <code>@list</code>, or <em>compacted item</em> is
+ an empty <tref>array</tref>, or <em>expanded property</em>
+ equals <code>@graph</code>, then set <em>useArray</em>
+ to <tref>true</tref>.
+ </li>
+ <li>
+ If <em>useArray</em> is <tref>true</tref> and
+ <em>compacted item</em> is not an <tref>array</tref>,
+ then set it equal to a new <tref>array</tref>
+ containing only <em>compacted item</em>.
+ </li>
+ If <tref>active property</tref> is not a key in
+ <em>result</em> then add the key-value pair,
+ (<tref>active property</tref>-<em>compacted item</em>),
+ to <em>result</em>.
+ </li>
+ <li>
+ Otherwise, if the value associated with the key that
+ equals <tref>active property</tref> in <em>result</em>
+ is not an <tref>array</tref>, set it equal to a new
+ <tref>array</tref> containing only the value. Then
+ append <em>compacted item</em> to the value if
+ <em>compacted item</em> is not an <tref>array</tref>,
+ otherwise, concatenate it.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ Return <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ At this point, <em>element</em> must a be <tref>scalar</tref>, which
+ is already compact, so simply return <em>element</em>.
+ </li>
+</ol>
+
+<p>
+If, after the algorithm outlined above is run, the result <em>result</em> is
+an <tref>array</tref> with two or more items and a <em>context</em> has
+been passed, replace it with a new <tref>JSON object</tref> with a single
+key-value pair where the key is the result of using the
+<a href="#iri-compaction-algorithm">IRI Compaction</a> algorithm, passing
+<tref>active context</tref> and <code>@graph</code> for <em>iri</em>, and
+the value is <em>result</em>. Otherwise, if <em>result</em> is an
+<tref>array</tref> with only one item, set <em>result</em> to that item.
+Otherwise, if <em>result</em> is an <tref>array</tref> with zero items,
+replace it with an empty <tref>JSON object</tref>. Finally, if a
+<em>context</em> has been passed, add an <code>@context</code> property to
+<em>result</em> and set its value to the initially passed
+<em>context</em>.
+</p>
+
+</section>
+
+<!-- end of Compaction -->
+</section>
+
+<section>
+<h2>IRI Compaction Algorithm</h2>
+
+<p>
+This section defines an algorithm for transforming an <tref>IRI</tref>
+to a <tref>term</tref> or <tref>compact IRI</tref>, or a <tref>keyword</tref>
+alias to a <tref>keyword</tref>. A value that is associated with the
+<tref>IRI</tref> may be passed in order to assist in selecting the most
+context-appropriate <tref>term</tref>.
+</p>
+
+<section>
+<h3>Problem</h3>
+
+We have an <tref>IRI</tref> (or <tref>keyword</tref>) that we may
+be able to compact to <tref>term</tref>, <tref>compact IRI</tref>, or
+<tref>keyword</tref> alias.
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+First, we handle the simple cases: if the value given as an <tref>IRI</tref>
+is <tref>null</tref>, we simply return <tref>null</tref> and if it is a
+<tref>keyword</tref> we return its associated alias.
+</p>
+
+<p>
+Otherwise, we first try to find a <tref>term</tref> that the
+<tref>IRI</tref> can be <tref title="compaction">compacted</tref> to. In
+order to select a <tref>term</tref>, we have to collect information about
+the <tref title="IRI">IRI's</tref> associated value. This information
+includes which <tref title="container mapping">container mappings</tref>
+would be preferred for expressing the value, and what its
+<tref>type mapping</tref> or <tref>language mapping</tref> is. For
+JSON-LD lists, the <tref>type mapping</tref> or <tref>language mapping</tref>
+will be chosen based on the most specific values that work for all items in
+the list. Once this information is gathered, it is passed to the
+<a href="#term-selection">Term Selection</a> subalgorithm, which will
+return the most appropriate <tref>term</tref> to use.</p>
+
+<p>
+If no <tref>term</tref> was found that could be used to compact the
+<tref>IRI</tref>, then an attempt is made to find a <tref>compact IRI</tref>
+to use. If there is no appropriate <tref>compact IRI</tref>, then
+the <tref title="active context">active context's</tref>
+<tref>vocabulary mapping</tref> is used. Finally, if the <tref>IRI</tref>
+still could not be compacted, we simply return it as is.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+This algorithm takes three required inputs and three optional inputs.
+The required inputs an <tref>active context</tref> and the <em>iri</em> to
+be compacted. The optional inputs are: a <em>value</em> associated with
+the <em>iri</em>, a <em>vocabRelative</em> flag which specifies whether the
+passed <em>iri</em> should be compacted using the
+<tref title="active context">active context's</tref>
+<tref>vocabulary mapping</tref>, and the <em>parent</em> element for
+the <em>value</em>. If not passed, <em>value</em> is set to
+<tref>null</tref>, <em>vocabRelative</em> is set to <code>false</code>, and
+<em>parent</em> is set to <tref>null</tref>.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>iri</em> is <tref>null</tref>, return <tref>null</tref>.
+ </li>
+ <li>
+ If <em>iri</em> is a <tref>keyword</tref> and does not have a
+ <tref>keyword</tref> alias, return <em>iri</em>, otherwise return
+ its first associated <tref>keyword</tref> alias from
+ <tref>active context</tref>.
+ </li>
+ <li>
+ If <tref>active context</tref> has no associated
+ <tref>inverse context</tref>, then generate it using the
+ <a href="#inverse-context-creation">Inverse Context Creation</a>
+ algorithm. Set <em>inverse context</em> to the
+ <tref>inverse context</tref> associated with <tref>active context</tref>.
+ </li>
+ <li>
+ Initialize <em>defaultLanguage</em> to
+ <tref title="active context">active context's</tref>
+ <tref>default language</tref>, if it has one, otherwise to
+ <code>@none</code>.
+ </li>
+ <li>
+ If <em>iri</em> is a key in <em>inverse context</em>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>entry</em> to the value in <em>inverse context</em>
+ associated with the key that equals <em>iri</em>.
+ </li>
+ <li>
+ Initialize <em>containers</em> to an empty <tref>array</tref>. This
+ <tref>array</tref> will be used to keep track of an ordered list of
+ preferred <tref title="container mapping">container mappings</tref>
+ for a <tref>term</tref>, based on what is compatible with
+ <em>value</em>.
+ </li>
+ <li>
+ If <em>value</em> is a <tref>JSON object</tref> that contains the
+ key <code>@index</code>, then append the value <code>@index</code>
+ to <em>containers</em>.
+ </li>
+ <li>
+ Initialize <em>typeOrLanguage</em> to <code>@language</code>,
+ and <em>typeOrLanguageValue</em> to <code>@null</code>. These two
+ variables will keep track of the preferred
+ <tref>type mapping</tref> or <tref>language mapping</tref> for
+ a <tref>term</tref>, based on what is compatible with <em>value</em>.
+ </li>
+ If <em>value</em> is a <tref>list object</tref>, then set
+ <em>typeOrLanguage</em> and <em>typeOrLanguageValue</em>
+ to the most specific values that work for all items in
+ the list as follows:
+ <ol class="algorithm">
+ <li>
+ If <code>@index</code> is a not key in <em>value</em>, then
+ append <code>@list</code> to <em>containers</em>.
+ </li>
+ <li>
+ Initialize <em>list</em> to the <tref>array</tref> associated
+ with the key <code>@list</code> in <em>value</em>.
+ </li>
+ <li>
+ Initialize <em>commonLanguage</em> to <tref>null</tref>. If
+ <em>list</em> is empty, set <em>commonLanguage</em> to
+ <em>defaultLanguage</em>.
+ </li>
+ <li>
+ For each <em>item</em> in <em>list</em>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>itemLanguage</em> to <code>@none</code> and
+ <em>itemType</em> to <code>@none</code>.
+ </li>
+ <li>
+ If <em>item</em> contains the key <code>@value</code>:
+ <ol class="algorithm">
+ <li>
+ If <em>item</em> contains the key <code>@language</code>,
+ then set <em>itemLanguage</em> to its associated
+ value.
+ </li>
+ <li>
+ Otherwise, if <em>item</em> contains the key
+ <code>@type</code>, set <em>itemType</em> to its
+ associated value.
+ </li>
+ <li>
+ Otherwise, set <em>itemLanguage</em> to
+ <code>@null</code>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>commonLanguage</em> is <tref>null</tref>, set it
+ to <em>itemLanguage</em>.
+ </li>
+ <li>
+ Otherwise, if <em>itemLanguage</em> does not equal
+ <em>commonLanguage</em> and <em>item</em> contains the
+ key <code>@value</code>, then set <em>commonLanguage</em>
+ to <code>@none</code> because list items have conflicting
+ languages.
+ </li>
+ <li>
+ If <em>commonType</em> is <tref>null</tref>, set it
+ to <em>itemType</em>.
+ </li>
+ <li>
+ Otherwise, if <em>itemType</em> does not equal
+ <em>commonType</em>, then set <em>commonType</em>
+ to <code>@none</code> because list items have conflicting
+ types.
+ </li>
+ <li>
+ If <em>commonLanguage</em> equals <code>@none</code> and
+ <em>commonType</em> equals <code>@none</code>, then
+ stop processing items in the list because it has been
+ detected that there is no common language or type amongst
+ the items.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>commonLanguage</em> is <tref>null</tref>, set it to
+ <code>@none</code>.
+ </li>
+ <li>
+ If <em>commonType</em> is <tref>null</tref>, set it to
+ <code>@none</code>.
+ </li>
+ <li>
+ If <em>commonType</em> is not <code>@none</code> then set
+ <em>typeOrLanguage</em> to <code>@type</code> and
+ <em>typeOrLanguageValue</em> to <em>commonType</em>.
+ </li>
+ <li>
+ Otherwise, set <em>typeOrLanguageValue</em> to
+ <em>commonLanguage</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise:
+ <ol class="algorithm">
+ <li>
+ If <em>value</em> contains the key <code>@value</code>:
+ <ol class="algorithm">
+ <li>
+ If <em>value</em> contains the key <code>@language</code>,
+ then set <em>typeOrLanguageValue</em> to its associated
+ value and append <code>@language</code> to
+ <em>containers</em>.
+ </li>
+ <li>
+ Otherwise, if <em>value</em> contains the key
+ <code>@type</code>, then set <em>typeOrLanguageValue</em> to
+ its associated value and set <em>typeOrLanguage</em> to
+ <code>@type</code>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, set <em>typeOrLanguage</em> to <code>@type</code>
+ and set <em>typeOrLanguageValue</em> to <code>@id</code>.
+ </li>
+ <li>
+ Append <code>@set</code> to <em>containers</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Initialize <em>term</em> to the result of the
+ <a href="#term-selection">Term Selection</a> subalgorithm, passing
+ <tref>active context</tref>, <em>value</em>, <em>parent</em>,
+ <em>entry</em>, <em>containers</em>, <em>typeOrLanguage</em>, and
+ <em>typeOrLangaugeValue</em>.
+ </li>
+ <li>
+ If <em>term</em> is not <tref>null</tref>, return <em>term</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ At this point, there is no simple <tref>term</tref> that <em>iri</em>
+ can be compacted to. Instead, try to choose a <tref>compact IRI</tref>,
+ starting by initializing <em>choice</em> to <tref>null</tref>. This
+ variable will be used to store the chosen <tref>compact IRI</tref> to
+ use, if any.
+ </li>
+ <li>
+ For each key <tref>term</tref> and value <tref>term definition</tref> in
+ the <tref>active context</tref>:
+ <ol class="algorithm">
+ <li>
+ If the <tref>term</tref> contains a colon (<code>:</code>),
+ then continue to the next <tref>term</tref> because
+ <tref title="term">terms</tref> with colons can't be
+ used as <tref title="prefix">prefixes</tref>.
+ </li>
+ <li>
+ If the <tref>term definition</tref> is <tref>null</tref>
+ or for a <tref>property generator</tref> or its
+ <tref>IRI mapping</tref> equals <em>iri</em> or is not
+ a substring at the beginning of <em>iri</em>, then the
+ <tref>term</tref> cannot be used as a <tref>prefix</tref>
+ because it is not a partial match with <em>iri</em>. So
+ continue to the next <tref>term</tref>.
+ </li>
+ <li>
+ Initialize <em>curie</em> by concatenating <tref>term</tref>,
+ a colon (<code>:</code>), and the substring of <em>iri</em>
+ that follows after the value of the
+ <tref title="term definition">term definition's</tref>
+ <tref>IRI mapping</tref>.
+ </li>
+ <li>
+ Initialize <em>isUsableCurie</em> to <tref>false</tref>. If
+ <em>curie</em> does not have a <tref>term definition</tref> in
+ <tref>active context</tref> or if the
+ <tref>term definition</tref> has an <tref>IRI mapping</tref>
+ that equals <em>iri</em> and <em>value</em> is <tref>null</tref>,
+ then set <em>isUsableCurie</em> to <tref>true</tref>.
+ </li>
+ <li>
+ If <em>isUsableCurie</em> equals <tref>true</tref> and either
+ <em>choice</em> is <tref>null</tref> or <em>curie</em> is shorter
+ or the same length but lexicographically less than
+ <em>choice</em>, set <em>choice</em> to <em>curie</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>choice</em> is not <tref>null</tref>, return <em>choice</em>.
+ </li>
+ <li>
+ At this point, there is no <tref>compact IRI</tref> that <em>iri</em>
+ can be compacted to, so if <em>vocabRelative</em> equals
+ <tref>true</tref> and <tref>active context</tref> has a
+ <tref>vocabulary mapping</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>iri</em> begins with the
+ <tref title="vocabulary mapping">vocabulary mapping's</tref> value
+ but is longer, then initialize <em>suffix</em> to the substring
+ of <em>iri</em> that does not match. If <em>suffix</em> does not
+ have a <tref>term definition</tref> in <tref>active context</tref>,
+ then return <em>suffix</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ There are no <tref>compaction</tref> options for <em>iri</em> so
+ return <em>iri</em> as is.
+ </li>
+</ol>
+
+</section>
+
+<!-- end of IRI Compaction -->
+</section>
+
+<section>
+<h2>Inverse Context Creation Subalgorithm</h2>
+
+<p>
+When there is more than one <tref>term</tref> that could be chosen
+to compact an <tref>IRI</tref>, we want to ensure that our <tref>term</tref>
+selection is both deterministic and not unexpected, representing the most
+context-appropriate choice whilst taking into consideration algorithmic
+complexity.
+</p>
+
+<p>
+In order to make <tref>term</tref> selections the concept of an
+<tref>inverse context</tref> is introduced. An <tdef>inverse context</tdef>
+is essentially a reverse lookup table that maps
+<tref title="container mapping">container mappings</tref>,
+<tref title="type mapping">type mappings</tref>, and
+<tref title="language mapping">language mappings</tref> to a simple
+<tref>term</tref> and, if applicable, an <tref>array</tref> of potential
+<tref>property generator</tref> <tref title="term">terms</tref> for
+a given <tref>active context</tref>. A <tref>inverse context</tref> only
+needs to be generated for an <tref>active context</tref> if it is being
+used for <tref>compaction</tref>.
+</p>
+
+<p>
+To make use of an <tref>inverse context</tref>, a list of preferred
+<tref title="container mapping">container mappings</tref> and the
+<tref>type mapping</tref> or <tref>language mapping</tref> are gathered
+for a particular value associated with an <tref>IRI</tref>. These parameters
+are then fed to the <a href="#term-selection">Term Selection</a>
+subalgorithm, which will find the <tref>term</tref> that most appropriately
+matches the value's mappings.
+</p>
+
+<section>
+<h3>Problem</h3>
+
+An <tref>inverse context</tref> must be created for the given
+<tref>active context</tref>.
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+To create an <tref>inverse context</tref> for a given
+<tref>active context</tref>, each <tref>term</tref> in the
+<tref>active context</tref> is visited, ordered by length, shortest
+first (ties are broken by choosing the lexicographically least
+<tref>term</tref>). For each <tref>term</tref>, an entry is added to
+the <tref>inverse context</tref> for each possible combination of
+<tref>container mapping</tref> and <tref>type mapping</tref>
+or <tref>language mapping</tref> that would legally match the
+<tref>term</tref>. Illegal matches include differences between a
+value's <tref>type mapping</tref> or <tref>language mapping</tref> and
+that of the <tref>term</tref>. If a <tref>term</tref> has no
+<tref>container mapping</tref>, <tref>type mapping</tref>, or
+<tref>language mapping</tref> (or some combination of these), then it
+will have an entry in the <tref>inverse context</tref> using the special
+key <code>@none</code>. This allows the
+<a href="#term-selection">Term Selection</a> subalgorithm to fall back
+to choosing more generic <tref title="term">terms</tref> when a more
+specificly-matching <tref>term</tref> is not available for a particular
+<tref>IRI</tref> and value combination.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+The algorithm takes one required input: the <tref>active context</tref> that
+the <tref>inverse context</tref> is being created for.
+</p>
+
+<ol class="algorithm">
+ <li>
+ Initialize <em>result</em> to an empty <tref>JSON object</tref>.
+ <li>
+ Initialize <em>defaultLanguage</em> to <code>@none</code>. If the
+ <tref>active context</tref> has a <tref>default language</tref>, then
+ set <em>defaultLanguage</em> to it.
+ </li>
+ <li>
+ For each key <tref>term</tref> and value <term>term definition</tref> in
+ the <tref>active context</tref>, ordered by shortest <tref>term</tref>
+ first (breaking ties by choosing the lexicographically least
+ <tref>term</tref>):
+ <ol class="algorithm">
+ <li>
+ If the <tref>term definition</tref> is <tref>null</tref>, then
+ <tref>term</tref> cannot be selected during <tref>compaction</tref>,
+ so continue to the next <tref>term</tref>.
+ </li>
+ <li>
+ Initialize <em>iris</em> to the value of the <tref>IRI mapping</tref>
+ for the <tref>term definition</tref>. If <em>iris</em> is not an
+ <tref>array</tref>, then set it to an <tref>array</tref> containing
+ only <em>iris</em>.
+ </li>
+ <li>
+ For each item <em>iri</em> in <em>iris</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>iri</em> is not a key in <em>result</em>, then add
+ a key-value pair where the key is <em>iri</em> and the value
+ is an empty <tref>JSON object</tref> to <em>result</em>.
+ </li>
+ <li>
+ Initialize <em>container map</em> to the value associated with
+ the <em>iri</em> key in <em>result</em>.
+ </li>
+ <li>
+ Initialize <em>container</em> to <code>@none</code>. If there
+ is a <tref>container mapping</tref> in
+ <tref>term definition</tref>, then set <em>container</em> to
+ its associated value.
+ </li>
+ <li>
+ If <em>container</em> is not a key in <em>container map</em>,
+ then initialize <em>typeOrLanguage map</em> to a new
+ <tref>JSON object</tref>. Add two key-value pairs to
+ <em>typeOrLanguage map</em>, where the first's key is
+ <code>@language</code> and its value is a new
+ <tref>JSON object</tref> and where the second's key is
+ <code>@type</code> and its value is a new
+ <tref>JSON object</tref>. Set the value of the key
+ <em>defaultLanguage</em> in the value associated with the
+ key <code>@language</code> in <em>typeOrLanguage map</em>
+ to a new <tref>JSON object</tref> containing a key-value pair
+ where the key is <code>term</code> and the value is
+ <tref>null</tref>.
+ </li>
+ <li>
+ Set <em>typeOrLanguage map</em> to the value associated with
+ the key <em>container</em> in <em>container map</em>.
+ </li>
+ <li>
+ If there is no <tref>type mapping</tref> in the
+ <tref>term definition</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>language map</em> to the value associated
+ with the key <code>@language</code> in
+ <em>typeOrLanguage map</em>.
+ </li>
+ <li>
+ If there is a <tref>language mapping</tref> in the
+ <tref>term definition</tref>:
+ <ol class="algorithm">
+ <li>
+ If the value of the <tref>language mapping</tref>
+ is <tref>null</tref> initialize <em>language</em>
+ to <code>@null</code>, otherwise initialize it to the
+ value.
+ </li>
+ <li>
+ If <em>language</em> is not a key in
+ <em>language map</em>, then add a key-value
+ pair to <em>language map</em> where the key is
+ <em>language</em> and the value is a new
+ <tref>JSON object</tref> with two key-value
+ pairs, where the first's key is <code>term</code>
+ and its value is <tref>null</tref>, and the second's
+ key is <code>propertyGenerators</code> and the
+ value is an empty <tref>array</tref>.
+ </li>
+ <li>
+ Initialize <em>entry</em> to the value associated with
+ the key <em>language</em> in <em>language map</em>.
+ </li>
+ <li>
+ If <tref>term definition</tref> is a
+ <tref>property generator</tref>, append the
+ <tref>term</tref> to the <tref>array</tref> associated
+ with the <code>propertyGenerators</code> key in
+ <em>entry</em>.
+ </li>
+ <li>
+ Otherwise, if the value associated with the key
+ <code>term</code> in <em>entry</em> is <tref>null</tref>,
+ set it to the <tref>term</tref>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise:
+ <ol class="algorithm">
+ <li>
+ If <em>defaultLanguage</em> is not a key in
+ <em>language map</em>, then add a key-value
+ pair to <em>language map</em> where the key is
+ <em>defaultLanguage</em> and the value is a new
+ <tref>JSON object</tref> with two key-value
+ pairs, where the first's key is <code>term</code>
+ and its value is <tref>null</tref>, and the second's
+ key is <code>propertyGenerators</code> and the
+ value is an empty <tref>array</tref>.
+ </li>
+ <li>
+ Initialize <em>entry</em> to the value associated with
+ the key <em>defaultLanguage</em> in <em>language map</em>.
+ </li>
+ <li>
+ If <tref>term definition</tref> is a
+ <tref>property generator</tref>, append the
+ <tref>term</tref> to the <tref>array</tref> associated
+ with the <code>propertyGenerators</code> key in
+ <em>entry</em>.
+ </li>
+ <li>
+ Otherwise, if the value associated with the key
+ <code>term</code> in <em>entry</em> is <tref>null</tref>,
+ set it to the <tref>term</tref>.
+ </li>
+ <li>
+ If <code>@none</code> is not a key in
+ <em>language map</em>, then add a key-value
+ pair to <em>language map</em> where the key is
+ <code>@none</code> and the value is a new
+ <tref>JSON object</tref> with two key-value
+ pairs, where the first's key is <code>term</code>
+ and its value is <tref>null</tref>, and the second's
+ key is <code>propertyGenerators</code> and the
+ value is an empty <tref>array</tref>.
+ </li>
+ <li>
+ Set <em>entry</em> to the value associated with
+ the key <code>@none</code> in <em>language map</em>.
+ </li>
+ <li>
+ If <tref>term definition</tref> is a
+ <tref>property generator</tref>, append the
+ <tref>term</tref> to the <tref>array</tref> associated
+ with the <code>propertyGenerators</code> key in
+ <em>entry</em>.
+ </li>
+ <li>
+ Otherwise, if the value associated with the key
+ <code>term</code> in <em>entry</em> is <tref>null</tref>,
+ set it to the <tref>term</tref>.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ If there is no <tref>language mapping</tref> in the
+ <tref>term definition</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>type map</em> to the value associated
+ with the key <code>@type</code> in
+ <em>typeOrLanguage map</em>.
+ </li>
+ <li>
+ If there is a <tref>type mapping</tref> in the
+ <tref>term definition</tref> then initialize <em>type</em>
+ to its value, otherwise initialize it to
+ to <code>@none</code>.
+ </li>
+ <li>
+ If <em>type</em> is not a key in <em>type map</em>, then
+ add a key-value pair to <em>type map</em> where the key is
+ <em>type</em> and the value is a new <tref>JSON object</tref>
+ with two key-value pairs, where the first's key is
+ <code>term</code> and its value is <tref>null</tref>, and the
+ second's key is <code>propertyGenerators</code> and the
+ value is an empty <tref>array</tref>.
+ </li>
+ <li>
+ Initialize <em>entry</em> to the value associated with
+ the key <em>type</em> in <em>type map</em>.
+ </li>
+ <li>
+ If <tref>term definition</tref> is a
+ <tref>property generator</tref>, append the
+ <tref>term</tref> to the <tref>array</tref> associated
+ with the <code>propertyGenerators</code> key in
+ <em>entry</em>.
+ </li>
+ <li>
+ Otherwise, if the value associated with the key
+ <code>term</code> in <em>entry</em> is <tref>null</tref>,
+ set it to the <tref>term</tref>.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ Return <em>result</em>.
+ </li>
+</ol>
+
+</section>
+
+<!-- end of Inverse Context Creation subalgorithm -->
+</section>
+
+<section>
+<h2>Term Selection Subalgorithm</h2>
+
+<p>
+This subalgorithm, invoked via the
+<a href="#iri-compaction-algorithm">IRI Compaction</a> algorithm, makes use
+of an <tref title="active context">active context's</tref>
+<tref>inverse context</tref> to find the <tref>term</tref> that is best
+used to <tref title="compaction">compact</tref> an <tref>IRI</tref>. Other
+information about a value associated with the <tref>IRI</tref> is given,
+including which <tref title="container mapping">container mappings</tref>
+and which <tref>type mapping</tref> or <tref>language mapping</tref> would
+be best used to express the value.
+</p>
+
+<section>
+<h3>Problem</h3>
+
+An <tref>IRI</tref> with an associated <em>value</em> should be compacted
+to the most appropriate <tref>term</tref> in the <tref>active context</tref>.
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+The <tref title="inverse context">inverse context's</tref> entry for
+the <tref>IRI</tref> will be first searched according to the preferred
+<tref title="container mapping">container mappings</tref>, in the order
+that they are given. Amongst <tref title="term">terms</tref> with a matching
+<tref>container mapping</tref>, preference will be given to those
+with a matching <tref>type mapping</tref> or <tref>language mapping</tref>,
+over those without a <tref>type mapping</tref> or
+<tref>language mapping</tref>. If there is no <tref>term</tref>
+with a matching <tref>container mapping</tref> then the <tref>term</tref>
+without a <tref>container mapping</tref> that matches the given
+<tref>type mapping</tref> or <tref>language mapping</tref> is selected. If
+there is still no selected <tref>term</tref>, then a <tref>term</tref>
+with no <tref>type mapping</tref> or <tref>language mapping</tref> will
+be selected if available. No <tref>term</tref> will be selected that
+has a conflicting <tref>type mapping</tref> or <tref>language mapping</tref>.
+Ties between <tref title="term">terms</tref> that have the same
+mappings are resolved by first choosing the shortest terms, and then by
+choosing the lexicographically least term. Note that these ties are
+resolved automatically because they were previously resolved when the
+<a href="#inverse-context-creation">Inverse Context Creation algorithm</a>
+was used to create the <tref>inverse context</tref>.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+This subalgorithm has seven required inputs. They are:
+an <tref>active context</tref>, an <tref>IRI</tref> <em>iri</em>,
+a <em>value</em> associated with the <tref>IRI</tref>, the expanded
+<em>parent</em> element for <em>value</em> (which may be a
+<tref>JSON object</tref>, an <tref>array</tref>, or <tref>null</tref>), an
+<tref>array</tref> <em>containers</em> that represents ordered list of
+preferred <tref title="container mapping">container mappings</tref>, a
+<tref>string</tref> <em>typeOrLanguage</em> that indicates whether
+to look for a <tref>term</tref> with a matching <tref>type mapping</tref>
+or <tref>language mapping</tref>, and a <tref>string</tref>
+<em>typeOrLanguageValue</em> with the associated value for the
+<tref>type mapping</tref> or <tref>language mapping</tref> to look for.
+</p>
+
+<ol class="algorithm">
+ <li>
+ Append <code>@none</code> to <em>containers</em>. This represents
+ the non-existence of a <tref>container mapping</tref>, and it will
+ be the last <tref>container mapping</tref> value to be checked as it
+ is the most generic.
+ </li>
+ <li>
+ Initialize <em>container map</em> to the value associated with
+ <em>iri</em> in the <tref>inverse context</tref>.
+ </li>
+ <li>
+ If <em>typeOrLanguageValue</em> is <tref>null</tref>, set it to
+ <code>@null</code>. This is the key underwhich <tref>null</tref> values
+ are stored in the <tref>inverse context</tref> <em>entry</em>.
+ </li>
+ <li>
+ Initialize <em>preferred values</em> to an <tref>array</tref> containing
+ <em>typeOrLangageValue</em> and <code>@none</code>, in that order. This
+ <tref>array</tref> indicates, in order, the preferred values for
+ a <tref title="term">term's</tref> <tref>type mapping</tref> or
+ <tref>language mapping</tref>.
+ </li>
+ <li>
+ Initialize <em>selected term</em> to <tref>null</tref>.
+ </li>
+ <li>
+ For each item <em>container</em> in <em>containers</em> while
+ <em>selected term</em> is <tref>null</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>container</em> is not a key in <em>container map</em>, then
+ there is no <tref>term</tref> with a matching
+ <tref>container mapping</tref> for it, so continue to the next
+ <em>container</em>.
+ </li>
+ <li>
+ Initialize <em>typeOrLanguage map</em> to the value associated
+ with <em>container</em> in <em>container map</em>.
+ </li>
+ <li>
+ Initialize <em>typeOrLanguageValue map</em> to the value associated
+ with <em>typeOrLanguage</em> in <em>typeOrLanguage map</em>.
+ </li>
+ <li>
+ For each <em>item</em> in <em>preferred values</em> while
+ <em>selected term</em> is <tref>null</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>item</em> is not a key in <em>typeOrLanguageValue map</em>,
+ then there is no <tref>term</tref> with a matching
+ <tref>type mapping</tref> or <tref>language mapping</tref>,
+ so continue to the next <em>item</em>.
+ </li>
+ <li>
+ Initialize <em>termInfo</em> to the value associated with
+ <em>item</em> in <em>typeOrLanguageValue map</em>.
+ </li>
+ <li>
+ If <em>parent</em> is a <tref>JSON object</tref>,
+ then for each <tref>property generator</tref> <tref>term</tref>
+ <em>propertyGeneratorTerm</em> in <em>termInfo</em> while
+ <em>selected term</em> is <tref>null</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>iris</em> to the value of the
+ <tref>IRI mapping</tref> for <em>propertyGeneratorTerm</em>
+ in the <tref>active context</tref>.
+ </li>
+ <li>
+ Initialize <em>match</em> to <tref>true</tref>.
+ </li>
+ <li>
+ For each item <em>propertyGeneratorIri</em> in <em>iris</em>
+ while <em>match</em> equals <tref>true</tref>:
+ <ol class="algorithm">
+ <li>
+ If <em>propertyGeneratorIri</em> is not a key in
+ <em>parent</em>, set <em>match</em> to <tref>false</tref>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>match</em> equals <tref>true</tref>, then set
+ <em>selected term</em> to <em>propertyGeneratorTerm</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>selected term</em> is <tref>null</tref>, then no
+ <tref>property generator</tref> match was found, so set
+ <em>selected term</em> to the non-<tref>property generator</tref>
+ <tref>term</tref> in <em>termInfo</em>, which may be
+ <tref>null</tref>.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>
+ Return <em>selected term</em>.
+ </li>
+</ol>
+
+</section>
+
+<!-- end of Term Selection subalgorithm -->
+</section>
+
+<section>
+<h2>Value Compaction</h2>
+
+<p>
+<tref>Expansion</tref> transforms all values into <tref>expanded form</tref>
+in JSON-LD. This algorithm performs the opposite operation, transforming
+a value into <tdef>compacted form</tdef>. This algorithm compacts a
+value according to the <tref>term definition</tref> in the given
+<tref>active context</tref> that is associated with the value's associated
+<tref>active property</tref>.
+</p>
+
+<section>
+<h3>Problem</h3>
+
+A <em>value</em> associated with an <tref>active property</tref> must
+be <tref title="compaction">compacted</tref> to <tref>compacted form</tref>.
+
+</section>
+
+<section>
+<h3>General Solution</h3>
+
+<p>
+The <em>value</em> to compact either contains the key <code>@value</code>
+or the key <code>@id</code>.
+</p>
+
+<p>
+We start with the former case, first trying to compact the
+<em>value</em> into just the value associated with its
+<code>@value</code> key. This can be done if the <em>value</em> is not
+going to be contained by an <code>@index</code> container and if the
+<tref>active property</tref> has a matching <tref>type mapping</tref> or
+<tref>language mapping</tref>. It can also be done if <code>@value</code>
+is the only key in <em>value</em> and either its associated value is
+not a <tref>string</tref>, there's no <tref>default language</tref>, or
+there's an explicit <tref>null</tref> <tref>language mapping</tref> for
+the <tref>active property</tref>.
+</p>
+
+<p>
+If we couldn't do the above optimal compaction, then we simply replace
+<tref title="keyword">keywords</tref> with aliases and compact any
+<tref title="IRI">IRIs</tref>.
+</p>
+
+<p>
+For the latter case, where the key <code>@id</code> appears in <em>value</em>,
+we compact the associated value using the
+<a href="#iri-compaction-algorithm">IRI Compaction</a> algorithm, and
+use its value if the <tref>type mapping</tref> associated with the
+<tref>active property</tref> is <code>@id</code> or the expanded value for
+the <tref>active property</tref> is <code>@graph</code>. Otherwise, we
+replace the <code>@id</code> key with its alias and its associated value
+with its compacted version.
+</p>
+
+</section>
+
+<section>
+<h3>Algorithm</h3>
+
+<p>
+This algorithm has three required inputs: an <tref>active context</tref>, an
+an <tref>active property</tref>, and a <em>value</em> to be compacted.
+</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>value</em> contains the key <code>@value</code>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>preserveIndex</em> to <tref>false</tref>. If
+ <code>@index</code> is a key in <em>value</em> and
+ <tref>active property</tref> does not have a
+ <tref>container mapping</tref> in <tref>active context</tref> that
+ equals <code>@index</code>, set <em>preserveIndex</em> to
+ <tref>true</tref>.
+ </li>
+ <li>
+ If <em>preserveIndex</em> equals <tref>false</tref> and either
+ <em>value</em> has a <code>@type</code> key with a value that
+ matches <tref title="active property">active property's</tref>
+ <tref>type mapping</tref> in <tref>active context</tref> or
+ <em>value</em> has a <code>@language</code> key with a value that
+ matches <tref title="active property">active property's</tref>
+ <tref>language mapping</tref> in <tref>active context</tref>, then
+ return the value associated with the <code>@value</code> key in
+ <em>value</em>.
+ </li>
+ <li>
+ If <code>@value</code> is the only key in <em>value</em> or
+ <em>preserveIndex</em> equals <tref>false</tref> and either
+ there is no <tref>default language</tref> in
+ <tref>active context</tref>, the value associated with the
+ <code>@value</code> key in <em>value</em> is not a
+ <tref>string</tref>, or <tref>active property</tref>
+ has a <tref>null</tref> <tref>language mapping</tref> in
+ <tref>active context</tref>, then return the value
+ associated with the <code>@value</code> key in <em>value</em>.
+ </li>
+ <li>
+ Initialize <em>result</em> to an empty <tref>JSON object</tref>.
+ </li>
+ <li>
+ If <em>preserveIndex</em> equals <tref>true</tref>, then add
+ a key-value pair to <em>result</em> where the key is the result
+ using the <a href="#iri-compaction-algorithm">IRI compaction</a>
+ algorithm, passing <tref>active context</tref> and
+ <code>@index</code> for <em>iri</em>, and the value is
+ the value associated with the <code>@index</code> key in
+ <em>value</em>.
+ </li>
+ <li>
+ If <em>value</em> contains the key <code>@type</code>, then add
+ a key-value pair to <em>result</em> where the key is the result
+ using the <a href="#iri-compaction-algorithm">IRI compaction</a>
+ algorithm, passing <tref>active context</tref> and
+ <code>@type</code> for <em>iri</em>, and the value is the result
+ of using the <a href="#iri-compaction-algorithm">IRI compaction</a>
+ algorithm, passing <tref>active context</tref>, the value associated
+ with the <code>@type</code> key in <em>value</em> for <em>iri</em>,
+ <tref>true</tref> for <em>vocabRelative</em>, and
+ <tref>true</tref> for <em>documentRelative</em>.
+ </li>
+ <li>
+ Otherwise, if <em>value</em> contains the key <code>@language</code>,
+ then add a key-value pair to <em>result</em> where the key is the
+ result using the
+ <a href="#iri-compaction-algorithm">IRI compaction</a>
+ algorithm, passing <tref>active context</tref> and
+ <code>@language</code> for <em>iri</em>, and the value is the
+ value associated with the <code>@language</code> key in
+ <em>value</em>.
+ </li>
+ <li>
+ Add a key-value pair to <em>result</em> where the key is the result
+ using the <a href="#iri-compaction-algorithm">IRI compaction</a>
+ algorithm, passing <tref>active context</tref> and
+ <code>@value</code> for <em>iri</em>, and the value is the value
+ associated with the <code>@value</code> key in <em>value</em>.
+ </li>
+ <li>
+ Return <em>result</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, <em>value</em> must contain the single key <code>@id</code>.
+ Initialize <em>expanded property</em> to the result of using the
+ <a href="#iri-expansion">IRI Expansion</a> algorithm, passing
+ passing <tref>active context</tref> and <em>value</em>.
+ </li>
+ <li>
+ Initialize <em>term</em> to the result of using the
+ <a href="#iri-compaction-algorithm">IRI compaction</a> algorithm,
+ passing <tref>active context</tref>, the value associated with
+ the key <code>@id</code> in <em>value</em> for <em>iri</em>,
+ and <tref>true</tref> for <em>documentRelative</em>.
+ </li>
+ <li>
+ If <tref>active property</tref> has a <tref>type mapping</tref> in
+ the <tref>active context</tref> that is equal to <code>@id</code> or
+ <em>expanded property</em> equals <code>@graph</code>, then return
+ <em>term</em>.
+ </li>
+ <li>
+ Initialize <em>result</em> to an empty <tref>JSON object</tref>. Add
+ a key-value pair to <em>result</em> where the key is the result of
+ using the <a href="#iri-compaction-algorithm">IRI compaction</a>
+ algorithm, passing <tref>active context</tref>, and <code>@id</code> for
+ <em>iri</em>, and the value is <em>term</em>.
+ </li>
+ <li>
+ Return <em>result</em>.
+ </li>
+</ol>
+
+</section>
+
+<!-- end of Value Compaction algorithm -->
+</section>
+
+<section>
+<h2>Find and Remove Property Generator Duplicates Subalgorithm</h2>
+
+<p>
+This algorithm checks if a specific value exists for all
+<tref title="IRI">IRIs</tref> associated with a
+<tref>property generator</tref> and, if so, it removes them.
+The algorithm takes five required inputs: an <tref>active context</tref>,
+<em>element</em>, <em>expanded property</em>, <em>value</em>, and
+<tref>active property</tref>.
+</p>
+
+<ol class="algorithm">
+ <li>
+ Initialize <em>iris</em> to the <tref>array</tref> associated with the
+ <tref>IRI mapping</tref> for <tref>active property</tref> in
+ <tref>active context</tref>.
+ </li>
+ <li>
+ For each <em>iri</em> in <em>iris</em>:
+ <ol class="algorithm">
+ <li>
+ If <em>iri</em> equals <em>expanded property</em>, then this
+ is the <em>iri</em> that is to be preserved, so continue to the next
+ <em>iri</em>.
+ </li>
+ <li>
+ Initialize <em>prospects</em> to the value associated with the
+ key that equals <em>iri</em> in <em>element</em>. This
+ <tref>array</tref> will be checked for a value that matches
+ the <tref>property generator</tref> <em>value</em>.
+ </li>
+ <li>
+ For each item <em>prospect</em> in <em>prospects</em>, until
+ a <tref>property generator</tref> duplicate is found for
+ <em>value</em>:
+ <ol class="algorithm">
+ <li>
+ Check to see if <em>prospect</em> and <em>value</em> are
+ <tref>property generator</tref> duplicates:
+ <ol class="algorithm">
+ <li>
+ If their types and values are equal, then they are duplicates.
+ </li>
+ <li>
+ Otherwise, if they are both
+ <tref title="JSON object">JSON objects</tref> that contain
+ the key <code>@value</code> and they both have the same
+ key-value pairs for the keys <code>@value</code>,
+ <code>@type</code>, <code>@language</code>, and
+ <code>@index</code>, then they are duplicates.
+ </li>
+ <li>
+ Otherwise, if they are both
+ <tref title="list object">list objects</tref> with the same
+ key-value pairs for the key <code>@index</code>, and the
+ <tref title="array">arrays</tref> associated with their
+ <code>@list</code> keys have the same length and their
+ corresponding items, by index, are duplicates, then they
+ are duplicates.
+ </li>
+ <li>
+ Otherwise, if they are both
+ <tref title="JSON object">JSON objects</tref> that contain
+ the key <code>@id</code> and the values associated with
+ those keys are equal, then they are duplicates.
+ </li>
+ <li>
+ Otherwise, they are not duplicates.
+ </li>
+ </ol>
+ </li>
+ <li>
+ If <em>prospect</em> and <em>value</em> are
+ <tref>property generator</tref> duplicates, then remove
+ <em>prospect</em> from <em>prospects</em> and, if
+ <em>prospects</em> is now empty, remove <em>iri</em>
+ from <em>element</em>.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+</ol>
+
+</section>
+
+<!-- FIXME -->
+<section>
+ <h2>Flattening Algorithm</h2>
+
+ <p>The algorithm takes two input variables, an <em>element</em> to flatten and a
+ <em>context</em> used to compact the flattened document.</p>
+
+ <ol class="algorithm">
+ <li>Expand <em>element</em> according the
+ <a href="#expansion-algorithm">Expansion algorithm</a>.</li>
+ <li>Generate a <em>nodeMap</em> according the
+ <a href="#node-map-generation">Node Map Generation algorithm</a>.</li>
+ <li>Let <em>defaultGraph</em> be the value of the <code>@default</code> member of
+ <em>nodeMap</em>; a <tref>JSON object</tref> representing the <tref>default graph</tref>.</li>
+ <li>For each other <em>graphName</em>-<em>graph</em> pair in <em>nodeMap</em>
+ perform the following steps:
+ <ol class="algorithm">
+ <li>If <em>defaultGraph</em> does not have a <em>graphName</em> member, create
+ one and initialize its value to a <tref>JSON object</tref> consisting of an
+ <code>@id</code> member whose value is set to <em>graphName</em>.</li>
+ <li>Add an <code>@graph</code> member set to an empty <tref>array</tref>
+ (referred to as <em>nodes</em>) to the <tref>JSON object</tref> which is the
+ value of the <em>graphName</em> member of <em>nodeMap</em>.</li>
+ <li>For each <em>id</em>-<em>node</em> pair in <em>graph</em> ordered by <em>id</em>,
+ add <em>node</em> to the <em>nodes</em> <tref>array</tref>.</li>
+ </ol>
+ </li>
+ <li>Initialize an empty <tref>array</tref> flattened.</li>
+ <li>For each <em>id</em>-<em>node</em> pair in <em>defaultGraph</em> ordered by <em>id</em>,
+ add <em>node</em> to <em>flattened</em>.</li>
+ <li>If <em>context</em> equals <tref>null</tref>, return <em>flattened</em>.</li>
+ <li>Otherwise, return the result of compacting <em>flattened</em> according the
+ <a href="#compaction-algorithm">Compaction algorithm</a> passing <em>context</em>
+ ensuring that the compaction result uses the <code>@graph</code> keyword (or its alias)
+ at the top-level, even if the context is empty or if there is only one element to
+ put in the <code>@graph</code> <tref>array</tref>. This ensures that the returned
+ document has a deterministic structure.</li>
+ </ol>
+</section>
+
+<!-- FIXME -->
+<section>
+ <h2>Node Map Generation</h2>
+
+ <p>This algorithm creates a <tref>JSON object</tref> <em>nodeMap</em> holding an indexed
+ representation of the <tref title="JSON-LD graph">graphs</tref> and <tref title="node">nodes</tref>
+ represented in the passed, expanded document. All <tref title="node">nodes</tref> that are not
+ uniquely identified by an IRI get assigned a (new) <tref>blank node identifier</tref>.
+ The resulting <em>nodeMap</em> will have a member for every graph in the document whose
+ value is another object with a member for every <tref>node</tref> represented in the document.
+ The default graph is stored under the <code>@default</code> member, all other graphs are
+ stored under their graph name</tref>.</p>
+
+ <p>The algorithm takes as input an expanded JSON-LD document <em>element</em> and a reference to
+ a <tref>JSON object</tref> <em>nodeMap</em>. Furthermore it has the optional parameters
+ <tref>active graph</tref> (which defaults to <code>@default</code>), an <tref>active subject</tref>,
+ <tref>active property</tref>, and a reference to a <tref>JSON object</tref> <em>list</em>. The
+ <em>nodeMap</em> must be initialized to a <tref>JSON object</tref> consisting of a single member
+ whose name corresponds with <tref>active graph</tref> and whose value is an empty <tref>JSON object</tref>.</p>
+
+ <ol class="algorithm">
+ <li>If <em>element</em> is an array, process each entry in <em>element</em> recursively, using this algorithm
+ and return.</li>
+ <li>Otherwise <em>element</em> is a <tref>JSON object</tref>. Let <em>activeGraph</em> be the
+ <tref>JSON object</tref> which is the value of the <tref>active graph</tref> member of
+ <em>nodeMap</em>.</li>
+ <li>If it has an <code>@type</code> member, perform for each <em>item</em> the following
+ steps:
+ <ol class="algorithm">
+ <li>If <em>item</em> is a <tref>blank node identifier</tref>, replace it with a
+ <a href="#generate-blank-node-identifier">new blank node identifier</a>.</li>
+ <li>If <em>activeGraph</em> has no member <em>item</em>, create it and initialize its
+ value to a <tref>JSON object</tref> consisting of a single member <code>@id</code>
+ with the value <em>item</em>.</li>
+ </ol>
+ </li>
+ <li>If <em>element</em> has an <code>@value</code> member, perform the following steps:
+ <ol class="algorithm">
+ <li>If no <em>list</em> has been passed, merge <em>element</em> into the
+ <tref>active property</tref> member of the <tref>active subject</tref> in
+ <em>activeGraph</em>.</li>
+ <li>Otherwise, append <em>element</em> to the <code>@list</code> member of <em>list</em>.</li>
+ </ol>
+ </li>
+ <li>Otherwise, if <em>element</em> has an <code>@list</code> member, perform
+ the following steps:
+ <ol class="algorithm">
+ <li>Initialize a new <tref>JSON object</tref> <em>result</em> having a single member
+ <code>@list</code> whose value is initialized to an empty <tref>array</tref>.</li>
+ <li>Recursively call this algorithm passing the value of <em>element's</em>
+ <code>@list</code> member as new <em>element</em> and <em>result</em> as <em>list</em>.</li>
+ <li>If <tref>active property</tref> equals <tref>null</tref> or <code>@graph</code>,
+ <a href="#generate-blank-node-identifier">generate a blank node identifier</a> <em>id</em>
+ and store <em>result</em> as value of the member <em>id</em> in <em>activeGraph</em>.</li>
+ <li>Otherwise, add <em>result</em> to the the value of the <tref>active property</tref> member
+ of the <tref>active subject</tref> in <em>activeGraph</em>.</li>
+ </ol>
+ </li>
+ <li>Otherwise <em>element</em> is a <tref>node object</tref>, perform the following
+ steps:
+ <ol class="algorithm">
+ <li>If <em>element</em> has an <code>@id</code> member, store its value in <em>id</em> and remove
+ the member from <em>element</em>. If <em>id</em> is a <tref>blank node identifier</tref>, replace it with
+ <a href="#generate-blank-node-identifier">a new blank node identifier</a>.</li>
+ <li>Otherwise <a href="#generate-blank-node-identifier">generate a new blank node identifier</a>
+ and store it as <em>id</em>.</li>
+ <li>If <em>activeGraph</em> does not contain a member <em>id</em>, create one and initialize
+ it to a <tref>JSON object</tref> consisting of a single member <code>@id</code> whose
+ value is set to <em>id</em>.</li>
+ <li>If <tref>active property</tref> is not <tref>null</tref>, perform the following steps:
+ <ol class="algorithm">
+ <li>Create a new <tref>JSON object</tref> <em>reference</em> consisting of a single member
+ <code>@id</code> whose value is <em>id</em>.</li>
+ <li>If no <em>list</em> has been passed, merge <em>element</em> into the
+ <tref>active property</tref> member of the <tref>active subject</tref> in
+ <em>activeGraph</em>.</li>
+ <li>Otherwise, append <em>element</em> to the <code>@list</code> member of <em>list</em>.</li>
+ </ol>
+ </li>
+ <li>If <em>element</em> has an <code>@type</code> member, merge each value into the <code>@type</code>
+ of <tref>active subject</tref> in <em>activeGraph</em>. Then remove the <code>@type</code> member
+ from <em>element</em>.</li>
+ <li>If <em>element</em> has an <code>@annotation</code> member, set the <code>@annotation</code>
+ of <tref>active subject</tref> in <em>activeGraph</em> to its value. If such a member already
+ exists in <tref>active subject</tref> and has a different value, raise a
+ <code class="error">CONFLICTING_ANNOTATION</code> error. Otherwise continue and remove the
+ <code>@annotation</code> from <em>element</em>.</li>
+ <li>If <em>element</em> has an <code>@graph</code> member, recursively invoke this algorithm passing
+ the value of the <code>@graph</code> member as new <em>element</em> and <em>id</em> as new
+ <tref>active subject</tref>. Then remove the <code>@graph</code> member from <em>element</em>.</li>
+ <li>Finally for each <em>property</em>-<em>value</em> pair in <em>element</em> ordered by
+ <em>property</em> perform the following steps:
+ <ol class="algorithm">
+ <li>If no <em>property</em> member exists in the <tref>JSON object</tref> which is the
+ value of the <em>id</em> member of <em>activeGraph</em> create the member and initialize
+ its value to an empty <tref>array</tref>.</li>
+ <li>Recursively invoke this algorithm passing <em>value</em> as new <em>element</em>, <em>id</em>
+ as new <tref>active subject</tref>, and <em>property</em> as new <tref>active property</tref>.</li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+</section>
+
+<!-- FIXME -->
+<section>
+<h2>RDF Conversion Algorithms</h2>
+
+<p>
+This section describes algorithms to transform JSON-LD documents to an array
+of RDF <tref title="quad">quads</tref> and vice-versa. Note that many uses of
+JSON-LD may not require generation of RDF.
+</p>
+
+<p>
+The processing algorithms described in this section are provided in order to
+demonstrate how one might implement a JSON-LD to RDF processor. Conformant
+implementations are only required to produce the same type and number of
+<tref title="quad">quads</tref> but are not required to implement the
+algorithm exactly as described.
+</p>
+
+<section>
+<h3>Convert to RDF Algorithm</h3>
+
+<p>
+The algorithm below is designed for in-memory implementations with random
+access to <tref>JSON object</tref> elements.
+</p>
+
+<p>
+A conforming JSON-LD processor implementing RDF conversion MUST implement a
+processing algorithm that results in the same set of RDF
+<tref title="quad">quads</tref> that the following algorithm generates.
+</p>
+
+<p>
+The algorithm takes five input variables: an <em>element</em> to be converted,
+an <tref>active subject</tref>, an <tref>active property</tref>, a
+<tref>graph name</tref>, and an <tref>array</tref> <em>quads</em> of
+<tref title="quad">Quads</tref>. To begin, the <tref>active subject</tref>,
+<tref>active property</tref>, and <tref>graph name</tref>
+are set to <tref>null</tref>, <em>quads</em> is set to an empty
+<tref>array</tref>, and <em>element</em> is set to the result of
+performing the <a href="#expansion-algorithm">Expansion Algorithm</a> on the
+<tref>JSON-LD input</tref> which is expected to be a a well-formed JSON-LD
+document as defined in [[!JSON-LD]].
+</p>
+
+<p class="issue">This algorithm hasn't been updated to use [[!RDF-CONCEPTS]]
+yet.</p>
+<p class="issue">This algorithm needs some clarification on its details.</p>
+
+<ol class="algorithm">
+ <li>
+ If <em>element</em> is an <tref>array</tref>, then for each <em>item</em>
+ in <em>element</em> invoke this algorithm recursively, passing
+ <em>item</em> for <em>element</em>, <tref>active subject</tref>,
+ <tref>active property</tref>, <tref>graph name</tref>, and <em>quads</em>.
+ </li>
+ <li>
+ Otherwise, if <em>element</em> is a <tref>string</tref>, then
+ generate a <tref>quad</tref> using <tref>active subject</tref>,
+ <tref>active property</tref>, an <tref>IRI</tref> with the value
+ of <em>element</em> for <tref>RDF object</tref>, and
+ <tref>graph name</tref>. Append the <tref>quad</tref> to
+ <em>quads</em>.
+ </li>
+ <li>
+ Otherwise, if <em>element</em> is a <tref>list object</tref>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>list</em> to the result of the
+ <a href="#list-conversion">List Conversion</a> algorithm, passing
+ the value associated with the <code>@list</code> key.
+ </li>
+ <li>
+ Invoke this algorithm recursively, passing <em>list</em> for
+ <em>element</em>, <tref>active subject</tref>,
+ <tref>active property</tref>, <tref>graph name</tref>, and
+ <em>quads</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, if <em>element</em> is a <tref>JSON object</tref> that
+ contains the key <code>@value</code>:
+ <ol class="algorithm">
+ <li>
+ Initialize <em>value</em> to the value associated with the
+ <code>@value</code> key in <em>element</em>. Initialize
+ <em>datatype</em> to the value associated with the <code>@type</code>
+ key in <em>element</em>, or <tref>null</tref> if <em>element</em>
+ does not contain that key.
+ </li>
+ <li>
+ Otherwise, if <em>value</em> equals <tref>true</tref> or
+ <tref>false</tref>, then set <em>value</em> its
+ <tref>canonical lexical form</tref> as defined
+ in the section <a href="#data-round-tripping">Data Round Tripping</a>.
+ If <em>datatype</em> is <tref>null</tref>, set it to
+ <code>xsd:boolean</code>.
+ </li>
+ <li>
+ Otherwise, if <em>value</em> is a <tref>number</tref>, then set
+ <em>value</em> to its <tref>canonical lexical form</tref> as defined
+ in the section <a href="#data-round-tripping">Data Round Tripping</a>.
+ If <em>datatype</em> is <tref>null</tref>, set it to either
+ <code>xsd:integer</code> or <code>xsd:double</code>, depending
+ on if the value contains a fractional and/or an exponential
+ component.
+ </li>
+ <li>
+ Otherwise, if <em>datatype</em> is <tref>null</tref>, set it to
+ <code>xsd:string</code>.
+ </li>
+ <li>
+ Initialize <tref>active object</tref> using <em>value</em> and
+ <em>datatype</em>. If <em>element</em> has the key
+ <code>@language</code> and <em>datatype</em> equals
+ <code>xsd:string</code>, then add the value associated with the
+ <code>@language</code> key as the language of the
+ <tref>active object</tref>.
+ </li>
+ <li>
+ Generate a <tref>quad</tref> using <tref>active subject</tref>,
+ <tref>active property</tref>, <tref>active object</tref>, and
+ <tref>graph name</tref>. Append the <tref>quad</tref> to
+ <em>quads</em>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Otherwise, <em>element</em> must represent the next
+ <tref>RDF subject</tref> to be processed:
+ <ol class="algorithm">
+ <li>
+ If <em>element</em> contains the key <code>@id</code>, then
+ initialize <em>id</em> to its associated value, otherwise initialize
+ it to <tref>null</tref>. If <em>element</em> is a
+ <tref>blank node</tref>, then set <em>id</em> to the result of
+ using the
+ <a href="#generate-blank-node-identifier">Generate Blank Node Identifier</a>
+ algorithm, passing <em>id</em> for <em>identifier</em>.
+ </li>
+ <li>
+ Initialize <tref>active object</tref> to an <tref>IRI</tref> or
+ <tref>blank node</tref>, as appropriate, with the value of
+ <em>element</em>.
+ </li>
+ <li>
+ If <tref>active subject</tref> is not <tref>null</tref>, then
+ generate a <tref>quad</tref> using <tref>active subject</tref>,
+ <tref>active property</tref>, <tref>active object</tref>, and
+ <tref>graph name</tref>. Append the <tref>quad</tref> to
+ <em>quads</em>.
+ </li>
+ <li>
+ Set <tref>active subject</tref> to <tref>active object</tref>.
+ </li>
+ <li>
+ For each <em>key</em>-<em>value</em> pair in <em>element</em>,
+ sorted lexicographically by <em>key</em>:
+ <ol class="algorithm">
+ <li>
+ Set <tref>active property</tref> to <em>value</em>.
+ </li>
+ <li>
+ If <tref>active property</tref> equals <code>@graph</code>, then
+ use this algorithm recursively, passing <em>value</em> for
+ <em>element</em>, <tref>null</tref> for
+ <tref>active subject</tref> and <tref>active property</tref>,
+ <tref>active subject</tref> for <tref>graph name</tref>,
+ and <em>quads</em>. Then continue to the next <em>key</em>.
+ </li>
+ <li>
+ If <em>key</em> equals <code>@type</code>, then set
+ <tref>active property</tref> to <code>rdf:type</code>.
+ </li>
+ <li>
+ If <tref>active property</tref> is a <tref>keyword</tref>,
+ then continue to the next <em>key</em>.
+ </li>
+ <li>
+ Use this algorithm recursively, passing <em>value</em> for
+ <em>element</em>, <tref>active subject</tref>,
+ <tref>active property</tref>, <tref>graph name</tref>,
+ and <em>quads</em>.
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+</ol>
+
+</section>
+
+<section id="list-conversion">
+<h3>List Conversion</h3>
+
+<p>
+List Conversion is the process of taking an <tref>array</tref> of values and
+converting it to a JSON-LD linked list of
+<tref title="JSON object">JSON objects</tref>. Each element of the list is
+linked by using <code>rdf:first</code> and <code>rdf:rest</code>, terminating
+the list with <code>rdf:nil</code>.
+</p>
+
+<p>
+The algorithm takes a single input: an <tref>array</tref> <em>list</em>.
+</p>
+
+<div class="note">This algorithm does not support lists containing lists.</div>
+
+<ol class="algorithm">
+ <li>
+ Initialize <em>length</em> to the length of <em>list</em>.
+ </li>
+ <li>
+ Initialize <em>tail</em> to a <tref>JSON object</tref> containing
+ one key-value pair, (<code>@id</code>-<code>rdf:nil</code>).
+ </li>
+ <li>
+ Starting <em>itr</em> at <em>length</em> minus <code>1</code>, loop
+ until <em>itr</em> is <code>0</code> (inclusive):
+ <ol class="algorithm">
+ <li>
+ Initialize <em>element</em> to an empty <tref>JSON object</tref>.
+ </li>
+ <li>
+ Add a key-value pair to <em>element</em> where the key is
+ <code>rdf:first</code> and the value is an <tref>array</tref>
+ containing the value associated with the index <em>itr</em>
+ in <em>list</em>.
+ </li>
+ <li>
+ Add a key-value pair to <em>element</em> where the key is
+ <code>rdf:rest</code> and the value is an <tref>array</tref>
+ containing <em>tail</em>.
+ </li>
+ <li>
+ Set <em>tail</em> to <em>element</em>.
+ </li>
+ <li>
+ Decrement <em>itr</em> by <code>1</code>.
+ </li>
+ </ol>
+ </li>
+ <li>
+ Return <em>tail</em>.
+ </li>
+</ol>
+
+</section>
+
+<!-- FIXME -->
+<section>
+ <h2>Convert from RDF Algorithm</h2>
+ <p>In some cases, data exists natively in the form of triples or or <tref title="quad">quads</tref>;
+ for example, if the data was originally represented in an RDF graph or triple/quad store. This
+ algorithm is designed to simply translate an array of <tref title="quad">quads</tref> into a
+ JSON-LD document.</p>
+ <p>When expanding <tref title="typed value">typed values</tref> having a datatype of <code>xsd:string</code>,
+ the <code>@type</code> MUST NOT be set to <code>xsd:string</code> and the resulting value
+ MUST have only an <code>@value</code> property.</p>
+
+ <p>The conversion algorithm takes a single parameter <em>input</em> in the form of an
+ array of <tref>Quad</tref> representations.</p>
+
+ <p class="issue">This algorithm hasn't been updated to use [[!RDF-CONCEPTS]] yet.</p>
+
+ <ol class="algorithm">
+ <li id="new_graph">Construct <em>defaultGraph</em> as a <tref>JSON object</tref>
+ containing <em>nodes</em> and <em>listMap</em>, each an empty <tref>JSON object</tref>.</li>
+ <li>Construct <em>graphs</em> as a <tref>JSON object</tref> containing <em>defaultGraph</em>
+ identified by
+ an empty <tref>string</tref>.</li>
+ <li>For each <tref>quad</tref> in <em>input</em>:
+ <ol class="algorithm">
+ <li>Set <em>graph</em> to the entry in <em>graphs</em> identified
+ by <em>name</em>, initializing it to a new entry using the mechanism
+ described in <a href="#new_graph">Step 1</a>.</li>
+ <li>If <em>property</em> is <code>rdf:first</code>,
+ use the entry in <em>graph.listMap</em> indexed by <em>subject</em>,
+ initializing it to a new <tref>JSON object</tref> if nesessary. Represent
+ <em>object</em> in <tref>expanded form</tref>, as described in
+ <a href="#value-expansion">Value Expansion</a>. Add the
+ resulting <em>object representation</em> to the entry indexed by
+ <em>first</em>, and skip to the next <tref>quad</tref>.</li>
+ <li>If <em>property</em> is <code>rdf:rest</code>:
+ <ol class="algorithm">
+ <li>If <em>object</em> is a <tref>blank node</tref>, use the entry in
+ <em>graph.listMap</em> indexed by <em>subject</em>, initializing it
+ to a new <tref>JSON object</tref> if necessary. Add the <em>nominalValue</em> of
+ <em>object</em> to the entry indexed by <em>rest</em>.
+ </li>
+ <li>Skip to the next <tref>quad</tref>.</li>
+ </ol>
+ </li>
+ <li>If <em>name</em> is not <tref>null</tref>, and <em>defaultGraph.nodes</em>
+ does not contain an entry for <em>name</em>,
+ create a new entry for <em>name</em> from a new
+ <tref>JSON object</tref> with key/value pair of <code>@id</code> and
+ <em>name</em> represented in <tref>expanded IRI form</tref>.</li>
+ <li>Set <em>value</em> as the entry from <em>graph.nodes</em> for
+ <em>subject</em>, initializing it to a new
+ <tref>JSON object</tref> with key/value pair of <code>@id</code> and
+ <em>subject</em> represented in <tref>expanded IRI form</tref> if necessary.</li>
+ <li>If <em>property</em> is <code>rdf:type</code>, <em>object</em> is not a <tref>JSON-LD value</tref>, and the
+ <code class="idlMemberName"><a href="#widl-JsonLdOptions-useRdfType">useRdfType</a></code>
+ option is not present or <tref>false</tref>:
+ <ol class="algorithm">
+ <li>Append <em>object</em> represented in <tref>expanded IRI form</tref> to the array value for the
+ key <code>@type</code>, creating an entry in <em>value</em> if necessary.</li>
+ </ol>
+ </li>
+
+ <li>Otherwise, if <em>object</em> is a <tref>typed value</tref> and the
+ <code class="idlMemberName"><a href="#widl-JsonLdOptions-useNativeTypes">useNativeTypes</a></code>
+ option is set to <tref>true</tref>:
+ <ol class="algorithm">
+ <li>Generate a <em>converted value</em>:
+ <ol class="algorithm">
+ <li>If the literal's type is <code>xsd:boolean</code>, the
+ <em>converted value</em> is <tref>true</tref> if the literal
+ matches the value <code>true</code> or <code>false</code> if
+ the literal matches the value <code>false</code>.</li>
+ <li>If the literal's type is <code>xsd:integer</code> or
+ <code>xsd:double</code>, try to convert the literal to a
+ JSON <tref>number</tref>. If the conversion is successful,
+ store the result in <em>converted value</em>, otherwise
+ set <em>converted value</em> to <em>value</em>.</li>
+ <li>Otherwise, do not perform a conversion. Set
+ the <em>converted value</em> to the <em>value</em>.</li>
+ </ol>
+ </li>
+ <li>Append the <em>converted value</em> to the array value for the
+ key, creating an entry in <em>value</em> if necessary.</li>
+ </ol>
+ </li>
+
+ <li>Otherwise, if <em>object</em> is <code>rdf:nil</code>:
+ <ol class="algorithm">
+ <li>Let <em>key</em> be <em>property</em> expressed in <tref>expanded IRI form</tref>.</li>
+ <li>Append an empty <code>@list</code> representation to the array value for
+ <em>key</em>, creating an entry in <em>value</em> if necessary.</li>
+ </ol>
+ </li>
+ <li>Otherwise,
+ <ol class="algorithm">
+ <li>Let <em>key</em> be <em>property</em> expressed in <tref>expanded IRI form</tref> and let
+ <em>object representation</em>
+ be <em>object</em> represented in <tref>expanded form</tref> as described in
+ <a href="#value-expansion">Value Expansion</a>.</li>
+ <li>If <em>object</em> is a <tref>blank node</tref>,
+ use the entry in <em>graph.listMap</em> indexed by <em>object</em>,
+ initializing it to a new <tref>JSON object</tref> if nesessary.
+ Add an entry for <em>head</em> with <em>object representation</em>.</li>
+ <li>Append <em>object representation</em> to the array value for
+ <em>key</em>, creating an entry in <em>value</em> if necessary.</li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>For each <em>name</em> and <em>graph</em> in <em>graphs</em>:
+ <ol class="algorithm">
+ <li>For each <em>subject</em> and <em>entry</em> in <em>graph</em>
+ where <em>entry</em> has both <em>head</em> and <em>first</em> keys:
+ <ol class="algorithm">
+ <li>Set <em>value</em> to the value of <em>head</em> in <em>entry</em>.</li>
+ <li>Remove the entry for <code>@id</code> in <em>value</em>.</li>
+ <li>Add an entry to <em>value</em> for <code>@list</code> initialized to a new array
+ containing the value of <em>first</em> from <em>entry</em>.</li>
+ <li>While <em>entry</em> has a key for <em>rest</em>:
+ <ol class="algorithm">
+ <li>Set <em>entry</em> to the value of <em>graph.listMap</em> for <em>entry.rest</em>.</li>
+ <li>Add the value for <em>entry.first</em> to the list array.</li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>Create <em>array</em> as an empty <tref>array</tref>.</li>
+ <li>For each <em>subject</em> and <em>entry</em> in <em>defaultGraph.nodes</em>
+ ordered by <em>subject</em>:
+ <ol class="algorithm">
+ <li>Add <em>entry</em> to <em>array</em>.</li>
+ <li>If <em>graphs</em> has an entry for <em>subject</em>, add a property
+ <code>@graph</code> in <em>entry</em> containing the ordered entries
+ from <em>graphs[subject].nodes</em>.</li>
+ </ol>
+ </li>
+ <li>Return <em>array</em> as the result.</li>
+ </ol>
+</section>
+
+<!-- FIXME -->
+<section>
+ <h3>Data Round Tripping</h3>
+
+ <p>When <a href="#rdf-conversion">converting JSON-LD to RDF</a> JSON-native types such as
+ <em>numbers</em> and <em>booleans</em> are automatically coerced to <strong>xsd:integer</strong>,
+ <strong>xsd:double</strong>, or <strong>xsd:boolean</strong>. Implementers MUST ensure that the
+ result is in <tref>canonical lexical form</tref>. A
+ <tdef>canonical lexical form</tdef> is a set of literals from among the valid set of literals for
+ a datatype such that there is a one-to-one mapping between the <tref>canonical lexical form</tref> and a value
+ in the value space as defined in [[!XMLSCHEMA11-2]]. In other words, every value MUST be converted
+ to a deterministic <tref>string</tref> representation.</p>
+
+ <p>The canonical lexical form of an <em>integer</em>, i.e., a number without fractions
+ or a number coerced to <strong>xsd:integer</strong>, is a finite-length sequence of decimal
+ digits (<code>0-9</code>) with an optional leading minus sign; leading zeroes are prohibited.
+ To convert the number in JavaScript, implementers can use the following snippet of code:</p>
+
+ <pre class="example" data-transform="updateExample"
+ title="Sample integer serialization implementation in JavaScript">
+ <!--
+ (value).toFixed(0).toString()
+ -->
+ </pre>
+
+ <p>The canonical lexical form of a <em>double</em>, i.e., a number with fractions
+ or a number coerced to <strong>xsd:double</strong>, consists of a mantissa followed by the
+ character "E", followed by an exponent. The mantissa MUST be a decimal number. The exponent
+ MUST be an integer. Leading zeroes and a preceding plus sign (<code>+</code>) are prohibited
+ in the exponent. If the exponent is zero, it must be indicated by <code>E0</code>.
+ For the mantissa, the preceding optional plus sign is prohibited and the decimal point is
+ required. Leading and trailing zeroes are prohibited subject to the following: number
+ representations must be normalized such that there is a single digit which is non-zero to the
+ left of the decimal point and at least a single digit to the right of the decimal point unless
+ the value being represented is zero. The canonical representation for zero is <code>0.0E0</code>.
+ <strong>xsd:double</strong>'s value space is defined by the IEEE double-precision 64-bit
+ floating point type [[!IEEE-754-1985]]; in JSON-LD the mantissa is rounded to 15 digits after the
+ decimal point.</p>
+
+ <p>To convert the number in JavaScript, implementers can use the following snippet of code:</p>
+
+ <pre class="example" data-transform="updateExample"
+ title="Sample floating point number serialization implementation in JavaScript">
+ <!--
+ (value).toExponential(15).replace(/(\d)0*e\+?/,'$1E')
+ -->
+ </pre>
+
+ <p class="note">When data such as decimals need to be normalized, JSON-LD authors should
+ not use values that are going to undergo automatic conversion. This is due to the lossy nature
+ of <strong>xsd:double</strong> values. Authors should instead use the expanded object form to
+ set the canonical lexical form directly.</p>
+
+ <p>The canonical lexical form of the <em>boolean</em> values <code>true</code> and <code>false</code>
+ are the strings <strong>true</strong> and <strong>false</strong>.</p>
+
+ <p>When JSON-native <tref>number</tref>s, are type coerced, lossless data round-tripping can not
+ be guaranted as rounding errors might occur. Additionally, only literals typed as
+ <strong>xsd:integer</strong>, <strong>xsd:double</strong>, and <strong>xsd:boolean</strong> are
+ automatically converted back to their JSON-native counterparts in when
+ <a href="#rdf-conversion">converting from RDF</a>.</p>
+
+ <p>Some JSON serializers, such as PHP's native implementation in some versions,
+ backslash-escape the forward slash character. For example, the value
+ <code>http://example.com/</code> would be serialized as <code>http:\/\/example.com\/</code>.
+ This is problematic as other JSON parsers might not understand those escaping characters.
+ There is no need to backslash-escape forward slashes in JSON-LD. To aid interoperability
+ between JSON-LD processors, a JSON-LD serializer MUST NOT backslash-escape forward slashes.</p>
+</section>
+
+<!-- end of RDF algorithms -->
+</section>
+
+<!-- end of Algorithms -->
+</section>
+
+<section>
+ <h2>The Application Programming Interface</h2>
+
+ <p>This API provides a clean mechanism that enables developers to convert
+ JSON-LD data into a a variety of output formats that are easier to work
+ with in JavaScript. If a JavaScript JSON-LD API is provided, the entirety
+ of the following API MUST be implemented.</p>
+
+ <section>
+ <h3>JsonLdProcessor</h3>
+
+ <p>The JSON-LD Processor interface is the high-level programming structure
+ that developers use to access the JSON-LD transformation methods.</p>
+
+ <p>It is important to highlight that conformant <tref title="JSON-LD Processor">JSON-LD processors</tref>
+ MUST NOT modify the input parameters.</p>
+
+ <dl title="[Constructor] interface JsonLdProcessor" class="idl">
+
+ <dt>void expand()</dt>
+ <dd>
+ <a href="#expansion">Expands</a> the given <code>input</code> according to
+ the steps in the <a href="#expansion-algorithm">Expansion Algorithm</a>.
+
+ <dl class="parameters">
+ <dt>(object or object[] or DOMString) input</dt>
+ <dd>The JSON-LD object or array of JSON-LD objects to perform the expansion upon or an
+ <tref>IRI</tref> referencing the JSON-LD document to expand.</dd>
+ <dt>JsonLdCallback callback</dt>
+ <dd>A callback that is called when processing completed successfully
+ on the given <code>input</code>, or a fatal error prevented
+ processing from completing.</dd>
+ <dt>optional JsonLdOptions? options</dt>
+ <dd>A set of options to configure the used algorithms such. This allows, e.g.,
+ to set the input document's base <tref>IRI</tref>.</dd>
+ </dl>
+ </dd>
+
+ <dt>void compact()</dt>
+ <dd>
+ <a href="#compaction">Compacts</a> the given <code>input</code> using the
+ <code>context</code> according to the steps in the
+ <a href="#compaction-algorithm">Compaction Algorithm</a>.
+
+ <dl class="parameters">
+ <dt>(object or object[] or DOMString) input</dt>
+ <dd>The JSON-LD object or array of JSON-LD objects to perform the compaction upon or an
+ <tref>IRI</tref> referencing the JSON-LD document to compact.</dd>
+ <dt>(object or DOMString) context</dt>
+ <dd>The context to use when compacting the <code>input</code>; either in the
+ form of an <tref>JSON object</tref> or as <tref>IRI</tref>.</dd>
+ <dt>JsonLdCallback callback</dt>
+ <dd>A callback that is called when processing completed successfully
+ on the given <code>input</code>, or a fatal error prevented
+ processing from completing.</dd>
+ <dt>optional JsonLdOptions? options</dt>
+ <dd>A set of options to configure the used algorithms such. This allows, e.g.,
+ to set the input document's base <tref>IRI</tref>. This also includes
+ the <code>optimize</code> flag, which, if set, will allow processor-specific
+ optimization.</dd>
+ </dl>
+ </dd>
+
+ <dt>void flatten()</dt>
+ <dd>
+ <a href="#flattening">Flattens</a> the given <code>input</code> and
+ <a href="#compaction">compacts</a> it using the passed <code>context</code>
+ according to the steps in the <a href="#flattening-algorithm">Flattening Algorithm</a>.
+
+ <dl class="parameters">
+ <dt>(object or object[] or DOMString) input</dt>
+ <dd>The JSON-LD object or array of JSON-LD objects or an <tref>IRI</tref>
+ referencing the JSON-LD document to flatten.</dd>
+ <dt>(object or DOMString)? context</dt>
+ <dd>The context to use when compacting the flattened <code>input</code>; either
+ in the form of an <tref>JSON object</tref> or as <tref>IRI</tref>. If
+ <tref>null</tref> is passed, the result will not be compacted but keept
+ in expanded form.</dd>
+ <dt>JsonLdCallback callback</dt>
+ <dd>A callback that is called when processing completed successfully
+ on the given <code>input</code>, or a fatal error prevented
+ processing from completing.</dd>
+ <dt>optional JsonLdOptions? options</dt>
+ <dd>A set of options to configure the used algorithms such. This allows, e.g.,
+ to set the input document's base <tref>IRI</tref>.</dd>
+ </dl>
+ </dd>
+ </dl>
+
+ </section>
+
+ <section>
+ <h3>Callbacks</h3>
+
+ <p>JSON-LD processors utilize callbacks in order to return information in an
+ asynchronous manner to calling applications. This section details the
+ parameters sent to those callbacks.</p>
+
+ <section>
+ <h3>JsonLdCallback</h3>
+ <p>The <a>JsonLdCallback</a> is called when an API method of
+ <a>JsonLdProcessor</a> has been completed, either successfully or
+ by a fatal error.</p>
+
+ <dl title="callback JsonLdCallback = void" class="idl">
+ <dt>JsonLdError error</dt>
+ <dd>If the value is <tref>null</tref>, then no issue was detected
+ during processing. Otherwise, a processing issue was detected and
+ the details are contained within the <em>error</em> object.</dd>
+ <dt>object or object[] document</dt>
+ <dd>The processed JSON-LD document.</dd>
+ </dl>
+ </section>
+ </section>
+
+ <section>
+ <h3>Data Structures</h3>
+ <p>This section describes datatype definitions used within the JSON-LD API.</p>
+
+ <section>
+ <h3>JsonLdOptions</h3>
+ <p>The <a>JsonLdOptions</a> type is used to pass various options to the <a>JsonLdProcessor</a> methods.</p>
+ <dl title="dictionary JsonLdOptions" class="idl">
+ <dt>DOMString base</dt>
+ <dd>The Base IRI to use when expanding the document. This overrides the value of
+ <em>input</em> if it is a <a>IRI</a>. If not specified and <em>input</em> is not
+ an <a>IRI</a>, the base IRI defaults to the current document IRI if in a browser context,
+ or the empty string if there is no document context.
+ <p class="issue atrisk" title="Feature at risk">The default value of this option
+ implies that all IRIs that cannot be compacted otherwise are transformed to relative IRIs
+ during compaction. To avoid that data is being lost, developers thus have to store the
+ base IRI along with the compacted document. This might be problematic in practice and
+ thus the default behavior might be changed in future.</p>
+ </dd>
+ <dt>object or DOMString expandContext = null</dt>
+ <dd>A context that is used to initialize the active context when expanding a document.</dd>
+ <dt>boolean compactArrays = true</dt>
+ <dd>If set to <code>true</code>, the JSON-LD processor replaces arrays with just
+ one element with that element during compaction. If set to <code>false</code>,
+ all arrays will remain arrays even if they have just one element.
+ </dd>
+ <dt>boolean optimize = false</dt>
+ <dd>If set to <code>true</code>, the JSON-LD processor is allowed to
+ optimize the output of the <a href="#compaction-algorithm">Compaction Algorithm</a>
+ to produce even compacter representations. The algorithm for compaction
+ optimization is beyond the scope of this specification and thus
+ not defined. Consequently, different implementations MAY implement
+ different optimization algorithms.
+ </dd>
+ <dt>boolean useRdfType = false</dt>
+ <dd>If set to <code>true</code>, the JSON-LD processor will use the
+ expanded <code>rdf:type</code> IRI as the property instead of
+ <code>@type</code> when <a href="#convert-from-rdf-algorithm">converting from RDF</a>.
+ </dd>
+ <dt>boolean useNativeTypes = true</dt>
+ <dd>If set to <code>true</code>, the JSON-LD processor will try to convert
+ <tref title="typed value">typed values</tref> to JSON native types instead of using the
+ expanded object form when <a href="#convert-from-rdf-algorithm">converting from RDF</a>.
+ <code>xsd:boolean</code> values will be converted to <tref>true</tref> or <tref>false</tref>.
+ <code>xsd:integer</code> and <code>xsd:double</code> values will be
+ converted to
+ <tref title="number">JSON numbers</tref>.
+ </dd>
+ </dl>
+ </section>
+
+ <section>
+ <h3>JsonLdError</h3>
+
+ <p>The <a>JsonLdError</a> type is used to report processing errors
+ to a <a>JsonLdCallback</a>.</p>
+
+ <dl title="dictionary JsonLdError" class="idl">
+ <dt>JsonLdErrorCode code</dt>
+ <dd>a string representing the particular error type, as described in
+ the various algorithms in this document.</dd>
+ <dt>DOMString? message</dt>
+ <dd>an optional error message containing additional debugging information.
+ The specific contents of error messages are outside the scope of this
+ specification.</dd>
+ </dl>
+ </section>
+
+ <section>
+ <h3>JsonLdErrorCode</h3>
+ <p>The <a>JsonLdErrorCode</a> represents the collection of valid JSON-LD error
+ codes.</p>
+
+ <dl title="enum JsonLdErrorCode" class="idl">
+ <dt>invalid syntax</dt>
+ <dd>The document could not be parsed as JSON.</dd>
+ <dt>list of lists detected</dt>
+ <dd>A list of lists was detected. List of lists are not supported in
+ this version of JSON-LD due to the algorithmic complexity associated
+ with conversion to RDF.</dd>
+ <dt>invalid @annotation value</dt>
+ <dd>An <code>@annotation</code> member was encountered whose value was
+ not a <tref>string</tref>.</dd>
+ <dt>invalid @id value</dt>
+ <dd>An <code>@id</code> member was encountered whose value was not a
+ <tref>string</tref>.</dd>
+ <dt>invalid local context</dt>
+ <dd>In invalid <tref>local context</tref> was detected.</dd>
+ <dt>loading remote context failed</dt>
+ <dd>There was a problem encountered loading a remote context.</dd>
+ <dt>invalid remote context</dt>
+ <dd>No valid context document has been found for a referenced,
+ remote context.</dd>
+ <dt>recursive context inclusion</dt>
+ <dd>A cycle in remote context inclusions has been detected.</dd>
+ <dt>invalid default language</dt>
+ <dd>The value of the <tref>default language</tref> is not a <tref>string</tref>
+ or <tref>null</tref> and thus invalid.</dd>
+ <dt>invalid vocab mapping</dt>
+ <dd>An invalid <tref>vocabulary mapping</tref> has been detected, i.e.,
+ it is neither an <tref>absolute IRI</tref> nor <tref>null</tref>.</dd>
+ <dt>keyword redefinition</dt>
+ <dd>A <tref>keyword</tref> redefinition has been detected.</dd>
+ <dt>invalid term definition</dt>
+ <dd>An invalid <tref>term definition</tref> has been detected.</dd>
+ <dt>invalid term IRI mapping</dt>
+ <dd>A <tref>local context</tref> contains a <tref>term</tref> that
+ has not been mapped to an <tref>absolute IRI</tref>.</dd>
+ <dt>cyclic IRI mapping</dt>
+ <dd>A cycle in <tref title="IRI mapping">IRI mappings</tref> has been detected.</dd>
+ <dt>invalid type mapping</dt>
+ <dd>An <code>@type</code> member in a <tref>term definition</tref>
+ was encountered whose value could not be expanded to an
+ <tref>absolute IRI</tref>.</dd>
+ <dt>invalid language mapping</dt>
+ <dd>An <code>@language</code> member in a <tref>term definition</tref>
+ was encountered whose value was neither a <tref>string</tref> nor
+ <tref>null</tref> and thus invalid.</dd>
+ <dt>invalid container mapping</dt>
+ <dd>An <code>@container</code> member was encountered whose value was
+ not one of the following <tref title="string">strings</tref>:
+ <code>@list</code>, <code>@set</code>, or <code>@annotation</code>.</dd>
+ <dt>invalid property generator</dt>
+ <dd>A non-<tref>string</tref> value has been detected in a
+ <tref title="property generator">property generator's</tref>
+ <tref>IRI mapping</tref>.</dd>
+ <dt>invalid property generator IRI mapping</dt>
+ <dd>Expanding all values of a
+ <tref title="property generator">property generator's</tref>
+ <tref>IRI mapping</tref> to <tref>absolute IRI</tref> failed.</dd>
+ <dt>property generator in term definition</dt>
+ <dd>A <tref>property generator</tref> was used in the
+ <tref>IRI mapping</tref> of another <tref>term</tref> or
+ <tref>property generator</tref>.</dd>
+ <dt>invalid type value</dt>
+ <dd>An invalid value for an <code>@type</code> member has been detected,
+ i.e., the value was neither a <tref>string</tref> nor an <tref>array</tref>
+ of <tref title="string">strings</tref>.</dd>
+ <dt>invalid value object</dt>
+ <dd>A <tdef>value object</tdef> with disallowed members has been
+ detected.</dd>
+ <dt>invalid value object value</dt>
+ <dd>An invalid value for the <code>@value</code> member of a
+ <tref>value object</tref> has been detected, i.e., it is neither
+ a <tref>scalar</tref> nor <tref>null</tref>.</dd>
+ <dt>invalid language tagged string</dt>
+ <dd>A <tref>language-tagged string</tref> with disallowed members has
+ been detected.</dd>
+ <dt>invalid language value</dt>
+ <dd>A <tref>language-tagged string</tref> with an invalid language
+ value was detected.</dd>
+ <dt>invalid typed value</dt>
+ <dd>A <tref>typed value</tref> with disallowed members has been
+ detected.</dd>
+ <dt>invalid set or list object</dt>
+ <dd>A <tdef>set object</tref> or <tref>list object</tref> with
+ disallowed members has been detected.</dd>
+ <dt>language map invalid value</dt>
+ <dd>An invalid value in a <tdef>language map</tdef> was detected. It has
+ to be a <tref>string</tref> or an <tref>array</tref> of
+ <tref title="string">strings</tref>.</dd>
+ <dt>compaction to list of lists</dt>
+ <dd>The compacted document contains a list of lists as multiple
+ lists have been compacted to the same term.</dd>
+ </dl>
+ </section>
+
+ </section>
+</section>
+
+<section class="appendix">
+ <h1>Acknowledgements</h1>
+
+ <p>A large amount of thanks goes out to the JSON-LD Community Group
+ participants who worked through many of the technical issues on the mailing
+ list and the weekly telecons - of special mention are Niklas Lindström,
+ François Daoust, Lin Clark, and Zdenko 'Denny' Vrandečić.
+ The editors would like to thank Mark Birbeck, who provided a great deal of
+ the initial push behind the JSON-LD work via his work on RDFj.
+ The work of Dave Lehn and Mike Johnson are appreciated for reviewing,
+ and performing several implementations of the specification. Ian Davis is
+ thanked for his work on RDF/JSON. Thanks also to Nathan Rixham,
+ Bradley P. Allen, Kingsley Idehen, Glenn McDonald, Alexandre Passant,
+ Danny Ayers, Ted Thibodeau Jr., Olivier Grisel, Josh Mandel, Eric Prud'hommeaux,
+ David Wood, Guus Schreiber, Pat Hayes, Sandro Hawke, and Richard Cyganiak
+ or their input on the specification.</p>
+</section>
+
+</body>
+</html>