ddr-models 2.8.0 → 2.9.0.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4826c97c7faaee06b8ecd52dc5a322bc5a56acb9
4
- data.tar.gz: 42e1c7666e775cd37451848e53cc07e378022d77
3
+ metadata.gz: 0cc0364fbbf04479e361ddf450e21d70aa9d9f21
4
+ data.tar.gz: a18facc359b48603080daf6cbf8f82b22e41a15e
5
5
  SHA512:
6
- metadata.gz: 1e6d24131304e7d017acd556de2db085496b103f59f58dc5d8350d9a9e95caea811254dc44be950c758629fcc97665a971803926a7ee5d1ef263e73f07fa064b
7
- data.tar.gz: a13fa84b44a46e9890135443b36780d30e39c3923ed7eed54712b29069b556a5f94e6dfb87833103950600088f66e4dfe85143e5fd43f4b529e74652a4fc0148
6
+ metadata.gz: 08988037c01145241f52c2914b5f0330d93b79865e1effbdcea509f79b42b2a926956ec8aa049b406a788385d534f252f180aad054899618175598eefd1fcc87
7
+ data.tar.gz: 4bdc44aaf67465193eac2c5302a5f30abcefe6b60df8bb44653083f8f3f0441346a907df6a7b74fa53c880dd8cf9820537ca1365a0ca8d9802c7d5f7233c6864
@@ -1,3 +1,4 @@
1
+ require 'htmlentities'
1
2
  #
2
3
  # A Collection is a conceptual and administrative entity containing a set of items.
3
4
  #
@@ -51,6 +52,10 @@ class Collection < Ddr::Models::Base
51
52
  true
52
53
  end
53
54
 
55
+ def default_structure
56
+ build_default_structure
57
+ end
58
+
54
59
  private
55
60
 
56
61
  def default_roles
@@ -69,4 +74,54 @@ class Collection < Ddr::Models::Base
69
74
  save!
70
75
  end
71
76
 
77
+ def build_default_structure
78
+ document = Ddr::Models::Structure.xml_template
79
+ structure = Ddr::Models::Structure.new(document)
80
+ metshdr = structure.add_metshdr
81
+ structure.add_agent(parent: metshdr, role: Ddr::Models::Structures::Agent::ROLE_CREATOR,
82
+ name: Ddr::Models::Structures::Agent::NAME_REPOSITORY_DEFAULT)
83
+ structmap = structure.add_structmap(type: Ddr::Models::Structure::TYPE_DEFAULT)
84
+ add_items_to_structure(structure, structmap)
85
+ structure
86
+ end
87
+
88
+ def add_items_to_structure(structure, structmap)
89
+ sorted_items_for_structure.each do |item|
90
+ if path = item[Ddr::Index::Fields::NESTED_PATH]
91
+ nest = path.split(File::SEPARATOR)
92
+ else
93
+ nest = []
94
+ end
95
+ find_or_create_div(structure, structmap, nest, item[Ddr::Index::Fields::PERMANENT_ID])
96
+ end
97
+ end
98
+
99
+ def find_or_create_div(structure, parent, nest, permanent_id)
100
+ label = nest.shift
101
+ order = parent.elements.count + 1
102
+ if nest.empty?
103
+ div = structure.add_div(parent: parent, order: order)
104
+ add_mptr(structure, div, permanent_id)
105
+ else
106
+ label = HTMLEntities.new.encode(label)
107
+ div = parent.xpath(%Q[xmlns:div[@LABEL="#{label}"]]).first ||
108
+ structure.add_div(parent: parent, type: 'Directory', label: label, order: order)
109
+ find_or_create_div(structure, div, nest, permanent_id)
110
+ end
111
+ end
112
+
113
+ def add_mptr(structure, div, permanent_id)
114
+ structure.add_mptr(parent: div, href: permanent_id)
115
+ end
116
+
117
+ def sorted_items_for_structure
118
+ ActiveFedora::SolrService.query(association_query(:children), sort: item_sort_for_structure, rows: 999999)
119
+ end
120
+
121
+ def item_sort_for_structure
122
+ "#{Ddr::Index::Fields::NESTED_PATH} ASC,
123
+ #{Ddr::Index::Fields::LOCAL_ID} ASC,
124
+ #{Ddr::Index::Fields::OBJECT_CREATE_DATE} ASC"
125
+ end
126
+
72
127
  end
