acorn_lib/schema/raid.rs
1//! ## Research activity identifier (RAiD) metadata schema
2//!
3//! See <https://metadata.raid.org/en/v1.6/index.html> for official documentation on schema.
4//!
5//! Use ACORN to generate JSON schema for RAiD metadata with `acorn schema --raid`
6use crate::schema::validate::{is_iso8601_date, is_iso8601_year, is_raid, is_ror};
7use crate::{License, SemanticVersion};
8use bon::{builder, Builder};
9use derive_more::Display;
10use schemars::{schema_for, JsonSchema};
11use serde::{Deserialize, Serialize};
12use serde_with::skip_serializing_none;
13use validator::Validate;
14
15/// Allowed values for access types
16#[derive(Clone, Debug, Default, Deserialize, Display, JsonSchema, Serialize)]
17#[serde(rename = "kebab-case")]
18pub enum AccessType {
19 /// Open access
20 #[default]
21 #[display("open-access")]
22 OpenAccess,
23 /// Embargoed access
24 #[display("embargoed-access")]
25 EmbargoedAccess,
26}
27/// CRediT role
28///
29/// Taxonomy of 14 roles that can be used to describe the key types of contributions typically made to the production and publication of research output such as research articles.
30///
31/// See <https://www.niso.org/publications/z39104-2022-credit>
32#[derive(Clone, Debug, Deserialize, Display, JsonSchema, Serialize)]
33#[serde(rename = "kebab-case")]
34pub enum CreditRole {
35 /// Ideas; formulation or evolution of overarching research goals and aims.
36 #[display("conceptualization")]
37 Conceptualization,
38 /// Management activities to annotate (produce metadata), scrub data and maintain research data (including software code, where it is necessary for interpreting the data itself) for initial use and later re-use.
39 #[display("data-curation")]
40 DataCuration,
41 /// Application of statistical, mathematical, computational, or other formal techniques to analyze or synthesize study data.
42 #[display("formal-analysis")]
43 FormalAnalysis,
44 /// Acquisition of the financial support for the project leading to this publication.
45 #[display("funding-acquisition")]
46 FundingAcquisition,
47 /// Conducting a research and investigation process, specifically performing the experiments, or data/evidence collection.
48 #[display("investigation")]
49 Investigation,
50 /// Development or design of methodology; creation of models.
51 #[display("methodology")]
52 Methodology,
53 /// Management and coordination responsibility for the research activity planning and execution.
54 #[display("project-administration")]
55 ProjectAdministration,
56 /// Provision of study materials, reagents, materials, patients, laboratory samples, animals, instrumentation, computing resources, or other analysis tools.
57 #[display("resources")]
58 Resources,
59 /// Programming, software development; designing computer programs; implementation of the computer code and supporting algorithms; testing of existing code components.
60 #[display("software")]
61 Software,
62 /// Oversight and leadership responsibility for the research activity planning and execution, including mentorship external to the core team.
63 #[display("supervision")]
64 Supervision,
65 /// Verification, whether as a part of the activity or separate, of the overall replication/reproducibility of results/experiments and other research outputs.
66 #[display("validation")]
67 Validation,
68 /// Preparation, creation and/or presentation of the published work, specifically visualization/data presentation.
69 #[display("visualization")]
70 Visualization,
71 /// Preparation, creation and/or presentation of the published work, specifically writing the initial draft (including substantive translation).
72 #[display("writing-original-draft")]
73 WritingOriginalDraft,
74 /// Preparation, creation and/or presentation of the published work by those from the original research group, specifically critical review, commentary or revision - including pre- or post-publication stages
75 #[display("writing-review-editing")]
76 WritingReviewEditing,
77}
78/// Description types
79#[derive(Clone, Debug, Deserialize, Display, JsonSchema, Serialize)]
80#[serde(rename = "kebab-case")]
81pub enum DescriptionType {
82 /// Primary description (i.e., a preferred full description or abstract)
83 Primary,
84 /// An alternative description (i.e., an additional or supplementary full description or abstract)
85 Alternative,
86 /// Brief description (i.e., a shorter version of the primary description)
87 Brief,
88 /// Significance statement
89 #[display("significance-statement")]
90 SignificanceStatement,
91 /// Methods
92 Methods,
93 /// Objectives
94 Objectives,
95 /// Acknowledgements (i.e., for recognition of people not listed as Contributors or organizations not listed as organizations)
96 Acknowledgements,
97 /// Other (i.e., any other descriptive information such as a note)
98 Other,
99}
100/// Flag indicating that a value is affirmative (e.g., for `leader` or `contact`)
101#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize)]
102pub enum Flag {
103 /// Affirmative flag
104 Yes,
105}
106/// Category of input, output, or process document
107#[derive(Clone, Debug, Deserialize, Display, JsonSchema, Serialize)]
108#[serde(rename = "kebab-case")]
109pub enum ObjectCategoryType {
110 /// Input
111 #[display("input")]
112 Input,
113 /// Internal process document or artifact
114 #[display("internal-process-document")]
115 InternalProcessDocument,
116 /// Output
117 #[display("output")]
118 Output,
119}
120/// Type of input, output, or process document
121#[derive(Clone, Debug, Deserialize, Display, JsonSchema, Serialize)]
122#[serde(rename = "kebab-case")]
123pub enum ObjectType {
124 /// Audiovisual
125 #[display("audiovisual")]
126 Audiovisual,
127 /// Book
128 #[display("book")]
129 Book,
130 /// Book chapter
131 #[display("book-chapter")]
132 BookChapter,
133 /// Computational notebook (e.g., Jupyter notebook)
134 #[display("computational-notebook")]
135 ComputationalNotebook,
136 /// Conference paper
137 #[display("conference-paper")]
138 ConferencePaper,
139 /// Conference poster
140 #[display("conference-poster")]
141 ConferencePoster,
142 /// Conference proceeding
143 #[display("conference-proceeding")]
144 ConferenceProceeding,
145 /// Data paper
146 #[display("data-paper")]
147 DataPaper,
148 /// Dataset
149 #[display("dataset")]
150 Dataset,
151 /// Dissertation
152 #[display("dissertation")]
153 Dissertation,
154 /// Event
155 #[display("event")]
156 Event,
157 /// Funding
158 ///
159 /// *Note*
160 /// > Includes grants or other cash or in-kind awards, but not prizes
161 #[display("funding")]
162 Funding,
163 /// Image
164 #[display("image")]
165 Image,
166 /// Instrument
167 #[display("instrument")]
168 Instrument,
169 /// Journal article
170 #[display("journal-article")]
171 JournalArticle,
172 /// Learning object
173 #[display("learning-object")]
174 LearningObject,
175 /// Model
176 #[display("model")]
177 Model,
178 /// Output management plan
179 #[display("output-management-plan")]
180 OutputManagementPlan,
181 /// Physical object
182 #[display("physical-object")]
183 PhysicalObject,
184 /// Preprint
185 #[display("preprint")]
186 Preprint,
187 /// Prize (excluding funded awards)
188 #[display("prize")]
189 Prize,
190 /// Report
191 #[display("report")]
192 Report,
193 /// Service
194 #[display("service")]
195 Service,
196 /// Software
197 #[display("software")]
198 Software,
199 /// Sound
200 #[display("sound")]
201 Sound,
202 /// Standard
203 #[display("standard")]
204 Standard,
205 /// Text
206 #[display("text")]
207 Text,
208 /// Workflow
209 #[display("workflow")]
210 Workflow,
211}
212/// Organization role identifier
213#[derive(Clone, Debug, Deserialize, Display, JsonSchema, Serialize)]
214#[serde(rename = "kebab-case")]
215pub enum OrganizationRoleType {
216 /// Lead research organization
217 #[display("lead-research-organization")]
218 LeadResearchOrganization,
219 /// Other research organization
220 #[display("other-research-organization")]
221 OtherResearchOrganization,
222 /// Partner organization (i.e., a non-research organization, such as an industry, government, or community partner that is collaborating on the project or activity, as a research partner rather than a hired consultant or contractor)
223 #[display("partner-organization")]
224 PartnerOrganization,
225 /// Contractor (i.e., a consulting organization hired by the project)
226 #[display("contractor")]
227 Contractor,
228 /// Funder (i.e., an organization underwriting the research via a cash or in-kind grant, prize, or investment, but not otherwise listed as a research organization, partner organization or contractor)
229 #[display("funder")]
230 Funder,
231 /// Facility (i.e., an organization providing access to physical or digital infrastructure, but not otherwise listed as a research organization, partner organization or contractor)
232 #[display("facility")]
233 Facility,
234 /// Other Organiation not covered by the roles above
235 #[display("other-organization")]
236 OtherOrganization,
237}
238/// Represents a contributor's administrative position on a project (such as their position on a grant application)
239///
240/// <div class="warning">Use contributor role to define scientific or scholarly contributions</div>
241#[derive(Clone, Debug, Deserialize, Display, JsonSchema, Serialize)]
242#[serde(rename = "kebab-case")]
243pub enum PositionType {
244 /// Principal Investigator
245 #[display("principal-investigator")]
246 #[serde(alias = "ChiefInvestigator")]
247 PrincipalInvestigator,
248 /// Co-Investigator
249 #[display("co-investigator")]
250 #[serde(alias = "collaborator")]
251 CoInvestigator,
252 /// Partner Investigator (e.g., industry, government, or community collaborator)
253 #[display("partner-investigator")]
254 PartnerInvestigator,
255 /// Consultant (e.g., someone hired as a contract researcher by the project)
256 #[display("consultant")]
257 Consultant,
258 /// Other Participant not covered by one of the positions above, e.g., "member" or "other significant contributor"
259 #[display("other")]
260 Other,
261}
262/// RAiD Relation Type
263///
264/// Describes the relationship being one activity and another
265#[derive(Clone, Debug, Deserialize, Display, JsonSchema, Serialize)]
266#[serde(rename = "kebab-case")]
267pub enum RelatedRaidType {
268 /// Continues
269 Continues,
270 /// Is continued by
271 #[display("is-continued-by")]
272 IsContinuedBy,
273 /// Has part
274 #[display("has-part")]
275 HasPart,
276 /// Is part of
277 #[display("is-part-of")]
278 IsPartOf,
279 /// Is source of
280 #[display("is-source-of")]
281 IsSourceOf,
282 /// Is derived from
283 #[display("is-derived-from")]
284 IsDerivedFrom,
285 /// Obsoletes
286 /// > For resolving duplicate RAiDs
287 Obsoletes,
288 /// Is obsoleted by
289 /// > For resolving duplicate RAiDs
290 #[display("is-obsoleted-by")]
291 IsObsoletedBy,
292}
293/// Allowed values for title identifiers
294#[derive(Clone, Debug, Deserialize, Display, JsonSchema, Serialize)]
295pub enum TitleType {
296 /// Preferred full or long title
297 Primary,
298 /// Abreviated title
299 Short,
300 /// Title acronym
301 Acronym,
302 /// Alternative title, including subtitle or other supplemental title
303 Alternative,
304}
305/// Metadata schema block containing RAiD access information
306///
307/// See <https://metadata.raid.org/en/v1.6/core/access.html>
308#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
309pub struct Access {
310 /// Access type
311 #[serde(rename = "type")]
312 pub access_type: AccessIdentifier,
313 /// Date an embargo on access to the RAiD metadata ends
314 /// ### Format
315 /// > [ISO 8601] standard date (e.g., `YYYY-MM-DD`)
316 ///
317 /// <div class="warning">Mandatory if access type is "embargoed"</div>
318 ///
319 /// <div class="warning">Embargo expiration dates may not lay more than 18 months from the date the RAiD was registered. Year, month, and day mush be specified.</div>
320 ///
321 /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
322 #[validate(custom(function = "is_iso8601_date"))]
323 pub embargo_expiry: Option<String>,
324 /// Access statement
325 ///
326 /// <div class="warning">Mandatory if access type is not "open"</div>
327 #[validate(nested)]
328 pub statement: Option<AccessStatement>,
329}
330/// Access type identifier
331#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
332#[serde(rename = "camelCase")]
333pub struct AccessIdentifier {
334 /// Type of access granted to a RAiD metadata record
335 pub id: AccessType,
336 /// URI of the access type schema
337 #[validate(url)]
338 pub schema_uri: String,
339}
340/// Metadata schema block containing an explanation for any access type that is not "open", with the explanation's associated properties
341#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
342pub struct AccessStatement {
343 /// The text of an access statement that explains any restrictions on access
344 #[validate(length(min = 1, max = 1000))]
345 pub text: Option<String>,
346 /// The language of the access statement
347 #[validate(nested)]
348 pub language: Option<Language>,
349}
350/// Metadata schema block containing alternative local or global identifiers for the project or activity associated with the RAiD
351#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
352pub struct AlternateIdentifier {
353 /// Identifier other than the RAiD applied to the project or activity
354 /// ### Example
355 /// > ACORN research activity data (RAD) [identifier]
356 ///
357 /// [identifier]: ./struct.Metadata.html#structfield.identifier
358 pub id: String,
359 /// Free text description of the type of alternate identifier supplied
360 #[serde(rename = "type")]
361 pub alternate_identifier_type: String,
362}
363/// Link to another website related to the project or activity
364#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
365pub struct AlternateUrl {
366 #[validate(url)]
367 url: String,
368}
369/// Metadata schema block containing a contributor to a RAiD and their associated properties
370///
371/// See <https://metadata.raid.org/en/v1.6/core/contributors.html>
372#[skip_serializing_none]
373#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
374#[serde(rename = "camelCase")]
375#[serde(deny_unknown_fields)]
376pub struct Contributor {
377 /// Contributor (person) associated with a project or activity identified by a persistent identifier (PID)
378 pub id: String,
379 /// URI of the contributor identifier schema
380 ///
381 /// <div class="warning">PID is required and (currently) only [ORCID] and [ISNI] are allowed</div>
382 ///
383 /// [ISNI]: https://isni.org/
384 /// [ORCID]: https://orcid.org/
385 #[validate(url)]
386 pub schema_uri: String,
387 /// Contributor's administrative position on a project or activity
388 pub position: ContributorPosition,
389 /// Flag indicating that the contributor as a project leader
390 ///
391 /// Allowed values: `Yes` or `Null`
392 pub leader: Option<Flag>,
393 /// Flag indicating that the contributor as a project contact
394 ///
395 /// Allowed values: `Yes` or `Null`
396 pub contact: Option<Flag>,
397 /// Contributor's role(s) on a project or activity
398 pub role: Option<Vec<Role>>,
399}
400/// Metadata schema sub-block describing a contributor's administrative position on a project or activity
401///
402/// See <https://metadata.raid.org/en/v1.6/core/contributors.html#contributor-position>
403#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
404#[serde(rename = "camelCase")]
405#[serde(deny_unknown_fields)]
406pub struct ContributorPosition {
407 /// Contributor's administrative position in the project
408 /// ### Example
409 /// > "Principal Investigator"
410 pub id: PositionType,
411 /// URI of the position schema used
412 ///
413 /// <div class="warning">Controlled list of schemas is informed by Simon Cox's [Project Ontology], [OpenAIRE] "Project" guidelines, NIH definitions, ARC definitions, and DataCite Metadata Schema 4.4 Appendix 1 Table 5 "Description of contributorType".</div>
414 ///
415 /// [OpenAIRE]: https://guidelines.openaire.eu/en/latest/
416 /// [Project Ontology]: http://linked.data.gov.au/def/project
417 #[validate(url)]
418 pub schema_uri: String,
419 /// Dates associated with contributor's involvement in a project or activity
420 #[serde(flatten)]
421 pub date: Date,
422}
423/// Start and end dates for the associated metadata
424#[skip_serializing_none]
425#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
426#[serde(rename = "camelCase")]
427#[serde(deny_unknown_fields)]
428pub struct Date {
429 /// Associated data start date
430 /// ### Format
431 /// > [ISO 8601] standard date (e.g., `YYYY-MM-DD`)
432 ///
433 /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
434 #[validate(custom(function = "is_iso8601_date"))]
435 pub start_date: String,
436 /// Associated data end date
437 /// ### Format
438 /// > [ISO 8601] standard date (e.g., `YYYY-MM-DD`)
439 ///
440 /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
441 #[validate(custom(function = "is_iso8601_date"))]
442 pub end_date: Option<String>,
443}
444/// Metadata schema block containing the description of the RAiD and associated properties
445///
446/// See <https://metadata.raid.org/en/v1.6/core/descriptions.html>
447#[skip_serializing_none]
448#[derive(Builder, Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
449#[serde(deny_unknown_fields)]
450pub struct Description {
451 /// Description text
452 #[validate(length(min = 3, max = 1000))]
453 pub text: String,
454 /// Description type information
455 #[serde(rename = "type")]
456 pub description_type: DescriptionIdentifier,
457 /// Language of the description text
458 pub language: Option<Language>,
459}
460/// Metadata schema block declaring the type of description
461#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize, Validate)]
462pub struct DescriptionIdentifier {
463 /// Description identifier
464 pub id: DescriptionType,
465 /// URI of the associated description schema
466 #[validate(url)]
467 pub schema_uri: String,
468}
469/// Metadata schema block containing information about the associated type
470#[derive(Builder, Clone, Debug, Deserialize, Serialize, JsonSchema, Validate)]
471#[serde(rename = "camelCase")]
472#[serde(deny_unknown_fields)]
473pub struct Identifier {
474 /// Type identifier
475 pub id: String,
476 /// URI of the associated type schema
477 #[validate(url)]
478 pub schema_uri: String,
479}
480/// Metadata schema block declaring the language of the associated text
481#[derive(Builder, Clone, Debug, Deserialize, Serialize, JsonSchema, Validate)]
482#[serde(rename = "camelCase")]
483#[serde(deny_unknown_fields)]
484pub struct Language {
485 /// Language used for the associated text, identified by a code or another identifier
486 /// ### Examples
487 /// - "eng"
488 /// - "fra"
489 /// - "jpn"
490 ///
491 /// <div class="warning">Limited to <a href="https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes">ISO 639:2023 (Set 3)</a></div>
492 #[validate(length(equal = 3))]
493 pub id: String,
494 /// URI of the associated type schema
495 #[validate(url)]
496 pub schema_uri: String,
497}
498/// Research Activity Identifier (RAiD) Metadata
499#[skip_serializing_none]
500#[derive(Builder, Clone, Debug, Display, Deserialize, Serialize, JsonSchema, Validate)]
501#[builder(start_fn = init)]
502#[display("{} ({identifier})", self.title[0])]
503#[serde(deny_unknown_fields)]
504pub struct Metadata {
505 /// Metadata schema block containing the RAiD name and associated properties
506 #[validate(nested)]
507 pub identifier: MetadataIdentifier,
508 /// Dates associated with the RAiD metadata
509 #[validate(nested)]
510 pub date: Date,
511 /// Title metadata of the RAiD
512 ///
513 /// <div class="warning">One and only one title should be identified as "primary"</div>
514 #[validate(nested, length(min = 1))]
515 pub title: Vec<Title>,
516 /// Description metadata of the RAiD
517 #[validate(nested)]
518 pub description: Option<Vec<Description>>,
519 /// Contributors to the RAiD
520 #[validate(nested, length(min = 1))]
521 pub contributors: Vec<Contributor>,
522 /// Organizations associated with the RAiD
523 ///
524 /// <div class="warning">If only one organization is listed, it's role defaults to "Lead Research Organization"</div>
525 ///
526 /// <div class="warning">One and only one organization should be identified as "Lead Research Organization"</div>
527 #[validate(nested)]
528 pub organization: Option<Vec<Organization>>,
529 /// Related objects associated with the RAiD
530 #[validate(nested)]
531 pub related_object: Option<Vec<RelatedObject>>,
532 /// Alternate identifiers associated with the RAiD
533 #[validate(nested)]
534 pub alternate_identifier: Option<Vec<Identifier>>,
535 /// Alternate URLs associated with the RAiD
536 #[validate(nested)]
537 pub alternate_url: Option<Vec<AlternateUrl>>,
538 /// Related RAiD(s) associated with the RAiD
539 #[validate(nested)]
540 pub related_raid: Option<Vec<RelatedRaid>>,
541 /// Access for the RAiD metadata
542 #[validate(nested)]
543 pub access: Access,
544}
545/// Metadata schema block containing the RAiD name and associated properties
546///
547/// See <https://metadata.raid.org/en/v1.6/core/identifier.html#identifier>
548#[derive(Builder, Clone, Debug, Serialize, Deserialize, Display, JsonSchema, Validate)]
549#[display("{id}")]
550#[serde(rename = "camelCase")]
551#[serde(deny_unknown_fields)]
552pub struct MetadataIdentifier {
553 /// Unique alphanumeric character string that identifies a Research Activity Identifier (RAiD) name
554 /// ### Format
555 /// > `https://raid.org/prefix/suffix`
556 #[validate(custom(function = "is_raid"))]
557 pub id: String,
558 /// URI of the identifier scheme used to identify RAiDs
559 /// ### Example
560 /// > `https://raid.org/`
561 #[validate(url)]
562 pub schema_uri: String,
563 /// Mtadata schema sub-block declaring the Registration Agency that minted the RAiD
564 #[validate(nested)]
565 pub registration_agency: RegistrationAgency,
566 /// The licence, or licence waiver, under which the RAiD metadata record associated with this Identifier has been issued
567 ///
568 /// <div class="warning">Only supports CC-0 (?)</div>
569 pub license: License,
570 /// Version number of the RAiD
571 pub version: SemanticVersion,
572}
573/// Metadata schema block containing the organization associated with a RAiD and its associated properties
574///
575/// See <https://metadata.raid.org/en/v1.6/core/organisations.html#organisation>
576#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
577#[serde(rename = "camelCase")]
578pub struct Organization {
579 /// Organization identifier
580 ///
581 /// <div class="warning">Should be <a href="https://ror.org">ROR</a>, if available</div>
582 pub id: String,
583 /// URI of the organization identifier schema
584 ///
585 /// Only allowed value: `https://ror.org/`
586 #[validate(url, contains(pattern = "https://ror.org"))]
587 pub schema_uri: String,
588 /// Organization role
589 #[validate(nested)]
590 pub role: OrganizationRole,
591}
592/// Organization role
593#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
594#[serde(rename = "camelCase")]
595pub struct OrganizationRole {
596 /// Organization role identifier
597 pub id: OrganizationRoleType,
598 /// URI of the organization role identifier schema
599 #[validate(url)]
600 pub schema_uri: String,
601 /// Date information associated with the organization role
602 #[serde(flatten)]
603 pub date: Date,
604}
605/// Metadata schema sub-block that declares the owner of the RAiD (i.e. the organization requesting the RAiD)
606///
607/// See <https://metadata.raid.org/en/v1.6/core/identifier.html#identifier-owner>
608#[derive(Builder, Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
609#[serde(rename = "camelCase")]
610#[serde(deny_unknown_fields)]
611pub struct Owner {
612 /// Persistent identifier of the legal entity responsible for the RAiD
613 ///
614 /// *Default* ROR of the organization requesting the RAiD
615 /// ### Example
616 /// > `https://ror.org/01qz5mb56` (ORNL)
617 #[validate(custom(function = "is_ror"))]
618 pub id: String,
619 /// URI of the identifier scheme used to identify RAiDs
620 /// ### Example
621 /// > `https://ror.org/`
622 #[validate(url)]
623 pub schema_uri: String,
624 /// Service point (SP) that requested the RAiD
625 /// ### Notes
626 /// - RAiD owners can have multiple SPs
627 /// - SPs do not need to be legal entities
628 /// - List of SPs is maintained by each [`RegistrationAgency`]
629 pub service_point: Vec<String>,
630}
631/// Metadata schema block containing inputs, outputs, and process documents related to a RAiD plus associated properties
632///
633/// See <https://metadata.raid.org/en/v1.6/core/relatedObjects.html>
634#[derive(Builder, Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
635#[serde(rename = "camelCase")]
636#[serde(deny_unknown_fields)]
637pub struct RelatedObject {
638 /// Persistent identifier (PID) of related object
639 ///
640 /// The object can be any combination of
641 /// - input or resource used by a project or activity
642 /// - output or product created by a project or activity
643 /// - internal process documentation used within a project or activity
644 pub id: String,
645 /// URI of the relatedObject identifier schema
646 #[validate(url)]
647 pub schema_uri: String,
648 /// Type information of related object
649 #[serde(rename = "type")]
650 #[validate(nested)]
651 pub related_object_type: RelatedObjectIdentifier,
652 /// Category information of related object
653 #[validate(nested, length(min = 1))]
654 pub category: Vec<RelatedObjectCategory>,
655}
656/// Related object category information
657#[derive(Builder, Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
658#[serde(rename = "camelCase")]
659pub struct RelatedObjectCategory {
660 /// Related object category identifier
661 pub id: ObjectCategoryType,
662 /// URI of the category schema used
663 #[validate(url)]
664 pub schema_uri: String,
665}
666/// Related object identifier
667#[derive(Builder, Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
668#[serde(rename = "camelCase")]
669pub struct RelatedObjectIdentifier {
670 /// Related object type identifier
671 pub id: ObjectType,
672 /// URI of the related object type identifier schema
673 #[validate(url)]
674 pub schema_uri: String,
675}
676/// Metadata schema block containing related RAiDs and qualifying the relationship
677///
678/// See <https://metadata.raid.org/en/v1.6/core/relatedRaids.html>
679#[derive(Builder, Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
680#[serde(rename = "camelCase")]
681pub struct RelatedRaid {
682 /// Subsidiary or otherwise related RAiD
683 pub id: String,
684 /// Related RAiD type
685 #[serde(rename = "type")]
686 pub related_raid_type: RelatedRaidIdentifier,
687}
688/// Related RAiD identifier
689#[derive(Builder, Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
690#[serde(rename = "camelCase")]
691pub struct RelatedRaidIdentifier {
692 /// Related RAiD type identifier
693 pub id: RelatedRaidType,
694 /// URI of the related RAiD type identifier schema
695 #[validate(url)]
696 pub schema_uri: String,
697}
698/// Metadata schema block containing the RAiD name and associated properties
699///
700/// See <https://metadata.raid.org/en/v1.6/core/identifier.html#identifier-registrationagency>
701#[derive(Builder, Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
702#[serde(rename = "camelCase")]
703#[serde(deny_unknown_fields)]
704pub struct RegistrationAgency {
705 /// Persistent identifier of the RAiD Registration Agency that minted the RAiD
706 ///
707 /// *Default* ROR of the RAiD Registration Agency
708 #[validate(custom(function = "is_ror"))]
709 pub id: String,
710 /// URI of the identifier scheme used to identify RAiDs
711 /// ### Example
712 /// > `https://raid.org/`
713 #[validate(url)]
714 pub schema_uri: String,
715}
716/// Metadata schema sub-block describing a contributor's scientific or scholarly role on a project using the [CRediT] vocabulary
717///
718/// See <https://metadata.raid.org/en/v1.6/core/contributors.html#contributor-role>
719///
720/// [CRediT]: https://credit.niso.org/
721#[skip_serializing_none]
722#[derive(Builder, Clone, Debug, Serialize, Deserialize, JsonSchema, Validate)]
723#[serde(rename = "camelCase")]
724#[serde(deny_unknown_fields)]
725pub struct Role {
726 /// Contributor role on a project or activity
727 pub id: Option<CreditRole>,
728 /// URI of the role schema used
729 #[validate(url)]
730 pub schema_uri: Option<String>,
731}
732/// Metadata schema block containing the title of RAiD and associated properties
733///
734/// See <https://metadata.raid.org/en/v1.6/core/titles.html>
735#[skip_serializing_none]
736#[derive(Builder, Clone, Debug, Display, Serialize, Deserialize, JsonSchema, Validate)]
737#[display("{text} ({title_type})")]
738#[serde(deny_unknown_fields)]
739pub struct Title {
740 /// Name or title by which the project or activity is known
741 #[validate(length(min = 3, max = 100))]
742 pub text: String,
743 /// Metadata schema block containing information about the title type
744 #[serde(rename = "type")]
745 #[validate(nested)]
746 pub title_type: TitleIdentifier,
747 /// Language of the title
748 #[validate(nested)]
749 pub language: Option<Language>,
750 /// Date the project or activity's title began being used
751 /// ### Format
752 /// > [ISO 8601] standard date (e.g., `YYYY-MM-DD`)
753 ///
754 /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
755 #[validate(custom(function = "is_iso8601_date"))]
756 pub start_date: String,
757 /// Date the project or activity title was changed or stopped being used
758 /// ### Format
759 /// > [ISO 8601] standard date (e.g., `YYYY-MM-DD`)
760 ///
761 /// <div class="warning">Only the year is required, month and day are optional</div>
762 ///
763 /// <div class="warning">Listed as "recommended" (optional) and "required"</div>
764 ///
765 /// [ISO 8601]: https://en.wikipedia.org/wiki/ISO_8601
766 // TODO: Add support for month and day(?)
767 #[validate(custom(function = "is_iso8601_year"))]
768 pub end_date: String,
769}
770/// Metadata schema block containing information about the title type
771#[derive(Clone, Debug, Serialize, Deserialize, Display, JsonSchema, Validate)]
772#[display("{id}")]
773#[serde(deny_unknown_fields)]
774pub struct TitleIdentifier {
775 /// Title type
776 ///
777 /// <div class="warning">Only one title should be identified as "Primary"</div>
778 pub id: TitleType,
779 /// URI of the title type schema
780 #[validate(url)]
781 pub schema_uri: String,
782}
783impl Metadata {
784 /// Print research activity identifier (RAiD) metadata schema as JSON schema
785 pub fn to_schema() {
786 let schema = schema_for!(Metadata);
787 println!("{}", serde_json::to_string_pretty(&schema).unwrap());
788 }
789}