dor-services-client 0.4.0 → 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
  SHA256:
3
- metadata.gz: d0938b1979de1f6767e88044a77182623502a0ee923d445fd11d892f83c9c81c
4
- data.tar.gz: d091617c14b075d111980b1052ab0662382362bbbdd2ffe943609c4d94f997ee
3
+ metadata.gz: cbe8578f95f4533b0b91fe9a3c47ede0d1ba51db157e5f015928ba7b5b1fe19e
4
+ data.tar.gz: b3e4e136c27186b625b86ebc138d59f032e03f1f6c908f65ee6c7206c73c7143
5
5
  SHA512:
6
- metadata.gz: 121eecbb6172914d1bd345167ae7f92064c815c17634f2e017cf1c39617368da597e4d0cb9598c7d907cff64e3d7740d4916f174ba3d1c33b5b2e57b7eb66087
7
- data.tar.gz: 99ce5863977ec58b8b315ed91867eeb8c1f2f31efe763f045ca0519676d0b03842bdf9095f67bee5e9ea5bd041c3ddf939c26dd792d68f645eabd591594e4b67
6
+ metadata.gz: 933595fee0dbdec82b6d46c5b1bb63ed0cf4022d702ae97df1c294a8688d14e080fc893303ea981def0f9d8d86d08afff16517811a1e26fbd611258023259025
7
+ data.tar.gz: fd88271153d2c461cedacfb7447c22fc4c47b87db50c5d44b8484a9f63fdb56ebc285006605ee5280a43688aa4461dae8cf3cb72f0d29dffec496e7a33531e76
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_dependency 'activesupport', '>= 4.2', '< 6'
26
26
  spec.add_dependency 'faraday', '~> 0.15'
27
+ spec.add_dependency 'nokogiri', '~> 1.8'
27
28
 
28
29
  spec.add_development_dependency 'bundler', '~> 1.17'
29
30
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -4,6 +4,7 @@ require 'dor/services/client/version'
4
4
  require 'singleton'
5
5
  require 'faraday'
6
6
  require 'active_support/core_ext/hash/indifferent_access'
7
+ require 'active_support/core_ext/module/delegation'
7
8
  require 'dor/services/client/versioned_service'
8
9
  require 'dor/services/client/files'
9
10
  require 'dor/services/client/objects'
@@ -16,6 +17,13 @@ module Dor
16
17
  class Client
17
18
  class Error < StandardError; end
18
19
 
20
+ # Error that is raised when the remote server returns some unexpected response
21
+ # this could be any 4xx or 5xx status.
22
+ class UnexpectedResponse < Error; end
23
+
24
+ # Error that is raised when the remote server returns some unparsable response
25
+ class MalformedResponse < Error; end
26
+
19
27
  DEFAULT_VERSION = 'v1'
20
28
 
21
29
  include Singleton
@@ -40,68 +48,85 @@ module Dor
40
48
  @release_tags ||= ReleaseTags.new(connection: connection, version: DEFAULT_VERSION)
41
49
  end
42
50
 
43
- def self.configure(url:, username: nil, password: nil)
44
- instance.url = url
45
- instance.username = username
46
- instance.password = password
47
- # Force connection to be re-established when `.configure` is called
48
- instance.connection = nil
49
- end
51
+ class << self
52
+ def configure(url:, username: nil, password: nil)
53
+ instance.url = url
54
+ instance.username = username
55
+ instance.password = password
56
+ # Force connection to be re-established when `.configure` is called
57
+ instance.connection = nil
58
+ end
50
59
 
51
- # Creates a new object in DOR
52
- # @return [HashWithIndifferentAccess] the response, which includes a :pid
53
- def self.register(params:)
54
- instance.objects.register(params: params)
55
- end
60
+ delegate :objects, :files, :workflow, :workspace, :release_tags, to: :instance
61
+ private :objects, :files, :workflow, :workspace, :release_tags
56
62
 
