lib/json/ld/evaluation_context.rb in json-ld-0.1.4.2 vs lib/json/ld/evaluation_context.rb in json-ld-0.1.5
- old
+ new
@@ -62,10 +62,18 @@
#
#
# This adds a language to plain strings that aren't otherwise coerced
# @attr [String]
attr :default_language, true
+
+ # Default vocabulary
+ #
+ #
+ # Sets the default vocabulary used for expanding terms which
+ # aren't otherwise absolute IRIs
+ # @attr [String]
+ attr :vocab, true
# Global options used in generating IRIs
# @attr [Hash] options
attr :options, true
@@ -147,22 +155,37 @@
ec.provided_context = context
debug("parse") {"=> provided_context: #{context.inspect}"}
ec
when Hash
new_ec = self.dup
- new_ec.provided_context = context
-
+ new_ec.provided_context = context.dup
+
+ {
+ '@language' => :default_language=,
+ '@vocab' => :vocab=
+ }.each do |key, setter|
+ v = context.fetch(key, false)
+ if v.nil? || v.is_a?(String)
+ context.delete(key)
+ debug("parse") {"Hash[#{key}] = #{v.inspect}"}
+ new_ec.send(setter, v)
+ elsif v
+ raise InvalidContext::Syntax, "#{key.inspect} is invalid"
+ end
+ end
+
num_updates = 1
while num_updates > 0 do
num_updates = 0
# Map terms to IRIs/keywords first
context.each do |key, value|
# Expand a string value, unless it matches a keyword
debug("parse") {"Hash[#{key}] = #{value.inspect}"}
- if key == '@language' && (value.nil? || value.is_a?(String))
- new_ec.default_language = value
+
+ if KEYWORDS.include?(key)
+ raise InvalidContext::Syntax, "key #{key.inspect} must not be a keyword"
elsif term_valid?(key)
# Remove all coercion information for the property
new_ec.set_coerce(key, nil)
new_ec.set_container(key, nil)
@languages.delete(key)
@@ -170,13 +193,11 @@
# Extract IRI mapping. This is complicated, as @id may have been aliased
value = value.fetch('@id', nil) if value.is_a?(Hash)
raise InvalidContext::Syntax, "unknown mapping for #{key.inspect} to #{value.class}" unless value.is_a?(String) || value.nil?
iri = new_ec.expand_iri(value, :position => :predicate) if value.is_a?(String)
- if iri && KEYWORDS.include?(key)
- raise InvalidContext::Syntax, "key #{key.inspect} must not be a keyword"
- elsif iri && new_ec.mappings.fetch(key, nil) != iri
+ if iri && new_ec.mappings.fetch(key, nil) != iri
# Record term definition
new_ec.set_mapping(key, iri)
num_updates += 1
elsif value.nil?
new_ec.set_mapping(key, nil)
@@ -252,10 +273,11 @@
else
debug("serlialize: generate context")
debug {"=> context: #{inspect}"}
ctx = Hash.ordered
ctx['@language'] = default_language.to_s if default_language
+ ctx['@vocab'] = vocab.to_s if vocab
# Mappings
mappings.keys.sort{|a, b| a.to_s <=> b.to_s}.each do |k|
next unless term_valid?(k.to_s)
debug {"=> mappings[#{k}] => #{mappings[k]}"}
@@ -451,19 +473,20 @@
# @see http://json-ld.org/spec/latest/json-ld-api/#iri-expansion
def expand_iri(iri, options = {})
return iri unless iri.is_a?(String)
prefix, suffix = iri.split(':', 2)
return mapping(iri) if mapping(iri) # If it's an exact match
- debug("expand_iri") {"prefix: #{prefix.inspect}, suffix: #{suffix.inspect}"} unless options[:quiet]
+ debug("expand_iri") {"prefix: #{prefix.inspect}, suffix: #{suffix.inspect}, vocab: #{vocab.inspect}"} unless options[:quiet]
base = self.base unless [:predicate, :datatype].include?(options[:position])
prefix = prefix.to_s
case
when prefix == '_' && suffix then bnode(suffix)
when iri.to_s[0,1] == "@" then iri
when suffix.to_s[0,2] == '//' then uri(iri)
when mappings.has_key?(prefix) then uri(mappings[prefix] + suffix.to_s)
when base then base.join(iri)
+ when vocab then uri("#{vocab}#{iri}")
else
# Otherwise, it must be an absolute IRI
u = uri(iri)
u if u.absolute? || [:subject, :object].include?(options[:position])
end
@@ -533,14 +556,24 @@
# Find terms having the greatest term match value
least_distance = term_map.values.max
terms = term_map.keys.select {|t| term_map[t] == least_distance}
- # If the list of found terms is empty, append a compact IRI for
- # each term which is a prefix of iri which does not have
- # @type coercion, @container coercion or @language coercion rules
- # along with the iri itself.
+ # If terms is empty, and the active context has a @vocab which is a
+ # prefix of iri where the resulting relative IRI is not a term in the
+ # active context. The resulting relative IRI is the unmatched part of iri.
+ if vocab && terms.empty? && iri.to_s.index(vocab) == 0
+ terms << iri.to_s.sub(vocab, '')
+ debug("vocab") {"vocab: #{vocab}, rel: #{terms.first}"}
+ end
+
+ # If terms is empty, add a compact IRI representation of iri for each
+ # term in the active context which maps to an IRI which is a prefix for
+ # iri where the resulting compact IRI is not a term in the active
+ # context. The resulting compact IRI is the term associated with the
+ # partially matched IRI in the active context concatenated with a colon
+ # (:) character and the unmatched part of iri.
if terms.empty?
debug("curies") {"mappings: #{mappings.inspect}"}
curies = mappings.keys.map do |k|
debug("curies[#{k}]") {"#{mapping(k).inspect}"}
#debug("curies[#{k}]") {"#{(mapping(k).to_s.length > 0).inspect}, #{iri.to_s.index(mapping(k).to_s)}"}
@@ -564,33 +597,35 @@
coerce(curie).nil? &&
language(curie) == default_language
end
debug("curies") {"selected #{terms.inspect}"}
+ end
- # If we still don't have any terms and we're using standard_prefixes,
- # try those, and add to mapping
- if terms.empty? && @options[:standard_prefixes]
- terms = RDF::Vocabulary.
- select {|v| iri.index(v.to_uri.to_s) == 0}.
- map do |v|
- prefix = v.__name__.to_s.split('::').last.downcase
- set_mapping(prefix, v.to_uri.to_s)
- iri.sub(v.to_uri.to_s, "#{prefix}:").sub(/:$/, '')
- end
- debug("curies") {"using standard prefies: #{terms.inspect}"}
- end
+ # If we still don't have any terms and we're using standard_prefixes,
+ # try those, and add to mapping
+ if terms.empty? && @options[:standard_prefixes]
+ terms = RDF::Vocabulary.
+ select {|v| iri.index(v.to_uri.to_s) == 0}.
+ map do |v|
+ prefix = v.__name__.to_s.split('::').last.downcase
+ set_mapping(prefix, v.to_uri.to_s)
+ iri.sub(v.to_uri.to_s, "#{prefix}:").sub(/:$/, '')
+ end
+ debug("curies") {"using standard prefies: #{terms.inspect}"}
+ end
+ if terms.empty?
# If there is a mapping from the complete IRI to null, return null,
# otherwise, return the complete IRI.
if mappings.has_key?(iri.to_s) && !mapping(iri)
debug("iri") {"use nil IRI mapping"}
terms << nil
else
terms << iri.to_s
end
end
-
+
# Get the first term based on distance and lexecographical order
# Prefer terms that don't have @container @set over other terms, unless as set is true
terms = terms.sort do |a, b|
debug("term sort") {"c(a): #{container(a).inspect}, c(b): #{container(b)}"}
if a.to_s.length == b.to_s.length