Skip to content

Commit

Permalink
* Use _override\_protected_ instead of _from\_property_.
Browse files Browse the repository at this point in the history
* Use _propagate_: true instead of _from\_type_: false.
* Add _protected_ option to context parsing to allow for sourced contexts to be protected.
  • Loading branch information
gkellogg committed Jul 6, 2019
1 parent 94841f7 commit 1e04382
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 31 deletions.
4 changes: 2 additions & 2 deletions lib/json/ld/compact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def compact(element, property: nil, ordered: false)

# Look up term definintions from property using the original type-scoped context, if it exists, but apply them to the now current previous context
td = input_context.term_definitions[property] if property
self.context = context.parse(td.context, from_property: property) if td && td.context
self.context = context.parse(td.context, override_protected: true) if td && td.context

if element.key?('@id') || element.key?('@value')
result = context.compact_value(property, element, log_depth: @options[:log_depth])
Expand All @@ -84,7 +84,7 @@ def compact(element, property: nil, ordered: false)
sort.
each do |term|
term_context = input_context.term_definitions[term].context if input_context.term_definitions[term]
self.context = context.parse(term_context, from_type: true) if term_context
self.context = context.parse(term_context, propagate: false) if term_context
end

element.keys.opt_sort(ordered: ordered).each do |expanded_property|
Expand Down
49 changes: 24 additions & 25 deletions lib/json/ld/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ def inspect
# @raise [JsonLdError]
# on a remote context load error, syntax error, or a reference to a term which is not defined.
# @return [Context]
def self.parse(local_context, from_property: false, from_type: false, **options)
self.new(options).parse(local_context, from_property: from_property, from_type: from_type)
def self.parse(local_context, protected: false, override_protected: false, propagate: true, **options)
self.new(options).parse(local_context, protected: false, override_protected: override_protected, propagate: propagate)
end

##
Expand Down Expand Up @@ -437,10 +437,10 @@ def propagate=(value, **options)
#
# @param [String] value
# @return [self]
def source=(value, remote_contexts:)
def source=(value, remote_contexts:, protected:)
raise JsonLdError::InvalidContextMember, "@source may only be used in 1.1 mode}" if (processingMode || 'json-ld-1.0') < 'json-ld-1.1'
raise JsonLdError::InvalidSourceValue, "@source must be a string: #{value.inspect}" unless value.is_a?(String)
self.merge!(self.parse(value, remote_contexts: remote_contexts.dup))
self.merge!(self.parse(value, protected: protected, remote_contexts: remote_contexts.dup))
end

# Create an Evaluation Context
Expand All @@ -454,31 +454,31 @@ def source=(value, remote_contexts:)
#
# @param [String, #read, Array, Hash, Context] local_context
# @param [Array<String>] remote_contexts
# @param [Boolean] from_property
# Context is created from a scoped context for a property. Sealed terms may not be cleared unless from a context associated with a term used as a property.
# @param [Boolean] protected Make defined terms protected (as if `@protected` were used).
# @param [Boolean] override_protected Protected terms may be cleared.
# @param [Boolean] propagate
# Retains any previously defined term, which can be rolled back when the descending into a new node object changes.
# If false, retains any previously defined term, which can be rolled back when the descending into a new node object changes.
# @param [RDF::Resource] context_id from context IRI, for sealing terms
# @raise [JsonLdError]
# on a remote context load error, syntax error, or a reference to a term which is not defined.
# @return [Context]
# @see https://www.w3.org/TR/json-ld11-api/index.html#context-processing-algorithm
def parse(local_context, remote_contexts: [], from_property: false, from_type: false)
def parse(local_context, remote_contexts: [], protected: false, override_protected: false, propagate: true)
result = self.dup
result.provided_context = local_context if self.empty?
# Early check for @propagate, which can only appear in a local context
propagate = local_context.is_a?(Hash) ? local_context.fetch('@propagate', !from_type) : !from_type
propagate = local_context.is_a?(Hash) ? local_context.fetch('@propagate', propagate) : propagate
result.previous_context ||= result.dup unless propagate

local_context = as_array(local_context)

