Skip to main content

entrenar/research/artifact/
research_artifact.rs

1//! Research artifact with full metadata.
2
3use serde::{Deserialize, Serialize};
4
5use super::{ArtifactType, Author, License};
6
7/// Research artifact with full metadata
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
9pub struct ResearchArtifact {
10    /// Unique identifier
11    pub id: String,
12    /// Artifact title
13    pub title: String,
14    /// Authors with affiliations and roles
15    pub authors: Vec<Author>,
16    /// Type of artifact
17    pub artifact_type: ArtifactType,
18    /// License
19    pub license: License,
20    /// Digital Object Identifier (optional)
21    pub doi: Option<String>,
22    /// Version string
23    pub version: String,
24    /// Abstract or description
25    pub description: Option<String>,
26    /// Keywords for discovery
27    pub keywords: Vec<String>,
28    /// Creation timestamp
29    pub created_at: chrono::DateTime<chrono::Utc>,
30}
31
32impl ResearchArtifact {
33    /// Create a new research artifact
34    pub fn new(
35        id: impl Into<String>,
36        title: impl Into<String>,
37        artifact_type: ArtifactType,
38        license: License,
39    ) -> Self {
40        Self {
41            id: id.into(),
42            title: title.into(),
43            authors: Vec::new(),
44            artifact_type,
45            license,
46            doi: None,
47            version: "1.0.0".to_string(),
48            description: None,
49            keywords: Vec::new(),
50            created_at: chrono::Utc::now(),
51        }
52    }
53
54    /// Add an author
55    pub fn with_author(mut self, author: Author) -> Self {
56        self.authors.push(author);
57        self
58    }
59
60    /// Add multiple authors
61    pub fn with_authors(mut self, authors: impl IntoIterator<Item = Author>) -> Self {
62        self.authors.extend(authors);
63        self
64    }
65
66    /// Set the DOI
67    pub fn with_doi(mut self, doi: impl Into<String>) -> Self {
68        self.doi = Some(doi.into());
69        self
70    }
71
72    /// Set the version
73    pub fn with_version(mut self, version: impl Into<String>) -> Self {
74        self.version = version.into();
75        self
76    }
77
78    /// Set the description
79    pub fn with_description(mut self, description: impl Into<String>) -> Self {
80        self.description = Some(description.into());
81        self
82    }
83
84    /// Add keywords
85    pub fn with_keywords(mut self, keywords: impl IntoIterator<Item = impl Into<String>>) -> Self {
86        self.keywords.extend(keywords.into_iter().map(Into::into));
87        self
88    }
89
90    /// Get the first author (for citation keys)
91    pub fn first_author(&self) -> Option<&Author> {
92        self.authors.first()
93    }
94}