Class: ROCrate::Crate

Inherits:
Directory show all
Defined in:
lib/ro_crate/model/crate.rb

Overview

A Ruby abstraction of an RO-Crate.

Constant Summary collapse

IDENTIFIER =
'./'.freeze

Instance Attribute Summary collapse

Attributes inherited from Entity

#crate

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Directory

#remote?

Methods inherited from DataEntity

#filepath, specialize

Methods inherited from Entity

#==, #[], #[]=, #auto_dereference, #auto_reference, #eql?, #external?, #has_type?, #hash, #id, #id=, #inspect, #linked_entities, properties, #raw_properties, #reference, #to_json, #type, #type=

Constructor Details

#initialize(id = IDENTIFIER, properties = {}) ⇒ Crate

Initialize an empty RO-Crate.



24
25
26
27
28
# File 'lib/ro_crate/model/crate.rb', line 24

def initialize(id = IDENTIFIER, properties = {})
  @data_entities = Set.new
  @contextual_entities = Set.new
  super(self, nil, id, properties)
end

Instance Attribute Details

#contextual_entitiesObject (readonly)

Returns the value of attribute contextual_entities.



9
10
11
# File 'lib/ro_crate/model/crate.rb', line 9

def contextual_entities
  @contextual_entities
end

#data_entitiesObject (readonly)

Returns the value of attribute data_entities.



8
9
10
# File 'lib/ro_crate/model/crate.rb', line 8

def data_entities
  @data_entities
end

Class Method Details

.format_id(id) ⇒ Object



12
13
14
15
# File 'lib/ro_crate/model/crate.rb', line 12

def self.format_id(id)
  i = super(id)
  i.end_with?('/') ? i : "#{i}/"
end

.format_local_id(id) ⇒ Object



17
18
19
20
# File 'lib/ro_crate/model/crate.rb', line 17

def self.format_local_id(id)
  return id if id == IDENTIFIER
  super
end

Instance Method Details

#add_all(source_directory, create_entities = true, include_hidden: false) ⇒ Array<DataEntity>

Recursively add the contents of the given source directory at the root of the crate. Useful for quickly RO-Crate-ifying a directory. Creates data entities for each file/directory discovered (excluding the top level directory itself) if ‘create_entities` is true.

Parameters:

  • source_directory (String, Pathname, ::File, )

    The source directory that will be included in the crate.

  • create_entities (Boolean) (defaults to: true)

    Whether to create data entities for the added content, or just include them anonymously.

  • include_hidden (Boolean) (defaults to: false)

    Whether to include hidden files, i.e. those prefixed by a ‘.` (period).