local_context.each do |context|
case context
when nil
# 3.1 If the `from_property` is not null, and the active context contains protected terms, an error is raised.
if from_property || result.term_definitions.values.none?(&:protected?)
# 3.1 If the `override_protected` is false, and the active context contains protected terms, an error is raised.
if override_protected || result.term_definitions.values.none?(&:protected?)
null_context = Context.new(options)
null_context.previous_context = result if from_type
null_context.previous_context = result unless propagate
result = null_context
else
raise JSON::LD::JsonLdError::InvalidContextNullification,
Expand Down Expand Up @@ -552,7 +552,7 @@ def parse(local_context, remote_contexts: [], from_property: false, from_type: f
end

# 3.2.6) Set context to the result of recursively calling this algorithm, passing context no base for active context, context for local context, and remote contexts.
context = context_no_base.parse(context, remote_contexts: remote_contexts.dup, from_property: from_property, from_type: from_type)
context = context_no_base.parse(context, remote_contexts: remote_contexts.dup, protected: protected, override_protected: override_protected, propagate: propagate)
PRELOADED[context_canon.to_s] = context
context.provided_context = result.provided_context
end
Expand All @@ -572,7 +572,7 @@ def parse(local_context, remote_contexts: [], from_property: false, from_type: f
'@vocab' => :vocab=,
}.each do |key, setter|
next unless context.has_key?(key)
result.send(setter, context[key], remote_contexts: remote_contexts)
result.send(setter, context[key], remote_contexts: remote_contexts, protected: context.fetch('@protected', protected))
context.delete(key)
end

Expand All @@ -582,9 +582,9 @@ def parse(local_context, remote_contexts: [], from_property: false, from_type: f
context.each_key do |key|
# ... where key is not @base, @vocab, @language, or @version
result.create_term_definition(context, key, defined,
from_property: from_property,
from_type: from_type,
protected: context['@protected']) unless NON_TERMDEF_KEYS.include?(key)
override_protected: override_protected,
propagate: propagate,
protected: context.fetch('@protected', protected)) unless NON_TERMDEF_KEYS.include?(key)
end
else
# 3.3) If context is not a JSON object, an invalid local context error has been detected and processing is aborted.
Expand Down Expand Up @@ -641,15 +641,14 @@ def merge!(context)
# @param [Hash] local_context
# @param [String] term
# @param [Hash] defined
# @param [Boolean] from_property
# Context is created from a scoped context for a property. Sealed terms may not be cleared unless from a context associated with a term used as a property.
# @param [Boolean] from_type
# Context is created from a scoped context for a type.
# @param [Boolean] protected if true, causes all terms to be marked protected
# @param [Boolean] override_protected Protected terms may be cleared.
# @param [Boolean] propagate
# Context is propagated across node objects.
# @raise [JsonLdError]
# Represents a cyclical term dependency
# @see https://www.w3.org/TR/json-ld11-api/index.html#create-term-definition
def create_term_definition(local_context, term, defined, from_property: false, from_type: false, protected: false)
def create_term_definition(local_context, term, defined, override_protected: false, propagate: true, protected: false)
# Expand a string value, unless it matches a keyword
#log_debug("create_term_definition") {"term = #{term.inspect}"}

Expand Down Expand Up @@ -680,7 +679,7 @@ def create_term_definition(local_context, term, defined, from_property: false, f

# Remove any existing term definition for term in active context.
previous_definition = term_definitions[term]
if previous_definition && previous_definition.protected? && !from_property
if previous_definition && previous_definition.protected? && !override_protected
# Check later to detect identical redefinition
else
term_definitions.delete(term) if previous_definition
Expand Down Expand Up @@ -823,7 +822,7 @@ def create_term_definition(local_context, term, defined, from_property: false, f

if value.has_key?('@context')
begin
self.parse(value['@context'], from_property: true)
self.parse(value['@context'], override_protected: true)
# Record null context in array form
definition.context = value['@context'] ? value['@context'] : [nil]
rescue JsonLdError => e
Expand Down Expand Up @@ -857,7 +856,7 @@ def create_term_definition(local_context, term, defined, from_property: false, f
end
end

if previous_definition && previous_definition.protected? && definition != previous_definition && !from_property
if previous_definition && previous_definition.protected? && definition != previous_definition && !override_protected
definition = previous_definition
raise JSON::LD::JsonLdError::ProtectedTermRedefinition, "Attempt to redefine protected term #{term}"
end
Expand Down
8 changes: 4 additions & 4 deletions lib/json/ld/expand.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def expand(input, active_property, context, ordered: false, framing: false, from
end

# Apply property-scoped context after reverting term-scoped context
context = property_scoped_context ? context.parse(property_scoped_context, from_property: true) : context
context = property_scoped_context ? context.parse(property_scoped_context, override_protected: true) : context

# If element contains the key @context, set active context to the result of the Context Processing algorithm, passing active context and the value of the @context key as local context.
if input.has_key?('@context')
Expand All @@ -90,7 +90,7 @@ def expand(input, active_property, context, ordered: false, framing: false, from
if type_key
Array(input[type_key]).sort.each do |term|
term_context = type_scoped_context.term_definitions[term].context if type_scoped_context.term_definitions[term]
context = term_context ? context.parse(term_context, from_type: true) : context
context = term_context ? context.parse(term_context, propagate: false) : context
end
end

Expand Down Expand Up @@ -169,7 +169,7 @@ def expand(input, active_property, context, ordered: false, framing: false, from
return nil if input.nil? || active_property.nil? || expanded_active_property == '@graph'

# Apply property-scoped context
context = property_scoped_context ? context.parse(property_scoped_context, from_property: true) : context
context = property_scoped_context ? context.parse(property_scoped_context, override_protected: true) : context

context.expand_value(active_property, input, log_depth: @options[:log_depth])
end
Expand Down Expand Up @@ -451,7 +451,7 @@ def expand_object(input, active_property, context, output_object,
keys.each do |k|
# If container mapping in the active context includes @type, and k is a term in the active context having a local context, use that context when expanding values
map_context = container_context.term_definitions[k].context if container.include?('@type') && container_context.term_definitions[k]
map_context = container_context.parse(map_context, from_type: true) if map_context
map_context = container_context.parse(map_context, propagate: false) if map_context
map_context ||= container_context

expanded_k = container_context.expand_iri(k, vocab: true, quiet: true).to_s
Expand Down

0 comments on commit 1e04382

Please sign in to comment.