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 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.



22
23
24
25
26
# File 'lib/ro_crate/model/crate.rb', line 22

def initialize(id = IDENTIFIER, properties = {})
  @data_entities = []
  @contextual_entities = []
  super(self, nil, id, properties)
end

Instance Attribute Details

#contextual_entitiesObject (readonly)

Returns the value of attribute contextual_entities.



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

def contextual_entities
  @contextual_entities
end

#data_entitiesObject (readonly)

Returns the value of attribute data_entities.



6
7
8
# File 'lib/ro_crate/model/crate.rb', line 6

def data_entities
  @data_entities
end

Class Method Details

.format_id(id) ⇒ Object



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

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

.format_local_id(id) ⇒ Object



15
16
17
18
# File 'lib/ro_crate/model/crate.rb', line 15

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.



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

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:



125
126
127
# File 'lib/ro_crate/model/crate.rb', line 125

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.



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

def add_contextual_entity(entity)
  entity = claim(entity)
  contextual_entities.delete(entity) # Remove (then re-add) the entity if it exists
  contextual_entities.push(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.



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

def add_data_entity(entity)
  entity = claim(entity)
  data_entities.delete(entity) # Remove (then re-add) the entity if it exists
  data_entities.push(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:



74
75
76
# File 'lib/ro_crate/model/crate.rb', line 74

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:



60
61
62
# File 'lib/ro_crate/model/crate.rb', line 60

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:



47
48
49
# File 'lib/ro_crate/model/crate.rb', line 47

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:



136
137
138
# File 'lib/ro_crate/model/crate.rb', line 136

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:



114
115
116
# File 'lib/ro_crate/model/crate.rb', line 114

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)


219
220
221
# File 'lib/ro_crate/model/crate.rb', line 219

def 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)



236
237
238
239
# File 'lib/ro_crate/model/crate.rb', line 236

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

#default_entitiesArray<Entity>

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

Returns:



201
202
203
# File 'lib/ro_crate/model/crate.rb', line 201

def default_entities
  [, 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.



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

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:



33
34
35
# File 'lib/ro_crate/model/crate.rb', line 33

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

#entitiesArray<Entity>

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

Returns:



193
194
195
# File 'lib/ro_crate/model/crate.rb', line 193

def entities
  default_entities | data_entities | contextual_entities
end

#get_bindingObject



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

def get_binding
  binding
end

#metadataMetadata

The RO-Crate metadata file

Returns:



168
169
170
# File 'lib/ro_crate/model/crate.rb', line 168

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

#own_payloadObject



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

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})

    ]



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

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
  non_self_entities = default_entities.reject { |e| e == self }
  sorted_entities = (non_self_entities | 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:



176
177
178
# File 'lib/ro_crate/model/crate.rb', line 176

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:



185
186
187
# File 'lib/ro_crate/model/crate.rb', line 185

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

#propertiesObject



205
206
207
# File 'lib/ro_crate/model/crate.rb', line 205

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)


229
230
231
# File 'lib/ro_crate/model/crate.rb', line 229

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

#uuidObject



209
210
211
# File 'lib/ro_crate/model/crate.rb', line 209

def uuid
  @uuid ||= SecureRandom.uuid
end