ldp 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,7 +28,7 @@ module Ldp
28
28
  end
29
29
 
30
30
  def graph
31
- @graph ||= new? ? build_empty_graph : build_graph(response_as_graph(get))
31
+ @graph ||= new? ? build_empty_graph : filtered_graph(response_graph)
32
32
  end
33
33
 
34
34
  def build_empty_graph
@@ -38,34 +38,49 @@ module Ldp
38
38
  ##
39
39
  # graph_class may be overridden so that a subclass of RDF::Graph
40
40
  # is returned (e.g. an ActiveTriples resource)
41
- # @returns [Class] a class that is an descendant of RDF::Graph
41
+ # @return [Class] a class that is an descendant of RDF::Graph
42
42
  def graph_class
43
43
  RDF::Graph
44
44
  end
45
45
 
46
+ ##
47
+ # Parse the graph returned by the LDP server into an RDF::Graph
48
+ # @return [RDF::Graph]
49
+ def response_graph
50
+ @response_graph ||= response_as_graph(get)
51
+ end
52
+
53
+ # Get the body and ensure it's UTF-8 encoded. Since Fedora 9.3 isn't
54
+ # returning a charset, then Net::HTTP is just returning ASCII-8BIT
55
+ # See https://github.com/ruby-rdf/rdf-turtle/issues/13
56
+ # See https://jira.duraspace.org/browse/FCREPO-1750
57
+ def body
58
+ body.force_encoding('utf-8')
59
+ end
46
60
 
61
+ protected
62
+
63
+ def interaction_model
64
+ RDF::Vocab::LDP.Resource unless client.options[:omit_ldpr_interaction_model]
65
+ end
47
66
 
48
67
  private
49
68
  ##
50
69
  # @param [Faraday::Response] graph query response
51
70
  # @return [RDF::Graph]
52
71
  def response_as_graph(resp)
53
- content_type = resp.headers['Content-Type'] || 'text/turtle'
54
- content_type = Array(content_type).first
55
- format = Array(RDF::Format.content_types[content_type]).first
56
- source = resp.body
57
- reader = RDF::Reader.for(content_type:content_type).new(source, base_uri:subject)
58
72
  graph = build_empty_graph
59
- reader.each_statement do |stmt|
73
+ resp.each_statement do |stmt|
60
74
  graph << stmt
61
75
  end
62
76
  graph
63
77
  end
78
+
64
79
  ##
65
80
  # @param [RDF::Graph] original_graph The graph returned by the LDP server
66
- # @return [RDF::Graph] A graph striped of any inlined resources present in the original
67
- def build_graph(original_graph)
68
- inlined_resources = response_as_graph(get).query(predicate: Ldp.contains).map { |x| x.object }
81
+ # @return [RDF::Graph] A graph stripped of any inlined resources present in the original
82
+ def filtered_graph(original_graph)
83
+ inlined_resources = original_graph.query(predicate: RDF::Vocab::LDP.contains).map { |x| x.object }
69
84
 
70
85
  # we want to scope this graph to just statements about this model, not contained relations
71
86
  if inlined_resources.empty?
@@ -1,35 +1,40 @@
1
+ require 'uri'
2
+
1
3
  module Ldp
2
- module Response
3
- require 'ldp/response/paging'
4
+ class Response
5
+ extend Forwardable
4
6
 
5
7
  TYPE = 'type'.freeze
6
- ##
7
- # Wrap the raw Faraday respone with our LDP extensions
8
- def self.wrap client, raw_resp
9
- raw_resp.send(:extend, Ldp::Response)
10
- raw_resp.send(:extend, Ldp::Response::Paging) if raw_resp.has_page?
11
- raw_resp
8
+
9
+ attr_reader :response
10
+
11
+ attr_writer :etag, :last_modified
12
+
13
+ def initialize(response)
14
+ @response = response
12
15
  end
13
16
 
14
17
  ##
15
18
  # Extract the Link: headers from the HTTP resource
