aspace_client 0.0.1
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/lib/aspace_client.rb +15 -0
- data/lib/aspace_client/archivesspace_json_schema.rb +210 -0
- data/lib/aspace_client/asutils.rb +142 -0
- data/lib/aspace_client/client_enum_source.rb +30 -0
- data/lib/aspace_client/exceptions.rb +15 -0
- data/lib/aspace_client/helpers.rb +0 -0
- data/lib/aspace_client/json_schema_concurrency_fix.rb +52 -0
- data/lib/aspace_client/json_schema_utils.rb +414 -0
- data/lib/aspace_client/jsonmodel.rb +342 -0
- data/lib/aspace_client/jsonmodel_client.rb +528 -0
- data/lib/aspace_client/jsonmodel_i18n_mixin.rb +77 -0
- data/lib/aspace_client/jsonmodel_type.rb +478 -0
- data/lib/aspace_client/memoryleak.rb +59 -0
- data/lib/aspace_client/schemas/abstract_agent.rb +51 -0
- data/lib/aspace_client/schemas/abstract_agent_relationship.rb +12 -0
- data/lib/aspace_client/schemas/abstract_archival_object.rb +96 -0
- data/lib/aspace_client/schemas/abstract_classification.rb +44 -0
- data/lib/aspace_client/schemas/abstract_name.rb +23 -0
- data/lib/aspace_client/schemas/abstract_note.rb +13 -0
- data/lib/aspace_client/schemas/accession.rb +174 -0
- data/lib/aspace_client/schemas/accession_parts_relationship.rb +31 -0
- data/lib/aspace_client/schemas/accession_sibling_relationship.rb +31 -0
- data/lib/aspace_client/schemas/active_edits.rb +23 -0
- data/lib/aspace_client/schemas/advanced_query.rb +12 -0
- data/lib/aspace_client/schemas/agent_contact.rb +25 -0
- data/lib/aspace_client/schemas/agent_corporate_entity.rb +32 -0
- data/lib/aspace_client/schemas/agent_family.rb +29 -0
- data/lib/aspace_client/schemas/agent_person.rb +31 -0
- data/lib/aspace_client/schemas/agent_relationship_associative.rb +28 -0
- data/lib/aspace_client/schemas/agent_relationship_earlierlater.rb +28 -0
- data/lib/aspace_client/schemas/agent_relationship_parentchild.rb +26 -0
- data/lib/aspace_client/schemas/agent_relationship_subordinatesuperior.rb +26 -0
- data/lib/aspace_client/schemas/agent_software.rb +22 -0
- data/lib/aspace_client/schemas/archival_object.rb +60 -0
- data/lib/aspace_client/schemas/archival_record_children.rb +15 -0
- data/lib/aspace_client/schemas/boolean_field_query.rb +13 -0
- data/lib/aspace_client/schemas/boolean_query.rb +13 -0
- data/lib/aspace_client/schemas/classification.rb +10 -0
- data/lib/aspace_client/schemas/classification_term.rb +38 -0
- data/lib/aspace_client/schemas/classification_tree.rb +17 -0
- data/lib/aspace_client/schemas/collection_management.rb +27 -0
- data/lib/aspace_client/schemas/container.rb +29 -0
- data/lib/aspace_client/schemas/container_location.rb +19 -0
- data/lib/aspace_client/schemas/date.rb +19 -0
- data/lib/aspace_client/schemas/date_field_query.rb +14 -0
- data/lib/aspace_client/schemas/deaccession.rb +20 -0
- data/lib/aspace_client/schemas/defaults.rb +104 -0
- data/lib/aspace_client/schemas/digital_object.rb +64 -0
- data/lib/aspace_client/schemas/digital_object_component.rb +53 -0
- data/lib/aspace_client/schemas/digital_object_tree.rb +19 -0
- data/lib/aspace_client/schemas/digital_record_children.rb +15 -0
- data/lib/aspace_client/schemas/enumeration.rb +29 -0
- data/lib/aspace_client/schemas/enumeration_migration.rb +14 -0
- data/lib/aspace_client/schemas/event.rb +88 -0
- data/lib/aspace_client/schemas/extent.rb +17 -0
- data/lib/aspace_client/schemas/external_document.rb +12 -0
- data/lib/aspace_client/schemas/external_id.rb +11 -0
- data/lib/aspace_client/schemas/field_query.rb +15 -0
- data/lib/aspace_client/schemas/file_version.rb +26 -0
- data/lib/aspace_client/schemas/group.rb +17 -0
- data/lib/aspace_client/schemas/instance.rb +27 -0
- data/lib/aspace_client/schemas/job.rb +57 -0
- data/lib/aspace_client/schemas/location.rb +36 -0
- data/lib/aspace_client/schemas/location_batch.rb +45 -0
- data/lib/aspace_client/schemas/merge_request.rb +48 -0
- data/lib/aspace_client/schemas/name_corporate_entity.rb +15 -0
- data/lib/aspace_client/schemas/name_family.rb +13 -0
- data/lib/aspace_client/schemas/name_form.rb +15 -0
- data/lib/aspace_client/schemas/name_person.rb +19 -0
- data/lib/aspace_client/schemas/name_software.rb +14 -0
- data/lib/aspace_client/schemas/note_abstract.rb +17 -0
- data/lib/aspace_client/schemas/note_bibliography.rb +29 -0
- data/lib/aspace_client/schemas/note_bioghist.rb +22 -0
- data/lib/aspace_client/schemas/note_chronology.rb +28 -0
- data/lib/aspace_client/schemas/note_citation.rb +32 -0
- data/lib/aspace_client/schemas/note_definedlist.rb +25 -0
- data/lib/aspace_client/schemas/note_digital_object.rb +23 -0
- data/lib/aspace_client/schemas/note_index.rb +29 -0
- data/lib/aspace_client/schemas/note_index_item.rb +25 -0
- data/lib/aspace_client/schemas/note_multipart.rb +25 -0
- data/lib/aspace_client/schemas/note_orderedlist.rb +27 -0
- data/lib/aspace_client/schemas/note_outline.rb +20 -0
- data/lib/aspace_client/schemas/note_outline_level.rb +21 -0
- data/lib/aspace_client/schemas/note_singlepart.rb +24 -0
- data/lib/aspace_client/schemas/note_text.rb +17 -0
- data/lib/aspace_client/schemas/permission.rb +15 -0
- data/lib/aspace_client/schemas/preference.rb +16 -0
- data/lib/aspace_client/schemas/record_tree.rb +17 -0
- data/lib/aspace_client/schemas/repository.rb +32 -0
- data/lib/aspace_client/schemas/repository_with_agent.rb +14 -0
- data/lib/aspace_client/schemas/resource.rb +112 -0
- data/lib/aspace_client/schemas/resource_tree.rb +20 -0
- data/lib/aspace_client/schemas/rights_statement.rb +35 -0
- data/lib/aspace_client/schemas/subject.rb +30 -0
- data/lib/aspace_client/schemas/term.rb +16 -0
- data/lib/aspace_client/schemas/user.rb +56 -0
- data/lib/aspace_client/schemas/user_defined.rb +42 -0
- data/lib/aspace_client/schemas/vocabulary.rb +15 -0
- data/lib/aspace_client/validations.rb +434 -0
- data/lib/aspace_client/validator_cache.rb +47 -0
- data/lib/aspace_client/version.rb +3 -0
- metadata +244 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: ac953db47d3758e451a44a90dbdf570bad1c6d48
|
|
4
|
+
data.tar.gz: ee196ef429407e4f59cea5190865fd08a70b9c44
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 191e45a120e291974d55e0000073acfd460e6162847d3c891c7b9422e98532b5ad8f8f7861410d4906191bb4d37fbbfe4833c05c5c45328f957152e8880cc1ec
|
|
7
|
+
data.tar.gz: 34076a7f7f5fb3d8c8d64ac578c66bde17f1c5887da65462af9b76855c94c5ed70bafcf145c4c7b58db9bd121d9fa6ed0015039cf8000705e00b7c5343a8426c
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
$: << "#{File.dirname(__FILE__)}" unless $:.include? File.dirname(__FILE__)
|
|
2
|
+
|
|
3
|
+
require "aspace_client/jsonmodel"
|
|
4
|
+
require "aspace_client/asutils"
|
|
5
|
+
require "aspace_client/memoryleak"
|
|
6
|
+
require "aspace_client/client_enum_source"
|
|
7
|
+
require "aspace_client/jsonmodel_i18n_mixin"
|
|
8
|
+
require 'aspace_client/jsonmodel_client'
|
|
9
|
+
require 'aspace_client/archivesspace_json_schema.rb'
|
|
10
|
+
|
|
11
|
+
include JSONModel
|
|
12
|
+
|
|
13
|
+
module AspaceClient
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
|
|
3
|
+
# Add a new 'ifmissing' attribute which emits either an error or warning
|
|
4
|
+
# depending on its value.
|
|
5
|
+
class IfMissingAttribute < JSON::Schema::PropertiesAttribute
|
|
6
|
+
|
|
7
|
+
def self.validate(current_schema, data, fragments, validator, options = {})
|
|
8
|
+
super
|
|
9
|
+
|
|
10
|
+
if data.is_a?(Hash)
|
|
11
|
+
current_schema.schema['properties'].each do |property, property_schema|
|
|
12
|
+
if (property_schema['ifmissing'] && !data.has_key?(property))
|
|
13
|
+
message = nil
|
|
14
|
+
|
|
15
|
+
if property_schema['ifmissing'] == 'error'
|
|
16
|
+
message = "ERROR: The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|
|
17
|
+
elsif property_schema['ifmissing'] == 'warn'
|
|
18
|
+
message = "WARNING: The property '#{build_fragment(fragments)}' did not contain a required property of '#{property}'"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if message
|
|
22
|
+
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ArchivesSpaceTypeAttribute < JSON::Schema::TypeAttribute
|
|
33
|
+
extend JSONModel
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# This reuse business is a bit of a pain. The story here: JRuby backtraces
|
|
37
|
+
# are relatively expensive to create (relative to MRI Ruby), and JSON Schema
|
|
38
|
+
# validation is using exceptions as control flow here (sigh). During imports,
|
|
39
|
+
# these validation error are hit a *lot*, and calculating a backtrace every
|
|
40
|
+
# time is expensive.
|
|
41
|
+
#
|
|
42
|
+
# So, we recycle.
|
|
43
|
+
def self.validation_error_for(expected_type, fragments, current_schema)
|
|
44
|
+
Thread.current[:json_validation_cached_errors] ||= {}
|
|
45
|
+
if !Thread.current[:json_validation_cached_errors][expected_type]
|
|
46
|
+
msg = "ERROR: Schema type mismatch. Expected type: #{expected_type}"
|
|
47
|
+
Thread.current[:json_validation_cached_errors][expected_type] = JSON::Schema::ValidationError.new(msg, fragments, self, current_schema)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Thread.current[:json_validation_cached_errors][expected_type].fragments = fragments
|
|
51
|
+
Thread.current[:json_validation_cached_errors][expected_type]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def self.validate(current_schema, data, fragments, validator, options = {})
|
|
56
|
+
types = current_schema.schema['type']
|
|
57
|
+
|
|
58
|
+
if types == 'date'
|
|
59
|
+
begin
|
|
60
|
+
Date.parse(data)
|
|
61
|
+
return
|
|
62
|
+
rescue
|
|
63
|
+
validation_error("The property '#{build_fragment(fragments)}' was not " +
|
|
64
|
+
"a well-formed date (value: #{data})",
|
|
65
|
+
fragments, current_schema, self, options[:record_errors])
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if types == 'object' && data.is_a?(Hash) && data.has_key?('ref') && current_schema.schema['subtype'] != 'ref'
|
|
71
|
+
# Provide a helpful warning about potentially missing subtype definitions
|
|
72
|
+
$stderr.puts("WARNING: Schema #{current_schema.inspect} appears to be missing a subtype definition of 'ref'")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# A bit crazy, sorry. If we're being asked to validate a hash whose
|
|
76
|
+
# jsonmodel_type is marked against a different JSONModel schema, we're
|
|
77
|
+
# wasting our time. Just stop straight away.
|
|
78
|
+
if (data.is_a?(Hash) && data["jsonmodel_type"]) &&
|
|
79
|
+
(current_schema.schema.is_a?(Hash) &&
|
|
80
|
+
"#{current_schema.schema["type"]}".include?("JSONModel") &&
|
|
81
|
+
!"#{current_schema.schema["type"]}".include?("JSONModel(:#{data['jsonmodel_type']})"))
|
|
82
|
+
|
|
83
|
+
raise validation_error_for(data['jsonmodel_type'], fragments, current_schema)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if JSONModel.parse_jsonmodel_ref(types)
|
|
87
|
+
(model, qualifier) = JSONModel.parse_jsonmodel_ref(types)
|
|
88
|
+
|
|
89
|
+
if qualifier == 'uri' || (qualifier == 'uri_or_object' && data.is_a?(String))
|
|
90
|
+
if JSONModel(model).id_for(data, {}, true).nil?
|
|
91
|
+
validation_error("The property '#{build_fragment(fragments)}' of type " +
|
|
92
|
+
"#{data.class} did not match the following type: #{types} in schema",
|
|
93
|
+
fragments, current_schema, self, options[:record_errors])
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
elsif qualifier == 'uri_or_object' || qualifier == 'object'
|
|
97
|
+
if data.is_a?(Hash)
|
|
98
|
+
data["jsonmodel_type"] ||= model.to_s
|
|
99
|
+
|
|
100
|
+
ValidatorCache.with_validator_for(JSONModel(model), data) do |subvalidator|
|
|
101
|
+
# Urk. Validate the subrecord but pass in the fragments of the point
|
|
102
|
+
# we're at in the parent record.
|
|
103
|
+
subvalidator.instance_eval do
|
|
104
|
+
@base_schema.validate(@data, fragments, @validation_options)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
else
|
|
109
|
+
validation_error("The property '#{build_fragment(fragments)}' of type " +
|
|
110
|
+
"#{data.class} did not match the following type: #{types} in schema",
|
|
111
|
+
fragments, current_schema, self, options[:record_errors])
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
else
|
|
115
|
+
super
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class ArchivesSpaceSubTypeAttribute < JSON::Schema::TypeAttribute
|
|
122
|
+
|
|
123
|
+
def self.validate(current_schema, data, fragments, validator, options = {})
|
|
124
|
+
if data.is_a?(Hash) && !data.has_key?('ref')
|
|
125
|
+
message = "ERROR: The property '#{build_fragment(fragments)}' did not contain a required property of 'ref'"
|
|
126
|
+
validation_error(message, fragments, current_schema, self, options[:record_errors])
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class ArchivesSpaceReadOnlyDynamicEnumAttribute < JSON::Schema::TypeAttribute; end
|
|
133
|
+
|
|
134
|
+
class ArchivesSpaceDynamicEnumAttribute < JSON::Schema::TypeAttribute
|
|
135
|
+
|
|
136
|
+
def self.validate(current_schema, data, fragments, validator, options = {})
|
|
137
|
+
enum_name = current_schema.schema['dynamic_enum']
|
|
138
|
+
|
|
139
|
+
if !JSONModel.init_args[:enum_source].valid?(enum_name, data)
|
|
140
|
+
possible_values = JSONModel.init_args[:enum_source].values_for(enum_name)
|
|
141
|
+
message = ("The property '#{build_fragment(fragments)}' value #{data.inspect} " +
|
|
142
|
+
"did not match one of the following configurable values: #{possible_values.join(', ')}")
|
|
143
|
+
|
|
144
|
+
if JSONModel.init_args[:enum_source].editable?(enum_name)
|
|
145
|
+
klass = self
|
|
146
|
+
else
|
|
147
|
+
klass = ArchivesSpaceReadOnlyDynamicEnumAttribute
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
validation_error(message, fragments, current_schema, klass, options[:record_errors])
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class ArchivesSpaceSchema < JSON::Schema::Validator
|
|
158
|
+
def initialize
|
|
159
|
+
super
|
|
160
|
+
extend_schema_definition("http://json-schema.org/draft-03/schema#")
|
|
161
|
+
@attributes["type"] = ArchivesSpaceTypeAttribute
|
|
162
|
+
@attributes["subtype"] = ArchivesSpaceSubTypeAttribute
|
|
163
|
+
@attributes["dynamic_enum"] = ArchivesSpaceDynamicEnumAttribute
|
|
164
|
+
@attributes["properties"] = IfMissingAttribute
|
|
165
|
+
@uri = URI.parse("http://www.archivesspace.org/archivesspace.json")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def already_failed?(fragments)
|
|
170
|
+
JSON::Validator.validation_errors.any? {|error|
|
|
171
|
+
error.fragments == fragments
|
|
172
|
+
}
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def validate(current_schema, data, fragments, options = {})
|
|
177
|
+
super
|
|
178
|
+
|
|
179
|
+
# Run any custom validations if we've made it this far with no errors
|
|
180
|
+
if !already_failed?(fragments) && current_schema.schema.has_key?("validations")
|
|
181
|
+
current_schema.schema["validations"].each do |level_and_name|
|
|
182
|
+
level, name = level_and_name
|
|
183
|
+
|
|
184
|
+
errors = JSONModel::custom_validations[name].call(data)
|
|
185
|
+
|
|
186
|
+
errors.each do |error|
|
|
187
|
+
error_string = nil
|
|
188
|
+
|
|
189
|
+
if error.is_a? Symbol
|
|
190
|
+
error_string = "Validation error code: #{error}"
|
|
191
|
+
else
|
|
192
|
+
field, msg = error
|
|
193
|
+
prefix = level == :warning ? "Warning generated for" : "Validation failed for"
|
|
194
|
+
error_string = "#{prefix} '#{field}': #{msg}"
|
|
195
|
+
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
err = JSON::Schema::ValidationError.new(error_string,
|
|
199
|
+
fragments,
|
|
200
|
+
"custom_validation",
|
|
201
|
+
current_schema)
|
|
202
|
+
|
|
203
|
+
JSON::Validator.validation_error(err)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
JSON::Validator.register_validator(self.new)
|
|
210
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'tmpdir'
|
|
3
|
+
require 'tempfile'
|
|
4
|
+
|
|
5
|
+
module ASUtils
|
|
6
|
+
|
|
7
|
+
def self.keys_as_strings(hash)
|
|
8
|
+
result = {}
|
|
9
|
+
|
|
10
|
+
hash.each do |key, value|
|
|
11
|
+
result[key.to_s] = value.is_a?(Date) ? value.to_s : value
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
result
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def self.as_array(thing)
|
|
19
|
+
return [] if thing.nil?
|
|
20
|
+
thing.kind_of?(Array) ? thing : [thing]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def self.jsonmodels_to_hashes(elt)
|
|
25
|
+
|
|
26
|
+
if elt.is_a?(JSONModelType)
|
|
27
|
+
elt = elt.to_hash(:raw)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if elt.is_a?(Hash)
|
|
31
|
+
Hash[elt.map {|k, v| [k, self.jsonmodels_to_hashes(v)]}]
|
|
32
|
+
elsif elt.is_a?(Array)
|
|
33
|
+
elt.map {|v| self.jsonmodels_to_hashes(v)}
|
|
34
|
+
else
|
|
35
|
+
elt
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def self.json_parse(s)
|
|
41
|
+
JSON.parse(s, :max_nesting => false, :create_additions => false)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def self.to_json(obj, opts = {})
|
|
47
|
+
if obj.respond_to?(:jsonize)
|
|
48
|
+
obj.jsonize(opts.merge(:max_nesting => false))
|
|
49
|
+
else
|
|
50
|
+
obj.to_json(opts.merge(:max_nesting => false))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def self.find_base_directory(root = nil)
|
|
56
|
+
[ File.join(*[File.dirname(__FILE__), "..", root].compact)].find {|dir|
|
|
57
|
+
Dir.exists?(dir)
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def self.find_local_directories(base = nil, *plugins)
|
|
63
|
+
base_directory = self.find_base_directory
|
|
64
|
+
Array(plugins).map { |plugin| File.join(*[base_directory, "plugins", plugin, base].compact) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def self.find_locales_directories(base = nil)
|
|
69
|
+
[File.join(*[self.find_base_directory("common"), "locales", base].compact)]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def self.extract_nested_strings(coll)
|
|
74
|
+
if coll.is_a?(Hash)
|
|
75
|
+
coll.values.map {|v| self.extract_nested_strings(v)}.flatten.compact
|
|
76
|
+
elsif coll.is_a?(Array)
|
|
77
|
+
coll.map {|v| self.extract_nested_strings(v)}.flatten.compact
|
|
78
|
+
else
|
|
79
|
+
coll
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.dump_diagnostics(exception = nil)
|
|
84
|
+
diagnostics = self.get_diagnostics( exception )
|
|
85
|
+
tmp = File.join(Dir.tmpdir, "aspaue_diagnostic_#{Time.now.to_i}.txt")
|
|
86
|
+
File.open(tmp, "w") do |fh|
|
|
87
|
+
fh.write(JSON.pretty_generate(diagnostics))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
msg = <<EOF
|
|
91
|
+
A trace file has been written to the following location: #{tmp}
|
|
92
|
+
|
|
93
|
+
This file contains information that will assist developers in diagnosing
|
|
94
|
+
problems with your ArchivesSpace installation. Please review the file's
|
|
95
|
+
contents for sensitive information (such as passwords) that you might not
|
|
96
|
+
want to share.
|
|
97
|
+
EOF
|
|
98
|
+
|
|
99
|
+
$stderr.puts("=" * 72)
|
|
100
|
+
$stderr.puts(msg)
|
|
101
|
+
$stderr.puts("=" * 72)
|
|
102
|
+
|
|
103
|
+
raise exception if exception
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# Recursively overlays hash2 onto hash 1
|
|
108
|
+
def self.deep_merge(hash1, hash2)
|
|
109
|
+
target = hash1.dup
|
|
110
|
+
hash2.keys.each do |key|
|
|
111
|
+
if hash2[key].is_a? Hash and hash1[key].is_a? Hash
|
|
112
|
+
target[key] = self.deep_merge(target[key], hash2[key])
|
|
113
|
+
next
|
|
114
|
+
end
|
|
115
|
+
target[key] = hash2[key]
|
|
116
|
+
end
|
|
117
|
+
target
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def self.load_plugin_gems(context)
|
|
122
|
+
ASUtils.find_local_directories.each do |plugin|
|
|
123
|
+
gemfile = File.join(plugin, 'Gemfile')
|
|
124
|
+
if File.exists?(gemfile)
|
|
125
|
+
context.instance_eval(File.read(gemfile))
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# Borrowed from: file activesupport/lib/active_support/core_ext/array/wrap.rb, line 36
|
|
132
|
+
def self.wrap(object)
|
|
133
|
+
if object.nil?
|
|
134
|
+
[]
|
|
135
|
+
elsif object.respond_to?(:to_ary)
|
|
136
|
+
object.to_ary || [object]
|
|
137
|
+
else
|
|
138
|
+
[object]
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require "aspace_client/jsonmodel"
|
|
2
|
+
require "aspace_client/memoryleak"
|
|
3
|
+
|
|
4
|
+
class ClientEnumSource
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
MemoryLeak::Resources.define(:enumerations, proc {
|
|
8
|
+
JSONModel::Client::EnumSource.fetch_enumerations
|
|
9
|
+
}, 300)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def valid?(name, value)
|
|
14
|
+
values_for(name).include?(value)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def editable?(name)
|
|
18
|
+
MemoryLeak::Resources.get(:enumerations).fetch(name).editable?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def values_for(name)
|
|
23
|
+
MemoryLeak::Resources.get(:enumerations).fetch(name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def default_value_for(name)
|
|
27
|
+
MemoryLeak::Resources.get(:enumerations)[:defaults].fetch(name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Monkey patch against json-schema 1.0.12 to work around
|
|
2
|
+
# https://github.com/hoxworth/json-schema/issues/24
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module JSON
|
|
6
|
+
class Validator
|
|
7
|
+
|
|
8
|
+
# Run a simple true/false validation of data against a schema
|
|
9
|
+
def validate()
|
|
10
|
+
begin
|
|
11
|
+
Validator.clear_errors
|
|
12
|
+
@base_schema.validate(@data,[],@validation_options)
|
|
13
|
+
Validator.clear_cache
|
|
14
|
+
if @options[:errors_as_objects]
|
|
15
|
+
self.class.validation_errors.map{|e| e.to_hash}
|
|
16
|
+
else
|
|
17
|
+
self.class.validation_errors.map{|e| e.to_string}
|
|
18
|
+
end
|
|
19
|
+
rescue JSON::Schema::ValidationError
|
|
20
|
+
Validator.clear_cache
|
|
21
|
+
raise $!
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
def clear_errors
|
|
27
|
+
Thread.current[:jsonschema_errors] = []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def validation_error(error)
|
|
31
|
+
Thread.current[:jsonschema_errors] << error
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def validation_errors
|
|
35
|
+
Thread.current[:jsonschema_errors] or []
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Plus one bonus: don't use MultiJson here.
|
|
41
|
+
def serialize schema
|
|
42
|
+
# if defined?(MultiJson)
|
|
43
|
+
# MultiJson.respond_to?(:dump) ? MultiJson.dump(schema) : MultiJson.encode(schema)
|
|
44
|
+
# else
|
|
45
|
+
# @@serializer.call(schema)
|
|
46
|
+
# end
|
|
47
|
+
|
|
48
|
+
ASUtils.to_json(schema)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|