collectionspace-client 0.3.0 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CollectionSpace
2
4
  # Helper methods for client requests
3
5
  module Helpers
6
+ # add / update batch job
7
+ def add_batch_job(name, template, data = {}, params = { pgSz: 100 })
8
+ payload = Template.process(template, data)
9
+ response = get('batch', { query: params })
10
+ create_or_update(response, 'batch', 'name', name, payload)
11
+ end
12
+
13
+ # add / update reports
14
+ def add_report(data = {}, params = { pgSz: 100 })
15
+ payload = Template.process('report', data)
16
+ response = get('reports', { query: params })
17
+ create_or_update(response, 'reports', 'name', data[:name], payload)
18
+ end
19
+
4
20
  # get ALL records at path by paging through record set
5
21
  def all(path, options = {})
6
22
  list_type, list_item = get_list_types(path)
@@ -9,9 +25,7 @@ module CollectionSpace
9
25
 
10
26
  Enumerator::Lazy.new(0...iterations) do |yielder, i|
11
27
  response = request('GET', path, options.merge(query: { pgNum: i }))
12
- unless response.result.success?
13
- raise CollectionSpace::RequestError, response.result.body
14
- end
28
+ raise CollectionSpace::RequestError, response.result.body unless response.result.success?
15
29
 
16
30
  items_in_page = response.parsed[list_type].fetch('itemsInPage', 0).to_i
17
31
  list_items = items_in_page.positive? ? response.parsed[list_type][list_item] : []
@@ -24,24 +38,131 @@ module CollectionSpace
24
38
  def count(path)
25
39
  list_type, = get_list_types(path)
26
40
  response = request('GET', path, query: { pgNum: 0, pgSz: 1 })
27
- response.parsed[list_type]['totalItems'].to_i if response.result.success?
41
+ raise CollectionSpace::RequestError, response.result.body unless response.result.success?
42
+
43
+ response.parsed[list_type]['totalItems'].to_i
44
+ end
45
+
46
+ # get the tenant domain from a system required top level authority (person)
47
+ def domain
48
+ path = 'personauthorities'
49
+ response = request('GET', path, query: { pgNum: 0, pgSz: 1 })
50
+ raise CollectionSpace::RequestError, response.result.body unless response.result.success?
51
+
52
+ refname = response.parsed.dig(*get_list_types(path), 'refName')
53
+ CollectionSpace::RefName.parse(refname)[:domain]
54
+ end
55
+
56
+ # find procedure or object by type and id
57
+ # find authority/vocab term by type, subtype, and refname
58
+ # rubocop:disable Metrics/ParameterLists
59
+ def find(type:, value:, subtype: nil, field: nil, schema: 'common', sort: nil, operator: '=')
60
+ service = CollectionSpace::Service.get(type: type, subtype: subtype)
61
+ field ||= service[:term] # this will be set if it is an authority or vocabulary, otherwise nil
62
+ field ||= service[:identifier]
63
+ search_args = CollectionSpace::Search.new.from_hash(
64
+ path: service[:path],
65
+ namespace: "#{service[:ns_prefix]}_#{schema}",
66
+ field: field,
67
+ expression: "#{operator} '#{value.gsub(/'/, '\\\\\'')}'"
68
+ )
69
+ search(search_args, sortBy: CollectionSpace::Search::DEFAULT_SORT)
70
+ end
71
+ # rubocop:enable Metrics/ParameterLists
72
+
73
+ # @param subject_csid [String] to be searched as `sbj` value
74
+ # @param object_csid [String] to be searched as `obj` value
75
+ # @param rel_type [String<'affects', 'hasBroader'>, nil] to be searched as `prd` value
76
+ def find_relation(subject_csid:, object_csid:, rel_type: nil)
77
+ if rel_type
78
+ get('relations', query: { 'sbj' => subject_csid, 'obj' => object_csid, 'prd' => rel_type })
79
+ else
80
+ warn(
81
+ "No rel_type specified, so multiple types of relations between #{subject_csid} and #{object_csid} may be returned",
82
+ uplevel: 1
83
+ )
84
+ get('relations', query: { 'sbj' => subject_csid, 'obj' => object_csid })
85
+ end
28
86
  end
29
87
 
30
88
  def get_list_types(path)
31
89
  {
32
90
  'accounts' => %w[accounts_common_list account_list_item],
33
- 'relations' => %w[relations_common_list relation_list_item],
91
+ 'relations' => %w[relations_common_list relation_list_item]
34
92
  }.fetch(path, %w[abstract_common_list list_item])
