use super::Form;
use crate::node_wrappers::{BaseNodeTrait, CommonNodeTrait, FinalNode, InheritanceNodeTrait};
use crate::tao::archetype::{Archetype, ArchetypeFormTrait, ArchetypeTrait};
use crate::tao::relation::attribute::{Inherits, MetaForm};
use crate::tao::relation::flag::IsIndividual;
use crate::tao::Tao;
use std::collections::{HashMap, VecDeque};
use std::ops::{Deref, DerefMut};
pub trait FormTrait:
Deref<Target = FinalNode> + DerefMut + std::fmt::Debug + ArchetypeTrait
{
fn ego_death(&self) -> Tao {
Tao::from(self.id())
}
fn as_form(&self) -> Form {
Form::from(self.id())
}
fn add_parent(&mut self, parent: Archetype) {
self.add_outgoing(Inherits::TYPE_ID, &parent);
}
fn is_individual(&self) -> bool {
self.has_flag(IsIndividual::TYPE_ID)
}
fn parents(&self) -> Vec<Archetype> {
let direct_parents: Vec<Archetype> = self
.outgoing_nodes(Inherits::TYPE_ID)
.into_iter()
.filter(|p| p.id() == Tao::TYPE_ID || p != self.deref())
.map(Archetype::from)
.filter(|a| !a.is_individual())
.collect();
let mut specific_parents = Vec::<Archetype>::new();
for parent in direct_parents {
if specific_parents.iter().any(|sp| sp.has_ancestor(parent)) {
continue; }
specific_parents.retain(|sp| !parent.has_ancestor(*sp));
specific_parents.push(parent);
}
specific_parents
}
fn ancestry(&self) -> Vec<Archetype> {
let mut to_be_visited = VecDeque::<Form>::new();
let mut backpointers = HashMap::<Form, Form>::new();
to_be_visited.push_back(self.as_form());
while let Some(next_node) = to_be_visited.pop_front() {
for parent in next_node.parents() {
let parent_tao = parent.as_form();
#[allow(clippy::map_entry)]
if !backpointers.contains_key(&parent_tao) {
backpointers.insert(parent_tao, next_node);
to_be_visited.push_back(parent_tao);
if parent == Tao::archetype() {
break;
}
}
}
}
let mut ancestry = Vec::new();
let mut next_node = Tao::archetype().as_form();
let selfless_ego = self.as_form();
while next_node != selfless_ego {
ancestry.push(Archetype::from(next_node.id()));
next_node = *backpointers.get(&next_node).unwrap();
}
ancestry
}
fn has_parent(&self, possible_ancestor: Archetype) -> bool {
self.outgoing_nodes(Inherits::TYPE_ID)
.contains(&possible_ancestor)
}
fn has_ancestor(&self, possible_ancestor: Archetype) -> bool {
self.inheritance_nodes().contains(&possible_ancestor)
}
fn meta(&self) -> Self::ArchetypeForm {
Self::ArchetypeForm::from(self.id())
}
fn meta_archetype(&self) -> Archetype {
Archetype::from(
self.outgoing_nodes(MetaForm::TYPE_ID)
.last()
.unwrap_or(&FinalNode::from(Archetype::TYPE_ID))
.id(),
)
}
fn specific_meta(&mut self) -> Archetype {
let uninherited_metas = self.base_wrapper().outgoing_nodes(MetaForm::TYPE_ID);
match uninherited_metas.last() {
Some(specific_meta) => Archetype::from(specific_meta.id()),
None => {
let mut parent_metas = Vec::<Archetype>::new();
for parent in self.parents().iter_mut() {
parent_metas.push(parent.specific_meta());
}
let mut new_meta = Archetype::archetype().individuate_as_archetype();
for parent_meta in parent_metas {
new_meta.add_parent(parent_meta);
}
self.set_meta_archetype(&new_meta);
new_meta
}
}
}
fn has_specific_meta(&self) -> bool {
!self
.base_wrapper()
.outgoing_nodes(MetaForm::TYPE_ID)
.is_empty()
}
fn set_meta_archetype(&mut self, archetype: &Archetype) {
self.add_outgoing(MetaForm::TYPE_ID, &archetype)
}
fn mark_individual(&mut self) {
self.add_flag(IsIndividual::TYPE_ID);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tao::archetype::{Archetype, ArchetypeFormTrait};
use crate::tao::initialize_kb;
use crate::tao::relation::attribute::{Attribute, Owner, Value};
#[test]
fn test_parents() {
initialize_kb();
let owner = Owner::new();
assert_eq!(owner.parents(), vec![Owner::archetype().into()]);
}
#[test]
fn test_multiple_parents() {
initialize_kb();
let mut owner = Owner::new();
owner.add_parent(Value::archetype().into()); assert_eq!(
owner.parents(),
vec![Owner::archetype().into(), Value::archetype().into()]
);
}
#[test]
fn test_ancestry_archetype() {
initialize_kb();
let type1 = Tao::archetype().individuate_as_archetype();
let type2 = type1.individuate_as_archetype();
assert_eq!(type2.ancestry(), vec![Tao::archetype(), type1]);
}
#[test]
fn test_ancestry_individual() {
initialize_kb();
let type1 = Tao::archetype().individuate_as_archetype();
let type2 = type1.individuate_as_archetype();
let form = type2.individuate_as_form();
assert_eq!(form.ancestry(), vec![Tao::archetype(), type1, type2]);
}
#[test]
fn test_tao_ancestry() {
initialize_kb();
assert_eq!(Tao::archetype().ancestry(), Vec::<Archetype>::new());
}
#[test]
fn test_looped_ancestry() {
initialize_kb();
let mut type1 = Tao::archetype().individuate_as_archetype();
type1.add_parent(type1);
assert_eq!(type1.ancestry(), vec![Tao::archetype()]);
}
#[test]
fn test_looped_child_ancestry() {
initialize_kb();
let mut type1 = Tao::archetype().individuate_as_archetype();
type1.add_parent(type1);
let type2 = type1.individuate_as_archetype();
assert_eq!(type2.ancestry(), vec![Tao::archetype(), type1]);
}
#[test]
fn test_parenthood() {
initialize_kb();
let owner = Owner::new();
assert!(owner.has_parent(Owner::archetype().into()));
assert!(!owner.has_parent(Tao::archetype()));
assert!(!owner.has_parent(Value::archetype().into()));
}
#[test]
fn test_multiple_parenthood() {
initialize_kb();
let mut owner = Owner::new();
owner.add_parent(Value::archetype().into()); assert!(owner.has_parent(Owner::archetype().into()));
assert!(!owner.has_parent(Tao::archetype()));
assert!(owner.has_parent(Value::archetype().into()));
}
#[test]
fn test_self_parenthood_ignored() {
initialize_kb();
let mut new_type = Tao::archetype().individuate_as_archetype();
new_type.add_parent(new_type);
assert_eq!(new_type.parents(), vec![Tao::archetype()]);
}
#[test]
fn test_tao_self_parenthood_not_ignored() {
initialize_kb();
assert_eq!(Tao::archetype().parents(), vec![Tao::archetype()]);
}
#[test]
fn specific_to_generic_parenthood() {
initialize_kb();
let mut form = Form::new();
form.add_parent(Tao::archetype());
assert_eq!(form.parents(), vec![Form::archetype()]);
}
#[test]
fn generic_to_specific_parenthood() {
initialize_kb();
let mut form = Tao::new();
form.add_parent(Form::archetype());
assert_eq!(form.parents(), vec![Form::archetype()]);
}
#[test]
fn test_individual_inheritance_ignored() {
initialize_kb();
let form1 = Tao::archetype().individuate_as_form();
let mut form2 = Tao::archetype().individuate_as_form();
form2.add_parent(Archetype::from(form1.id()));
assert_eq!(form2.parents(), vec![Tao::archetype()]);
}
#[test]
fn test_has_ancestor() {
initialize_kb();
let owner = Owner::new();
assert!(owner.has_ancestor(Owner::archetype().into()));
assert!(owner.has_ancestor(Tao::archetype()));
assert!(!owner.has_ancestor(Value::archetype().into()));
}
#[test]
fn test_form_meta_set() {
initialize_kb();
let mut form_type = Form::archetype().individuate_as_archetype();
let form_indv = form_type.individuate_as_form();
let meta_type = Archetype::archetype().individuate_as_archetype();
assert_eq!(form_indv.meta_archetype(), Archetype::archetype());
form_type.set_meta_archetype(&meta_type);
assert_eq!(form_indv.meta_archetype(), meta_type);
}
#[test]
fn test_form_meta_inheritance() {
initialize_kb();
let mut form_type = Form::archetype().individuate_as_archetype();
let meta_type = Archetype::archetype().individuate_as_archetype();
form_type.set_meta_archetype(&meta_type);
assert_eq!(form_type.meta_archetype(), meta_type);
let form_type2 = form_type.individuate_as_archetype();
let form_type3 = form_type2.individuate_as_archetype();
assert_eq!(form_type3.meta_archetype(), meta_type);
assert!(!form_type3.has_specific_meta());
}
#[test]
fn test_form_meta_inheritance_override() {
initialize_kb();
let mut form_type = Form::archetype().individuate_as_archetype();
let meta_type = Archetype::archetype().individuate_as_archetype();
form_type.set_meta_archetype(&meta_type);
let form_type2 = form_type.individuate_as_archetype();
let mut form_type3 = form_type2.individuate_as_archetype();
let meta_type3 = form_type3.specific_meta();
assert_eq!(form_type3.meta_archetype(), meta_type3);
assert!(meta_type3.has_ancestor(meta_type));
assert!(form_type3.has_specific_meta());
}
#[test]
fn test_new_is_individual() {
initialize_kb();
let new_instance = Form::new();
assert!(new_instance.is_individual());
}
#[test]
fn test_individual_as_form_is_individual() {
initialize_kb();
let new_instance = Form::archetype().individuate_as_form();
assert!(new_instance.is_individual());
}
#[test]
fn test_query_meta() {
initialize_kb();
let new_attr = Attribute::from(Owner::new().id());
assert!(new_attr.meta().attributes().contains(&Owner::archetype()));
}
}