json-ld 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/README.md +9 -8
- data/VERSION +1 -1
- data/bin/jsonld +2 -1
- data/lib/json/ld.rb +43 -42
- data/lib/json/ld/api.rb +184 -39
- data/lib/json/ld/compact.rb +1 -1
- data/lib/json/ld/context.rb +88 -58
- data/lib/json/ld/expand.rb +27 -25
- data/lib/json/ld/extensions.rb +0 -23
- data/lib/json/ld/flatten.rb +1 -1
- data/lib/json/ld/reader.rb +2 -2
- data/lib/json/ld/resource.rb +1 -1
- data/spec/api_spec.rb +3 -1
- data/spec/compact_spec.rb +6 -4
- data/spec/context_spec.rb +20 -35
- data/spec/expand_spec.rb +42 -22
- data/spec/frame_spec.rb +1 -1
- data/spec/from_rdf_spec.rb +4 -22
- data/spec/suite_compact_spec.rb +2 -19
- data/spec/suite_error_spec.rb +17 -0
- data/spec/suite_expand_spec.rb +2 -16
- data/spec/suite_flatten_spec.rb +2 -16
- data/spec/suite_frame_spec.rb +2 -16
- data/spec/suite_from_rdf_spec.rb +2 -18
- data/spec/suite_helper.rb +218 -60
- data/spec/suite_remote_doc_spec.rb +17 -0
- data/spec/suite_to_rdf_spec.rb +2 -19
- data/spec/to_rdf_spec.rb +5 -5
- data/spec/writer_spec.rb +3 -3
- metadata +8 -6
- data/spec/suite_error_expand_spec.rb +0 -23
    
        data/lib/json/ld/compact.rb
    CHANGED
    
    | @@ -133,7 +133,7 @@ module JSON::LD | |
| 133 133 | 
             
                              compacted_item[key] = expanded_item['@index']
         | 
| 134 134 | 
             
                            end
         | 
| 135 135 | 
             
                          else
         | 
| 136 | 
            -
                            raise  | 
| 136 | 
            +
                            raise JsonLdError::CompactionToListOfLists,
         | 
| 137 137 | 
             
                                  "key cannot have more than one list value" if result.has_key?(item_active_property)
         | 
| 138 138 | 
             
                          end
         | 
| 139 139 | 
             
                        end
         | 
    
        data/lib/json/ld/context.rb
    CHANGED
    
    | @@ -116,16 +116,19 @@ module JSON::LD | |
| 116 116 | 
             
                # @return [Context] A context provided to us that we can use without re-serializing XXX
         | 
| 117 117 | 
             
                attr_accessor :provided_context
         | 
| 118 118 |  | 
| 119 | 
            -
                # @!attribute [r] remote_contexts
         | 
| 120 | 
            -
                # @return [Array<String>] The list of remote contexts already processed
         | 
| 121 | 
            -
                attr_accessor :remote_contexts
         | 
| 122 | 
            -
             | 
| 123 119 | 
             
                # @!attribute [r] namer
         | 
| 124 120 | 
             
                # @return [BlankNodeNamer]
         | 
| 125 121 | 
             
                attr_accessor :namer
         | 
| 126 122 |  | 
| 127 123 | 
             
                ##
         | 
| 128 124 | 
             
                # Create new evaluation context
         | 
| 125 | 
            +
                # @param [Hash] options
         | 
| 126 | 
            +
                # @option options [String, #to_s] :base
         | 
| 127 | 
            +
                #   The Base IRI to use when expanding the document. This overrides the value of `input` if it is a _IRI_. If not specified and `input` is not an _IRI_, the base IRI defaults to the current document IRI if in a browser context, or the empty string if there is no document context.
         | 
| 128 | 
            +
                # @option options [Proc] :documentLoader
         | 
| 129 | 
            +
                #   The callback of the loader to be used to retrieve remote documents and contexts. If specified, it must be used to retrieve remote documents and contexts; otherwise, if not specified, the processor's built-in loader must be used. See {API.documentLoader} for the method signature.
         | 
| 130 | 
            +
                # @option options [Hash{Symbol => String}] :prefixes
         | 
| 131 | 
            +
                #   See `RDF::Reader#initialize`
         | 
| 129 132 | 
             
                # @yield [ec]
         | 
| 130 133 | 
             
                # @yieldparam [Context]
         | 
| 131 134 | 
             
                # @return [Context]
         | 
| @@ -136,12 +139,12 @@ module JSON::LD | |
| 136 139 | 
             
                    @doc_base.fragment = nil
         | 
| 137 140 | 
             
                    @doc_base.query = nil
         | 
| 138 141 | 
             
                  end
         | 
| 142 | 
            +
                  options[:documentLoader] ||= JSON::LD::API.method(:documentLoader)
         | 
| 139 143 | 
             
                  @term_definitions = {}
         | 
| 140 144 | 
             
                  @iri_to_term = {
         | 
| 141 145 | 
             
                    RDF.to_uri.to_s => "rdf",
         | 
| 142 146 | 
             
                    RDF::XSD.to_uri.to_s => "xsd"
         | 
| 143 147 | 
             
                  }
         | 
| 144 | 
            -
                  @remote_contexts = []
         | 
| 145 148 | 
             
                  @namer = BlankNodeMapper.new("t")
         | 
| 146 149 |  | 
| 147 150 | 
             
                  @options = options
         | 
| @@ -151,7 +154,7 @@ module JSON::LD | |
| 151 154 | 
             
                    @iri_to_term[v.to_s] = k unless k.nil?
         | 
| 152 155 | 
             
                  end
         | 
| 153 156 |  | 
| 154 | 
            -
                  debug("init") {"iri_to_term: #{iri_to_term.inspect}"}
         | 
