ldp 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/bin/ldp +127 -0
- data/ldp.gemspec +2 -0
- data/lib/ldp/client/methods.rb +89 -12
- data/lib/ldp/client.rb +18 -21
- data/lib/ldp/container/basic.rb +23 -0
- data/lib/ldp/container/direct.rb +16 -0
- data/lib/ldp/container/indirect.rb +11 -0
- data/lib/ldp/container.rb +23 -9
- data/lib/ldp/orm.rb +49 -20
- data/lib/ldp/resource/binary_source.rb +23 -0
- data/lib/ldp/resource/rdf_source.rb +77 -0
- data/lib/ldp/resource.rb +39 -70
- data/lib/ldp/response/paging.rb +57 -0
- data/lib/ldp/response.rb +59 -95
- data/lib/ldp/uri.rb +37 -5
- data/lib/ldp/version.rb +1 -1
- data/lib/ldp.rb +11 -1
- data/spec/lib/ldp/client_spec.rb +71 -30
- data/spec/lib/ldp/orm/orm_spec.rb +19 -9
- data/spec/lib/ldp/resource/rdf_source_spec.rb +52 -0
- data/spec/lib/ldp/resource_spec.rb +30 -0
- data/spec/lib/ldp/response_spec.rb +2 -8
- data/spec/spec_helper.rb +2 -1
- metadata +41 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b564742703ded9a1ea57b61c4d35095152470b0d
|
4
|
+
data.tar.gz: 92c8f28addad7872849b36acfdeac29bb2ebf280
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c47ff6ed7653614374db095e93defbfa21138b072862de841464c06b8c0494707ee5d39610d06bdb640d8b4214590aae81de5f264ccbb61349afe2ffffaeb594
|
7
|
+
data.tar.gz: 2ad220371ea1d981c8ab3d29aca7f615e0bf573d56da2c56de84ba0d15a23a1173638eba23e97ef38d09eab26a7cef398037113453b017a8ffe5b01c138b25aa
|
data/Gemfile
CHANGED
data/bin/ldp
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib = File.expand_path('../../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'ldp'
|
7
|
+
require 'slop'
|
8
|
+
|
9
|
+
HttpLogger.logger = Logger.new(STDERR)
|
10
|
+
HttpLogger.log_headers = true
|
11
|
+
|
12
|
+
def with_error_handling
|
13
|
+
yield
|
14
|
+
rescue Ldp::NotFound
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
|
18
|
+
do_help = lambda do |x|
|
19
|
+
|
20
|
+
x.command 'help' do
|
21
|
+
run do |opts, args|
|
22
|
+
puts opts.help
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
Slop.parse do
|
29
|
+
banner "Usage: ldp [command] --host [HOST] [options]"
|
30
|
+
|
31
|
+
on '-v', 'Print the version' do
|
32
|
+
puts "ldp #{Ldp::VERSION}"
|
33
|
+
end
|
34
|
+
|
35
|
+
on :host=, "Host"
|
36
|
+
|
37
|
+
do_help.call(self)
|
38
|
+
|
39
|
+
command 'get' do
|
40
|
+
banner "Usage: ldp get --host [HOST] [PATH]"
|
41
|
+
|
42
|
+
on :host=, "Host"
|
43
|
+
|
44
|
+
do_help.call(self)
|
45
|
+
|
46
|
+
run do |opts, (path)|
|
47
|
+
with_error_handling do
|
48
|
+
host = opts[:host] || ENV['LDP_HOST']
|
49
|
+
puts Ldp::Client.new(url: host).find_or_initialize(path).get.body
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
command 'delete' do
|
55
|
+
banner "Usage: ldp delete --host [HOST] [PATH]"
|
56
|
+
|
57
|
+
on :host=, "Host"
|
58
|
+
do_help.call(self)
|
59
|
+
|
60
|
+
run do |opts, (path)|
|
61
|
+
with_error_handling do
|
62
|
+
host = opts[:host] || ENV['LDP_HOST']
|
63
|
+
Ldp::Client.new(url: host).delete path
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
command 'create' do
|
69
|
+
banner "Usage: ldp create --host [HOST] [PATH] [SOURCE]"
|
70
|
+
|
71
|
+
on :host=, "Host"
|
72
|
+
do_help.call(self)
|
73
|
+
|
74
|
+
run do |opts, (path, file)|
|
75
|
+
with_error_handling do
|
76
|
+
host = opts[:host] || ENV['LDP_HOST']
|
77
|
+
if file.nil?
|
78
|
+
Ldp::Client.new(url: host).post path
|
79
|
+
elsif file == "-"
|
80
|
+
Ldp::Client.new(url: host).post path, $stdin
|
81
|
+
else
|
82
|
+
Ldp::Client.new(url: host).post path, File.read(file)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
command 'replace' do
|
89
|
+
banner "Usage: ldp replace --host [HOST] [PATH] [SOURCE]"
|
90
|
+
|
91
|
+
on :host=, "Host"
|
92
|
+
do_help.call(self)
|
93
|
+
|
94
|
+
run do |opts, (path,file)|
|
95
|
+
with_error_handling do
|
96
|
+
host = opts[:host] || ENV['LDP_HOST']
|
97
|
+
if file.nil?
|
98
|
+
Ldp::Client.new(url: host).put path
|
99
|
+
elsif file == "-"
|
100
|
+
Ldp::Client.new(url: host).put path, $stdin
|
101
|
+
else
|
102
|
+
Ldp::Client.new(url: host).put path, File.read(file)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
command 'patch' do
|
109
|
+
banner "Usage: ldp patch --host [HOST] [PATH] [SOURCE]"
|
110
|
+
|
111
|
+
on :host=, "Host"
|
112
|
+
do_help.call(self)
|
113
|
+
|
114
|
+
run do |opts, (path,file)|
|
115
|
+
with_error_handling do
|
116
|
+
host = opts[:host] || ENV['LDP_HOST']
|
117
|
+
if file.nil?
|
118
|
+
Ldp::Client.new(url: host).patch path
|
119
|
+
elsif file == "-"
|
120
|
+
Ldp::Client.new(url: host).patch path, $stdin.read
|
121
|
+
else
|
122
|
+
Ldp::Client.new(url: host).patch path, File.read(file)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/ldp.gemspec
CHANGED
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_dependency "faraday"
|
22
22
|
spec.add_dependency "linkeddata", ">= 1.1"
|
23
|
+
spec.add_dependency "http_logger"
|
24
|
+
spec.add_dependency "slop"
|
23
25
|
spec.add_development_dependency "bundler", "~> 1.3"
|
24
26
|
spec.add_development_dependency "rake"
|
25
27
|
spec.add_development_dependency "rspec"
|
data/lib/ldp/client/methods.rb
CHANGED
@@ -1,12 +1,46 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
##
|
4
|
+
# HTTP client methods for making requests to an LDP resource and getting a response back.
|
1
5
|
module Ldp::Client::Methods
|
2
|
-
|
3
|
-
|
6
|
+
|
7
|
+
attr_reader :http
|
8
|
+
def initialize_http_client *http_client
|
9
|
+
if http_client.length == 1 and http_client.first.is_a? Faraday::Connection
|
10
|
+
@http = http_client.first
|
11
|
+
else
|
12
|
+
@http = Faraday.new *http_client
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def head url
|
17
|
+
logger.debug "LDP: HEAD [#{url}]"
|
18
|
+
resp = http.head do |req|
|
19
|
+
req.url munge_to_relative_url(url)
|
20
|
+
|
21
|
+
yield req if block_given?
|
22
|
+
end
|
23
|
+
|
24
|
+
check_for_errors(resp)
|
4
25
|
end
|
5
26
|
|
6
27
|
# Get a LDP Resource by URI
|
7
|
-
def get url
|
28
|
+
def get url, options = {}
|
29
|
+
logger.debug "LDP: GET [#{url}]"
|
8
30
|
resp = http.get do |req|
|
9
|
-
req.url url
|
31
|
+
req.url munge_to_relative_url(url)
|
32
|
+
|
33
|
+
if options[:minimal]
|
34
|
+
req.headers["Prefer"] = "return=minimal"
|
35
|
+
else
|
36
|
+
includes = Array(options[:include]).map { |x| Ldp.send("prefer_#{x}") if Ldp.respond_to? "prefer_#{x}" }
|
37
|
+
omits = Array(options[:omit]).map { |x| Ldp.send("prefer_#{x}") if Ldp.respond_to? "prefer_#{x}" }
|
38
|
+
req.headers["Prefer"] = ["return=representation",
|
39
|
+
("include=\"#{includes.join(" ")}\"" unless includes.empty?),
|
40
|
+
("omit=\"#{omits.join(" ")}\"" unless omits.empty?)
|
41
|
+
].compact.join("; ")
|
42
|
+
end
|
43
|
+
|
10
44
|
yield req if block_given?
|
11
45
|
end
|
12
46
|
|
@@ -15,41 +49,84 @@ module Ldp::Client::Methods
|
|
15
49
|
else
|
16
50
|
resp
|
17
51
|
end
|
52
|
+
|
53
|
+
check_for_errors(resp)
|
18
54
|
end
|
19
55
|
|
20
56
|
# Delete a LDP Resource by URI
|
21
57
|
def delete url
|
22
|
-
|
23
|
-
|
58
|
+
logger.debug "LDP: DELETE [#{url}]"
|
59
|
+
resp = http.delete do |req|
|
60
|
+
req.url munge_to_relative_url(url)
|
24
61
|
yield req if block_given?
|
25
62
|
end
|
63
|
+
|
64
|
+
check_for_errors(resp)
|
26
65
|
end
|
27
66
|
|
28
67
|
# Post TTL to an LDP Resource
|
29
68
|
def post url, body = nil, headers = {}
|
30
|
-
logger.debug "POST [#{url}]
|
31
|
-
http.post do |req|
|
32
|
-
req.url url
|
69
|
+
logger.debug "LDP: POST [#{url}]"
|
70
|
+
resp = http.post do |req|
|
71
|
+
req.url munge_to_relative_url(url)
|
33
72
|
req.headers = default_headers.merge headers
|
34
73
|
req.body = body
|
35
74
|
yield req if block_given?
|
36
75
|
end
|
76
|
+
check_for_errors(resp)
|
37
77
|
end
|
38
78
|
|
39
79
|
# Update an LDP resource with TTL by URI
|
40
80
|
def put url, body, headers = {}
|
41
|
-
logger.debug "PUT [#{url}]
|
42
|
-
http.put do |req|
|
43
|
-
req.url url
|
81
|
+
logger.debug "LDP: PUT [#{url}]"
|
82
|
+
resp = http.put do |req|
|
83
|
+
req.url munge_to_relative_url(url)
|
44
84
|
req.headers = default_headers.merge headers
|
45
85
|
req.body = body
|
46
86
|
yield req if block_given?
|
47
87
|
end
|
88
|
+
check_for_errors(resp)
|
48
89
|
end
|
49
90
|
|
91
|
+
# Update an LDP resource with TTL by URI
|
92
|
+
def patch url, body, headers = {}
|
93
|
+
logger.debug "LDP: PATCH [#{url}]"
|
94
|
+
resp = http.patch do |req|
|
95
|
+
req.url munge_to_relative_url(url)
|
96
|
+
req.headers = default_patch_headers.merge headers
|
97
|
+
req.body = body
|
98
|
+
yield req if block_given?
|
99
|
+
end
|
100
|
+
check_for_errors(resp)
|
101
|
+
end
|
50
102
|
private
|
103
|
+
|
104
|
+
def check_for_errors resp
|
105
|
+
resp.tap do |resp|
|
106
|
+
unless resp.success?
|
107
|
+
raise Ldp::NotFound.new(resp.body) if resp.status == 404
|
108
|
+
raise Ldp::HttpError.new("STATUS: #{resp.status} #{resp.body[0, 1000]}...")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
51
112
|
|
52
113
|
def default_headers
|
53
114
|
{"Content-Type"=>"text/turtle"}
|
54
115
|
end
|
116
|
+
|
117
|
+
def default_patch_headers
|
118
|
+
{"Content-Type"=>"application/sparql-update"}
|
119
|
+
end
|
120
|
+
##
|
121
|
+
# Some valid query paths can be mistaken for absolute URIs
|
122
|
+
# with an alternative scheme. If the scheme isn't HTTP(S), assume
|
123
|
+
# they meant a relative URI instead.
|
124
|
+
def munge_to_relative_url url
|
125
|
+
purl = URI.parse(url)
|
126
|
+
if purl.absolute? and !((purl.scheme rescue nil) =~ /^http/)
|
127
|
+
"./" + url
|
128
|
+
else
|
129
|
+
url
|
130
|
+
end
|
131
|
+
end
|
55
132
|
end
|
data/lib/ldp/client.rb
CHANGED
@@ -1,36 +1,33 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
##
|
2
|
+
# LDP client for presenting an ORM on top of an LDP resource
|
3
3
|
module Ldp
|
4
4
|
class Client
|
5
5
|
|
6
6
|
require 'ldp/client/methods'
|
7
|
-
|
8
7
|
include Ldp::Client::Methods
|
9
|
-
|
10
|
-
attr_reader :http
|
11
8
|
|
12
9
|
def initialize *http_client
|
13
|
-
|
14
|
-
@http = http_client.first
|
15
|
-
else
|
16
|
-
@http = Faraday.new *http_client
|
17
|
-
end
|
10
|
+
initialize_http_client *http_client
|
18
11
|
end
|
19
12
|
|
20
13
|
# Find or initialize a new LDP resource by URI
|
21
|
-
def find_or_initialize subject
|
22
|
-
data = get(subject)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
14
|
+
def find_or_initialize subject, options = {}
|
15
|
+
data = get(subject, options = {})
|
16
|
+
|
17
|
+
case
|
18
|
+
when !data.is_a?(Ldp::Response)
|
19
|
+
Resource::BinarySource.new self, subject, data
|
20
|
+
when data.container?
|
21
|
+
Ldp::Container.new_from_response self, subject, data
|
22
|
+
when data.resource?
|
23
|
+
Resource::RdfSource.new self, subject, data
|
24
|
+
else
|
25
|
+
Resource::BinarySource.new self, subject, data
|
32
26
|
end
|
33
27
|
end
|
34
28
|
|
29
|
+
def logger
|
30
|
+
Ldp.logger
|
31
|
+
end
|
35
32
|
end
|
36
33
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Ldp
|
2
|
+
class Container::Basic < Container
|
3
|
+
def members
|
4
|
+
return enum_for(:members) unless block_given?
|
5
|
+
contains.each { |k, x| yield x }
|
6
|
+
end
|
7
|
+
|
8
|
+
def contains
|
9
|
+
@contains ||= Hash[get.graph.query(predicate: Ldp.contains).map do |x|
|
10
|
+
[x.object, Ldp::Resource::RdfSource.new(client, x.object, contained_graph(x.object))]
|
11
|
+
end]
|
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
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Ldp
|
2
|
+
class Container::Direct < Container::Basic
|
3
|
+
def members
|
4
|
+
return enum_for(:members) unless block_given?
|
5
|
+
|
6
|
+
get.graph.query(subject: subject, predicate: member_relation).map do |x|
|
7
|
+
yield contains[x.object] || Ldp::Resource::RdfSource.new(client, x.object)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def member_relation
|
12
|
+
graph.first_object(predicate: Ldp.hasMemberRelation) || Ldp.member
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Ldp
|
2
|
+
class Container::Indirect < Container::Direct
|
3
|
+
def members
|
4
|
+
return enum_for(:members) unless block_given?
|
5
|
+
|
6
|
+
get.graph.query(predicate: member_relation, object: subject).map do |x|
|
7
|
+
yield contains[x.object] || Ldp::Resource::RdfSource.new(client, x.object)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/ldp/container.rb
CHANGED
@@ -1,7 +1,22 @@
|
|
1
1
|
module Ldp
|
2
|
-
class Container < Resource
|
2
|
+
class Container < Resource::RdfSource
|
3
|
+
require 'ldp/container/basic'
|
4
|
+
require 'ldp/container/direct'
|
5
|
+
require 'ldp/container/indirect'
|
6
|
+
|
7
|
+
def self.new_from_response client, subject, data
|
8
|
+
case
|
9
|
+
when data.types.include?(Ldp.indirect_container)
|
10
|
+
Ldp::Container::Indirect.new client, subject, data
|
11
|
+
when data.types.include?(Ldp.direct_container)
|
12
|
+
Ldp::Container::Direct.new client, subject, data
|
13
|
+
else
|
14
|
+
Ldp::Container::Basic.new client, subject, data
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
3
18
|
##
|
4
|
-
# Add a resource to the LDP container
|
19
|
+
# Add a new resource to the LDP container
|
5
20
|
def add *args
|
6
21
|
# slug, graph
|
7
22
|
# graph
|
@@ -11,21 +26,20 @@ module Ldp
|
|
11
26
|
when (args.length > 2 || args.length == 0)
|
12
27
|
|
13
28
|
when (args.length == 2)
|
14
|
-
slug,
|
29
|
+
slug, graph_or_content = args
|
15
30
|
when (args.first.is_a? RDF::Graph)
|
16
31
|
slug = nil
|
17
|
-
|
32
|
+
graph_or_content = args.first
|
18
33
|
else
|
19
34
|
slug = args.first
|
20
|
-
|
35
|
+
graph_or_content = RDF::Graph.new
|
21
36
|
end
|
22
37
|
|
23
|
-
resp = client.post subject,
|
38
|
+
resp = client.post subject, (graph_or_content.is_a?(RDF::Graph) ? graph_or_content.dump(:ttl) : graph_or_content) do |req|
|
24
39
|
req.headers['Slug'] = slug
|
25
40
|
end
|
26
41
|
|
27
|
-
|
28
|
-
return client.find_or_initialize subject
|
42
|
+
client.find_or_initialize resp.headers['Location']
|
29
43
|
end
|
30
44
|
end
|
31
|
-
end
|
45
|
+
end
|
data/lib/ldp/orm.rb
CHANGED
@@ -7,39 +7,67 @@ module Ldp
|
|
7
7
|
def initialize resource
|
8
8
|
@resource = resource
|
9
9
|
end
|
10
|
+
|
11
|
+
def subject_uri
|
12
|
+
resource.subject_uri
|
13
|
+
end
|
14
|
+
|
15
|
+
def new?
|
16
|
+
resource.new?
|
17
|
+
end
|
18
|
+
|
19
|
+
def persisted?
|
20
|
+
!new?
|
21
|
+
end
|
10
22
|
|
11
23
|
def graph
|
12
|
-
|
24
|
+
Ldp.instrument 'graph.orm.ldp', subject: subject_uri do
|
25
|
+
resource.graph
|
26
|
+
end
|
13
27
|
end
|
14
28
|
|
15
29
|
def value predicate
|
16
|
-
graph.query(:subject =>
|
30
|
+
graph.query(:subject => subject_uri, :predicate => predicate).map do |stmt|
|
17
31
|
stmt.object
|
18
32
|
end
|
19
33
|
end
|
20
34
|
|
21
35
|
def query *args, &block
|
22
|
-
|
36
|
+
Ldp.instrument 'query.orm.ldp', subject: subject_uri do
|
37
|
+
graph.query *args, &block
|
38
|
+
end
|
23
39
|
end
|
24
40
|
|
25
41
|
def reload
|
26
|
-
Ldp
|
42
|
+
Ldp.instrument 'reload.orm.ldp', subject: subject_uri do
|
43
|
+
Ldp::Orm.new resource.reload
|
44
|
+
end
|
27
45
|
end
|
28
46
|
|
29
47
|
def create
|
30
|
-
|
48
|
+
Ldp.instrument 'create.orm.ldp', subject: subject_uri do
|
49
|
+
# resource.create returns a reloaded resource which causes any default URIs (e.g. "<>")
|
50
|
+
# in the graph to be transformed to routable URIs
|
51
|
+
Ldp::Orm.new resource.create
|
52
|
+
end
|
31
53
|
end
|
32
54
|
|
33
55
|
def save
|
34
|
-
|
56
|
+
Ldp.instrument 'save.orm.ldp', subject: subject_uri do
|
57
|
+
@last_response = resource.save
|
35
58
|
|
36
|
-
|
59
|
+
diff = resource.check_for_differences_and_reload
|
37
60
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
61
|
+
if diff.any?
|
62
|
+
diff
|
63
|
+
else
|
64
|
+
@last_response.success?
|
65
|
+
end
|
42
66
|
end
|
67
|
+
rescue Ldp::HttpError => e
|
68
|
+
@last_response = e
|
69
|
+
logger.debug e
|
70
|
+
false
|
43
71
|
end
|
44
72
|
|
45
73
|
def save!
|
@@ -48,14 +76,16 @@ module Ldp
|
|
48
76
|
if result.is_a? RDF::Graph
|
49
77
|
raise GraphDifferenceException.new "", result
|
50
78
|
elsif !result
|
51
|
-
raise SaveException.new
|
79
|
+
raise SaveException.new @last_response
|
52
80
|
end
|
53
81
|
|
54
82
|
result
|
55
83
|
end
|
56
84
|
|
57
85
|
def delete
|
58
|
-
|
86
|
+
Ldp.instrument 'delete.orm.ldp', subject: subject_uri do
|
87
|
+
resource.delete
|
88
|
+
end
|
59
89
|
end
|
60
90
|
|
61
91
|
def method_missing meth, *args, &block
|
@@ -66,6 +96,11 @@ module Ldp
|
|
66
96
|
super
|
67
97
|
end
|
68
98
|
|
99
|
+
private
|
100
|
+
|
101
|
+
def logger
|
102
|
+
Ldp.logger
|
103
|
+
end
|
69
104
|
end
|
70
105
|
|
71
106
|
class GraphDifferenceException < Exception
|
@@ -76,12 +111,6 @@ module Ldp
|
|
76
111
|
end
|
77
112
|
end
|
78
113
|
|
79
|
-
class SaveException <
|
80
|
-
attr_reader :response
|
81
|
-
def initialize message, response
|
82
|
-
super(message)
|
83
|
-
@response = response
|
84
|
-
end
|
114
|
+
class SaveException < RuntimeError
|
85
115
|
end
|
86
116
|
end
|
87
|
-
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Ldp
|
2
|
+
class Resource::BinarySource < Ldp::Resource
|
3
|
+
attr_accessor :content
|
4
|
+
|
5
|
+
def initialize client, subject, content_or_response = nil
|
6
|
+
super client, subject, content_or_response
|
7
|
+
|
8
|
+
case content_or_response
|
9
|
+
when Faraday::Response
|
10
|
+
else
|
11
|
+
@content = content_or_response
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def content
|
16
|
+
@content ||= get.body
|
17
|
+
end
|
18
|
+
|
19
|
+
def described_by
|
20
|
+
client.find_or_initialize Array(Ldp::Response.links(self)["describedby"]).first
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Ldp
|
2
|
+
class Resource::RdfSource < Ldp::Resource
|
3
|
+
|
4
|
+
def initialize client, subject, graph_or_response = nil
|
5
|
+
super client, subject, graph_or_response
|
6
|
+
|
7
|
+
case graph_or_response
|
8
|
+
when RDF::Graph
|
9
|
+
@graph = graph_or_response
|
10
|
+
when Ldp::Response
|
11
|
+
when NilClass
|
12
|
+
#nop
|
13
|
+
else
|
14
|
+
raise ArgumentError, "Third argument to #{self.class}.new should be a RDF::Graph or a Ldp::Response. You provided #{graph_or_response.class}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def create
|
19
|
+
super do |req|
|
20
|
+
req.headers = { "Content-Type" => "text/turtle" }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def content
|
25
|
+
graph.dump(:ttl) if graph
|
26
|
+
end
|
27
|
+
|
28
|
+
def graph
|
29
|
+
@graph ||= RDF::Graph.new if new?
|
30
|
+
@graph ||= begin
|
31
|
+
original_graph = get.graph
|
32
|
+
|
33
|
+
inlinedResources = get.graph.query(:predicate => Ldp.contains).map { |x| x.object }
|
34
|
+
|
35
|
+
# we want to scope this graph to just statements about this model, not contained relations
|
36
|
+
unless inlinedResources.empty?
|
37
|
+
new_graph = RDF::Graph.new
|
38
|
+
|
39
|
+
original_graph.each_statement do |s|
|
40
|
+
unless inlinedResources.include? s.subject
|
41
|
+
new_graph << s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
new_graph
|
46
|
+
else
|
47
|
+
original_graph
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def check_for_differences_and_reload
|
53
|
+
self.class.check_for_differences_and_reload_resource self
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.check_for_differences_and_reload_resource old_object
|
57
|
+
new_object = old_object.reload
|
58
|
+
|
59
|
+
bijection = new_object.graph.bijection_to(old_object.graph)
|
60
|
+
diff = RDF::Graph.new
|
61
|
+
|
62
|
+
old_object.graph.each do |statement|
|
63
|
+
if statement.has_blank_nodes?
|
64
|
+
subject = bijection.fetch(statement.subject, false) if statement.subject.node?
|
65
|
+
object = bijection.fetch(statement.object, false) if statement.object.node?
|
66
|
+
bijection_statement = RDF::Statement.new :subject => subject || statemnet.subject, :predicate => statement.predicate, :object => object || statement.object
|
67
|
+
|
68
|
+
diff << statement if subject === false or object === false or new_object.graph.has_statement?(bijection_statement)
|
69
|
+
elsif !new_object.graph.has_statement? statement
|
70
|
+
diff << statement
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
diff
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|