57
- # @param [String] object the identifier for the object
58
- # @param [String] filename the name of the file to retrieve
59
- # @return [String] the file contents from the workspace
60
- def self.retrieve_file(object:, filename:)
61
- instance.files.retrieve(object: object, filename: filename)
62
- end
63
+ # Creates a new object in DOR
64
+ # @return [HashWithIndifferentAccess] the response, which includes a :pid
65
+ delegate :register, to: :objects
63
66
 
64
- # @param [String] object the identifier for the object
65
- # @return [Array<String>] the list of filenames in the workspace
66
- def self.list_files(object:)
67
- instance.files.list(object: object)
68
- end
67
+ # @param [String] object the identifier for the object
68
+ # @param [String] filename the name of the file to retrieve
69
+ # @return [String] the file contents from the workspace
70
+ def retrieve_file(object:, filename:)
71
+ files.retrieve(object: object, filename: filename)
72
+ end
69
73
 
70
- # Initializes a new workflow
71
- # @param object [String] the pid for the object
72
- # @param wf_name [String] the name of the workflow
73
- # @raises [Error] if the request is unsuccessful.
74
- # @return nil
75
- def self.initialize_workflow(object:, wf_name:)
76
- instance.workflow.create(object: object, wf_name: wf_name)
77
- end
74
+ # Get the preserved file contents
75
+ # @param [String] object the identifier for the object
76
+ # @param [String] filename the name of the file to retrieve
77
+ # @param [Integer] version the version of the file to retrieve
78
+ # @return [String] the file contents from the SDR
79
+ delegate :preserved_content, to: :files
80
+
81
+ # @param [String] object the identifier for the object
82
+ # @return [Array<String>] the list of filenames in the workspace
83
+ def list_files(object:)
84
+ files.list(object: object)
85
+ end
78
86
 
79
- # Initializes a new workspace
80
- # @param object [String] the pid for the object
81
- # @param source [String] the path to the object
82
- # @raises [Error] if the request is unsuccessful.
83
- # @return nil
84
- def self.initialize_workspace(object:, source:)
85
- instance.workspace.create(object: object, source: source)
86
- end
87
+ # Initializes a new workflow
88
+ # @param object [String] the pid for the object
89
+ # @param wf_name [String] the name of the workflow
90
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
91
+ # @return nil
92
+ def initialize_workflow(object:, wf_name:)
93
+ workflow.create(object: object, wf_name: wf_name)
94
+ end
87
95
 
88
- # Creates a new release tag for the object
89
- # @param object [String] the pid for the object
90
- # @param release [Boolean]
91
- # @param what [String]
92
- # @param to [String]
93
- # @param who [String]
94
- # @return [Boolean] true if successful
95
- def self.create_release_tag(object:, release:, what:, to:, who:)
96
- instance.release_tags.create(object: object, release: release, what: what, to: to, who: who)
96
+ # Initializes a new workspace
97
+ # @param object [String] the pid for the object
98
+ # @param source [String] the path to the object
99
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
100
+ # @return nil
101
+ def initialize_workspace(object:, source:)
102
+ workspace.create(object: object, source: source)
103
+ end
104
+
105
+ # Creates a new release tag for the object
106
+ # @param object [String] the pid for the object
107
+ # @param release [Boolean]
108
+ # @param what [String]
109
+ # @param to [String]
110
+ # @param who [String]
111
+ # @return [Boolean] true if successful
112
+ def create_release_tag(object:, release:, what:, to:, who:)
113
+ release_tags.create(object: object, release: release, what: what, to: to, who: who)
114
+ end
115
+
116
+ # Publish a new object
117
+ # @param object [String] the pid for the object
118
+ # @raise [UnexpectedResponse] when the response is not successful.
119
+ # @return [boolean] true on success
120
+ delegate :publish, to: :objects
97
121
  end
98
122
 
99
- # Publish a new object
123
+ # Gets the current version number for the object
100
124
  # @param object [String] the pid for the object
101
- # @raise [Error] when the response is not successful.
102
- # @return [boolean] true on success
103
- def self.publish(object:)
104
- instance.objects.publish(object: object)
125
+ # @raise [UnexpectedResponse] when the response is not successful.
126
+ # @raise [MalformedResponse] when the response is not parseable.
127
+ # @return [Integer] the current version
128
+ def self.current_version(object:)
129
+ instance.objects.current_version(object: object)
105
130
  end
