sea_core/primitives/
resource_instance.rs

1use crate::ConceptId;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use std::collections::HashMap;
5use uuid::Uuid;
6
7const DEFAULT_NAMESPACE: &str = "default";
8
9/// Represents a physical instance of a resource at a specific entity location.
10///
11/// Instances capture the "WHERE" of resources - they represent specific physical
12/// instances of resources located at particular entities.
13///
14/// # Examples
15///
16/// ```
17/// use sea_core::primitives::{Entity, Resource, ResourceInstance};
18/// use sea_core::units::unit_from_string;
19///
20/// let warehouse = Entity::new_with_namespace("Warehouse A".to_string(), "default".to_string());
21/// let product = Resource::new_with_namespace("Camera", unit_from_string("units"), "default".to_string());
22///
23/// let camera_123 = ResourceInstance::new(
24///     product.id().clone(),
25///     warehouse.id().clone()
26/// );
27///
28/// assert_eq!(camera_123.entity_id(), warehouse.id());
29/// ```
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
31pub struct ResourceInstance {
32    id: ConceptId,
33    resource_id: ConceptId,
34    entity_id: ConceptId,
35    namespace: String,
36    attributes: HashMap<String, Value>,
37}
38
39impl ResourceInstance {
40    /// Creates a new ResourceInstance (default namespace).
41    pub fn new(resource_id: ConceptId, entity_id: ConceptId) -> Self {
42        Self::new_with_namespace(resource_id, entity_id, DEFAULT_NAMESPACE)
43    }
44
45    pub fn new_with_namespace(
46        resource_id: ConceptId,
47        entity_id: ConceptId,
48        namespace: impl Into<String>,
49    ) -> Self {
50        let namespace = namespace.into();
51        // Use UUID v4 for instances to ensure uniqueness (instances are unique occurrences)
52        let id = ConceptId::from_uuid(Uuid::new_v4());
53
54        Self {
55            id,
56            resource_id,
57            entity_id,
58            namespace,
59            attributes: HashMap::new(),
60        }
61    }
62
63    pub fn id(&self) -> &ConceptId {
64        &self.id
65    }
66    pub fn resource_id(&self) -> &ConceptId {
67        &self.resource_id
68    }
69    pub fn entity_id(&self) -> &ConceptId {
70        &self.entity_id
71    }
72    pub fn namespace(&self) -> &str {
73        &self.namespace
74    }
75
76    pub fn set_attribute(&mut self, key: impl Into<String>, value: Value) {
77        self.attributes.insert(key.into(), value);
78    }
79
80    pub fn get_attribute(&self, key: &str) -> Option<&Value> {
81        self.attributes.get(key)
82    }
83
84    /// Returns all attributes as a reference.
85    pub fn attributes(&self) -> &HashMap<String, Value> {
86        &self.attributes
87    }
88}