16
- def self.links response
17
- h = {}
18
- Array(response.headers['Link'.freeze]).map { |x| x.split(', '.freeze) }.flatten.inject(h) do |memo, header|
19
- m = header.match(/<(?<link>.*)>;\s?rel="(?<rel>[^"]+)"/)
20
- if m
21
- memo[m[:rel]] ||= []
22
- memo[m[:rel]] << m[:link]
23
- end
19
+ def links
20
+ @links ||= begin
21
+ h = {}
22
+ Array(headers['Link'.freeze]).map { |x| x.split(','.freeze) }.flatten.inject(h) do |memo, header|
23
+ m = header.match(/<(?<link>.*)>;\s?rel="(?<rel>[^"]+)"/)
24
+ if m
25
+ memo[m[:rel]] ||= []
26
+ memo[m[:rel]] << m[:link]
27
+ end
24
28
 
25
- memo
29
+ memo
30
+ end
26
31
  end
27
32
  end
28
33
 
29
- def self.applied_preferences headers
34
+ def applied_preferences
30
35
  h = {}
31
36
 
32
- Array(headers).map { |x| x.split(",") }.flatten.inject(h) do |memo, header|
37
+ Array(headers['Preference-Applied'.freeze]).map { |x| x.split(",") }.flatten.inject(h) do |memo, header|
33
38
  m = header.match(/(?<key>[^=;]*)(=(?<value>[^;,]*))?(;\s*(?<params>[^,]*))?/)
34
39
  includes = (m[:params].match(/include="(?<include>[^"]+)"/)[:include] || "").split(" ")
35
40
  omits = (m[:params].match(/omit="(?<omit>[^"]+)"/)[:omit] || "").split(" ")
@@ -40,101 +45,78 @@ module Ldp
40
45
  ##
41
46
  # Is the response an LDP resource?
42
47
 
43
- def self.resource? response
44
- Array(links(response)[TYPE]).include? Ldp.resource.to_s
48
+ def resource?
49
+ Array(links[TYPE]).include? RDF::Vocab::LDP.Resource.to_s
45
50
  end
46
51
 
47
52
  ##
48
53
  # Is the response an LDP container?
49
- def self.container? response
54
+ def container?
50
55
  [
51
- Ldp.basic_container,
52
- Ldp.direct_container,
53
- Ldp.indirect_container
54
- ].any? { |x| Array(links(response)[TYPE]).include? x.to_s }
56
+ RDF::Vocab::LDP.BasicContainer,
57
+ RDF::Vocab::LDP.DirectContainer,
58
+ RDF::Vocab::LDP.IndirectContainer
59
+ ].any? { |x| Array(links[TYPE]).include? x.to_s }
55
60
  end
56
61
 
57
62
  ##
58
63
  # Is the response an LDP RDFSource?
59
64
  # ldp:Container is a subclass of ldp:RDFSource
60
- def self.rdf_source? response
61
- container?(response) || Array(links(response)[TYPE]).include?(Ldp.rdf_source)
65
+ def rdf_source?
66
+ container? || Array(links[TYPE]).include?(RDF::Vocab::LDP.RDFSource)
62
67
  end
63
68
 
64
69
  def dup
65
70
  super.tap do |new_resp|
66
- new_resp.send(:extend, Ldp::Response)
67
71
  unless new_resp.instance_variable_get(:@graph).nil?
68
- if ::RUBY_VERSION < '2.0'
69
- new_resp.send(:remove_instance_variable, :@graph)
70
- else
71
- new_resp.remove_instance_variable(:@graph)
72
- end
72
+ new_resp.remove_instance_variable(:@graph)
73
73
  end
74
74
  end
75
75
  end
76
76
 
77
- ##
78
- # Link: headers from the HTTP response
79
- def links
80
- @links ||= Ldp::Response.links(self)
81
- end
82
-
83
- ##
84
- # Is the response an LDP resource?
85
- def resource?
86
- Ldp::Response.resource?(self)
87
- end
88
-
89
- ##
90
- # Is the response an LDP rdf source?
91
- def rdf_source?
92
- Ldp::Response.rdf_source?(self)
93
- end
94
-
95
- ##
96
- # Is the response an LDP container
97
- def container?
98
- Ldp::Response.container?(self)
99
- end
100
-
101
- def preferences
102
- Ldp::Resource.applied_preferences(headers['Preference-Applied'.freeze])
103
- end
104
77
  ##
105
78
  # Get the subject for the response
106
79
  def subject
