Class: Rubydora::Datastream
- Inherits:
-
Object
- Object
- Rubydora::Datastream
- Extended by:
- ActiveModel::Callbacks
- Includes:
- ActiveModel::Dirty
- Defined in:
- lib/rubydora/datastream.rb
Overview
This class represents a Fedora datastream object and provides helper methods for creating and manipulating them.
Constant Summary collapse
- DS_ATTRIBUTES =
mapping datastream attributes (and api parameters) to datastream profile names
{:controlGroup => :dsControlGroup, :dsLocation => :dsLocation, :altIDs => nil, :dsLabel => :dsLabel, :versionable => :dsVersionable, :dsState => :dsState, :formatURI => :dsFormatURI, :checksumType => :dsChecksumType, :checksum => :dsChecksum, :mimeType => :dsMIME, :logMessage => nil, :ignoreContent => nil, :lastModifiedDate => nil, :content => nil, :asOfDateTime => nil}
- DS_DEFAULT_ATTRIBUTES =
{ :controlGroup => 'M', :dsState => 'A', :versionable => true }
- DS_READONLY_ATTRIBUTES =
[ :dsCreateDate , :dsSize, :dsVersionID ]
Instance Attribute Summary collapse
-
#digital_object ⇒ Object
readonly
Returns the value of attribute digital_object.
-
#dsid ⇒ Object
readonly
Returns the value of attribute dsid.
Class Method Summary collapse
Instance Method Summary collapse
- #asOfDateTime(asOfDateTime = nil) ⇒ Object
- #changed? ⇒ Boolean
-
#content ⇒ Object
(also: #read)
This method is overridden in ActiveFedora, so we didn’t.
-
#content=(new_content) ⇒ String or IO
Set the content of the datastream.
- #content_changed? ⇒ Boolean
-
#create ⇒ Rubydora::Datastream
Add datastream to Fedora.
- #current_version? ⇒ Boolean
- #datastream_content ⇒ Object
- #datastream_will_change! ⇒ Object
- #default_attributes ⇒ Object
- #default_attributes=(attributes) ⇒ Object
-
#delete ⇒ Rubydora::Datastream
Purge the datastream from Fedora.
- #empty? ⇒ Boolean
-
#external? ⇒ boolean
Is this an external datastream?.
- #has_content? ⇒ Boolean
-
#initialize(digital_object, dsid, options = {}, default_instance_attributes = {}) ⇒ Datastream
constructor
Initialize a Rubydora::Datastream object, which may or may not already exist in the datastore.
-
#inline? ⇒ boolean
Is this an inline datastream?.
-
#local_or_remote_content(ensure_fetch = true) ⇒ String
Retrieve the content of the datastream (and cache it).
-
#managed? ⇒ boolean
Is this a managed datastream?.
-
#new? ⇒ Boolean
Does this datastream already exist?.
-
#pid ⇒ Object
Helper method to get digital object pid.
-
#profile(opts = {}) ⇒ Hash
Retrieve the datastream profile as a hash (and cache it).
- #profile=(profile_hash) ⇒ Object
-
#redirect? ⇒ boolean
Is this a redirect datastream?.
-
#save ⇒ Rubydora::Datastream
Modify or save the datastream.
-
#stream(from = 0, length = nil) ⇒ Object
Returns a streaming response of the datastream.
-
#url ⇒ String
Get the URL for the datastream content.
- #versions ⇒ Object
Constructor Details
#initialize(digital_object, dsid, options = {}, default_instance_attributes = {}) ⇒ Datastream
Initialize a Rubydora::Datastream object, which may or may not already exist in the datastore.
Provides ‘after_initialize` callback for extensions
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/rubydora/datastream.rb', line 102 def initialize digital_object, dsid, = {}, default_instance_attributes = {} run_callbacks :initialize do @digital_object = digital_object @dsid = dsid @options = @default_attributes = default_attributes.merge(default_instance_attributes) .each do |key, value| self.send(:"#{key}=", value) end end end |
Instance Attribute Details
#digital_object ⇒ Object (readonly)
Returns the value of attribute digital_object.
16 17 18 |
# File 'lib/rubydora/datastream.rb', line 16 def digital_object @digital_object end |
#dsid ⇒ Object (readonly)
Returns the value of attribute dsid.
16 17 18 |
# File 'lib/rubydora/datastream.rb', line 16 def dsid @dsid end |
Class Method Details
.default_attributes ⇒ Object
81 82 83 |
# File 'lib/rubydora/datastream.rb', line 81 def self.default_attributes DS_DEFAULT_ATTRIBUTES end |
Instance Method Details
#asOfDateTime(asOfDateTime = nil) ⇒ Object
73 74 75 76 77 78 79 |
# File 'lib/rubydora/datastream.rb', line 73 def asOfDateTime asOfDateTime = nil if asOfDateTime == nil return @asOfDateTime end return self.class.new(@digital_object, dsid, @options.merge(:asOfDateTime => asOfDateTime)) end |
#changed? ⇒ Boolean
199 200 201 |
# File 'lib/rubydora/datastream.rb', line 199 def changed? super || content_changed? end |
#content ⇒ Object Also known as: read
This method is overridden in ActiveFedora, so we didn’t
126 127 128 |
# File 'lib/rubydora/datastream.rb', line 126 def content local_or_remote_content(true) end |
#content=(new_content) ⇒ String or IO
Set the content of the datastream
174 175 176 177 |
# File 'lib/rubydora/datastream.rb', line 174 def content= new_content raise "Can't change values on older versions" if @asOfDateTime @content = new_content end |
#content_changed? ⇒ Boolean
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/rubydora/datastream.rb', line 179 def content_changed? return false if ['E','R'].include? controlGroup return true if new? and !local_or_remote_content(false).blank? # new datastreams must have content if controlGroup == "X" if self.eager_load_datastream_content return !EquivalentXml.equivalent?(Nokogiri::XML(content), Nokogiri::XML(datastream_content)) else return !EquivalentXml.equivalent?(Nokogiri::XML(content), Nokogiri::XML(@datastream_content)) end else if self.eager_load_datastream_content return local_or_remote_content(false) != datastream_content else return local_or_remote_content(false) != @datastream_content end end super end |
#create ⇒ Rubydora::Datastream
Add datastream to Fedora
290 291 292 293 294 295 296 297 298 |
# File 'lib/rubydora/datastream.rb', line 290 def create check_if_read_only run_callbacks :create do p = repository.add_datastream( to_api_params.merge({ :pid => pid, :dsid => dsid, :content => content })) || {} reset_profile_attributes self.profile= p unless p.empty? self.class.new(digital_object, dsid, @options) end end |
#current_version? ⇒ Boolean
282 283 284 285 286 |
# File 'lib/rubydora/datastream.rb', line 282 def current_version? return true if new? vers = versions return vers.empty? || dsVersionID == vers.first.dsVersionID end |
#datastream_content ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/rubydora/datastream.rb', line 151 def datastream_content return nil if new? @datastream_content ||=begin = { :pid => pid, :dsid => dsid } [:asOfDateTime] = asOfDateTime if asOfDateTime repository.datastream_dissemination rescue RestClient::ResourceNotFound end end |
#datastream_will_change! ⇒ Object
326 327 328 |
# File 'lib/rubydora/datastream.rb', line 326 def datastream_will_change! attribute_will_change! :profile end |
#default_attributes ⇒ Object
85 86 87 |
# File 'lib/rubydora/datastream.rb', line 85 def default_attributes @default_attributes ||= self.class.default_attributes end |
#default_attributes=(attributes) ⇒ Object
89 90 91 |
# File 'lib/rubydora/datastream.rb', line 89 def default_attributes= attributes @default_attributes = default_attributes.merge attributes end |
#delete ⇒ Rubydora::Datastream
Purge the datastream from Fedora
316 317 318 319 320 321 322 323 324 |
# File 'lib/rubydora/datastream.rb', line 316 def delete check_if_read_only run_callbacks :destroy do repository.purge_datastream(:pid => pid, :dsid => dsid) unless self.new? digital_object.datastreams.delete(dsid) reset_profile_attributes self end end |
#empty? ⇒ Boolean
217 218 219 |
# File 'lib/rubydora/datastream.rb', line 217 def empty? !has_content? end |
#external? ⇒ boolean
Returns is this an external datastream?.
331 332 333 |
# File 'lib/rubydora/datastream.rb', line 331 def external? controlGroup == 'E' end |
#has_content? ⇒ Boolean
203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/rubydora/datastream.rb', line 203 def has_content? # persisted objects are required to have content return true unless new? # type E and R have content if dsLocation is set. return dsLocation.present? if ['E','R'].include? controlGroup # type M has content if dsLocation is not empty return true if controlGroup == 'M' and dsLocation.present? # if we've set content, then we have content behaves_like_io?(@content) || content.present? end |
#inline? ⇒ boolean
Returns is this an inline datastream?.
346 347 348 |
# File 'lib/rubydora/datastream.rb', line 346 def inline? controlGroup == 'X' end |
#local_or_remote_content(ensure_fetch = true) ⇒ String
Retrieve the content of the datastream (and cache it)
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/rubydora/datastream.rb', line 133 def local_or_remote_content(ensure_fetch = true) return @content if new? @content ||= ensure_fetch ? datastream_content : @datastream_content if behaves_like_io?(@content) begin @content.rewind @content.read ensure @content.rewind end else @content end end |
#managed? ⇒ boolean
Returns is this a managed datastream?.
341 342 343 |
# File 'lib/rubydora/datastream.rb', line 341 def managed? controlGroup == 'M' end |
#new? ⇒ Boolean
Does this datastream already exist?
121 122 123 |
# File 'lib/rubydora/datastream.rb', line 121 def new? digital_object.nil? || digital_object.new_record? || profile.empty? end |
#pid ⇒ Object
Helper method to get digital object pid
115 116 117 |
# File 'lib/rubydora/datastream.rb', line 115 def pid digital_object.pid end |
#profile(opts = {}) ⇒ Hash
Retrieve the datastream profile as a hash (and cache it)
259 260 261 262 263 264 265 266 267 268 |
# File 'lib/rubydora/datastream.rb', line 259 def profile opts= {} if @profile && !(opts[:validateChecksum] && !@profile.has_key?('dsChecksumValid')) ## Force a recheck of the profile if they've passed :validateChecksum and we don't have dsChecksumValid return @profile end return @profile = {} unless digital_object.respond_to? :repository @profile = repository.datastream_profile(pid, dsid, opts[:validateChecksum], asOfDateTime) end |
#profile=(profile_hash) ⇒ Object
270 271 272 273 |
# File 'lib/rubydora/datastream.rb', line 270 def profile= profile_hash raise ArgumentError, "Must pass a profile, you passed #{profile_hash.class}" unless profile_hash.kind_of? Hash @profile = profile_hash end |
#redirect? ⇒ boolean
Returns is this a redirect datastream?.
336 337 338 |
# File 'lib/rubydora/datastream.rb', line 336 def redirect? controlGroup == 'R' end |
#save ⇒ Rubydora::Datastream
Modify or save the datastream
302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/rubydora/datastream.rb', line 302 def save check_if_read_only run_callbacks :save do raise RubydoraError.new("Unable to save #{self.inspect} without content") unless has_content? return create if new? p = repository.modify_datastream(to_api_params.merge({ :pid => pid, :dsid => dsid })) || {} reset_profile_attributes self.profile= p unless p.empty? self.class.new(digital_object, dsid, @options) end end |
#stream(from = 0, length = nil) ⇒ Object
Returns a streaming response of the datastream. This is ideal for large datasteams because it doesn’t require holding the entire content in memory. If you specify the from and length parameters it simulates a range request. Unfortunatly Fedora 3 doesn’t have range requests, so this method needs to download the whole thing and just seek to the part you care about.
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/rubydora/datastream.rb', line 228 def stream (from = 0, length = nil) raise "Can't determine dsSize" unless dsSize length = dsSize - from unless length counter = 0 Enumerator.new do |blk| repository.datastream_dissemination(:pid => pid, :dsid => dsid) do |response| response.read_body do |chunk| last_counter = counter counter += chunk.size if (counter > from) # greater than the range minimum if counter > from + length # At the end of what we need. Write the beginning of what was read. offset = (length + from) - counter - 1 blk << chunk[0..offset] elsif from >= last_counter # At the end of what we beginning of what we need. Write the end of what was read. offset = from - last_counter blk << chunk[offset..-1] else # In the middle. We need all of this blk << chunk end end end end end end |
#url ⇒ String
Get the URL for the datastream content
165 166 167 168 169 |
# File 'lib/rubydora/datastream.rb', line 165 def url = { } [:asOfDateTime] = asOfDateTime if asOfDateTime repository.datastream_url(pid, dsid, ) + "/content" end |
#versions ⇒ Object
275 276 277 278 279 280 |
# File 'lib/rubydora/datastream.rb', line 275 def versions versions = repository.versions_for_datastream(pid, dsid) versions.map do |asOfDateTime, profile| self.class.new(@digital_object, dsid, asOfDateTime: asOfDateTime, profile: profile) end end |