Skip to content

Commit

Permalink
refactor value objects to use borrowed values and lifetimes
Browse files Browse the repository at this point in the history
  • Loading branch information
subotic committed Sep 1, 2023
1 parent 56fbd69 commit aa3cee0
Show file tree
Hide file tree
Showing 10 changed files with 340 additions and 261 deletions.
5 changes: 5 additions & 0 deletions src/dsp_meta/domain/converter/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
pub mod project;

// Re-exported for convenience.
#[doc(inline)]
pub use project::project_attributes::extract_project_attributes;
pub use project::project_blocks::extract_project_blocks;
145 changes: 2 additions & 143 deletions src/dsp_meta/domain/converter/project/mod.rs
Original file line number Diff line number Diff line change
@@ -1,143 +1,2 @@
use std::collections::HashMap;

use hcl::Block;

use crate::domain::converter::project::project_blocks::parse_project_blocks;
use crate::domain::project::Project;
use crate::domain::{AlternativeNames, Description, ID};
use crate::errors::DspMetaError;

mod project_attributes;
mod project_blocks;

pub fn convert_project_block(project_block: &Block) -> Result<Project, DspMetaError> {
if project_block.identifier.as_str() != "project" {
return Err(crate::errors::DspMetaError::ParseProject(
"Parse error: project block needs to be named 'project'.",
));
}

let project_label = project_block.labels().first().ok_or_else(|| {
DspMetaError::ParseProject("Parse error: project needs to have one label.")
})?;
let id = ID(project_label.as_str());

// extract the project attributes
// created_at, created_by, shortcode, name, teaser_text, how_to_cite, start_date, end_date, datasets, funders, grants

let extracted_attributes =
project_attributes::extract_project_attributes(project_block.body.attributes().collect())?;

let created_at = extracted_attributes.created_at.ok_or_else(|| {
DspMetaError::ParseProject("Parse error: project needs to have a created_at value.")
})?;

let created_by = extracted_attributes.created_by.ok_or_else(|| {
DspMetaError::ParseProject("Parse error: project needs to have a created_by value.")
})?;

let shortcode = extracted_attributes.shortcode.ok_or_else(|| {
DspMetaError::ParseProject("Parse error: project needs to have a shortcode.")
})?;

let name = extracted_attributes
.name
.ok_or_else(|| DspMetaError::ParseProject("Parse error: project needs to have a name."))?;

let teaser_text = extracted_attributes.teaser_text.ok_or_else(|| {
DspMetaError::ParseProject("Parse error: project needs to have a teaser_text.")
})?;

let how_to_cite = extracted_attributes.how_to_cite.ok_or_else(|| {
DspMetaError::ParseProject("Parse error: project needs to have a how_to_cite.")
})?;

let start_date = extracted_attributes.start_date.ok_or_else(|| {
DspMetaError::ParseProject("Parse error: project needs to have a start_date.")
})?;

let end_date = extracted_attributes.end_date;

// extract the project blocks
// alternative_names, description, url, keywords, disciplines, publications)

let project_blocks: Vec<&Block> = project_block.body.blocks().collect();
let _blocks = parse_project_blocks(project_blocks)?;

let alternative_names = AlternativeNames(HashMap::new());
let description = Description(HashMap::new());

let project = Project {
id,
created_at,
created_by,
shortcode,
name,
alternative_names,
teaser_text,
description,
how_to_cite,
start_date,
end_date,
};

Ok(project)
}

#[cfg(test)]
mod tests {
use hcl::block;
use tracing_test::traced_test;

use crate::domain::{
CreatedAt, CreatedBy, EndDate, HowToCite, Name, Shortcode, StartDate, TeaserText,
};

use super::*;

#[traced_test]
#[test]
fn test_convert_project_block() {
let input_project_block = block!(
project {
created_at = 1630601274523025000u64 // FIXME: is there a more readable way to write an i64?
created_by = "dsp-metadata-gui"
shortcode = "0803"
name = "The German Family Panel (pairfam)"
alternative_name "1" {
de = "Der deutsche Familienpanel (pairfam)"
en = "The German Family Panel (pairfam)"
}
teaser_text = "The German Family Panel (pairfam) is a multidisciplinary, longitudinal study."
description {
de = "Der deutsche Familienpanel (pairfam) ist eine multidisziplinäre, längsschnittliche Studie."
en = "The German Family Panel (pairfam) is a multidisciplinary, longitudinal study."
}
how_to_cite = "Huinink, Johannes; Schröder, Carolin; Castiglioni, Laura; Feldhaus, Michael"
start_date = "2009-04-01"
end_date = "2012-03-31"
}
);
let project = super::convert_project_block(&input_project_block).unwrap();
dbg!(&project);
assert_eq!(project.id, ID("0803"));
assert_eq!(project.created_at, CreatedAt(1630601274523025000));
assert_eq!(project.created_by, CreatedBy("dsp-metadata-gui"));
assert_eq!(project.shortcode, Shortcode("0803"));
assert_eq!(project.name, Name("The German Family Panel (pairfam)"));
assert_eq!(
project.teaser_text,
TeaserText(
"The German Family Panel (pairfam) is a multidisciplinary, longitudinal study."
)
);
assert_eq!(
project.how_to_cite,
HowToCite(
"Huinink, Johannes; Schröder, Carolin; Castiglioni, Laura; Feldhaus, Michael"
)
);
assert_eq!(project.start_date, StartDate("2009-04-01"));
assert_eq!(project.end_date, Some(EndDate("2012-03-31")));
}
}
pub mod project_attributes;
pub mod project_blocks;
6 changes: 2 additions & 4 deletions src/dsp_meta/domain/converter/project/project_attributes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::collections::HashMap;