| 157 | 
            +
                  #debug("init") {"iri_to_term: #{iri_to_term.inspect}"}
         | 
| 155 158 |  | 
| 156 159 | 
             
                  yield(self) if block_given?
         | 
| 157 160 | 
             
                end
         | 
| @@ -159,12 +162,12 @@ module JSON::LD | |
| 159 162 | 
             
                # @param [String] value must be an absolute IRI
         | 
| 160 163 | 
             
                def base=(value)
         | 
| 161 164 | 
             
                  if value
         | 
| 162 | 
            -
                    raise  | 
| 165 | 
            +
                    raise JsonLdError::InvalidBaseIRI, "@base must be a string: #{value.inspect}" unless value.is_a?(String) || value.is_a?(RDF::URI)
         | 
| 163 166 | 
             
                    @base = RDF::URI(value)
         | 
| 164 167 | 
             
                    @base.canonicalize!
         | 
| 165 168 | 
             
                    @base.fragment = nil
         | 
| 166 169 | 
             
                    @base.query = nil
         | 
| 167 | 
            -
                    raise  | 
| 170 | 
            +
                    raise JsonLdError::InvalidBaseIRI, "@base must be an absolute IRI: #{value.inspect}" unless @base.absolute?
         | 
| 168 171 | 
             
                    @base
         | 
| 169 172 | 
             
                  else
         | 
| 170 173 | 
             
                    @base = nil
         | 
| @@ -175,7 +178,7 @@ module JSON::LD | |
| 175 178 | 
             
                # @param [String] value
         | 
| 176 179 | 
             
                def default_language=(value)
         | 
| 177 180 | 
             
                  @default_language = if value
         | 
| 178 | 
            -
                    raise  | 
| 181 | 
            +
                    raise JsonLdError::InvalidDefaultLanguage, "@language must be a string: #{value.inspect}" unless value.is_a?(String)
         | 
| 179 182 | 
             
                    value.downcase
         | 
| 180 183 | 
             
                  else
         | 
| 181 184 | 
             
                    nil
         | 
| @@ -189,12 +192,12 @@ module JSON::LD | |
| 189 192 | 
             
                    value
         | 
| 190 193 | 
             
                  when String
         | 
| 191 194 | 
             
                    v = as_resource(value)
         | 
| 192 | 
            -
                    raise  | 
| 195 | 
            +
                    raise JsonLdError::InvalidVocabMapping, "@value must be an absolute IRI: #{value.inspect}" if v.uri? && v.relative?
         | 
| 193 196 | 
             
                    v
         | 
| 194 197 | 
             
                  when nil
         | 
| 195 198 | 
             
                    nil
         | 
| 196 199 | 
             
                  else
         | 
| 197 | 
            -
                    raise  | 
| 200 | 
            +
                    raise JsonLdError::InvalidVocabMapping, "@value must be a string: #{value.inspect}"
         | 
| 198 201 | 
             
                  end
         | 
| 199 202 | 
             
                end
         | 
| 200 203 |  | 
| @@ -208,7 +211,7 @@ module JSON::LD | |
| 208 211 | 
             
                # 
         | 
| 209 212 | 
             
                #
         | 
| 210 213 | 
             
                # @param [String, #read, Array, Hash, Context] local_context
         | 
| 211 | 
            -
                # @raise [ | 
| 214 | 
            +
                # @raise [JsonLdError]
         | 
| 212 215 | 
             
                #   on a remote context load error, syntax error, or a reference to a term which is not defined.
         | 
| 213 216 | 
             
                # @see http://json-ld.org/spec/latest/json-ld-api/index.html#context-processing-algorithm
         | 
| 214 217 | 
             
                def parse(local_context, remote_contexts = [])
         | 
| @@ -229,46 +232,57 @@ module JSON::LD | |
| 229 232 | 
             
                        # Load context document, if it is a string
         | 
| 230 233 | 
             
                        begin
         | 
| 231 234 | 
             
                          ctx = JSON.load(context)
         | 
| 232 | 
            -
                          raise JSON::LD:: | 
| 235 | 
            +
                          raise JSON::LD::JsonLdError::InvalidRemoteContext, "Context missing @context key" if @options[:validate] && ctx['@context'].nil?
         | 
| 233 236 | 
             
                          result = parse(ctx["@context"] ? ctx["@context"].dup : {})
         | 
| 234 237 | 
             
                          result.provided_context = ctx["@context"]
         | 
| 235 238 | 
             
                          result
         | 
| 236 239 | 
             
                        rescue JSON::ParserError => e
         | 
| 237 240 | 
             
                          debug("parse") {"Failed to parse @context from remote document at #{context}: #{e.message}"}
         | 
| 238 | 
            -
                          raise JSON::LD:: | 
| 241 | 
            +
                          raise JSON::LD::JsonLdError::InvalidRemoteContext, "Failed to parse remote context at #{context}: #{e.message}" if @options[:validate]
         | 
| 239 242 | 
             
                          self.dup
         | 
| 240 243 | 
             
                        end
         | 
| 241 | 
            -
                      when String
         | 
| 244 | 
            +
                      when String, RDF::URI
         | 
| 242 245 | 
             
                        debug("parse") {"remote: #{context}, base: #{result.context_base || result.base}"}
         | 
| 243 246 | 
             
                        # Load context document, if it is a string
         | 
| 244 | 
            -
                         | 
| 245 | 
            -
             | 
| 246 | 
            -
                          context = RDF::URI(result.context_base || result.base).join(context)
         | 
| 247 | 
            +
                        # 3.2.1) Set context to the result of resolving value against the base IRI which is established as specified in section 5.1 Establishing a Base URI of [RFC3986]. 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].
         | 