106
131
 
107
132
  attr_writer :url, :username, :password, :connection
@@ -5,18 +5,39 @@ module Dor
5
5
  class Client
6
6
  # API calls relating to files
7
7
  class Files < VersionedService
8
+ # Get the contents from the workspace
9
+ # @param [String] object the identifier for the object
10
+ # @param [String] filename the name of the file to retrieve
11
+ # @return [String] the file contents from the workspace
8
12
  def retrieve(object:, filename:)
9
13
  resp = connection.get do |req|
10
- req.url "#{version}/objects/#{object}/contents/#{filename}"
14
+ req.url "#{api_version}/objects/#{object}/contents/#{filename}"
11
15
  end
12
16
  return unless resp.success?
13
17
 
14
18
  resp.body
15
19
  end
16
20
 
21
+ # Get the preserved file contents
22
+ # @param [String] object the identifier for the object
23
+ # @param [String] filename the name of the file to retrieve
24
+ # @param [Integer] version the version of the file to retrieve
25
+ # @return [String] the file contents from the SDR
26
+ def preserved_content(object:, filename:, version:)
27
+ resp = connection.get do |req|
28
+ req.url "#{api_version}/sdr/objects/#{object}/content/#{CGI.escape(filename)}?version=#{version}"
29
+ end
30
+ return unless resp.success?
31
+
32
+ resp.body
33
+ end
34
+
35
+ # Get the list of files in the workspace
36
+ # @param [String] object the identifier for the object
37
+ # @return [Array<String>] the list of filenames in the workspace
17
38
  def list(object:)
18
39
  resp = connection.get do |req|
19
- req.url "#{version}/objects/#{object}/contents"
40
+ req.url "#{api_version}/objects/#{object}/contents"
20
41
  end
21
42
  return [] unless resp.success?
22
43
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'nokogiri'
4
+
3
5
  module Dor
4
6
  module Services
5
7
  class Client
@@ -8,29 +10,72 @@ module Dor
8
10
  # Creates a new object in DOR
9
11
  # @return [HashWithIndifferentAccess] the response, which includes a :pid
10
12
  def register(params:)
13
+ json = register_response(params: params)
14
+ JSON.parse(json).with_indifferent_access
15
+ end
16
+
17
+ # Publish a new object
18
+ # @param object [String] the pid for the object
19
+ # @raise [UnexpectedResponse] when the response is not successful.
20
+ # @return [boolean] true on success
21
+ def publish(object:)
11
22
  resp = connection.post do |req|
12
- req.url "#{version}/objects"
23
+ req.url "#{api_version}/objects/#{object}/publish"
24
+ end
25
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
26
+
27
+ true
28
+ end
29
+
30
+ # Gets the current version number for the object
31
+ # @param object [String] the pid for the object
32
+ # @raise [UnexpectedResponse] when the response is not successful.
33
+ # @raise [MalformedResponse] when the response is not parseable.
34
+ # @return [Integer] the current version
35
+ def current_version(object:)
36
+ xml = current_version_response(object: object)
37
+ begin
38
+ doc = Nokogiri::XML xml
39
+ raise if doc.root.name != 'currentVersion'
40
+
41
+ return Integer(doc.text)
42
+ rescue StandardError
43
+ raise MalformedResponse, "Unable to parse XML from current_version API call: #{xml}"
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ # make the registration request to the server
50
+ # @raises [UnexpectedResponse] on an unsuccessful response from the server
51
+ # @returns [String] the raw JSON from the server
52
+ def register_response(params:)
53
+ resp = connection.post do |req|
54
+ req.url "#{api_version}/objects"
13
55
  req.headers['Content-Type'] = 'application/json'
14
56
  # asking the service to return JSON (else it'll be plain text)
15
57
  req.headers['Accept'] = 'application/json'
16
58
  req.body = params.to_json
17
59
  end
18
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
60
+ return resp.body if resp.success?
19
61
 
20
- JSON.parse(resp.body).with_indifferent_access
62
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})"
21
63
  end
22
64
 
