diff --git a/CHANGELOG.md b/CHANGELOG.md index 617ece17..396d77f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed + - [499](https://github.com/thoth-pub/thoth/issues/499) - Default main\_contribution to true + +### Fixed + - [447](https://github.com/thoth-pub/thoth/issues/447) - Prevents Google Books Onix3 format output from Export API if Thoth record doesn't contain at least one BIC, BISAC or LCC subject code + - [404](https://github.com/thoth-pub/thoth/issues/404) - Prevents JSTOR Onix3 format output from Export API if Thoth record doesn't contain at least one BISAC subject code ## [[0.11.16]](https://github.com/thoth-pub/thoth/releases/tag/v0.11.16) - 2024-02-19 ### Changed - - [499](https://github.com/thoth-pub/thoth/issues/499) - Default main\_contribution to true - [561](https://github.com/thoth-pub/thoth/issues/561) - Add "Publisher Website" as a location platform - [553](https://github.com/thoth-pub/thoth/pull/553) - Upgrade rust to `1.76.0` in production and development `Dockerfile` - [305](https://github.com/thoth-pub/thoth/issues/305) - Update rust edition to 2021 diff --git a/thoth-export-server/src/xml/onix3_google_books.rs b/thoth-export-server/src/xml/onix3_google_books.rs index 5fa83b31..0578701a 100644 --- a/thoth-export-server/src/xml/onix3_google_books.rs +++ b/thoth-export-server/src/xml/onix3_google_books.rs @@ -66,20 +66,36 @@ impl XmlSpecification for Onix3GoogleBooks { impl XmlElementBlock for Work { fn xml_element(&self, w: &mut EventWriter) -> ThothResult<()> { + // Don't output works with no BIC, BISAC or LCC subject code + // Google Books can only ingest works which have at least one + + if !self.subjects.iter().any(|s| { + matches!( + s.subject_type, + SubjectType::BISAC | SubjectType::BIC | SubjectType::LCC + ) + }) { + return Err(ThothError::IncompleteMetadataRecord( + ONIX_ERROR.to_string(), + "No BIC, BISAC or LCC subject code".to_string(), + )); + } // Don't output works with no publication date (mandatory in Google Books) if self.publication_date.is_none() { - Err(ThothError::IncompleteMetadataRecord( + return Err(ThothError::IncompleteMetadataRecord( ONIX_ERROR.to_string(), "Missing Publication Date".to_string(), - )) + )); + } // Don't output works with no contributors (at least one required for Google Books) - } else if self.contributions.is_empty() { - Err(ThothError::IncompleteMetadataRecord( + if self.contributions.is_empty() { + return Err(ThothError::IncompleteMetadataRecord( ONIX_ERROR.to_string(), "No contributors supplied".to_string(), - )) + )); + } // We can only generate the document if there's an EPUB or PDF - } else if let Some(main_publication) = self + if let Some(main_publication) = self .publications .iter() // For preference, distribute the EPUB only @@ -1050,7 +1066,6 @@ mod tests { test_work.long_abstract = None; test_work.publications[0].prices.pop(); test_work.publications[0].publication_type = PublicationType::EPUB; - test_work.subjects.clear(); let output = generate_test_output(true, &test_work); // Ebook type changed assert!(!output.contains(r#" E107"#)); @@ -1077,17 +1092,6 @@ mod tests { assert!(!output.contains(r#" "#)); assert!(!output.contains(r#" WORLD"#)); assert!(output.contains(r#" 01"#)); - // No subjects supplied - assert!(!output.contains(r#" "#)); - assert!(!output.contains(r#" 12"#)); - assert!(!output.contains(r#" AAB"#)); - assert!(!output.contains(r#" 10"#)); - assert!(!output.contains(r#" AAA000000"#)); - assert!(!output.contains(r#" 04"#)); - assert!(!output.contains(r#" JA85"#)); - assert!(!output.contains(r#" 23"#)); - assert!(!output.contains(r#" keyword1"#)); - assert!(!output.contains(r#" custom1"#)); // Replace long abstract but remove table of contents // Result: CollateralDetail block still present, but now only contains long abstract @@ -1114,7 +1118,22 @@ mod tests { assert!(!output.contains(r#" 04"#)); assert!(!output.contains(r#" 1. Chapter 1"#)); - // Remove publication date: result is error + // Remove all subjects + // Result: error (can't generate Google Books ONIX without a BIC, BISAC, or LCC subject) + test_work.subjects.clear(); + let output = generate_test_output(false, &test_work); + assert_eq!( + output, + "Could not generate onix_3.0::google_books: No BIC, BISAC or LCC subject code" + .to_string() + ); + + // Reinstate the BIC subject but remove publication date: result is error + test_work.subjects = vec![WorkSubjects { + subject_code: "AAB".to_string(), + subject_type: SubjectType::BIC, + subject_ordinal: 1, + }]; test_work.publication_date = None; let output = generate_test_output(false, &test_work); assert_eq!( diff --git a/thoth-export-server/src/xml/onix3_jstor.rs b/thoth-export-server/src/xml/onix3_jstor.rs index 33338f8f..9026627e 100644 --- a/thoth-export-server/src/xml/onix3_jstor.rs +++ b/thoth-export-server/src/xml/onix3_jstor.rs @@ -60,6 +60,18 @@ impl XmlSpecification for Onix3Jstor { impl XmlElementBlock for Work { fn xml_element(&self, w: &mut EventWriter) -> ThothResult<()> { + // Don't output works with no BISAC subject code + // JSTOR can only ingest works which have at least one + if !self + .subjects + .iter() + .any(|s| matches!(s.subject_type, SubjectType::BISAC)) + { + return Err(ThothError::IncompleteMetadataRecord( + ONIX_ERROR.to_string(), + "No BISAC subject code".to_string(), + )); + } // We can only generate the document if there's a PDF if let Some(pdf_url) = self .publications @@ -969,7 +981,6 @@ mod tests { test_work.place = None; test_work.publication_date = None; test_work.landing_page = None; - test_work.subjects.clear(); test_work.publications[0].publication_type = PublicationType::XML; let output = generate_test_output(true, &test_work); // No DOI supplied @@ -1012,20 +1023,6 @@ mod tests { r#" Publisher's website: web shop"# )); assert!(!output.contains(r#" https://www.book.com"#)); - // No subjects supplied - assert!(!output.contains(r#" "#)); - assert!(!output.contains(r#" 12"#)); - assert!(!output.contains(r#" AAB"#)); - assert!(!output.contains(r#" 10"#)); - assert!(!output.contains(r#" AAA000000"#)); - assert!(!output.contains(r#" 04"#)); - assert!(!output.contains(r#" JA85"#)); - assert!(!output.contains(r#" 93"#)); - assert!(!output.contains(r#" JWA"#)); - assert!(!output.contains(r#" 20"#)); - assert!(!output.contains(r#" keyword1"#)); - assert!(!output.contains(r#" B2"#)); - assert!(!output.contains(r#" custom1"#)); // No print ISBN supplied assert!(!output.contains(r#" "#)); assert!(!output.contains(r#" 13"#)); @@ -1033,9 +1030,23 @@ mod tests { assert!(!output.contains(r#" 15"#)); assert!(!output.contains(r#" 9781402894626"#)); - // Remove the last publication, which is the PDF - // Result: error (can't generate OAPEN ONIX without PDF URL) - test_work.publications.pop(); + // Remove all subjects + // Result: error (can't generate JSTOR ONIX without a BISAC subject) + test_work.subjects.clear(); + let output = generate_test_output(false, &test_work); + assert_eq!( + output, + "Could not generate onix_3.0::jstor: No BISAC subject code".to_string() + ); + + // Reinstate the BISAC subject but remove the only publication, which is the PDF + // Result: error (can't generate JSTOR ONIX without PDF URL) + test_work.subjects = vec![WorkSubjects { + subject_code: "AAA000000".to_string(), + subject_type: SubjectType::BISAC, + subject_ordinal: 1, + }]; + test_work.publications.clear(); let output = generate_test_output(false, &test_work); assert_eq!( output,