Skip to main content

entrenar/research/ro_crate/
descriptor.rs

1//! RO-Crate metadata descriptor.
2
3use super::entity::{EntityType, RoCrateEntity};
4use serde::{Deserialize, Serialize};
5use serde_json::json;
6
7/// JSON-LD context for RO-Crate 1.1
8pub const RO_CRATE_CONTEXT: &str = "https://w3id.org/ro/crate/1.1/context";
9
10/// RO-Crate metadata descriptor
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct RoCrateDescriptor {
13    /// JSON-LD context
14    #[serde(rename = "@context")]
15    pub context: String,
16    /// Graph of entities
17    #[serde(rename = "@graph")]
18    pub graph: Vec<RoCrateEntity>,
19}
20
21impl Default for RoCrateDescriptor {
22    fn default() -> Self {
23        Self::new()
24    }
25}
26
27impl RoCrateDescriptor {
28    /// Create a new RO-Crate descriptor
29    pub fn new() -> Self {
30        // Start with the metadata file entity pointing to root
31        let metadata_entity =
32            RoCrateEntity::new("ro-crate-metadata.json", EntityType::CreativeWork)
33                .with_property("conformsTo", json!({ "@id": "https://w3id.org/ro/crate/1.1" }))
34                .with_reference("about", "./");
35
36        Self { context: RO_CRATE_CONTEXT.to_string(), graph: vec![metadata_entity] }
37    }
38
39    /// Add an entity to the graph
40    pub fn add_entity(&mut self, entity: RoCrateEntity) {
41        self.graph.push(entity);
42    }
43
44    /// Get the root dataset entity
45    pub fn root_dataset(&self) -> Option<&RoCrateEntity> {
46        self.graph.iter().find(|e| e.id == "./")
47    }
48
49    /// Get the root dataset entity mutably
50    pub fn root_dataset_mut(&mut self) -> Option<&mut RoCrateEntity> {
51        self.graph.iter_mut().find(|e| e.id == "./")
52    }
53
54    /// Serialize to JSON
55    pub fn to_json(&self) -> String {
56        serde_json::to_string_pretty(self).unwrap_or_else(|_err| "{}".to_string())
57    }
58}