Returns:

  • (Array<DataEntity>)

    Any entities that were created from the directory contents. Will be empty if ‘create_entities` was false.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/ro_crate/model/crate.rb', line 90

def add_all(source_directory, create_entities = true, include_hidden: false)
  added = []

  if create_entities
    list_all_files(source_directory, include_hidden: include_hidden).each do |rel_path|
      source_path = Pathname.new(::File.join(source_directory, rel_path)).expand_path
      if source_path.directory?
        added << add_directory(source_path, rel_path)
      else
        added << add_file(source_path, rel_path)
      end
    end
  else
    populate_entries(Pathname.new(::File.expand_path(source_directory)), include_hidden: include_hidden)
  end

  added
end

#add_contact_point(id, properties = {}) ⇒ ContactPoint

Create a new ROCrate::ContactPoint and add it to the crate

Parameters:

  • id (String, nil)

    An ID to identify this contact point, or blank to auto-generate an appropriate one, (or determine via the properties param)

  • properties (Hash{String => Object}) (defaults to: {})

    A hash of JSON-LD properties to associate with this contact point.

Returns:



127
128
129
# File 'lib/ro_crate/model/crate.rb', line 127

def add_contact_point(id, properties = {})
  add_contextual_entity(ROCrate::ContactPoint.new(self, id, properties))
end

#add_contextual_entity(entity) ⇒ Entity

Add a contextual entity to the crate

Parameters:

  • entity (Entity)

    the entity to add to the crate.

Returns:

  • (Entity)

    the entity itself, or a clone of the entity “owned” by this crate.



147
148
149
150
151
152
# File 'lib/ro_crate/model/crate.rb', line 147

def add_contextual_entity(entity)
  entity = claim(entity)
  contextual_entities.delete?(entity) # Remove (then re-add) the entity if it exists
  contextual_entities.add(entity)
  entity
end

#add_data_entity(entity) ⇒ Entity

Add a data entity to the crate

Parameters:

  • entity (Entity)

    the entity to add to the crate.

Returns:

  • (Entity)

    the entity itself, or a clone of the entity “owned” by this crate.



159
160
161
162
163
164
# File 'lib/ro_crate/model/crate.rb', line 159

def add_data_entity(entity)
  entity = claim(entity)
  data_entities.delete?(entity) # Remove (then re-add) the entity if it exists
  data_entities.add(entity)
  entity
end

#add_directory(source_directory, crate_path = nil, entity_class: ROCrate::Directory, **properties) ⇒ Entity

Create a new directory and add it to the crate.

Parameters:

  • source_directory (String, Pathname, ::File, #read, nil)

    The source directory that will be included in the crate.

  • crate_path (String) (defaults to: nil)

    The relative path within the RO-Crate where this directory will be written.

  • entity_class (Class) (defaults to: ROCrate::Directory)

    The class to use to instantiate the Entity, useful if you have created a subclass of ROCrate::Directory that you want to use. (defaults to ROCrate::Directory).

  • properties (Hash{String => Object})

    A hash of JSON-LD properties to associate with this directory.

Returns:



76
77
78
# File 'lib/ro_crate/model/crate.rb', line 76

def add_directory(source_directory, crate_path = nil, entity_class: ROCrate::Directory, **properties)
  entity_class.new(self, source_directory, crate_path, properties).tap { |e| add_data_entity(e) }
end

#add_external_file(source, entity_class: ROCrate::File, **properties) ⇒ Entity

Create a new file that references a remote URI and add it to the crate.

Parameters:

  • source (String, URI)

    The URI to add.

  • entity_class (Class) (defaults to: ROCrate::File)

    The class to use to instantiate the Entity, useful if you have created a subclass of ROCrate::File that you want to use. (defaults to ROCrate::File).

  • properties (Hash{String => Object})

    A hash of JSON-LD properties to associate with this file.

Returns:



62
63
64
# File 'lib/ro_crate/model/crate.rb', line 62

def add_external_file(source, entity_class: ROCrate::File, **properties)
  entity_class.new(self, source, nil, properties).tap { |e| add_data_entity(e) }
end

#add_file(source, crate_path = nil, entity_class: ROCrate::File, **properties) ⇒ Entity

Create a new file and add it to the crate.

Parameters:

  • source (String, Pathname, ::File, #read, nil)

    The source on the disk where this file will be read.

  • crate_path (String) (defaults to: nil)

    The relative path within the RO-Crate where this file will be written.

  • entity_class (Class) (defaults to: ROCrate::File)

    The class to use to instantiate the Entity, useful if you have created a subclass of ROCrate::File that you want to use. (defaults to ROCrate::File).

  • properties (Hash{String => Object})

    A hash of JSON-LD properties to associate with this file.

Returns:



49
50
51
# File 'lib/ro_crate/model/crate.rb', line 49

def add_file(source, crate_path = nil, entity_class: ROCrate::File, **properties)
  entity_class.new(self, source, crate_path, properties).tap { |e| add_data_entity(e) }
end

#add_organization(id, properties = {}) ⇒ Organization

Create a new ROCrate::Organization and add it to the crate

Parameters:

  • id (String, nil)

    An ID to identify this organization, or blank to auto-generate an appropriate one, (or determine via the properties param)

  • properties (Hash{String => Object}) (defaults to: {})

    A hash of JSON-LD properties to associate with this organization.

Returns:



138
139
140
# File 'lib/ro_crate/model/crate.rb', line 138

def add_organization(id, properties = {})
  add_contextual_entity(ROCrate::Organization.new(self, id, properties))
end

#add_person(id, properties = {}) ⇒ Person

Create a new ROCrate::Person and add it to the crate

Parameters:

  • id (String, nil)

    An ID to identify this person, or blank to auto-generate an appropriate one, (or determine via the properties param)

  • properties (Hash{String => Object}) (defaults to: {})

    A hash of JSON-LD properties to associate with this person.

Returns:



116
117
118
# File 'lib/ro_crate/model/crate.rb', line 116

def add_person(id, properties = {})
  add_contextual_entity(ROCrate::Person.new(self, id, properties))
end

#canonical_idAddressable::URI

The “canonical”, global ID of the crate. If the crate was not given an absolute URI as its ID, it will use an “Archive and Package” (ARCP) URI with the UUID of the crate, for example:

arcp://uuid,b3d6fa2b-4e49-43ba-bd89-464e948b7f0c/

Returns:

  • (Addressable::URI)


221
222
223
# File 'lib/ro_crate/model/crate.rb', line 221

def canonical_id
  @canonical_id ||= Addressable::URI.parse("arcp://uuid,#{uuid}").join(id)
end

#claim(entity) ⇒ Object

Copy the entity, but as if it was in this crate. (Or just return the entity if it was already included)



238
239
240
241
# File 'lib/ro_crate/model/crate.rb', line 238

def claim(entity)
  return entity if entity.crate == self
  entity.class.new(crate, entity.id, entity.raw_properties)
end

#default_entitiesSet<Entity>

Entities for the metadata file and crate itself, which should be present in all RO-Crates.

Returns:



203
204
205
# File 'lib/ro_crate/model/crate.rb', line 203

def default_entities
  Set.new([, preview, self])
end

#delete(entity, remove_orphaned: true) ⇒ Entity?

Remove the entity from the RO-Crate.

Parameters:

  • entity (Entity, String)

    The entity or ID of an entity to remove from the crate.

  • remove_orphaned (Boolean) (defaults to: true)

    Should linked contextual entities also be removed from the crate they are left dangling (nothing else is linked to them)?

Returns:

  • (Entity, nil)

    The entity that was deleted, or nil if nothing was deleted.



277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/ro_crate/model/crate.rb', line 277

def delete(entity, remove_orphaned: true)
  entity = dereference(entity) if entity.is_a?(String)
  return unless entity

  deleted = data_entities.delete?(entity) || contextual_entities.delete?(entity)

  if deleted && remove_orphaned
    crate_entities = crate.linked_entities(deep: true)
    to_remove = (entity.linked_entities(deep: true) - crate_entities)
    to_remove.each(&:delete)
  end

  deleted
end

#dereference(id) ⇒ Entity?

Lookup an Entity using the given ID (in this Entity’s crate).

Parameters:

  • id (String)

    The ID to query.

Returns:



35
36
37
# File 'lib/ro_crate/model/crate.rb', line 35

def dereference(id)
  entities.detect { |e| e.canonical_id == crate.resolve_id(id) } if id
end

#entitiesSet<Entity>

All the entities within the crate. Includes contextual entities, data entities, the crate itself and its metadata file.

Returns:



195
196
197
# File 'lib/ro_crate/model/crate.rb', line 195

def entities
  default_entities | data_entities | contextual_entities
end

#gc {|entity| ... } ⇒ Array<ContextualEntity>

Remove any contextual entities that are not linked from any other entity. Optionally takes a block to decide whether the given entity should be removed or not, otherwise removes all unlinked entities.

Yield Parameters:

Yield Returns:

  • (Boolean)

    remove Should this entity be removed?

Returns:



300
301
302
303
304
# File 'lib/ro_crate/model/crate.rb', line 300

def gc(&block)
  unlinked_entities = contextual_entities - .linked_entities(deep: true)

  unlinked_entities.select(&block).each { |e| e.delete(remove_orphaned: false) }
end

#get_bindingObject



265
266
267
# File 'lib/ro_crate/model/crate.rb', line 265

def get_binding
  binding
end

#metadataMetadata

The RO-Crate metadata file

Returns:



170
171
172
# File 'lib/ro_crate/model/crate.rb', line 170

def 
  @metadata ||= ROCrate::Metadata.new(self)
end

#own_payloadObject



243
# File 'lib/ro_crate/model/crate.rb', line 243

alias_method :own_payload, :payload

#payloadHash{String => Entry} Also known as: entries

The file payload of the RO-Crate - a map of all the files/directories contained in the RO-Crate, where the key is the path relative to the crate’s root, and the value is an Entry where the source data can be read.

Returns:

  • (Hash{String => Entry})

    ]



249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/ro_crate/model/crate.rb', line 249

def payload
  # Gather a map of entries, starting from the crate itself, then any directory data entities, then finally any
  # file data entities. This ensures in the case of a conflict, the more "specific" data entities take priority.
  entries = own_payload
  sorted_entities = (default_entities.delete(self) | data_entities).sort_by { |e| e.is_a?(ROCrate::Directory) ? 0 : 1 }

  sorted_entities.each do |entity|
    entity.payload.each do |path, entry|
      entries[path] = entry
    end
  end

  entries
end

#previewPreview

The RO-Crate preview file

Returns:



178
179
180
# File 'lib/ro_crate/model/crate.rb', line 178

def preview
  @preview ||= ROCrate::Preview.new(self)
end

#preview=(preview) ⇒ Preview

Set the RO-Crate preview file

Parameters:

  • preview (Preview)

    the preview to set.

Returns:



187
188
189
# File 'lib/ro_crate/model/crate.rb', line 187

def preview=(preview)
  @preview = claim(preview)
end

#propertiesObject



207
208
209
# File 'lib/ro_crate/model/crate.rb', line 207

def properties
  super.merge('hasPart' => data_entities.map(&:reference))
end

#resolve_id(id) ⇒ Addressable::URI

Return an absolute URI for the given string ID, relative to the crate’s canonical ID.

Parameters:

  • id (String)

    The ID to “join” onto the crate’s base URI.

Returns:

  • (Addressable::URI)


231
232
233
# File 'lib/ro_crate/model/crate.rb', line 231

def resolve_id(id)
  canonical_id.join(id)
end

#uuidObject



211
212
213
# File 'lib/ro_crate/model/crate.rb', line 211

def uuid
  @uuid ||= SecureRandom.uuid
end