Skip to content

Commit

Permalink
Language maps (pending term ranking changes).
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Dec 12, 2012
1 parent 5f93eed commit f2c841e
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 27 deletions.
23 changes: 18 additions & 5 deletions lib/json/ld/compact.rb
Expand Up @@ -91,37 +91,50 @@ def compact(element, property = nil)
compacted_key = context.compact_iri(key, :position => :predicate, :depth => @depth)
next if compacted_key.nil?
result[compacted_key] = value
next
end

# For each item in value:
raise ProcessingError, "found #{value.inspect} for #{key} if #{element.inspect}" unless value.is_a?(Array)
value.each do |item|
compacted_key = context.compact_iri(key, :position => :predicate, :value => item, :depth => @depth)

# Result for this item, typically the output object itself
item_result = result
item_key = compacted_key
debug {" => compacted key: #{compacted_key.inspect} for #{item.inspect}"}
next if compacted_key.nil?

# TODO: Property Generators

# Language maps and annotations
if field = %w(@language @annoation).detect {|kk| context.container(compacted_key) == kk}
item_result = result[compacted_key] ||= Hash.new
item_key = item[field]
end

compacted_item = depth {self.compact(item, compacted_key)}
debug {" => compacted value: #{compacted_value.inspect}"}

case result[compacted_key]
case item_result[item_key]
when Array
result[compacted_key] << compacted_item
item_result[item_key] << compacted_item
when nil
if !compacted_value.is_a?(Array) && context.container(compacted_key) == '@set'
compacted_item = [compacted_item].compact
debug {" => as @set: #{compacted_item.inspect}"}
end
result[compacted_key] = compacted_item
item_result[item_key] = compacted_item
else
result[compacted_key] = [result[compacted_key], compacted_item]
item_result[item_key] = [item_result[item_key], compacted_item]
end
end
end
end

# Re-order result keys
r = Hash.ordered
result.keys.kw_sort.each {|k| r[k] = result[k]}
result.keys.kw_sort.each {|kk| r[kk] = result[kk]}
r
else
# For other types, the compacted value is the element value
Expand Down
17 changes: 9 additions & 8 deletions lib/json/ld/evaluation_context.rb
Expand Up @@ -510,7 +510,7 @@ def expand_iri(iri, options = {})
end

##
# Compact an IRI
# Compacts an absolute IRI to the shortest matching term or compact IRI
#
# @param [RDF::URI] iri
# @param [Hash{Symbol => Object}] options ({})
Expand All @@ -536,9 +536,8 @@ def compact_iri(iri, options = {})
# Create an empty list of terms _terms_ that will be populated with terms that are ranked according to how closely they match value. Initialize highest rank to 0, and set a flag list container to false.
terms = {}

# If value is a @list add a term rank for each
# term mapping to iri which has @container @list.
debug("compact_iri", "#{value.inspect} is a list? #{list?(value).inspect}")
# If value is a @list select terms that match every item equivalently.
debug("compact_iri", "#{value.inspect} is a list? #{list?(value).inspect}") if value
if list?(value)
list_terms = matched_terms.select {|t| container(t) == '@list'}

Expand Down Expand Up @@ -783,7 +782,7 @@ def compact_value(property, value, options = {})
value[self.alias('@id')] = compact_iri(value['@id'], :position => :subject)
debug {" (#{self.alias('@id')} => #{value['@id']})"}
value
when value['@language'] && value['@language'] == language(property)
when value['@language'] && (value['@language'] == language(property) || container(property) == '@language')
# Compact language
debug {" (@language) == #{language(property).inspect}"}
value['@value']
Expand Down Expand Up @@ -896,8 +895,8 @@ def term_rank(term, value)
# If the @list property is an empty array, if term has @container set to @list, term rank is 1, otherwise 0.
container(term) == '@list' ? 1 : 0
else
# Otherwise, return the sum of the term ranks for every entry in the list.
depth {value['@list'].inject(0) {|memo, v| memo + term_rank(term, v)}}
# Otherwise, return the greatest rank of all elements in the term.
depth {value['@list'].map {|v| term_rank(term, v)}.max}
end
elsif value?(value)
val_type = value.fetch('@type', nil)
Expand All @@ -911,8 +910,10 @@ def term_rank(term, value)
debug("val_lang.nil") {"#{language(term).inspect} && #{coerce(term).inspect}"}
language(term) == false || (default_term && default_language.nil?) ? 3 : 0
else
if val_lang == language(term) || (default_term && default_language == val_lang)
if val_lang && container(term) == '@language'
3
elsif val_lang == language(term) || (default_term && default_language == val_lang)
2
elsif default_term
1
else
Expand Down
38 changes: 38 additions & 0 deletions spec/compact_spec.rb
Expand Up @@ -393,6 +393,7 @@
}
}.each_pair do |title, params|
it title do
pending("term rank") if title =~ /compact-0018/
input = params[:input].is_a?(String) ? JSON.parse(params[:input]) : params[:input]
ctx = params[:context].is_a?(String) ? JSON.parse(params[:context]) : params[:context]
output = params[:output].is_a?(String) ? JSON.parse(params[:output]) : params[:output]
Expand Down Expand Up @@ -467,6 +468,43 @@
end
end

