Class: ROCrate::Reader
- Inherits:
-
Object
- Object
- ROCrate::Reader
- Defined in:
- lib/ro_crate/reader.rb
Overview
A class to handle reading of RO Crates from Zip files or directories.
Class Method Summary collapse
-
.build_crate(entity_hash, source) ⇒ Crate
Create a crate from the given set of entities.
-
.create_data_entity(crate, entity_class, source, entity_props) ⇒ ROCrate::File, ...
Create a DataEntity of the given class.
-
.entities_from_metadata(metadata_json) ⇒ Hash{String => Hash}
Extracts all the entities from the @graph of the RO Crate Metadata.
-
.extract_contextual_entities(crate, entity_hash) ⇒ Array<ContextualEntity>
Create appropriately specialized ContextualEntity objects from the given hash of entities and their properties.
-
.extract_data_entities(crate, source, entity_hash) ⇒ Array<ROCrate::File, ROCrate::Directory>
Discover data entities from the ‘hasPart` property of a crate, and create DataEntity objects for them.
-
.extract_metadata_entity(entities) ⇒ Hash{String => Hash}
Extract the metadata entity from the entity hash, according to the rules defined here: www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity mapped by its @id.
-
.extract_root_entity(entities) ⇒ Hash{String => Hash}
Extract the root entity from the entity hash, according to the rules defined here: www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity mapped by its @id.
-
.read(source, target_dir: Dir.mktmpdir) ⇒ Crate
Reads an RO Crate from a directory of zip file.
-
.read_directory(source) ⇒ Crate
Reads an RO Crate from a directory.
-
.read_zip(source, target_dir: Dir.mktmpdir) ⇒ Crate
Reads an RO Crate from a zip file.
-
.unzip_to(source, target) ⇒ Object
Extract the contents of the given Zip file to the given directory.
Class Method Details
.build_crate(entity_hash, source) ⇒ Crate
Create a crate from the given set of entities.
104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/ro_crate/reader.rb', line 104 def self.build_crate(entity_hash, source) ROCrate::Crate.new.tap do |crate| crate.properties = entity_hash.delete(ROCrate::Crate::IDENTIFIER) crate..properties = entity_hash.delete(ROCrate::Metadata::IDENTIFIER) extract_data_entities(crate, source, entity_hash).each do |entity| crate.add_data_entity(entity) end # The remaining entities in the hash must be contextual. extract_contextual_entities(crate, entity_hash).each do |entity| crate.add_contextual_entity(entity) end end end |
.create_data_entity(crate, entity_class, source, entity_props) ⇒ ROCrate::File, ...
Create a DataEntity of the given class.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/ro_crate/reader.rb', line 160 def self.create_data_entity(crate, entity_class, source, entity_props) id = entity_props.delete('@id') decoded_id = URI.decode_www_form_component(id) path = nil uri = URI(id) rescue nil if uri&.absolute? path = uri decoded_id = nil else [id, decoded_id].each do |i| fullpath = ::File.join(source, i) path = Pathname.new(fullpath) if ::File.exist?(fullpath) end unless path warn "Missing file/directory: #{id}, skipping..." return nil end end entity_class.new(crate, path, decoded_id, entity_props) end |
.entities_from_metadata(metadata_json) ⇒ Hash{String => Hash}
Extracts all the entities from the @graph of the RO Crate Metadata.
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/ro_crate/reader.rb', line 75 def self.() = JSON.parse() graph = ['@graph'] if graph # Collect all the things in the graph, mapped by their @id entities = {} graph.each do |entity| entities[entity['@id']] = entity end # Do some normalization... entities[ROCrate::Metadata::IDENTIFIER] = (entities) raise "No metadata entity found in @graph!" unless entities[ROCrate::Metadata::IDENTIFIER] entities[ROCrate::Crate::IDENTIFIER] = extract_root_entity(entities) raise "No root entity (with @id: #{entities[ROCrate::Metadata::IDENTIFIER].dig('about', '@id')}) found in @graph!" unless entities[ROCrate::Crate::IDENTIFIER] entities else raise "No @graph found in metadata!" end end |
.extract_contextual_entities(crate, entity_hash) ⇒ Array<ContextualEntity>
Create appropriately specialized ContextualEntity objects from the given hash of entities and their properties.
141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/ro_crate/reader.rb', line 141 def self.extract_contextual_entities(crate, entity_hash) entities = [] entity_hash.each do |id, entity_props| entity_class = ROCrate::ContextualEntity.specialize(entity_props) entity = entity_class.new(crate, id, entity_props) entities << entity end entities end |
.extract_data_entities(crate, source, entity_hash) ⇒ Array<ROCrate::File, ROCrate::Directory>
Discover data entities from the ‘hasPart` property of a crate, and create DataEntity objects for them. Entities are looked up in the given `entity_hash` (and then removed from it).
125 126 127 128 129 130 131 132 133 134 |
# File 'lib/ro_crate/reader.rb', line 125 def self.extract_data_entities(crate, source, entity_hash) crate.raw_properties['hasPart'].map do |ref| entity_props = entity_hash.delete(ref['@id']) next unless entity_props entity_class = ROCrate::DataEntity.specialize(entity_props) entity = create_data_entity(crate, entity_class, source, entity_props) next if entity.nil? entity end.compact end |
.extract_metadata_entity(entities) ⇒ Hash{String => Hash}
Extract the metadata entity from the entity hash, according to the rules defined here: www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity mapped by its @id.
188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/ro_crate/reader.rb', line 188 def self.(entities) key = entities.detect do |_, props| props.dig('conformsTo', '@id')&.start_with?(ROCrate::Metadata::RO_CRATE_BASE) end&.first return entities.delete(key) if key # Legacy support (entities.delete("./#{ROCrate::Metadata::IDENTIFIER}") || entities.delete(ROCrate::Metadata::IDENTIFIER) || entities.delete("./#{ROCrate::Metadata::IDENTIFIER_1_0}") || entities.delete(ROCrate::Metadata::IDENTIFIER_1_0)) end |
.extract_root_entity(entities) ⇒ Hash{String => Hash}
Extract the root entity from the entity hash, according to the rules defined here: www.researchobject.org/ro-crate/1.1/root-data-entity.html#finding-the-root-data-entity mapped by its @id.
207 208 209 210 211 |
# File 'lib/ro_crate/reader.rb', line 207 def self.extract_root_entity(entities) root_id = entities[ROCrate::Metadata::IDENTIFIER].dig('about', '@id') raise "Metadata entity does not reference any root entity" unless root_id entities.delete(root_id) end |
.read(source, target_dir: Dir.mktmpdir) ⇒ Crate
Reads an RO Crate from a directory of zip file.
11 12 13 14 15 16 17 18 |
# File 'lib/ro_crate/reader.rb', line 11 def self.read(source, target_dir: Dir.mktmpdir) raise "Not a directory!" unless ::File.directory?(target_dir) if ::File.directory?(source) read_directory(source) else read_zip(source, target_dir: target_dir) end end |
.read_directory(source) ⇒ Crate
Reads an RO Crate from a directory.
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/ro_crate/reader.rb', line 57 def self.read_directory(source) source = ::File.(source) = Dir.entries(source).detect { |entry| entry == ROCrate::Metadata::IDENTIFIER || entry == ROCrate::Metadata::IDENTIFIER_1_0 } if entities = (::File.read(::File.join(source, ))) build_crate(entities, source) else raise 'No metadata found!' end end |
.read_zip(source, target_dir: Dir.mktmpdir) ⇒ Crate
Reads an RO Crate from a zip file. It first extracts the Zip file to a temporary directory, and then calls #read_directory.
46 47 48 49 50 |
# File 'lib/ro_crate/reader.rb', line 46 def self.read_zip(source, target_dir: Dir.mktmpdir) unzip_to(source, target_dir) read_directory(target_dir) end |
.unzip_to(source, target) ⇒ Object
Extract the contents of the given Zip file to the given directory.
25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/ro_crate/reader.rb', line 25 def self.unzip_to(source, target) source = ::File.(source) Dir.chdir(target) do Zip::File.open(source) do |zipfile| zipfile.each do |entry| unless ::File.exist?(entry.name) FileUtils::mkdir_p(::File.dirname(entry.name)) zipfile.extract(entry, entry.name) end end end end end |