Skip to content

Commit

Permalink
use blanknodes
Browse files Browse the repository at this point in the history
  • Loading branch information
nbittich committed Nov 23, 2024
1 parent dac8128 commit 420b412
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 149 deletions.
1 change: 1 addition & 0 deletions src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub const NS_TYPE: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
pub const RDF_NIL: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#nil";
pub const RDF_FIRST: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#first";
pub const RDF_REST: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#rest";
#[allow(unused)]
pub const DEFAULT_WELL_KNOWN_PREFIX: &str = "http://example.org/.well-known/genid#";
pub static DATE_FORMATS: [&str; 9] = [
"%Y-%m-%dT%H:%M:%S%.3f%Z",
Expand Down
2 changes: 1 addition & 1 deletion src/triple_common_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ pub(crate) mod triple {
pub(crate) fn labeled_bnode(s: &str) -> ParserResult<BlankNode> {
let parse_label = delimited(
tag(BLANK_NODE_LABEL),
take_while(|s: char| !s.is_whitespace()),
take_while(|s: char| !s.is_whitespace() && s != '.' && s != ';' && s != '<'),
space0,
);

Expand Down
80 changes: 62 additions & 18 deletions src/turtle/turtle_doc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::grammar::BLANK_NODE_LABEL;
use crate::shared::{
DATE_FORMATS, DEFAULT_DATE_FORMAT, DEFAULT_DATE_TIME_FORMAT, DEFAULT_TIME_FORMAT,
DEFAULT_WELL_KNOWN_PREFIX, RDF_FIRST, RDF_NIL, RDF_REST, TIME_FORMATS, XSD_BOOLEAN, XSD_DATE,
XSD_DATE_TIME, XSD_DECIMAL, XSD_DOUBLE, XSD_INTEGER, XSD_TIME,
DATE_FORMATS, DEFAULT_DATE_FORMAT, DEFAULT_DATE_TIME_FORMAT, DEFAULT_TIME_FORMAT, RDF_FIRST,
RDF_NIL, RDF_REST, TIME_FORMATS, XSD_BOOLEAN, XSD_DATE, XSD_DATE_TIME, XSD_DECIMAL, XSD_DOUBLE,
XSD_INTEGER, XSD_TIME,
};
use crate::triple_common_parser::{comments, Literal as ASTLiteral};
use crate::triple_common_parser::{BlankNode, Iri};
Expand Down Expand Up @@ -40,7 +41,7 @@ fn get_uuid() -> String {

struct Context<'a> {
base: Option<&'a str>,
well_known_prefix: String,
well_known_prefix: Option<String>,
prefixes: BTreeMap<&'a str, &'a str>,
}
#[derive(Serialize, PartialEq, Deserialize, Clone, Debug)]
Expand Down Expand Up @@ -88,6 +89,7 @@ pub enum Node<'a> {
Literal(Literal<'a>),
Ref(Arc<Node<'a>>),
List(Vec<Node<'a>>),
LabeledBlankNode(String),
}
#[derive(PartialEq, PartialOrd, Debug, Clone)]
pub struct Statement<'a> {
Expand All @@ -97,7 +99,7 @@ pub struct Statement<'a> {
}
#[derive(PartialEq, PartialOrd, Debug, Default)]
pub struct TurtleDoc<'a> {
well_known_prefix: String,
well_known_prefix: Option<String>,
base: Option<&'a str>,
prefixes: BTreeMap<Cow<'a, str>, Cow<'a, str>>,
statements: Vec<Statement<'a>>,
Expand Down Expand Up @@ -139,20 +141,35 @@ impl<'a> PartialEq for Node<'a> {
match (self, other) {
(Node::Iri(n1), Node::Iri(n2)) => n1.eq(n2),
(Node::Literal(n1), Node::Literal(n2)) => n1 == n2,
(l @ Node::Literal(_) | l @ Node::Iri(_) | l @ Node::List(_), Node::Ref(n2)) => {
n2.as_ref().eq(l)
}

(Node::Ref(n1), r @ Node::Iri(_) | r @ Node::Literal(_) | r @ Node::List(_)) => {
n1.as_ref().eq(r)
}
(
l @ Node::Literal(_)
| l @ Node::Iri(_)
| l @ Node::List(_)
| l @ Node::LabeledBlankNode(_),
Node::Ref(n2),
) => n2.as_ref().eq(l),

(
Node::Ref(n1),
r @ Node::Iri(_)
| r @ Node::Literal(_)
| r @ Node::List(_)
| r @ Node::LabeledBlankNode(_),
) => n1.as_ref().eq(r),
(Node::Ref(n1), Node::Ref(n2)) => n1 == n2,
(Node::List(n1), Node::List(n2)) => n1 == n2,
(Node::LabeledBlankNode(n1), Node::LabeledBlankNode(n2)) => n1 == n2,
(Node::Iri(_), Node::Literal(_))
| (Node::Iri(_), Node::LabeledBlankNode(_))
| (Node::Iri(_), Node::List(_))
| (Node::LabeledBlankNode(_), Node::Iri(_))
| (Node::LabeledBlankNode(_), Node::Literal(_))
| (Node::LabeledBlankNode(_), Node::List(_))
| (Node::Literal(_), Node::Iri(_))
| (Node::Literal(_), Node::LabeledBlankNode(_))
| (Node::Literal(_), Node::List(_))
| (Node::List(_), Node::Iri(_))
| (Node::List(_), Node::LabeledBlankNode(_))
| (Node::List(_), Node::Literal(_)) => false,
}
}
Expand Down Expand Up @@ -407,8 +424,8 @@ impl<'a> TurtleDoc<'a> {
turtle_values: Vec<TurtleValue<'a>>,
well_known_prefix: Option<String>,
) -> Result<Self, TurtleDocError> {
let well_known_prefix =
well_known_prefix.unwrap_or_else(|| DEFAULT_WELL_KNOWN_PREFIX.to_string());
// let well_known_prefix =
// well_known_prefix.unwrap_or_else(|| DEFAULT_WELL_KNOWN_PREFIX.to_string());
let mut context = Context {
base: None,
well_known_prefix,
Expand Down Expand Up @@ -606,7 +623,6 @@ impl<'a> TurtleDoc<'a> {
ctx: &'x Context,
statements: &'x mut Vec<Statement<'a>>,
) -> Result<Node<'a>, TurtleDocError> {
let well_known_prefix = ctx.well_known_prefix.as_str();
match value {
v @ TurtleValue::Iri(_) | v @ TurtleValue::Literal(_) => {
let prefixes: BTreeMap<Cow<str>, Cow<str>> = ctx
Expand All @@ -618,11 +634,19 @@ impl<'a> TurtleDoc<'a> {
Self::simple_turtle_value_to_node(v, base, prefixes, true)
}
TurtleValue::BNode(BlankNode::Labeled(label)) => {
Ok(Node::Iri(Cow::Owned(well_known_prefix.to_owned() + label)))
if let Some(well_known_prefix) = ctx.well_known_prefix.as_ref() {
Ok(Node::Iri(Cow::Owned(well_known_prefix.to_owned() + label)))
} else {
Ok(Node::LabeledBlankNode(label.into()))
}
}
TurtleValue::BNode(BlankNode::Unlabeled) => {
let uuid = get_uuid();
Ok(Node::Iri(Cow::Owned(format!("{well_known_prefix}{uuid}"))))
if let Some(well_known_prefix) = ctx.well_known_prefix.as_ref() {
Ok(Node::Iri(Cow::Owned(format!("{well_known_prefix}{uuid}"))))
} else {
Ok(Node::LabeledBlankNode(uuid.replace("-", "")))
}
}
TurtleValue::Statement {
subject,
Expand Down Expand Up @@ -786,7 +810,14 @@ impl From<&Node<'_>> for RdfJsonNodeResult {
fn from(value: &Node<'_>) -> Self {
let typ_uri = "uri".into();
let typ_literal = "literal".into();
let typ_bnode = "bnode".into();
match value {
Node::LabeledBlankNode(bnode) => RdfJsonNodeResult::SingleNode(RdfJsonNode {
typ: typ_bnode,
datatype: None,
lang: None,
value: bnode.into(),
}),
Node::Iri(iri) => RdfJsonNodeResult::SingleNode(RdfJsonNode {
typ: typ_uri,
datatype: None,
Expand Down Expand Up @@ -916,6 +947,9 @@ impl Display for Node<'_> {
Node::Literal(Literal::Time(d)) => {
write!(f, r#""{}"^^<{}>"#, d.format(DEFAULT_TIME_FORMAT), XSD_TIME)
}
Node::LabeledBlankNode(bnode) => {
write!(f, "{BLANK_NODE_LABEL}{bnode}")
}
Node::List(list) => {
panic!("encountered node list where we shouldn't {list:?}");
}
Expand Down Expand Up @@ -1214,6 +1248,15 @@ mod test {
assert_eq!(9, triples.len());
}

#[test]
#[serial]
fn test_labeled_bnode_err() {
FAKE_UUID_GEN.store(0, std::sync::atomic::Ordering::SeqCst);
let mut buf_c = String::new();
let turtle_c =
TurtleDoc::from_file("tests/labeled_bnode_err.ttl", None, &mut buf_c).unwrap();
assert_eq!(turtle_c.len(), 40)
}
#[test]
#[serial]
fn other_test() {
Expand All @@ -1228,9 +1271,10 @@ mod test {
println!("{}", turtle_expected.difference(&turtle_c).unwrap());
assert_eq!(turtle_c.difference(&turtle_expected).unwrap().len(), 0);
}

#[test]
#[serial]
fn complex_test() {
fn complex_test_with_bnode() {
FAKE_UUID_GEN.store(0, std::sync::atomic::Ordering::SeqCst);
let mut buf_c = String::new();
let mut buf_e = String::new();
Expand Down
27 changes: 26 additions & 1 deletion src/turtle/turtle_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,32 @@ mod test {
);
}

#[test] // NORDINE
#[test]
fn predicate_labeled_bnode_test() {
let s = r#"
<http://example.org/ns#ComplexResource> <http://example.org/ns#hasNestedObject> _:1.
"#;
let (rest, res) = statements(s).unwrap();
assert!(rest.trim().is_empty());
assert_eq!(
res,
vec![TurtleValue::Statement {
subject: Box::new(TurtleValue::Iri(Iri::Enclosed(
"http://example.org/ns#ComplexResource",
),)),
predicate_objects: [TurtleValue::PredicateObject {
predicate: Box::new(TurtleValue::Iri(Iri::Enclosed(
"http://example.org/ns#hasNestedObject",
),)),
object: Box::new(TurtleValue::BNode(BlankNode::Labeled("1",),)),
},]
.into(),
},]
);
}

#[test]
fn collection_test_from_other() {
let s = r#"
ex:techProducts ex:hasProducts ( ex:product1 ex:product2 )."#;
Expand Down
58 changes: 29 additions & 29 deletions tests/expected_complex.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
<http://example.org/ns#ComplexResource> <http://purl.org/dc/elements/1.1/created> "2024-11-22T12:34:56Z"^^<http://www.w3.org/2001/XMLSchema#dateTime>.
<http://example.org/ns#ComplexResource> <http://example.org/ns#hasValue> "42"^^<http://www.w3.org/2001/XMLSchema#integer>.
<http://example.org/ns#ComplexResource> <http://example.org/ns#hasValue> "forty-two"@en.
<http://example.org/.well-known/genid#1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/ns#NestedType>.
<http://example.org/.well-known/genid#1> <http://example.org/ns#nestedProperty> "Nested Value"^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/.well-known/genid#1> <http://example.org/ns#linksTo> <http://example.org/another-resource>.
<http://example.org/ns#ComplexResource> <http://example.org/ns#hasNestedObject> <http://example.org/.well-known/genid#1>.
<http://example.org/.well-known/genid#2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Item1"^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/.well-known/genid#3> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Item2"^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/.well-known/genid#5> <http://example.org/ns#innerProperty> "Inner Value"^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/.well-known/genid#4> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.org/.well-known/genid#5>.
<http://example.org/.well-known/genid#4> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>.
<http://example.org/.well-known/genid#3> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://example.org/.well-known/genid#4>.
<http://example.org/.well-known/genid#2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://example.org/.well-known/genid#3>.
<http://example.org/ns#ComplexResource> <http://example.org/ns#hasCollection> <http://example.org/.well-known/genid#2>.
_:1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/ns#NestedType>.
_:1 <http://example.org/ns#nestedProperty> "Nested Value"^^<http://www.w3.org/2001/XMLSchema#string>.
_:1 <http://example.org/ns#linksTo> <http://example.org/another-resource>.
<http://example.org/ns#ComplexResource> <http://example.org/ns#hasNestedObject> _:1.
_:2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Item1"^^<http://www.w3.org/2001/XMLSchema#string>.
_:3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Item2"^^<http://www.w3.org/2001/XMLSchema#string>.
_:5 <http://example.org/ns#innerProperty> "Inner Value"^^<http://www.w3.org/2001/XMLSchema#string>.
_:4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:5.
_:4 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>.
_:3 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:4.
_:2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:3.
<http://example.org/ns#ComplexResource> <http://example.org/ns#hasCollection> _:2.
<http://example.org/ns#ComplexResource> <http://www.w3.org/2004/02/skos/core#note> "This resource demonstrates a variety of RDF features."@en.
<http://example.org/ns#ComplexResource> <http://www.w3.org/2002/07/owl#sameAs> <http://example.org/ns#AliasResource>.
<http://example.org/ns#Type1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class>.
Expand All @@ -24,27 +24,27 @@
<http://example.org/ns#SuperType> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Class>.
<http://example.org/ns#SuperType> <http://www.w3.org/2000/01/rdf-schema#label> "Super Type"@en.
<http://example.org/ns#SuperType> <http://www.w3.org/2000/01/rdf-schema#comment> "A superclass for demonstration purposes."@en.
<http://example.org/.well-known/genid#6> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/ns#AnonymousType>.
<http://example.org/.well-known/genid#6> <http://example.org/ns#anonymousProperty> "I am a blank node."^^<http://www.w3.org/2001/XMLSchema#string>.
_:6 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/ns#AnonymousType>.
_:6 <http://example.org/ns#anonymousProperty> "I am a blank node."^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/ns#MultilingualResource> <http://purl.org/dc/elements/1.1/title> "Título en Español"@es.
<http://example.org/ns#MultilingualResource> <http://purl.org/dc/elements/1.1/title> "Title in English"@en.
<http://example.org/ns#MultilingualResource> <http://purl.org/dc/elements/1.1/title> "Titre en Français"@fr.
<http://example.org/ns#DataTypedLiterals> <http://example.org/ns#integerValue> "123"^^<http://www.w3.org/2001/XMLSchema#integer>.
<http://example.org/ns#DataTypedLiterals> <http://example.org/ns#decimalValue> "123.45"^^<http://www.w3.org/2001/XMLSchema#decimal>.
<http://example.org/ns#DataTypedLiterals> <http://example.org/ns#booleanValue> "true"^^<http://www.w3.org/2001/XMLSchema#boolean>.
<http://example.org/ns#DataTypedLiterals> <http://example.org/ns#customValue> "custom-datatype"^^<http://example.org/ns#CustomDatatype>.
<http://example.org/.well-known/genid#7> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement>.
<http://example.org/.well-known/genid#7> <http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://example.org/ns#ComplexResource>.
<http://example.org/.well-known/genid#7> <http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://purl.org/dc/elements/1.1/creator>.
<http://example.org/.well-known/genid#7> <http://www.w3.org/1999/02/22-rdf-syntax-ns#object> "Author Name"@en.
<http://example.org/.well-known/genid#8> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "First Item"^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/.well-known/genid#10> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Nested Item 1"^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/.well-known/genid#11> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Nested Item 2"^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/.well-known/genid#11> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>.
<http://example.org/.well-known/genid#10> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://example.org/.well-known/genid#11>.
<http://example.org/.well-known/genid#9> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> <http://example.org/.well-known/genid#10>.
<http://example.org/.well-known/genid#12> <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Second Item"^^<http://www.w3.org/2001/XMLSchema#string>.
<http://example.org/.well-known/genid#12> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>.
<http://example.org/.well-known/genid#9> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://example.org/.well-known/genid#12>.
<http://example.org/.well-known/genid#8> <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://example.org/.well-known/genid#9>.
<http://example.org/ns#ComplexList> <http://example.org/ns#hasList> <http://example.org/.well-known/genid#8>.
_:7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/1999/02/22-rdf-syntax-ns#Statement>.
_:7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#subject> <http://example.org/ns#ComplexResource>.
_:7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate> <http://purl.org/dc/elements/1.1/creator>.
_:7 <http://www.w3.org/1999/02/22-rdf-syntax-ns#object> "Author Name"@en.
_:8 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "First Item"^^<http://www.w3.org/2001/XMLSchema#string>.
_:10 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Nested Item 1"^^<http://www.w3.org/2001/XMLSchema#string>.
_:11 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Nested Item 2"^^<http://www.w3.org/2001/XMLSchema#string>.
_:11 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>.
_:10 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:11.
_:9 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> _:10.
_:12 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "Second Item"^^<http://www.w3.org/2001/XMLSchema#string>.
_:12 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>.
_:9 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:12.
_:8 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:9.
<http://example.org/ns#ComplexList> <http://example.org/ns#hasList> _:8.
Loading

0 comments on commit 420b412

Please sign in to comment.