use super::{debug_wrapper, BaseNode, BaseNodeTrait, InheritanceNode, InheritanceNodeTrait};
use crate::graph::value_wrappers::KBValue;
use std::cmp::{Eq, PartialEq};
use std::convert::TryFrom;
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::hash::Hash;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub struct FinalNode {
inode: InheritanceNode,
}
#[allow(clippy::new_without_default)]
impl FinalNode {
pub fn new() -> Self {
FinalNode {
inode: InheritanceNode::new(),
}
}
pub fn new_with_inheritance(type_id: usize) -> Self {
Self::from(InheritanceNode::new_with_inheritance(type_id))
}
pub fn inheritance_wrapper(&self) -> &InheritanceNode {
&self.inode
}
pub fn base_wrapper(&self) -> &BaseNode {
&self.inode.base_wrapper()
}
}
impl From<usize> for FinalNode {
fn from(id: usize) -> Self {
FinalNode {
inode: InheritanceNode::from(id),
}
}
}
impl From<BaseNode> for FinalNode {
fn from(b: BaseNode) -> Self {
FinalNode {
inode: InheritanceNode::from(b),
}
}
}
impl From<InheritanceNode> for FinalNode {
fn from(b: InheritanceNode) -> Self {
FinalNode { inode: b }
}
}
impl<'a> TryFrom<&'a str> for FinalNode {
type Error = String;
fn try_from(name: &'a str) -> Result<Self, Self::Error> {
InheritanceNode::try_from(name).map(|n| FinalNode { inode: n })
}
}
impl Debug for FinalNode {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
debug_wrapper("FWrapper", self, f)
}
}
impl Deref for FinalNode {
type Target = InheritanceNode;
fn deref(&self) -> &Self::Target {
&self.inode
}
}
impl DerefMut for FinalNode {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inode
}
}
impl BaseNodeTrait<FinalNode> for FinalNode {
fn set_value(&mut self, value: Rc<dyn KBValue>) {
self.inode.set_value(value)
}
fn value(&self) -> Option<Rc<dyn KBValue>> {
self.inode.value()
}
fn add_flag(&mut self, flag_type: usize) {
self.inode.add_flag(flag_type);
}
fn has_flag(&self, flag_type: usize) -> bool {
self.inode.has_flag(flag_type)
}
fn add_outgoing(&mut self, edge_type: usize, to: &FinalNode) {
self.inode.add_outgoing(edge_type, &to.inode)
}
fn add_incoming(&mut self, edge_type: usize, from: &FinalNode) {
self.inode.add_incoming(edge_type, &from.inode)
}
fn has_outgoing(&self, edge_type: usize, to: &FinalNode) -> bool {
self.inode.has_outgoing(edge_type, &to.inode)
}
fn has_incoming(&self, edge_type: usize, from: &FinalNode) -> bool {
self.inode.has_incoming(edge_type, &from.inode)
}
fn outgoing_nodes(&self, edge_type: usize) -> Vec<FinalNode> {
self.inode
.outgoing_nodes(edge_type)
.into_iter()
.map(FinalNode::from)
.collect()
}
fn incoming_nodes(&self, edge_type: usize) -> Vec<FinalNode> {
self.inode
.incoming_nodes(edge_type)
.into_iter()
.map(FinalNode::from)
.collect()
}
}
impl InheritanceNodeTrait<FinalNode> for FinalNode {
fn inheritance_nodes(&self) -> Vec<FinalNode> {
self.inode
.inheritance_nodes()
.into_iter()
.map(FinalNode::from)
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::graph::value_wrappers::{unwrap_value, WeakValue};
use crate::node_wrappers::CommonNodeTrait;
use crate::tao::archetype::ArchetypeTrait;
use crate::tao::initialize_kb;
use crate::tao::relation::attribute::{Inherits, Owner};
#[test]
fn from_node_id() {
initialize_kb();
let node = FinalNode::new();
let node_copy = FinalNode::from(node.id());
assert_eq!(node.id(), node_copy.id());
}
#[test]
fn from_name() {
initialize_kb();
let mut node = FinalNode::new();
node.set_internal_name("A");
assert_eq!(FinalNode::try_from("A"), Ok(node));
assert!(FinalNode::try_from("B").is_err());
}
#[test]
fn retrieve_node_value() {
initialize_kb();
let mut node = FinalNode::new();
let v = Rc::new(5);
node.set_value(Rc::new(WeakValue::new(&v)));
assert_eq!(unwrap_value::<i32>(node.value()), Some(v));
}
#[test]
fn create_with_inheritance() {
initialize_kb();
let owner = FinalNode::new();
let mut type1 = FinalNode::new();
type1.add_outgoing(Owner::TYPE_ID, &owner);
let node = FinalNode::new_with_inheritance(type1.id());
assert!(node.has_outgoing(Owner::TYPE_ID, &owner));
}
#[test]
fn check_inheritance_nodes() {
initialize_kb();
let type1 = FinalNode::new();
let mut type2 = FinalNode::new();
let mut a = FinalNode::new();
type2.add_outgoing(Inherits::TYPE_ID, &type1);
a.add_outgoing(Inherits::TYPE_ID, &type2);
assert_eq!(a.inheritance_nodes(), vec![type1, type2, a]);
assert_eq!(type2.inheritance_nodes(), vec![type1, type2]);
assert_eq!(type1.inheritance_nodes(), vec![type1]);
}
#[test]
fn test_flags() {
initialize_kb();
let mut a = FinalNode::new();
let b = FinalNode::new();
assert!(!a.has_flag(b.id()));
a.add_flag(b.id());
assert!(a.has_flag(b.id()));
}
#[test]
fn test_inherited_flags() {
initialize_kb();
let mut a = FinalNode::new();
let b = FinalNode::new();
let mut c = FinalNode::new();
c.add_outgoing(Inherits::TYPE_ID, &a);
assert!(!c.has_flag(b.id()));
a.add_flag(b.id());
assert!(c.has_flag(b.id()));
}
#[test]
fn no_outgoing_nodes() {
initialize_kb();
let a = FinalNode::new();
assert_eq!(a.outgoing_nodes(a.id()), Vec::new());
}
#[allow(clippy::many_single_char_names)]
#[test]
fn outgoing_nodes() {
initialize_kb();
let mut a = FinalNode::new();
let b = FinalNode::new();
let c = FinalNode::new();
let d = FinalNode::new();
let mut e = FinalNode::new();
let edge_type1 = FinalNode::new();
let edge_type2 = FinalNode::new();
a.add_outgoing(edge_type1.id(), &b);
a.add_outgoing(edge_type2.id(), &c);
a.add_outgoing(edge_type1.id(), &d);
e.add_outgoing(edge_type1.id(), &a);
assert_eq!(a.outgoing_nodes(edge_type1.id()), vec![b, d]);
}
#[test]
fn inherited_outgoing_nodes() {
initialize_kb();
let mut type1 = FinalNode::new();
let mut type2 = FinalNode::new();
let mut a = FinalNode::new();
let b = FinalNode::new();
let c = FinalNode::new();
let mut d = FinalNode::new();
let edge_type = FinalNode::new();
a.add_outgoing(edge_type.id(), &b);
type1.add_outgoing(edge_type.id(), &c);
type2.add_outgoing(edge_type.id(), &c);
d.add_outgoing(edge_type.id(), &a);
type2.add_outgoing(Inherits::TYPE_ID, &type1);
a.add_outgoing(Inherits::TYPE_ID, &type2);
assert_eq!(a.outgoing_nodes(edge_type.id()), vec![b, c]);
assert_eq!(type1.outgoing_nodes(edge_type.id()), vec![c]);
}
#[test]
fn no_incoming_nodes() {
initialize_kb();
let a = FinalNode::new();
assert_eq!(a.incoming_nodes(a.id()), Vec::new());
}
#[allow(clippy::many_single_char_names)]
#[test]
fn incoming_nodes() {
initialize_kb();
let mut a = FinalNode::new();
let b = FinalNode::new();
let c = FinalNode::new();
let d = FinalNode::new();
let mut e = FinalNode::new();
let edge_type1 = FinalNode::new();
let edge_type2 = FinalNode::new();
a.add_incoming(edge_type1.id(), &b);
a.add_incoming(edge_type2.id(), &c);
a.add_incoming(edge_type1.id(), &d);
e.add_incoming(edge_type1.id(), &a);
assert_eq!(a.incoming_nodes(edge_type1.id()), vec![b, d]);
}
#[test]
fn inherited_incoming_nodes() {
initialize_kb();
let mut type1 = FinalNode::new();
let mut type2 = FinalNode::new();
let mut a = FinalNode::new();
let b = FinalNode::new();
let c = FinalNode::new();
let mut d = FinalNode::new();
let edge_type = FinalNode::new();
a.add_incoming(edge_type.id(), &b);
type1.add_incoming(edge_type.id(), &c);
type2.add_incoming(edge_type.id(), &c);
d.add_incoming(edge_type.id(), &a);
type2.add_outgoing(Inherits::TYPE_ID, &type1);
a.add_outgoing(Inherits::TYPE_ID, &type2);
assert_eq!(a.incoming_nodes(edge_type.id()), vec![b, c]);
assert_eq!(type1.incoming_nodes(edge_type.id()), vec![c]);
}
#[test]
fn test_has_outgoing() {
initialize_kb();
let mut a = FinalNode::new();
let b = FinalNode::new();
let edge_type1 = FinalNode::new();
let edge_type2 = FinalNode::new();
a.add_outgoing(edge_type1.id(), &b);
assert!(a.has_outgoing(edge_type1.id(), &b));
assert!(!a.has_outgoing(edge_type2.id(), &b));
assert!(!b.has_outgoing(edge_type1.id(), &a));
}
#[test]
fn test_has_incoming() {
initialize_kb();
let mut a = FinalNode::new();
let b = FinalNode::new();
let edge_type1 = FinalNode::new();
let edge_type2 = FinalNode::new();
a.add_incoming(edge_type1.id(), &b);
assert!(a.has_incoming(edge_type1.id(), &b));
assert!(!a.has_incoming(edge_type2.id(), &b));
assert!(!b.has_incoming(edge_type1.id(), &a));
}
#[test]
fn inherited_has_outgoing() {
initialize_kb();
let mut type1 = FinalNode::new();
let mut type2 = FinalNode::new();
let mut a = FinalNode::new();
let b = FinalNode::new();
let c = FinalNode::new();
let edge_type = FinalNode::new();
type1.add_outgoing(edge_type.id(), &b);
type1.add_incoming(edge_type.id(), &c);
type2.add_outgoing(Inherits::TYPE_ID, &type1);
a.add_outgoing(Inherits::TYPE_ID, &type2);
assert!(a.has_outgoing(edge_type.id(), &b));
assert!(!a.has_outgoing(edge_type.id(), &c));
}
#[test]
fn inherited_has_incoming() {
initialize_kb();
let mut type1 = FinalNode::new();
let mut type2 = FinalNode::new();
let mut a = FinalNode::new();
let b = FinalNode::new();
let c = FinalNode::new();
let edge_type = FinalNode::new();
type1.add_outgoing(edge_type.id(), &b);
type1.add_incoming(edge_type.id(), &c);
type2.add_outgoing(Inherits::TYPE_ID, &type1);
a.add_outgoing(Inherits::TYPE_ID, &type2);
assert!(!a.has_incoming(edge_type.id(), &b));
assert!(a.has_incoming(edge_type.id(), &c));
}
}