From e837063465cc302f633f34c6bf7329633edc6429 Mon Sep 17 00:00:00 2001 From: Ivan Subotic <400790+subotic@users.noreply.github.com> Date: Tue, 19 Sep 2023 09:07:21 +0200 Subject: [PATCH] feat: add convert project - temporal_coverage (#41) --- src/dsp_meta/domain/convert/project.rs | 21 +++++ src/dsp_meta/domain/value/mod.rs | 1 + src/dsp_meta/domain/value/spatial_coverage.rs | 7 +- .../domain/value/temporal_coverage.rs | 89 +++++++++++++++++++ 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 src/dsp_meta/domain/value/temporal_coverage.rs diff --git a/src/dsp_meta/domain/convert/project.rs b/src/dsp_meta/domain/convert/project.rs index d08e6c16..87466de6 100644 --- a/src/dsp_meta/domain/convert/project.rs +++ b/src/dsp_meta/domain/convert/project.rs @@ -4,6 +4,7 @@ use tracing::warn; use crate::domain::value::discipline::Discipline; use crate::domain::value::iso_code::IsoCode; use crate::domain::value::spatial_coverage::SpacialCoverage; +use crate::domain::value::temporal_coverage::TemporalCoverage; use crate::domain::value::{ AlternativeName, ContactPoint, CreatedAt, CreatedBy, Description, EndDate, HowToCite, Keyword, LangString, Name, Publication, Shortcode, StartDate, TeaserText, URL, @@ -137,6 +138,7 @@ pub struct ExtractedProjectBlocks { pub keywords: Vec, pub disciplines: Vec, pub spacial_coverages: Vec, + pub temporal_coverages: Vec, pub publications: Vec, } @@ -150,6 +152,7 @@ impl TryFrom> for ExtractedProjectBlocks { let mut keywords: Vec = vec![]; let mut disciplines: Vec = vec![]; let mut spacial_coverages: Vec = vec![]; + let mut temporal_coverages: Vec = vec![]; let mut publications: Vec = vec![]; for block in blocks { @@ -184,6 +187,9 @@ impl TryFrom> for ExtractedProjectBlocks { "spacial_coverage" => { spacial_coverages.push(SpacialCoverage::try_from(block)?); } + "temporal_coverage" => { + temporal_coverages.push(TemporalCoverage::try_from(block)?); + } "publication" => { publications = vec![]; } @@ -200,6 +206,7 @@ impl TryFrom> for ExtractedProjectBlocks { keywords, disciplines, spacial_coverages, + temporal_coverages, publications, }) } @@ -521,6 +528,20 @@ mod tests { assert_eq!(result.spacial_coverages.len(), 1); } + #[test] + fn extract_temporal_coverage() { + let input1 = block!( + temporal_coverage chronontology { + ref_id = "https://chronontology.dainst.org/period/INtagfT8h7Fs" + description = "20th and 21st Centuries" + url = "https://chronontology.dainst.org/period/INtagfT8h7Fs" + } + ); + let blocks = vec![&input1]; + let result = ExtractedProjectBlocks::try_from(blocks).unwrap(); + assert_eq!(result.temporal_coverages.len(), 1); + } + #[test] fn extract_publications() { let blocks = vec![]; diff --git a/src/dsp_meta/domain/value/mod.rs b/src/dsp_meta/domain/value/mod.rs index 20938bf0..1bb4f4ac 100644 --- a/src/dsp_meta/domain/value/mod.rs +++ b/src/dsp_meta/domain/value/mod.rs @@ -9,6 +9,7 @@ pub(crate) mod iso_code; mod lang_text_data; mod ref_data; pub(crate) mod spatial_coverage; +pub(crate) mod temporal_coverage; pub(crate) mod version; #[derive(Debug, Default, Clone, PartialEq)] diff --git a/src/dsp_meta/domain/value/spatial_coverage.rs b/src/dsp_meta/domain/value/spatial_coverage.rs index 1647b3ca..4833dd7d 100644 --- a/src/dsp_meta/domain/value/spatial_coverage.rs +++ b/src/dsp_meta/domain/value/spatial_coverage.rs @@ -1,6 +1,9 @@ use crate::domain::value::ref_data::RefData; use crate::errors::DspMetaError; +const SPACIAL_COVERAGE: &str = "spacial_coverage"; +const GEONAMES: &str = "geonames"; + #[derive(Debug, PartialEq)] pub enum SpacialCoverage { Geonames(RefData), @@ -10,7 +13,7 @@ impl TryFrom<&hcl::Block> for SpacialCoverage { type Error = DspMetaError; fn try_from(block: &hcl::Block) -> Result { - if block.identifier.as_str() != "spacial_coverage" { + if block.identifier.as_str() != SPACIAL_COVERAGE { let msg = format!( "The passed block is not named correctly. Expected 'spacial_coverage', however got '{}' instead.", block.identifier.as_str() @@ -32,7 +35,7 @@ impl TryFrom<&hcl::Block> for SpacialCoverage { let attributes: Vec<&hcl::Attribute> = block.body.attributes().collect(); match reference_data_type.as_str() { - "geonames" => { + GEONAMES => { let ref_data = RefData::try_from(attributes)?; Ok(SpacialCoverage::Geonames(ref_data)) } diff --git a/src/dsp_meta/domain/value/temporal_coverage.rs b/src/dsp_meta/domain/value/temporal_coverage.rs new file mode 100644 index 00000000..94a58616 --- /dev/null +++ b/src/dsp_meta/domain/value/temporal_coverage.rs @@ -0,0 +1,89 @@ +use crate::domain::value::lang_text_data::LangTextData; +use crate::domain::value::ref_data::RefData; +use crate::errors::DspMetaError; + +const TEMPORAL_COVERAGE: &str = "temporal_coverage"; +const CHRONONTOLOGY: &str = "chronontology"; +const PERIODO: &str = "periodo"; + +const TEXT: &str = "text"; + +#[derive(Debug, PartialEq)] +pub enum TemporalCoverage { + Chronontology(RefData), + Periodo(RefData), + Text(LangTextData), +} + +impl TryFrom<&hcl::Block> for TemporalCoverage { + type Error = DspMetaError; + + fn try_from(block: &hcl::Block) -> Result { + if block.identifier.as_str() != TEMPORAL_COVERAGE { + let msg = format!( + "The passed block is not named correctly. Expected 'temporal_coverage', however got '{}' instead.", + block.identifier.as_str() + ); + return Err(DspMetaError::CreateValueObject(msg)); + } + + if block.labels.len() != 1 { + return Err(DspMetaError::CreateValueObject("The passed number of block labels is not correct. Expected '1', namely 'reference data type' (e.g., 'chronontology, periodo').".to_string())); + } + + let reference_data_type = block.labels.first().ok_or_else(|| { + DspMetaError::CreateValueObject( + "The passed spacial_coverage block is missing the reference data type label." + .to_string(), + ) + })?; + + let attributes: Vec<&hcl::Attribute> = block.body.attributes().collect(); + + match reference_data_type.as_str() { + CHRONONTOLOGY => { + let ref_data = RefData::try_from(attributes)?; + Ok(TemporalCoverage::Chronontology(ref_data)) + } + PERIODO => { + let ref_data = RefData::try_from(attributes)?; + Ok(TemporalCoverage::Periodo(ref_data)) + } + TEXT => { + let text_data = LangTextData::try_from(attributes)?; + Ok(TemporalCoverage::Text(text_data)) + } + _ => { + let msg = format!("The passed temporal_coverage block is missing the correct reference data type label. Expected one of '{}', '{}' or '{}'. Got '{}'.", CHRONONTOLOGY, PERIODO, TEXT, reference_data_type.as_str()); + Err(DspMetaError::CreateValueObject(msg)) + } + } + } +} +#[cfg(test)] +mod tests { + use super::*; + use crate::domain::value::ref_data::RefData; + + #[test] + fn test_try_from_block_with_chonontology() { + let block = hcl::block!( + temporal_coverage chronontology { + ref_id = "https://chronontology.dainst.org/period/INtagfT8h7Fs" + description = "20th and 21st Centuries" + url = "https://chronontology.dainst.org/period/INtagfT8h7Fs" + } + ); + + let input = TemporalCoverage::try_from(&block).unwrap(); + let expected = TemporalCoverage::Chronontology(RefData { + ref_id: "https://chronontology.dainst.org/period/INtagfT8h7Fs".to_string(), + description: "20th and 21st Centuries".to_string(), + url: "https://chronontology.dainst.org/period/INtagfT8h7Fs" + .parse() + .unwrap(), + }); + + assert_eq!(input, expected); + } +}