Skip to content

Commit

Permalink
feat: convert project - publication (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
subotic authored Sep 19, 2023
1 parent e837063 commit 598c906
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 43 deletions.
13 changes: 10 additions & 3 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
normalize_comments = true
reorder_imports = true
# Basic
max_width = 100
# Imports
group_imports = "StdExternalCrate"
newline_style = "Unix"
imports_granularity = "Module"
reorder_imports = true
# Comments
comment_width = 100
normalize_comments = true
wrap_comments = true
# Consistency
newline_style = "Unix"
18 changes: 9 additions & 9 deletions data/incunabula.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ person "hannes_hug" {
created_at = "1637624150959055000"
created_by = "dsp-metadata-gui"

family_name "1" {
family_name {
text = "Hug"
}
given_name "1" {
given_name {
text = "Hannes"
}
// reference to organization (1-n)
Expand All @@ -142,10 +142,10 @@ person "lukas_rosenthaler" {
created_at = "1637624150959124000"
created_by = "dsp-metadata-gui"

family_name "1" {
family_name {
text = "Rosenthaler"
}
given_name "1" {
given_name {
text = "Lukas"
}
// reference to organization (1-n)
Expand All @@ -156,10 +156,10 @@ person "lothar_schmitt" {
created_at = "1637624150959191000"
created_by = "dsp-metadata-gui"

family_name "1" {
family_name {
text = "Schmitt"
}
given_name "1" {
given_name {
text = "Lothar"
}

Expand All @@ -171,13 +171,13 @@ person "katrin_graf_lamei" {
created_at = "1637624150959244000"
created_by = "dsp-metadata-gui"

family_name "1" {
family_name {
text = "Graf"
}
family_name "2" {
family_name {
text = "Lamei"
}
given_name "1" {
given_name {
text = "Katrin"
}

Expand Down
48 changes: 28 additions & 20 deletions src/dsp_meta/domain/convert/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ use tracing::warn;

use crate::domain::value::discipline::Discipline;
use crate::domain::value::iso_code::IsoCode;
use crate::domain::value::publication::Publication;
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,
LangString, Name, Shortcode, StartDate, TeaserText, URL,
};
use crate::errors::DspMetaError;

Expand Down Expand Up @@ -37,6 +38,7 @@ impl TryFrom<Vec<&hcl::Attribute>> for ExtractedProjectAttributes {
let mut end_date: Option<EndDate> = None;
let mut contact_point: Option<ContactPoint> = None;

// FIXME: throw error on duplicate attributes
for attribute in attributes {
match attribute.key() {
"created_at" => {
Expand Down Expand Up @@ -130,6 +132,15 @@ impl TryFrom<Vec<&hcl::Attribute>> for ExtractedProjectAttributes {
}
}

const ALTERNATIVE_NAME_BLOCK: &str = "alternative_name";
const DESCRIPTION_BLOCK: &str = "description";
const URL_BLOCK: &str = "url";
const KEYWORD_BLOCK: &str = "keyword";
const DISCIPLINE_BLOCK: &str = "discipline";
const SPACIAL_COVERAGE_BLOCK: &str = "spacial_coverage";
const TEMPORAL_COVERAGE_BLOCK: &str = "temporal_coverage";
const PUBLICATION_BLOCK: &str = "publication";

#[derive(Debug, Default, PartialEq)]
pub struct ExtractedProjectBlocks {
pub alternative_names: Vec<AlternativeName>,
Expand Down Expand Up @@ -157,10 +168,10 @@ impl TryFrom<Vec<&hcl::Block>> for ExtractedProjectBlocks {

for block in blocks {
match block.identifier.as_str() {
"alternative_name" => {
ALTERNATIVE_NAME_BLOCK => {
alternative_names.push(AlternativeName::try_from(block)?);
}
"description" => {
DESCRIPTION_BLOCK => {
description = if description.is_none() {
Ok(Some(Description::try_from(block)?))
} else {
Expand All @@ -169,7 +180,7 @@ impl TryFrom<Vec<&hcl::Block>> for ExtractedProjectBlocks {
))
}?
}
"url" => {
URL_BLOCK => {
url = if url.is_none() {
Ok(Some(URL::try_from(block)?))
} else {
Expand All @@ -178,21 +189,13 @@ impl TryFrom<Vec<&hcl::Block>> for ExtractedProjectBlocks {
))
}?
}
"keyword" => {
keywords.push(Keyword::try_from(block)?);
}
"discipline" => {
disciplines.push(Discipline::try_from(block)?);
}
"spacial_coverage" => {
spacial_coverages.push(SpacialCoverage::try_from(block)?);
}
"temporal_coverage" => {
temporal_coverages.push(TemporalCoverage::try_from(block)?);
}
"publication" => {
publications = vec![];
KEYWORD_BLOCK => keywords.push(Keyword::try_from(block)?),
DISCIPLINE_BLOCK => disciplines.push(Discipline::try_from(block)?),
SPACIAL_COVERAGE_BLOCK => spacial_coverages.push(SpacialCoverage::try_from(block)?),
TEMPORAL_COVERAGE_BLOCK => {
temporal_coverages.push(TemporalCoverage::try_from(block)?)
}
PUBLICATION_BLOCK => publications.push(Publication::try_from(block)?),
_ => {
// catch all
warn!("Parse error: unknown block '{}'.", block.identifier);
Expand Down Expand Up @@ -544,9 +547,14 @@ mod tests {

#[test]
fn extract_publications() {
let blocks = vec![];
let input1 = block!(
publication {
text = "A publication"
}
);
let blocks = vec![&input1];
let result = ExtractedProjectBlocks::try_from(blocks).unwrap();
assert_eq!(result.publications.len(), 0);
assert_eq!(result.publications.len(), 1);
}

#[traced_test]
Expand Down
6 changes: 4 additions & 2 deletions src/dsp_meta/domain/entity/project.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::domain::convert::project::{ExtractedProjectAttributes, ExtractedProjectBlocks};
use crate::domain::value::discipline::Discipline;
use crate::domain::value::publication::Publication;
use crate::domain::value::{
AlternativeName, ContactPoint, CreatedAt, CreatedBy, Description, EndDate, HowToCite, Keyword,
Name, Publication, Shortcode, StartDate, TeaserText, URL,
Name, Shortcode, StartDate, TeaserText, URL,
};
use crate::errors::DspMetaError;

Expand Down Expand Up @@ -40,7 +41,8 @@ impl TryFrom<&hcl::Block> for Project {
}

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

let attributes: Vec<&hcl::Attribute> = project_block.body.attributes().collect();

Expand Down
11 changes: 2 additions & 9 deletions src/dsp_meta/domain/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use crate::errors::DspMetaError;
pub(crate) mod discipline;
pub(crate) mod iso_code;
mod lang_text_data;
pub(crate) mod publication;
mod ref_data;
mod simple_text_data;
pub(crate) mod spatial_coverage;
pub(crate) mod temporal_coverage;
pub(crate) mod version;
Expand Down Expand Up @@ -183,12 +185,3 @@ pub struct ContactPoint(pub String);

#[derive(Debug, Default, PartialEq)]
pub struct Title(pub String);

#[derive(Debug, PartialEq)]
pub struct Publication(String);

impl Default for Publication {
fn default() -> Self {
Publication("Default publication".to_string())
}
}
62 changes: 62 additions & 0 deletions src/dsp_meta/domain/value/publication.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use crate::domain::value::simple_text_data::SimpleTextData;
use crate::errors::DspMetaError;

const PUBLICATION_BLOCK_IDENTIFIER: &str = "publication";

#[derive(Debug, PartialEq)]
pub enum Publication {
SimpleText(SimpleTextData),
}

impl TryFrom<&hcl::Block> for Publication {
type Error = DspMetaError;

fn try_from(block: &hcl::Block) -> Result<Self, Self::Error> {
if block.identifier.as_str() != PUBLICATION_BLOCK_IDENTIFIER {
let msg = format!(
"The passed block is not named correctly. Expected 'publication', however got '{}' instead.",
block.identifier.as_str()
);
return Err(DspMetaError::CreateValueObject(msg));
}

let attributes: Vec<&hcl::Attribute> = block.body.attributes().collect();

SimpleTextData::try_from(attributes).map(Publication::SimpleText)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_try_from_correct_block() {
let block = hcl::block!(
publication {
text = "A publication"
}
);

let publication = Publication::try_from(&block).unwrap();

match publication {
Publication::SimpleText(data) => {
assert_eq!(data, SimpleTextData("A publication".to_string()));
}
}
}

#[test]
fn test_try_from_incorrect_block() {
let block = hcl::block!(
publication_other {
text = "A publication"
}
);

let publication = Publication::try_from(&block);

assert!(publication.is_err());
}
}
81 changes: 81 additions & 0 deletions src/dsp_meta/domain/value/simple_text_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use tracing::warn;

use crate::errors::DspMetaError;

const TEXT_ATTRIBUTE_IDENTIFIER: &str = "text";

#[derive(Debug, PartialEq)]
pub struct SimpleTextData(pub String);

impl TryFrom<Vec<&hcl::Attribute>> for SimpleTextData {
type Error = DspMetaError;

fn try_from(attributes: Vec<&hcl::Attribute>) -> Result<Self, Self::Error> {
let mut text_attribute_value: Option<String> = None;

for attribute in attributes {
match attribute.key() {
TEXT_ATTRIBUTE_IDENTIFIER => {
if text_attribute_value.is_some() {
return Err(DspMetaError::CreateValueObject(
"Multiple text attributes are not allowed.".to_string(),
));
}
text_attribute_value = match attribute.expr() {
hcl::Expression::String(value) => Ok(Some(value.to_owned())),
_ => Err(DspMetaError::CreateValueObject(
"The attribute value is not of String type.".to_string(),
)),
}?;
}
_ => {
warn!("Parse error: unknown attribute '{}'.", attribute.key());
}
}
}
Ok(SimpleTextData(text_attribute_value.ok_or_else(|| {
DspMetaError::CreateValueObject("Missing text attribute.".to_string())
})?))
}
}

#[cfg(test)]
mod tests {

use tracing_test::traced_test;

use super::*;

#[test]
fn test_try_from_attributes() {
let attribute = hcl::Attribute::new("text", "some text");
let text_data = SimpleTextData::try_from(vec![&attribute]).unwrap();
assert_eq!(text_data, SimpleTextData("some text".to_string()));
}

#[traced_test]
#[test]
fn test_try_from_attributes_missing_text() {
let attribute = hcl::Attribute::new("some_other_attribute", "some text");
let text_data = SimpleTextData::try_from(vec![&attribute]);
assert!(text_data.is_err());
assert!(logs_contain(
"Parse error: unknown attribute 'some_other_attribute'"
));
}

#[test]
fn test_try_from_attributes_multiple_text() {
let attribute = hcl::Attribute::new("text", "some text");
let attribute2 = hcl::Attribute::new("text", "some text");
let text_data = SimpleTextData::try_from(vec![&attribute, &attribute2]);
assert!(text_data.is_err());
}

#[test]
fn test_try_from_attributes_wrong_type() {
let attribute = hcl::Attribute::new("text", 1);
let text_data = SimpleTextData::try_from(vec![&attribute]);
assert!(text_data.is_err());
}
}

0 comments on commit 598c906

Please sign in to comment.