From efcdccd735ced2533a48655ebc742fb5239bbcbc Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Wed, 29 Mar 2017 23:32:59 +0200 Subject: [PATCH] json_ld: fix base iri handling --- lib/json/ld/compaction.ex | 4 ++-- lib/json/ld/context.ex | 21 ++++++++++++++------- lib/json/ld/iri_expansion.ex | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/json/ld/compaction.ex b/lib/json/ld/compaction.ex index 840240c..98ce845 100644 --- a/lib/json/ld/compaction.ex +++ b/lib/json/ld/compaction.ex @@ -7,7 +7,7 @@ defmodule JSON.LD.Compaction do def compact(input, context, options \\ %JSON.LD.Options{}) do with options = JSON.LD.Options.new(options), - active_context = JSON.LD.context(context), + active_context = JSON.LD.context(context, options), inverse_context = Context.inverse(active_context), expanded = JSON.LD.expand(input, options) do @@ -432,7 +432,7 @@ defmodule JSON.LD.Compaction do compact_iri # 7) If vocab is false then transform iri to a relative IRI using the document's base IRI. not vocab -> - remove_base(iri, active_context.base_iri) + remove_base(iri, Context.base(active_context)) # 8) Finally, return iri as is. true -> iri diff --git a/lib/json/ld/context.ex b/lib/json/ld/context.ex index c6a6879..6b39e89 100644 --- a/lib/json/ld/context.ex +++ b/lib/json/ld/context.ex @@ -1,8 +1,9 @@ defmodule JSON.LD.Context do defstruct term_defs: %{}, + default_language: nil, vocab: nil, - base_iri: nil, - default_language: nil + base_iri: false, + api_base_iri: nil import JSON.LD.IRIExpansion import JSON.LD.Utils @@ -10,10 +11,15 @@ defmodule JSON.LD.Context do alias JSON.LD.Context.TermDefinition - def new(options \\ %JSON.LD.Options{}), - do: %JSON.LD.Context{base_iri: JSON.LD.Options.new(options).base} + def base(%JSON.LD.Context{base_iri: false, api_base_iri: api_base_iri}), + do: api_base_iri + def base(%JSON.LD.Context{base_iri: base_iri}), + do: base_iri + def new(options \\ %JSON.LD.Options{}), + do: %JSON.LD.Context{api_base_iri: JSON.LD.Options.new(options).base} + def create(%{"@context" => json_ld_context}, options), do: new(options) |> update(json_ld_context, [], options) @@ -31,9 +37,10 @@ defmodule JSON.LD.Context do update(active, [local], remote, options) end + # 3.1) If context is null, set result to a newly-initialized active context and continue with the next context. The base IRI of the active context is set to the IRI of the currently being processed document (which might be different from the currently being processed context), if available; otherwise to null. If set, the base option of a JSON-LD API Implementation overrides the base IRI. - defp do_update(%JSON.LD.Context{} = active, nil, remote, options) do - JSON.LD.Context.new(base: JSON.LD.Options.new(options).base || active.base_iri) + defp do_update(%JSON.LD.Context{}, nil, remote, options) do + new(options) end # 3.2) If context is a string, [it's interpreted as a remote context] @@ -368,7 +375,7 @@ defmodule JSON.LD.Context do end) end - def empty?(%JSON.LD.Context{term_defs: term_defs, vocab: nil, base_iri: nil, default_language: nil}) + def empty?(%JSON.LD.Context{term_defs: term_defs, vocab: nil, base_iri: false, default_language: nil}) when map_size(term_defs) == 0, do: true def empty?(_), diff --git a/lib/json/ld/iri_expansion.ex b/lib/json/ld/iri_expansion.ex index 57a0b9a..5cc1a47 100644 --- a/lib/json/ld/iri_expansion.ex +++ b/lib/json/ld/iri_expansion.ex @@ -55,7 +55,7 @@ defmodule JSON.LD.IRIExpansion do vocabulary_mapping <> value # 6) Otherwise, if document relative is true, set value to the result of resolving value against the base IRI. Only the basic algorithm in section 5.2 of [RFC3986] is used; neither Syntax-Based Normalization nor Scheme-Based Normalization 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]. doc_relative -> - absolute_iri(value, active_context.base_iri) + absolute_iri(value, JSON.LD.Context.base(active_context)) # TODO: RDF.rb's implementation differs from the spec here, by checking if base_iri is actually present in the previous clause and adding the following additional clause. Another Spec error? # if local_context && RDF::URI(value).relative? # # If local context is not null and value is not an absolute IRI, an invalid IRI mapping error has been detected and processing is aborted.