ldp 0.4.1 → 0.5.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/.gitignore +1 -0
- data/.travis.yml +8 -3
- data/Gemfile +3 -1
- data/ldp.gemspec +5 -0
- data/lib/ldp.rb +3 -9
- data/lib/ldp/client.rb +20 -15
- data/lib/ldp/client/methods.rb +4 -6
- data/lib/ldp/container.rb +30 -4
- data/lib/ldp/container/basic.rb +4 -13
- data/lib/ldp/container/direct.rb +11 -6
- data/lib/ldp/container/indirect.rb +9 -3
- data/lib/ldp/error.rb +20 -0
- data/lib/ldp/orm.rb +13 -24
- data/lib/ldp/resource.rb +23 -5
- data/lib/ldp/resource/binary_source.rb +9 -1
- data/lib/ldp/resource/rdf_source.rb +26 -11
- data/lib/ldp/response.rb +117 -88
- data/lib/ldp/uri.rb +39 -23
- data/lib/ldp/version.rb +1 -1
- data/spec/lib/integration/integration_spec.rb +51 -2
- data/spec/lib/ldp/client_spec.rb +20 -11
- data/spec/lib/ldp/resource/binary_source_spec.rb +25 -0
- data/spec/lib/ldp/resource/rdf_source_spec.rb +24 -0
- data/spec/lib/ldp/resource_spec.rb +1 -2
- data/spec/lib/ldp/response_spec.rb +49 -29
- data/spec/spec_helper.rb +10 -0
- metadata +61 -6
- data/lib/ldp/response/paging.rb +0 -57
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a68882c3e0ea6d21e3819d632a92e88734bec0f
|
4
|
+
data.tar.gz: a3f31f5e16fc2a60b109bef5f7da218ad008e949
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4111cddaaccda626e39b8ba24619763ca217f97915855ba2fb936e7fcb7ba1f9d6afc78d268393f7c3a67128d6427a0a41f99b2d24d2f09d41e287e5aa1f1ae0
|
7
|
+
data.tar.gz: 173b2d3954e4aa0184a5d87916c637c8348fe185ad561b51cdc28b844d81c14bf820bcdac27551d097f6ccf348c35eaf5c49d20759741ce3cf64571f963dd133
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/ldp.gemspec
CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.summary = spec.description
|
13
13
|
spec.homepage = "https://github.com/projecthydra/ldp"
|
14
14
|
spec.license = "APACHE2"
|
15
|
+
spec.required_ruby_version = '~> 2.0'
|
15
16
|
|
16
17
|
spec.files = `git ls-files`.split($/)
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
@@ -20,9 +21,13 @@ Gem::Specification.new do |spec|
|
|
20
21
|
|
21
22
|
spec.add_dependency "faraday"
|
22
23
|
spec.add_dependency "linkeddata", ">= 1.1"
|
24
|
+
spec.add_dependency "rdf-vocab"
|
23
25
|
spec.add_dependency "http_logger"
|
26
|
+
spec.add_dependency "deprecation"
|
24
27
|
spec.add_dependency "slop"
|
25
28
|
spec.add_development_dependency "bundler", "~> 1.3"
|
26
29
|
spec.add_development_dependency "rake"
|
27
30
|
spec.add_development_dependency "rspec"
|
31
|
+
spec.add_development_dependency "coveralls"
|
32
|
+
spec.add_development_dependency "simplecov"
|
28
33
|
end
|
data/lib/ldp.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'ldp/version'
|
2
2
|
require 'linkeddata'
|
3
|
+
require 'rdf/vocab/ldp'
|
3
4
|
require 'logger'
|
4
5
|
require 'singleton'
|
6
|
+
require 'deprecation'
|
5
7
|
|
6
8
|
module Ldp
|
7
9
|
RDF::Graph.send(:include, RDF::Isomorphic)
|
8
10
|
|
11
|
+
require 'ldp/error'
|
9
12
|
require 'ldp/client'
|
10
13
|
require 'ldp/uri'
|
11
14
|
|
@@ -17,15 +20,6 @@ module Ldp
|
|
17
20
|
|
18
21
|
autoload :Orm, 'ldp/orm'
|
19
22
|
|
20
|
-
class HttpError < RuntimeError; end
|
21
|
-
class BadRequest < HttpError; end # 400
|
22
|
-
class NotFound < HttpError; end # 404
|
23
|
-
class Conflict < HttpError; end # 409
|
24
|
-
class Gone < HttpError; end # 410
|
25
|
-
class EtagMismatch < HttpError; end # 412
|
26
|
-
|
27
|
-
class UnexpectedContentType < RuntimeError; end
|
28
|
-
|
29
23
|
# Returned when there is no result (e.g. 404)
|
30
24
|
class NoneClass
|
31
25
|
include Singleton
|
data/lib/ldp/client.rb
CHANGED
@@ -7,24 +7,29 @@ module Ldp
|
|
7
7
|
require 'ldp/client/prefer_headers'
|
8
8
|
include Ldp::Client::Methods
|
9
9
|
|
10
|
-
|
11
|
-
initialize_http_client *http_client
|
12
|
-
end
|
10
|
+
attr_reader :options
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
when data.container?
|
22
|
-
Ldp::Container.new_from_response self, subject, data
|
23
|
-
when data.resource?
|
24
|
-
Resource::RdfSource.new self, subject, data
|
12
|
+
def initialize(*args)
|
13
|
+
http_client, options = if args.length == 2
|
14
|
+
args
|
15
|
+
elsif args.length == 1 && args.first.is_a?(Faraday::Connection)
|
16
|
+
[args.first, {}]
|
17
|
+
elsif args.length == 1
|
18
|
+
[nil, args.first]
|
25
19
|
else
|
26
|
-
|
20
|
+
raise ArgumentError
|
27
21
|
end
|
22
|
+
|
23
|
+
@options = options
|
24
|
+
|
25
|
+
initialize_http_client(http_client || options)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Find or initialize a new LDP resource by URI
|
29
|
+
def find_or_initialize(subject, options = {})
|
30
|
+
data = get(subject, options)
|
31
|
+
|
32
|
+
Ldp::Resource.for(self, subject, data)
|
28
33
|
end
|
29
34
|
|
30
35
|
def logger
|
data/lib/ldp/client/methods.rb
CHANGED
@@ -23,6 +23,8 @@ module Ldp::Client::Methods
|
|
23
23
|
end
|
24
24
|
|
25
25
|
check_for_errors(resp)
|
26
|
+
|
27
|
+
Ldp::Response.new(resp)
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -48,13 +50,9 @@ module Ldp::Client::Methods
|
|
48
50
|
yield req if block_given?
|
49
51
|
end
|
50
52
|
|
51
|
-
if Ldp::Response.resource? resp
|
52
|
-
Ldp::Response.wrap self, resp
|
53
|
-
else
|
54
|
-
resp
|
55
|
-
end
|
56
|
-
|
57
53
|
check_for_errors(resp)
|
54
|
+
|
55
|
+
Ldp::Response.new(resp)
|
58
56
|
end
|
59
57
|
end
|
60
58
|
|
data/lib/ldp/container.rb
CHANGED
@@ -4,17 +4,27 @@ module Ldp
|
|
4
4
|
require 'ldp/container/direct'
|
5
5
|
require 'ldp/container/indirect'
|
6
6
|
|
7
|
-
def self.
|
7
|
+
def self.for(client, subject, data)
|
8
8
|
case
|
9
|
-
when data.types.include?(
|
9
|
+
when data.types.include?(RDF::Vocab::LDP.IndirectContainer)
|
10
10
|
Ldp::Container::Indirect.new client, subject, data
|
11
|
-
when data.types.include?(
|
11
|
+
when data.types.include?(RDF::Vocab::LDP.DirectContainer)
|
12
12
|
Ldp::Container::Direct.new client, subject, data
|
13
13
|
else
|
14
14
|
Ldp::Container::Basic.new client, subject, data
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
class << self
|
19
|
+
alias new_from_response for
|
20
|
+
end
|
21
|
+
|
22
|
+
def contains
|
23
|
+
@contains ||= Hash[graph.query(predicate: RDF::Vocab::LDP.contains).map do |x|
|
24
|
+
[x.object, Ldp::Resource::RdfSource.new(client, x.object, contained_graph(x.object))]
|
25
|
+
end]
|
26
|
+
end
|
27
|
+
|
18
28
|
##
|
19
29
|
# Add a new resource to the LDP container
|
20
30
|
def add *args
|
@@ -32,7 +42,7 @@ module Ldp
|
|
32
42
|
graph_or_content = args.first
|
33
43
|
else
|
34
44
|
slug = args.first
|
35
|
-
graph_or_content =
|
45
|
+
graph_or_content = build_empty_graph
|
36
46
|
end
|
37
47
|
|
38
48
|
resp = client.post subject, (graph_or_content.is_a?(RDF::Enumerable) ? graph_or_content.dump(:ttl) : graph_or_content) do |req|
|
@@ -41,5 +51,21 @@ module Ldp
|
|
41
51
|
|
42
52
|
client.find_or_initialize resp.headers['Location']
|
43
53
|
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def contained_graph subject
|
58
|
+
g = RDF::Graph.new
|
59
|
+
response_graph.query(subject: subject) do |stmt|
|
60
|
+
g << stmt
|
61
|
+
end
|
62
|
+
g
|
63
|
+
end
|
64
|
+
|
65
|
+
def rdf_source_for(object)
|
66
|
+
g = contained_graph(object)
|
67
|
+
|
68
|
+
Ldp::Resource::RdfSource.new(client, object, (g unless g.empty?))
|
69
|
+
end
|
44
70
|
end
|
45
71
|
end
|
data/lib/ldp/container/basic.rb
CHANGED
@@ -5,19 +5,10 @@ module Ldp
|
|
5
5
|
contains.each { |k, x| yield x }
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
def contained_graph subject
|
16
|
-
g = RDF::Graph.new
|
17
|
-
get.graph.query(subject: subject) do |stmt|
|
18
|
-
g << stmt
|
19
|
-
end
|
20
|
-
g
|
8
|
+
protected
|
9
|
+
|
10
|
+
def interaction_model
|
11
|
+
RDF::Vocab::LDP.BasicContainer
|
21
12
|
end
|
22
13
|
end
|
23
14
|
end
|
data/lib/ldp/container/direct.rb
CHANGED
@@ -2,15 +2,20 @@ module Ldp
|
|
2
2
|
class Container::Direct < Container::Basic
|
3
3
|
def members
|
4
4
|
return enum_for(:members) unless block_given?
|
5
|
-
|
6
|
-
|
7
|
-
yield
|
5
|
+
|
6
|
+
response_graph.query(subject: subject, predicate: member_relation).map do |x|
|
7
|
+
yield rdf_source_for(x.object)
|
8
8
|
end
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def member_relation
|
12
|
-
|
12
|
+
response_graph.first_object(predicate: RDF::Vocab::LDP.hasMemberRelation) || RDF::Vocab::LDP.member
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def interaction_model
|
18
|
+
RDF::Vocab::LDP.DirectContainer
|
13
19
|
end
|
14
|
-
|
15
20
|
end
|
16
21
|
end
|
@@ -2,10 +2,16 @@ module Ldp
|
|
2
2
|
class Container::Indirect < Container::Direct
|
3
3
|
def members
|
4
4
|
return enum_for(:members) unless block_given?
|
5
|
-
|
6
|
-
|
7
|
-
yield
|
5
|
+
|
6
|
+
response_graph.query(predicate: member_relation, object: subject).map do |x|
|
7
|
+
yield rdf_source_for(x.object)
|
8
8
|
end
|
9
9
|
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def interaction_model
|
14
|
+
RDF::Vocab::LDP.IndirectContainer
|
15
|
+
end
|
10
16
|
end
|
11
17
|
end
|
data/lib/ldp/error.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Ldp
|
2
|
+
class Error < StandardError; end
|
3
|
+
|
4
|
+
class HttpError < RuntimeError; end
|
5
|
+
class BadRequest < HttpError; end # 400
|
6
|
+
class NotFound < HttpError; end # 404
|
7
|
+
class Conflict < HttpError; end # 409
|
8
|
+
class Gone < HttpError; end # 410
|
9
|
+
class EtagMismatch < HttpError; end # 412
|
10
|
+
|
11
|
+
class UnexpectedContentType < RuntimeError; end
|
12
|
+
|
13
|
+
class GraphDifferenceException < Ldp::Error
|
14
|
+
attr_reader :diff
|
15
|
+
def initialize message, diff
|
16
|
+
super(message)
|
17
|
+
@diff = diff
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/ldp/orm.rb
CHANGED
@@ -54,22 +54,19 @@ module Ldp
|
|
54
54
|
|
55
55
|
def save
|
56
56
|
Ldp.instrument 'save.orm.ldp', subject: subject_uri do
|
57
|
-
|
58
|
-
|
57
|
+
response = create_or_update
|
58
|
+
|
59
|
+
response.success?
|
59
60
|
end
|
60
|
-
rescue Ldp::HttpError
|
61
|
-
@last_response = e
|
62
|
-
logger.debug e
|
61
|
+
rescue Ldp::HttpError
|
63
62
|
false
|
64
63
|
end
|
65
64
|
|
66
65
|
def save!
|
67
|
-
result =
|
66
|
+
result = create_or_update
|
68
67
|
|
69
68
|
if result.is_a? RDF::Enumerable
|
70
|
-
raise GraphDifferenceException
|
71
|
-
elsif !result
|
72
|
-
raise @last_response
|
69
|
+
raise Ldp::GraphDifferenceException, 'Graph failed to persist', result
|
73
70
|
end
|
74
71
|
|
75
72
|
result
|
@@ -81,26 +78,18 @@ module Ldp
|
|
81
78
|
end
|
82
79
|
end
|
83
80
|
|
84
|
-
|
85
|
-
super
|
86
|
-
end
|
81
|
+
private
|
87
82
|
|
88
|
-
def
|
89
|
-
|
83
|
+
def create_or_update
|
84
|
+
@last_response = resource.save
|
85
|
+
rescue Ldp::HttpError => e
|
86
|
+
@last_response = e
|
87
|
+
logger.debug e
|
88
|
+
raise e
|
90
89
|
end
|
91
90
|
|
92
|
-
private
|
93
|
-
|
94
91
|
def logger
|
95
92
|
Ldp.logger
|
96
93
|
end
|
97
94
|
end
|
98
|
-
|
99
|
-
class GraphDifferenceException < Exception
|
100
|
-
attr_reader :diff
|
101
|
-
def initialize message, diff
|
102
|
-
super(message)
|
103
|
-
@diff = diff
|
104
|
-
end
|
105
|
-
end
|
106
95
|
end
|
data/lib/ldp/resource.rb
CHANGED
@@ -6,6 +6,17 @@ module Ldp
|
|
6
6
|
attr_reader :client, :subject
|
7
7
|
attr_accessor :content
|
8
8
|
|
9
|
+
def self.for(client, subject, response = nil)
|
10
|
+
case
|
11
|
+
when response.container?
|
12
|
+
Ldp::Container.for client, subject, response
|
13
|
+
when response.rdf_source?
|
14
|
+
Resource::RdfSource.new client, subject, response
|
15
|
+
else
|
16
|
+
Resource::BinarySource.new client, subject, response
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
9
20
|
def initialize client, subject, response = nil, base_path = ''
|
10
21
|
@client = client
|
11
22
|
@subject = subject
|
@@ -67,10 +78,10 @@ module Ldp
|
|
67
78
|
# Create a new resource at the URI
|
68
79
|
# @return [RdfSource] the new representation
|
69
80
|
def create &block
|
70
|
-
raise "Can't call create on an existing resource" unless new?
|
81
|
+
raise Ldp::Error, "Can't call create on an existing resource" unless new?
|
71
82
|
verb = subject.nil? ? :post : :put
|
72
83
|
resp = client.send(verb, (subject || @base_path), content) do |req|
|
73
|
-
|
84
|
+
req.headers["Link"] = "<#{interaction_model}>;rel=\"type\"" if interaction_model
|
74
85
|
yield req if block_given?
|
75
86
|
end
|
76
87
|
|
@@ -103,14 +114,21 @@ module Ldp
|
|
103
114
|
new_response.headers['Last-Modified'] == response.headers['Last-Modified']
|
104
115
|
end
|
105
116
|
|
106
|
-
def update_cached_get
|
107
|
-
Response.
|
117
|
+
def update_cached_get(response)
|
118
|
+
response = Response.new(response)
|
119
|
+
|
108
120
|
if response.etag.nil? || response.last_modified.nil?
|
109
|
-
response =
|
121
|
+
response = client.head(subject)
|
110
122
|
end
|
111
123
|
@get.etag = response.etag
|
112
124
|
@get.last_modified = response.last_modified
|
113
125
|
end
|
114
126
|
|
127
|
+
protected
|
128
|
+
|
129
|
+
def interaction_model
|
130
|
+
nil
|
131
|
+
end
|
132
|
+
|
115
133
|
end
|
116
134
|
end
|
@@ -17,7 +17,9 @@ module Ldp
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def described_by
|
20
|
-
|
20
|
+
described_by = Array(head.links["describedby"]).first
|
21
|
+
|
22
|
+
client.find_or_initialize described_by if described_by
|
21
23
|
end
|
22
24
|
|
23
25
|
# Override inspect so that `content` is never shown. It is typically too big to be helpful
|
@@ -26,5 +28,11 @@ module Ldp
|
|
26
28
|
fields = [:subject].map{|field| "#{field}=\"#{self.send(field)}\""}
|
27
29
|
string << fields.join(", ") << ">"
|
28
30
|
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def interaction_model
|
35
|
+
RDF::Vocab::LDP.NonRDFSource
|
36
|
+
end
|
29
37
|
end
|
30
38
|
end
|