use crate::error::Error;
use crate::model::features::{Featured, FEATURE_GRAPH_DUPLICATES, FEATURE_RDF_STAR};
use crate::model::statement::{BlankNode, ObjectNode, Statement, SubjectNode};
use bimap::BiHashMap;
use rdftk_iri::{Iri, IriExtra, Name, QName};
use rdftk_names::{dc, foaf, owl, rdf, rdfs, skos, xsd};
use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Display, Formatter};
use std::hash::Hash;
use std::iter::FusedIterator;
use std::str::FromStr;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum GraphName {
BNode(BlankNode),
Iri(Iri),
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct PrefixMapping {
map: BiHashMap<Option<Name>, Iri>,
}
#[derive(Clone, Debug, Default)]
pub struct Graph {
name: Option<GraphName>,
statements: Statements,
mappings: PrefixMapping,
}
#[derive(Clone, Debug)]
enum Statements {
Unique(HashSet<Statement>),
NonUnique(Vec<Statement>),
}
#[derive(Debug)]
enum StatementIter<'a> {
Unique(std::collections::hash_set::Iter<'a, Statement>),
NonUnique(std::slice::Iter<'a, Statement>),
}
impl Display for GraphName {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match &self {
Self::BNode(node) => format!("_:{}", node),
Self::Iri(iri) => format!("<{}>", iri),
}
)
}
}
impl From<Name> for GraphName {
fn from(name: Name) -> Self {
Self::BNode(BlankNode::from(name))
}
}
impl From<&Name> for GraphName {
fn from(name: &Name) -> Self {
Self::BNode(BlankNode::from(name))
}
}
impl From<BlankNode> for GraphName {
fn from(name: BlankNode) -> Self {
Self::BNode(name)
}
}
impl From<&BlankNode> for GraphName {
fn from(name: &BlankNode) -> Self {
Self::BNode(name.clone())
}
}
impl From<Iri> for GraphName {
fn from(name: Iri) -> Self {
Self::Iri(name)
}
}
impl From<&Iri> for GraphName {
fn from(name: &Iri) -> Self {
Self::Iri(name.clone())
}
}
impl From<SubjectNode> for GraphName {
fn from(value: SubjectNode) -> Self {
match value {
SubjectNode::Blank(v) => Self::BNode(v.clone()),
SubjectNode::Resource(v) => Self::Iri(v.clone()),
_ => unreachable!(),
}
}
}
impl GraphName {
pub fn blank() -> Self {
Self::BNode(BlankNode::generate())
}
pub fn blank_named<S>(name: S) -> Result<Self, Error>
where
S: AsRef<str>,
{
Ok(Self::BNode(BlankNode::from_str(name.as_ref())?))
}
pub fn named(name: Iri) -> Self {
Self::Iri(name)
}
pub fn is_blank(&self) -> bool {
matches!(self, Self::BNode(_))
}
pub fn as_blank(&self) -> Option<&BlankNode> {
match &self {
Self::BNode(s) => Some(s),
_ => None,
}
}
pub fn is_iri(&self) -> bool {
matches!(self, Self::Iri(_))
}
pub fn as_iri(&self) -> Option<&Iri> {
match &self {
Self::Iri(u) => Some(u),
_ => None,
}
}
}
impl PrefixMapping {
pub fn common() -> Self {
Self::default()
.with_dc_elements()
.with_owl()
.with_rdf()
.with_rdfs()
.with_skos()
.with_xsd()
}
pub fn with_default(self, iri: Iri) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.set_default_namespace(iri);
mut_self
}
pub fn with_dc_terms(self) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert_dc_terms();
mut_self
}
pub fn with_dc_elements(self) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert_dc_elements();
mut_self
}
pub fn with_foaf(self) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert_foaf();
mut_self
}
pub fn with_owl(self) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert_owl();
mut_self
}
pub fn with_rdf(self) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert_rdf();
mut_self
}
pub fn with_rdfs(self) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert_rdfs();
mut_self
}
pub fn with_xsd(self) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert_xsd();
mut_self
}
pub fn with_skos(self) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert_skos();
mut_self
}
pub fn with(self, prefix: Name, iri: Iri) -> Self
where
Self: Sized,
{
let mut mut_self = self;
mut_self.insert(prefix, iri);
mut_self
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn get_default_namespace(&self) -> Option<&Iri> {
self.map.get_by_left(&None)
}
pub fn set_default_namespace(&mut self, iri: Iri) {
let _ = self.map.insert(None, iri);
}
pub fn remove_default_namespace(&mut self) {
let _ = self.map.remove_by_left(&None);
}
pub fn get_namespace(&self, prefix: &Name) -> Option<&Iri> {
self.map.get_by_left(&Some(prefix.clone()))
}
pub fn get_prefix(&self, namespace: &Iri) -> Option<&Option<Name>> {
self.map.get_by_right(namespace)
}
pub fn mappings<'a>(&'a self) -> Box<dyn Iterator<Item = (&'a Option<Name>, &'a Iri)> + 'a> {
Box::new(self.map.iter())
}
pub fn insert(&mut self, prefix: Name, iri: Iri) {
let _ = self.map.insert(Some(prefix), iri);
}
pub fn insert_owl(&mut self) {
self.insert(owl::default_prefix().clone(), owl::namespace().clone());
}
pub fn insert_rdf(&mut self) {
self.insert(rdf::default_prefix().clone(), rdf::namespace().clone());
}
pub fn insert_rdfs(&mut self) {
self.insert(rdfs::default_prefix().clone(), rdfs::namespace().clone());
}
pub fn insert_xsd(&mut self) {
self.insert(xsd::default_prefix().clone(), xsd::namespace().clone());
}
pub fn insert_foaf(&mut self) {
self.insert(foaf::default_prefix().clone(), foaf::namespace().clone());
}
pub fn insert_dc_elements(&mut self) {
self.insert(
dc::elements::default_prefix().clone(),
dc::elements::namespace().clone(),
);
}
pub fn insert_dc_terms(&mut self) {
self.insert(
dc::terms::default_prefix().clone(),
dc::terms::namespace().clone(),
);
}
pub fn insert_skos(&mut self) {
self.insert(skos::default_prefix().clone(), skos::namespace().clone());
}
pub fn insert_skos_xl(&mut self) {
self.insert(
skos::xl::default_prefix().clone(),
skos::xl::namespace().clone(),
);
}
pub fn insert_skos_iso(&mut self) {
self.insert(
skos::iso::default_prefix().clone(),
skos::iso::namespace().clone(),
);
}
pub fn remove(&mut self, prefix: &Name) {
let _ = self.map.remove_by_left(&Some(prefix.clone()));
}
pub fn clear(&mut self) {
self.map.clear();
}
pub fn expand(&self, qname: &QName) -> Option<Iri> {
let prefix = if let Some(prefix) = qname.prefix() {
self.get_namespace(prefix)
} else {
self.get_default_namespace()
};
match prefix {
None => None,
Some(namespace) => namespace.make_name(qname.name().clone()),
}
}
pub fn compress(&self, iri: &Iri) -> Option<QName> {
let (iri, name) = if let Some((iri, name)) = iri.split() {
(iri, name)
} else {
return None;
};
match self.get_prefix(&iri) {
None => None,
Some(None) => Some(QName::new_unqualified(name).unwrap()),
Some(Some(prefix)) => Some(QName::new(prefix.clone(), name).unwrap()),
}
}
}
impl Featured for Graph {
fn supports_feature(&self, feature: &Iri) -> bool {
(*feature == *FEATURE_GRAPH_DUPLICATES && self.statements.is_unique())
|| *feature == *FEATURE_RDF_STAR
}
}
impl From<Statement> for Graph {
fn from(value: Statement) -> Self {
Self::from_iter([value])
}
}
impl From<Vec<Statement>> for Graph {
fn from(value: Vec<Statement>) -> Self {
Graph::from_iter(value)
}
}
impl FromIterator<Statement> for Graph {
fn from_iter<T: IntoIterator<Item = Statement>>(iter: T) -> Self {
Self {
statements: Statements::NonUnique(iter.into_iter().collect()),
..Default::default()
}
}
}
impl Graph {
pub fn named<N>(name: N) -> Self
where
N: Into<GraphName>,
{
Self {
name: Some(name.into()),
..Default::default()
}
}
pub fn unique() -> Self {
Self {
statements: Statements::Unique(Default::default()),
..Default::default()
}
}
pub fn unique_named<N>(name: N) -> Self
where
N: Into<GraphName>,
{
Self {
name: Some(name.into()),
..Self::unique()
}
}
pub fn with_mappings(self, mappings: PrefixMapping) -> Self {
Self { mappings, ..self }
}
pub fn with_statements(self, statements: Vec<Statement>) -> Self {
Self {
statements: match self.statements {
Statements::Unique(_) => Statements::Unique(HashSet::from_iter(statements)),
Statements::NonUnique(_) => Statements::NonUnique(statements),
},
..self
}
}
pub fn is_empty(&self) -> bool {
self.statements.is_empty()
}
pub fn len(&self) -> usize {
self.statements.len()
}
pub fn is_named(&self) -> bool {
self.name().is_some()
}
pub fn name(&self) -> Option<&GraphName> {
self.name.as_ref()
}
pub fn set_name(&mut self, name: GraphName) {
self.name = Some(name);
}
pub fn unset_name(&mut self) {
self.name = None;
}
pub fn contains_subject(&self, subject: &SubjectNode) -> bool {
self.statements.iter().any(|st| st.subject() == subject)
}
pub fn contains(&self, statement: &Statement) -> bool {
!self
.matches(
Some(statement.subject()),
Some(statement.predicate()),
Some(statement.object()),
)
.is_empty()
}
pub fn contains_all(
&self,
subject: &SubjectNode,
predicate: &Iri,
object: &ObjectNode,
) -> bool {
!self
.matches(Some(subject), Some(predicate), Some(object))
.is_empty()
}
pub fn matches(
&self,
subject: Option<&SubjectNode>,
predicate: Option<&Iri>,
object: Option<&ObjectNode>,
) -> HashSet<&Statement> {
self.statements
.iter()
.filter(|st| {
(subject.is_some() && st.subject() == subject.unwrap())
&& (predicate.is_some() && st.predicate() == predicate.unwrap())
&& (object.is_some() && st.object() == object.unwrap())
})
.collect()
}
pub fn statements(&self) -> impl Iterator<Item = &Statement> {
self.statements.iter()
}
pub fn subjects(&self) -> HashSet<&SubjectNode> {
self.statements.iter().map(|st| st.subject()).collect()
}
pub fn node_subjects(&self) -> HashSet<&SubjectNode> {
self.subjects()
.into_iter()
.filter(|s| !s.is_blank())
.collect()
}
pub fn blank_node_subjects(&self) -> HashSet<&SubjectNode> {
self.subjects()
.into_iter()
.filter(|s| s.is_blank())
.collect()
}
pub fn predicates(&self) -> HashSet<&Iri> {
self.statements.iter().map(|st| st.predicate()).collect()
}
pub fn predicates_for(&self, subject: &SubjectNode) -> HashSet<&Iri> {
self.statements
.iter()
.filter_map(|st| {
if st.subject() == subject {
Some(st.predicate())
} else {
None
}
})
.collect()
}
pub fn objects(&self) -> HashSet<&ObjectNode> {
self.statements.iter().map(|st| st.object()).collect()
}
pub fn objects_for(&self, subject: &SubjectNode, predicate: &Iri) -> HashSet<&ObjectNode> {
self.statements
.iter()
.filter_map(|st| {
if st.subject() == subject && st.predicate() == predicate {
Some(st.object())
} else {
None
}
})
.collect()
}
pub fn prefix_mappings(&self) -> &PrefixMapping {
&self.mappings
}
pub fn set_prefix_mappings(&mut self, mappings: PrefixMapping) {
self.mappings = mappings;
}
pub fn insert(&mut self, statement: Statement) {
self.statements.insert(statement);
}
pub fn merge(&mut self, other: &Self) {
other.statements().for_each(|st| self.insert(st.clone()))
}
pub fn dedup(&mut self) -> Vec<Statement> {
if self.statements.is_unique() {
Default::default()
} else {
let (keep, discard) = self.statements.iter().fold(
(HashSet::<Statement>::default(), Vec::default()),
|(mut keep, mut discard), st| {
if keep.contains(st) {
discard.push(st.clone());
} else {
let _ = keep.insert(st.clone());
}
(keep, discard)
},
);
self.statements = Statements::NonUnique(Vec::from_iter(keep));
discard
}
}
pub fn remove(&mut self, statement: &Statement) {
self.statements.remove(statement);
}
pub fn remove_all_for(&mut self, subject: &SubjectNode) -> Vec<Statement> {
let (keep, discard) = self.statements.iter().fold(
(Default::default(), Default::default()),
|(mut keep, mut discard): (Vec<Statement>, Vec<Statement>), st| {
if st.subject() == subject {
keep.push(st.clone());
} else {
discard.push(st.clone());
}
(keep, discard)
},
);
if self.statements.is_unique() {
self.statements = Statements::Unique(HashSet::from_iter(keep));
} else {
self.statements = Statements::NonUnique(keep);
}
discard
}
pub fn clear(&mut self) {
self.statements.clear()
}
pub fn skolemize(self, base: &Iri) -> Result<Self, Error> {
let mut mapping: HashMap<BlankNode, Iri> = Default::default();
let mut new_graph = Self::default();
for statement in self.statements() {
let mut new_statement = statement.clone();
if let Some(blank) = new_statement.subject().as_blank() {
if !mapping.contains_key(blank) {
let _ = mapping.insert(blank.clone(), base.genid()?);
}
let name = mapping.get(blank).unwrap().clone();
let subject = SubjectNode::from(name);
new_statement.set_subject(subject);
}
if let Some(blank) = new_statement.object().as_blank() {
if !mapping.contains_key(blank) {
let _ = mapping.insert(blank.clone(), base.genid()?);
}
let name = mapping.get(blank).unwrap().clone();
let object = ObjectNode::from(name);
new_statement.set_object(object);
}
new_graph.insert(new_statement);
}
Ok(new_graph)
}
}
impl Default for Statements {
fn default() -> Self {
Self::NonUnique(Default::default())
}
}
impl Statements {
fn len(&self) -> usize {
match self {
Self::Unique(vs) => vs.len(),
Self::NonUnique(vs) => vs.len(),
}
}
fn is_empty(&self) -> bool {
match self {
Self::Unique(vs) => vs.is_empty(),
Self::NonUnique(vs) => vs.is_empty(),
}
}
fn insert(&mut self, st: Statement) -> bool {
match self {
Self::Unique(vs) => vs.insert(st),
Self::NonUnique(vs) => {
vs.push(st);
true
}
}
}
fn remove(&mut self, st: &Statement) -> bool {
match self {
Self::Unique(vs) => vs.remove(st),
Self::NonUnique(vs) => {
vs.retain(|e| e != st);
true
}
}
}
fn clear(&mut self) {
match self {
Self::Unique(vs) => vs.clear(),
Self::NonUnique(vs) => vs.clear(),
}
}
fn is_unique(&self) -> bool {
matches!(self, Self::Unique(_))
}
fn iter(&self) -> StatementIter<'_> {
match self {
Self::Unique(vs) => StatementIter::Unique(vs.iter()),
Self::NonUnique(vs) => StatementIter::NonUnique(vs.iter()),
}
}
#[allow(dead_code)]
fn into_unique(self) -> Self {
match self {
Statements::Unique(_) => self,
Statements::NonUnique(vs) => Statements::Unique(HashSet::from_iter(vs)),
}
}
#[allow(dead_code)]
fn into_non_unique(self) -> Self {
match self {
Statements::NonUnique(_) => self,
Statements::Unique(vs) => Statements::NonUnique(Vec::from_iter(vs)),
}
}
}
impl<'a> Iterator for StatementIter<'a> {
type Item = &'a Statement;
fn next(&mut self) -> Option<Self::Item> {
match self {
StatementIter::Unique(vs) => vs.next(),
StatementIter::NonUnique(vs) => vs.next(),
}
}
}
impl ExactSizeIterator for StatementIter<'_> {
fn len(&self) -> usize {
match self {
StatementIter::Unique(vs) => vs.len(),
StatementIter::NonUnique(vs) => vs.len(),
}
}
}
impl FusedIterator for StatementIter<'_> {}