35
93
  end
36
94
 
37
- def prepare_query(query, options = {})
38
- query_string = "#{query.type}:#{query.field} #{query.expression}"
39
- options.merge(query: { as: query_string })
95
+ def reindex_full_text(doctype, csids = [])
96
+ if csids.any?
97
+ run_job(
98
+ 'Reindex Full Text', :reindex_full_text, :reindex_by_csids, { doctype: doctype, csids: csids }
99
+ )
100
+ else
101
+ run_job(
102
+ 'Reindex Full Text', :reindex_full_text, :reindex_by_doctype, { doctype: doctype }
103
+ )
104
+ end
40
105
  end
41
106
 
42
- def search(query, options = {})
43
- options = prepare_query(query, options)
107
+ def reset_media_blob(id, url)
108
+ raise CollectionSpace::ArgumentError, "Not a valid url #{url}" unless URI.parse(url).instance_of? URI::HTTPS
109
+
110
+ response = find(type: 'media', value: id, field: 'identificationNumber')
111
+ raise CollectionSpace::RequestError, response.result.body unless response.result.success?
112
+
113
+ found = response.parsed
114
+ total = found['abstract_common_list']['totalItems'].to_i
115
+ raise CollectionSpace::NotFoundError, "Media #{id} not found" if total.zero?
116
+ raise CollectionSpace::DuplicateIdFound, "Found multiple media records for #{id}" unless total == 1
117
+
118
+ media_uri = found['abstract_common_list']['list_item']['uri']
119
+ blob_csid = found['abstract_common_list']['list_item']['blobCsid']
120
+
121
+ delete("/blobs/#{blob_csid}") if blob_csid
122
+
123
+ payload = Template.process(:reset_media_blob, { id: id })
124
+ put(media_uri, payload, query: { 'blobUri' => url })
125
+ end
126
+
127
+ def run_job(name, template, invoke_template, data = {})
128
+ payload = Template.process(invoke_template, data)
129
+ job = add_batch_job(name, template)
130
+ path = job.parsed['document']['collectionspace_core']['uri']
131
+ post(path, payload)
132
+ end
133
+
134
+ def search(query, params = {})
135
+ options = prepare_query(query, params)
44
136
  request 'GET', query.path, options
45
137
  end
138
+
139
+ def keyword_search(type:, value:, subtype: nil, sort: nil)
140
+ service = CollectionSpace::Service.get(type: type, subtype: subtype)
141
+ options = prepare_keyword_query(value, { sortBy: CollectionSpace::Search::DEFAULT_SORT })
142
+ request 'GET', service[:path], options
143
+ end
144
+
145
+ def service(type:, subtype: '')
146
+ CollectionSpace::Service.get(type: type, subtype: subtype)
147
+ end
148
+
149
+ private
150
+
151
+ def create_or_update(response, path, property, value, payload)
152
+ list_type, item_type = get_list_types(path)
153
+ item = response.find(list_type, item_type, property, value)
154
+ path = item ? "#{path}/#{item['csid']}" : path
155
+ item ? put(path, payload) : post(path, payload)
156
+ end
157
+
158
+ def prepare_query(query, params = {})
159
+ query_string = "#{query.namespace}:#{query.field} #{query.expression}"
160
+ { query: { as: query_string }.merge(params) }
161
+ end
162
+
163
+ def prepare_keyword_query(query, sort = {})
164
+ query_string = query.downcase.gsub(' ', '+')
165
+ { query: { kw: query_string }.merge(sort) }
166
+ end
46
167
  end
47
168
  end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'strscan'