@@ -5,6 +5,7 @@
5
5
  #
6
6
  class Component < Ddr::Models::Base
7
7
 
8
+ include Ddr::Models::Captionable
8
9
  include Ddr::Models::HasContent
9
10
  include Ddr::Models::HasIntermediateFile
10
11
  include Ddr::Models::HasMultiresImage
@@ -17,6 +18,10 @@ class Component < Ddr::Models::Base
17
18
  alias_method :item, :parent
18
19
  alias_method :item=, :parent=
19
20
 
21
+ STRUCTURALLY_RELEVANT_DATASTREAMS = [ Ddr::Datastreams::CAPTION, Ddr::Datastreams::CONTENT,
22
+ Ddr::Datastreams::INTERMEDIATE_FILE, Ddr::Datastreams::MULTIRES_IMAGE,
23
+ Ddr::Datastreams::STREAMABLE_MEDIA, Ddr::Datastreams::THUMBNAIL ]
24
+
20
25
  def collection
21
26
  self.parent.parent rescue nil
22
27
  end
@@ -30,7 +35,7 @@ class Component < Ddr::Models::Base
30
35
  end
31
36
 
32
37
  def default_structure
33
- build_default_structure if has_content?
38
+ build_default_structure
34
39
  end
35
40
 
36
41
  private
@@ -41,19 +46,24 @@ class Component < Ddr::Models::Base
41
46
  metshdr = structure.add_metshdr
42
47
  structure.add_agent(parent: metshdr, role: Ddr::Models::Structures::Agent::ROLE_CREATOR,
43
48
  name: Ddr::Models::Structures::Agent::NAME_REPOSITORY_DEFAULT)
44
- filesec = structure.add_filesec
45
49
  structmap = structure.add_structmap(type: Ddr::Models::Structure::TYPE_DEFAULT)
46
- div = structure.add_div(parent: structmap)
47
- filegrp = structure.add_filegrp(parent: filesec)
48
- add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_ORIGINAL_FILE,
49
- Ddr::Datastreams::CONTENT)
50
- add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_PRESERVATION_MASTER_FILE,
51
- Ddr::Datastreams::CONTENT)
52
- add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_INTERMEDIATE_FILE,
53
- Ddr::Datastreams::INTERMEDIATE_FILE) if has_intermediate_file?
54
- add_service_file_uses_to_default_structure(structure, filegrp, div)
55
- add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_THUMBNAIL_IMAGE,
56
- Ddr::Datastreams::THUMBNAIL) if has_thumbnail?
50
+ if has_content?
51
+ filesec = structure.add_filesec
52
+ div = structure.add_div(parent: structmap)
53
+ filegrp = structure.add_filegrp(parent: filesec)
54
+ add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_ORIGINAL_FILE,
55
+ Ddr::Datastreams::CONTENT)
56
+ add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_PRESERVATION_MASTER_FILE,
57
+ Ddr::Datastreams::CONTENT)
58
+ add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_INTERMEDIATE_FILE,
59
+ Ddr::Datastreams::INTERMEDIATE_FILE) if has_intermediate_file?
60
+ add_service_file_uses_to_default_structure(structure, filegrp, div)
61
+ add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_THUMBNAIL_IMAGE,
62
+ Ddr::Datastreams::THUMBNAIL) if has_thumbnail?
63
+ add_use_to_structure(structure, filegrp, div, Ddr::Models::Structure::USE_TRANSCRIPT,
64
+ Ddr::Datastreams::CAPTION) if captioned?
65
+
66
+ end
57
67
  structure
58
68
  end
59
69
 
data/app/models/item.rb CHANGED
@@ -11,6 +11,8 @@ class Item < Ddr::Models::Base
11
11
  has_many :children, property: :is_part_of, class_name: 'Component'
