valkyrie 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7439f8be7099e4b54998826abda9222d07226ff7a54fdb868f2ab7d99596fd56
4
- data.tar.gz: 866c57941b2e2604a8d7bd8b013e0b31c07dd909404733cfb7043c61412389ad
3
+ metadata.gz: 3bd57af32d07a78e2ac9a9a1c6217b8b601018413c1a08a67762565f92da91cd
4
+ data.tar.gz: 58e0073f9ef70694e77d016cf08869d90b920f2fca3a7c42e7141289a8b7121d
5
5
  SHA512:
6
- metadata.gz: 89d1857a2f40c0d8c32c6a31a9ff1247e9b8c32aa84e917c77c3d89e6a0cb52c7548802852914ddcf11d9805f3cf0b6784331f937cf9004b18e63ecb27449971
7
- data.tar.gz: 5b143107a9ca53b86c83c5ba884635fb869919a7641c1373324193f9ac918684557177cf2c2519f5d8eeb0420bd48404037da5fb46c84d5a17bda0e4381b72f7
6
+ metadata.gz: 939dbb151e2cb770e9bfbac0cedbfc78a160ace0f3f1c482560659f1a6cd16ad0984ae1eb15caf49d4ef5926f3a01721e032f7c8363ea815e935064eb547f7c0
7
+ data.tar.gz: d2b295e1881cc0d8d45e1c69e6255fab7b5be4d3e277d3e01eaa53498ca7346131ac1c2180d73f675c93b9b4a03d73316b9f6a8256b6b40a7492dda8c088d16a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # v3.3.0 2024-07-03
2
+
3
+ ## Changes since last release
4
+
5
+ * Add support for configurable pairtree IDs in Fedora 6. ([randalldfloyd](https://github.com/randalldfloyd))
6
+
1
7
  # v3.2.0 2024-04-10
2
8
 
3
9
  ## Changes since last release
data/README.md CHANGED
@@ -234,6 +234,39 @@ config. If Fedora requires auth, you can also include that in the URL, e.g.:
234
234
  fedora_version: 5
235
235
  )
236
236
  ```
237
+ #### Pairtree paths in Fedora 4/6
238
+ Fedora 4 and 6.5+ support automatic creation of "pairtree" paths, which means that identifiers are stored in
239
+ a hashed directory structure to avoid excessive child nodes directly in the root node.
240
+
241
+ Unlike Fedora 4 where this is the default behavior, it has to be enabled via options in Fedora 6.5. This is
242
+ done by configuring both the count and length of the pairtree algorithm, so it needs to be configured
243
+ in the Fedora adapters so that both sides match.
244
+
245
+ In the following example, Fedora 6.5 is being started with options to create pairtree paths consisting of
246
+ 4 segments, 2 characters in length:
247
+
248
+ ```angular2html
249
+ CATALINA_OPTS=-Dfcrepo.home=/fcrepo-home ...
250
+ ...
251
+ -Dfcrepo.pid.minter.length=2 -Dfcrepo.pid.minter.count=4
252
+ ```
253
+ For the Fedora metadata/storage adapters to correctly translate identifiers into URI's, they should be initialized
254
+ like:
255
+
256
+ ```angular2html
257
+ Valkyrie::Persistence::Fedora::MetadataAdapter.new(
258
+ connection: ::Ldp::Client.new("http://localhost:8080/fcrepo/rest"),
259
+ fedora_version: 6.5,
260
+ fedora_pairtree_count: 4,
261
+ fedora_pairtree_length: 2
262
+ )
263
+ ```
264
+
265
+ In the configuration above, an ID of `AaBbCcDd` will be created in Fedora under the root node as `/Aa/Bb/Cc/Dd/AaBbCcDd`.
266
+ If count and length correctly match in the Fedora adapters, that same path will be calculated and returned.
267
+
268
+ Note that the configuration above is not required for pairtree paths to work correctly in Fedora 4, and automatic
269
+ pairtree creation is not supported under Fedora 5 or Fedora 6 < 6.5.
237
270
 
238
271
  ## Installing a Development environment
239
272
 
@@ -9,17 +9,23 @@ module Valkyrie::Persistence::Fedora
9
9
  # schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new(title: RDF::URI("http://example.com/title"))
10
10
  # )
11
11
  class MetadataAdapter
12
- attr_reader :connection, :base_path, :schema, :fedora_version
12
+ attr_reader :connection, :base_path, :schema, :fedora_version, :pairtree_count, :pairtree_length
13
13
 
14
14
  # @param [Ldp::Client] connection
15
15
  # @param [String] base_path
16
16
  # @param [Valkyrie::Persistence::Fedora::PermissiveSchema] schema
17
17
  # @param [Integer] fedora_version
18
- def initialize(connection:, base_path: "/", schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new, fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION)
18
+ # @param [Integer] fedora_pairtree_count
19
+ # @param [Integer] fedora_pairtree_length
20
+ def initialize(connection:, base_path: "/", schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new, # rubocop:disable Metrics/ParameterLists
21
+ fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION,
22
+ fedora_pairtree_count: 0, fedora_pairtree_length: 0)
19
23
  @connection = connection
20
24
  @base_path = base_path
21
25
  @schema = schema
22
26
  @fedora_version = fedora_version
27
+ @pairtree_count = fedora_pairtree_count
28
+ @pairtree_length = fedora_pairtree_length
23
29
  end
24
30
 
25
31
  # Construct the query service object using this adapter
@@ -58,7 +64,8 @@ module Valkyrie::Persistence::Fedora
58
64
  # @param [RDF::URI] id the Valkyrie ID
59
65
  # @return [RDF::URI]
60
66
  def id_to_uri(id)
61
- prefix = [5, 6].include?(fedora_version) ? "" : "#{pair_path(id)}/"
67
+ prefix = ""
68
+ prefix = "#{pair_path(id)}/" if fedora_version == 4 || (fedora_version >= 6.5 && (pairtree_count * pairtree_length).positive?)
62
69
  RDF::URI("#{connection_prefix}/#{prefix}#{CGI.escape(id.to_s)}")
63
70
  end
64
71
 
@@ -68,7 +75,16 @@ module Valkyrie::Persistence::Fedora
68
75
  # @param [Valkyrie::ID] id the Valkyrie ID
69
76
  # @return [Array<String>]
70
77
  def pair_path(id)
71
- id.to_s.split(/[-\/]/).first.split("").each_slice(2).map(&:join).join("/")
78
+ if fedora_version >= 6.5
79
+ # When configurable, pair the part up to count * length, but only up to a slash
80
+ pair_part = id.to_s[0, pairtree_count * pairtree_length].split(/[\/]/).first
81
+ slice_length = pairtree_length
82
+ else
83
+ # When not configurable, pair the full string, but only up to a dash or slash
84
+ pair_part = id.to_s.split(/[-\/]/).first
85
+ slice_length = 2
86
+ end
87
+ pair_part.split("").each_slice(slice_length).map(&:join).join("/")
72
88
  end
73
89
 
74
90
  def url_prefix
@@ -2,15 +2,26 @@
2
2
  module Valkyrie::Storage
3
3
  # Implements the DataMapper Pattern to store binary data in fedora
4
4
  class Fedora
5
- attr_reader :connection, :base_path, :fedora_version
5
+ attr_reader :connection, :base_path, :fedora_version, :pairtree_count, :pairtree_length, :uri_transformer
6
6
  PROTOCOL = 'fedora://'
7
7
  SLASH = '/'
8
8
 
9
9
  # @param [Ldp::Client] connection
10
- def initialize(connection:, base_path: "/", fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION)
10
+ # @param [Integer] fedora_pairtree_count
11
+ # @param [Integer] fedora_pairtree_length
12
+ def initialize(connection:, base_path: "/", fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION,
13
+ fedora_pairtree_count: 0, fedora_pairtree_length: 0)
11
14
  @connection = connection
12
15
  @base_path = base_path
13
16
  @fedora_version = fedora_version
17
+ @pairtree_count = fedora_pairtree_count
18
+ @pairtree_length = fedora_pairtree_length
19
+
20
+ @uri_transformer = if fedora_version >= 6.5 && (pairtree_count * pairtree_length).positive?
21
+ pairtree_resource_uri_transformer
22
+ else
23
+ default_resource_uri_transformer
24
+ end
14
25
  end
15
26
 
16
27
  # @param id [Valkyrie::ID]
@@ -24,7 +35,7 @@ module Valkyrie::Storage
24
35
  def supports?(feature)
25
36
  return true if feature == :versions
26
37
  # Fedora 6 auto versions and you can't delete versions.
27
- return true if feature == :version_deletion && fedora_version != 6
38
+ return true if feature == :version_deletion && fedora_version < 6
28
39
  false
29
40
  end
30
41
 
@@ -44,7 +55,7 @@ module Valkyrie::Storage
44
55
  # @param extra_arguments [Hash] additional arguments which may be passed to other adapters
45
56
  # @return [Valkyrie::StorageAdapter::StreamFile]
46
57
  def upload(file:, original_filename:, resource:, content_type: "application/octet-stream", # rubocop:disable Metrics/ParameterLists
47
- resource_uri_transformer: default_resource_uri_transformer, **_extra_arguments)
58
+ resource_uri_transformer: uri_transformer, **_extra_arguments)
48
59
  identifier = resource_uri_transformer.call(resource, base_url) + '/original'
49
60
  upload_file(fedora_uri: identifier, io: file, content_type: content_type, original_filename: original_filename)
50
61
  # Fedora 6 auto versions, so check to see if there's a version for this
@@ -60,7 +71,7 @@ module Valkyrie::Storage
60
71
  uri = fedora_identifier(id: id)
61
72
  # Fedora 6 has auto versioning, so have to sleep if it's too soon after last
62
73
  # upload.
63
- if fedora_version == 6 && current_version_id(id: id).to_s.split("/").last == Time.current.utc.strftime("%Y%m%d%H%M%S")
74
+ if fedora_version >= 6 && current_version_id(id: id).to_s.split("/").last == Time.current.utc.strftime("%Y%m%d%H%M%S")
64
75
  sleep(0.5)
65
76
  return upload_version(id: id, file: file)
66
77
  end
@@ -102,7 +113,7 @@ module Valkyrie::Storage
102
113
  end
103
114
 
104
115
  def upload_file(fedora_uri:, io:, content_type: "application/octet-stream", original_filename: "default")
105
- sha1 = [5, 6].include?(fedora_version) ? "sha" : "sha1"
116
+ sha1 = fedora_version >= 5 ? "sha" : "sha1"
106
117
  connection.http.put do |request|
107
118
  request.url fedora_uri
108
119
  request.headers['Content-Type'] = content_type
@@ -141,7 +152,7 @@ module Valkyrie::Storage
141
152
  version_id ||= id if id != current_id
142
153
  # No version got passed and we're asking for a current_id, gotta get the
143
154
  # version ID
144
- return perform_find(id: current_id, version_id: (current_version_id(id: id) || :empty)) if version_id.nil?
155
+ return perform_find(id: current_id, version_id: current_version_id(id: id) || :empty) if version_id.nil?
145
156
  Valkyrie::StorageAdapter::StreamFile.new(id: current_id, io: response(id: id), version_id: version_id)
146
157
  end
147
158
 
@@ -211,6 +222,18 @@ module Valkyrie::Storage
211
222
  end
212
223
  end
213
224
 
225
+ def pairtree_resource_uri_transformer
226
+ lambda do |resource, base_url|
227
+ id = CGI.escape(resource.id.to_s)
228
+ return RDF::URI.new(base_url + id) unless (pairtree_count * pairtree_length).positive?
229
+
230
+ pair_part = id.to_s[0, pairtree_count * pairtree_length].split(/[\/]/).first
231
+ slice_length = pairtree_length
232
+ prefix = pair_part.split("").each_slice(slice_length).map(&:join).join("/")
233
+ RDF::URI.new(base_url + "#{prefix}/" + id)
234
+ end
235
+ end
236
+
214
237
  def base_url
215
238
  pre_divider = base_path.starts_with?(SLASH) ? '' : SLASH
216
239
  post_divider = base_path.ends_with?(SLASH) ? '' : SLASH
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie
3
- VERSION = "3.2.0"
3
+ VERSION = "3.3.0"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valkyrie
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Trey Pendragon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-05-07 00:00:00.000000000 Z
11
+ date: 2024-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct