Skip to content

Commit

Permalink
Finish 2.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
gkellogg committed Aug 12, 2016
2 parents dddc28f + 0670805 commit a1ad43c
Show file tree
Hide file tree
Showing 26 changed files with 3,463 additions and 1,046 deletions.
13 changes: 5 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ script: "bundle exec rspec spec"
env:
- CI=true
rvm:
- 2.0
- 2.1
- 2.2.4
- 2.3.0
- jruby-9.0.4.0
- rbx-2
- 2.2.5
- 2.3.1
- jruby-9.1.2.0
- rbx
cache: bundler
sudo: false
matrix:
allow_failures:
- rvm: rbx-2
- rvm: jruby-9.0.4.0
- rvm: jruby-9.1.2.0


9 changes: 7 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ gem 'jsonlint', github: "dougbarth/jsonlint", platforms: [:rbx, :m

group :development do
gem 'ebnf', github: "gkellogg/ebnf", branch: "develop"
gem 'sxp', github: "gkellogg/sxp-ruby", branch: "develop"
gem 'sxp', github: "dryruby/sxp.rb", branch: "develop"
gem 'rdf-isomorphic', github: "ruby-rdf/rdf-isomorphic", branch: "develop"
gem 'rdf-turtle', github: "ruby-rdf/rdf-turtle", branch: "develop"
gem 'rdf-trig', github: "ruby-rdf/rdf-trig", branch: "develop"
Expand All @@ -20,6 +20,7 @@ group :development, :test do
gem 'simplecov', require: false, platform: :mri
gem 'coveralls', require: false, platform: :mri
gem 'psych', platforms: [:mri, :rbx]
gem 'benchmark-ips'
end

group :debug do
Expand All @@ -28,6 +29,10 @@ group :debug do
end

platforms :rbx do
gem 'rubysl', '~> 2.0'
gem 'rubysl', '~> 2.0'
gem 'rubinius', '~> 2.0'
end

platforms :jruby do
gem 'gson', '~> 0.6'
end
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,17 @@ Then, when performing something like expansion:

JSON::LD::API.expand(input, documentLoader: load_document_local)


## Preloading contexts
In many cases, for small documents, processing time can be dominated by loading and parsing remote contexts. In particular, a small schema.org example may need to download a large context and turn it into an internal representation, before the actual document can be expanded for processing. Using {JSON::LD::Context.add_preloaded}, an implementation can perform this loading up-front, and make it available to the processor.

ctx = JSON::LD::Context.new().parse('http://schema.org/')
JSON::LD::Context.add_preloaded('http://schema.org/', ctx)

On lookup, URIs with an `https` prefix are normalized to `http`.

A context may be serialized to Ruby to speed this process using `Context#to_rb`. When loaded, this generated file will add entries to the {JSON::LD::Context::PRELOADED}.

## RDF Reader and Writer
{JSON::LD} also acts as a normal RDF reader and writer, using the standard RDF.rb reader/writer interfaces:

Expand Down Expand Up @@ -274,7 +285,7 @@ Note, the API method signatures differed in versions before 1.0, in that they al
* {JSON::LD::Writer}

## Dependencies
* [Ruby](http://ruby-lang.org/) (>= 2.0)
* [Ruby](http://ruby-lang.org/) (>= 2.2.2)
* [RDF.rb](http://rubygems.org/gems/rdf) (>= 2.0)
* [JSON](https://rubygems.org/gems/json) (>= 1.5)

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.0.1
2.0.1
28 changes: 28 additions & 0 deletions example-files/nicholas-arduino-bench.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env ruby
require "bundler/setup"
require 'json/ld'
#require File.expand_path('../schema-context', __FILE__)
require 'benchmark/ips'

source = JSON.parse %({
"@context": "http://schema.org/",
"@type": "SoftwareApplication",
"name": "EtherSia",
"description": "IPv6 library for the ENC28J60 Ethernet controller",
"url": "https://github.com/njh/EtherSia",
"author": {
"@type": "Person",
"name": "Nicholas Humfrey <njh@aelius.com>"
},
"applicationCategory": "Communication",
"operatingSystem": "Arduino",
"downloadUrl": "http://downloads.arduino.cc/libraries/njh/EtherSia-1.0.0.zip",
"softwareVersion": "1.0.0",
"fileSize": 77
})


Benchmark.ips do |x|
x.config(time: 10, warmup: 1)
x.report('toRdf') {JSON::LD::API.toRdf(source)}
end
2,121 changes: 2,121 additions & 0 deletions example-files/schema-context.rb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion json-ld.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Gem::Specification.new do |gem|
gem.test_files = Dir.glob('spec/**/*.rb') + Dir.glob('spec/test-files/*')
gem.has_rdoc = false

gem.required_ruby_version = '>= 2.0'
gem.required_ruby_version = '>= 2.2.2'
gem.requirements = []
gem.add_runtime_dependency 'rdf', '~> 2.0'
gem.add_runtime_dependency 'multi_json', '~> 1.11'
Expand Down
4 changes: 3 additions & 1 deletion lib/json/ld.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..')))
# -*- encoding: utf-8 -*-
# frozen_string_literal: true
$:.unshift(File.expand_path("../ld", __FILE__))
require 'rdf' # @see http://rubygems.org/gems/rdf
require 'multi_json'

Expand Down
43 changes: 23 additions & 20 deletions lib/json/ld/api.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- encoding: utf-8 -*-
# frozen_string_literal: true
require 'openssl'
require 'json/ld/expand'
require 'json/ld/compact'
Expand Down Expand Up @@ -70,12 +72,6 @@ class API
# If set to a value that is not `false`, the JSON-LD processor must modify the output of the Compaction Algorithm or the Expansion Algorithm by coalescing all properties associated with each subject via the Flattening Algorithm. The value of `flatten must` be either an _IRI_ value representing the name of the graph to flatten, or `true`. If the value is `true`, then the first graph encountered in the input document is selected and flattened.
# @option options [String] :processingMode ("json-ld-1.0")
# If set to "json-ld-1.0", the JSON-LD processor must produce exactly the same results as the algorithms defined in this specification. If set to another value, the JSON-LD processor is allowed to extend or modify the algorithms defined in this specification to enable application-specific optimizations. The definition of such optimizations is beyond the scope of this specification and thus not defined. Consequently, different implementations may implement different optimizations. Developers must not define modes beginning with json-ld as they are reserved for future versions of this specification.
# @option options [String] :produceGeneralizedRdf (false)
# Unless the produce generalized RDF flag is set to true, RDF triples containing a blank node predicate are excluded from output.
# @option options [Boolean] :useNativeTypes (false)
# If set to `true`, the JSON-LD processor will use native datatypes for expression xsd:integer, xsd:boolean, and xsd:double values, otherwise, it will use the expanded form.
# @option options [Boolean] :useRdfType (false)
# If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
# @option options [Boolean] :rename_bnodes (true)
# Rename bnodes as part of expansion, or keep them the same.
# @option options [Boolean] :unique_bnodes (false)
Expand Down Expand Up @@ -141,6 +137,9 @@ def initialize(input, context, options = {}, &block)
end
end
end

# This is used internally only
private :initialize

##
# Expands the given input according to the steps in the Expansion Algorithm. The input must be copied, expanded and returned
Expand All @@ -152,6 +151,8 @@ def initialize(input, context, options = {}, &block)
# The JSON-LD object to copy and perform the expansion upon.
# @param [Hash{Symbol => Object}] options
# See options in {JSON::LD::API#initialize}
# @option options [String, #read, Hash, Array, JSON::LD::Context] :expandContext
# A context that is used to initialize the active context when expanding a document.
# @raise [JsonLdError]
# @yield jsonld
# @yieldparam [Array<Hash>] jsonld
Expand All @@ -163,7 +164,10 @@ def initialize(input, context, options = {}, &block)
def self.expand(input, options = {})
result = nil
API.new(input, options[:expandContext], options) do |api|
result = api.expand(api.value, nil, api.context)
result = api.expand(api.value, nil, api.context,
ordered: options.fetch(:ordered, true),
framing: options.fetch(:framing, false),
keep_free_floating_nodes: options.fetch(:keep_free_floating_nodes, false))
end

# If, after the algorithm outlined above is run, the resulting element is an
Expand Down Expand Up @@ -204,9 +208,9 @@ def self.compact(input, context, options = {})

# 1) Perform the Expansion Algorithm on the JSON-LD input.
# This removes any existing context to allow the given context to be cleanly applied.
expanded = options[:expanded] ? input : API.expand(input, options)
expanded_input = options[:expanded] ? input : API.expand(input, options)

API.new(expanded, context, options) do
API.new(expanded_input, context, options) do
log_debug(".compact") {"expanded input: #{expanded.to_json(JSON_STATE) rescue 'malformed json'}"}
result = compact(value, nil)

Expand Down Expand Up @@ -270,7 +274,7 @@ def self.flatten(input, context, options = {})

if context && !flattened.empty?
# Otherwise, return the result of compacting flattened according the Compaction algorithm passing context ensuring that the compaction result uses the @graph keyword (or its alias) at the top-level, even if the context is empty or if there is only one element to put in the @graph array. This ensures that the returned document has a deterministic structure.
compacted = log_depth {compact(flattened, nil)}
compacted = compact(flattened, nil)
compacted = [compacted] unless compacted.is_a?(Array)
kwgraph = self.context.compact_iri('@graph', quiet: true)
flattened = self.context.serialize.merge(kwgraph => compacted)
Expand All @@ -294,7 +298,7 @@ def self.flatten(input, context, options = {})
# @param [Hash{Symbol => Object}] options
# See options in {JSON::LD::API#initialize}
# Other options passed to {JSON::LD::API.expand}
# @option options ['@last', '@always', '@never', '@link'] :embed ('@link')
# @option options ['@last', '@always', '@never', '@link'] :embed ('@last')
# a flag specifying that objects should be directly embedded in the output,
# instead of being referred to by their IRI.
# @option options [Boolean] :explicit (false)
Expand Down Expand Up @@ -347,28 +351,25 @@ def self.frame(input, frame, options = {})
expanded_input = options[:expanded] ? input : API.expand(input, options)

# Expand frame to simplify processing
expanded_frame = API.expand(frame, options)
expanded_frame = API.expand(frame, options.merge(framing: true, keep_free_floating_nodes: true))

# Initialize input using frame as context
API.new(expanded_input, nil, options) do
#log_debug(".frame") {"context from frame: #{context.inspect}"}
log_debug(".frame") {"expanded frame: #{expanded_frame.to_json(JSON_STATE) rescue 'malformed json'}"}

# Get framing nodes from expanded input, replacing Blank Node identifiers as necessary
old_logger, @options[:logger] = @options[:logger], []
create_node_map(value, framing_state[:graphs], '@merged')
create_node_map(value, framing_state[:graphs], graph: '@merged')
@options[:logger] = old_logger
framing_state[:subjects] = framing_state[:graphs]['@merged']
log_debug(".frame") {"subjects: #{framing_state[:subjects].to_json(JSON_STATE) rescue 'malformed json'}"}

result = []
frame(framing_state, framing_state[:subjects].keys.sort, (expanded_frame.first || {}), options.merge(parent: result))
log_debug(".frame") {"after frame: #{result.to_json(JSON_STATE) rescue 'malformed json'}"}

# Initalize context from frame
@context = log_depth {@context.parse(frame['@context'])}
@context = @context.parse(frame['@context'])
# Compact result
compacted = log_depth {compact(result, nil)}
compacted = compact(result, nil)
compacted = [compacted] unless compacted.is_a?(Array)

# Add the given context to the output
Expand Down Expand Up @@ -449,18 +450,20 @@ def self.toRdf(input, options = {}, &block)
# @param [Array<RDF::Statement>] input
# @param [Hash{Symbol => Object}] options
# See options in {JSON::LD::API#initialize}
# @option options [Boolean] :useRdfType (false)
# If set to `true`, the JSON-LD processor will treat `rdf:type` like a normal property instead of using `@type`.
# @yield jsonld
# @yieldparam [Hash] jsonld
# The JSON-LD document in expanded form
# @yieldreturn [Object] returned object
# @return [Object, Hash]
# If a block is given, the result of evaluating the block is returned, otherwise, the expanded JSON-LD document
def self.fromRdf(input, options = {}, &block)
options = {useNativeTypes: false}.merge!(options)
useRdfType = options.fetch(:useRdfType, false)
result = nil

API.new(nil, nil, options) do |api|
result = api.from_statements(input)
result = api.from_statements(input, useRdfType: useRdfType)
end

block_given? ? yield(result) : result
Expand Down

0 comments on commit a1ad43c

Please sign in to comment.