ddr-models 1.2.0
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/LICENSE.txt +12 -0
- data/README.md +5 -0
- data/Rakefile +37 -0
- data/app/models/attachment.rb +7 -0
- data/app/models/collection.rb +54 -0
- data/app/models/component.rb +15 -0
- data/app/models/item.rb +19 -0
- data/app/models/solr_document.rb +36 -0
- data/app/models/target.rb +8 -0
- data/config/initializers/active_fedora_base.rb +77 -0
- data/config/initializers/active_fedora_datastream.rb +5 -0
- data/config/initializers/ddr.rb +8 -0
- data/config/initializers/devise.rb +245 -0
- data/config/initializers/devise.rb~ +245 -0
- data/config/initializers/subscriptions.rb +15 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20141021233359_create_events.rb +28 -0
- data/db/migrate/20141021234156_create_minted_ids.rb +19 -0
- data/db/migrate/20141103192146_create_workflow_state.rb +13 -0
- data/db/migrate/20141104181418_create_users.rb +34 -0
- data/db/migrate/20141104181418_create_users.rb~ +6 -0
- data/lib/ddr-models.rb +1 -0
- data/lib/ddr/actions.rb +8 -0
- data/lib/ddr/actions/fixity_check.rb +35 -0
- data/lib/ddr/auth.rb +45 -0
- data/lib/ddr/auth.rb~ +47 -0
- data/lib/ddr/auth/ability.rb +204 -0
- data/lib/ddr/auth/ability.rb~ +204 -0
- data/lib/ddr/auth/group_service.rb +53 -0
- data/lib/ddr/auth/group_service.rb~ +53 -0
- data/lib/ddr/auth/grouper_service.rb +76 -0
- data/lib/ddr/auth/grouper_service.rb~ +77 -0
- data/lib/ddr/auth/remote_group_service.rb +35 -0
- data/lib/ddr/auth/remote_group_service.rb~ +35 -0
- data/lib/ddr/auth/superuser.rb +13 -0
- data/lib/ddr/auth/superuser.rb~ +9 -0
- data/lib/ddr/auth/user.rb +71 -0
- data/lib/ddr/auth/user.rb~ +65 -0
- data/lib/ddr/configurable.rb +34 -0
- data/lib/ddr/datastreams.rb +32 -0
- data/lib/ddr/datastreams/content_metadata_datastream.rb +147 -0
- data/lib/ddr/datastreams/datastream_behavior.rb +95 -0
- data/lib/ddr/datastreams/descriptive_metadata_datastream.rb +84 -0
- data/lib/ddr/datastreams/properties_datastream.rb +25 -0
- data/lib/ddr/datastreams/role_assignments_datastream.rb +19 -0
- data/lib/ddr/events.rb +17 -0
- data/lib/ddr/events/creation_event.rb +12 -0
- data/lib/ddr/events/event.rb +163 -0
- data/lib/ddr/events/fixity_check_event.rb +43 -0
- data/lib/ddr/events/ingestion_event.rb +12 -0
- data/lib/ddr/events/preservation_event_behavior.rb +37 -0
- data/lib/ddr/events/preservation_event_type.rb +24 -0
- data/lib/ddr/events/reindex_object_after_save.rb +18 -0
- data/lib/ddr/events/update_event.rb +9 -0
- data/lib/ddr/events/validation_event.rb +11 -0
- data/lib/ddr/events/virus_check_event.rb +30 -0
- data/lib/ddr/index_fields.rb +39 -0
- data/lib/ddr/metadata.rb +22 -0
- data/lib/ddr/metadata/duke_terms.rb +15 -0
- data/lib/ddr/metadata/premis_event.rb +59 -0
- data/lib/ddr/metadata/rdf_vocabulary_parser.rb +45 -0
- data/lib/ddr/metadata/roles_vocabulary.rb +10 -0
- data/lib/ddr/metadata/sources/duketerms.rdf.xml +856 -0
- data/lib/ddr/metadata/vocabulary.rb +37 -0
- data/lib/ddr/models.rb +60 -0
- data/lib/ddr/models/access_controllable.rb +23 -0
- data/lib/ddr/models/base.rb +37 -0
- data/lib/ddr/models/describable.rb +81 -0
- data/lib/ddr/models/engine.rb +58 -0
- data/lib/ddr/models/error.rb +12 -0
- data/lib/ddr/models/event_loggable.rb +36 -0
- data/lib/ddr/models/file_management.rb +183 -0
- data/lib/ddr/models/fixity_checkable.rb +20 -0
- data/lib/ddr/models/governable.rb +48 -0
- data/lib/ddr/models/has_attachments.rb +12 -0
- data/lib/ddr/models/has_children.rb +21 -0
- data/lib/ddr/models/has_content.rb +114 -0
- data/lib/ddr/models/has_content_metadata.rb +16 -0
- data/lib/ddr/models/has_properties.rb +15 -0
- data/lib/ddr/models/has_role_assignments.rb +17 -0
- data/lib/ddr/models/has_thumbnail.rb +27 -0
- data/lib/ddr/models/has_workflow.rb +29 -0
- data/lib/ddr/models/indexing.rb +53 -0
- data/lib/ddr/models/licensable.rb +28 -0
- data/lib/ddr/models/minted_id.rb +10 -0
- data/lib/ddr/models/permanent_identification.rb +48 -0
- data/lib/ddr/models/solr_document.rb +193 -0
- data/lib/ddr/models/version.rb +5 -0
- data/lib/ddr/notifications.rb +15 -0
- data/lib/ddr/services.rb +8 -0
- data/lib/ddr/services/id_service.rb +48 -0
- data/lib/ddr/utils.rb +153 -0
- data/lib/ddr/workflow.rb +8 -0
- data/lib/ddr/workflow/workflow_state.rb +39 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/user.rb +5 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +29 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +78 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/assets.rb +8 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +80 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +4974 -0
- data/spec/dummy/log/test.log +55627 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/attachment_factories.rb +15 -0
- data/spec/factories/collection_factories.rb +16 -0
- data/spec/factories/component_factories.rb +15 -0
- data/spec/factories/event_factories.rb +7 -0
- data/spec/factories/item_factories.rb +16 -0
- data/spec/factories/target_factories.rb +11 -0
- data/spec/factories/test_model_factories.rb +133 -0
- data/spec/factories/user_factories.rb +7 -0
- data/spec/factories/user_factories.rb~ +7 -0
- data/spec/features/grouper_integration_spec.rb~ +21 -0
- data/spec/fixtures/contentMetadata.xml +37 -0
- data/spec/fixtures/image1.tiff +0 -0
- data/spec/fixtures/image2.tiff +0 -0
- data/spec/fixtures/image3.tiff +0 -0
- data/spec/fixtures/library-devil.tiff +0 -0
- data/spec/fixtures/sample.docx +0 -0
- data/spec/fixtures/sample.pdf +0 -0
- data/spec/fixtures/target.png +0 -0
- data/spec/models/ability_spec.rb +248 -0
- data/spec/models/ability_spec.rb~ +245 -0
- data/spec/models/active_fedora_base_spec.rb +107 -0
- data/spec/models/active_fedora_datastream_spec.rb +121 -0
- data/spec/models/attachment_spec.rb +13 -0
- data/spec/models/collection_spec.rb +33 -0
- data/spec/models/component_spec.rb +8 -0
- data/spec/models/descriptive_metadata_datastream_spec.rb +102 -0
- data/spec/models/events_spec.rb +64 -0
- data/spec/models/file_management_spec.rb +179 -0
- data/spec/models/has_role_assignments_spec.rb +29 -0
- data/spec/models/has_workflow_spec.rb +54 -0
- data/spec/models/item_spec.rb +8 -0
- data/spec/models/permanent_identification_spec.rb +65 -0
- data/spec/models/role_assignments_datastream_spec.rb +25 -0
- data/spec/models/superuser_spec.rb +13 -0
- data/spec/models/superuser_spec.rb~ +13 -0
- data/spec/models/target_spec.rb +8 -0
- data/spec/models/user_spec.rb +60 -0
- data/spec/models/user_spec.rb~ +56 -0
- data/spec/services/group_service_spec.rb +75 -0
- data/spec/services/group_service_spec.rb~ +71 -0
- data/spec/services/id_service_spec.rb +33 -0
- data/spec/spec_helper.rb +125 -0
- data/spec/support/shared_examples_for_access_controllables.rb +6 -0
- data/spec/support/shared_examples_for_associations.rb +8 -0
- data/spec/support/shared_examples_for_ddr_models.rb +7 -0
- data/spec/support/shared_examples_for_describables.rb +63 -0
- data/spec/support/shared_examples_for_event_loggables.rb +3 -0
- data/spec/support/shared_examples_for_events.rb +179 -0
- data/spec/support/shared_examples_for_governables.rb +17 -0
- data/spec/support/shared_examples_for_has_content.rb +136 -0
- data/spec/support/shared_examples_for_has_content_metadata.rb +74 -0
- data/spec/support/shared_examples_for_has_properties.rb +5 -0
- data/spec/support/shared_examples_for_indexing.rb +36 -0
- metadata +562 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Ddr
|
|
2
|
+
module Configurable
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
# Base directory of external file store
|
|
7
|
+
mattr_accessor :external_file_store
|
|
8
|
+
|
|
9
|
+
# Regexp for building external file subpath from hex digest
|
|
10
|
+
mattr_accessor :external_file_subpath_regexp
|
|
11
|
+
|
|
12
|
+
# Pattern (template) for constructing noids
|
|
13
|
+
mattr_accessor :noid_template
|
|
14
|
+
|
|
15
|
+
# Noid minter state file location
|
|
16
|
+
mattr_accessor :minter_statefile
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module ClassMethods
|
|
20
|
+
def configure
|
|
21
|
+
yield self
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def external_file_subpath_pattern= (pattern)
|
|
25
|
+
unless /^-{1,2}(\/-{1,2}){0,3}$/ =~ pattern
|
|
26
|
+
raise "Invalid external file subpath pattern: #{pattern}"
|
|
27
|
+
end
|
|
28
|
+
re = pattern.split("/").map { |x| "(\\h{#{x.length}})" }.join("")
|
|
29
|
+
self.external_file_subpath_regexp = Regexp.new("^#{re}")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'active_fedora'
|
|
2
|
+
|
|
3
|
+
module Ddr
|
|
4
|
+
module Datastreams
|
|
5
|
+
extend ActiveSupport::Autoload
|
|
6
|
+
|
|
7
|
+
CONTENT = "content"
|
|
8
|
+
CONTENT_METADATA = "contentMetadata"
|
|
9
|
+
DC = "DC"
|
|
10
|
+
DEFAULT_RIGHTS = "defaultRights"
|
|
11
|
+
DESC_METADATA = "descMetadata"
|
|
12
|
+
PROPERTIES = "properties"
|
|
13
|
+
RELS_EXT = "RELS-EXT"
|
|
14
|
+
RIGHTS_METADATA = "rightsMetadata"
|
|
15
|
+
THUMBNAIL = "thumbnail"
|
|
16
|
+
|
|
17
|
+
CHECKSUM_TYPE_MD5 = "MD5"
|
|
18
|
+
CHECKSUM_TYPE_SHA1 = "SHA-1"
|
|
19
|
+
CHECKSUM_TYPE_SHA256 = "SHA-256"
|
|
20
|
+
CHECKSUM_TYPE_SHA384 = "SHA-384"
|
|
21
|
+
CHECKSUM_TYPE_SHA512 = "SHA-512"
|
|
22
|
+
|
|
23
|
+
CHECKSUM_TYPES = [ CHECKSUM_TYPE_MD5, CHECKSUM_TYPE_SHA1, CHECKSUM_TYPE_SHA256, CHECKSUM_TYPE_SHA384, CHECKSUM_TYPE_SHA512 ]
|
|
24
|
+
|
|
25
|
+
autoload :ContentMetadataDatastream
|
|
26
|
+
autoload :DescriptiveMetadataDatastream
|
|
27
|
+
autoload :PropertiesDatastream
|
|
28
|
+
autoload :DatastreamBehavior
|
|
29
|
+
autoload :RoleAssignmentsDatastream
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
module Ddr
|
|
2
|
+
module Datastreams
|
|
3
|
+
class ContentMetadataDatastream < ActiveFedora::Datastream
|
|
4
|
+
|
|
5
|
+
def parse
|
|
6
|
+
parsed = []
|
|
7
|
+
cm = Nokogiri::XML(self.content)
|
|
8
|
+
fileSec_nodes = cm.xpath("//xmlns:fileSec")
|
|
9
|
+
structMap_nodes = cm.xpath("//xmlns:structMap").sort{ |x,y| sort_nodes(x, y) }
|
|
10
|
+
structMap_nodes.each do |structMap_node|
|
|
11
|
+
structMap_hash = {}
|
|
12
|
+
div_nodes = structMap_node.xpath("xmlns:div").sort{ |x,y| sort_nodes(x,y) }
|
|
13
|
+
div_array = []
|
|
14
|
+
div_nodes.each do |div_node|
|
|
15
|
+
div_array << parse_div(fileSec_nodes, div_node)
|
|
16
|
+
end
|
|
17
|
+
structMap_hash["div"] = div_array
|
|
18
|
+
parsed << structMap_hash
|
|
19
|
+
end
|
|
20
|
+
return parsed
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_solr(solr_doc=Hash.new)
|
|
24
|
+
solr_doc = super(solr_doc)
|
|
25
|
+
if self.content
|
|
26
|
+
solr_doc.merge!({Ddr::IndexFields::CONTENT_METADATA_PARSED => parse.to_json})
|
|
27
|
+
end
|
|
28
|
+
solr_doc
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def first_pid
|
|
32
|
+
find_first_pid(parse.first)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def find_first_pid(structure)
|
|
38
|
+
case
|
|
39
|
+
when structure.has_key?("div")
|
|
40
|
+
find_first_pid(structure["div"].first)
|
|
41
|
+
when structure.has_key?("pids")
|
|
42
|
+
structure["pids"].first["pid"]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def walk_structure_to_pid(structure)
|
|
47
|
+
if structure.has_key("div")
|
|
48
|
+
walk_structure_div(structure["div"])
|
|
49
|
+
else
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def parse_div(fileSec_nodes, div_node)
|
|
55
|
+
div_hash = {}
|
|
56
|
+
div_hash["label"] = div_node["LABEL"] unless div_node["LABEL"].nil?
|
|
57
|
+
div_hash["orderlabel"] = div_node["ORDERLABEL"] unless div_node["ORDERLABEL"].nil?
|
|
58
|
+
div_hash["type"] = div_node["TYPE"] unless div_node["TYPE"].nil?
|
|
59
|
+
div_subnodes = div_node.xpath("xmlns:div").sort{ |x,y| sort_nodes(x, y) }
|
|
60
|
+
if div_subnodes.empty?
|
|
61
|
+
fptr_nodes = div_node.xpath("xmlns:fptr")
|
|
62
|
+
fptr_array = []
|
|
63
|
+
fptr_nodes.each do |fptr_node|
|
|
64
|
+
fptr_hash = {}
|
|
65
|
+
if !fptr_node["FILEID"].nil?
|
|
66
|
+
pid = get_pid(fileSec_nodes, fptr_node["FILEID"])
|
|
67
|
+
file_use = get_use(fileSec_nodes, fptr_node["FILEID"])
|
|
68
|
+
fptr_hash["pid"] = pid unless pid.nil?
|
|
69
|
+
fptr_hash["use"] = file_use unless file_use.nil?
|
|
70
|
+
end
|
|
71
|
+
fptr_array << fptr_hash
|
|
72
|
+
end
|
|
73
|
+
div_hash["pids"] = fptr_array
|
|
74
|
+
else
|
|
75
|
+
div_array = []
|
|
76
|
+
div_subnodes.each do |div_subnode|
|
|
77
|
+
div_array << parse_div(fileSec_nodes, div_subnode)
|
|
78
|
+
end
|
|
79
|
+
div_hash["div"] = div_array
|
|
80
|
+
end
|
|
81
|
+
return div_hash
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def get_use(fileSec_nodes, file_id)
|
|
85
|
+
file_nodes = fileSec_nodes.xpath("//xmlns:file[@ID='#{file_id}']")
|
|
86
|
+
file_node =
|
|
87
|
+
case file_nodes.size
|
|
88
|
+
when 1
|
|
89
|
+
file_nodes.first
|
|
90
|
+
when 0
|
|
91
|
+
raise "Matching file node not found"
|
|
92
|
+
else
|
|
93
|
+
raise "Multiple matching file nodes found"
|
|
94
|
+
end
|
|
95
|
+
return find_use(file_node)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def find_use(node)
|
|
99
|
+
file_use = nil
|
|
100
|
+
if node["USE"].nil?
|
|
101
|
+
file_use = find_use(node.parent) unless node.name.eql?("fileGrp")
|
|
102
|
+
else
|
|
103
|
+
file_use = node["USE"]
|
|
104
|
+
end
|
|
105
|
+
return file_use
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def get_pid(fileSec_nodes, file_id)
|
|
109
|
+
file_nodes = fileSec_nodes.xpath("//xmlns:file[@ID='#{file_id}']")
|
|
110
|
+
file_node =
|
|
111
|
+
case file_nodes.size
|
|
112
|
+
when 1
|
|
113
|
+
file_nodes.first
|
|
114
|
+
when 0
|
|
115
|
+
raise "Matching file node not found"
|
|
116
|
+
else
|
|
117
|
+
raise "Multiple matching file nodes found"
|
|
118
|
+
end
|
|
119
|
+
fLocat_nodes = file_node.xpath("xmlns:FLocat")
|
|
120
|
+
fLocat_node =
|
|
121
|
+
case fLocat_nodes.size
|
|
122
|
+
when 1
|
|
123
|
+
fLocat_nodes.first
|
|
124
|
+
when 0
|
|
125
|
+
raise "FLocat node not found"
|
|
126
|
+
else
|
|
127
|
+
raise "Multiple FLocat nodes found"
|
|
128
|
+
end
|
|
129
|
+
href = fLocat_node["xlink:href"]
|
|
130
|
+
pid = href.split('/')[0]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def sort_nodes(node_1, node_2)
|
|
134
|
+
if node_1["ORDER"].nil? && node_2["ORDER"].nil?
|
|
135
|
+
return 0
|
|
136
|
+
elsif node_1["ORDER"].nil?
|
|
137
|
+
return 1
|
|
138
|
+
elsif node_2["ORDER"].nil?
|
|
139
|
+
return -1
|
|
140
|
+
else
|
|
141
|
+
return node_1["ORDER"].to_i <=> node_2["ORDER"].to_i
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module Ddr
|
|
2
|
+
module Datastreams
|
|
3
|
+
module DatastreamBehavior
|
|
4
|
+
|
|
5
|
+
DEFAULT_FILE_EXTENSION = "bin"
|
|
6
|
+
|
|
7
|
+
STRFTIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%LZ"
|
|
8
|
+
|
|
9
|
+
def validate_checksum! checksum, checksum_type=nil
|
|
10
|
+
raise Ddr::Models::Error, "Checksum cannot be validated on new datastream." if new?
|
|
11
|
+
raise Ddr::Models::Error, "Checksum cannot be validated on unpersisted content." if content_changed?
|
|
12
|
+
raise Ddr::Models::ChecksumInvalid, "The repository internal checksum validation failed." unless dsChecksumValid
|
|
13
|
+
algorithm = checksum_type || self.checksumType
|
|
14
|
+
ds_checksum = if algorithm == self.checksumType
|
|
15
|
+
self.checksum
|
|
16
|
+
else
|
|
17
|
+
content_digest(algorithm)
|
|
18
|
+
end
|
|
19
|
+
if checksum == ds_checksum
|
|
20
|
+
"The checksum [#{algorithm}]#{checksum} is valid for datastream #{version_info}."
|
|
21
|
+
else
|
|
22
|
+
raise Ddr::Models::ChecksumInvalid, "The checksum [#{algorithm}]#{checksum} is not valid for datastream #{version_info}."
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def version_uri
|
|
27
|
+
# E.g., info:fedora/duke:1/content/content.0
|
|
28
|
+
["info:fedora", pid, dsid, dsVersionID].join("/") unless new?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def version_info
|
|
32
|
+
# E.g., info:fedora/duke:1/content/content.0 [2013-09-26T20:00:03.357Z]
|
|
33
|
+
"#{version_uri} [#{Ddr::Utils.ds_as_of_date_time(self)}]" unless new?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def create_date_string
|
|
37
|
+
dsCreateDate.strftime(STRFTIME_FORMAT) if dsCreateDate
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def content_digest algorithm
|
|
41
|
+
Ddr::Utils.digest(self.content, algorithm)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Returns a list of the external file paths for all versions of the datastream.
|
|
45
|
+
def file_paths
|
|
46
|
+
raise "The `file_paths' method is valid only for external datastreams." unless external?
|
|
47
|
+
return Array(file_path) if new?
|
|
48
|
+
versions.map(&:file_path).compact
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns the external file path for the datastream.
|
|
52
|
+
# Returns nil if dsLocation is not a file URI.
|
|
53
|
+
def file_path
|
|
54
|
+
raise "The `file_path' method is valid only for external datastreams." unless external?
|
|
55
|
+
Ddr::Utils.path_from_uri(dsLocation) if Ddr::Utils.file_uri?(dsLocation)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns the file name of the external file for the datastream.
|
|
59
|
+
# See #external_datastream_file_path(ds)
|
|
60
|
+
def file_name
|
|
61
|
+
raise "The `file_name' method is valid only for external datastreams." unless external?
|
|
62
|
+
File.basename(file_path) rescue nil
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Returns the size of the external file for the datastream.
|
|
66
|
+
def file_size
|
|
67
|
+
raise "The `file_size' method is valid only for external datastreams." unless external?
|
|
68
|
+
File.size(file_path) rescue nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Return default file extension for datastream based on MIME type
|
|
72
|
+
def default_file_extension
|
|
73
|
+
mimetypes = MIME::Types[mimeType]
|
|
74
|
+
return mimetypes.first.extensions.first unless mimetypes.empty?
|
|
75
|
+
case mimeType
|
|
76
|
+
when 'application/n-triples'
|
|
77
|
+
'txt'
|
|
78
|
+
else
|
|
79
|
+
DEFAULT_FILE_EXTENSION
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Return default file name prefix based on object PID
|
|
84
|
+
def default_file_prefix
|
|
85
|
+
[pid.sub(/:/, '_'), dsid].join("_")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Return default file name
|
|
89
|
+
def default_file_name
|
|
90
|
+
[default_file_prefix, default_file_extension].join(".")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module Ddr
|
|
2
|
+
module Datastreams
|
|
3
|
+
class DescriptiveMetadataDatastream < ActiveFedora::NtriplesRDFDatastream
|
|
4
|
+
|
|
5
|
+
class_attribute :vocabularies
|
|
6
|
+
self.vocabularies = [RDF::DC, Ddr::Metadata::DukeTerms].freeze
|
|
7
|
+
|
|
8
|
+
def self.default_attributes
|
|
9
|
+
super.merge(:mimeType => 'application/n-triples')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.indexers
|
|
13
|
+
# Add term_name => [indexers] mapping to customize indexing
|
|
14
|
+
{}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.default_indexers
|
|
18
|
+
[:stored_searchable]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.indexers_for(term_name)
|
|
22
|
+
indexers.fetch(term_name, default_indexers)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.term_names
|
|
26
|
+
terms = []
|
|
27
|
+
vocabularies.each do |vocab|
|
|
28
|
+
terms |= Ddr::Metadata::Vocabulary.term_names(vocab)
|
|
29
|
+
end
|
|
30
|
+
terms.sort
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Add terms from the vocabularies as properties
|
|
34
|
+
vocabularies.each do |vocab|
|
|
35
|
+
vocab.each do |term|
|
|
36
|
+
term_name = Ddr::Metadata::Vocabulary.term_name(vocab, term)
|
|
37
|
+
property term_name, predicate: term do |index|
|
|
38
|
+
index.as *indexers_for(term_name)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns ActiveFedora::Rdf::Term now that this is an RDF datastream
|
|
44
|
+
def values term
|
|
45
|
+
term == :format ? self.format : self.send(term)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Update term with values
|
|
49
|
+
# Note that empty values (nil or "") are rejected from values array
|
|
50
|
+
def set_values term, values
|
|
51
|
+
if values.respond_to?(:reject!)
|
|
52
|
+
values.reject! { |v| v.blank? }
|
|
53
|
+
else
|
|
54
|
+
values = nil if values.blank?
|
|
55
|
+
end
|
|
56
|
+
begin
|
|
57
|
+
self.send("#{term}=", values)
|
|
58
|
+
rescue NoMethodError
|
|
59
|
+
raise ArgumentError, "No such term: #{term}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Add value to term
|
|
64
|
+
# Note that empty value (nil or "") is not added
|
|
65
|
+
def add_value term, value
|
|
66
|
+
begin
|
|
67
|
+
unless value.blank?
|
|
68
|
+
values = values(term).to_a << value
|
|
69
|
+
set_values term, values
|
|
70
|
+
end
|
|
71
|
+
rescue NoMethodError
|
|
72
|
+
raise ArgumentError, "No such term: #{term}"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Override ActiveFedora::Rdf::Indexing#apply_prefix(name) to not
|
|
77
|
+
# prepend the index field name with a string based on the datastream id.
|
|
78
|
+
def apply_prefix(name)
|
|
79
|
+
name
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Ddr
|
|
2
|
+
module Datastreams
|
|
3
|
+
class PropertiesDatastream < ActiveFedora::OmDatastream
|
|
4
|
+
|
|
5
|
+
set_terminology do |t|
|
|
6
|
+
t.root(:path => "fields")
|
|
7
|
+
t.original_filename
|
|
8
|
+
t.permanent_id
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def prefix
|
|
12
|
+
# Squash AF 8.0 deprecation warning
|
|
13
|
+
""
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.xml_template
|
|
17
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
|
18
|
+
xml.fields
|
|
19
|
+
end
|
|
20
|
+
builder.doc
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Ddr
|
|
2
|
+
module Datastreams
|
|
3
|
+
class RoleAssignmentsDatastream < ActiveFedora::NtriplesRDFDatastream
|
|
4
|
+
|
|
5
|
+
vocabulary = Ddr::Metadata::RolesVocabulary
|
|
6
|
+
|
|
7
|
+
vocabulary.each do |term|
|
|
8
|
+
property Ddr::Metadata::Vocabulary.term_name(vocabulary, term), predicate: term do |index|
|
|
9
|
+
index.as :symbol
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def principal_has_role?(principal, role)
|
|
14
|
+
(send(role) & Array(principal)).any?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/ddr/events.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Ddr
|
|
2
|
+
module Events
|
|
3
|
+
extend ActiveSupport::Autoload
|
|
4
|
+
|
|
5
|
+
autoload :Event
|
|
6
|
+
autoload :CreationEvent
|
|
7
|
+
autoload :FixityCheckEvent
|
|
8
|
+
autoload :IngestionEvent
|
|
9
|
+
autoload :UpdateEvent
|
|
10
|
+
autoload :ValidationEvent
|
|
11
|
+
autoload :VirusCheckEvent
|
|
12
|
+
autoload :PreservationEventType
|
|
13
|
+
autoload :PreservationEventBehavior
|
|
14
|
+
autoload :ReindexObjectAfterSave
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|