reactive_graph_graph/instances/relations/
relation_instance_id.rs

1use schemars::JsonSchema;
2use serde::Deserialize;
3use serde::Serialize;
4use std::cmp::Ordering;
5use std::fmt::Display;
6use std::fmt::Formatter;
7use typed_builder::TypedBuilder;
8use uuid::Uuid;
9
10use crate::NamespacedType;
11use crate::NamespacedTypeGetter;
12use crate::RelationInstanceTypeId;
13use crate::RelationTypeId;
14use crate::TypeDefinition;
15use crate::TypeDefinitionGetter;
16use crate::TypeIdType;
17
18/// Separator for the string representation of a relation instance.
19pub static RELATION_INSTANCE_ID_SEPARATOR: &str = "--";
20
21/// Unique ID of the relation instance
22#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema, TypedBuilder)]
23pub struct RelationInstanceId {
24    /// The id of the outbound entity.
25    pub outbound_id: Uuid,
26
27    /// The relation instance type id containing the relation type and the instance id.
28    #[builder(setter(into))]
29    pub ty: RelationInstanceTypeId,
30
31    /// The id of the inbound entity.
32    pub inbound_id: Uuid,
33}
34
35impl RelationInstanceId {
36    pub fn new<RIT: Into<RelationInstanceTypeId>>(outbound_id: Uuid, ty: RIT, inbound_id: Uuid) -> Self {
37        RelationInstanceId {
38            outbound_id,
39            ty: ty.into(),
40            inbound_id,
41        }
42    }
43
44    pub fn new_unique<RT: Into<RelationTypeId>>(outbound_id: Uuid, ty: RT, inbound_id: Uuid) -> Self {
45        RelationInstanceId {
46            outbound_id,
47            ty: RelationInstanceTypeId::new_unique_id(ty),
48            inbound_id,
49        }
50    }
51
52    pub fn new_unique_for_instance_id<RT: Into<RelationTypeId>>(outbound_id: Uuid, ty: RT, instance_id: String, inbound_id: Uuid) -> Self {
53        RelationInstanceId {
54            outbound_id,
55            ty: RelationInstanceTypeId::new_unique_for_instance_id(ty, instance_id),
56            inbound_id,
57        }
58    }
59
60    pub fn new_with_random_instance_id<RT: Into<RelationTypeId>>(outbound_id: Uuid, ty: RT, inbound_id: Uuid) -> Self {
61        RelationInstanceId {
62            outbound_id,
63            ty: RelationInstanceTypeId::new_with_random_instance_id(ty),
64            inbound_id,
65        }
66    }
67}
68
69impl NamespacedTypeGetter for RelationInstanceId {
70    fn namespace(&self) -> String {
71        self.ty.namespace()
72    }
73
74    /// Returns the full instance type name (relation type name + instance id)
75    fn type_name(&self) -> String {
76        self.ty.type_name()
77    }
78}
79
80impl TypeDefinitionGetter for RelationInstanceId {
81    fn type_definition(&self) -> TypeDefinition {
82        self.into()
83    }
84}
85
86impl PartialOrd<Self> for RelationInstanceId {
87    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
88        Some(self.cmp(other))
89    }
90}
91
92impl Ord for RelationInstanceId {
93    fn cmp(&self, other: &Self) -> Ordering {
94        match self.ty.cmp(&other.ty) {
95            Ordering::Less => Ordering::Less,
96            Ordering::Equal => match self.outbound_id.cmp(&other.outbound_id) {
97                Ordering::Less => Ordering::Less,
98                Ordering::Equal => self.inbound_id.cmp(&other.inbound_id),
99                Ordering::Greater => Ordering::Greater,
100            },
101            Ordering::Greater => Ordering::Greater,
102        }
103    }
104}
105
106impl From<&RelationInstanceId> for RelationInstanceId {
107    fn from(ty: &RelationInstanceId) -> Self {
108        ty.clone()
109    }
110}
111
112impl From<&RelationInstanceId> for TypeDefinition {
113    fn from(ty: &RelationInstanceId) -> Self {
114        TypeDefinition::new(TypeIdType::RelationType, ty.into())
115    }
116}
117
118impl From<&RelationInstanceId> for NamespacedType {
119    fn from(ty: &RelationInstanceId) -> Self {
120        // Returns the namespaced type with the full instance type name (relation type name + instance id)
121        NamespacedType::from(&ty.ty)
122    }
123}
124
125impl TryFrom<&String> for RelationInstanceId {
126    type Error = ();
127
128    fn try_from(s: &String) -> Result<Self, Self::Error> {
129        let mut s = s.splitn(3, &RELATION_INSTANCE_ID_SEPARATOR);
130        let outbound_id = s.next().ok_or(())?.try_into().map_err(|_| ())?;
131        let ty: RelationInstanceTypeId = s.next().ok_or(())?.to_string().try_into().map_err(|_| ())?;
132        let inbound_id = s.next().ok_or(())?.try_into().map_err(|_| ())?;
133        Ok(RelationInstanceId::new(outbound_id, ty, inbound_id))
134    }
135}
136
137impl Display for RelationInstanceId {
138    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
139        write!(f, "{}-[{}]->{}", self.outbound_id, &self.ty, self.inbound_id)
140    }
141}