1use crate::journal::{article::JournalArticle, issue::JournalIssue, metadata::JournalMetadata};
2use serde::Serialize;
3use validator::Validate;
4
5pub mod article;
6pub mod issue;
7pub mod metadata;
8
9#[derive(Debug, Clone, Default, Serialize, Validate)]
10#[serde(rename = "journal")]
11pub struct Journal {
12 #[validate(nested)]
13 pub journal_metadata: JournalMetadata,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 #[validate(nested)]
16 pub journal_issue: Option<JournalIssue>,
17 #[serde(default, skip_serializing_if = "Vec::is_empty")]
18 #[validate(nested)]
19 pub journal_article: Vec<JournalArticle>,
20}
21
22#[cfg(test)]
23mod unit {
24 use super::*;
25 use crate::enums::{ContentVersion, Iso639_1, MediaType, MediaTypeDate, PublicationType};
26 use crate::journal::article::JournalArticle;
27 use crate::journal::issue::{JournalIssue, PublicationDate, Titles};
28 use crate::journal::metadata::{ArchiveLocations, DoiData, Issn, JournalMetadata, Resource};
29
30 fn valid_journal() -> Journal {
31 Journal {
32 journal_metadata: JournalMetadata {
33 lang: Iso639_1::En,
34 full_title: "Example Journal".to_string(),
35 abbrev_title: Some("Ex. J.".to_string()),
36 issn: Some(Issn {
37 media_type: MediaType::Electronic,
38 value: "1234-5678".to_string(),
39 }),
40 coden: None,
41 archive_locations: ArchiveLocations::default(),
42 doi_data: DoiData {
43 doi: "10.1234/journal".to_string(),
44 timestamp: (),
45 resource: Resource {
46 value: "https://example.com/journal".to_string(),
47 mime_type: None,
48 content_version: ContentVersion::Vor,
49 },
50 },
51 },
52 journal_issue: None,
53 journal_article: vec![],
54 }
55 }
56
57 #[test]
58 fn valid_journal_passes() {
59 let journal = valid_journal();
60 assert!(journal.validate().is_ok());
61 }
62
63 #[test]
64 fn journal_with_issue_passes() {
65 let mut journal = valid_journal();
66 journal.journal_issue = Some(JournalIssue {
67 contributors: vec![],
68 titles: Some(Titles {
69 title: "Issue 1".to_string(),
70 subtitle: None,
71 original_language_title: None,
72 orginal_language_subtitle: None,
73 }),
74 publication_date: PublicationDate {
75 media_type: MediaTypeDate::Online,
76 month: Some(6),
77 day: Some(15),
78 year: 2024,
79 },
80 issue: Some("1".to_string()),
81 special_numbering: None,
82 archive_locations: ArchiveLocations::default(),
83 doi_data: DoiData {
84 doi: "10.1234/issue.001".to_string(),
85 timestamp: (),
86 resource: Resource {
87 value: "https://example.com/issue/1".to_string(),
88 mime_type: None,
89 content_version: ContentVersion::Vor,
90 },
91 },
92 });
93 assert!(journal.validate().is_ok());
94 }
95
96 #[test]
97 fn journal_with_articles_passes() {
98 let mut journal = valid_journal();
99 journal.journal_article = vec![JournalArticle {
100 publication_type: PublicationType::FullText,
101 language: Iso639_1::En,
102 titles: Titles {
103 title: "Example Article".to_string(),
104 subtitle: None,
105 original_language_title: None,
106 orginal_language_subtitle: None,
107 },
108 contributors: vec![],
109 jats_abstract: None,
110 publication_date: PublicationDate {
111 media_type: MediaTypeDate::Online,
112 month: Some(6),
113 day: Some(15),
114 year: 2024,
115 },
116 acceptance_date: None,
117 pages: None,
118 publisher_item: None,
119 crossmark: None,
120 archive_locations: ArchiveLocations::default(),
121 doi_data: DoiData {
122 doi: "10.1234/article.001".to_string(),
123 timestamp: (),
124 resource: Resource {
125 value: "https://example.com/article".to_string(),
126 mime_type: None,
127 content_version: ContentVersion::Vor,
128 },
129 },
130 citation_list: Default::default(),
131 component_list: Default::default(),
132 }];
133 assert!(journal.validate().is_ok());
134 }
135
136 #[test]
137 fn journal_with_invalid_metadata_fails() {
138 let mut journal = valid_journal();
139 journal.journal_metadata.full_title = "".to_string(); assert!(journal.validate().is_err());
141 }
142
143 #[test]
144 fn journal_with_invalid_issue_fails() {
145 let mut journal = valid_journal();
146 journal.journal_issue = Some(JournalIssue {
147 contributors: vec![],
148 titles: None,
149 publication_date: PublicationDate {
150 media_type: MediaTypeDate::Online,
151 month: None,
152 day: None,
153 year: 1000, },
155 issue: None,
156 special_numbering: None,
157 archive_locations: ArchiveLocations::default(),
158 doi_data: DoiData {
159 doi: "10.1234/issue.001".to_string(),
160 timestamp: (),
161 resource: Resource {
162 value: "https://example.com/issue/1".to_string(),
163 mime_type: None,
164 content_version: ContentVersion::Vor,
165 },
166 },
167 });
168 assert!(journal.validate().is_err());
169 }
170
171 #[test]
172 fn journal_with_invalid_article_fails() {
173 let mut journal = valid_journal();
174 journal.journal_article = vec![JournalArticle {
175 publication_type: PublicationType::FullText,
176 language: Iso639_1::En,
177 titles: Titles {
178 title: "Example Article".to_string(),
179 subtitle: None,
180 original_language_title: None,
181 orginal_language_subtitle: None,
182 },
183 contributors: vec![],
184 jats_abstract: None,
185 publication_date: PublicationDate {
186 media_type: MediaTypeDate::Online,
187 month: None,
188 day: None,
189 year: 1000, },
191 acceptance_date: None,
192 pages: None,
193 publisher_item: None,
194 crossmark: None,
195 archive_locations: ArchiveLocations::default(),
196 doi_data: DoiData {
197 doi: "10.1234/article.001".to_string(),
198 timestamp: (),
199 resource: Resource {
200 value: "https://example.com/article".to_string(),
201 mime_type: None,
202 content_version: ContentVersion::Vor,
203 },
204 },
205 citation_list: Default::default(),
206 component_list: Default::default(),
207 }];
208 assert!(journal.validate().is_err());
209 }
210
211 #[test]
212 fn minimal_journal_passes() {
213 let journal = Journal {
214 journal_metadata: JournalMetadata {
215 lang: Iso639_1::En,
216 full_title: "J".to_string(),
217 abbrev_title: None,
218 issn: None,
219 coden: None,
220 archive_locations: ArchiveLocations::default(),
221 doi_data: DoiData {
222 doi: "10.1234/j".to_string(),
223 timestamp: (),
224 resource: Resource {
225 value: "https://example.com".to_string(),
226 mime_type: None,
227 content_version: ContentVersion::Vor,
228 },
229 },
230 },
231 journal_issue: None,
232 journal_article: vec![],
233 };
234 assert!(journal.validate().is_ok());
235 }
236}