4
+
5
+ module CollectionSpace
6
+ # CollectionSpace RefName
7
+ #
8
+ # There are four patterns we need to handle:
9
+ #
10
+ # - urn:cspace:domain:type:name(subtype)'label' : Top level authority/vocabulary
11
+ # - urn:cspace:domain:type:name(subtype):item:name(identifier)'label' : Authority/vocabulary term
12
+ # - urn:cspace:domain:type:id(identifier)'label' : Collectionobject
13
+ # - urn:cspace:domain:type:id(identifier) : Procedures, relations, blobs
14
+ class RefName
15
+ attr_reader :domain, :type, :subtype, :identifier, :label
16
+
17
+ def initialize(refname)
18
+ @refname = refname
19
+ @domain = nil
20
+ @type = nil
21
+ @subtype = nil
22
+ @identifier = nil
23
+ @label = nil
24
+ parse
25
+ end
26
+
27
+ def parse
28
+ scanner = StringScanner.new(@refname)
29
+ scanner.skip('urn:cspace:')
30
+ @domain = to_next_colon(scanner)
31
+ @type = to_next_colon(scanner)
32
+
33
+ case next_segment(scanner)
34
+ when 'name'
35
+ set_subtype(scanner)
36
+ when 'id'
37
+ set_identifier(scanner)
38
+ end
39
+
40
+ self
41
+ end
42
+
43
+ # Convenience class method, so new instance of RefName does not have to be instantiated in order to parse
44
+ #
45
+ # As of v0.13.1, return_class is added and defaults to nil for backward compatibility
46
+ # Eventually this default will be deprecated, and a parsed RefName object will be returned as the default.
47
+ # Any new code written using this method should set the return_class parameter to :refname_obj
48
+ def self.parse(refname, return_class = nil)
49
+ return_class == :refname_obj ? new(refname) : new(refname).to_h
50
+ end
51
+
52
+ # Returns a parsed RefName object as a hash.
53
+ # As of v0.13.1, this is equivalent to calling RefName.parse('refnamevalue', :hash)
54
+ # This was added to simplify the process of updating existing code that expects a hash when calling RefName.parse
55
+ def to_h
56
+ {
57
+ domain: domain,
58
+ type: type,
59
+ subtype: subtype,
60
+ identifier: identifier,
61
+ label: label
62
+ }
63
+ end
64
+
65
+ private
66
+
67
+ def next_segment(scanner)
68
+ segment = scanner.check_until(/\(/)
69
+ return nil unless segment
70
+
71
+ segment.delete_suffix('(')
72
+ end
73
+
74
+ def set_identifier(scanner)
75
+ scanner.skip('id(')
76
+ @identifier = to_end_paren(scanner)
77
+ return if scanner.eos?
78
+
79
+ set_label(scanner)
80
+ end
81
+
82
+ def set_label(scanner)
83
+ scanner.skip("'")
84
+ @label = scanner.rest.delete_suffix("'")
85
+ end
86
+
87
+ def set_subtype(scanner)
88
+ scanner.skip('name(')
89
+ @subtype = to_end_paren(scanner)
90
+
91
+ case next_segment(scanner)
92
+ when nil
93
+ set_label(scanner)
94
+ when ':item:name'
95
+ set_term_identifier(scanner)
96
+ end
97
+ end
98
+
99
+ def set_term_identifier(scanner)
100
+ scanner.skip(':item:name(')
101
+ @identifier = to_end_paren(scanner)
102
+ scanner.skip("'")
103
+ set_label(scanner)
104
+ end
105
+
106
+ def to_end_paren(scanner)
107
+ scanner.scan_until(/\)/).delete_suffix(')')
108
+ end
109
+
110
+ def to_next_colon(scanner)
111
+ scanner.scan_until(/:/).delete_suffix(':')
112
+ end
113
+ end
114
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CollectionSpace
2
4
  # CollectionSpace request
3
5
  class Request
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CollectionSpace
2
4
  # CollectionSpace response
3
5
  class Response
@@ -10,5 +12,14 @@ module CollectionSpace
10
12
  body = result.body
11
13
  @xml = @result.success? && body =~ /<?xml/ ? Nokogiri::XML(body) : nil
12
14
  end
15
+
16
+ def find(list_type, item_type, property, value)
17
+ total = parsed[list_type]['totalItems'].to_i
18
+ return unless total.positive?
19
+
20
+ list = parsed[list_type][item_type]
21
+ list = [list] if total == 1 # wrap if single item
22
+ list.find { |i| i[property] == value }
23
+ end
13
24
  end
14
25
  end
@@ -1,11 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CollectionSpace
2
4
  # CollectionSpace search
3
5
  class Search
4
- attr_accessor :path, :type, :field, :expression
6
+ attr_accessor :path, :namespace, :field, :expression
7
+
8
+ DEFAULT_SORT = 'collectionspace_core:updatedAt DESC'
5
9
 
6
- def initialize(path: nil, type: nil, field: nil, expression: nil)
10
+ def initialize(path: nil, namespace: nil, field: nil, expression: nil)
7
11
  @path = path