107
- page_subject
80
+ @subject ||= if has_page?
81
+ graph.first_object [page_subject, RDF::Vocab::LDP.pageOf, nil]
82
+ else
83
+ page_subject
84
+ end
108
85
  end
109
86
 
110
87
  ##
111
88
  # Get the URI to the response
112
89
  def page_subject
113
- @page_subject ||= RDF::URI.new env[:url]
90
+ @page_subject ||= RDF::URI.new response.env[:url]
114
91
  end
115
92
 
116
93
  ##
117
94
  # Is the response paginated?
118
95
  def has_page?
119
- rdf_source? && graph.has_statement?(RDF::Statement.new(page_subject, RDF.type, Ldp.page))
96
+ rdf_source? && graph.has_statement?(RDF::Statement.new(page_subject, RDF.type, RDF::Vocab::LDP.Page))
97
+ end
98
+
99
+ def body
100
+ response.body
120
101
  end
121
102
 
122
103
  ##
123
104
  # Get the graph for the resource (or a blank graph if there is no metadata for the resource)
124
105
  def graph
125
106
  @graph ||= begin
126
- raise UnexpectedContentType, "The resource at #{page_subject} is not an RDFSource" unless rdf_source?
127
107
  graph = RDF::Graph.new
108
+ each_statement { |s| graph << s }
109
+ graph
110
+ end
111
+ end
128
112
 
129
- if resource?
130
- RDF::Reader.for(:ttl).new(response_body, base_uri: page_subject) do |reader|
131
- reader.each_statement do |s|
132
- graph << s
133
- end
134
- end
135
- end
113
+ def reader(&block)
114
+ reader_for_content_type.new(body, base_uri: page_subject, &block)
115
+ end
136
116
 
137
- graph
117
+ def each_statement(&block)
118
+ reader do |reader|
119
+ reader.each_statement(&block)
138
120
  end
139
121
  end
140
122
 
@@ -144,20 +126,12 @@ module Ldp
144
126
  @etag ||= headers['ETag'.freeze]
145
127
  end
146
128
 
147
- def etag=(val)
148
- @etag = val
149
- end
150
-
151
129
  ##
152
130
  # Extract the last modified header for the resource
153
131
  def last_modified
154
132
  @last_modified ||= headers['Last-Modified'.freeze]
155
133
  end
156
134
 
157
- def last_modified=(val)
158
- @last_modified = val
159
- end
160
-
161
135
  ##
162
136
  # Extract the Link: rel="type" headers for the resource
163
137
  def types
@@ -176,14 +150,69 @@ module Ldp
176
150
  preferences[RETURN][:value] == "minimal"
177
151
  end
178
152
 
179
- private
153
+ ##
154
+ # Statements about the page
155
+ def page
156
+ @page_graph ||= begin
157
+ g = RDF::Graph.new
158
+
159
+ if resource?
160
+ res = graph.query RDF::Statement.new(page_subject, nil, nil)
161
+
162
+ res.each_statement do |s|
163
+ g << s
164
+ end
165
+ end
166
+
167
+ g
168
+ end
169
+ end
170
+
171
+ ##
172
+ # Is there a next page?
173
+ def has_next?
174
+ next_page != nil
175
+ end
176
+
177
+ ##
178
+ # Get the URI for the next page
179
+ def next_page
180
+ graph.first_object [page_subject, RDF::Vocab::LDP.nextPage, nil]
181
+ end
180
182
 
181
- # Get the body and ensure it's UTF-8 encoded. Since Fedora 9.3 isn't
182
- # returning a charset, then Net::HTTP is just returning ASCII-8BIT
183
- # See https://github.com/ruby-rdf/rdf-turtle/issues/13
184
- # See https://jira.duraspace.org/browse/FCREPO-1750
185
- def response_body
186
- body.force_encoding('utf-8')
183
+ ##
184
+ # Get the URI to the first page
185
+ def first_page
186
+ if links['first']
187
+ RDF::URI.new links['first']
188
+ elsif graph.has_statement? RDf::Statement.new(page_subject, RDF::Vocab::LDP.nextPage, nil)
189
+ subject
187
190
  end