23
- # Publish a new object
24
- # @param object [String] the pid for the object
25
- # @raise [Error] when the response is not successful.
26
- # @return [boolean] true on success
27
- def publish(object:)
28
- resp = connection.post do |req|
29
- req.url "#{version}/objects/#{object}/publish"
65
+ # make the request to the server for the currentVersion xml
66
+ # @raises [UnexpectedResponse] on an unsuccessful response from the server
67
+ # @returns [String] the raw xml from the server
68
+ def current_version_response(object:)
69
+ resp = connection.get do |req|
70
+ req.url current_version_path(object: object)
30
71
  end
31
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
72
+ return resp.body if resp.success?
32
73
 
33
- true
74
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body}) for #{object}"
75
+ end
76
+
77
+ def current_version_path(object:)
78
+ "#{api_version}/sdr/objects/#{object}/current_version"
34
79
  end
35
80
  end
36
81
  end
@@ -11,6 +11,7 @@ module Dor
11
11
  # @param what [String]
12
12
  # @param to [String]
13
13
  # @param who [String]
14
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
14
15
  # @return [Boolean] true if successful
15
16
  # rubocop:disable Metrics/MethodLength
16
17
  def create(object:, release:, what:, to:, who:)
@@ -21,11 +22,11 @@ module Dor
21
22
  release: release
22
23
  }
23
24
  resp = connection.post do |req|
24
- req.url "#{version}/objects/#{object}/release_tags"
25
+ req.url "#{api_version}/objects/#{object}/release_tags"
25
26
  req.headers['Content-Type'] = 'application/json'
26
27
  req.body = params.to_json
27
28
  end
28
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
29
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
29
30
 
30
31
  true
31
32
  end
@@ -3,7 +3,7 @@
3
3
  module Dor
4
4
  module Services
5
5
  class Client
6
- VERSION = '0.4.0'
6
+ VERSION = '0.5.0'
7
7
  end
8
8
  end
9
9
  end
@@ -7,12 +7,12 @@ module Dor
7
7
  class VersionedService
8
8
  def initialize(connection:, version:)
9
9
  @connection = connection
10
- @version = version
10
+ @api_version = version
11
11
  end
12
12
 
13
13
  private
14
14
 
15
- attr_reader :connection, :version
15
+ attr_reader :connection, :api_version
16
16
  end
17
17
  end
18
18
  end
@@ -8,13 +8,13 @@ module Dor
8
8
  # Begin a new workflow
9
9
  # @param object [String] the pid for the object
10
10
  # @param wf_name [String] the name of the workflow
11
- # @raises [Error] if the request is unsuccessful.
11
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
12
12
  # @return nil
13
13
  def create(object:, wf_name:)
14
14
  resp = connection.post do |req|
15
- req.url "#{version}/objects/#{object}/apo_workflows/#{wf_name}"
15
+ req.url "#{api_version}/objects/#{object}/apo_workflows/#{wf_name}"
16
16
  end
17
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
17
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
18
18
  end
19
19
  end
20
20
  end
@@ -4,18 +4,18 @@ module Dor
4
4
  module Services
5
5
  class Client
6
6
  # API calls that are about the DOR workspace
7
- class Workspace < VersionedService
7
+ class Workspace < VersionedService
8
8
  # Initializes a new workspace
9
9
  # @param object [String] the pid for the object
10
10
  # @param source [String] the path to the object
11
- # @raises [Error] if the request is unsuccessful.
11
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
12
12
  # @return nil
13
13
  def create(object:, source:)
14
14
  resp = connection.post do |req|
15
- req.url "#{version}/objects/#{object}/initialize_workspace"
15
+ req.url "#{api_version}/objects/#{object}/initialize_workspace"
16
16
  req.params['source'] = source
17
17
  end
18
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
18
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
19
19
  end
20
20
  end
21
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dor-services-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
@@ -45,6 +45,20 @@ dependencies:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0.15'
48
+ - !ruby/object:Gem::Dependency
49
+ name: nokogiri
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.8'
48
62
  - !ruby/object:Gem::Dependency
49
63
  name: bundler
50
64
  requirement: !ruby/object:Gem::Requirement