use ifc_model::{EntityId, Model};
use super::slots::RelSlots;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RelationshipKind {
Aggregates,
ContainedIn,
Nests,
CoversElements,
CoversSpaces,
ConnectsElements,
InterferesElements,
AssignsToActor,
AssignsToProcess,
AssignsToProduct,
AssignsToGroupByFactor,
Declares,
DefinesByObject,
FlowControlElements,
ServicesBuildings,
ConnectsWithEccentricity,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Relationship {
pub id: EntityId,
pub kind: RelationshipKind,
pub relating: Option<EntityId>,
pub related: Vec<EntityId>,
}
pub(crate) fn refs_in_slot(model: &Model, id: EntityId, slot: usize) -> Vec<EntityId> {
let Some(entity) = model.get(id) else {
return Vec::new();
};
let Some(attribute) = entity.attribute(slot) else {
return Vec::new();
};
let mut out = Vec::new();
attribute.for_each_ref(&mut |target| out.push(target));
out
}
pub(crate) fn read(
model: &Model,
id: EntityId,
slots: RelSlots,
kind: RelationshipKind,
) -> Option<Relationship> {
let entity = model.get(id)?;
if !entity.is_type(slots.type_name) {
return None;
}
let relating = refs_in_slot(model, id, slots.relating).into_iter().next();
Some(Relationship {
id,
kind,
relating,
related: refs_in_slot(model, id, slots.related),
})
}