use super::object_value::ObjectValue;
use crate::ir::exclusion::{IriExclusion, LanguageExclusion, LiteralExclusion};
use prefixmap::PrefixMap;
use rudof_iri::IriS;
use rudof_rdf::rdf_core::term::{
Object,
literal::{ConcreteLiteral, Lang},
};
use std::fmt::Display;
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ValueSetValue {
IriStem {
stem: IriS,
},
IriStemRange {
stem: IriOrWildcard,
exclusions: Option<Vec<IriExclusion>>,
},
LiteralStem {
stem: String,
},
LiteralStemRange {
stem: StringOrWildcard,
exclusions: Option<Vec<LiteralExclusion>>,
},
Language {
language_tag: Lang,
},
LanguageStem {
stem: LangOrWildcard,
},
LanguageStemRange {
stem: LangOrWildcard,
exclusions: Option<Vec<LanguageExclusion>>,
},
ObjectValue(ObjectValue),
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum StringOrLiteralStem {
String(String),
LiteralStem { stem: String },
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum IriOrWildcard {
Iri(IriS),
Wildcard { type_: String },
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum StringOrWildcard {
String(String),
Wildcard { type_: String },
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum LangOrWildcard {
Lang(Lang),
Wildcard { type_: String },
}
impl Display for LangOrWildcard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
LangOrWildcard::Lang(lang) => write!(f, "{lang}"),
LangOrWildcard::Wildcard { .. } => write!(f, ""),
}
}
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum StringOrIriStem {
String(String),
IriStem { stem: String },
}
impl ValueSetValue {
pub fn match_value(&self, object: &Object) -> bool {
match self {
ValueSetValue::IriStem { stem } => match object {
Object::Iri(iri_s) => iri_s.as_str().starts_with(stem.as_str()),
_ => false,
},
ValueSetValue::IriStemRange { stem, exclusions } => {
let matches_stem = match stem {
IriOrWildcard::Iri(iri) => match object {
Object::Iri(iri_s) => iri_s.as_str().starts_with(iri.as_str()),
_ => false,
},
IriOrWildcard::Wildcard { type_: _ } => true, };
if !matches_stem {
return false;
}
if let Some(exclusions) = exclusions {
for ex in exclusions {
match ex {
IriExclusion::Iri(iri) => {
if let Object::Iri(iri_s) = object
&& iri_s.as_str() == iri.as_str()
{
return false;
}
},
IriExclusion::IriStem(stem) => {
if let Object::Iri(iri_s) = object
&& iri_s.as_str().starts_with(stem.as_str())
{
return false;
}
},
}
}
}
true
},
ValueSetValue::LiteralStem { stem } => match object {
Object::Literal(lit) => {
let str = lit.lexical_form();
str.starts_with(stem)
},
_ => false,
},
ValueSetValue::LiteralStemRange { stem, exclusions } => {
let matches_stem = match stem {
StringOrWildcard::String(s) => match object {
Object::Literal(lit) => {
let str = lit.lexical_form();
str.starts_with(s)
},
_ => false,
},
StringOrWildcard::Wildcard { type_: _ } => true, };
if !matches_stem {
return false;
}
if let Some(exclusions) = exclusions {
for ex in exclusions {
match ex {
LiteralExclusion::Literal(s) => {
if let Object::Literal(lit) = object {
let str = lit.lexical_form();
if str == *s {
return false;
}
}
},
LiteralExclusion::LiteralStem(stem) => {
if let Object::Literal(lit) = object {
let str = lit.lexical_form();
if str.starts_with(stem) {
return false;
}
}
},
}
}
}
true
},
ValueSetValue::Language { language_tag } => object.lang().map(|lang| language_tag == lang).unwrap_or(false),
ValueSetValue::LanguageStem { stem } => object
.lang()
.map(|lang| match stem {
LangOrWildcard::Lang(s) => lang.as_str().starts_with(s.as_str()),
LangOrWildcard::Wildcard { .. } => true, })
.unwrap_or(false),
ValueSetValue::LanguageStemRange { stem, exclusions } => {
let matches_stem = match stem {
LangOrWildcard::Lang(lang) => match object {
Object::Literal(ConcreteLiteral::StringLiteral { lang: Some(l), .. }) => {
l.as_str().starts_with(lang.as_str())
},
_ => false,
},
LangOrWildcard::Wildcard { type_: _ } => true, };
if !matches_stem {
return false;
}
if let Some(exclusions) = exclusions {
for ex in exclusions {
match ex {
LanguageExclusion::Language(lang) => {
if let Object::Literal(ConcreteLiteral::StringLiteral { lang: Some(l), .. }) = object
&& l == lang
{
return false;
}
},
LanguageExclusion::LanguageStem(stem) => {
if let Object::Literal(ConcreteLiteral::StringLiteral { lang: Some(l), .. }) = object
&& l.as_str().starts_with(stem.as_str())
{
return false;
}
},
}
}
}
true
},
ValueSetValue::ObjectValue(v) => v.match_value(object),
}
}
pub fn show_qualified(&self, prefixmap: &PrefixMap) -> String {
match self {
ValueSetValue::IriStem { stem } => format!("{}~", prefixmap.qualify(stem)),
ValueSetValue::IriStemRange { stem, exclusions } => {
let mut s = match stem {
IriOrWildcard::Iri(iri) => prefixmap.qualify(iri),
IriOrWildcard::Wildcard { type_: _ } => "*".to_string(),
};
s.push('~');
if let Some(exclusions) = exclusions {
s.push_str(" - ");
let mut first = true;
for ex in exclusions {
if !first {
s.push(' ');
}
s.push_str(&ex.to_string());
first = false;
}
}
s
},
ValueSetValue::LiteralStem { stem } => {
format!("{stem}~")
},
ValueSetValue::LiteralStemRange { stem, exclusions } => {
let mut s = match stem {
StringOrWildcard::String(s) => s.clone(),
StringOrWildcard::Wildcard { type_: _ } => "*".to_string(),
};
s.push('~');
if let Some(exclusions) = exclusions {
s.push_str(" - ");
let mut first = true;
for ex in exclusions {
if !first {
s.push(' ');
}
s.push_str(&ex.to_string());
first = false;
}
}
s
},
ValueSetValue::Language { language_tag } => {
format!("@{}", language_tag)
},
ValueSetValue::LanguageStem { stem } => {
format!("@{stem}~")
},
ValueSetValue::LanguageStemRange { stem, exclusions } => {
let mut s = match stem {
LangOrWildcard::Lang(lang) => lang.to_string(),
LangOrWildcard::Wildcard { type_: _ } => "*".to_string(),
};
s.push('~');
if let Some(exclusions) = exclusions {
s.push_str(" - ");
let mut first = true;
for ex in exclusions {
if !first {
s.push_str(", ");
}
s.push_str(&ex.to_string());
first = false;
}
}
s
},
ValueSetValue::ObjectValue(object_value) => object_value.show_qualified(prefixmap),
}
}
}
impl Display for ValueSetValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ValueSetValue::IriStem { stem } => write!(f, "{stem}~"),
ValueSetValue::IriStemRange { stem, exclusions } => {
match stem {
IriOrWildcard::Iri(iri) => write!(f, "{iri}~"),
IriOrWildcard::Wildcard { type_ } => write!(f, "*{type_}"),
}?;
if let Some(exclusions) = exclusions {
write!(f, " EXCEPT ")?;
let mut first = true;
for ex in exclusions {
if !first {
write!(f, ", ")?;
}
write!(f, "{ex}")?;
first = false;
}
}
Ok(())
},
ValueSetValue::LiteralStem { stem } => write!(f, "{stem}~"),
ValueSetValue::LiteralStemRange { stem, exclusions } => {
match stem {
StringOrWildcard::String(s) => write!(f, "{s}~"),
StringOrWildcard::Wildcard { type_ } => write!(f, "*{type_}"),
}?;
if let Some(exclusions) = exclusions {
write!(f, " EXCEPT ")?;
let mut first = true;
for ex in exclusions {
if !first {
write!(f, ", ")?;
}
write!(f, "{ex}")?;
first = false;
}
}
Ok(())
},
ValueSetValue::Language { language_tag } => write!(f, "@{language_tag}"),
ValueSetValue::LanguageStem { stem } => write!(f, "{stem}~"),
ValueSetValue::LanguageStemRange { stem, exclusions } => {
match stem {
LangOrWildcard::Lang(lang) => write!(f, "{lang}~"),
LangOrWildcard::Wildcard { type_ } => write!(f, "*{type_}"),
}?;
if let Some(exclusions) = exclusions {
write!(f, " EXCEPT ")?;
let mut first = true;
for ex in exclusions {
if !first {
write!(f, ", ")?;
}
write!(f, "{ex}")?;
first = false;
}
}
Ok(())
},
ValueSetValue::ObjectValue(ov) => write!(f, "{ov}"),
}
}
}