rubydora 1.8.1 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +573 -0
- data/.travis.yml +6 -6
- data/Gemfile +2 -3
- data/README.md +86 -0
- data/Rakefile +22 -25
- data/VERSION +1 -1
- data/lib/rubydora.rb +3 -6
- data/lib/rubydora/array_with_callback.rb +4 -4
- data/lib/rubydora/audit_trail.rb +7 -7
- data/lib/rubydora/callbacks.rb +9 -9
- data/lib/rubydora/datastream.rb +43 -39
- data/lib/rubydora/digital_object.rb +31 -33
- data/lib/rubydora/fc3_service.rb +10 -14
- data/lib/rubydora/fedora_url_helpers.rb +21 -22
- data/lib/rubydora/models_mixin.rb +4 -4
- data/lib/rubydora/profile_parser.rb +8 -8
- data/lib/rubydora/relationships_mixin.rb +15 -16
- data/lib/rubydora/repository.rb +11 -11
- data/lib/rubydora/resource_index.rb +10 -14
- data/lib/rubydora/rest_api_client.rb +52 -53
- data/lib/rubydora/transactions.rb +42 -51
- data/rubydora.gemspec +25 -25
- data/spec/audit_trail_spec.rb +1 -1
- data/spec/lib/datastream_spec.rb +34 -32
- data/spec/lib/digital_object_spec.rb +13 -10
- data/spec/lib/integration_test_spec.rb +116 -119
- data/spec/lib/profile_parser_spec.rb +1 -1
- data/spec/lib/repository_spec.rb +5 -5
- data/spec/lib/rest_api_client_spec.rb +60 -66
- data/spec/lib/transactions_spec.rb +4 -6
- data/spec/spec_helper.rb +2 -9
- metadata +30 -31
- data/.gitmodules +0 -0
- data/README.rdoc +0 -79
- data/gemfiles/gemfile.rails3 +0 -11
- data/gemfiles/gemfile.rails4 +0 -10
data/.travis.yml
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
+
sudo: false
|
1
2
|
language: ruby
|
2
3
|
rvm:
|
3
|
-
- 1.
|
4
|
-
- 2.
|
5
|
-
- 2.1
|
4
|
+
- 2.1.10
|
5
|
+
- 2.2.5
|
6
|
+
- 2.3.1
|
6
7
|
|
7
|
-
|
8
|
-
-
|
9
|
-
- gemfiles/gemfile.rails4
|
8
|
+
jdk:
|
9
|
+
- oraclejdk8
|
10
10
|
|
11
11
|
notifications:
|
12
12
|
irc: "irc.freenode.org#projecthydra"
|
data/Gemfile
CHANGED
data/README.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# rubydora
|
2
|
+
[<img src="https://travis-ci.org/projecthydra/rubydora.png?branch=master"
|
3
|
+
alt="Build Status" />](https://travis-ci.org/projecthydra/rubydora) [<img
|
4
|
+
src="https://badge.fury.io/rb/rubydora.png" alt="Gem Version"
|
5
|
+
/>](http://badge.fury.io/rb/rubydora)
|
6
|
+
|
7
|
+
Rubydora is a low-level Fedora Commons REST API consumer, providing direct
|
8
|
+
access to REST API methods, as well as a primitive ruby abstraction.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
```bash
|
13
|
+
gem install rubydora
|
14
|
+
```
|
15
|
+
|
16
|
+
## Examples
|
17
|
+
|
18
|
+
```
|
19
|
+
> repo = Rubydora.connect :url => 'http://localhost:8983/fedora', :user => 'fedoraAdmin', :password => 'fedoraAdmin'
|
20
|
+
=> #<Rubydora::Repository:0x101859538 @config={:url=>"http://localhost:8983/fedora", :user=>"fedoraAdmin", :password=>"fedoraAdmin"}>
|
21
|
+
|
22
|
+
> obj = repo.find('test:1')
|
23
|
+
=> #<Rubydora::DigitalObject:0x101977230 @pid="test:1", @repository=#<Rubydora::Repository:0x1019beef0 @config={:user=>"fedoraAdmin", :url=>"http://localhost:8983/fedora", :password=>"fedora"}>>
|
24
|
+
|
25
|
+
> obj.new?
|
26
|
+
=> true
|
27
|
+
|
28
|
+
> obj = obj.save
|
29
|
+
=> #<Rubydora::DigitalObject:0x1017601b8 @pid="test:1", @repository=#<Rubydora::Repository:0x1018e3058 @config={:url=>"http://localhost:8983/fedora", :user=>"fedoraAdmin", :password=>"fedoraAdmin"}, @client=#<RestClient::Resource:0x101882910 @options={:user=>"fedoraAdmin", :password=>"fedoraAdmin"}, @block=nil, @url="http://localhost:8983/fedora">>>
|
30
|
+
|
31
|
+
> obj.profile
|
32
|
+
=> {"objDissIndexViewURL"=>"http://localhost:8983/fedora/get/test:1/fedora-system:3/viewMethodIndex", "objLabel"=>"", "objModels"=>"info:fedora/fedora-system:FedoraObject-3.0", "objCreateDate"=>"2011-04-18T13:34:11.285Z", "objOwnerId"=>"fedoraAdmin", "objState"=>"A", "objItemIndexViewURL"=>"http://localhost:8983/fedora/get/test:1/fedora-system:3/viewItemIndex", "objLastModDate"=>"2011-04-18T13:47:30.110Z"}
|
33
|
+
|
34
|
+
> obj.models
|
35
|
+
=> ["info:fedora/fedora-system:FedoraObject-3.0"]
|
36
|
+
|
37
|
+
> obj.models << 'info:fedora/test:cmodel'
|
38
|
+
=> ["info:fedora/fedora-system:FedoraObject-3.0", "info:fedora/test:cmodel"]
|
39
|
+
|
40
|
+
> obj2 = repo.find('test:2')
|
41
|
+
=> [...]
|
42
|
+
|
43
|
+
> obj1.parts << obj2
|
44
|
+
=> [...]
|
45
|
+
|
46
|
+
> obj.datastreams
|
47
|
+
=> {"DC"=>#<Rubydora::Datastream:0x101860180 @dsid="DC" ...> }
|
48
|
+
|
49
|
+
> ds = obj.datastreams['File']
|
50
|
+
=> #<Rubydora::Datastream:0x1017f26a8 @dsid="File" ...>
|
51
|
+
> ds.controlGroup = 'R'
|
52
|
+
=> "R"
|
53
|
+
> ds.dsLocation = 'http://example.org/index.html'
|
54
|
+
=> "http://example.org/index.html"
|
55
|
+
> ds.dsLabel = 'Example redirect datastream'
|
56
|
+
=> "Example redirect datastream"
|
57
|
+
> ds.mimeType = 'text/html'
|
58
|
+
=> "text/html"
|
59
|
+
> ds.save
|
60
|
+
=> #<Rubydora::Datastream:0x10177a568 @dsid="File" ...>
|
61
|
+
|
62
|
+
> obj.datastreams
|
63
|
+
=> {"DC"=>#<Rubydora::Datastream:0x101860180 @dsid="DC" ..., "File"=>#<Rubydora::Datastream:0x10177a568 @dsid="File" ...>}
|
64
|
+
|
65
|
+
> obj.datastreams["File"].delete
|
66
|
+
=> true
|
67
|
+
> obj.datastreams["File"].new?
|
68
|
+
=> true
|
69
|
+
```
|
70
|
+
|
71
|
+
## Contributing to rubydora
|
72
|
+
|
73
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
74
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
75
|
+
* Fork the project
|
76
|
+
* Start a feature/bugfix branch
|
77
|
+
* Commit and push until you are happy with your contribution
|
78
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
79
|
+
* Please try not to mess with the Rakefile, version, or history. If you want
|
80
|
+
to have your own version, or is otherwise necessary, that is fine, but
|
81
|
+
please isolate to its own commit so I can cherry-pick around it.
|
82
|
+
|
83
|
+
## Copyright
|
84
|
+
|
85
|
+
Copyright (c) 2011 Chris Beer. See LICENSE.txt for further details.
|
86
|
+
|
data/Rakefile
CHANGED
@@ -1,56 +1,57 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler'
|
3
3
|
require 'jettywrapper'
|
4
|
+
require 'yard'
|
4
5
|
require 'bundler/gem_tasks'
|
5
6
|
|
7
|
+
ZIP_URL = 'https://github.com/projecthydra/hydra-jetty/archive/v7.2.0.zip'
|
8
|
+
|
6
9
|
begin
|
7
10
|
Bundler.setup(:default, :development)
|
8
11
|
rescue Bundler::BundlerError => e
|
9
12
|
$stderr.puts e.message
|
10
|
-
$stderr.puts
|
13
|
+
$stderr.puts 'Run `bundle install` to install missing gems'
|
11
14
|
exit e.status_code
|
12
15
|
end
|
13
16
|
|
14
17
|
# Get your spec rake tasks working in RSpec 2.0
|
15
|
-
|
16
18
|
require 'rspec/core/rake_task'
|
17
19
|
|
18
20
|
desc 'Default: run ci build.'
|
19
21
|
task :default => :ci
|
20
22
|
|
21
|
-
desc
|
23
|
+
desc 'Run specs'
|
22
24
|
RSpec::Core::RakeTask.new do |t|
|
23
|
-
|
24
|
-
if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.8/
|
25
|
+
if ENV['COVERAGE'] && RUBY_VERSION =~ /^1.8/
|
25
26
|
t.rcov = true
|
26
27
|
t.rcov_opts = %w{--exclude spec\/*,gems\/*,ruby\/* --aggregate coverage.data}
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
YARD::Rake::YardocTask.new do |yt|
|
32
|
+
yt.files = ['lib/**/*.rb']
|
33
|
+
yt.options = ['--readme', 'README.md']
|
33
34
|
end
|
34
35
|
|
35
|
-
desc
|
36
|
+
desc 'Open an irb session preloaded with this library'
|
36
37
|
task :console do
|
37
|
-
sh
|
38
|
+
sh 'irb -rubygems -I lib -r rubydora.rb'
|
38
39
|
end
|
39
40
|
|
40
|
-
desc
|
41
|
+
desc 'Execute Continuous Integration build'
|
41
42
|
task :ci => 'jetty:clean' do
|
42
43
|
unless ENV['environment'] == 'test'
|
43
|
-
exec(
|
44
|
+
exec('rake ci environment=test')
|
44
45
|
end
|
45
46
|
|
46
47
|
jetty_params = {
|
47
|
-
:jetty_home
|
48
|
-
:quiet
|
49
|
-
:jetty_port
|
50
|
-
:solr_home
|
51
|
-
:fedora_home
|
48
|
+
:jetty_home => File.expand_path(File.dirname(__FILE__) + '/jetty'),
|
49
|
+
:quiet => true,
|
50
|
+
:jetty_port => ENV['TEST_JETTY_PORT'] || 8983,
|
51
|
+
:solr_home => File.expand_path(File.dirname(__FILE__) + '/jetty/solr'),
|
52
|
+
:fedora_home => File.expand_path(File.dirname(__FILE__) + '/jetty/fedora/default'),
|
52
53
|
:startup_wait => 90,
|
53
|
-
:java_opts
|
54
|
+
:java_opts => ['-Xmx256m', '-XX:MaxPermSize=128m']
|
54
55
|
}
|
55
56
|
|
56
57
|
error = Jettywrapper.wrap(jetty_params) do
|
@@ -60,14 +61,10 @@ task :ci => 'jetty:clean' do
|
|
60
61
|
raise "test failures: #{error}" if error
|
61
62
|
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
task :coverage do
|
64
|
+
desc 'Execute specs with coverage'
|
65
|
+
task :coverage do
|
66
66
|
# Put spec opts in a file named .rspec in root
|
67
|
-
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE :
|
67
|
+
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
68
68
|
ENV['COVERAGE'] = 'true' unless ruby_engine == 'jruby'
|
69
|
-
|
70
|
-
|
71
69
|
Rake::Task['spec'].invoke
|
72
70
|
end
|
73
|
-
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.9.0
|
data/lib/rubydora.rb
CHANGED
@@ -23,9 +23,6 @@ module Rubydora
|
|
23
23
|
require 'time'
|
24
24
|
require 'hooks'
|
25
25
|
|
26
|
-
if CSV.const_defined? :Reader
|
27
|
-
require 'fastercsv'
|
28
|
-
end
|
29
26
|
require 'restclient'
|
30
27
|
require 'nokogiri'
|
31
28
|
|
@@ -35,7 +32,7 @@ module Rubydora
|
|
35
32
|
class << self
|
36
33
|
# Connect to Fedora Repository
|
37
34
|
# @return Rubydora::Repository
|
38
|
-
def connect
|
35
|
+
def connect(*args)
|
39
36
|
Repository.new *args
|
40
37
|
end
|
41
38
|
|
@@ -48,7 +45,7 @@ module Rubydora
|
|
48
45
|
# Set the default Fedora Repository
|
49
46
|
# @param [Rubydora::Repository] repository
|
50
47
|
# @return Rubydora::Repository
|
51
|
-
def repository=
|
48
|
+
def repository=(repository)
|
52
49
|
@repository = repository
|
53
50
|
end
|
54
51
|
|
@@ -64,6 +61,6 @@ module Rubydora
|
|
64
61
|
|
65
62
|
class FedoraInvalidRequest < RubydoraError; end
|
66
63
|
|
67
|
-
class RecordNotFound < RubydoraError; end
|
64
|
+
class RecordNotFound < RubydoraError; end
|
68
65
|
|
69
66
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Rubydora
|
2
2
|
##
|
3
|
-
# This is an attempt to implement an Array-like
|
4
|
-
# object that calls a method after data is modified
|
3
|
+
# This is an attempt to implement an Array-like
|
4
|
+
# object that calls a method after data is modified
|
5
5
|
class ArrayWithCallback < Array
|
6
6
|
##
|
7
7
|
# FIXME: It would be nice to use Rubydora::Callbacks here,
|
8
|
-
# however, this method requires instance-level callbacks
|
8
|
+
# however, this method requires instance-level callbacks
|
9
9
|
|
10
10
|
[:<<, :collect!, :map!, :compact!, :concat, :delete, :delete_at, :delete_if, :pop, :push, :reject!, :replace, :select!, :[]=, :slice!, :uniq! ].each do |method|
|
11
11
|
class_eval <<-RUBY
|
@@ -25,7 +25,7 @@ module Rubydora
|
|
25
25
|
end
|
26
26
|
|
27
27
|
# duck-typing Rubydora::Callbacks call_* methods
|
28
|
-
def call_on_change
|
28
|
+
def call_on_change(changes = {})
|
29
29
|
self.on_change.each do |h|
|
30
30
|
h.call(self, changes)
|
31
31
|
end
|
data/lib/rubydora/audit_trail.rb
CHANGED
@@ -5,19 +5,19 @@ module Rubydora::AuditTrail
|
|
5
5
|
end
|
6
6
|
|
7
7
|
private
|
8
|
-
|
8
|
+
|
9
9
|
AT_NS = {'audit' => 'info:fedora/fedora-system:def/audit#'}
|
10
10
|
FOXML_NS = {'foxml' => 'info:fedora/fedora-system:def/foxml#'}
|
11
11
|
AT_XPATH = '/foxml:digitalObject/foxml:datastream[@ID = "AUDIT"]/descendant::audit:auditTrail'
|
12
|
-
|
12
|
+
|
13
13
|
class FedoraAuditTrail
|
14
14
|
def initialize(object_xml)
|
15
|
-
@ng_xml = Nokogiri::XML(object_xml).xpath(AT_XPATH, FOXML_NS.merge(AT_NS))
|
15
|
+
@ng_xml = Nokogiri::XML(object_xml).xpath(AT_XPATH, FOXML_NS.merge(AT_NS))
|
16
16
|
end
|
17
17
|
def records
|
18
|
-
|
18
|
+
unless @records
|
19
19
|
@records = []
|
20
|
-
@ng_xml.xpath('.//audit:record', AT_NS).each do |node|
|
20
|
+
@ng_xml.xpath('.//audit:record', AT_NS).each do |node|
|
21
21
|
@records << FedoraAuditRecord.new(node)
|
22
22
|
end
|
23
23
|
end
|
@@ -27,7 +27,7 @@ module Rubydora::AuditTrail
|
|
27
27
|
@ng_xml.to_xml
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
class FedoraAuditRecord
|
32
32
|
def initialize(node)
|
33
33
|
@record = node
|
@@ -53,6 +53,6 @@ module Rubydora::AuditTrail
|
|
53
53
|
def justification
|
54
54
|
@record.at_xpath('audit:justification', AT_NS).text
|
55
55
|
end
|
56
|
-
end
|
56
|
+
end
|
57
57
|
|
58
58
|
end
|
data/lib/rubydora/callbacks.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Rubydora
|
2
2
|
|
3
|
-
# Provides class level methods for handling
|
4
|
-
# callback methods that alter object instances
|
3
|
+
# Provides class level methods for handling
|
4
|
+
# callback methods that alter object instances
|
5
5
|
module Callbacks
|
6
6
|
# add callback framework to base class
|
7
|
-
# @param [Class] base
|
7
|
+
# @param [Class] base
|
8
8
|
def self.included(base)
|
9
9
|
base.extend ExtendableClassMethods
|
10
10
|
end
|
@@ -19,10 +19,10 @@ module Rubydora
|
|
19
19
|
|
20
20
|
# register callback procs
|
21
21
|
# @param [Array<Symbol>] hook name
|
22
|
-
def register_callback
|
23
|
-
attrs.each do |method_name|
|
22
|
+
def register_callback(*attrs)
|
23
|
+
attrs.each do |method_name|
|
24
24
|
next if methods.include? method_name.to_s
|
25
|
-
instance_eval
|
25
|
+
instance_eval "
|
26
26
|
def #{method_name}(&blk)
|
27
27
|
self.hooks[:#{method_name}] ||= []
|
28
28
|
self.hooks[:#{method_name}] << blk
|
@@ -31,9 +31,9 @@ module Rubydora
|
|
31
31
|
def clear_#{method_name}_blocks!
|
32
32
|
self.hooks[:#{method_name}] = []
|
33
33
|
end
|
34
|
-
|
34
|
+
"
|
35
35
|
|
36
|
-
class_eval
|
36
|
+
class_eval "
|
37
37
|
def call_#{method_name}
|
38
38
|
self.class.hooks[:#{method_name}] ||= []
|
39
39
|
self.class.hooks[:#{method_name}].each do |h|
|
@@ -41,7 +41,7 @@ module Rubydora
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
|
44
|
+
"
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
data/lib/rubydora/datastream.rb
CHANGED
@@ -2,7 +2,7 @@ require 'equivalent-xml'
|
|
2
2
|
module Rubydora
|
3
3
|
# This class represents a Fedora datastream object
|
4
4
|
# and provides helper methods for creating and manipulating
|
5
|
-
# them.
|
5
|
+
# them.
|
6
6
|
class Datastream
|
7
7
|
extend ActiveModel::Callbacks
|
8
8
|
define_model_callbacks :save, :create, :destroy
|
@@ -21,42 +21,41 @@ module Rubydora
|
|
21
21
|
|
22
22
|
define_attribute_methods DS_ATTRIBUTES.keys
|
23
23
|
|
24
|
-
# accessors for datastream attributes
|
24
|
+
# accessors for datastream attributes
|
25
25
|
DS_ATTRIBUTES.each do |attribute, profile_name|
|
26
26
|
define_method attribute.to_s do
|
27
27
|
var = "@#{attribute.to_s}".to_sym
|
28
28
|
if instance_variable_defined?(var)
|
29
29
|
instance_variable_get var
|
30
30
|
elsif profile.has_key? profile_name.to_s
|
31
|
-
|
31
|
+
profile[profile_name.to_s]
|
32
32
|
else
|
33
33
|
default_attributes[attribute.to_sym]
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
class_eval
|
37
|
+
class_eval "
|
38
38
|
def #{attribute.to_s}= val
|
39
39
|
validate_#{attribute.to_s}!(val) if respond_to?(:validate_#{attribute.to_s}!, true)
|
40
40
|
#{attribute.to_s}_will_change! unless val == #{attribute.to_s}
|
41
41
|
@#{attribute.to_s} = val
|
42
42
|
end
|
43
|
-
|
43
|
+
"
|
44
44
|
end
|
45
45
|
|
46
46
|
DS_READONLY_ATTRIBUTES = [ :dsCreateDate , :dsSize, :dsVersionID ]
|
47
47
|
DS_READONLY_ATTRIBUTES.each do |attribute|
|
48
|
-
class_eval
|
48
|
+
class_eval "
|
49
49
|
def #{attribute.to_s}
|
50
50
|
@#{attribute} || profile['#{attribute.to_s}'] || default_attributes[:#{attribute}]
|
51
51
|
end
|
52
|
-
|
52
|
+
"
|
53
53
|
|
54
54
|
def dsChecksumValid
|
55
55
|
profile(:validateChecksum=>true)['dsChecksumValid']
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
59
|
# Create humanized accessors for the DS attribute (dsState -> state, dsCreateDate -> createDate)
|
61
60
|
(DS_ATTRIBUTES.keys + DS_READONLY_ATTRIBUTES).select { |k| k.to_s =~ /^ds/ }.each do |attribute|
|
62
61
|
simple_attribute = attribute.to_s.sub(/^ds/, '')
|
@@ -69,13 +68,12 @@ module Rubydora
|
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
72
|
-
|
73
|
-
|
74
|
-
if asOfDateTime == nil
|
71
|
+
def asOfDateTime(asOfDateTime = nil)
|
72
|
+
if asOfDateTime.nil?
|
75
73
|
return @asOfDateTime
|
76
74
|
end
|
77
75
|
|
78
|
-
|
76
|
+
self.class.new(@digital_object, dsid, @options.merge(:asOfDateTime => asOfDateTime))
|
79
77
|
end
|
80
78
|
|
81
79
|
def self.default_attributes
|
@@ -86,7 +84,7 @@ module Rubydora
|
|
86
84
|
@default_attributes ||= self.class.default_attributes
|
87
85
|
end
|
88
86
|
|
89
|
-
def default_attributes=
|
87
|
+
def default_attributes=(attributes)
|
90
88
|
@default_attributes = default_attributes.merge attributes
|
91
89
|
end
|
92
90
|
|
@@ -95,11 +93,11 @@ module Rubydora
|
|
95
93
|
# may not already exist in the datastore.
|
96
94
|
#
|
97
95
|
# Provides `after_initialize` callback for extensions
|
98
|
-
#
|
96
|
+
#
|
99
97
|
# @param [Rubydora::DigitalObject]
|
100
98
|
# @param [String] Datastream ID
|
101
99
|
# @param [Hash] default attribute values (used esp. for creating new datastreams)
|
102
|
-
def initialize
|
100
|
+
def initialize(digital_object, dsid, options = {}, default_instance_attributes = {})
|
103
101
|
run_callbacks :initialize do
|
104
102
|
@digital_object = digital_object
|
105
103
|
@dsid = dsid
|
@@ -119,7 +117,10 @@ module Rubydora
|
|
119
117
|
# Does this datastream already exist?
|
120
118
|
# @return [Boolean]
|
121
119
|
def new?
|
122
|
-
digital_object.nil? ||
|
120
|
+
digital_object.nil? ||
|
121
|
+
(digital_object.respond_to?(:new_record?) && digital_object.new_record?) ||
|
122
|
+
(digital_object.respond_to?(:new?) && digital_object.new?) ||
|
123
|
+
profile.empty?
|
123
124
|
end
|
124
125
|
|
125
126
|
# This method is overridden in ActiveFedora, so we didn't
|
@@ -131,7 +132,7 @@ module Rubydora
|
|
131
132
|
# @param [Boolean] ensure_fetch <true> if true, it will grab the content from the repository if is not already loaded
|
132
133
|
# @return [String]
|
133
134
|
def local_or_remote_content(ensure_fetch = true)
|
134
|
-
return @content if new?
|
135
|
+
return @content if new?
|
135
136
|
|
136
137
|
@content ||= ensure_fetch ? datastream_content : @datastream_content
|
137
138
|
|
@@ -169,16 +170,17 @@ module Rubydora
|
|
169
170
|
end
|
170
171
|
|
171
172
|
# Set the content of the datastream
|
172
|
-
# @param [String or IO]
|
173
|
+
# @param [String or IO]
|
173
174
|
# @return [String or IO]
|
174
|
-
def content=
|
175
|
+
def content=(new_content)
|
175
176
|
raise "Can't change values on older versions" if @asOfDateTime
|
176
|
-
|
177
|
+
@content = new_content
|
177
178
|
end
|
178
179
|
|
179
180
|
def content_changed?
|
180
181
|
return false if ['E','R'].include? controlGroup
|
181
|
-
return
|
182
|
+
return false unless content_loaded?
|
183
|
+
return true if new? && !local_or_remote_content(false).blank? # new datastreams must have content
|
182
184
|
|
183
185
|
if controlGroup == "X"
|
184
186
|
if self.eager_load_datastream_content
|
@@ -208,12 +210,16 @@ module Rubydora
|
|
208
210
|
return dsLocation.present? if ['E','R'].include? controlGroup
|
209
211
|
|
210
212
|
# type M has content if dsLocation is not empty
|
211
|
-
return true if controlGroup == 'M'
|
213
|
+
return true if controlGroup == 'M' && dsLocation.present?
|
212
214
|
|
213
215
|
# if we've set content, then we have content
|
214
216
|
behaves_like_io?(@content) || content.present?
|
215
217
|
end
|
216
218
|
|
219
|
+
def content_loaded?
|
220
|
+
!@content.nil?
|
221
|
+
end
|
222
|
+
|
217
223
|
def empty?
|
218
224
|
!has_content?
|
219
225
|
end
|
@@ -222,9 +228,9 @@ module Rubydora
|
|
222
228
|
# it doesn't require holding the entire content in memory. If you specify the from and length
|
223
229
|
# parameters it simulates a range request. Unfortunatly Fedora 3 doesn't have range requests,
|
224
230
|
# so this method needs to download the whole thing and just seek to the part you care about.
|
225
|
-
#
|
226
|
-
# @param [Integer] from (bytes) the starting point you want to return.
|
227
|
-
#
|
231
|
+
#
|
232
|
+
# @param [Integer] from (bytes) the starting point you want to return.
|
233
|
+
#
|
228
234
|
def stream (from = 0, length = nil)
|
229
235
|
counter = 0
|
230
236
|
Enumerator.new do |blk|
|
@@ -246,7 +252,7 @@ module Rubydora
|
|
246
252
|
# At the end of what we beginning of what we need. Write the end of what was read.
|
247
253
|
offset = from - last_counter
|
248
254
|
blk << chunk[offset..-1]
|
249
|
-
else
|
255
|
+
else
|
250
256
|
# In the middle. We need all of this
|
251
257
|
blk << chunk
|
252
258
|
end
|
@@ -259,18 +265,18 @@ module Rubydora
|
|
259
265
|
# Retrieve the datastream profile as a hash (and cache it)
|
260
266
|
# @param opts [Hash] :validateChecksum if you want fedora to validate the checksum
|
261
267
|
# @return [Hash] see Fedora #getDatastream documentation for keys
|
262
|
-
def profile
|
268
|
+
def profile(opts= {})
|
263
269
|
if @profile && !(opts[:validateChecksum] && !@profile.has_key?('dsChecksumValid'))
|
264
270
|
## Force a recheck of the profile if they've passed :validateChecksum and we don't have dsChecksumValid
|
265
271
|
return @profile
|
266
272
|
end
|
267
|
-
|
273
|
+
|
268
274
|
return @profile = {} unless digital_object.respond_to? :repository
|
269
|
-
|
275
|
+
|
270
276
|
@profile = repository.datastream_profile(pid, dsid, opts[:validateChecksum], asOfDateTime)
|
271
277
|
end
|
272
278
|
|
273
|
-
def profile=
|
279
|
+
def profile=(profile_hash)
|
274
280
|
raise ArgumentError, "Must pass a profile, you passed #{profile_hash.class}" unless profile_hash.kind_of? Hash
|
275
281
|
@profile = profile_hash
|
276
282
|
end
|
@@ -285,7 +291,7 @@ module Rubydora
|
|
285
291
|
def current_version?
|
286
292
|
return true if new?
|
287
293
|
vers = versions
|
288
|
-
|
294
|
+
vers.empty? || dsVersionID == vers.first.dsVersionID
|
289
295
|
end
|
290
296
|
|
291
297
|
# Add datastream to Fedora
|
@@ -307,7 +313,7 @@ module Rubydora
|
|
307
313
|
run_callbacks :save do
|
308
314
|
raise RubydoraError.new("Unable to save #{self.inspect} without content") unless has_content?
|
309
315
|
if new?
|
310
|
-
create
|
316
|
+
create
|
311
317
|
else
|
312
318
|
p = repository.modify_datastream(to_api_params.merge({ :pid => pid, :dsid => dsid })) || {}
|
313
319
|
reset_profile_attributes
|
@@ -353,15 +359,13 @@ module Rubydora
|
|
353
359
|
controlGroup == 'X'
|
354
360
|
end
|
355
361
|
|
356
|
-
|
357
|
-
|
358
362
|
protected
|
359
|
-
# datastream parameters
|
363
|
+
# datastream parameters
|
360
364
|
# @return [Hash]
|
361
365
|
def to_api_params
|
362
366
|
h = default_api_params
|
363
367
|
valid_changed_attributes = changes.keys.map { |x| x.to_sym }.select { |x| DS_ATTRIBUTES.key? x }
|
364
|
-
valid_changed_attributes += [:content] if content_changed?
|
368
|
+
valid_changed_attributes += [:content] if content_changed? && !valid_changed_attributes.include?(:content)
|
365
369
|
## if we don't provide a mimeType, application/octet-stream will be used instead
|
366
370
|
(valid_changed_attributes | [:mimeType]).each do |attribute|
|
367
371
|
h[attribute.to_sym] = send(attribute) unless send(attribute).nil?
|
@@ -392,7 +396,7 @@ module Rubydora
|
|
392
396
|
digital_object.repository
|
393
397
|
end
|
394
398
|
|
395
|
-
def asOfDateTime=
|
399
|
+
def asOfDateTime=(val)
|
396
400
|
@asOfDateTime = val
|
397
401
|
end
|
398
402
|
|
@@ -400,7 +404,7 @@ module Rubydora
|
|
400
404
|
raise "Can't change values on older versions" if @asOfDateTime
|
401
405
|
end
|
402
406
|
|
403
|
-
def validate_dsLocation!
|
407
|
+
def validate_dsLocation!(val)
|
404
408
|
URI.parse(val) unless val.nil?
|
405
409
|
end
|
406
410
|
|
@@ -411,7 +415,7 @@ module Rubydora
|
|
411
415
|
obj.is_a?(IO) || (defined?(Rack) && obj.is_a?(Rack::Test::UploadedFile))
|
412
416
|
end
|
413
417
|
|
414
|
-
def attribute_will_change!
|
418
|
+
def attribute_will_change!(*args)
|
415
419
|
check_if_read_only
|
416
420
|
super
|
417
421
|
end
|