12
12
  belongs_to :parent, property: :is_member_of_collection, class_name: 'Collection'
13
13
 
14
+ has_attributes :nested_path, datastream: Ddr::Datastreams::ADMIN_METADATA, multiple: false
15
+
14
16
  alias_method :components, :children
15
17
  alias_method :component_ids, :child_ids
16
18
 
@@ -37,4 +39,30 @@ class Item < Ddr::Models::Base
37
39
  children_having_extracted_text.docs.map(&:extracted_text).flatten
38
40
  end
39
41
 
42
+ def default_structure
43
+ build_default_structure
44
+ end
45
+
46
+ private
47
+
48
+ def build_default_structure
49
+ document = Ddr::Models::Structure.xml_template
50
+ structure = Ddr::Models::Structure.new(document)
51
+ metshdr = structure.add_metshdr
52
+ structure.add_agent(parent: metshdr, role: Ddr::Models::Structures::Agent::ROLE_CREATOR,
53
+ name: Ddr::Models::Structures::Agent::NAME_REPOSITORY_DEFAULT)
54
+ structmap = structure.add_structmap(type: Ddr::Models::Structure::TYPE_DEFAULT)
55
+ add_components_to_structure(structure, structmap)
56
+ structure
57
+ end
58
+
59
+ def add_components_to_structure(structure, structmap)
60
+ count = 0
61
+ sorted_children.each do |child|
62
+ count += 1
63
+ div = structure.add_div(parent: structmap, order: count)
64
+ structure.add_mptr(parent: div, href: child[Ddr::Index::Fields::PERMANENT_ID])
65
+ end
66
+ end
67
+
40
68
  end
@@ -69,6 +69,14 @@ module ActiveFedora
69
69
  can_have_thumbnail? && thumbnail.has_content?
70
70
  end
71
71
 
72
+ def captionable?
73
+ datastreams.include? Ddr::Datastreams::CAPTION
74
+ end
75
+
76
+ def captioned?
77
+ captionable? && datastreams[Ddr::Datastreams::CAPTION].has_content?
78
+ end
79
+
72
80
  def can_be_streamable?
73
81
  datastreams.include? Ddr::Datastreams::STREAMABLE_MEDIA
74
82
  end
@@ -5,6 +5,7 @@ module Ddr
5
5
  extend ActiveSupport::Autoload
6
6
 
7
7
  ADMIN_METADATA = "adminMetadata"
8
+ CAPTION = "caption"
8
9
  CONTENT = "content"
9
10
  DC = "DC"
10
11
  DESC_METADATA = "descMetadata"
@@ -29,6 +30,7 @@ module Ddr
29
30
  CHECKSUM_TYPES = [ CHECKSUM_TYPE_MD5, CHECKSUM_TYPE_SHA1, CHECKSUM_TYPE_SHA256, CHECKSUM_TYPE_SHA384, CHECKSUM_TYPE_SHA512 ]
30
31
 
31
32
  autoload :AdministrativeMetadataDatastream
33
+ autoload :CaptionDatastream
32
34
  autoload :ContentDatastream
33
35
  autoload :DatastreamBehavior
34
36
  autoload :DeleteExternalFiles
@@ -15,6 +15,9 @@ module Ddr
15
15
  index.as :stored_sortable
16
16
  end
17
17
 
18
+ property :nested_path,
19
+ predicate: Ddr::Vocab::Asset.nestedPath
20
+
18
21
  property :workflow_state,
19
22
  predicate: Ddr::Vocab::Asset.workflowState
20
23
 
@@ -0,0 +1,5 @@
1
+ module Ddr::Datastreams
2
+ class CaptionDatastream < ExternalFileDatastream
3
+
4
+ end
5
+ end
@@ -74,6 +74,8 @@ module Ddr::Index
74
74
  MEDIA_TYPE = Field.new :content_media_type, :symbol
75
75
  MEDIUM_FACET = Field.new :medium_facet, :facetable
76
76
  MULTIRES_IMAGE_FILE_PATH = Field.new :multires_image_file_path, :stored_sortable
77
+ NESTED_PATH = Field.new :nested_path, :stored_sortable
78
+ NESTED_PATH_TEXT = Field.new :nested_path_text, :searchable
77
79
  OBJECT_PROFILE = Field.new :object_profile, :displayable
78
80
  OBJECT_STATE = Field.new :object_state, :stored_sortable
79
81
  OBJECT_CREATE_DATE = Field.new :system_create, :stored_sortable, type: :date
data/lib/ddr/models.rb CHANGED
@@ -37,6 +37,7 @@ module Ddr
37
37
  autoload :AdminSet
38
38
  autoload :Base
39
39
  autoload :Cache
40
+ autoload :Captionable
40
41
  autoload :ChecksumInvalid, 'ddr/models/error'
41
42
  autoload :Contact
42
43
  autoload :ContentModelError, 'ddr/models/error'
@@ -134,15 +135,36 @@ module Ddr
134
135
  # Maps file extensions to preferred media types
135
136
  mattr_accessor :preferred_media_types do
136
137
  {
137
- '.mp4' => 'video/mp4',
138
- '.flv' => 'video/flv',
139
- '.webm' => 'video/webm',
140
138
  '.aac' => 'audio/mp4',
141
- '.m4a' => 'audio/mp4',
142
139
  '.f4a' => 'audio/mp4',
140
+ '.flv' => 'video/flv',
141
+ '.m4a' => 'audio/mp4',
142
+ '.mov' => 'video/quicktime',
143
143
  '.mp3' => 'audio/mpeg',
144
- '.ogg' => 'audio/ogg',
144
+ '.mp4' => 'video/mp4',
145
145
  '.oga' => 'audio/ogg',
146
+ '.ogg' => 'audio/ogg',
147
+ '.srt' => 'text/plain',
148
+ '.vtt' => 'text/vtt',
149
+ '.wav' => 'audio/wav',
150
+ '.webm' => 'video/webm',
151
+ '.zip' => 'application/zip'
152
+ }
153
+ end
154
+
155
+ # Maps media types to preferred file extensions
156
+ mattr_accessor :preferred_file_extensions do
157
+ {
158
+ 'application/zip' => 'zip',
159
+ 'audio/mp4' => 'm4a',
160
+ 'audio/mpeg' => 'mp3',
161
+ 'audio/ogg' => 'ogg',
162
+ 'audio/wav' => 'wav',
163
+ 'text/vtt' => 'vtt',
164
+ 'video/flv' => 'flv',
165
+ 'video/mp4' => 'mp4',
166
+ 'video/quicktime' => 'mov',
167
+ 'video/webm' => 'webm'
146
168
  }
147
169
  end
148
170
 
@@ -31,8 +31,8 @@ module Ddr
31
31
  before_create :set_ingested_by, if: :performed_by, unless: :ingested_by
32
32
  before_create :grant_default_roles
33
33
 
34
- after_create :notify_ingest
35
34
  after_create :assign_permanent_id!, if: :assign_permanent_id?
35
+ after_create :notify_ingest
36
36
 
37
37
  around_save :notify_update, unless: :new_record?
38
38
 
@@ -95,6 +95,10 @@ module Ddr
95
95
  datastreams.select { |dsid, ds| ds.changed? }
96
96
  end
97
97
 
98
+ def new_datastreams_having_content
99
+ datastreams.select { |dsid, ds| ds.new? && ds.has_content? }
100
+ end
101
+
98
102
  def datastreams_having_content
99
103
  datastreams.select { |dsid, ds| ds.has_content? }
100
104
  end
@@ -108,6 +112,12 @@ module Ddr
108
112
  end
109
113
  end
110
114
 
115
+ def parent_id
116
+ parent.id
117
+ rescue NoMethodError
118
+ nil
119
+ end
120
+
111
121
  private
112
122
 
113
123
  def grant_default_roles
@@ -141,7 +151,9 @@ module Ddr
141
151
  .merge(pid: pid,
142
152
  user_key: performed_by,
143
153
  permanent_id: permanent_id,
144
- model: self.class.to_s)
154
+ model: self.class.to_s,
155
+ parent: parent_id,
156
+ skip_structure_updates: cache.fetch(:skip_structure_updates, false))
145
157
  end