context "language maps" do
{
"compact-0024" => {
:input => [
{
"@id" => "http://example.com/queen",
"http://example.com/vocab/label" => [
{"@value" => "The Queen", "@language" => "en"},
{"@value" => "Die Königin", "@language" => "de"},
{"@value" => "Ihre Majestät", "@language" => "de"}
]
}
],
:context => {
"vocab" => "http://example.com/vocab/",
"label" => {"@id" => "vocab:label", "@container" => "@language"}
},
:output => {
"@context" => {
"vocab" => "http://example.com/vocab/",
"label" => {"@id" => "vocab:label", "@container" => "@language"}
},
"@id" => "http://example.com/queen",
"label" => {
"en" => "The Queen",
"de" => ["Die Königin", "Ihre Majestät"]
}
}
},
}.each_pair do |title, params|
it title do
jld = JSON::LD::API.compact(params[:input], params[:context], nil, :debug => @debug)
jld.should produce(params[:output], @debug)
end
end
end

context "@graph" do
{
"Uses @graph given mutliple inputs" => {
Expand Down
17 changes: 6 additions & 11 deletions spec/evaluation_context_spec.rb
Expand Up @@ -709,24 +709,16 @@ def ctx.content_type; "application/ld+json"; end
"setdouble" => {"@id" => "http://example.com/double", "@type" => "xsd:double", "@container" => "@set"},
"setdate" => {"@id" => "http://example.com/date", "@type" => "xsd:date", "@container" => "@set"},
"setid" => {"@id" => "http://example.com/id", "@type" => "@id", "@container" => "@set"},
"langmap" => {"@id" => "http://example.com/langmap", "@container" => "@language"},
})
@debug.clear
c
end

{
"setplain" => [
{"@value" => "foo"},
{"@value" => "de", "@language" => "de"},
{"@value" => "other dt", "@language" => "http://example.com/other-datatype"}
],
"setlang" => [{"@value" => "en", "@language" => "en"}],
"setbool" => [{"@value" => true}, {"@value" => false}, {"@value" => "true", "@type" => RDF::XSD.boolean.to_s}],
"setinteger" => [{"@value" => 1}, {"@value" => "1", "@type" => RDF::XSD.integer.to_s}],
"setdouble" => [{"@value" => 1.1}, {"@value" => "1", "@type" => RDF::XSD.double.to_s}],
"setdate" => [{"@value" => "2012-04-17", "@type" => RDF::XSD.date.to_s}],
"langmap" => [{"@value" => "en", "@language" => "en"}],
}.each do |prop, values|
context "uses #{prop}", :pending => "does algorithm favor @set?" do
context "uses #{prop}" do
values.each do |value|
it "for #{value.inspect}" do
ctx.compact_iri("http://example.com/#{prop.sub('set', '')}", :value => value).should produce(prop, @debug)
Expand Down Expand Up @@ -1139,6 +1131,8 @@ def ctx.content_type; "application/ld+json"; end
subject.set_coerce("dc:created", RDF::XSD.date.to_s)
subject.set_container("list", "@list")
subject.set_language("nolang", nil)
subject.set_mapping("langmap", "http://example.org/langmap")
subject.set_container("langmap", "@language")
end

{
Expand Down Expand Up @@ -1173,6 +1167,7 @@ def ctx.content_type; "application/ld+json"; end
"no lang" => ["foo", {"@value" => "foo" }, {"@value" => "foo"}],
"same lang" => ["foo", "foo", {"@value" => "foo", "@language" => "en"}],
"other lang" => ["foo", {"@value" => "foo", "@language" => "bar"}, {"@value" => "foo", "@language" => "bar"}],
"langmap" => ["langmap", "en", {"@value" => "en", "@language" => "en"}],
"no lang with @type coercion" => ["dc:created", {"@value" => "foo"}, {"@value" => "foo"}],
"no lang with @id coercion" => ["foaf:knows", {"@value" => "foo"}, {"@value" => "foo"}],
"no lang with @language=null" => ["nolang", "string", {"@value" => "string"}],
Expand Down
4 changes: 1 addition & 3 deletions spec/suite_compact_spec.rb
Expand Up @@ -13,11 +13,9 @@
case t.property('input')
when /compact-(0018|0024)/
pending("term rank")
when /compact-(0025|0026|0027)/
pending("implementation of language maps")
when /compact-(0029|0030)/
pending("implementation of annotation maps")
when /compact-(0031|0032)/
when /compact-(0031|0032|0033|0034|0035)/
pending("implementation of property generators")
end
t.debug = ["test: #{t.inspect}", "source: #{t.input.read}"]
Expand Down

0 comments on commit f2c841e

Please sign in to comment.