| 248 | 
            +
                        context = RDF::URI(result.context_base || result.base).join(context)
         | 
| 247 249 |  | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            +
                        raise JsonLdError::RecursiveContextInclusion, "#{context}" if remote_contexts.include?(context.to_s)
         | 
| 251 | 
            +
                        remote_contexts << context.to_s
         | 
| 250 252 |  | 
| 251 | 
            -
             | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
                          context_no_base. | 
| 253 | 
            +
                        context_no_base = self.dup
         | 
| 254 | 
            +
                        context_no_base.base = nil
         | 
| 255 | 
            +
                        unless @options[:processingMode] == "json-ld-1.0"
         | 
| 256 | 
            +
                          context_no_base.provided_context = context.to_s
         | 
| 257 | 
            +
                        end
         | 
| 258 | 
            +
                        context_no_base.context_base = context.to_s
         | 
| 255 259 |  | 
| 256 | 
            -
             | 
| 260 | 
            +
                        begin
         | 
| 261 | 
            +
                          @options[:documentLoader].call(context.to_s) do |remote_doc|
         | 
| 257 262 | 
             
                            # 3.2.5) Dereference context. If the dereferenced document has no top-level JSON object with an @context member, an invalid remote context has been detected and processing is aborted; otherwise, set context to the value of that member.
         | 
| 258 | 
            -
                            jo =  | 
| 259 | 
            -
                             | 
| 263 | 
            +
                            jo = case remote_doc.document
         | 
| 264 | 
            +
                            when String then JSON.parse(remote_doc.document)
         | 
| 265 | 
            +
                            else remote_doc.document
         | 
| 266 | 
            +
                            end
         | 
| 267 | 
            +
                            raise JsonLdError::InvalidRemoteContext, "#{context}" unless jo.is_a?(Hash) && jo.has_key?('@context')
         | 
| 260 268 | 
             
                            context = jo['@context']
         | 
| 269 | 
            +
                            if @options[:processingMode] == "json-ld-1.0"
         | 
| 270 | 
            +
                              context_no_base.provided_context = context.dup
         | 
| 271 | 
            +
                            end
         | 
| 261 272 | 
             
                          end
         | 
| 262 | 
            -
             | 
| 263 | 
            -
                           | 
| 264 | 
            -
                          context = context_no_base.parse(context, remote_contexts.dup)
         | 
| 265 | 
            -
                          context.base = result.base unless result.base.nil?
         | 
| 266 | 
            -
                          result = context
         | 
| 267 | 
            -
                          debug("parse") {"=> provided_context: #{context.inspect}"}
         | 
| 273 | 
            +
                        rescue JsonLdError
         | 
| 274 | 
            +
                          raise
         | 
| 268 275 | 
             
                        rescue Exception => e
         | 
| 269 276 | 
             
                          debug("parse") {"Failed to retrieve @context from remote document at #{context_no_base.context_base.inspect}: #{e.message}"}
         | 
| 270 | 
            -
                          raise  | 
| 277 | 
            +
                          raise JsonLdError::LoadingRemoteContextFailed, "#{context_no_base.context_base}", e.backtrace if @options[:validate]
         | 
| 271 278 | 
             
                        end
         | 
| 279 | 
            +
             | 
| 280 | 
            +
                        # 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.
         | 
| 281 | 
            +
                        context = context_no_base.parse(context, remote_contexts.dup)
         | 
| 282 | 
            +
                        context.provided_context = context_no_base.provided_context
         | 
| 283 | 
            +
                        context.base ||= result.base
         | 
| 284 | 
            +
                        result = context
         | 
| 285 | 
            +
                        debug("parse") {"=> provided_context: #{context.inspect}"}
         | 
| 272 286 | 
             
                      when Hash
         | 
| 273 287 | 
             
                        # If context has a @vocab member: if its value is not a valid absolute IRI or null trigger an INVALID_VOCAB_MAPPING error; otherwise set the active context's vocabulary mapping to its value and remove the @vocab member from context.
         | 
