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.
@@ -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