use node::{Node};
use std::slice::Iter;
use std::vec::IntoIter;
use std::cmp::PartialEq;
#[derive(PartialEq, Debug)]
pub enum TripleSegment {
Subject,
Predicate,
Object
}
#[derive(PartialOrd, Ord, Clone, Debug)]
pub struct Triple {
subject: Node,
predicate: Node,
object: Node
}
impl Triple {
pub fn new(subject: &Node, predicate: &Node, object: &Node) -> Triple {
Triple {
subject: subject.clone(),
predicate: predicate.clone(),
object: object.clone()
}
}
pub fn subject(&self) -> &Node {
&self.subject
}
pub fn predicate(&self) -> &Node {
&self.predicate
}
pub fn object(&self) -> &Node {
&self.object
}
}
impl PartialEq for Triple {
fn eq(&self, other: &Triple) -> bool {
self.subject() == other.subject() &&
self.predicate() == other.predicate() &&
self.object() == other.object()
}
}
impl Eq for Triple { }
#[derive(Debug)]
pub struct TripleStore {
triples: Vec<Triple>
}
impl TripleStore {
pub fn new() -> TripleStore {
TripleStore {
triples: Vec::new()
}
}
pub fn count(&self) -> usize {
self.triples.len()
}
pub fn is_empty(&self) -> bool {
self.count() == 0
}
pub fn add_triple(&mut self, triple: &Triple) {
self.triples.push(triple.clone());
}
pub fn remove_triple(&mut self, triple: &Triple) {
self.triples.retain(|ref t| {
*t != triple
});
}
pub fn get_triples_with_subject(&self, node: &Node) -> Vec<&Triple> {
self.triples.iter().filter(|t| t.subject() == node).collect::<Vec<_>>()
}
pub fn get_triples_with_predicate(&self, node: &Node) -> Vec<&Triple> {
self.triples.iter().filter(|t| t.predicate() == node).collect::<Vec<_>>()
}
pub fn get_triples_with_object(&self, node: &Node) -> Vec<&Triple> {
self.triples.iter().filter(|t| t.object() == node).collect::<Vec<_>>()
}
pub fn get_triples_with_subject_and_object(&self, subject_node: &Node, object_node: &Node) -> Vec<&Triple> {
self.triples.iter().filter(|t|
t.object() == object_node && t.subject() == subject_node
).collect::<Vec<_>>()
}
pub fn get_triples_with_subject_and_predicate(&self, subject_node: &Node, predicate_node: &Node) -> Vec<&Triple> {
self.triples.iter().filter(|t|
t.predicate() == predicate_node && t.subject() == subject_node
).collect::<Vec<_>>()
}
pub fn get_triples_with_predicate_and_object(&self, predicate_node: &Node, object_node: &Node) -> Vec<&Triple> {
self.triples.iter().filter(|t|
t.predicate() == predicate_node && t.object() == object_node
).collect::<Vec<_>>()
}
pub fn get_blank_nodes(&self) -> Vec<&Node> {
let mut blank_nodes = Vec::new();
for triple in self.triples.iter() {
match triple {
&Triple { subject: Node::BlankNode {id : _}, predicate: _, object: Node::BlankNode {id : _} } => {
blank_nodes.push(triple.subject());
blank_nodes.push(triple.object());
},
&Triple { subject: Node::BlankNode {id : _}, predicate: _, object: _ } =>
blank_nodes.push(triple.subject()),
&Triple { subject: _, predicate: _, object: Node::BlankNode {id : _} } =>
blank_nodes.push(triple.object()),
_ => { }
}
}
blank_nodes
}
pub fn into_vec(self) -> Vec<Triple> {
self.triples
}
pub fn iter(&self) -> Iter<Triple> {
self.triples.iter()
}
}
impl IntoIterator for TripleStore {
type Item = Triple;
type IntoIter = IntoIter<Triple>;
fn into_iter(self) -> Self::IntoIter {
self.triples.into_iter()
}
}
#[cfg(test)]
mod tests {
use node::*;
use triple::*;
#[test]
fn empty_triple_store() {
let store = TripleStore::new();
assert!(store.is_empty());
}
#[test]
fn count_triples_in_triple_store() {
let mut store = TripleStore::new();
let subject = Node::LiteralNode {
literal: "abcd".to_string(),
data_type: None,
language: None
};
let predicate = Node::LiteralNode {
literal: "d".to_string(),
data_type: None,
language: None
};
let object = Node::LiteralNode {
literal: "s".to_string(),
data_type: None,
language: None
};
let trip = Triple::new(&subject, &predicate, &object);
store.add_triple(&trip);
assert_eq!(store.count(), 1);
}
}