2017-02-19 02:47:05 +00:00
defmodule JSON.LD.IRIExpansion do
2017-03-21 00:01:55 +00:00
import JSON.LD.Utils
2017-02-19 02:47:05 +00:00
@keywords JSON.LD . keywords # to allow this to be used in function guard clauses, we redefine this here
@doc """
see http :/ / json - ld . org / spec / latest / json - ld - api / #iri-expansion
"""
def expand_iri ( value , active_context , doc_relative \\ false , vocab \\ false ,
local_context \\ nil , defined \\ nil )
# 1) If value is a keyword or null, return value as is.
def expand_iri ( value , active_context , _ , _ , local_context , defined )
when is_nil ( value ) or value in @keywords do
if local_context || defined do
{ value , active_context , defined }
else
value
end
end
def expand_iri ( value , active_context , doc_relative , vocab , local_context , defined ) do
# 2)
2017-09-13 23:41:12 +00:00
{ active_context , defined } =
if local_context && local_context [ value ] && defined [ value ] != true do
local_def = local_context [ value ]
2017-02-19 02:47:05 +00:00
JSON.LD.Context . create_term_definition (
active_context , local_context , value , local_def , defined )
2017-09-13 23:41:12 +00:00
else
{ active_context , defined }
end
2017-02-19 02:47:05 +00:00
2017-09-13 23:41:12 +00:00
{ result , active_context , defined } =
cond do
# 3) If vocab is true and the active context has a term definition for value, return the associated IRI mapping.
vocab && Map . has_key? ( active_context . term_defs , value ) ->
result = ( term_def = active_context . term_defs [ value ] ) && term_def . iri_mapping
{ result , active_context , defined }
# 4) If value contains a colon (:), it is either an absolute IRI, a compact IRI, or a blank node identifier
String . contains? ( value , " : " ) ->
case compact_iri_parts ( value ) do
[ prefix , suffix ] ->
# 4.3)
2017-02-19 02:47:05 +00:00
{ active_context , defined } =
2017-09-13 23:41:12 +00:00
if local_context && local_context [ prefix ] && defined [ prefix ] != true do
local_def = local_context [ prefix ]
JSON.LD.Context . create_term_definition (
active_context , local_context , prefix , local_def , defined )
else
{ active_context , defined }
end
# 4.4)
result =
if prefix_def = active_context . term_defs [ prefix ] do
prefix_def . iri_mapping <> suffix
else
value # 4.5)
end
{ result , active_context , defined }
nil ->
{ value , active_context , defined } # 4.2)
end
# 5) If vocab is true, and active context has a vocabulary mapping, return the result of concatenating the vocabulary mapping with value.
vocab && active_context . vocab ->
vocabulary_mapping = active_context . vocab
{ vocabulary_mapping <> value , active_context , defined }
# 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 , JSON.LD.Context . base ( active_context ) ) , active_context , defined }
2017-02-19 02:47:05 +00:00
# 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.
# raise JSON.LD.InvalidIRIMappingError, message: "not an absolute IRI: #{value}"
2017-09-13 23:41:12 +00:00
# 7) Return value as is.
true ->
{ value , active_context , defined }
end
2017-02-19 02:47:05 +00:00
if local_context do
{ result , active_context , defined }
else
result
end
end
end