use hcl::{Attribute, Expression};
use tracing::warn;

Expand All @@ -8,7 +6,7 @@ use crate::domain::{
};
use crate::errors::DspMetaError;

pub struct ExtractedAttributes<'a> {
struct ExtractedAttributes<'a> {
pub created_at: Option<CreatedAt>,
pub created_by: Option<CreatedBy<'a>>,
pub shortcode: Option<Shortcode<'a>>,
Expand All @@ -35,7 +33,7 @@ pub fn extract_project_attributes(
match attribute.key() {
"created_at" => {
created_at = match attribute.expr() {
Expression::Number(value) => Ok(Some(CreatedAt(value.as_u64().unwrap()))), /* FIXME: unwrap */
Expression::Number(value) => Ok(Some(CreatedAt(value.as_u64().unwrap()))), /* FIXME: get rid of unwrap */
_ => Err(DspMetaError::ParseProject(
"Parse error: created_at needs to be a number.",
)),
Expand Down
23 changes: 11 additions & 12 deletions src/dsp_meta/domain/converter/project/project_blocks.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
use std::collections::HashMap;

use hcl::Block;

use crate::domain::{AlternativeName, AlternativeNames, Description};
use crate::errors::DspMetaError;

struct ExtractedProjectBlocks<'a> {
pub alternative_names: Vec<AlterntiveName>,
pub alternative_names: AlternativeNames<'a>,
pub description: Option<Description<'a>>,
}

pub fn parse_project_blocks(
blocks: Vec<&Block>,
) -> Result<HashMap<&str, ProjectValue>, DspMetaError> {
let result: HashMap<&str, ProjectValue> = HashMap::new();

pub fn extract_project_blocks(
blocks: Vec<&hcl::Block>,
) -> Result<ExtractedProjectBlocks, DspMetaError> {
for block in blocks {
let mut alternative_names: Vec<&AlternativeName> = vec![];

match block.identifier.as_str() {
"alternative_name" => {
// TODO: how do we handle multiple alternative names?
println!("alternative_name");
dbg!(block);
}
Expand All @@ -31,5 +27,8 @@ pub fn parse_project_blocks(
}
}
}
Ok(result)
Ok(ExtractedProjectBlocks {
alternative_names: AlternativeNames::default(),
description: None,
})
}
33 changes: 17 additions & 16 deletions src/dsp_meta/domain/dataset.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
use serde::{Deserialize, Serialize};
use crate::domain::{Title, ID};
use crate::errors::DspMetaError;

#[derive(Debug, PartialEq, Deserialize, Serialize)]
pub struct Dataset {
pub id: String,
pub title: String,
#[derive(Debug, PartialEq)]
pub struct Dataset<'a> {
pub id: ID<'a>,
pub title: Title<'a>,
}

impl TryFrom<hcl::Block> for Dataset {
type Error = crate::errors::DspMetaError;
impl<'a> TryFrom<&hcl::Block> for Dataset<'a> {
type Error = DspMetaError;

fn try_from(dataset_block: hcl::Block) -> Result<Self, Self::Error> {
fn try_from(dataset_block: &hcl::Block) -> Result<Self, Self::Error> {
if dataset_block.identifier.as_str() != "dataset" {
return Err(crate::errors::DspMetaError::ParseDataset(
return Err(DspMetaError::ParseDataset(
"Parse error: dataset block needs to be named 'dataset'.",
));
}
let id = dataset_block.labels().unwrap().to_string();
let title = dataset_block
.attributes()
.next()
.unwrap()
.value()
.to_string();

let dataset_label = dataset_block.labels().first().ok_or_else(|| {
DspMetaError::ParseDataset("Parse error: dataset needs to have one label.")
})?;
let id = ID(dataset_label.as_str());

let title = Title("TODO: implement title extraction");
Ok(Self { id, title })
}
}
Loading

0 comments on commit aa3cee0

Please sign in to comment.