191
+ end
192
+
193
+ def content_type
194
+ headers['Content-Type']
195
+ end
196
+
197
+ def content_length
198
+ headers['Content-Length'].to_i
199
+ end
200
+
201
+ def content_disposition_filename
202
+ m = headers['Content-Disposition'].match(/filename="(?<filename>[^"]*)";/)
203
+ URI.decode(m[:filename]) if m
204
+ end
205
+
206
+ private
207
+
208
+ def headers
209
+ response.headers
210
+ end
211
+
212
+ def reader_for_content_type
213
+ content_type = content_type || 'text/turtle'
214
+ content_type = Array(content_type).first
215
+ RDF::Reader.for(content_type: content_type)
216
+ end
188
217
  end
189
218
  end
@@ -1,75 +1,91 @@
1
1
  module Ldp::Uri
2
+ extend Deprecation
3
+ self.deprecation_horizon = 'ldp version 0.6'
2
4
 
3
5
  def uri str
4
6
  RDF::URI.new("http://www.w3.org/ns/ldp#") + str
5
7
  end
8
+ deprecation_deprecate :uri
6
9
 
7
10
  def resource
8
- uri("Resource")
11
+ RDF::Vocab::LDP.Resource
9
12
  end
13
+ deprecation_deprecate :resource
10
14
 
11
15
  def rdf_source
12
- uri("RDFSource")
16
+ RDF::Vocab::LDP.RDFSource
13
17
  end
18
+ deprecation_deprecate :rdf_source
14
19
 
15
20
  def non_rdf_source
16
- uri("NonRDFSource")
21
+ RDF::Vocab::LDP.NonRDFSource
17
22
  end
23
+ deprecation_deprecate :non_rdf_source
18
24
 
19
25
  def container
20
- uri("Container")
26
+ RDF::Vocab::LDP.Container
21
27
  end
28
+ deprecation_deprecate :container
22
29
 
23
30
  def basic_container
24
- uri("BasicContainer")
31
+ RDF::Vocab::LDP.BasicContainer
25
32
  end
33
+ deprecation_deprecate :basic_container
26
34
 
27
35
  def direct_container
28
- uri("DirectContainer")
36
+ RDF::Vocab::LDP.DirectContainer
29
37
  end
38
+ deprecation_deprecate :direct_container
30
39
 
31
40
  def indirect_container
32
- uri("IndirectContainer")
41
+ RDF::Vocab::LDP.IndirectContainer
33
42
  end
43
+ deprecation_deprecate :indirect_container
34
44
 
35
45
  def contains
36
- uri("contains")
46
+ RDF::Vocab::LDP.contains
37
47
  end
48
+ deprecation_deprecate :contains
38
49
 
39
50
  def page
40
- uri("Page")
51
+ RDF::Vocab::LDP.Page
41
52
  end
53
+ deprecation_deprecate :page
42
54
 
43
55
  def page_of
44
- uri("pageOf")
56
+ RDF::Vocab::LDP.pageOf
45
57
  end
58
+ deprecation_deprecate :page_of
46
59
 
47
60
  def next_page
48
- uri("nextPage")
61
+ RDF::Vocab::LDP.nextPage
49
62
  end
63
+ deprecation_deprecate :next_page
50
64
 
51
65
  def membership_predicate
52
- uri("membershipPredicate")
66
+ RDF::Vocab::LDP.membershipPredicate
53
67
  end
54
-
68
+ deprecation_deprecate :membership_predicate
69
+
55
70
  def prefer_empty_container
56
- uri("PreferEmptyContainer")
71
+ RDF::Vocab::LDP.PreferEmptyContainer
57
72
  end
58
-
73
+
59
74
  def prefer_membership
60
- uri("PreferMembership")
75
+ RDF::Vocab::LDP.PreferMembership
61
76
  end
62
-
77
+
63
78
  def prefer_containment
64
- uri("PreferContainment")
79
+ RDF::Vocab::LDP.PreferContainment
65
80
  end
66
-
81
+
67
82
  def has_member_relation
68
- uri("hasMemberRelation")
83
+ RDF::Vocab::LDP.hasMemberRelation
69
84
  end
70
-
85
+ deprecation_deprecate :has_member_relation
86
+
71
87
  def member
72
- uri("member")
88
+ RDF::Vocab::LDP.member
73
89
  end
74
-
90
+ deprecation_deprecate :member
75
91
  end