dor-workflow-service 1.3.3
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.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.travis.yml +7 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +16 -0
- data/Rakefile +13 -0
- data/bin/console +13 -0
- data/dor-workflow-service.gemspec +30 -0
- data/lib/dor-workflow-service.rb +2 -0
- data/lib/dor/services/workflow_service.rb +281 -0
- data/lib/dor/workflow_version.rb +7 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/workflow_service_spec.rb +245 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1d6fc3e584fe89a00011d92d20c3808bdbb7a9fe
|
4
|
+
data.tar.gz: 1f9c905de65222b5b1bcf85faa9a0caeb4b03054
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a93219741feb1dfed55872d75a97c6822debb2781b3b7aedf90daeb03bd28155baca5ec823d223fde63f5ce76aa0684505df5c35f90d750b815a0380b682897e
|
7
|
+
data.tar.gz: 2165204dc1a3b3c14dc9fa8c555e7959a6bcbc134d752bdae29023828fdd97c8fce9ce384b1facdc4c0b4716cd6824271151d2a4e2d774f286c415371a13143f
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
.rvmrc
|
7
|
+
Gemfile.lock
|
8
|
+
InstalledFiles
|
9
|
+
_yardoc
|
10
|
+
coverage
|
11
|
+
doc/
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
.ruby-version
|
20
|
+
.ruby-gemset
|
21
|
+
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Willy Mene
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# dor-workflow-service gem
|
2
|
+
|
3
|
+
Provides Ruby convenience methods to work with the DOR Workflow REST Service. The REST API is defined here:
|
4
|
+
https://consul.stanford.edu/display/DOR/DOR+services#DORservices-initializeworkflow
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
To initialize usage of the service, you need to call Dor::WorkflowService.configure, like in a bootup or startup method, e.g.:
|
9
|
+
|
10
|
+
Dor::WorkflowService.configure('https://test-server.edu/workflow/')
|
11
|
+
|
12
|
+
If you plan to archive workflows, then you need to set the URL to the Dor REST service:
|
13
|
+
|
14
|
+
Dor::WorkflowService.configure('https://test-server.edu/workflow/', :dor_services_url => 'https://sul-lyberservices-dev.stanford.edu/dor')
|
15
|
+
|
16
|
+
There's no need to call Dor::WorkflowService.configure if using the dor-services gem and using the Dor::Config object. The latest versions of dor-services will configure the workflow service for you.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
task :default => [:spec]
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
9
|
+
spec.pattern = 'spec/**/*_spec.rb', 'test/**/*.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'yard'
|
13
|
+
YARD::Rake::YardocTask.new
|
data/bin/console
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'irb'
|
5
|
+
|
6
|
+
project_root = File.expand_path(File.dirname(__FILE__) + '/..')
|
7
|
+
|
8
|
+
# Load config for current environment.
|
9
|
+
$LOAD_PATH.unshift(project_root + '/lib')
|
10
|
+
|
11
|
+
require 'dor-workflow-service'
|
12
|
+
|
13
|
+
IRB.start
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dor/workflow_version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "dor-workflow-service"
|
8
|
+
gem.version = Dor::Workflow::Service::VERSION
|
9
|
+
gem.authors = ["Willy Mene"]
|
10
|
+
gem.email = ["wmene@stanford.edu"]
|
11
|
+
gem.description = "Enables Ruby manipulation of the DOR Workflow Service via its REST API"
|
12
|
+
gem.summary = "Provides convenience methods to work with the DOR Workflow Service"
|
13
|
+
gem.homepage = "https://consul.stanford.edu/display/DOR/DOR+services#DORservices-initializeworkflow"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency "activesupport"
|
21
|
+
gem.add_dependency "nokogiri"
|
22
|
+
gem.add_dependency "rest-client"
|
23
|
+
gem.add_dependency "confstruct"
|
24
|
+
|
25
|
+
gem.add_development_dependency "rake"
|
26
|
+
gem.add_development_dependency "rspec"
|
27
|
+
gem.add_development_dependency "yard"
|
28
|
+
gem.add_development_dependency "redcarpet"
|
29
|
+
gem.add_development_dependency "equivalent-xml"
|
30
|
+
end
|
@@ -0,0 +1,281 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module Dor
|
6
|
+
|
7
|
+
# Methods to create and update workflow
|
8
|
+
module WorkflowService
|
9
|
+
class << self
|
10
|
+
|
11
|
+
@@resource = nil
|
12
|
+
@@dor_services_url = nil
|
13
|
+
|
14
|
+
# Creates a workflow for a given object in the repository. If this particular workflow for this objects exists,
|
15
|
+
# it will replace the old workflow with wf_xml passed to this method. You have the option of creating a datastream or not.
|
16
|
+
# Returns true on success. Caller must handle any exceptions
|
17
|
+
#
|
18
|
+
# == Parameters
|
19
|
+
# @param [String] repo The repository the object resides in. The service recoginzes "dor" and "sdr" at the moment
|
20
|
+
# @param [String] druid The id of the object
|
21
|
+
# @param [String] workflow_name The name of the workflow you want to create
|
22
|
+
# @param [String] wf_xml The xml that represents the workflow
|
23
|
+
# @param [Hash] opts optional params
|
24
|
+
# @option opts [Boolean] :create_ds if true, a workflow datastream will be created in Fedora. Set to false if you do not want a datastream to be created
|
25
|
+
# If you do not pass in an <b>opts</b> Hash, then :create_ds is set to true by default
|
26
|
+
# @option opts [Integer] :priority adds priority to all process elements in the wf_xml workflow xml
|
27
|
+
#
|
28
|
+
def create_workflow(repo, druid, workflow_name, wf_xml, opts = {:create_ds => true})
|
29
|
+
xml = wf_xml
|
30
|
+
xml = add_priority_to_workflow_xml(opts[:priority], wf_xml) if(opts[:priority])
|
31
|
+
workflow_resource["#{repo}/objects/#{druid}/workflows/#{workflow_name}"].put(xml, :content_type => 'application/xml',
|
32
|
+
:params => {'create-ds' => opts[:create_ds] })
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
|
36
|
+
# Adds priority attributes to each process of workflow xml
|
37
|
+
#
|
38
|
+
# @param [Integer] priority value to add to each process element
|
39
|
+
# @param [String] wf_xml the workflow xml
|
40
|
+
# @return [String] wf_xml with priority attributes
|
41
|
+
def add_priority_to_workflow_xml(priority, wf_xml)
|
42
|
+
return wf_xml if(priority.to_i == 0)
|
43
|
+
doc = Nokogiri::XML(wf_xml)
|
44
|
+
doc.xpath('/workflow/process').each { |proc| proc['priority'] = priority }
|
45
|
+
doc.to_xml
|
46
|
+
end
|
47
|
+
|
48
|
+
# Updates the status of one step in a workflow.
|
49
|
+
# Returns true on success. Caller must handle any exceptions
|
50
|
+
#
|
51
|
+
# @param [String] repo The repository the object resides in. The service recoginzes "dor" and "sdr" at the moment
|
52
|
+
# @param [String] druid The id of the object
|
53
|
+
# @param [String] workflow The name of the workflow
|
54
|
+
# @param [String] status The status that you want to set. Typical statuses are 'waiting', 'completed', 'error', but could be any string
|
55
|
+
# @param [Hash] opts optional values for the workflow step
|
56
|
+
# @option opts [Float] :elapsed The number of seconds it took to complete this step. Can have a decimal. Is set to 0 if not passed in.
|
57
|
+
# @option opts [String] :lifecycle Bookeeping label for this particular workflow step. Examples are: 'registered', 'shelved'
|
58
|
+
# @option opts [String] :note Any kind of string annotation that you want to attach to the workflow
|
59
|
+
# @option opts [Integer] :priority Processing priority, 0-100, 100 being the highest priority. Workflow queues are returned in order of highest to lowest priority. Stored in the system as 0 by default
|
60
|
+
# == Http Call
|
61
|
+
# The method does an HTTP PUT to the URL defined in Dor::WF_URI. As an example:
|
62
|
+
# PUT "/dor/objects/pid:123/workflows/GoogleScannedWF/convert"
|
63
|
+
# <process name=\"convert\" status=\"completed\" />"
|
64
|
+
def update_workflow_status(repo, druid, workflow, process, status, opts = {})
|
65
|
+
opts = {:elapsed => 0, :lifecycle => nil, :note => nil}.merge!(opts)
|
66
|
+
opts[:elapsed] = opts[:elapsed].to_s
|
67
|
+
xml = create_process_xml({:name => process, :status => status}.merge!(opts))
|
68
|
+
workflow_resource["#{repo}/objects/#{druid}/workflows/#{workflow}/#{process}"].put(xml, :content_type => 'application/xml')
|
69
|
+
return true
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Retrieves the process status of the given workflow for the given object identifier
|
74
|
+
#
|
75
|
+
def get_workflow_status(repo, druid, workflow, process)
|
76
|
+
workflow_md = workflow_resource["#{repo}/objects/#{druid}/workflows/#{workflow}"].get
|
77
|
+
doc = Nokogiri::XML(workflow_md)
|
78
|
+
raise Exception.new("Unable to parse response:\n#{workflow_md}") if(doc.root.nil?)
|
79
|
+
|
80
|
+
status = doc.root.at_xpath("//process[@name='#{process}']/@status")
|
81
|
+
if status
|
82
|
+
status=status.content
|
83
|
+
end
|
84
|
+
return status
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_workflow_xml(repo, druid, workflow)
|
88
|
+
workflow_resource["#{repo}/objects/#{druid}/workflows/#{workflow}"].get
|
89
|
+
end
|
90
|
+
|
91
|
+
# Get workflow names into an array for given PID
|
92
|
+
# This method only works when this gem is used in a project that is configured to connect to DOR
|
93
|
+
#
|
94
|
+
# @param [string] pid of druid
|
95
|
+
#
|
96
|
+
# @return [array] list of worklows
|
97
|
+
# e.g.
|
98
|
+
# Dor::WorkflowService.get_workflows('druid:sr100hp0609')
|
99
|
+
# => ["accessionWF", "assemblyWF", "disseminationWF"]
|
100
|
+
def get_workflows(pid)
|
101
|
+
xml_doc=Nokogiri::XML(get_workflow_xml('dor',pid,''))
|
102
|
+
return xml_doc.xpath('//workflow').collect {|workflow| workflow['id']}
|
103
|
+
end
|
104
|
+
|
105
|
+
# Updates the status of one step in a workflow to error.
|
106
|
+
# Returns true on success. Caller must handle any exceptions
|
107
|
+
#
|
108
|
+
# @param [String] repo The repository the object resides in. The service recoginzes "dor" and "sdr" at the moment
|
109
|
+
# @param [String] druid The id of the object
|
110
|
+
# @param [String] workflow The name of the workflow
|
111
|
+
# @param [String] error_msg The error message. Ideally, this is a brief message describing the error
|
112
|
+
# @param [Hash] opts optional values for the workflow step
|
113
|
+
# @option opts [String] :error_txt A slot to hold more information about the error, like a full stacktrace
|
114
|
+
#
|
115
|
+
# == Http Call
|
116
|
+
# The method does an HTTP PUT to the URL defined in Dor::WF_URI. As an example:
|
117
|
+
# PUT "/dor/objects/pid:123/workflows/GoogleScannedWF/convert"
|
118
|
+
# <process name=\"convert\" status=\"error\" />"
|
119
|
+
def update_workflow_error_status(repo, druid, workflow, process, error_msg, opts = {})
|
120
|
+
opts = {:error_txt => nil}.merge!(opts)
|
121
|
+
xml = create_process_xml({:name => process, :status => 'error', :errorMessage => error_msg}.merge!(opts))
|
122
|
+
workflow_resource["#{repo}/objects/#{druid}/workflows/#{workflow}/#{process}"].put(xml, :content_type => 'application/xml')
|
123
|
+
return true
|
124
|
+
end
|
125
|
+
|
126
|
+
# Deletes a workflow from a particular repository and druid
|
127
|
+
# @param [String] repo The repository the object resides in. The service recoginzes "dor" and "sdr" at the moment
|
128
|
+
# @param [String] druid The id of the object to delete the workflow from
|
129
|
+
# @param [String] workflow The name of the workflow to be deleted
|
130
|
+
def delete_workflow(repo, druid, workflow)
|
131
|
+
workflow_resource["#{repo}/objects/#{druid}/workflows/#{workflow}"].delete
|
132
|
+
return true
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns the Date for a requested milestone from workflow lifecycle
|
136
|
+
# @param [String] repo epository name
|
137
|
+
# @param [String] druid object id
|
138
|
+
# @param [String] milestone name of the milestone being queried for
|
139
|
+
# @return [Time] when the milestone was achieved. Returns nil if the milestone does not exist
|
140
|
+
# @example An example lifecycle xml from the workflow service.
|
141
|
+
# <lifecycle objectId="druid:ct011cv6501">
|
142
|
+
# <milestone date="2010-04-27T11:34:17-0700">registered</milestone>
|
143
|
+
# <milestone date="2010-04-29T10:12:51-0700">inprocess</milestone>
|
144
|
+
# <milestone date="2010-06-15T16:08:58-0700">released</milestone>
|
145
|
+
# </lifecycle>
|
146
|
+
def get_lifecycle(repo, druid, milestone)
|
147
|
+
doc = self.query_lifecycle(repo, druid)
|
148
|
+
milestone = doc.at_xpath("//lifecycle/milestone[text() = '#{milestone}']")
|
149
|
+
if(milestone)
|
150
|
+
return Time.parse(milestone['date'])
|
151
|
+
end
|
152
|
+
|
153
|
+
nil
|
154
|
+
end
|
155
|
+
|
156
|
+
# Returns the Date for a requested milestone ONLY FROM THE ACTIVE workflow table
|
157
|
+
# @param [String] repo epository name
|
158
|
+
# @param [String] druid object id
|
159
|
+
# @param [String] milestone name of the milestone being queried for
|
160
|
+
# @return [Time] when the milestone was achieved. Returns nil if the milestone does not exist
|
161
|
+
# @example An example lifecycle xml from the workflow service.
|
162
|
+
# <lifecycle objectId="druid:ct011cv6501">
|
163
|
+
# <milestone date="2010-04-27T11:34:17-0700">registered</milestone>
|
164
|
+
# <milestone date="2010-04-29T10:12:51-0700">inprocess</milestone>
|
165
|
+
# <milestone date="2010-06-15T16:08:58-0700">released</milestone>
|
166
|
+
# </lifecycle>
|
167
|
+
def get_active_lifecycle(repo, druid, milestone)
|
168
|
+
doc = self.query_lifecycle(repo, druid, true)
|
169
|
+
milestone = doc.at_xpath("//lifecycle/milestone[text() = '#{milestone}']")
|
170
|
+
if(milestone)
|
171
|
+
return Time.parse(milestone['date'])
|
172
|
+
end
|
173
|
+
|
174
|
+
nil
|
175
|
+
end
|
176
|
+
|
177
|
+
def get_milestones(repo, druid)
|
178
|
+
doc = self.query_lifecycle(repo, druid)
|
179
|
+
doc.xpath("//lifecycle/milestone").collect do |node|
|
180
|
+
{ :milestone => node.text, :at => Time.parse(node['date']), :version => node['version'] }
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def qualify_step(default_repository, default_workflow, step)
|
185
|
+
current = step.split(/:/,3)
|
186
|
+
current.unshift(default_workflow) if current.length < 3
|
187
|
+
current.unshift(default_repository) if current.length < 3
|
188
|
+
current.join(':')
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
# Returns a list of druids from the WorkflowService that meet the criteria of the passed in completed and waiting params
|
193
|
+
#
|
194
|
+
# @param [Array<String>, String] completed An array or single String of the completed steps, should use the qualified format:
|
195
|
+
# repository:workflow:step-name
|
196
|
+
# @param [String] waiting name of the waiting step
|
197
|
+
# @param [String] repository default repository to use if it isn't passed in the qualified-step-name
|
198
|
+
# @param [String] workflow default workflow to use if it isn't passed in the qualified-step-name
|
199
|
+
def get_objects_for_workstep completed, waiting, repository=nil, workflow=nil
|
200
|
+
result = nil
|
201
|
+
if(completed)
|
202
|
+
uri_string = "workflow_queue?waiting=#{qualify_step(repository,workflow,waiting)}"
|
203
|
+
Array(completed).each do |step|
|
204
|
+
uri_string << "&completed=#{qualify_step(repository,workflow,step)}"
|
205
|
+
end
|
206
|
+
else
|
207
|
+
uri_string = "workflow_queue?waiting=#{qualify_step(repository,workflow,waiting)}"
|
208
|
+
end
|
209
|
+
workflow_resource.options[:timeout] = 5 * 60 unless(workflow_resource.options.include?(:timeout))
|
210
|
+
resp = workflow_resource[uri_string].get
|
211
|
+
result = Nokogiri::XML(resp).xpath('//object[@id]').collect { |node| node['id'] }
|
212
|
+
|
213
|
+
result || []
|
214
|
+
end
|
215
|
+
|
216
|
+
# Get a list of druids that have errored out in a particular workflow and step
|
217
|
+
#
|
218
|
+
# @param [string] workflow name
|
219
|
+
# @param [string] step name
|
220
|
+
# @param [string] repository -- optional, default=dor
|
221
|
+
#
|
222
|
+
# @return [hash] hash of results, with key has a druid, and value as the error message
|
223
|
+
# e.g.
|
224
|
+
# Dor::WorkflowService.get_errored_objects_for_workstep('accessionWF','content-metadata')
|
225
|
+
# => {"druid:qd556jq0580"=>"druid:qd556jq0580 - Item error; caused by #<Rubydora::FedoraInvalidRequest: Error modifying datastream contentMetadata for druid:qd556jq0580. See logger for details>"}
|
226
|
+
def get_errored_objects_for_workstep workflow, step, repository='dor'
|
227
|
+
result = {}
|
228
|
+
uri_string = "workflow_queue?repository=#{repository}&workflow=#{workflow}&error=#{step}"
|
229
|
+
resp = workflow_resource[uri_string].get
|
230
|
+
objs = Nokogiri::XML(resp).xpath('//object').collect do |node|
|
231
|
+
result.merge!(node['id'] => node['errorMessage'])
|
232
|
+
end
|
233
|
+
result
|
234
|
+
end
|
235
|
+
|
236
|
+
def create_process_xml(params)
|
237
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
238
|
+
attrs = params.reject { |k,v| v.nil? }
|
239
|
+
xml.process(attrs)
|
240
|
+
end
|
241
|
+
return builder.to_xml
|
242
|
+
end
|
243
|
+
|
244
|
+
def query_lifecycle(repo, druid, active_only = false)
|
245
|
+
req = "#{repo}/objects/#{druid}/lifecycle"
|
246
|
+
req << '?active-only=true' if active_only
|
247
|
+
lifecycle_xml = workflow_resource[req].get
|
248
|
+
return Nokogiri::XML(lifecycle_xml)
|
249
|
+
end
|
250
|
+
|
251
|
+
def archive_workflow(repo, druid, wf_name, version_num=nil)
|
252
|
+
raise "Please call Dor::WorkflowService.configure(workflow_service_url, :dor_services_url => DOR_SERVIES_URL) once before archiving workflow" if(@@dor_services_url.nil?)
|
253
|
+
|
254
|
+
dor_services = RestClient::Resource.new(@@dor_services_url)
|
255
|
+
url = "/v1/objects/#{druid}/workflows/#{wf_name}/archive"
|
256
|
+
url << "/#{version_num}" if(version_num)
|
257
|
+
dor_services[url].post ''
|
258
|
+
end
|
259
|
+
|
260
|
+
def workflow_resource
|
261
|
+
raise "Please call Dor::WorkflowService.configure(url) once before calling any WorkflowService methods" if(@@resource.nil?)
|
262
|
+
@@resource
|
263
|
+
end
|
264
|
+
|
265
|
+
# @param [String] url points to the workflow service
|
266
|
+
# @param [Hash] opts optional params
|
267
|
+
# @option opts [String] :client_cert_file path to an SSL client certificate
|
268
|
+
# @option opts [String] :client_key_file path to an SSL key file
|
269
|
+
# @option opts [String] :client_key_pass password for the key file
|
270
|
+
# @option opts [String] :dor_services_uri uri to the DOR REST service
|
271
|
+
def configure(url, opts={})
|
272
|
+
params = {}
|
273
|
+
@@dor_services_url = opts[:dor_services_url] if opts[:dor_services_url]
|
274
|
+
#params[:ssl_client_cert] = OpenSSL::X509::Certificate.new(File.read(opts[:client_cert_file])) if opts[:client_cert_file]
|
275
|
+
#params[:ssl_client_key] = OpenSSL::PKey::RSA.new(File.read(opts[:client_key_file]), opts[:client_key_pass]) if opts[:client_key_file]
|
276
|
+
@@resource = RestClient::Resource.new(url, params)
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'dor-workflow-service'
|
3
|
+
require 'equivalent-xml'
|
4
|
+
|
5
|
+
describe Dor::WorkflowService do
|
6
|
+
|
7
|
+
let(:wf_xml) { <<-EOXML
|
8
|
+
<workflow id="etdSubmitWF">
|
9
|
+
<process name="register-object" status="completed" attempts="1" />
|
10
|
+
<process name="submit" status="waiting" />
|
11
|
+
<process name="reader-approval" status="waiting" />
|
12
|
+
<process name="registrar-approval" status="waiting" />
|
13
|
+
<process name="start-accession" status="waiting" />
|
14
|
+
</workflow>
|
15
|
+
EOXML
|
16
|
+
}
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
@repo = 'dor'
|
20
|
+
@druid = 'druid:123'
|
21
|
+
|
22
|
+
@mock_logger = double('logger').as_null_object
|
23
|
+
Rails.stub(:logger).and_return(@mock_logger)
|
24
|
+
|
25
|
+
@mock_resource = double('mock_rest_client_resource')
|
26
|
+
@mock_resource.stub(:[]).and_return(@mock_resource)
|
27
|
+
@mock_resource.stub(:options).and_return( {} )
|
28
|
+
RestClient::Resource.stub(:new).and_return(@mock_resource)
|
29
|
+
Dor::WorkflowService.configure 'https://dortest.stanford.edu/workflow'
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#create_workflow" do
|
33
|
+
it "should pass workflow xml to the DOR workflow service and return the URL to the workflow" do
|
34
|
+
@mock_resource.should_receive(:put).with(wf_xml, anything()).and_return('')
|
35
|
+
Dor::WorkflowService.create_workflow(@repo, @druid, 'etdSubmitWF', wf_xml)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should log an error and return false if the PUT to the DOR workflow service throws an exception" do
|
39
|
+
ex = Exception.new("exception thrown")
|
40
|
+
@mock_resource.should_receive(:put).and_raise(ex)
|
41
|
+
lambda{ Dor::WorkflowService.create_workflow(@repo, @druid, 'etdSubmitWF', wf_xml) }.should raise_error(Exception, "exception thrown")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "sets the create-ds param to the value of the passed in options hash" do
|
45
|
+
@mock_resource.should_receive(:put).with(wf_xml, :content_type => 'application/xml',
|
46
|
+
:params => {'create-ds' => false}).and_return('')
|
47
|
+
Dor::WorkflowService.create_workflow(@repo, @druid, 'etdSubmitWF', wf_xml, :create_ds => false)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "adds priority attributes to all steps if passed in as an option" do
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#add_priority_to_workflow_xml" do
|
57
|
+
|
58
|
+
it "adds priority attributes to all process elements" do
|
59
|
+
expected = <<-XML
|
60
|
+
<workflow id="etdSubmitWF">
|
61
|
+
<process name="register-object" status="completed" attempts="1" priority="50"/>
|
62
|
+
<process name="submit" status="waiting" priority="50"/>
|
63
|
+
<process name="reader-approval" status="waiting" priority="50"/>
|
64
|
+
<process name="registrar-approval" status="waiting" priority="50"/>
|
65
|
+
<process name="start-accession" status="waiting" priority="50"/>
|
66
|
+
</workflow>
|
67
|
+
XML
|
68
|
+
|
69
|
+
Dor::WorkflowService.add_priority_to_workflow_xml(50, wf_xml).should be_equivalent_to(expected)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#update_workflow_status" do
|
74
|
+
before(:each) do
|
75
|
+
@xml_re = /name="reader-approval"/
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should update workflow status and return true if successful" do
|
79
|
+
@mock_resource.should_receive(:put).with(@xml_re, { :content_type => 'application/xml' }).and_return('')
|
80
|
+
Dor::WorkflowService.update_workflow_status(@repo, @druid, "etdSubmitWF", "reader-approval", "completed", :version => 2, :note => 'annotation', :priority => 34).should be_true
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return false if the PUT to the DOR workflow service throws an exception" do
|
84
|
+
ex = Exception.new("exception thrown")
|
85
|
+
@mock_resource.should_receive(:put).with(@xml_re, { :content_type => 'application/xml' }).and_raise(ex)
|
86
|
+
lambda{ Dor::WorkflowService.update_workflow_status(@repo, @druid, "etdSubmitWF", "reader-approval", "completed") }.should raise_error(Exception, "exception thrown")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#update_workflow_error_status" do
|
91
|
+
it "should update workflow status to error and return true if successful" do
|
92
|
+
@mock_resource.should_receive(:put).with(/status="error"/, { :content_type => 'application/xml' }).and_return('')
|
93
|
+
Dor::WorkflowService.update_workflow_error_status(@repo, @druid, "etdSubmitWF", "reader-approval", "Some exception", :error_txt =>"The optional stacktrace")
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should return false if the PUT to the DOR workflow service throws an exception" do
|
97
|
+
ex = Exception.new("exception thrown")
|
98
|
+
@mock_resource.should_receive(:put).with(/status="completed"/, { :content_type => 'application/xml' }).and_raise(ex)
|
99
|
+
lambda{ Dor::WorkflowService.update_workflow_status(@repo, @druid, "etdSubmitWF", "reader-approval", "completed") }.should raise_error(Exception, "exception thrown")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#get_workflow_status" do
|
104
|
+
it "parses workflow xml and returns status as a string" do
|
105
|
+
@mock_resource.should_receive(:get).and_return('<process name="registrar-approval" status="completed" />')
|
106
|
+
Dor::WorkflowService.get_workflow_status('dor', 'druid:123', 'etdSubmitWF', 'registrar-approval').should == 'completed'
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should throw an exception if it fails for any reason" do
|
110
|
+
ex = Exception.new("exception thrown")
|
111
|
+
@mock_resource.should_receive(:get).and_raise(ex)
|
112
|
+
|
113
|
+
lambda{ Dor::WorkflowService.get_workflow_status('dor', 'druid:123', 'etdSubmitWF', 'registrar-approval') }.should raise_error(Exception, "exception thrown")
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should throw an exception if it cannot parse the response" do
|
117
|
+
@mock_resource.should_receive(:get).and_return('something not xml')
|
118
|
+
lambda{ Dor::WorkflowService.get_workflow_status('dor', 'druid:123', 'etdSubmitWF', 'registrar-approval') }.should raise_error(Exception, "Unable to parse response:\nsomething not xml")
|
119
|
+
end
|
120
|
+
it "should return nil if the workflow/process combination doesnt exist" do
|
121
|
+
@mock_resource.should_receive(:get).and_return('<process name="registrar-approval" status="completed" />')
|
122
|
+
Dor::WorkflowService.get_workflow_status('dor', 'druid:123', 'accessionWF', 'publish').should == nil
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#get_workflow_xml" do
|
128
|
+
it "returns the xml for a given repository, druid, and workflow" do
|
129
|
+
xml = '<workflow id="etdSubmitWF"><process name="registrar-approval" status="completed" /></workflow>'
|
130
|
+
@mock_resource.should_receive(:get).and_return(xml)
|
131
|
+
Dor::WorkflowService.get_workflow_xml('dor', 'druid:123', 'etdSubmitWF').should == xml
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "#get_lifecycle" do
|
136
|
+
it "returns a Time object reprenting when the milestone was reached" do
|
137
|
+
xml = <<-EOXML
|
138
|
+
<lifecycle objectId="druid:ct011cv6501">
|
139
|
+
<milestone date="2010-04-27T11:34:17-0700">registered</milestone>
|
140
|
+
<milestone date="2010-04-29T10:12:51-0700">inprocess</milestone>
|
141
|
+
<milestone date="2010-06-15T16:08:58-0700">released</milestone>
|
142
|
+
</lifecycle>
|
143
|
+
EOXML
|
144
|
+
@mock_resource.should_receive(:get).and_return(xml)
|
145
|
+
Dor::WorkflowService.get_lifecycle('dor', 'druid:123', 'released').beginning_of_day.should == Time.parse('2010-06-15T16:08:58-0700').beginning_of_day
|
146
|
+
end
|
147
|
+
|
148
|
+
it "returns nil if the milestone hasn't been reached yet" do
|
149
|
+
@mock_resource.should_receive(:get).and_return('<lifecycle/>')
|
150
|
+
Dor::WorkflowService.get_lifecycle('dor', 'druid:abc', 'inprocess').should be_nil
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "#get_objects_for_workstep" do
|
156
|
+
before :each do
|
157
|
+
@repository = "dor"
|
158
|
+
@workflow = "googleScannedBookWF"
|
159
|
+
@completed = "google-download"
|
160
|
+
@waiting = "process-content"
|
161
|
+
end
|
162
|
+
|
163
|
+
context "a query with one step completed and one waiting" do
|
164
|
+
it "creates the URI string with only the one completed step" do
|
165
|
+
@mock_resource.should_receive(:[]).with("workflow_queue?waiting=#{@repository}:#{@workflow}:#{@waiting}&completed=#{@repository}:#{@workflow}:#{@completed}")
|
166
|
+
@mock_resource.should_receive(:get).and_return(%{<objects count="1"><object id="druid:ab123de4567"/><object id="druid:ab123de9012"/></objects>})
|
167
|
+
Dor::WorkflowService.get_objects_for_workstep(@completed, @waiting, @repository, @workflow).should == ['druid:ab123de4567','druid:ab123de9012']
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "a query with TWO steps completed and one waiting" do
|
172
|
+
it "creates the URI string with the two completed steps correctly" do
|
173
|
+
second_completed="google-convert"
|
174
|
+
@mock_resource.should_receive(:[]).with("workflow_queue?waiting=#{@repository}:#{@workflow}:#{@waiting}&completed=#{@repository}:#{@workflow}:#{@completed}&completed=#{@repository}:#{@workflow}:#{second_completed}")
|
175
|
+
@mock_resource.should_receive(:get).and_return(%{<objects count="1"><object id="druid:ab123de4567"/><object id="druid:ab123de9012"/></objects>})
|
176
|
+
Dor::WorkflowService.get_objects_for_workstep([@completed,second_completed], @waiting, @repository, @workflow).should == ['druid:ab123de4567','druid:ab123de9012']
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "a query using qualified workflow names for completed and waiting" do
|
181
|
+
it "creates the URI string with the two completed steps across repositories correctly" do
|
182
|
+
qualified_waiting = "#{@repository}:#{@workflow}:#{@waiting}"
|
183
|
+
qualified_completed = "#{@repository}:#{@workflow}:#{@completed}"
|
184
|
+
repo2 = "sdr"
|
185
|
+
workflow2 = "sdrIngestWF"
|
186
|
+
completed2="complete-deposit"
|
187
|
+
completed3="ingest-transfer"
|
188
|
+
qualified_completed2 = "#{repo2}:#{workflow2}:#{completed2}"
|
189
|
+
qualified_completed3 = "#{repo2}:#{workflow2}:#{completed3}"
|
190
|
+
@mock_resource.should_receive(:[]).with("workflow_queue?waiting=#{qualified_waiting}&completed=#{qualified_completed}&completed=#{qualified_completed2}&completed=#{qualified_completed3}")
|
191
|
+
@mock_resource.should_receive(:get).and_return(%{<objects count="2"><object id="druid:ab123de4567" priority="0"/><object id="druid:ab123de9012" priority="0"/></objects>})
|
192
|
+
Dor::WorkflowService.get_objects_for_workstep([qualified_completed, qualified_completed2, qualified_completed3], qualified_waiting).should == ['druid:ab123de4567', 'druid:ab123de9012']
|
193
|
+
end
|
194
|
+
|
195
|
+
it "creates the URI string with only one completed step passed in as a String" do
|
196
|
+
qualified_waiting = "#{@repository}:#{@workflow}:#{@waiting}"
|
197
|
+
qualified_completed = "#{@repository}:#{@workflow}:#{@completed}"
|
198
|
+
repo2 = "sdr"
|
199
|
+
|
200
|
+
@mock_resource.should_receive(:[]).with("workflow_queue?waiting=#{qualified_waiting}&completed=#{qualified_completed}")
|
201
|
+
@mock_resource.should_receive(:get).and_return(%{<objects count="1"><object id="druid:ab123de4567"/></objects>})
|
202
|
+
Dor::WorkflowService.get_objects_for_workstep(qualified_completed, qualified_waiting).should == ['druid:ab123de4567']
|
203
|
+
end
|
204
|
+
|
205
|
+
it "creates the URI string without any completed steps, only waiting" do
|
206
|
+
qualified_waiting = "#{@repository}:#{@workflow}:#{@waiting}"
|
207
|
+
|
208
|
+
@mock_resource.should_receive(:[]).with("workflow_queue?waiting=#{qualified_waiting}")
|
209
|
+
@mock_resource.should_receive(:get).and_return(%{<objects count="1"><object id="druid:ab123de4567"/></objects>})
|
210
|
+
Dor::WorkflowService.get_objects_for_workstep(nil, qualified_waiting).should == ['druid:ab123de4567']
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context "get empty workflow queue" do
|
216
|
+
it "returns an empty list if it encounters an empty workflow queue" do
|
217
|
+
repository = "dor"
|
218
|
+
workflow = "googleScannedBookWF"
|
219
|
+
completed = "google-download"
|
220
|
+
waiting = "process-content"
|
221
|
+
@mock_resource.should_receive(:[]).with("workflow_queue?waiting=#{repository}:#{workflow}:#{waiting}&completed=#{repository}:#{workflow}:#{completed}")
|
222
|
+
@mock_resource.should_receive(:get).and_return(%{<objects count="0"/>})
|
223
|
+
Dor::WorkflowService.get_objects_for_workstep(completed, waiting, repository, workflow).should == []
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
describe "#delete_workflow" do
|
228
|
+
it "sends a delete request to the workflow service" do
|
229
|
+
@mock_resource.should_receive(:[]).with("#{@repo}/objects/#{@druid}/workflows/accessionWF")
|
230
|
+
@mock_resource.should_receive(:delete)
|
231
|
+
Dor::WorkflowService.delete_workflow(@repo, @druid, 'accessionWF')
|
232
|
+
end
|
233
|
+
end
|
234
|
+
describe 'get_milestones' do
|
235
|
+
it 'should include the version in with the milestones' do
|
236
|
+
xml='<?xml version="1.0" encoding="UTF-8"?><lifecycle objectId="druid:gv054hp4128"><milestone date="2012-01-26T21:06:54-0800" version="2">published</milestone></lifecycle>'
|
237
|
+
xml=Nokogiri::XML(xml)
|
238
|
+
Dor::WorkflowService.stub(:query_lifecycle).and_return(xml)
|
239
|
+
milestones=Dor::WorkflowService.get_milestones(@repo, @druid)
|
240
|
+
milestones.first[:milestone].should == "published"
|
241
|
+
milestones.first[:version].should == "2"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
metadata
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dor-workflow-service
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.3.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Willy Mene
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rest-client
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: confstruct
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: redcarpet
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: equivalent-xml
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Enables Ruby manipulation of the DOR Workflow Service via its REST API
|
140
|
+
email:
|
141
|
+
- wmene@stanford.edu
|
142
|
+
executables:
|
143
|
+
- console
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- .gitignore
|
148
|
+
- .travis.yml
|
149
|
+
- Gemfile
|
150
|
+
- LICENSE.txt
|
151
|
+
- README.md
|
152
|
+
- Rakefile
|
153
|
+
- bin/console
|
154
|
+
- dor-workflow-service.gemspec
|
155
|
+
- lib/dor-workflow-service.rb
|
156
|
+
- lib/dor/services/workflow_service.rb
|
157
|
+
- lib/dor/workflow_version.rb
|
158
|
+
- spec/spec_helper.rb
|
159
|
+
- spec/workflow_service_spec.rb
|
160
|
+
homepage: https://consul.stanford.edu/display/DOR/DOR+services#DORservices-initializeworkflow
|
161
|
+
licenses: []
|
162
|
+
metadata: {}
|
163
|
+
post_install_message:
|
164
|
+
rdoc_options: []
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - '>='
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - '>='
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
requirements: []
|
178
|
+
rubyforge_project:
|
179
|
+
rubygems_version: 2.0.3
|
180
|
+
signing_key:
|
181
|
+
specification_version: 4
|
182
|
+
summary: Provides convenience methods to work with the DOR Workflow Service
|
183
|
+
test_files:
|
184
|
+
- spec/spec_helper.rb
|
185
|
+
- spec/workflow_service_spec.rb
|
186
|
+
has_rdoc:
|