krikri 0.10.1 → 0.11.0
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 +4 -4
- data/app/models/krikri/original_record.rb +1 -0
- data/lib/krikri/async_uri_getter.rb +127 -0
- data/lib/krikri/engine.rb +18 -0
- data/lib/krikri/ldp.rb +3 -2
- data/lib/krikri/ldp/invalidatable.rb +107 -0
- data/lib/krikri/ldp/rdf_source.rb +24 -6
- data/lib/krikri/ldp/resource.rb +22 -1
- data/lib/krikri/map_crosswalk.rb +5 -2
- data/lib/krikri/version.rb +1 -1
- data/spec/internal/Gemfile.lock +4 -4
- data/spec/internal/config/initializers/blacklight_initializer.rb +1 -1
- data/spec/internal/config/initializers/devise.rb +2 -2
- data/spec/internal/config/secrets.yml +2 -2
- data/spec/internal/db/development.sqlite3 +0 -0
- data/spec/internal/db/migrate/{20151222175607_devise_create_users.rb → 20160113172004_devise_create_users.rb} +0 -0
- data/spec/internal/db/migrate/{20151222175629_create_searches.blacklight.rb → 20160113172024_create_searches.blacklight.rb} +0 -0
- data/spec/internal/db/migrate/{20151222175630_create_bookmarks.blacklight.rb → 20160113172025_create_bookmarks.blacklight.rb} +0 -0
- data/spec/internal/db/migrate/{20151222175631_add_polymorphic_type_to_bookmarks.blacklight.rb → 20160113172026_add_polymorphic_type_to_bookmarks.blacklight.rb} +0 -0
- data/spec/internal/db/schema.rb +1 -1
- data/spec/internal/db/test.sqlite3 +0 -0
- data/spec/internal/log/development.log +84 -84
- data/spec/internal/log/test.log +5709 -3532
- data/spec/lib/krikri/async_uri_getter_spec.rb +106 -0
- data/spec/lib/krikri/map_crosswalk_spec.rb +18 -0
- data/spec/lib/krikri/search_index_spec.rb +22 -14
- data/spec/models/dpla/map/aggregation_spec.rb +21 -0
- data/spec/models/original_record_spec.rb +3 -0
- data/spec/support/shared_contexts/entities_query.rb +1 -0
- data/spec/support/shared_examples/ldp_invalidatable.rb +98 -0
- data/spec/support/shared_examples/rdf_source.rb +2 -1
- metadata +18 -184
- data/spec/internal/db/test.sqlite3-journal +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_alerts.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_background-variant.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_border-radius.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_buttons.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_center-block.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_clearfix.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_forms.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_gradients.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_grid-framework.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_grid.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_hide-text.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_image.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_labels.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_list-group.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_nav-divider.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_nav-vertical-align.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_opacity.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_pagination.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_panels.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_progress-bar.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_reset-filter.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_resize.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_responsive-visibility.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_size.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_tab-focus.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_table-row.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_text-emphasis.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_text-overflow.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/4a3ee647961c7e45976eb2c0a94406aad3427b3d/_vendor-prefixes.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/93e201cf4a11978a1f491a057a3bd569c3825210/blacklight.css.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_alerts.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_badges.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_breadcrumbs.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_button-groups.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_buttons.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_carousel.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_close.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_code.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_component-animations.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_dropdowns.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_forms.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_glyphicons.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_grid.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_input-groups.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_jumbotron.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_labels.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_list-group.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_media.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_mixins.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_modals.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_navbar.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_navs.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_normalize.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_pager.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_pagination.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_panels.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_popovers.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_print.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_progress-bars.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_responsive-embed.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_responsive-utilities.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_scaffolding.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_tables.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_thumbnails.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_tooltip.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_type.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_utilities.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_variables.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/a1ec1bb9c9cafeb054d542e861ebc8ffd5904439/_wells.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/b28605b1c659cf09fc72f3c1fff32918869d28b8/_bootstrap-sprockets.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/b28605b1c659cf09fc72f3c1fff32918869d28b8/_bootstrap.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/ca8c12d03785e0d6cd4554f4d3939e7836d38282/_blacklight_base.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sass/ca8c12d03785e0d6cd4554f4d3939e7836d38282/blacklight.scssc +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/4052820c15af72ba690230a0f92bd75e +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/496a0d7dce1ff6bf4a9c3a089ea3a635 +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/50b9db0b908b421a9b941a445dbaeacc +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/528c628cf107f8be6dd122e1154344be +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/8edfca9082e02111be92e79000667f22 +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/90b54a819800edfa41b67722d1561040 +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/9c653367feff82588eb6041d783a5809 +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/b35e12934e9f05662777579549e31cd7 +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/bb108ef3fc4c96d1c20cc41f97d943a0 +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/dbba4bbc32c17ade3d618c5d0baeb371 +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/e9f7ccc553ce1a217709cc7a08cfb032 +0 -0
- data/spec/internal/tmp/cache/assets/test/sprockets/f274b5f22db177b6464b50691d531688 +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5aa4fcca719417b8f265da3ee528f69d5fcbc3ec
|
|
4
|
+
data.tar.gz: d505e82b5881a9fae1e3f65b85b19157a6083bae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 197ad8e9e763ce9abb331dc57b9bca7a12103484107f6b27002adc946a8a5244eb27b1756e5dbf8e37881977a59a0ba541639c5485ed9ff11f55f3453362902f
|
|
7
|
+
data.tar.gz: 0c328d43f14401964ec57725850d813cf50892b6c11f3e71fc74c2fa318b8b96c83a8eec8dde3542211b9d70787eb6322ae8c7d4ddac8bee916fee6adf8aaca3
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
require 'faraday'
|
|
2
|
+
require 'faraday_middleware'
|
|
3
|
+
|
|
4
|
+
require 'net/http'
|
|
5
|
+
require 'thread'
|
|
6
|
+
require 'uri'
|
|
7
|
+
|
|
8
|
+
module Krikri
|
|
9
|
+
##
|
|
10
|
+
# Helper class for fetching multiple URLs concurrently.
|
|
11
|
+
#
|
|
12
|
+
# @example to fetch 5 URLs in 5 threads
|
|
13
|
+
# urls = ['http://example.com/one',
|
|
14
|
+
# 'http://example.com/two',
|
|
15
|
+
# 'http://example.com/three',
|
|
16
|
+
# 'http://example.com/four',
|
|
17
|
+
# 'http://example.com/five']
|
|
18
|
+
# .map { |url| URI.parse(url) }
|
|
19
|
+
#
|
|
20
|
+
# getter = Krikri::AsyncUriGetter.new
|
|
21
|
+
#
|
|
22
|
+
# requests = urls.map do |url|
|
|
23
|
+
# getter.add_request(uri: url, opts: { follow_redirects: true })
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# At this point, 5 threads are launched to fetch the list of URLs. We can
|
|
27
|
+
# wait for them all to finish if we want to make sure we don't continue until
|
|
28
|
+
# all threads have terminated: `requests.map(&:join)`
|
|
29
|
+
#
|
|
30
|
+
# Or simply access the responses and have our current thread block until
|
|
31
|
+
# they're available:
|
|
32
|
+
#
|
|
33
|
+
# requests.each do |request|
|
|
34
|
+
# request.with_response do |response|
|
|
35
|
+
# if response.status == 200
|
|
36
|
+
# puts "Response body: #{response.body}"
|
|
37
|
+
# else
|
|
38
|
+
# puts "Got return status: #{response.status}"
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
# end
|
|
42
|
+
#
|
|
43
|
+
class AsyncUriGetter
|
|
44
|
+
MAX_REDIRECTS = 10
|
|
45
|
+
|
|
46
|
+
##
|
|
47
|
+
# Create a new asynchronous URL fetcher.
|
|
48
|
+
#
|
|
49
|
+
# @param opts [Hash] a hash of the supported options, which are:
|
|
50
|
+
# @option opts [Boolean] :follow_redirects Whether to follow HTTP 3xx
|
|
51
|
+
# redirects.
|
|
52
|
+
# @option opts [Integer] :max_redirects Number of redirects to follow before
|
|
53
|
+
# giving up. (default: 10)
|
|
54
|
+
def initialize(opts: {})
|
|
55
|
+
@default_opts = { max_redirects: MAX_REDIRECTS }.merge(opts)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
##
|
|
59
|
+
# Run a request (in a new thread) and return a promise-like object for the
|
|
60
|
+
# response.
|
|
61
|
+
#
|
|
62
|
+
# @param uri [URI] the URI to be fetched
|
|
63
|
+
# @param headers [Hash<String, String>] HTTP headers to include with the
|
|
64
|
+
# request
|
|
65
|
+
# @param opts [Hash] options to override the ones provided when
|
|
66
|
+
# AsyncUriGetter was initialized. All supported options from `#initialize`
|
|
67
|
+
# are available here as well.
|
|
68
|
+
def add_request(uri: nil, headers: {}, opts: {})
|
|
69
|
+
fail ArgumentError, "uri must be a URI; got: #{uri}" unless uri.is_a?(URI)
|
|
70
|
+
Request.new(uri, headers, @default_opts.merge(opts))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
Request = Struct.new(:uri, :headers, :opts) do
|
|
74
|
+
def initialize(*)
|
|
75
|
+
super
|
|
76
|
+
@request_thread = start_request
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
##
|
|
80
|
+
# Wait for the request thread to complete
|
|
81
|
+
def join
|
|
82
|
+
@request_thread.join
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
##
|
|
86
|
+
# @yield [Faraday::Response] the response returned for the request
|
|
87
|
+
def with_response
|
|
88
|
+
yield @request_thread.value
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
# Run the Faraday request in a new thread
|
|
95
|
+
def start_request
|
|
96
|
+
Thread.new do
|
|
97
|
+
http.get(uri) do |request|
|
|
98
|
+
headers.each { |header, val| request.headers[header.to_s] = val }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
##
|
|
104
|
+
# @return [Faraday::Connection] a connection with sensible defaults
|
|
105
|
+
def http
|
|
106
|
+
@http ||= Faraday.new do |conn|
|
|
107
|
+
conn.request :retry,
|
|
108
|
+
max: 4,
|
|
109
|
+
interval: 0.025,
|
|
110
|
+
interval_randomness: 0.5,
|
|
111
|
+
backoff_factor: 2,
|
|
112
|
+
exceptions: [Faraday::ConnectionFailed,
|
|
113
|
+
'Errno::ETIMEDOUT',
|
|
114
|
+
'Timeout::Error',
|
|
115
|
+
'Error::TimeoutError',
|
|
116
|
+
Faraday::TimeoutError]
|
|
117
|
+
if opts.fetch(:follow_redirects, false)
|
|
118
|
+
conn.use(FaradayMiddleware::FollowRedirects,
|
|
119
|
+
limit: opts.fetch(:max_redirects))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
conn.adapter Faraday.default_adapter
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
data/lib/krikri/engine.rb
CHANGED
|
@@ -83,6 +83,12 @@ module Krikri
|
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
initializer :aggregation do
|
|
86
|
+
class NamespaceError < RuntimeError
|
|
87
|
+
def initialize(uri)
|
|
88
|
+
super("Tried to get DPLA ID for non-DPLA URI #{uri}")
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
86
92
|
DPLA::MAP::Aggregation.class_eval do
|
|
87
93
|
include Krikri::MapCrosswalk
|
|
88
94
|
include Krikri::LDP::RdfSource
|
|
@@ -124,6 +130,18 @@ module Krikri
|
|
|
124
130
|
.to_s)
|
|
125
131
|
end
|
|
126
132
|
|
|
133
|
+
##
|
|
134
|
+
# @return [String, nil] returns only the final portion of the URI (the
|
|
135
|
+
# "local name"), with the `#base_uri` removed. `nil` if this is a node
|
|
136
|
+
#
|
|
137
|
+
# @raise NamespaceError
|
|
138
|
+
def dpla_id
|
|
139
|
+
return nil if node?
|
|
140
|
+
raise NamespaceError, rdf_subject unless id.start_with?(base_uri)
|
|
141
|
+
|
|
142
|
+
id.gsub("#{base_uri}/", '')
|
|
143
|
+
end
|
|
144
|
+
|
|
127
145
|
private
|
|
128
146
|
|
|
129
147
|
def local_name_from_original_record
|
data/lib/krikri/ldp.rb
CHANGED
|
@@ -4,7 +4,8 @@ module Krikri
|
|
|
4
4
|
# As LDP support develops, it might be possible to excract this or replace it
|
|
5
5
|
# with a tool like the `ldp` gem.
|
|
6
6
|
module LDP
|
|
7
|
-
autoload :Resource,
|
|
8
|
-
autoload :RdfSource,
|
|
7
|
+
autoload :Resource, 'krikri/ldp/resource'
|
|
8
|
+
autoload :RdfSource, 'krikri/ldp/rdf_source'
|
|
9
|
+
autoload :Invalidatable, 'krikri/ldp/invalidatable'
|
|
9
10
|
end
|
|
10
11
|
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
module Krikri::LDP
|
|
2
|
+
##
|
|
3
|
+
# Implements invalidation for `Krikri::LDP::Resource`s. This is different
|
|
4
|
+
# from deletion, in that the resource continues to respond `200 OK`, and
|
|
5
|
+
# return the representation, Nothing is removed from the LDP server.
|
|
6
|
+
#
|
|
7
|
+
# Works as a mixin to `Krikri::LDP::Resource`, assuming an implementation of
|
|
8
|
+
# `#rdf_source`, which may simply return `self`.
|
|
9
|
+
#
|
|
10
|
+
# @example invalidating a resource
|
|
11
|
+
# class MyResource
|
|
12
|
+
# include Krikri::LDP::Resource
|
|
13
|
+
# include Krikri::LDP::Invalidatable
|
|
14
|
+
#
|
|
15
|
+
# def rdf_subject
|
|
16
|
+
# @rdf_subject ||= RDF::URI('http://example.com/ldp/a/resource/path')
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# invalidatable_resource = MyResource.new
|
|
21
|
+
# # the resource must exist before it can be invalidated!
|
|
22
|
+
# invalidatable_resource.save
|
|
23
|
+
#
|
|
24
|
+
# invalidatable_resource.invalidate!
|
|
25
|
+
# invalidatable_resource.invalidated? # => true
|
|
26
|
+
# invalidatable_resource.invalidated_at_time
|
|
27
|
+
# # => Thu, 03 Dec 2015 10:27:45 -0800
|
|
28
|
+
#
|
|
29
|
+
# @see http://www.w3.org/TR/2013/REC-prov-dm-20130430/#term-Invalidation
|
|
30
|
+
# for documentation on PROV invalidation
|
|
31
|
+
module Invalidatable
|
|
32
|
+
# @see RDF::PROV
|
|
33
|
+
INVALIDATED_BY_URI = RDF::PROV.wasInvalidatedBy
|
|
34
|
+
INVALIDATED_TIME_URI = RDF::PROV.invalidatedAtTime
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# Invalidates the resource by marking it with a `prov:invalidatedAtTime`. If
|
|
38
|
+
# an `RDF::Term` is passed as the first argument, that term is used as the
|
|
39
|
+
# value of `prov:wasInvalidatedBy`.
|
|
40
|
+
#
|
|
41
|
+
# @example invalidating with an activity
|
|
42
|
+
# invalidatable_resource.invalidate!(RDF::URI('http://example.org/moomin'))
|
|
43
|
+
# invalidatable_resource.was_invalidated_by
|
|
44
|
+
# # => #<RDF::URI:0x2acab846109c URI:http://example.org/moomin>
|
|
45
|
+
#
|
|
46
|
+
# @param activity_uri [RDF::Term] a URI for the invalidating activity. If
|
|
47
|
+
# none is given, this defaults to `nil` and no `prov:wasInvalidatedBy`
|
|
48
|
+
# statement is added.
|
|
49
|
+
# @param ignore_invalid [Boolean] if true, supresses errors on already,
|
|
50
|
+
# invalid records
|
|
51
|
+
#
|
|
52
|
+
# @raise [RuntimeError] when the resource does not exist or is already
|
|
53
|
+
# invalid; unless `ignore_invalid` is `true`
|
|
54
|
+
# @return [void]
|
|
55
|
+
def invalidate!(activity_uri = nil, ignore_invalid = false)
|
|
56
|
+
raise "Cannot invalidate #{rdf_subject}, does not exist." unless exists?
|
|
57
|
+
|
|
58
|
+
# force a reload unless we have cached an invalidatedAtTime
|
|
59
|
+
rdf_source.get({}, true) unless invalidated?
|
|
60
|
+
# we check invalidated again in case the reload came back invalid
|
|
61
|
+
if invalidated?
|
|
62
|
+
return if ignore_invalid
|
|
63
|
+
raise "Cannot invalidate #{rdf_subject}, already invalid."
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
uri = RDF::URI(rdf_subject)
|
|
67
|
+
|
|
68
|
+
rdf_source << [uri, INVALIDATED_BY_URI, activity_uri] unless
|
|
69
|
+
activity_uri.nil?
|
|
70
|
+
rdf_source << [uri, INVALIDATED_TIME_URI, DateTime.now]
|
|
71
|
+
|
|
72
|
+
rdf_source.save
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# @return [Boolean] `true` if the resource has been marked invalidated.
|
|
77
|
+
def invalidated?
|
|
78
|
+
!invalidated_at_time.nil?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
##
|
|
82
|
+
# @return [DateTime, nil] the time this resource was marked invalidated;
|
|
83
|
+
# gives `nil` if the resource has not been invalidated.
|
|
84
|
+
#
|
|
85
|
+
# @note if two invalidatedAtTimes exist, we may get either of them back!
|
|
86
|
+
def invalidated_at_time
|
|
87
|
+
time = first_property(INVALIDATED_TIME_URI)
|
|
88
|
+
time.nil? ? nil : time.object
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
##
|
|
92
|
+
# @return [RDF::URI, nil] the activity responsible for invalidating the
|
|
93
|
+
# resource
|
|
94
|
+
#
|
|
95
|
+
# @note if two wasInvalidatedBys exist, we may get either of them back!
|
|
96
|
+
def was_invalidated_by
|
|
97
|
+
first_property(INVALIDATED_BY_URI)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
def first_property(predicate)
|
|
103
|
+
res = rdf_source.query([RDF::URI(rdf_subject), predicate, nil])
|
|
104
|
+
res.empty? ? nil : res.first.object
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -7,13 +7,26 @@ module Krikri::LDP
|
|
|
7
7
|
module RdfSource
|
|
8
8
|
extend ActiveSupport::Concern
|
|
9
9
|
include Krikri::LDP::Resource
|
|
10
|
+
include Krikri::LDP::Invalidatable
|
|
11
|
+
|
|
12
|
+
GENERATED_URI = RDF::PROV.wasGeneratedBy
|
|
13
|
+
REVISED_URI = RDF::DPLA.wasRevisedBy
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# @return [Boolean] false if this resource does not ex
|
|
17
|
+
# @see Krikri::LDP::Resource#exists?
|
|
18
|
+
def exists?
|
|
19
|
+
return false if node?
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
alias_method :exist?, :exists?
|
|
10
23
|
|
|
11
24
|
##
|
|
12
25
|
# PUTs the LDP resource named in #rdf_subject, populating it's content
|
|
13
26
|
# (graph) from the object's RDF::Graph.
|
|
14
27
|
#
|
|
15
28
|
# @see Krikri::LDP::Resource#save
|
|
16
|
-
# @note this may leave the resource's graph out of sync with the LDP
|
|
29
|
+
# @note this may leave the resource's graph out of sync with the LDP
|
|
17
30
|
# endpoint since the endpoint may add management triples when saving.
|
|
18
31
|
def save(*)
|
|
19
32
|
result = super(dump(:ttl))
|
|
@@ -21,14 +34,14 @@ module Krikri::LDP
|
|
|
21
34
|
end
|
|
22
35
|
|
|
23
36
|
##
|
|
24
|
-
# Saves and forces reload. This updates the graph with any management
|
|
37
|
+
# Saves and forces reload. This updates the graph with any management
|
|
25
38
|
# triples added by the LDP endpoint.
|
|
26
39
|
#
|
|
27
40
|
# @see #save
|
|
28
41
|
def save_and_reload(*args)
|
|
29
42
|
result = save(*args)
|
|
30
43
|
get({}, true)
|
|
31
|
-
result
|
|
44
|
+
result
|
|
32
45
|
end
|
|
33
46
|
|
|
34
47
|
##
|
|
@@ -42,6 +55,12 @@ module Krikri::LDP
|
|
|
42
55
|
result
|
|
43
56
|
end
|
|
44
57
|
|
|
58
|
+
##
|
|
59
|
+
# @return [self]
|
|
60
|
+
def rdf_source
|
|
61
|
+
self
|
|
62
|
+
end
|
|
63
|
+
|
|
45
64
|
##
|
|
46
65
|
# Adds an appropritate provenance statement with the given URI and saves
|
|
47
66
|
# the resource.
|
|
@@ -64,8 +83,7 @@ module Krikri::LDP
|
|
|
64
83
|
# @see http://www.w3.org/TR/prov-primer/
|
|
65
84
|
# @see http://www.w3.org/TR/2013/REC-prov-o-20130430/
|
|
66
85
|
def save_with_provenance(activity_uri)
|
|
67
|
-
predicate =
|
|
68
|
-
exists? ? RDF::DPLA.wasRevisedBy : RDF::PROV.wasGeneratedBy
|
|
86
|
+
predicate = exists? ? REVISED_URI : GENERATED_URI
|
|
69
87
|
self << RDF::Statement(self, predicate, activity_uri)
|
|
70
88
|
save
|
|
71
89
|
end
|
|
@@ -75,7 +93,7 @@ module Krikri::LDP
|
|
|
75
93
|
##
|
|
76
94
|
# Clears the RDF::Graph and repopulates it from the http body. Forces text
|
|
77
95
|
# encoding to UTF-8 before passing to the `RDF::Reader`.
|
|
78
|
-
#
|
|
96
|
+
#
|
|
79
97
|
# @return [void]
|
|
80
98
|
#
|
|
81
99
|
# @see http://www.w3.org/TR/turtle/#sec-mime for info about Turtle encoding
|
data/lib/krikri/ldp/resource.rb
CHANGED
|
@@ -3,7 +3,28 @@ require 'faraday_middleware'
|
|
|
3
3
|
|
|
4
4
|
module Krikri::LDP
|
|
5
5
|
##
|
|
6
|
-
# Implements basic LDP CRUD operations
|
|
6
|
+
# Implements basic LDP CRUD operations. Requires an implementation of
|
|
7
|
+
# `#rdf_subject` returning an `RDF::URI`. The resource idenitified by the URI
|
|
8
|
+
# must conform to LDP Resource's interaction patterns.
|
|
9
|
+
#
|
|
10
|
+
# @example implementing a resource
|
|
11
|
+
# class MyResource
|
|
12
|
+
# include Krikri::LDP::Resource
|
|
13
|
+
#
|
|
14
|
+
# def rdf_subject
|
|
15
|
+
# @rdf_subject ||= RDF::URI('http://example.com/ldp/a/resource/path')
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# @note Ideally, this is a general purpose LDP resource. However some HTTP
|
|
20
|
+
# PUT creation behavior may be specific to Marmotta. This avoids the need to
|
|
21
|
+
# interact directly with the owning container, but is a less generalized
|
|
22
|
+
# implementation.
|
|
23
|
+
#
|
|
24
|
+
# @see http://www.w3.org/TR/ldp/#h-ldpr-resource LDP Resource interaction
|
|
25
|
+
# patterns.
|
|
26
|
+
# @see https://wiki.apache.org/marmotta/LDPImplementationReport for
|
|
27
|
+
# information about Marmotta's PUT.
|
|
7
28
|
module Resource
|
|
8
29
|
extend ActiveSupport::Concern
|
|
9
30
|
|
data/lib/krikri/map_crosswalk.rb
CHANGED
|
@@ -134,7 +134,6 @@ module Krikri
|
|
|
134
134
|
|
|
135
135
|
set_value(sr, :relation, parent_sr.relation)
|
|
136
136
|
set_value(sr, :rights, parent_sr.rights, true)
|
|
137
|
-
set_value(sr, :temporal, parent_sr.temporal)
|
|
138
137
|
set_value(sr, :title, parent_sr.title)
|
|
139
138
|
|
|
140
139
|
set_value(sr, :collection, parent_sr.collection) do |coll|
|
|
@@ -149,6 +148,10 @@ module Krikri
|
|
|
149
148
|
build_time_span(date)
|
|
150
149
|
end
|
|
151
150
|
|
|
151
|
+
set_value(sr, :temporal, parent_sr.temporal) do |temporal|
|
|
152
|
+
build_time_span(temporal)
|
|
153
|
+
end
|
|
154
|
+
|
|
152
155
|
set_value(sr, :spatial, parent_sr.spatial) do |place|
|
|
153
156
|
build_place(place)
|
|
154
157
|
end
|
|
@@ -173,7 +176,7 @@ module Krikri
|
|
|
173
176
|
def build_time_span(source)
|
|
174
177
|
return unless source.is_a? DPLA::MAP::TimeSpan
|
|
175
178
|
date = {}
|
|
176
|
-
date
|
|
179
|
+
set_value(date, :displayDate, source.prefLabel, true, &:as_json)
|
|
177
180
|
set_value(date, :begin, source.begin, true, &:as_json)
|
|
178
181
|
set_value(date, :end, source.end, true, &:as_json)
|
|
179
182
|
|
data/lib/krikri/version.rb
CHANGED
data/spec/internal/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: /home/tjohnson/src/dpla/krikri
|
|
3
3
|
specs:
|
|
4
|
-
krikri (0.10.
|
|
4
|
+
krikri (0.10.1)
|
|
5
5
|
analysand (= 4.0.0)
|
|
6
6
|
audumbla (~> 0.1)
|
|
7
7
|
blacklight (~> 5.8.0)
|
|
@@ -152,8 +152,8 @@ GEM
|
|
|
152
152
|
domain_name (~> 0.5)
|
|
153
153
|
http_parser.rb (0.6.0)
|
|
154
154
|
i18n (0.7.0)
|
|
155
|
-
jbuilder (2.
|
|
156
|
-
activesupport (>= 3.0.0, < 5)
|
|
155
|
+
jbuilder (2.4.0)
|
|
156
|
+
activesupport (>= 3.0.0, < 5.1)
|
|
157
157
|
multi_json (~> 1.2)
|
|
158
158
|
jettywrapper (2.0.3)
|
|
159
159
|
activesupport (>= 3.0.0)
|
|
@@ -242,7 +242,7 @@ GEM
|
|
|
242
242
|
activesupport (= 4.1.6)
|
|
243
243
|
rake (>= 0.8.7)
|
|
244
244
|
thor (>= 0.18.1, < 2.0)
|
|
245
|
-
rake (10.
|
|
245
|
+
rake (10.5.0)
|
|
246
246
|
rdf (1.1.17.1)
|
|
247
247
|
link_header (~> 0.0, >= 0.0.8)
|
|
248
248
|
rdf-aggregate-repo (1.1.0.1)
|