| 274 288 | 
             
                        {
         | 
| @@ -293,7 +307,7 @@ module JSON::LD | |
| 293 307 | 
             
                        end
         | 
| 294 308 | 
             
                      else
         | 
| 295 309 | 
             
                        # 3.3) If context is not a JSON object, an invalid local context error has been detected and processing is aborted.
         | 
| 296 | 
            -
                        raise  | 
| 310 | 
            +
                        raise JsonLdError::InvalidLocalContext
         | 
| 297 311 | 
             
                      end
         | 
| 298 312 | 
             
                    end
         | 
| 299 313 | 
             
                  end
         | 
| @@ -311,7 +325,7 @@ module JSON::LD | |
| 311 325 | 
             
                # @param [Hash] local_context
         | 
| 312 326 | 
             
                # @param [String] term
         | 
| 313 327 | 
             
                # @param [Hash] defined
         | 
| 314 | 
            -
                # @raise [ | 
| 328 | 
            +
                # @raise [JsonLdError]
         | 
| 315 329 | 
             
                #   Represents a cyclical term dependency
         | 
| 316 330 | 
             
                # @see http://json-ld.org/spec/latest/json-ld-api/index.html#create-term-definition
         | 
| 317 331 | 
             
                def create_term_definition(local_context, term, defined)
         | 
| @@ -324,15 +338,15 @@ module JSON::LD | |
| 324 338 | 
             
                  when nil
         | 
| 325 339 | 
             
                    defined[term] = false
         | 
| 326 340 | 
             
                  else
         | 
| 327 | 
            -
                    raise  | 
| 341 | 
            +
                    raise JsonLdError::CyclicIRIMapping, "Cyclical term dependency found for #{term.inspect}"
         | 
| 328 342 | 
             
                  end
         | 
| 329 343 |  | 
| 330 344 | 
             
                  # Since keywords cannot be overridden, term must not be a keyword. Otherwise, an invalid value has been detected, which is an error.
         | 
| 331 345 | 
             
                  if KEYWORDS.include?(term) && !%w(@vocab @language).include?(term)
         | 
| 332 | 
            -
                    raise  | 
| 346 | 
            +
                    raise JsonLdError::KeywordRedefinition, "term #{term.inspect} must not be a keyword" if
         | 
| 333 347 | 
             
                      @options[:validate]
         | 
| 334 348 | 
             
                  elsif !term_valid?(term) && @options[:validate]
         | 
| 335 | 
            -
                    raise  | 
| 349 | 
            +
                    raise JsonLdError::InvalidTermDefinition, "term #{term.inspect} is invalid"
         | 
| 336 350 | 
             
                  end
         | 
| 337 351 |  | 
| 338 352 | 
             
                  # Remove any existing term definition for term in active context.
         | 
| @@ -356,16 +370,29 @@ module JSON::LD | |
| 356 370 | 
             
                    if value.has_key?('@type')
         | 
| 357 371 | 
             
                      type = value['@type']
         | 
| 358 372 | 
             
                      # SPEC FIXME: @type may be nil
         | 
| 359 | 
            -
                       | 
| 360 | 
            -
                       | 
| 373 | 
            +
                      type = case type
         | 
| 374 | 
            +
                      when nil
         | 
| 375 | 
            +
                        type
         | 
| 376 | 
            +
                      when String
         | 
| 377 | 
            +
                        begin
         | 
| 378 | 
            +
                          expand_iri(type, :vocab => true, :documentRelative => false, :local_context => local_context, :defined => defined)
         | 
| 379 | 
            +
                        rescue JsonLdError::InvalidIRIMapping
         | 
| 380 | 
            +
                          raise JsonLdError::InvalidTypeMapping, "invalid mapping for '@type' to #{type.inspect}"
         | 
| 381 | 
            +
                        end
         | 
| 382 | 
            +
                      else
         | 
| 383 | 
            +
                        :error
         | 
| 384 | 
            +
                      end
         | 
| 385 | 
            +
                      unless %w(@id @vocab).include?(type) || type.is_a?(RDF::URI) && type.absolute?
         | 
| 386 | 
            +
                        raise JsonLdError::InvalidTypeMapping, "unknown mapping for '@type' to #{type.inspect}"
         | 
| 387 | 
            +
                      end
         | 
| 361 388 | 
             
                      debug("") {"type_mapping: #{type.inspect}"}
         | 
| 362 389 | 
             
                      definition.type_mapping = type
         | 
| 363 390 | 
             
                    end
         | 
| 364 391 |  | 
| 365 392 | 
             
                    if value.has_key?('@reverse')
         | 
| 366 | 
            -
                      raise  | 
| 393 | 
            +
                      raise JsonLdError::InvalidReverseProperty, "unexpected key in #{value.inspect}" if
         | 
| 367 394 | 
             
                        value.keys.any? {|k| %w(@id).include?(k)}
         | 
| 368 | 
            -
                      raise  | 
| 395 | 
            +
                      raise JsonLdError::InvalidIRIMapping, "expected value of @reverse to be a string" unless
         | 
| 369 396 | 
             
                        value['@reverse'].is_a?(String)
         | 
| 370 397 |  | 
| 371 398 | 
             
                      # Otherwise, set the IRI mapping of definition to the result of using the IRI Expansion algorithm, passing active context, the value associated with the @reverse key for value, true for vocab, true for document relative, local context, and defined. If the result is not an absolute IRI, i.e., it contains no colon (:), an invalid IRI mapping error has been detected and processing is aborted.
         | 
| @@ -374,25 +401,27 @@ module JSON::LD | |
| 374 401 | 
             
                                                  :documentRelative => true,
         | 
| 375 402 | 
             
                                                  :local_context => local_context,
         | 
| 376 403 | 
             
                                                  :defined => defined)
         | 
| 377 | 
            -
                      raise  | 
| 378 | 
            -
                        definition.id.absolute?
         | 
| 404 | 
            +
                      raise JsonLdError::InvalidIRIMapping, "non-absolute @reverse IRI: #{definition.id}" unless
         | 
| 405 | 
            +
                        definition.id.is_a?(RDF::URI) && definition.id.absolute?
         | 
| 379 406 |  | 
| 380 407 | 
             
                      # If value contains an @container member, set the container mapping of definition to its value; if its value is neither @set, nor @index, nor null, an invalid reverse property error has been detected (reverse properties only support set- and index-containers) and processing is aborted.
         | 
| 381 408 | 
             
                      if (container = value['@container'])
         | 
| 382 | 
            -
                        raise  | 
| 409 | 
            +
                        raise JsonLdError::InvalidReverseProperty,
         | 
| 383 410 | 
             
                              "unknown mapping for '@container' to #{container.inspect}" unless
         | 
| 384 411 | 
             
                               ['@set', '@index', nil].include?(container)
         | 
| 385 412 | 
             
                        definition.container_mapping = container
         | 
| 386 413 | 
             
                      end
         | 
| 387 414 | 
             
                      definition.reverse_property = true
         | 
| 388 415 | 
             
                    elsif value.has_key?('@id') && value['@id'] != term
         | 
| 389 | 
            -
                      raise  | 
| 416 | 
            +
                      raise JsonLdError::InvalidIRIMapping, "expected value of @id to be a string" unless
         | 
| 390 417 | 
             
                        value['@id'].is_a?(String)
         | 
