ldp 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 882fd676e2cd2aac5923a8f7a4b308228569607b
4
- data.tar.gz: b94c819301cb2ab968085aa6ca371b4eec682e94
3
+ metadata.gz: 3a68882c3e0ea6d21e3819d632a92e88734bec0f
4
+ data.tar.gz: a3f31f5e16fc2a60b109bef5f7da218ad008e949
5
5
  SHA512:
6
- metadata.gz: d4efcff3ae303486a051bc22477ce087e89ee197d2eba531aee9d8c9bbf9767d06f6949f0be830627539377c78828c4d542e08d7a81daaaec9714892e6831cdd
7
- data.tar.gz: b3a69169e198f975e8cdb1b5be96e9d9aedbda161eda6c9deac37393ed4615949edb8a970d531c3b8faa7889eb53d62c254366643cb33d207c2da5b9895e72a8
6
+ metadata.gz: 4111cddaaccda626e39b8ba24619763ca217f97915855ba2fb936e7fcb7ba1f9d6afc78d268393f7c3a67128d6427a0a41f99b2d24d2f09d41e287e5aa1f1ae0
7
+ data.tar.gz: 173b2d3954e4aa0184a5d87916c637c8348fe185ad561b51cdc28b844d81c14bf820bcdac27551d097f6ccf348c35eaf5c49d20759741ce3cf64571f963dd133
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .storage
@@ -1,3 +1,7 @@
1
+ addons:
2
+ apt:
3
+ packages:
4
+ - libgmp-dev
1
5
  language: ruby
2
6
  cache: bundler
3
7
  sudo: false
@@ -5,6 +9,7 @@ env:
5
9
  global:
6
10
  - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
7
11
  rvm:
8
- - 2.1
9
- - 2.2
10
- - jruby
12
+ - 2.3.0
13
+ - 2.2.4
14
+ - 2.1.8
15
+ - jruby-9.0.5.0
data/Gemfile CHANGED
@@ -4,5 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'slop', '~> 3.6' if RUBY_PLATFORM == "java"
7
- gem 'byebug', platforms: :mri_20
7
+ gem 'byebug', platforms: [:mri]
8
8
  gem 'activesupport'
9
+ gem 'capybara_discoball'
10
+ gem 'derby'
@@ -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
@@ -7,24 +7,29 @@ module Ldp
7
7
  require 'ldp/client/prefer_headers'
8
8
  include Ldp::Client::Methods
9
9
 
10
- def initialize *http_client
11
- initialize_http_client *http_client
12
- end
10
+ attr_reader :options
13
11
 
14
- # Find or initialize a new LDP resource by URI
15
- def find_or_initialize subject, options = {}
16
- data = get(subject, options = {})
17
-
18
- case
19
- when !data.is_a?(Ldp::Response)
20
- Resource::BinarySource.new self, subject, data
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
- Resource::BinarySource.new self, subject, data
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
@@ -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
 
@@ -4,17 +4,27 @@ module Ldp
4
4
  require 'ldp/container/direct'
5
5
  require 'ldp/container/indirect'
6
6
 
7
- def self.new_from_response client, subject, data
7
+ def self.for(client, subject, data)
8
8
  case
9
- when data.types.include?(Ldp.indirect_container)
9
+ when data.types.include?(RDF::Vocab::LDP.IndirectContainer)
10
10
  Ldp::Container::Indirect.new client, subject, data
11
- when data.types.include?(Ldp.direct_container)
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 = RDF::Graph.new
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
@@ -5,19 +5,10 @@ module Ldp
5
5
  contains.each { |k, x| yield x }
6
6
  end
7
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
8
+ protected
9
+
10
+ def interaction_model
11
+ RDF::Vocab::LDP.BasicContainer
21
12
  end
22
13
  end
23
14
  end
@@ -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
- get.graph.query(subject: subject, predicate: member_relation).map do |x|
7
- yield contains[x.object] || Ldp::Resource::RdfSource.new(client, x.object)
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
- graph.first_object(predicate: Ldp.hasMemberRelation) || Ldp.member
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
- get.graph.query(predicate: member_relation, object: subject).map do |x|
7
- yield contains[x.object] || Ldp::Resource::RdfSource.new(client, x.object)
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
@@ -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
@@ -54,22 +54,19 @@ module Ldp
54
54
 
55
55
  def save
56
56
  Ldp.instrument 'save.orm.ldp', subject: subject_uri do
57
- @last_response = resource.save
58
- @last_response.success?
57
+ response = create_or_update
58
+
59
+ response.success?
59
60
  end
60
- rescue Ldp::HttpError => e
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 = save
66
+ result = create_or_update
68
67
 
69
68
  if result.is_a? RDF::Enumerable
70
- raise GraphDifferenceException.new "", result
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
- def method_missing meth, *args, &block
85
- super
86
- end
81
+ private
87
82
 
88
- def respond_to?(meth)
89
- super
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
@@ -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 response
107
- Response.wrap(client, 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 = Response.wrap(client, client.head(subject))
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
- client.find_or_initialize Array(Ldp::Response.links(self)["describedby"]).first
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