use crate::v2_4::aom2::constraint_model::archetype_constraint::ArchetypeConstraint;
use crate::v2_4::aom2::constraint_model::c_attribute::CAttribute;
use crate::v2_4::aom2::constraint_model::c_complex_object::CComplexObject;
use crate::v2_4::aom2::constraint_model::c_object_impl::{NodeFacts, conforms, congruent};
use crate::v2_4::aom2::constraint_model::c_second_order::CSecondOrder;
use crate::v2_4::aom2::constraint_model::sibling_order::SiblingOrder;
use openehr_base::v1_3::foundation_types::interval::multiplicity_interval::MultiplicityInterval;
impl CComplexObject {
#[must_use]
pub fn node_id(&self) -> &str {
match self {
Self::CArchetypeRoot(root) => &root.node_id,
Self::CComplexObject(data) => &data.node_id,
}
}
#[must_use]
pub fn occurrences(&self) -> Option<&MultiplicityInterval> {
match self {
Self::CArchetypeRoot(root) => root.occurrences.as_ref(),
Self::CComplexObject(data) => data.occurrences.as_ref(),
}
}
#[must_use]
pub fn parent(&self) -> Option<&ArchetypeConstraint> {
match self {
Self::CArchetypeRoot(root) => root.parent.as_ref(),
Self::CComplexObject(data) => data.parent.as_deref(),
}
}
#[must_use]
pub fn soc_parent(&self) -> Option<&CSecondOrder> {
match self {
Self::CArchetypeRoot(root) => root.soc_parent.as_ref(),
Self::CComplexObject(data) => data.soc_parent.as_ref(),
}
}
#[must_use]
pub fn attributes(&self) -> Option<&[CAttribute]> {
match self {
Self::CArchetypeRoot(root) => root.attributes.as_deref(),
Self::CComplexObject(data) => data.attributes.as_deref(),
}
}
#[must_use]
pub fn has_default_value(&self) -> bool {
match self {
Self::CArchetypeRoot(root) => root.default_value.is_some(),
Self::CComplexObject(data) => data.default_value.is_some(),
}
}
#[must_use]
pub fn any_allowed(&self) -> bool {
let attributes = self.attributes();
let occurrences = self.occurrences();
attributes.is_none_or(<[CAttribute]>::is_empty)
&& !occurrences.is_some_and(MultiplicityInterval::is_prohibited)
}
#[must_use]
pub fn rm_type_name(&self) -> &str {
match self {
Self::CArchetypeRoot(root) => &root.rm_type_name,
Self::CComplexObject(data) => &data.rm_type_name,
}
}
#[must_use]
pub fn sibling_order(&self) -> Option<&SiblingOrder> {
match self {
Self::CArchetypeRoot(root) => root.sibling_order.as_ref(),
Self::CComplexObject(data) => data.sibling_order.as_ref(),
}
}
fn facts(&self) -> NodeFacts<'_> {
NodeFacts {
node_id: self.node_id(),
rm_type_name: self.rm_type_name(),
occurrences: self.occurrences(),
sibling_order: self.sibling_order(),
}
}
#[must_use]
pub fn c_conforms_to(
&self,
other: &CComplexObject,
rmcc: &dyn Fn(&str, &str) -> bool,
owning_attribute: Option<&CAttribute>,
) -> bool {
conforms(&self.facts(), &other.facts(), rmcc, owning_attribute)
}
#[must_use]
pub fn c_congruent_to(
&self,
other: &CComplexObject,
owning_attribute: Option<&CAttribute>,
) -> bool {
congruent(&self.facts(), &other.facts(), owning_attribute)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::v2_4::aom2::constraint_model::c_complex_object::CComplexObjectData;
fn interval(lower: i32, upper: i32) -> MultiplicityInterval {
MultiplicityInterval {
lower: Some(lower),
upper: Some(upper),
lower_unbounded: false,
upper_unbounded: false,
lower_included: true,
upper_included: true,
}
}
fn object(
attributes: Option<Vec<CAttribute>>,
occurrences: Option<MultiplicityInterval>,
) -> CComplexObject {
CComplexObject::CComplexObject(CComplexObjectData {
parent: None,
soc_parent: None,
rm_type_name: "OBSERVATION".to_owned(),
occurrences,
node_id: "id1".to_owned(),
alternative_ids: None,
is_deprecated: None,
sibling_order: None,
default_value: None,
attributes,
attribute_tuples: None,
})
}
fn an_attribute() -> CAttribute {
CAttribute {
parent: None,
soc_parent: None,
rm_attribute_name: "data".to_owned(),
existence: None,
children: None,
differential_path: None,
cardinality: None,
is_multiple: false,
}
}
#[test]
fn no_attribute_constraints_and_no_prohibition_allows_anything() {
assert!(object(None, None).any_allowed());
assert!(object(Some(Vec::new()), Some(interval(0, 1))).any_allowed());
}
#[test]
fn a_prohibited_node_allows_nothing_even_with_no_attributes() {
assert!(!object(None, Some(interval(0, 0))).any_allowed());
}
#[test]
fn one_attribute_constraint_is_already_a_constraint() {
assert!(!object(Some(vec![an_attribute()]), None).any_allowed());
}
}