| 391 418 | 
             
                      definition.id = expand_iri(value['@id'],
         | 
| 392 419 | 
             
                        :vocab => true,
         | 
| 393 420 | 
             
                        :documentRelative => true,
         | 
| 394 421 | 
             
                        :local_context => local_context,
         | 
| 395 422 | 
             
                        :defined => defined)
         | 
| 423 | 
            +
                      raise JsonLdError::InvalidKeywordAlias, "expected value of @id to not be @context" if
         | 
| 424 | 
            +
                        definition.id == '@context'
         | 
| 396 425 | 
             
                    elsif term.include?(':')
         | 
| 397 426 | 
             
                      # If term is a compact IRI with a prefix that is a key in local context then a dependency has been found. Use this algorithm recursively passing active context, local context, the prefix as term, and defined.
         | 
| 398 427 | 
             
                      prefix, suffix = term.split(':')
         | 
| @@ -408,21 +437,21 @@ module JSON::LD | |
| 408 437 | 
             
                      debug("") {"=> #{definition.id}"}
         | 
| 409 438 | 
             
                    else
         | 
| 410 439 | 
             
                      # Otherwise, active context must have a vocabulary mapping, otherwise an invalid value has been detected, which is an error. Set the IRI mapping for definition to the result of concatenating the value associated with the vocabulary mapping and term.
         | 
| 411 | 
            -
                      raise  | 
| 440 | 
            +
                      raise JsonLdError::InvalidIRIMapping, "relative term definition without vocab" unless vocab
         | 
| 412 441 | 
             
                      definition.id = vocab + term
         | 
| 413 442 | 
             
                      debug("") {"=> #{definition.id}"}
         | 
| 414 443 | 
             
                    end
         | 
| 415 444 |  | 
| 416 445 | 
             
                    if value.has_key?('@container')
         | 
| 417 446 | 
             
                      container = value['@container']
         | 
| 418 | 
            -
                      raise  | 
| 447 | 
            +
                      raise JsonLdError::InvalidContainerMapping, "unknown mapping for '@container' to #{container.inspect}" unless %w(@list @set @language @index).include?(container)
         | 
| 419 448 | 
             
                      debug("") {"container_mapping: #{container.inspect}"}
         | 
| 420 449 | 
             
                      definition.container_mapping = container
         | 
| 421 450 | 
             
                    end
         | 
| 422 451 |  | 
| 423 452 | 
             
                    if value.has_key?('@language')
         | 
| 424 453 | 
             
                      language = value['@language']
         | 
| 425 | 
            -
                      raise  | 
| 454 | 
            +
                      raise JsonLdError::InvalidLanguageMapping, "language must be null or a string, was #{language.inspect}}" unless language.nil? || (language || "").is_a?(String)
         | 
| 426 455 | 
             
                      language = language.downcase if language.is_a?(String)
         | 
| 427 456 | 
             
                      debug("") {"language_mapping: #{language.inspect}"}
         | 
| 428 457 | 
             
                      definition.language_mapping = language || false
         | 
| @@ -431,7 +460,7 @@ module JSON::LD | |
| 431 460 | 
             
                    term_definitions[term] = definition
         | 
| 432 461 | 
             
                    defined[term] = true
         | 
| 433 462 | 
             
                  else
         | 
| 434 | 
            -
                    raise  | 
| 463 | 
            +
                    raise JsonLdError::InvalidTermDefinition, "Term definition for #{term.inspect} is an #{value.class}"
         | 
| 435 464 | 
             
                  end
         | 
| 436 465 | 
             
                end
         | 
| 437 466 |  | 
| @@ -447,7 +476,7 @@ module JSON::LD | |
| 447 476 | 
             
                  depth(options) do
         | 
| 448 477 | 
             
                    # FIXME: not setting provided_context now
         | 
| 449 478 | 
             
                    use_context = case provided_context
         | 
| 450 | 
            -
                    when RDF::URI
         | 
| 479 | 
            +
                    when String, RDF::URI
         | 
| 451 480 | 
             
                      debug "serlialize: reuse context: #{provided_context.inspect}"
         | 
| 452 481 | 
             
                      provided_context.to_s
         | 
| 453 482 | 
             
                    when Hash, Array
         | 
| @@ -462,7 +491,7 @@ module JSON::LD | |
| 462 491 | 
             
                      ctx['@vocab'] = vocab.to_s if vocab
         | 
| 463 492 |  | 
| 464 493 | 
             
                      # Term Definitions
         | 
| 465 | 
            -
                      term_definitions.each do |term, definition|
         | 
| 494 | 
            +
                      term_definitions.dup.each do |term, definition|
         | 
| 466 495 | 
             
                        ctx[term] = definition.to_context_definition(self)
         | 
| 467 496 | 
             
                      end
         | 
| 468 497 |  | 
| @@ -611,7 +640,7 @@ module JSON::LD | |
| 611 640 | 
             
                #   Used during Context Processing.
         | 
| 612 641 | 
             
                # @return [RDF::URI, String]
         | 
| 613 642 | 
             
                #   IRI or String, if it's a keyword
         | 
| 614 | 
            -
                # @raise [JSON::LD:: | 
| 643 | 
            +
                # @raise [JSON::LD::JsonLdError::InvalidIRIMapping] if the value cannot be expanded
         | 
| 615 644 | 
             
                # @see http://json-ld.org/spec/latest/json-ld-api/#iri-expansion
         | 
| 616 645 | 
             
                def expand_iri(value, options = {})
         | 
| 617 646 | 
             
                  return value unless value.is_a?(String)
         | 
| @@ -668,7 +697,7 @@ module JSON::LD | |
| 668 697 | 
             
                      RDF::URI(base).join(value)
         | 
| 669 698 | 
             
                    elsif local_context && RDF::URI(value).relative?
         | 
| 670 699 | 
             
                      # 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.
         | 
