Skip to content

Commit

Permalink
Annotation expansion.
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Dec 12, 2012
1 parent f2c841e commit 61d1bdd
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 7 deletions.
2 changes: 1 addition & 1 deletion lib/json/ld/evaluation_context.rb
Expand Up @@ -237,7 +237,7 @@ def parse(context)
new_ec.set_coerce(key, iri)
end
when '@container'
raise InvalidContext::Syntax, "unknown mapping for '@container' to #{value2.inspect}" unless %w(@list @set @language).include?(value2)
raise InvalidContext::Syntax, "unknown mapping for '@container' to #{value2.inspect}" unless %w(@list @set @language @annotation).include?(value2)
if new_ec.container(key) != value2
debug("parse") {"container #{key.inspect} as #{value2.inspect}"}
new_ec.set_container(key, value2)
Expand Down
31 changes: 27 additions & 4 deletions lib/json/ld/expand.rb
Expand Up @@ -94,6 +94,11 @@ def expand(input, active_property, context, options = {})
else
context.expand_iri(value, options.merge(:position => :property, :quiet => true)).to_s
end
when '@annotation'
# Otherwise, if the property is @annotation, the value MUST be a string
value = value.first if value.is_a?(Array) && value.length == 1
raise ProcessingError, "Value of @annotation is not a string: #{value.inspect}" unless value.is_a?(String)
value
when '@value', '@language'
# Otherwise, if the property is @value or @language the value must not be a JSON object or an array.
raise ProcessingError::Lossy, "Value of #{property} must be a string, was #{value.inspect}" if value.is_a?(Hash) || value.is_a?(Array)
Expand All @@ -113,7 +118,7 @@ def expand(input, active_property, context, options = {})

value
else
if context.container(active_property) == '@language'
if context.container(active_property) == '@language' && value.is_a?(Hash)
# Otherwise, if value is a JSON object and property is not a keyword and its associated term entry in the active context has a @container key associated with a value of @language, process the associated value as a language map:

# Set multilingual array to an empty array.
Expand All @@ -138,6 +143,24 @@ def expand(input, active_property, context, options = {})
end
# Set the value associated with property to the multilingual array.
multilingual_array
elsif context.container(active_property) == '@annotation' && value.is_a?(Hash)
# Otherwise, if value is a JSON object and property is not a keyword and its associated term entry in the active context has a @container key associated with a value of @annotation, process the associated value as a annotation:

# Set ary to an empty array.
ary = []

# For each key-value in the object:
value.keys.sort.each do |k|
[value[k]].flatten.each do |v|
# Expand the value, adding an '@annotation' key with value equal to the key
expanded_value = depth { expand(v, active_property, context, options) }
next unless expanded_value
expanded_value['@annotation'] ||= k
ary << expanded_value
end
end
# Set the value associated with property to the multilingual array.
ary
else
# Otherwise, expand value recursively using this algorithm, passing copies of the active context and active property.
depth { expand(value, active_property, context, options) }
Expand All @@ -163,7 +186,7 @@ def expand(input, active_property, context, options = {})
end

# Convert value to array form unless value is null or property is @id, @type, @value, or @language.
if !%(@id @language @type @value).include?(property) && !expanded_value.is_a?(Array)
if !%(@id @language @type @value @annotation).include?(property) && !expanded_value.is_a?(Array)
debug(" => make #{expanded_value.inspect} an array")
expanded_value = [expanded_value]
end
Expand All @@ -184,8 +207,8 @@ def expand(input, active_property, context, options = {})
if output_object.has_key?('@value')
output_object.delete('@language') if output_object['@language'].to_s.empty?
output_object.delete('@type') if output_object['@type'].to_s.empty?
if output_object.keys.length > 2 || (%w(@language @type) - output_object.keys).empty?
raise ProcessingError, "element must not have more than one other property, which can either be @language or @type with a string value." unless value.is_a?(String)
if (%w(@annotation @language @type) - output_object.keys).empty?
raise ProcessingError, "element must not have more than one other property other than @annotation, which can either be @language or @type with a string value." unless value.is_a?(String)
end

# if the value of @value equals null, replace element with the value of null.
Expand Down
35 changes: 35 additions & 0 deletions spec/expand_spec.rb
Expand Up @@ -728,6 +728,41 @@
end
end

context "annotations" do
{
"string annotation" => {
:input => {
"@context" => {
"container" => {
"@id" => "http://example.com/container",
"@container" => "@annotation"
}
},
"@id" => "http://example.com/annotationsTest",
"container" => {
"en" => "The Queen",
"de" => [ "Die Königin", "Ihre Majestät" ]
}
},
:output => [
{
"@id" => "http://example.com/annotationsTest",
"http://example.com/container" => [
{"@value" => "Die Königin", "@annotation" => "de"},
{"@value" => "Ihre Majestät", "@annotation" => "de"},
{"@value" => "The Queen", "@annotation" => "en"}
]
}
]
},
}.each do |title, params|
it title do
jld = JSON::LD::API.expand(params[:input], nil, nil, :debug => @debug)
jld.should produce(params[:output], @debug)
end
end
end

context "exceptions" do
{
"@list containing @list" => {
Expand Down
2 changes: 0 additions & 2 deletions spec/suite_expand_spec.rb
Expand Up @@ -11,8 +11,6 @@
specify "#{t.property('input')}: #{t.name}" do
begin
case t.property('input')
when /expand-(0036|0040)/
pending("implementation of @annotation")
when /expand-(0037|0038|0039)/
pending("implementation of property generators")
end
Expand Down

0 comments on commit 61d1bdd

Please sign in to comment.