diff --git a/hyrax/app/models/complex_modality.rb b/hyrax/app/models/complex_modality.rb index 414870fe3eb8cdf96a3cfcc82a65125311f00652..43c0eaf52b301972057f21b69e073b3ed2bb73f1 100644 --- a/hyrax/app/models/complex_modality.rb +++ b/hyrax/app/models/complex_modality.rb @@ -15,7 +15,7 @@ class ComplexModality < ActiveRecord::Base validates :s3_folder_name, uniqueness: { scope: :parent_source_identifier, message: ->(object, data) { I18n.t('rdms.errors.complex_modality.title.uniqueness', value: object.s3_folder_name) } } before_validation :set_s3_folder_name - after_save :save_work_meta_json_file_to_s3, :reindex_crc_dataset, :relocate_files_on_folder_name_change + after_save :save_work_meta_json_file_to_s3, :reindex_crc_dataset, :relocate_files_on_folder_name_change, :handle_meta_file_on_s3 delegate :crc_dataset, to: :complex_session delegate :complex_subject, to: :complex_session diff --git a/hyrax/app/models/complex_session.rb b/hyrax/app/models/complex_session.rb index 9e906a8939baf24b3a773e378f0b9384e91378be..0a917db7c71466cd6e94027fe25b535ec8247ae4 100644 --- a/hyrax/app/models/complex_session.rb +++ b/hyrax/app/models/complex_session.rb @@ -17,7 +17,7 @@ class ComplexSession < ActiveRecord::Base validates :s3_folder_name, uniqueness: { scope: :parent_source_identifier, message: ->(object, data) { I18n.t('rdms.errors.complex_session.title.uniqueness', value: object.s3_folder_name) } } before_validation :set_s3_folder_name - after_save :save_work_meta_json_file_to_s3, :reindex_crc_dataset, :relocate_files_on_folder_name_change + after_save :save_work_meta_json_file_to_s3, :reindex_crc_dataset, :relocate_files_on_folder_name_change, :handle_meta_file_on_s3 delegate :crc_dataset, to: :complex_subject diff --git a/hyrax/app/models/complex_subject.rb b/hyrax/app/models/complex_subject.rb index 39486440db15f41fa2655efcb669de51c93abccc..2972cdf1dc1c3e65fbbda76ca9b76d488e1ed3b9 100644 --- a/hyrax/app/models/complex_subject.rb +++ b/hyrax/app/models/complex_subject.rb @@ -5,6 +5,7 @@ class ComplexSubject < ActiveRecord::Base include S3FileHandleable has_many :complex_sessions, foreign_key: 'parent_source_identifier', primary_key: 'source_identifier', dependent: :destroy + has_many :complex_modalities, through: :complex_sessions attribute :source_identifier, :string, default: -> { SecureRandom.uuid } @@ -15,7 +16,7 @@ class ComplexSubject < ActiveRecord::Base validates :s3_folder_name, uniqueness: { scope: :parent_source_identifier, message: ->(object, data) { I18n.t('rdms.errors.complex_subject.title.uniqueness', value: object.s3_folder_name) } } before_validation :set_s3_folder_name - after_save :save_work_meta_json_file_to_s3, :reindex_crc_dataset, :relocate_files_on_folder_name_change + after_save :save_work_meta_json_file_to_s3, :reindex_crc_dataset, :relocate_files_on_folder_name_change, :handle_meta_file_on_s3 scope :sort_by_title, ->(source_identifier) { where(parent_source_identifier: source_identifier) diff --git a/hyrax/app/models/concerns/s3_file_handleable.rb b/hyrax/app/models/concerns/s3_file_handleable.rb index 931f661c84336a6e77b9a5a280425951a9539210..a31f3b569502889a9a980786407d866b738ddb86 100644 --- a/hyrax/app/models/concerns/s3_file_handleable.rb +++ b/hyrax/app/models/concerns/s3_file_handleable.rb @@ -9,4 +9,117 @@ module S3FileHandleable Hyrax::HandleS3FolderNameJob.perform_later(self.class.name, self.id, name_changes) end + + def handle_meta_file_on_s3 + s3 = S3StorageService.new + s3.init_client + + crc_dataset = self.class.name == "CrcDataset" ? self.class.find(self.id) : self.crc_dataset + bucket_name = s3.sanitise_name(crc_dataset.id) + complex_modalities = self.class.name == "ComplexModality" ? [self] : self.complex_modalities.to_a.flatten + + complex_modalities.each do |modality| + subject = modality.complex_subject + session = modality.complex_session + meta_file_key = "#{subject.s3_folder_name}/#{session.s3_folder_name}/#{modality.s3_folder_name}/meta.json" + json_data = prepare_json(crc_dataset, subject, session, modality) + + s3.add_content(bucket_name, meta_file_key, json_data) + end + end + + private + + def prepare_json(crc_dataset, subject, session, modality) + @meta = {} + + data_from_crc_dataset(crc_dataset) + data_from_complex_subject(subject) + data_from_complex_session(session) + data_from_complex_modality(modality) + + @meta.to_json + end + + def data_from_complex_subject(subject) + @meta["Subject ID"] = subject.id + @meta["Subject Species"] = subject.subject_species + @meta["Subject type"] = subject.subject_type + @meta["Subject sex"] = subject.subject_sex + @meta["Subject age"] = subject.subject_age + end + + def data_from_complex_session(session) + # TODO Date recorded curruntly fetch from ComplexDate we need to confirm is this correct? + end + + def data_from_complex_modality(modality) + @meta["Modality"] = modality.modality + end + + def data_from_crc_dataset(crc_dataset) + @meta["DublinCore-Title"] = crc_dataset.title[0] + @meta["Experiment title"] = crc_dataset.title[0] + @meta["DataCite-Title"] = crc_dataset.title[0] + @meta["DublinCore-Language"] = crc_dataset.language[0] + @meta["DataCite-Language"] = crc_dataset.language[0] + @meta["Resource Type"] = crc_dataset.resource_type[0] + @meta["Experiment Description"] = crc_dataset.experiment_description[0] + @meta["Group ID"] = "" # Complex Identifier removed + @meta["Animal|Ethics approval No."] = crc_dataset.approval_number + @meta["DublinCore-Subject"] = crc_dataset.subject.join("; ") + @meta["DataCite-Subject"] = crc_dataset.subject.join("; ") + @meta["DublinCore-Publisher"] = crc_dataset.publisher[0] + @meta["DataCite-Publisher"] = crc_dataset.publisher[0] + @meta["DublinCore-Coverage"] = crc_dataset.coverage + @meta["Software version"] = "" # TODO we don't have for now + @meta["Extra information"] = crc_dataset.extra_information[0] + + data_from_complex_person(crc_dataset.complex_person) + data_from_complex_date(crc_dataset.complex_date) + data_from_complex_funding_reference(crc_dataset.complex_funding_reference) + end + + def data_from_complex_person(complex_person) + return unless complex_person.any? + + complex_person = complex_person.group_by{ |p| p.role[0] } + + unless complex_person["creator"].nil? + @meta["Creator"] = complex_person["creator"].map{ |creator| "#{creator.first_name[0]}, #{creator.last_name[0]}" }.compact.join("; ") + @meta["DataCite-creatorName"] = @meta["Creator"] + @meta["DublinCore-Creator"] = @meta["Creator"] + @meta["DataCite-creatorFamilyName"] = complex_person["creator"].map{ |creator| creator.first_name[0] }.compact.join("; ") + @meta["DataCite-creatorGivenName"] = complex_person["creator"].map{ |creator| creator.last_name[0] }.compact.join("; ") + @meta["DataCite-creatorAffiliation"] = complex_person["creator"].map{ |creator| creator.affiliation[0] }.compact.join("; ") + @meta["DataCite-creatorNameIdentifier"] = complex_person["creator"].map{ |creator| creator.orcid[0] }.compact.join("; ") + end + + unless complex_person["contributor"].nil? + @meta["contributor"] = complex_person["contributor"].map{ |contributor| "#{contributor.first_name[0]}, #{contributor.last_name[0]}" }.compact.join("; ") + @meta["DataCite-contributorName"] = @meta["contributor"] + @meta["DublinCore-Contributor"] = @meta["contributor"] + @meta["DataCite-contributorFamilyName"] = complex_person["contributor"].map{ |contributor| contributor.first_name[0] }.compact.join("; ") + @meta["DataCite-contributorGivenName"] = complex_person["contributor"].map{ |contributor| contributor.last_name[0] }.compact.join("; ") + @meta["DataCite-contirbutorAffiliation"] = complex_person["contributor"].map{ |contributor| contributor.affiliation[0] }.compact.join("; ") + @meta["DataCite-contributorNameIdentifier"] = complex_person["contributor"].map{ |contributor| contributor.orcid[0] }.compact.join("; ") + end + end + + def data_from_complex_funding_reference(complex_funding_reference) + return unless complex_funding_reference.any? + + @meta["DataCite-FundingReference"] = complex_funding_reference.map{ |funding| funding.funder_name[0] }.compact.join("; ") + @meta["DataCite-funderIdentifier"] = complex_funding_reference.map{ |funding| funding.funder_identifier[0] }.compact.join("; ") + end + + def data_from_complex_date(complex_dates) + return unless complex_dates.any? + + @meta["Record date"] = complex_dates.map{ |complex_date| complex_date.date[0] if complex_date.description[0] == "Recorded" }.compact.join("; ") + @meta["DataCite-dateType"] = complex_dates.map{ |complex_date| complex_date.description[0] if complex_date.description[0] != "Recorded" }.compact.join("; ") + @meta["DataCite-Date"] = complex_dates.map{ |complex_date| complex_date.date[0] if complex_date.description[0] != "Recorded" }.compact.join("; ") + @meta["DublinCore-Date"] = @meta["DataCite-Date"] + end + end diff --git a/hyrax/app/models/crc_dataset.rb b/hyrax/app/models/crc_dataset.rb index 2296d31927fcf8936f9e6023403e22b3f78f03a2..053d47f0a603f6f78632fc873b2fcdbe6c28812c 100755 --- a/hyrax/app/models/crc_dataset.rb +++ b/hyrax/app/models/crc_dataset.rb @@ -6,12 +6,13 @@ class CrcDataset < ActiveFedora::Base include ::Hyrax::WorkBehavior include ::Hyrax::TombstoneBehavior include ExternalServices + include S3FileHandleable self.indexer = CrcDatasetIndexer # Change this to restrict which works can be added as a child. # self.valid_child_concerns = [] validates :title, presence: { message: 'Your CRC dataset must have a title.' } validate :validate_parent_collection - after_save :save_work_meta_json_file_to_s3 + after_save :save_work_meta_json_file_to_s3, :handle_meta_file_on_s3 after_create :set_default_source_and_tombstone_status after_create :register_ark @@ -144,6 +145,10 @@ class CrcDataset < ActiveFedora::Base ComplexSubject.where(parent_source_identifier: source.first) end + def complex_modalities + complex_subjects.map(&:complex_modalities) + end + def file_sets_fast_load_metadata FileSetFastLoadMetadata.sort_and_filter_by_title_and_source(source.first) end