| 671 | 
            -
                      raise JSON::LD:: | 
| 700 | 
            +
                      raise JSON::LD::JsonLdError::InvalidIRIMapping, "not an absolute IRI: #{value}"
         | 
| 672 701 | 
             
                    else
         | 
| 673 702 | 
             
                      RDF::URI(value)
         | 
| 674 703 | 
             
                    end
         | 
| @@ -813,7 +842,7 @@ module JSON::LD | |
| 813 842 | 
             
                    # try those, and add to mapping
         | 
| 814 843 | 
             
                    if @options[:standard_prefixes]
         | 
| 815 844 | 
             
                      candidates = RDF::Vocabulary.
         | 
| 816 | 
            -
                        select {|v| iri.start_with?(v.to_uri.to_s)}.
         | 
| 845 | 
            +
                        select {|v| iri.start_with?(v.to_uri.to_s) && iri != v.to_uri.to_s}.
         | 
| 817 846 | 
             
                        map do |v|
         | 
| 818 847 | 
             
                          prefix = v.__name__.to_s.split('::').last.downcase
         | 
| 819 848 | 
             
                          set_mapping(prefix, v.to_uri.to_s)
         | 
| @@ -854,7 +883,7 @@ module JSON::LD | |
| 854 883 | 
             
                # @raise [RDF::ReaderError] if the iri cannot be expanded
         | 
| 855 884 | 
             
                # @see http://json-ld.org/spec/latest/json-ld-api/#value-expansion
         | 
| 856 885 | 
             
                def expand_value(property, value, options = {})
         | 