8
- @type = type
12
+ @namespace = namespace
9
13
  @field = field
10
14
  @expression = expression
11
15
  end
@@ -0,0 +1,198 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CollectionSpace
4
+ # CollectionSpace service
5
+ class Service
6
+ TERM_SUFFIX = 'TermGroupList/0/termDisplayName'
7
+ def self.get(type:, subtype: '')
8
+ {
9
+ 'acquisitions' => {
10
+ identifier: 'acquisitionReferenceNumber',
11
+ ns_prefix: 'acquisitions',
12
+ path: 'acquisitions',
13
+ term: nil
14
+ },
15
+ 'citationauthorities' => {
16
+ identifier: 'shortIdentifier',
17
+ ns_prefix: 'citations',
18
+ path: "citationauthorities/urn:cspace:name(#{subtype})/items",
19
+ term: "citation#{TERM_SUFFIX}"
20
+ },
21
+ 'claims' => {
22
+ identifier: 'claimNumber',
23
+ ns_prefix: 'claims',
24
+ path: 'claims',
25
+ term: nil
26
+ },
27
+ 'collectionobjects' => {
28
+ identifier: 'objectNumber',
29
+ ns_prefix: 'collectionobjects',
30
+ path: 'collectionobjects',
31
+ term: nil
32
+ },
33
+ 'conceptauthorities' => {
34
+ identifier: 'shortIdentifier',
35
+ ns_prefix: 'concepts',
36
+ path: "conceptauthorities/urn:cspace:name(#{subtype})/items",
37
+ term: "concept#{TERM_SUFFIX}"
38
+ },
39
+ 'conditionchecks' => {
40
+ identifier: 'conditionCheckRefNumber',
41
+ ns_prefix: 'conditionchecks',
42
+ path: 'conditionchecks',
43
+ term: nil
44
+ },
45
+ 'conservation' => {
46
+ identifier: 'conservationNumber',
47
+ ns_prefix: 'conservation',
48
+ path: 'conservation',
49
+ term: nil
50
+ },
51
+ 'exhibitions' => {
52
+ identifier: 'exhibitionNumber',
53
+ ns_prefix: 'exhibitions',
54
+ path: 'exhibitions',
55
+ term: nil
56
+ },
57
+ 'groups' => {
58
+ identifier: 'title',
59
+ ns_prefix: 'groups',
60
+ path: 'groups',
61
+ term: nil
62
+ },
63
+ 'insurances' => {
64
+ identifier: 'insuranceIndemnityReferenceNumber',
65
+ ns_prefix: 'insurances',
66
+ path: 'insurances',
67
+ term: nil
68
+ },
69
+ 'intakes' => {
70
+ identifier: 'entryNumber',
71
+ ns_prefix: 'intakes',
72
+ path: 'intakes',
73
+ term: nil
74
+ },
75
+ 'loansin' => {
76
+ identifier: 'loanInNumber',
77
+ ns_prefix: 'loansin',
78
+ path: 'loansin',
79
+ term: nil
80
+ },
81
+ 'loansout' => {
82
+ identifier: 'loanOutNumber',
83
+ ns_prefix: 'loansout',
84
+ path: 'loansout',
85
+ term: nil
86
+ },
87
+ 'locationauthorities' => {
88
+ identifier: 'shortIdentifier',
89
+ ns_prefix: 'locations',
90
+ path: "locationauthorities/urn:cspace:name(#{subtype})/items",
91
+ term: "loc#{TERM_SUFFIX}"
92
+ },
93
+ 'materialauthorities' => {
94
+ identifier: 'shortIdentifier',
95
+ ns_prefix: 'materials',
96
+ path: "materialauthorities/urn:cspace:name(#{subtype})/items",
97
+ term: "material#{TERM_SUFFIX}"
98
+ },
99
+ 'media' => {
100
+ identifier: 'identificationNumber',
101
+ ns_prefix: 'media',
102
+ path: 'media',
103
+ term: nil
104
+ },
105
+ 'movements' => {
106
+ identifier: 'movementReferenceNumber',
107
+ ns_prefix: 'movements',
108
+ path: 'movements',
109
+ term: nil
110
+ },
111
+ 'objectexit' => {
112
+ identifier: 'exitNumber',
113
+ ns_prefix: 'objectexit',
114
+ path: 'objectexit',
115
+ term: nil
116
+ },
117
+ 'orgauthorities' => {
118
+ identifier: 'shortIdentifier',
119
+ ns_prefix: 'organizations',
120
+ path: "orgauthorities/urn:cspace:name(#{subtype})/items",
121
+ term: "org#{TERM_SUFFIX}"
122
+ },
123
+ 'osteology' => {
124
+ identifier: 'InventoryID',
125
+ ns_prefix: 'osteology',
126
+ path: 'osteology',
127
+ term: nil
128
+ },
129
+ 'personauthorities' => {
130
+ identifier: 'shortIdentifier',
131
+ ns_prefix: 'persons',
132
+ path: "personauthorities/urn:cspace:name(#{subtype})/items",
133
+ term: "person#{TERM_SUFFIX}"
134
+ },
135
+ 'placeauthorities' => {
136
+ identifier: 'shortIdentifier',
137
+ ns_prefix: 'places',
138
+ path: "placeauthorities/urn:cspace:name(#{subtype})/items",
139
+ term: "place#{TERM_SUFFIX}"
140
+ },
141
+ 'pottags' => {
142
+ identifier: 'potTagNumber',
143
+ ns_prefix: 'pottags',
144
+ path: 'pottags',
145
+ term: nil
146
+ },
147
+ 'propagations' => {
148
+ identifier: 'propNumber',
149
+ ns_prefix: 'propagations',
150
+ path: 'propagations',
151
+ term: nil
152
+ },
153
+ 'relations' => {
154
+ identifier: 'csid',
155
+ ns_prefix: 'relations',
156
+ path: 'relations',
157
+ term: nil
158
+ },
159
+ 'taxonomyauthority' => {
160
+ identifier: 'shortIdentifier',
161
+ ns_prefix: 'taxon',
162
+ path: "taxonomyauthority/urn:cspace:name(#{subtype})/items",
163
+ term: "taxon#{TERM_SUFFIX}"
164
+ },
165
+ 'transports' => {
166
+ identifier: 'transportReferenceNumber',
167
+ ns_prefix: 'transports',
168
+ path: 'transports',
169
+ term: nil
170
+ },
171
+ 'uoc' => {
172
+ identifier: 'referenceNumber',
173
+ ns_prefix: 'uoc',
174
+ path: 'uoc',
175
+ term: nil
176
+ },
177
+ 'valuationcontrols' => {
178
+ identifier: 'valuationcontrolRefNumber',
179
+ ns_prefix: 'valuationcontrols',
180
+ path: 'valuationcontrols',
181
+ term: nil
182
+ },
183
+ 'vocabularies' => {
184
+ identifier: 'shortIdentifier',
185
+ ns_prefix: 'vocabularyitems',
186
+ path: "vocabularies/urn:cspace:name(#{subtype})/items",
187
+ term: 'displayName'
188
+ },
189
+ 'workauthorities' => {
190
+ identifier: 'shortIdentifier',
191
+ ns_prefix: 'works',
192
+ path: "workauthorities/urn:cspace:name(#{subtype})/items",
193
+ term: "work#{TERM_SUFFIX}"
194
+ }
195
+ }.fetch(type)
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CollectionSpace
4
+ module Template
5
+ def self.list
6
+ Dir.glob File.join(templates_path, '*.erb')
7
+ end
8
+
9
+ def self.process(template, data)
10
+ t = ERB.new(read(template))
11
+ r = t.result(binding).gsub(/\n+/, "\n")
12
+ Nokogiri::XML.parse(r).to_xml
13
+ end
14
+
15
+ def self.read(file)
16
+ File.read("#{templates_path}/#{file}.xml.erb")
17
+ end
18
+
19
+ def self.templates_path
20
+ ENV.fetch(
21
+ 'COLLECTIONSPACE_CLIENT_TEMPLATES_PATH',
22
+ File.join(File.dirname(File.expand_path(__FILE__)), 'templates')
23
+ )
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2
+ <ns2:invocationContext xmlns:ns2="http://collectionspace.org/services/common/invocable">
3
+ <mode>list</mode>
4
+ <docType><%= data[:doctype] %></docType>
5
+ <listCSIDs>
6
+ <% data[:csids].each do |csid| %>
7
+ <csid><%= csid %></csid>
8
+ <% end %>
9
+ </listCSIDs>
10
+ </ns2:invocationContext>
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2
+ <ns2:invocationContext xmlns:ns2="http://collectionspace.org/services/common/invocable">
3
+ <mode>nocontext</mode>
4
+ <docType><%= data[:doctype] %></docType>
5
+ </ns2:invocationContext>
@@ -0,0 +1,51 @@
1
+ <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2
+ <document name="batch">
3
+ <ns2:batch_common xmlns:ns2="http://collectionspace.org/services/batch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4
+ <name>Reindex Full Text</name>
5
+ <notes>Recomputes the indexed full text of all or specified records.</notes>
6
+ <className>org.collectionspace.services.batch.nuxeo.ReindexFullTextBatchJob</className>
7
+ <supportsNoContext>true</supportsNoContext>
8
+ <supportsSingleDoc>true</supportsSingleDoc>
9
+ <supportsDocList>true</supportsDocList>
10
+ <supportsGroup>false</supportsGroup>
11
+ <createsNewFocus>false</createsNewFocus>
12
+ <forDocTypes>
13
+ <forDocType>Acquisition</forDocType>
14
+ <forDocType>Batch</forDocType>
15
+ <forDocType>Blob</forDocType>
16
+ <forDocType>Citation</forDocType>
17
+ <forDocType>Citationauthority</forDocType>
18
+ <forDocType>Claim</forDocType>
19
+ <forDocType>CollectionObject</forDocType>
20
+ <forDocType>Conceptauthority</forDocType>
21
+ <forDocType>Conceptitem</forDocType>
22
+ <forDocType>Contact</forDocType>
23
+ <forDocType>Dimension</forDocType>
24
+ <forDocType>Group</forDocType>
25
+ <forDocType>Intake</forDocType>
26
+ <forDocType>Loanin</forDocType>
27
+ <forDocType>Loanout</forDocType>
28
+ <forDocType>Locationauthority</forDocType>
29
+ <forDocType>Locationitem</forDocType>
30
+ <forDocType>Media</forDocType>
31
+ <forDocType>Movement</forDocType>
32
+ <forDocType>ObjectExit</forDocType>
33
+ <forDocType>Organization</forDocType>
34
+ <forDocType>Orgauthority</forDocType>
35
+ <forDocType>Osteology</forDocType>
36
+ <forDocType>Person</forDocType>
37
+ <forDocType>Personauthority</forDocType>
38
+ <forDocType>Placeauthority</forDocType>
39
+ <forDocType>Placeitem</forDocType>
40
+ <forDocType>PublicItem</forDocType>
41
+ <forDocType>Relation</forDocType>
42
+ <forDocType>Report</forDocType>
43
+ <forDocType>Taxon</forDocType>
44
+ <forDocType>Taxonomyauthority</forDocType>
45
+ <forDocType>Vocabulary</forDocType>
46
+ <forDocType>Vocabularyitem</forDocType>
47
+ <forDocType>Workauthority</forDocType>
48
+ <forDocType>Workitem</forDocType>
49
+ </forDocTypes>
50
+ </ns2:batch_common>
51
+ </document>
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <document name="reports">
3
+ <ns2:reports_common xmlns:ns2="http://collectionspace.org/services/report">
4
+ <name><%= data.fetch(:name) %></name>
5
+ <notes><%= data.fetch(:notes, data[:name]) %></notes>
6
+ <forDocTypes>
7
+ <forDocType><%= data.fetch(:doctype) %></forDocType>
8
+ </forDocTypes>
9
+ <supportsSingleDoc><%= data.fetch(:supports_single_doc, 'true') %></supportsSingleDoc>
10
+ <supportsDocList><%= data.fetch(:supports_doc_list, 'false') %></supportsDocList>
11
+ <supportsGroup><%= data.fetch(:supports_group, 'false') %></supportsGroup>
12
+ <supportsNoContext><%= data.fetch(:supports_no_context, 'true') %></supportsNoContext>
13
+ <filename><%= data.fetch(:filename) %></filename>
14
+ <outputMIME><%= data.fetch(:mimetype, 'application/pdf') %></outputMIME>
15
+ </ns2:reports_common>
16
+ </document>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <document name="media">
3
+ <ns2:media_common xmlns:ns2="http://collectionspace.org/services/media" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4
+ <identificationNumber><%= data[:id] %></identificationNumber>
5
+ </ns2:media_common>
6
+ </document>
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CollectionSpace
2
4
  class Client
3
- VERSION = '0.3.0'.freeze
5
+ VERSION = '0.14.1'
4
6
  end
5
7
  end