146
158
 
147
159
  def notify_ingest
@@ -156,6 +168,7 @@ module Ddr
156
168
  event_params = default_notification_payload.merge(
157
169
  attributes_changed: changes,
158
170
  datastreams_changed: datastreams_changed.keys,
171
+ new_datastreams: new_datastreams_having_content.keys,
159
172
  skip_update_derivatives: cache.fetch(:skip_update_derivatives, false)
160
173
  )
161
174
  ActiveSupport::Notifications.instrument(UPDATE, event_params) do |payload|
@@ -0,0 +1,37 @@
1
+ module Ddr::Models
2
+ module Captionable
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_file_datastream name: Ddr::Datastreams::CAPTION,
7
+ type: Ddr::Datastreams::CaptionDatastream,
8
+ versionable: true,
9
+ label: "Caption file for this object",
10
+ control_group: "E"
11
+ end
12
+
13
+ def caption_type
14
+ datastreams[Ddr::Datastreams::CAPTION].mimeType
15
+ end
16
+
17
+ def caption_extension
18
+ extensions = Ddr::Models.preferred_file_extensions
19
+ if extensions.include? caption_type
20
+ extensions[caption_type]
21
+ else
22
+ caption_extension_default
23
+ end
24
+ end
25
+
26
+ def caption_path
27
+ datastreams[Ddr::Datastreams::CAPTION].file_path
28
+ end
29
+
30
+ private
31
+
32
+ def caption_extension_default
33
+ datastreams[Ddr::Datastreams::CAPTION].default_file_extension
34
+ end
35
+
36
+ end
37
+ end
@@ -8,38 +8,10 @@ module Ddr
8
8
  ActiveFedora::SolrService.lazy_reify_solr_results(sorted_children).first
9
9
  end
10
10
 
11
- def default_structure
12
- if children.present?
13
- build_default_structure
14
- end
15
- end
16
-
17
11
  def sorted_children
18
12
  ActiveFedora::SolrService.query(association_query(:children), sort: DEFAULT_SORT, rows: 999999)
19
13
  end
20
14
 
21
- private
22
-
23
- def build_default_structure
24
- document = Ddr::Models::Structure.xml_template
25
- structure = Ddr::Models::Structure.new(document)
26
- metshdr = structure.add_metshdr
27
- structure.add_agent(parent: metshdr, role: Ddr::Models::Structures::Agent::ROLE_CREATOR,
28
- name: Ddr::Models::Structures::Agent::NAME_REPOSITORY_DEFAULT)
29
- structmap = structure.add_structmap(type: Ddr::Models::Structure::TYPE_DEFAULT)
30
- add_children(structure, structmap, sorted_children)
31
- structure
32
- end
33
-
34
- def add_children(structure, structmap, children)
35
- count = 0
36
- children.each do |child|
37
- count += 1
38
- div = structure.add_div(parent: structmap, order: count)
39
- structure.add_mptr(parent: div, href: child[Ddr::Index::Fields::PERMANENT_ID])
40
- end
41
- end
42
-
43
15
  end
44
16
  end
45
17
  end
@@ -13,6 +13,29 @@ module Ddr
13
13
  include FileManagement
14
14
  end
15
15
 
16
+ def intermediate_type
17
+ datastreams[Ddr::Datastreams::INTERMEDIATE_FILE].mimeType
18
+ end
19
+
20
+ def intermediate_extension
21
+ extensions = Ddr::Models.preferred_file_extensions
22
+ if extensions.include? intermediate_type
23
+ extensions[intermediate_type]
24
+ else
25
+ intermediate_extension_default
26
+ end
27
+ end
28
+
29
+ def intermediate_path
30
+ datastreams[Ddr::Datastreams::INTERMEDIATE_FILE].file_path
31
+ end
32
+
33
+ private
34
+
35
+ def intermediate_extension_default
36
+ datastreams[Ddr::Datastreams::INTERMEDIATE_FILE].default_file_extension
37
+ end
38
+
16
39
  end
17
40
  end
18
41
  end