| 857 | 
            -
                  options = {:useNativeTypes =>  | 
| 886 | 
            +
                  options = {:useNativeTypes => false}.merge(options)
         | 
| 858 887 | 
             
                  depth(options) do
         | 
| 859 888 | 
             
                    debug("expand_value") {"property: #{property.inspect}, value: #{value.inspect}"}
         | 
| 860 889 |  | 
| @@ -928,7 +957,7 @@ module JSON::LD | |
| 928 957 | 
             
                # @param  [Hash{Symbol => Object}] options
         | 
| 929 958 | 
             
                #
         | 
| 930 959 | 
             
                # @return [Hash] Object representation of value
         | 
| 931 | 
            -
                # @raise [ | 
| 960 | 
            +
                # @raise [JsonLdError] if the iri cannot be expanded
         | 
| 932 961 | 
             
                # @see http://json-ld.org/spec/latest/json-ld-api/#value-compaction
         | 
| 933 962 | 
             
                # FIXME: revisit the specification version of this.
         | 
| 934 963 | 
             
                def compact_value(property, value, options = {})
         | 
| @@ -994,6 +1023,7 @@ module JSON::LD | |
| 994 1023 |  | 
| 995 1024 | 
             
                def inspect
         | 
| 996 1025 | 
             
                  v = %w([Context)
         | 
| 1026 | 
            +
                  v << "base=#{base}" if base
         | 
| 997 1027 | 
             
                  v << "vocab=#{vocab}" if vocab
         | 
| 998 1028 | 
             
                  v << "def_language=#{default_language}" if default_language
         | 
| 999 1029 | 
             
                  v << "term_definitions[#{term_definitions.length}]=#{term_definitions}"
         | 
    
        data/lib/json/ld/expand.rb
    CHANGED
    
    | @@ -24,7 +24,7 @@ module JSON::LD | |
| 24 24 | 
             
                        v = expand(v, active_property, context, options)
         | 
| 25 25 |  | 
| 26 26 | 
             
                        # If the active property is @list or its container mapping is set to @list, the expanded item must not be an array or a list object, otherwise a list of lists error has been detected and processing is aborted.
         | 
| 27 | 
            -
                        raise  | 
| 27 | 
            +
                        raise JsonLdError::ListOfLists,
         | 
| 28 28 | 
             
                              "A list may not contain another list" if
         | 
| 29 29 | 
             
                              is_list && (v.is_a?(Array) || list?(v))
         | 
| 30 30 | 
             
                        v
         | 
| @@ -60,17 +60,17 @@ module JSON::LD | |
| 60 60 |  | 
| 61 61 | 
             
                        if KEYWORDS.include?(expanded_property)
         | 
| 62 62 | 
             
                          # If active property equals @reverse, an invalid reverse property map error has been detected and processing is aborted.
         | 
| 63 | 
            -
                          raise  | 
| 63 | 
            +
                          raise JsonLdError::InvalidReversePropertyMap,
         | 
| 64 64 | 
             
                                "@reverse not appropriate at this point" if active_property == '@reverse'
         | 
| 65 65 |  | 
| 66 66 | 
             
                          # If result has already an expanded property member, an colliding keywords error has been detected and processing is aborted.
         | 
| 67 | 
            -
                          raise  | 
| 67 | 
            +
                          raise JsonLdError::CollidingKeywords,
         | 
| 68 68 | 
             
                                "#{expanded_property} already exists in result" if output_object.has_key?(expanded_property)
         | 
| 69 69 |  | 
| 70 70 | 
             
                          expanded_value = case expanded_property
         | 
| 71 71 | 
             
                          when '@id'
         | 
| 72 72 | 
             
                            # If expanded property is @id and value is not a string, an invalid @id value error has been detected and processing is aborted
         | 
| 73 | 
            -
                            raise  | 
| 73 | 
            +
                            raise JsonLdError::InvalidIdValue,
         | 
| 74 74 | 
             
                                  "value of @id must be a string: #{value.inspect}" unless value.is_a?(String)
         | 
| 75 75 |  | 
| 76 76 | 
             
                            # Otherwise, set expanded value to the result of using the IRI Expansion algorithm, passing active context, value, and true for document relative.
         | 
| @@ -82,7 +82,7 @@ module JSON::LD | |
| 82 82 | 
             
                            when Array
         | 
| 83 83 | 
             
                              depth do
         | 
| 84 84 | 
             
                                value.map do |v|
         | 
| 85 | 
            -
                                  raise  | 
| 85 | 
            +
                                  raise JsonLdError::InvalidTypeValue,
         | 
| 86 86 | 
             
                                        "@type value must be a string or array of strings: #{v.inspect}" unless v.is_a?(String)
         | 
| 87 87 | 
             
                                  context.expand_iri(v, :vocab => true, :documentRelative => true, :quiet => true, :depth => @depth).to_s
         | 
| 88 88 | 
             
                                end
         | 
| @@ -91,11 +91,11 @@ module JSON::LD | |
| 91 91 | 
             
                              context.expand_iri(value, :vocab => true, :documentRelative => true, :quiet => true, :depth => @depth).to_s
         | 
| 92 92 | 
             
                            when Hash
         | 
| 93 93 | 
             
                              # For framing
         | 
| 94 | 
            -
                              raise  | 
| 94 | 
            +
                              raise JsonLdError::InvalidTypeValue,
         | 
| 95 95 | 
             
                                    "@type value must be a an empty object for framing: #{value.inspect}" unless
         | 
| 96 96 | 
             
                                    value.empty?
         | 
| 97 97 | 
             
                            else
         | 
| 98 | 
            -
                              raise  | 
| 98 | 
            +
                              raise JsonLdError::InvalidTypeValue,
         | 
| 99 99 | 
             
                                    "@type value must be a string or array of strings: #{value.inspect}"
         | 
| 100 100 | 
             
                            end
         | 
| 101 101 | 
             
                          when '@graph'
         | 
| @@ -103,7 +103,7 @@ module JSON::LD | |
| 103 103 | 
             
                            depth { expand(value, '@graph', context, options) }
         | 
| 104 104 | 
             
                          when '@value'
         | 
| 105 105 | 
             
                            # If expanded property is @value and value is not a scalar or null, an invalid value object value error has been detected and processing is aborted. Otherwise, set expanded value to value. If expanded value is null, set the @value member of result to null and continue with the next key from element. Null values need to be preserved in this case as the meaning of an @type member depends on the existence of an @value member.
         | 
| 106 | 
            -
                            raise  | 
| 106 | 
            +
                            raise JsonLdError::InvalidValueObjectValue,
         | 
| 107 107 | 
             
                                  "Value of #{expanded_property} must be a scalar or null: #{value.inspect}" if value.is_a?(Hash) || value.is_a?(Array)
         | 
| 108 108 | 
             
                            if value.nil?
         | 
| 109 109 | 
             
                              output_object['@value'] = nil
         | 
| @@ -112,12 +112,12 @@ module JSON::LD | |
| 112 112 | 
             
                            value
         | 
| 113 113 | 
             
                          when '@language'
         | 
| 114 114 | 
             
                            # If expanded property is @language and value is not a string, an invalid language-tagged string error has been detected and processing is aborted. Otherwise, set expanded value to lowercased value.
         | 
| 115 | 
            -
                            raise  | 
| 115 | 
            +
                            raise JsonLdError::InvalidLanguageTaggedString,
         | 
| 116 116 | 
             
                                  "Value of #{expanded_property} must be a string: #{value.inspect}" unless value.is_a?(String)
         | 
| 117 117 | 
             
                            value.downcase
         | 
| 118 118 | 
             
                          when '@index'
         | 
| 119 119 | 
             
                            # If expanded property is @index and value is not a string, an invalid @index value error has been detected and processing is aborted. Otherwise, set expanded value to value.
         | 
| 120 | 
            -
                            raise  | 
| 120 | 
            +
                            raise JsonLdError::InvalidIndexValue,
         | 
| 121 121 | 
             
                                  "Value of @index is not a string: #{value.inspect}" unless value.is_a?(String)
         | 
| 122 122 | 
             
                            value
         | 
| 123 123 | 
             
                          when '@list'
         | 
| @@ -134,7 +134,7 @@ module JSON::LD | |
| 134 134 |  | 
| 135 135 | 
             
                            # If expanded value is a list object, a list of lists error has been detected and processing is aborted.
         | 
| 136 136 | 
             
                            # Spec FIXME: Also look at each object if result is an array
         | 
| 137 | 
            -
                            raise  | 
| 137 | 
            +
                            raise JsonLdError::ListOfLists,
         | 
| 138 138 | 
             
                                  "A list may not contain another list" if value.any? {|v| list?(v)}
         | 
| 139 139 |  | 
| 140 140 | 
             
                            value
         | 
| @@ -143,7 +143,7 @@ module JSON::LD | |
| 143 143 | 
             
                            depth { expand(value, active_property, context, options) }
         | 
| 144 144 | 
             
                          when '@reverse'
         | 
| 145 145 | 
             
                            # If expanded property is @reverse and value is not a JSON object, an invalid @reverse value error has been detected and processing is aborted.
         | 
| 146 | 
            -
                            raise  | 
| 146 | 
            +
                            raise JsonLdError::InvalidReverseValue,
         | 
| 147 147 | 
             
                                  "@reverse value must be an object: #{value.inspect}" unless value.is_a?(Hash)
         | 
| 148 148 |  | 
| 149 149 | 
             
                            # Otherwise
         | 
| @@ -168,8 +168,8 @@ module JSON::LD | |
| 168 168 | 
             
                                next if property == '@reverse'
         | 
| 169 169 | 
             
                                items.each do |item|
         | 
| 170 170 | 
             
                                  if value?(item) || list?(item)
         | 
| 171 | 
            -
                                    raise  | 
| 172 | 
            -
                                           | 
| 171 | 
            +
                                    raise JsonLdError::InvalidReversePropertyValue,
         | 
| 172 | 
            +
                                          item.inspect
         | 
| 173 173 | 
             
                                  end
         | 
| 174 174 | 
             
                                  merge_value(reverse_map, property, item)
         | 
| 175 175 | 
             
                                end
         | 
| @@ -202,7 +202,7 @@ module JSON::LD | |
| 202 202 | 
             
                          value.keys.sort.each do |k|
         | 
| 203 203 | 
             
                            [value[k]].flatten.each do |item|
         | 
| 204 204 | 
             
                              # item must be a string, otherwise an invalid language map value error has been detected and processing is aborted.
         | 
| 205 | 
            -
                              raise  | 
| 205 | 
            +
                              raise JsonLdError::InvalidLanguageMapValue,
         | 
| 206 206 | 
             
                                    "Expected #{item.inspect} to be a string" unless item.is_a?(String)
         | 
| 207 207 |  | 
| 208 208 | 
             
                              # Append a JSON object to expanded value that consists of two key-value pairs: (@value-item) and (@language-lowercased language).
         | 
| @@ -256,8 +256,8 @@ module JSON::LD | |
| 256 256 | 
             
                          reverse_map = output_object['@reverse'] ||= {}
         | 
| 257 257 | 
             
                          [expanded_value].flatten.each do |item|
         | 
| 258 258 | 
             
                            # If item is a value object or list object, an invalid reverse property value has been detected and processing is aborted.
         | 
| 259 | 
            -
                            raise  | 
| 260 | 
            -
                                   | 
| 259 | 
            +
                            raise JsonLdError::InvalidReversePropertyValue,
         | 
| 260 | 
            +
                                  item.inspect if value?(item) || list?(item)
         | 
| 261 261 |  | 
| 262 262 | 
             
                            # If reverse map has no expanded property member, create one and initialize its value to an empty array.
         | 
| 263 263 | 
             
                            # Append item to the value of the expanded property member of reverse map.
         | 
| @@ -274,9 +274,10 @@ module JSON::LD | |
| 274 274 |  | 
| 275 275 | 
             
                      # If result contains the key @value:
         | 
| 276 276 | 
             
                      if value?(output_object)
         | 
| 277 | 
            -
                        unless (output_object.keys - %w(@value @language @type @index)).empty?
         | 
| 277 | 
            +
                        unless (output_object.keys - %w(@value @language @type @index)).empty? &&
         | 
| 278 | 
            +
                               (output_object.keys & %w(@language @type)).length < 2
         | 
| 278 279 | 
             
                          # The result must not contain any keys other than @value, @language, @type, and @index. It must not contain both the @language key and the @type key. Otherwise, an invalid value object error has been detected and processing is aborted.
         | 
| 279 | 
            -
                          raise  | 
| 280 | 
            +
                          raise JsonLdError::InvalidValueObject,
         | 
| 280 281 | 
             
                          "value object has unknown keys: #{output_object.inspect}"
         | 
| 281 282 | 
             
                        end
         | 
| 282 283 |  | 
| @@ -288,12 +289,13 @@ module JSON::LD | |
| 288 289 |  | 
| 289 290 | 
             
                        if !output_object['@value'].is_a?(String) && output_object.has_key?('@language')
         | 
| 290 291 | 
             
                          # Otherwise, if the value of result's @value member is not a string and result contains the key @language, an invalid language-tagged value error has been detected (only strings can be language-tagged) and processing is aborted.
         | 
| 291 | 
            -
                          raise  | 
| 292 | 
            +
                          raise JsonLdError::InvalidLanguageTaggedValue,
         | 
| 292 293 | 
             
                                "when @language is used, @value must be a string: #{@value.inspect}"
         | 
| 293 | 
            -
                        elsif !output_object.fetch('@type', "").is_a?(String)
         | 
| 294 | 
            -
             | 
| 295 | 
            -
                           | 
| 296 | 
            -
             | 
| 294 | 
            +
                        elsif !output_object.fetch('@type', "").is_a?(String) ||
         | 
| 295 | 
            +
                              !context.expand_iri(output_object.fetch('@type', ""), :vocab => true, :depth => @depth).is_a?(RDF::URI)
         | 
| 296 | 
            +
                          # Otherwise, if the result has a @type member and its value is not an IRI, an invalid typed value error has been detected and processing is aborted.
         | 
| 297 | 
            +
                          raise JsonLdError::InvalidTypedValue,
         | 
| 298 | 
            +
                                "value of @type must be an IRI: #{output_object['@type'].inspect}"
         | 
| 297 299 | 
             
                        end
         | 
| 298 300 | 
             
                      elsif !output_object.fetch('@type', []).is_a?(Array)
         | 
| 299 301 | 
             
                        # Otherwise, if result contains the key @type and its associated value is not an array, set it to an array containing only the associated value.
         | 
| @@ -301,7 +303,7 @@ module JSON::LD | |
| 301 303 | 
             
                      elsif output_object.keys.any? {|k| %w(@set @list).include?(k)}
         | 
| 302 304 | 
             
                        # Otherwise, if result contains the key @set or @list:
         | 
| 303 305 | 
             
                        # The result must contain at most one other key and that key must be @index. Otherwise, an invalid set or list object error has been detected and processing is aborted.
         | 
| 304 | 
            -
                        raise  | 
| 306 | 
            +
                        raise JsonLdError::InvalidSetOrListObject,
         | 
| 305 307 | 
             
                              "@set or @list may only contain @index: #{output_object.keys.inspect}" unless
         | 
| 306 308 | 
             
                              (output_object.keys - %w(@set @list @index)).empty?
         | 
| 307 309 |  |