diff --git a/CHANGELOG.md b/CHANGELOG.md index bce67ef6..1c7def2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [#456](https://github.com/thoth-pub/thoth/pull/456) - Implement JSON output format +### Changed + - [#455](https://github.com/thoth-pub/thoth/pull/455) - Extend CSV output format to include all available fields + ## [[0.9.2]](https://github.com/thoth-pub/thoth/releases/tag/v0.9.2) - 2022-11-01 ### Changed - [#396](https://github.com/thoth-pub/thoth/pull/396) - Expand the list of contribution types with: SoftwareBy, ResearchBy, ContributionsBy, Indexer diff --git a/thoth-export-server/src/csv/csv_thoth.rs b/thoth-export-server/src/csv/csv_thoth.rs index 0f0434c3..f4cb76bb 100644 --- a/thoth-export-server/src/csv/csv_thoth.rs +++ b/thoth-export-server/src/csv/csv_thoth.rs @@ -4,7 +4,7 @@ use std::io::Write; use thoth_client::{ SubjectType, Work, WorkContributions, WorkContributionsAffiliations, WorkFundings, WorkIssues, WorkLanguages, WorkPublications, WorkPublicationsLocations, WorkPublicationsPrices, - WorkRelations, WorkSubjects, + WorkReferences, WorkRelations, WorkSubjects, }; use thoth_errors::ThothResult; @@ -23,6 +23,7 @@ struct CsvThothRow { subtitle: Option, edition: Option, doi: Option, + reference: Option, publication_date: Option, publication_place: Option, license: Option, @@ -45,8 +46,11 @@ struct CsvThothRow { toc: Option, cover_url: Option, cover_caption: Option, + // All child objects with ordinals will be emitted in ordinal order as this + // is how they are retrieved by WorkQuery - don't print out ordinals explicitly + // (except for Series and Relations, as these represent real-world issue/chapter numbers etc) #[serde( - rename = "contributions [(type, first_name, last_name, full_name, orcid, [(position, ordinal, institution)])]" + rename = "contributions [(type, first_name, last_name, full_name, is_main, biography, orcid, website, [(position, institution, institution_doi, ror, country)])]" )] contributions: String, #[serde( @@ -75,8 +79,12 @@ struct CsvThothRow { rename = "funding [(institution, institution_doi, ror, country, program, project, grant, jurisdiction)]" )] funding: String, - #[serde(rename = "relations [(related_work, relation_type, ordinal)]")] + #[serde(rename = "relations [(related_work, doi, relation_type, relation_number)]")] relations: String, + #[serde( + rename = "references [(doi, citation, issn, isbn, journal_title, article_title, series_title, volume_title, edition, author, volume, issue, first_page, component_number, standard_designator, standards_body, publication_date, retrieval_date)]" + )] + references: String, } impl CsvSpecification for CsvThoth { @@ -107,6 +115,7 @@ impl From for CsvThothRow { work_status: format!("{:?}", work.work_status), title: work.title, subtitle: work.subtitle, + reference: work.reference, edition: work.edition, doi: work.doi.map(|d| d.to_string()), publication_date: work.publication_date.map(|d| d.to_string()), @@ -215,6 +224,13 @@ impl From for CsvThothRow { .map(CsvCell::::csv_cell) .collect::>(), ), + references: CsvCell::::csv_cell( + &work + .references + .iter() + .map(CsvCell::::csv_cell) + .collect::>(), + ), } } } @@ -303,16 +319,19 @@ impl CsvCell for WorkPublications { impl CsvCell for WorkContributions { fn csv_cell(&self) -> String { format!( - "(\"{:?}\", \"{}\", \"{}\", \"{}\", \"{}\", {})", + "(\"{:?}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", {})", self.contribution_type, self.first_name.clone().unwrap_or_default(), self.last_name, self.full_name, + self.main_contribution, + self.biography.clone().unwrap_or_default(), self.contributor .orcid .as_ref() .map(|o| o.to_string()) .unwrap_or_default(), + self.contributor.website.clone().unwrap_or_default(), CsvCell::::csv_cell( &self .affiliations @@ -345,10 +364,24 @@ impl CsvCell for WorkPublicationsLocations { impl CsvCell for WorkContributionsAffiliations { fn csv_cell(&self) -> String { format!( - "(\"{}\", \"{}\", \"{}\")", + "(\"{}\", \"{}\", \"{}\", \"{}\", \"{}\")", self.position.clone().unwrap_or_default(), - self.affiliation_ordinal, self.institution.institution_name, + self.institution + .institution_doi + .as_ref() + .map(|d| d.to_string()) + .unwrap_or_default(), + self.institution + .ror + .as_ref() + .map(|r| r.to_string()) + .unwrap_or_default(), + self.institution + .country_code + .as_ref() + .map(|c| format!("{:?}", c)) + .unwrap_or_default(), ) } } @@ -380,7 +413,7 @@ impl CsvCell for WorkLanguages { impl CsvCell for WorkSubjects { fn csv_cell(&self) -> String { - format!("{:?}", self.subject_code) + format!("\"{}\"", self.subject_code) } } @@ -415,8 +448,41 @@ impl CsvCell for WorkFundings { impl CsvCell for WorkRelations { fn csv_cell(&self) -> String { format!( - "(\"{}\", \"{:?}\", \"{}\")", - self.related_work.full_title, self.relation_type, self.relation_ordinal, + "(\"{}\", \"{}\", \"{:?}\", \"{}\")", + self.related_work.full_title, + self.related_work + .doi + .as_ref() + .map(|d| d.to_string()) + .unwrap_or_default(), + self.relation_type, + self.relation_ordinal, + ) + } +} + +impl CsvCell for WorkReferences { + fn csv_cell(&self) -> String { + format!( + "(\"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\")", + self.doi.as_ref().map(|d| d.to_string()).unwrap_or_default(), + self.unstructured_citation.clone().unwrap_or_default(), + self.issn.clone().unwrap_or_default(), + self.isbn.as_ref().map(|i| i.to_string()).unwrap_or_default(), + self.journal_title.clone().unwrap_or_default(), + self.article_title.clone().unwrap_or_default(), + self.series_title.clone().unwrap_or_default(), + self.volume_title.clone().unwrap_or_default(), + self.edition.as_ref().map(|e| e.to_string()).unwrap_or_default(), + self.author.clone().unwrap_or_default(), + self.volume.clone().unwrap_or_default(), + self.issue.clone().unwrap_or_default(), + self.first_page.clone().unwrap_or_default(), + self.component_number.clone().unwrap_or_default(), + self.standard_designator.clone().unwrap_or_default(), + self.standards_body_name.clone().unwrap_or_default(), + self.publication_date.map(|d| d.to_string()).unwrap_or_default(), + self.retrieval_date.map(|d| d.to_string()).unwrap_or_default(), ) } } @@ -451,9 +517,9 @@ mod tests { title: "Book Title".to_string(), subtitle: Some("Book Subtitle".to_string()), work_type: WorkType::MONOGRAPH, - reference: None, edition: Some(1), doi: Some(Doi::from_str("https://doi.org/10.00001/BOOK.0001").unwrap()), + reference: Some("IntRef1".to_string()), publication_date: Some(chrono::NaiveDate::from_ymd(1999, 12, 31)), license: Some("http://creativecommons.org/licenses/by/4.0/".to_string()), copyright_holder: Some("Author 1; Author 2".to_string()), @@ -504,7 +570,7 @@ mod tests { last_name: "1".to_string(), full_name: "Author 1".to_string(), main_contribution: true, - biography: None, + biography: Some("Author 1 is an author".to_string()), contribution_ordinal: 1, contributor: WorkContributionsContributor { orcid: Some(Orcid::from_str("https://orcid.org/0000-0002-0000-0001").unwrap()), @@ -517,7 +583,7 @@ mod tests { institution: WorkContributionsAffiliationsInstitution { institution_name: "University of Life".to_string(), institution_doi: None, - ror: None, + ror: Some(Ror::from_str("https://ror.org/0abcdef12").unwrap()), country_code: None, }, }, @@ -754,7 +820,7 @@ mod tests { title: "N/A".to_string(), subtitle: None, edition: None, - doi: None, + doi: Some(Doi::from_str("https://doi.org/10.00001/RELATION.0001").unwrap()), publication_date: None, license: None, short_abstract: None, @@ -774,12 +840,33 @@ mod tests { fundings: vec![], }, }], - references: vec![] + references: vec![WorkReferences { + reference_ordinal: 1, + doi: Some(Doi::from_str("https://doi.org/10.00001/reference").unwrap()), + unstructured_citation: Some("Author, A. (2022) Article, Journal.".to_string()), + issn: Some("1111-2222".to_string()), + isbn: None, + journal_title: Some("Journal".to_string()), + article_title: Some("Article".to_string()), + series_title: None, + volume_title: None, + edition: None, + author: Some("Author, A".to_string()), + volume: None, + issue: None, + first_page: Some("3".to_string()), + component_number: None, + standard_designator: None, + standards_body_name: None, + standards_body_acronym: None, + publication_date: Some(chrono::NaiveDate::from_ymd(2022, 1, 1)), + retrieval_date: Some(chrono::NaiveDate::from_ymd(2022, 12, 31)), + }], }; } - const TEST_RESULT: &str = r#""publisher","imprint","work_type","work_status","title","subtitle","edition","doi","publication_date","publication_place","license","copyright_holder","landing_page","page_count","page_breakdown","first_page","last_page","page_interval","image_count","table_count","audio_count","video_count","lccn","oclc","short_abstract","long_abstract","general_note","toc","cover_url","cover_caption","contributions [(type, first_name, last_name, full_name, orcid, [(position, ordinal, institution)])]","publications [(type, isbn, width (mm), width (cm), width (in), height (mm), height (cm), height (in), depth (mm), depth (cm), depth (in), weight (g), weight (oz), [(ISO_4217_currency, price)], [(landing_page, full_text, platform, is_canonical)])]","series [(type, name, issn_print, issn_digital, url, cfp_url, description, issue)]","languages [(relation, ISO_639-3/B_language, is_main)]","BIC [code]","THEMA [code]","BISAC [code]","LCC [code]","custom_categories [category]","keywords [keyword]","funding [(institution, institution_doi, ror, country, program, project, grant, jurisdiction)]","relations [(related_work, relation_type, ordinal)]" -"OA Editions","OA Editions Imprint","MONOGRAPH","ACTIVE","Book Title","Book Subtitle","1","10.00001/BOOK.0001","1999-12-31","León, Spain","http://creativecommons.org/licenses/by/4.0/","Author 1; Author 2","https://www.book.com","334","x+334","","","","15","20","25","30","123456789","987654321","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vel libero eleifend, ultrices purus vitae, suscipit ligula. Aliquam ornare quam et nulla vestibulum, id euismod tellus malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vel libero eleifend, ultrices purus vitae, suscipit ligula. Aliquam ornare quam et nulla vestibulum, id euismod tellus malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam ornare bibendum ex nec dapibus. Proin porta risus elementum odio feugiat tempus. Etiam eu felis ac metus viverra ornare. In consectetur neque sed feugiat ornare. Mauris at purus fringilla orci tincidunt pulvinar sed a massa. Nullam vestibulum posuere augue, sit amet tincidunt nisl pulvinar ac.","This is a general note","1. Chapter 1","https://www.book.com/cover","This is a cover caption","[(""AUTHOR"", ""Author"", ""1"", ""Author 1"", ""0000-0002-0000-0001"", [(""Manager"", ""1"", ""University of Life"")]),(""AUTHOR"", ""Author"", ""2"", ""Author 2"", """", )]","[(""PAPERBACK"", ""978-3-16-148410-0"", ""156"", ""15.6"", ""6.14"", ""234"", ""23.4"", ""9.21"", ""25"", ""2.5"", ""1"", ""152"", ""5.3616"", [(""EUR"", ""25.95""),(""GBP"", ""22.95""),(""USD"", ""31.95"")], [(""https://www.book.com/paperback"", """", ""OTHER"", ""true""),(""https://www.jstor.com/paperback"", """", ""JSTOR"", ""false"")]),(""HARDBACK"", ""978-1-4028-9462-6"", """", """", """", """", """", """", """", """", """", """", """", [(""EUR"", ""36.95""),(""GBP"", ""32.95""),(""USD"", ""40.95"")], ),(""PDF"", ""978-1-56619-909-4"", """", """", """", """", """", """", """", """", """", """", """", , [(""https://www.book.com/pdf_landing"", ""https://www.book.com/pdf_fulltext"", ""OTHER"", ""true"")]),(""HTML"", """", """", """", """", """", """", """", """", """", """", """", """", , [(""https://www.book.com/html_landing"", ""https://www.book.com/html_fulltext"", ""OTHER"", ""true"")]),(""XML"", ""978-92-95055-02-5"", """", """", """", """", """", """", """", """", """", """", """", , )]","[(""JOURNAL"", ""Name of series"", ""1234-5678"", ""8765-4321"", ""https://www.series.com"", ""https://www.series.com/cfp"", ""Description of series"", ""1"")]","[(""ORIGINAL"", ""SPA"", ""true"")]","[""AAA"",""AAB""]","[""JWA""]","[""AAA000000"",""AAA000001""]","[""JA85""]","[""Category1""]","[""keyword1"",""keyword2""]","[(""Name of institution"", ""10.00001/INSTITUTION.0001"", ""0aaaaaa00"", ""MDA"", ""Name of program"", ""Name of project"", ""Number of grant"", ""Funding jurisdiction"")]","[(""Related work title"", ""HAS_CHILD"", ""1"")]" + const TEST_RESULT: &str = r#""publisher","imprint","work_type","work_status","title","subtitle","edition","doi","reference","publication_date","publication_place","license","copyright_holder","landing_page","page_count","page_breakdown","first_page","last_page","page_interval","image_count","table_count","audio_count","video_count","lccn","oclc","short_abstract","long_abstract","general_note","toc","cover_url","cover_caption","contributions [(type, first_name, last_name, full_name, is_main, biography, orcid, website, [(position, institution, institution_doi, ror, country)])]","publications [(type, isbn, width (mm), width (cm), width (in), height (mm), height (cm), height (in), depth (mm), depth (cm), depth (in), weight (g), weight (oz), [(ISO_4217_currency, price)], [(landing_page, full_text, platform, is_canonical)])]","series [(type, name, issn_print, issn_digital, url, cfp_url, description, issue)]","languages [(relation, ISO_639-3/B_language, is_main)]","BIC [code]","THEMA [code]","BISAC [code]","LCC [code]","custom_categories [category]","keywords [keyword]","funding [(institution, institution_doi, ror, country, program, project, grant, jurisdiction)]","relations [(related_work, doi, relation_type, relation_number)]","references [(doi, citation, issn, isbn, journal_title, article_title, series_title, volume_title, edition, author, volume, issue, first_page, component_number, standard_designator, standards_body, publication_date, retrieval_date)]" +"OA Editions","OA Editions Imprint","MONOGRAPH","ACTIVE","Book Title","Book Subtitle","1","10.00001/BOOK.0001","IntRef1","1999-12-31","León, Spain","http://creativecommons.org/licenses/by/4.0/","Author 1; Author 2","https://www.book.com","334","x+334","","","","15","20","25","30","123456789","987654321","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vel libero eleifend, ultrices purus vitae, suscipit ligula. Aliquam ornare quam et nulla vestibulum, id euismod tellus malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vel libero eleifend, ultrices purus vitae, suscipit ligula. Aliquam ornare quam et nulla vestibulum, id euismod tellus malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam ornare bibendum ex nec dapibus. Proin porta risus elementum odio feugiat tempus. Etiam eu felis ac metus viverra ornare. In consectetur neque sed feugiat ornare. Mauris at purus fringilla orci tincidunt pulvinar sed a massa. Nullam vestibulum posuere augue, sit amet tincidunt nisl pulvinar ac.","This is a general note","1. Chapter 1","https://www.book.com/cover","This is a cover caption","[(""AUTHOR"", ""Author"", ""1"", ""Author 1"", ""true"", ""Author 1 is an author"", ""0000-0002-0000-0001"", """", [(""Manager"", ""University of Life"", """", ""0abcdef12"", """")]),(""AUTHOR"", ""Author"", ""2"", ""Author 2"", ""true"", """", """", """", )]","[(""PAPERBACK"", ""978-3-16-148410-0"", ""156"", ""15.6"", ""6.14"", ""234"", ""23.4"", ""9.21"", ""25"", ""2.5"", ""1"", ""152"", ""5.3616"", [(""EUR"", ""25.95""),(""GBP"", ""22.95""),(""USD"", ""31.95"")], [(""https://www.book.com/paperback"", """", ""OTHER"", ""true""),(""https://www.jstor.com/paperback"", """", ""JSTOR"", ""false"")]),(""HARDBACK"", ""978-1-4028-9462-6"", """", """", """", """", """", """", """", """", """", """", """", [(""EUR"", ""36.95""),(""GBP"", ""32.95""),(""USD"", ""40.95"")], ),(""PDF"", ""978-1-56619-909-4"", """", """", """", """", """", """", """", """", """", """", """", , [(""https://www.book.com/pdf_landing"", ""https://www.book.com/pdf_fulltext"", ""OTHER"", ""true"")]),(""HTML"", """", """", """", """", """", """", """", """", """", """", """", """", , [(""https://www.book.com/html_landing"", ""https://www.book.com/html_fulltext"", ""OTHER"", ""true"")]),(""XML"", ""978-92-95055-02-5"", """", """", """", """", """", """", """", """", """", """", """", , )]","[(""JOURNAL"", ""Name of series"", ""1234-5678"", ""8765-4321"", ""https://www.series.com"", ""https://www.series.com/cfp"", ""Description of series"", ""1"")]","[(""ORIGINAL"", ""SPA"", ""true"")]","[""AAA"",""AAB""]","[""JWA""]","[""AAA000000"",""AAA000001""]","[""JA85""]","[""Category1""]","[""keyword1"",""keyword2""]","[(""Name of institution"", ""10.00001/INSTITUTION.0001"", ""0aaaaaa00"", ""MDA"", ""Name of program"", ""Name of project"", ""Number of grant"", ""Funding jurisdiction"")]","[(""Related work title"", ""10.00001/RELATION.0001"", ""HAS_CHILD"", ""1"")]","[(""10.00001/reference"", ""Author, A. (2022) Article, Journal."", ""1111-2222"", """", ""Journal"", ""Article"", """", """", """", ""Author, A"", """", """", ""3"", """", """", """", ""2022-01-01"", ""2022-12-31"")]" "#; #[test] @@ -861,24 +948,27 @@ mod tests { last_name: "1".to_string(), full_name: "Author 1".to_string(), main_contribution: true, - biography: None, + biography: Some("Author 1 was born".to_string()), contribution_ordinal: 1, contributor: WorkContributionsContributor { orcid: Some(Orcid::from_str("https://orcid.org/0000-0002-0000-0001").unwrap()), - website: None, + website: Some("https://www.author1.org".to_string()), }, affiliations: vec![], }; assert_eq!( CsvCell::::csv_cell(&contribution), - r#"("AUTHOR", "Author", "1", "Author 1", "0000-0002-0000-0001", )"#.to_string() + r#"("AUTHOR", "Author", "1", "Author 1", "true", "Author 1 was born", "0000-0002-0000-0001", "https://www.author1.org", )"#.to_string() ); contribution.contribution_type = ContributionType::TRANSLATOR; contribution.first_name = None; + contribution.main_contribution = false; + contribution.biography = None; contribution.contributor.orcid = None; + contribution.contributor.website = None; assert_eq!( CsvCell::::csv_cell(&contribution), - r#"("TRANSLATOR", "", "1", "Author 1", "", )"#.to_string() + r#"("TRANSLATOR", "", "1", "Author 1", "false", "", "", "", )"#.to_string() ); } @@ -889,20 +979,26 @@ mod tests { affiliation_ordinal: 1, institution: WorkContributionsAffiliationsInstitution { institution_name: "University of Life".to_string(), - institution_doi: None, - ror: None, - country_code: None, + institution_doi: Some( + Doi::from_str("https://doi.org/10.00001/INSTITUTION.0001").unwrap(), + ), + ror: Some(Ror::from_str("https://ror.org/0abcdef12").unwrap()), + country_code: Some(CountryCode::MDA), }, }; assert_eq!( CsvCell::::csv_cell(&affiliation), - r#"("Manager", "1", "University of Life")"#.to_string() + r#"("Manager", "University of Life", "10.00001/INSTITUTION.0001", "0abcdef12", "MDA")"# + .to_string() ); affiliation.position = None; - affiliation.affiliation_ordinal = 2; + affiliation.institution.institution_name = "Polytechnic of Life".to_string(); + affiliation.institution.institution_doi = None; + affiliation.institution.ror = None; + affiliation.institution.country_code = None; assert_eq!( CsvCell::::csv_cell(&affiliation), - r#"("", "2", "University of Life")"#.to_string() + r#"("", "Polytechnic of Life", "", "", "")"#.to_string() ); } @@ -1047,7 +1143,7 @@ mod tests { title: "N/A".to_string(), subtitle: None, edition: None, - doi: None, + doi: Some(Doi::from_str("https://doi.org/10.00001/RELATION.0001").unwrap()), publication_date: None, license: None, short_abstract: None, @@ -1069,14 +1165,67 @@ mod tests { }; assert_eq!( CsvCell::::csv_cell(&relation), - r#"("Related work title", "HAS_CHILD", "1")"#.to_string() + r#"("Related work title", "10.00001/RELATION.0001", "HAS_CHILD", "1")"#.to_string() ); relation.relation_type = RelationType::IS_TRANSLATION_OF; relation.relation_ordinal = 2; relation.related_work.full_title = "Different related work title".to_string(); + relation.related_work.doi = None; assert_eq!( CsvCell::::csv_cell(&relation), - r#"("Different related work title", "IS_TRANSLATION_OF", "2")"#.to_string() + r#"("Different related work title", "", "IS_TRANSLATION_OF", "2")"#.to_string() + ); + } + + #[test] + fn test_csv_thoth_references() { + let mut reference = WorkReferences { + reference_ordinal: 1, + doi: Some(Doi::from_str("https://doi.org/10.00001/reference").unwrap()), + unstructured_citation: Some("Author, A. (2022) Article, Journal.".to_string()), + issn: Some("1111-2222".to_string()), + isbn: None, + journal_title: Some("Journal".to_string()), + article_title: Some("Article".to_string()), + series_title: None, + volume_title: None, + edition: None, + author: Some("Author, A".to_string()), + volume: None, + issue: None, + first_page: Some("3".to_string()), + component_number: None, + standard_designator: Some("14064-1".to_string()), + standards_body_name: Some("International Organization for Standardization".to_string()), + standards_body_acronym: None, + publication_date: Some(chrono::NaiveDate::from_ymd(2022, 1, 1)), + retrieval_date: Some(chrono::NaiveDate::from_ymd(2022, 12, 31)), + }; + assert_eq!( + CsvCell::::csv_cell(&reference), + r#"("10.00001/reference", "Author, A. (2022) Article, Journal.", "1111-2222", "", "Journal", "Article", "", "", "", "Author, A", "", "", "3", "", "14064-1", "International Organization for Standardization", "2022-01-01", "2022-12-31")"#.to_string() + ); + reference.doi = None; + reference.unstructured_citation = None; + reference.issn = None; + reference.isbn = Some(Isbn::from_str("978-92-95055-02-5").unwrap()); + reference.journal_title = None; + reference.article_title = None; + reference.series_title = Some("Series".to_string()); + reference.volume_title = Some("Volume".to_string()); + reference.edition = Some(41); + reference.author = None; + reference.volume = Some("5".to_string()); + reference.issue = Some("99".to_string()); + reference.first_page = None; + reference.component_number = Some("13".to_string()); + reference.standard_designator = None; + reference.standards_body_name = None; + reference.publication_date = None; + reference.retrieval_date = None; + assert_eq!( + CsvCell::::csv_cell(&reference), + r#"("", "", "", "978-92-95055-02-5", "", "", "Series", "Volume", "41", "", "5", "99", "", "13", "", "", "", "")"#.to_string() ); } }