use crate::{
GraphRecord,
errors::{GraphRecordError, GraphRecordResult},
prelude::{
AttributeMap, EdgeIndex, GraphRecordAttribute, GraphRecordValue, Group, NodeIndex,
SchemaType,
},
};
macro_rules! impl_attributes_mut {
(
$struct_name:ident,
$index_type:ty,
$index_field:ident,
$entity:literal,
$contains_fn:ident,
$groups_of_fn:ident,
$get_attributes_fn:ident,
$get_attributes_mut_fn:ident,
$schema_update_fn:ident,
$schema_validate_fn:ident,
$not_found_variant:ident,
$attribute_not_found_variant:ident
) => {
pub struct $struct_name<'a> {
$index_field: &'a $index_type,
graphrecord: &'a mut GraphRecord,
}
impl<'a> $struct_name<'a> {
pub(crate) fn new(
$index_field: &'a $index_type,
graphrecord: &'a mut GraphRecord,
) -> GraphRecordResult<Self> {
if !graphrecord.$contains_fn($index_field) {
return Err(GraphRecordError::$not_found_variant {
$index_field: $index_field.clone(),
});
}
Ok(Self {
$index_field,
graphrecord,
})
}
fn get_groups(&self) -> Vec<Group> {
self.graphrecord
.$groups_of_fn(self.$index_field)
.expect(concat!($entity, " must exist."))
.cloned()
.collect()
}
fn handle_schema(
&mut self,
attributes: &AttributeMap,
groups: &[Group],
) -> GraphRecordResult<()> {
let schema = &mut self.graphrecord.schema;
match schema.schema_type() {
SchemaType::Inferred => {
if groups.is_empty() {
schema.$schema_update_fn(attributes, None, false);
} else {
for group in groups {
schema.$schema_update_fn(attributes, Some(group), false);
}
}
}
SchemaType::Provided => {
if groups.is_empty() {
schema.$schema_validate_fn(self.$index_field, attributes, None)?;
} else {
for group in groups {
schema.$schema_validate_fn(
self.$index_field,
attributes,
Some(group),
)?;
}
}
}
}
Ok(())
}
fn set_attributes(&mut self, attributes: AttributeMap) {
*self
.graphrecord
.graph
.$get_attributes_mut_fn(self.$index_field)
.expect(concat!($entity, " must exist.")) = attributes;
}
pub fn replace_attributes(
&mut self,
attributes: AttributeMap,
) -> GraphRecordResult<()> {
let groups = self.get_groups();
self.handle_schema(&attributes, &groups)?;
self.set_attributes(attributes);
Ok(())
}
pub fn update_attribute(
&mut self,
attribute: &GraphRecordAttribute,
value: GraphRecordValue,
) -> GraphRecordResult<()> {
let groups = self.get_groups();
let mut attributes = self
.graphrecord
.$get_attributes_fn(self.$index_field)
.expect(concat!($entity, " must exist."))
.clone();
attributes
.entry(attribute.clone())
.and_modify(|v| *v = value.clone())
.or_insert(value);
self.handle_schema(&attributes, &groups)?;
self.set_attributes(attributes);
Ok(())
}
pub fn remove_attribute(
&mut self,
attribute: &GraphRecordAttribute,
) -> GraphRecordResult<GraphRecordValue> {
let groups = self.get_groups();
let mut attributes = self
.graphrecord
.$get_attributes_fn(self.$index_field)
.expect(concat!($entity, " must exist."))
.clone();
let removed_value = attributes.remove(attribute);
let Some(removed_value) = removed_value else {
return Err(GraphRecordError::$attribute_not_found_variant {
$index_field: self.$index_field.clone(),
attribute: attribute.clone(),
});
};
self.handle_schema(&attributes, &groups)?;
self.set_attributes(attributes);
Ok(removed_value)
}
}
};
}
impl_attributes_mut!(
NodeAttributesMut,
NodeIndex,
node_index,
"node",
contains_node,
groups_of_node,
node_attributes,
node_attributes_mut,
update_node,
validate_node,
NodeNotFound,
NodeAttributeNotFound
);
impl_attributes_mut!(
EdgeAttributesMut,
EdgeIndex,
edge_index,
"edge",
contains_edge,
groups_of_edge,
edge_attributes,
edge_attributes_mut,
update_edge,
validate_edge,
EdgeNotFound,
EdgeAttributeNotFound
);