Compare commits
18
Commits
8dcaa5b61f
...
master
| Author | SHA256 | Date | |
|---|---|---|---|
|
|
6d75248bde
|
||
|
|
abe3ac97b5
|
||
|
|
ebad6e6097
|
||
|
|
0c46d08e1d
|
||
|
|
1a122d6ecc
|
||
|
|
277d1d2a2d
|
||
|
|
a8938176be
|
||
|
|
948b415d5a
|
||
|
|
35477a3658
|
||
|
|
78243f53f5
|
||
|
|
70fca07790
|
||
|
|
37248f6ff3
|
||
|
|
8f6e2b3ac6
|
||
|
|
e28cfd1c53
|
||
|
|
631bb539f1
|
||
|
|
fcb1da7e0d
|
||
|
|
025392b129
|
||
|
|
72a39e5baa
|
Generated
+260
-237
File diff suppressed because it is too large
Load Diff
+4
-2
@@ -19,8 +19,8 @@ bytes = "1.12"
|
||||
clap = { version = "4.6", features = ["derive"] }
|
||||
color-eyre = "0.6"
|
||||
futures = "0.3"
|
||||
http = "1.4"
|
||||
iced = { git = "https://github.com/iced-rs/iced.git", branch = "master", features = ["advanced", "tokio"] }
|
||||
http = "1.5"
|
||||
iced = { git = "https://github.com/iced-rs/iced.git", branch = "master", features = ["advanced", "sipper", "tokio"] }
|
||||
num-traits = "0.2"
|
||||
oxigraph = { version = "0.5", features = ["rdf-12"] }
|
||||
oxilangtag = "0.1"
|
||||
@@ -28,8 +28,10 @@ parse_link_header = "0.4"
|
||||
pin-project-lite = "0.2"
|
||||
prost = "0.14"
|
||||
rand = "0.10"
|
||||
rayon = "1.12"
|
||||
rfd = "0.17"
|
||||
slotmap = "1.1"
|
||||
spargebra = "0.4"
|
||||
subtitler = "2.6"
|
||||
tantivy = "0.26"
|
||||
tar = "0.4"
|
||||
|
||||
@@ -9,5 +9,8 @@ gl-search.workspace = true
|
||||
|
||||
oxigraph.workspace = true
|
||||
oxilangtag.workspace = true
|
||||
rayon.workspace = true
|
||||
spargebra.workspace = true
|
||||
thiserror.workspace = true
|
||||
tracing.workspace = true
|
||||
url = "2.5.8"
|
||||
@@ -1,5 +1,5 @@
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
use crate::vocab;
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub enum Category {
|
||||
AudioBook = 0,
|
||||
@@ -8,14 +8,14 @@ pub enum Category {
|
||||
impl Category {
|
||||
pub fn to_named_node(&self) -> NamedNodeRef<'_> {
|
||||
match self {
|
||||
Category::AudioBook => vocab::gl::AUDIO_BOOK,
|
||||
Category::AudioBook => vocab::glo::AUDIO_BOOK,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_from_named_node<'a>(node: impl Into<NamedNodeRef<'a>>) -> Option<Self> {
|
||||
let node = node.into();
|
||||
match node {
|
||||
vocab::gl::AUDIO_BOOK => Some(Category::AudioBook),
|
||||
vocab::glo::AUDIO_BOOK => Some(Category::AudioBook),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
+214
-1
@@ -1,6 +1,11 @@
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
use crate::vocab;
|
||||
use gl_search::Schema;
|
||||
use oxigraph::model::{Graph, LiteralRef, NamedNode, NamedNodeRef, Triple};
|
||||
use oxilangtag::LanguageTag;
|
||||
use std::fmt::Display;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Class {
|
||||
RdfProperty = 0,
|
||||
RdfsClass = 1,
|
||||
@@ -12,7 +17,41 @@ pub enum Class {
|
||||
Manifestation = 10007,
|
||||
}
|
||||
|
||||
impl Display for Class {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Class::RdfProperty => f.write_str("RDF Property"),
|
||||
Class::RdfsClass => f.write_str("RDFS Class"),
|
||||
Class::SkosConcept => f.write_str("SKOS Concept"),
|
||||
Class::Work => f.write_str("Work"),
|
||||
Class::Person => f.write_str("Person"),
|
||||
Class::CorporateBody => f.write_str("Corporate Body"),
|
||||
Class::Expression => f.write_str("Expression"),
|
||||
Class::Manifestation => f.write_str("Manifestation"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Class {
|
||||
pub const ALL: &[Class] = &[
|
||||
Class::RdfProperty,
|
||||
Class::RdfsClass,
|
||||
Class::SkosConcept,
|
||||
Class::Work,
|
||||
Class::Person,
|
||||
Class::CorporateBody,
|
||||
Class::Expression,
|
||||
Class::Manifestation,
|
||||
];
|
||||
|
||||
pub const CREATABLE: &[Class] = &[
|
||||
Class::Work,
|
||||
Class::Person,
|
||||
Class::CorporateBody,
|
||||
Class::Expression,
|
||||
Class::Manifestation,
|
||||
];
|
||||
|
||||
pub fn to_named_node(&self) -> NamedNodeRef<'_> {
|
||||
match self {
|
||||
Class::RdfProperty => vocab::rdf::PROPERTY,
|
||||
@@ -40,4 +79,178 @@ impl Class {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fields(&self, language: LanguageTag<String>) -> Vec<(gl_search::Field, String)> {
|
||||
match self {
|
||||
Class::RdfProperty => vec![
|
||||
(
|
||||
Schema::field("label", Some(language.primary_language())),
|
||||
String::from("Label"),
|
||||
),
|
||||
(
|
||||
Schema::field("definition", Some(language.primary_language())),
|
||||
String::from("Definition"),
|
||||
),
|
||||
],
|
||||
Class::RdfsClass => vec![
|
||||
(
|
||||
Schema::field("label", Some(language.primary_language())),
|
||||
String::from("Label"),
|
||||
),
|
||||
(
|
||||
Schema::field("definition", Some(language.primary_language())),
|
||||
String::from("Definition"),
|
||||
),
|
||||
],
|
||||
Class::SkosConcept => vec![
|
||||
(
|
||||
Schema::field("label", Some(language.primary_language())),
|
||||
String::from("Label"),
|
||||
),
|
||||
(
|
||||
Schema::field("definition", Some(language.primary_language())),
|
||||
String::from("Definition"),
|
||||
),
|
||||
],
|
||||
Class::Work => vec![(
|
||||
Schema::field("title", Some(language.primary_language())),
|
||||
String::from("Title"),
|
||||
)],
|
||||
Class::Person => vec![
|
||||
(
|
||||
Schema::field("given_name", Some(language.primary_language())),
|
||||
String::from("Given Name"),
|
||||
),
|
||||
(
|
||||
Schema::field("surname", Some(language.primary_language())),
|
||||
String::from("Surname"),
|
||||
),
|
||||
],
|
||||
Class::CorporateBody => vec![(
|
||||
Schema::field("corporate_body", Some(language.primary_language())),
|
||||
String::from("Corporate Body"),
|
||||
)],
|
||||
Class::Expression => vec![(
|
||||
Schema::field("title", Some(language.primary_language())),
|
||||
String::from("Title"),
|
||||
)],
|
||||
Class::Manifestation => vec![(
|
||||
Schema::field("title", Some(language.primary_language())),
|
||||
String::from("Title"),
|
||||
)],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_url(&self) -> Option<Url> {
|
||||
match self {
|
||||
Class::Work => Some(Url::parse("http://fedora.quill.lan/rest/#Work").unwrap()),
|
||||
Class::Person => Some(Url::parse("http://fedora.quill.lan/rest/#Agent").unwrap()),
|
||||
Class::CorporateBody => {
|
||||
Some(Url::parse("http://fedora.quill.lan/rest/#Agent").unwrap())
|
||||
}
|
||||
Class::Expression => {
|
||||
Some(Url::parse("http://fedora.quill.lan/rest/#Expression").unwrap())
|
||||
}
|
||||
Class::Manifestation => {
|
||||
Some(Url::parse("http://fedora.quill.lan/rest/#Manifestation").unwrap())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn template(&self, subject: NamedNode) -> Graph {
|
||||
let subject = subject.as_ref();
|
||||
let empty_english_string_literal =
|
||||
LiteralRef::new_language_tagged_literal_unchecked("", "en");
|
||||
let empty_string_literal = LiteralRef::new_simple_literal("");
|
||||
let empty_node = NamedNodeRef::new_unchecked("");
|
||||
let hash_node = NamedNodeRef::new_unchecked("#");
|
||||
|
||||
match self {
|
||||
Class::RdfProperty => Graph::new(),
|
||||
Class::RdfsClass => Graph::new(),
|
||||
Class::SkosConcept => Graph::new(),
|
||||
Class::Work => Graph::from_iter([
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdawd::TITLE_OF_WORK,
|
||||
empty_english_string_literal,
|
||||
),
|
||||
Triple::new(subject, vocab::rdawo::IDENTIFIER_FOR_WORK, empty_node),
|
||||
Triple::new(subject, vocab::rdawo::EXPRESSION_OF_WORK, empty_node),
|
||||
]),
|
||||
Class::Person => Graph::from_iter([
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdaad::GIVEN_NAME,
|
||||
empty_english_string_literal,
|
||||
),
|
||||
Triple::new(subject, vocab::rdaad::SURNAME, empty_english_string_literal),
|
||||
Triple::new(subject, vocab::rdaao::IDENTIFIER_FOR_PERSON, hash_node),
|
||||
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
||||
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
||||
]),
|
||||
Class::CorporateBody => Graph::from_iter([
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdaao::IDENTIFIER_FOR_CORPORATE_BODY,
|
||||
hash_node,
|
||||
),
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdaad::NAME_OF_CORPORATE_BODY,
|
||||
empty_english_string_literal,
|
||||
),
|
||||
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
||||
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
||||
]),
|
||||
Class::Expression => Graph::from_iter([
|
||||
Triple::new(subject, vocab::rdaeo::WORK_EXPRESSED, empty_node),
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdaeo::LANGUAGE_OF_EXPRESSION,
|
||||
vocab::lclang::ENGLISH,
|
||||
),
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdaeo::TITLE_OF_EXPRESSION,
|
||||
empty_english_string_literal,
|
||||
),
|
||||
Triple::new(subject, vocab::rdaeo::CONTENT_TYPE, empty_node),
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdaeo::MANIFESTATION_OF_EXPRESSION,
|
||||
empty_node,
|
||||
),
|
||||
]),
|
||||
Class::Manifestation => Graph::from_iter([
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdamd::TITLE_OF_MANIFESTATION,
|
||||
empty_english_string_literal,
|
||||
),
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdamd::UNIFORM_RESOURCE_LOCATOR,
|
||||
empty_string_literal,
|
||||
),
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdamo::CARRIER_TYPE,
|
||||
vocab::rdact::ONLINE_RESOURCE,
|
||||
),
|
||||
Triple::new(subject, vocab::rdamo::MEDIA_TYPE, empty_node),
|
||||
Triple::new(subject, vocab::rdamo::FILE_TYPE, empty_node),
|
||||
Triple::new(subject, vocab::rdamo::CATEGORY_OF_MANIFESTATION, empty_node),
|
||||
Triple::new(subject, vocab::rdamo::EXPRESSION_MANIFESTED, empty_node),
|
||||
Triple::new(
|
||||
subject,
|
||||
vocab::rdamo::IDENTIFIER_FOR_MANIFESTATION,
|
||||
hash_node,
|
||||
),
|
||||
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
||||
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
||||
]),
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
-14
@@ -1,6 +1,6 @@
|
||||
use oxigraph::model::{GraphNameRef, NamedNodeRef};
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::LazyLock;
|
||||
use url::Url;
|
||||
|
||||
const ONTOLOGY_PREFIX: &str = "https://graphofliberty.org/2026/04/ont/";
|
||||
|
||||
@@ -19,12 +19,16 @@ pub static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| {
|
||||
"http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#",
|
||||
),
|
||||
("prov", "http://www.w3.org/ns/prov#"),
|
||||
("locid", "http://id.loc.gov/vocabulary/identifiers/"),
|
||||
("loclang", "http://id.loc.gov/vocabulary/languages/"),
|
||||
("lcid", "http://id.loc.gov/vocabulary/identifiers/"),
|
||||
("lca", "http://id.loc.gov/authorities/"),
|
||||
("lcn", "http://id.loc.gov/authorities/names/"),
|
||||
("lclang", "http://id.loc.gov/vocabulary/languages/"),
|
||||
("viaf", "http://viaf.org/viaf/"),
|
||||
("premis", "http://www.loc.gov/premis/rdf/v1#"),
|
||||
("premis3", "http://www.loc.gov/premis/rdf/v3/"),
|
||||
("dcterms", "http://purl.org/dc/terms/"),
|
||||
("fedora", "http://fedora.info/definitions/v4/repository#"),
|
||||
("lrmer", "http://iflastandards.info/ns/lrm/lrmer/"),
|
||||
("rdaa", "http://rdaregistry.info/Elements/a/"),
|
||||
("rdac", "http://rdaregistry.info/Elements/c/"),
|
||||
("rdae", "http://rdaregistry.info/Elements/e/"),
|
||||
@@ -58,25 +62,35 @@ impl CurieHelper {
|
||||
Self { prefixes }
|
||||
}
|
||||
|
||||
pub fn abbreviate(&self, base: Option<&str>, iri: &str) -> Option<String> {
|
||||
if let Some(base) = base
|
||||
&& let Some(local_name) = iri.strip_prefix(base)
|
||||
{
|
||||
return Some(format!(":{local_name}"));
|
||||
}
|
||||
pub fn abbreviate(&self, base: Option<&Url>, iri: &str) -> Option<String> {
|
||||
let relative_iri = base.and_then(|base| {
|
||||
let iri = Url::parse(iri).ok()?;
|
||||
base.make_relative(&iri)
|
||||
});
|
||||
|
||||
for (name, base) in &self.prefixes {
|
||||
if let Some(local_name) = iri.strip_prefix(base) {
|
||||
if relative_iri.is_some() {
|
||||
relative_iri
|
||||
} else {
|
||||
for (name, prefix) in &self.prefixes {
|
||||
if let Some(local_name) = iri.strip_prefix(prefix) {
|
||||
return Some(format!("{name}:{local_name}"));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand(&self, base: Option<&str>, abbreviated_iri: &str) -> Option<String> {
|
||||
let (prefix, name) = abbreviated_iri.split_once(':')?;
|
||||
pub fn expand(&self, base: Option<&Url>, abbreviated_iri: &str) -> Option<String> {
|
||||
let absolute_iri = base
|
||||
.and_then(|base| {
|
||||
base.join(abbreviated_iri)
|
||||
.ok()
|
||||
.map(|absolute| absolute.as_str().to_string())
|
||||
})
|
||||
.unwrap_or_else(|| abbreviated_iri.to_string());
|
||||
|
||||
if prefix == ""
|
||||
absolute_iri.split_once(':').and_then(|(prefix, name)| {
|
||||
if prefix.is_empty()
|
||||
&& let Some(base) = base
|
||||
{
|
||||
Some(format!("{base}{name}"))
|
||||
@@ -85,5 +99,6 @@ impl CurieHelper {
|
||||
.get(prefix)
|
||||
.map(|base| format!("{base}{name}"))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ pub type Result<R> = std::result::Result<R, Error>;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
IriParse(#[from] oxigraph::model::IriParseError),
|
||||
|
||||
@@ -16,6 +19,18 @@ pub enum Error {
|
||||
#[error(transparent)]
|
||||
QueryEvaluation(#[from] oxigraph::sparql::QueryEvaluationError),
|
||||
|
||||
#[error(transparent)]
|
||||
QueryResultsSyntax(#[from] oxigraph::sparql::results::QueryResultsSyntaxError),
|
||||
|
||||
#[error(transparent)]
|
||||
UpdateEvaluation(#[from] oxigraph::sparql::UpdateEvaluationError),
|
||||
|
||||
#[error(transparent)]
|
||||
TonicTransport(#[from] gl_inference::tonic::transport::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
TonicStatus(#[from] gl_inference::tonic::Status),
|
||||
|
||||
#[error("Ontology client is not connected")]
|
||||
NotConnected,
|
||||
}
|
||||
|
||||
+2
-10
@@ -1,6 +1,6 @@
|
||||
use oxigraph::model::{NamedNode, NamedNodeRef, Term, TermRef};
|
||||
use oxigraph::model::vocab::xsd;
|
||||
use crate::vocab::rdf;
|
||||
use oxigraph::model::vocab::xsd;
|
||||
use oxigraph::model::{NamedNode, Term, TermRef};
|
||||
|
||||
pub(crate) fn term_to_named_node(term: &Term) -> Option<&NamedNode> {
|
||||
if let Term::NamedNode(node) = term {
|
||||
@@ -10,14 +10,6 @@ pub(crate) fn term_to_named_node(term: &Term) -> Option<&NamedNode> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn term_ref_as_named_node(term: TermRef<'_>) -> Option<NamedNodeRef<'_>> {
|
||||
if let TermRef::NamedNode(node) = term {
|
||||
Some(node)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn term_as_str(term: &Term) -> Option<&str> {
|
||||
if let Term::Literal(literal) = term {
|
||||
match literal.datatype() {
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use oxigraph::model::NamedNode;
|
||||
use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsParser, SliceQueryResultsParserOutput};
|
||||
use gl_inference::tonic::transport::Channel;
|
||||
use gl_inference::proto::ontology_client::OntologyClient;
|
||||
use gl_inference::proto::OntologyQueryRequest;
|
||||
use gl_search::{Field, OwnedValue, Schema};
|
||||
use crate::class::Class;
|
||||
use crate::{curie, CurieHelper};
|
||||
use crate::helpers::{term_as_str, term_to_named_node};
|
||||
use crate::language::LanguageCondition;
|
||||
|
||||
pub async fn index_ontology(
|
||||
client: &mut OntologyClient<Channel>,
|
||||
language: &LanguageCondition,
|
||||
) -> crate::Result<Vec<HashMap<Field, OwnedValue>>> {
|
||||
let curie_helper = CurieHelper::new((&*curie::PREFIXES).clone());
|
||||
|
||||
let label_filter = language.to_filter_expression("label");
|
||||
let description_filter = language.to_filter_expression("description");
|
||||
|
||||
let mut request = OntologyQueryRequest::default();
|
||||
request.sparql_query = Some(format!(r#"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
||||
|
||||
SELECT ?class ?subject ?label ?description WHERE {{
|
||||
VALUES ?class {{ rdf:Property rdfs:Class skos:Concept }}
|
||||
?subject a ?class ;
|
||||
rdfs:label ?label .
|
||||
{label_filter}
|
||||
|
||||
OPTIONAL {{ ?subject rdfs:comment ?comment }}
|
||||
OPTIONAL {{ ?subject skos:definition ?definition }}
|
||||
BIND(COALESCE(?definition, ?comment) AS ?description)
|
||||
{description_filter}
|
||||
}}"#));
|
||||
|
||||
let response = client.query(request).await.unwrap();
|
||||
let parser_output = QueryResultsParser::from_format(QueryResultsFormat::Json)
|
||||
.for_slice(&response.get_ref().results)
|
||||
.unwrap();
|
||||
|
||||
let mut results = Vec::new();
|
||||
if let SliceQueryResultsParserOutput::Solutions(solutions) = parser_output {
|
||||
let primary_language = language.primary_language();
|
||||
let label_field = Schema::field("label", primary_language);
|
||||
let definition_field = Schema::field("definition", primary_language);
|
||||
for solution in solutions.filter_map(Result::ok) {
|
||||
let mut document = HashMap::with_capacity(4);
|
||||
|
||||
let discriminant = solution
|
||||
.get("class")
|
||||
.and_then(term_to_named_node)
|
||||
.and_then(Class::try_from_named_node)
|
||||
.map(|doc_type| doc_type as u64)
|
||||
.map(OwnedValue::U64)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(Schema::discriminant_field(), discriminant);
|
||||
|
||||
let subject_str = solution
|
||||
.get("subject")
|
||||
.and_then(term_to_named_node)
|
||||
.map(NamedNode::as_str);
|
||||
|
||||
let curie = subject_str
|
||||
.and_then(|subject| curie_helper.abbreviate(None, subject))
|
||||
.map(OwnedValue::Str)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(Schema::curie_field(), curie);
|
||||
|
||||
let subject = subject_str
|
||||
.map(OwnedValue::from)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(Schema::iri_field(), subject);
|
||||
|
||||
let label = solution
|
||||
.get("label")
|
||||
.and_then(term_as_str)
|
||||
.map(OwnedValue::from)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(label_field, label);
|
||||
|
||||
let definition = solution
|
||||
.get("description")
|
||||
.and_then(term_as_str)
|
||||
.map(OwnedValue::from)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(definition_field, definition);
|
||||
|
||||
results.push(document);
|
||||
}
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
use crate::class::Class;
|
||||
use crate::language::LanguageCondition;
|
||||
use crate::ontology::ResourceDescription;
|
||||
use crate::{CurieHelper, helpers, vocab};
|
||||
use gl_search::{Field, OwnedValue, Schema};
|
||||
use oxigraph::model::{Graph, NamedNode, NamedNodeRef, NamedOrBlankNodeRef, TermRef};
|
||||
use rayon::iter::IntoParallelRefIterator;
|
||||
use rayon::iter::ParallelIterator;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub struct Indexer<'a> {
|
||||
language: LanguageCondition,
|
||||
curie_helper: &'a CurieHelper,
|
||||
}
|
||||
|
||||
impl<'a> Indexer<'a> {
|
||||
pub fn new(language: LanguageCondition, curie_helper: &'a CurieHelper) -> Self {
|
||||
Self {
|
||||
language,
|
||||
curie_helper,
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_string(
|
||||
&self,
|
||||
graph: &Graph,
|
||||
subject: NamedNodeRef,
|
||||
predicate: NamedNodeRef,
|
||||
) -> OwnedValue {
|
||||
graph
|
||||
.object_for_subject_predicate(subject, predicate)
|
||||
.filter(|term| self.language.primary_matches_term(*term))
|
||||
.and_then(helpers::term_ref_as_str)
|
||||
.map(String::from)
|
||||
.map(OwnedValue::Str)
|
||||
.unwrap_or_else(|| OwnedValue::Null)
|
||||
}
|
||||
|
||||
fn person(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||
HashMap::from_iter([
|
||||
(
|
||||
Schema::field("given_name", self.language.primary_language()),
|
||||
self.extract_string(graph, subject, vocab::rdaad::GIVEN_NAME),
|
||||
),
|
||||
(
|
||||
Schema::field("surname", self.language.primary_language()),
|
||||
self.extract_string(graph, subject, vocab::rdaad::SURNAME),
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
fn corporate_body(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||
HashMap::from_iter([(
|
||||
Schema::field("corporate_name", self.language.primary_language()),
|
||||
self.extract_string(graph, subject, vocab::rdaad::NAME_OF_CORPORATE_BODY),
|
||||
)])
|
||||
}
|
||||
|
||||
fn work(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||
HashMap::from_iter([(
|
||||
Schema::field("title", self.language.primary_language()),
|
||||
self.extract_string(graph, subject, vocab::rdawd::TITLE_OF_WORK),
|
||||
)])
|
||||
}
|
||||
|
||||
fn expression(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||
HashMap::from_iter([(
|
||||
Schema::field("title", self.language.primary_language()),
|
||||
self.extract_string(graph, subject, vocab::rdaed::TITLE_OF_EXPRESSION),
|
||||
)])
|
||||
}
|
||||
|
||||
fn manifestation(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||
HashMap::from_iter([(
|
||||
Schema::field("title", self.language.primary_language()),
|
||||
self.extract_string(graph, subject, vocab::rdamd::TITLE_OF_MANIFESTATION),
|
||||
)])
|
||||
}
|
||||
|
||||
pub fn graph(&self, graph: &Graph) -> Vec<HashMap<Field, OwnedValue>> {
|
||||
let mut entities_and_types = HashSet::new();
|
||||
let triples = graph.triples_for_predicate(vocab::rdf::TYPE);
|
||||
for triple in triples {
|
||||
if let NamedOrBlankNodeRef::NamedNode(subject) = triple.subject
|
||||
&& let TermRef::NamedNode(class) = triple.object
|
||||
{
|
||||
entities_and_types.insert((subject, class));
|
||||
}
|
||||
}
|
||||
|
||||
entities_and_types
|
||||
.par_iter()
|
||||
.filter_map(|(subject, class)| {
|
||||
Class::try_from_named_node(*class).and_then(|class| {
|
||||
match class {
|
||||
Class::RdfProperty => None,
|
||||
Class::RdfsClass => None,
|
||||
Class::SkosConcept => None,
|
||||
Class::Work => Some(self.work(graph, *subject)),
|
||||
Class::Person => Some(self.person(graph, *subject)),
|
||||
Class::CorporateBody => Some(self.corporate_body(graph, *subject)),
|
||||
Class::Expression => Some(self.expression(graph, *subject)),
|
||||
Class::Manifestation => Some(self.manifestation(graph, *subject)),
|
||||
}
|
||||
.map(|mut document| {
|
||||
document
|
||||
.insert(Schema::discriminant_field(), OwnedValue::from(class as u64));
|
||||
document.insert(
|
||||
Schema::iri_field(),
|
||||
OwnedValue::Str(subject.as_str().to_string()),
|
||||
);
|
||||
|
||||
let curie = self
|
||||
.curie_helper
|
||||
.abbreviate(None, subject.as_str())
|
||||
.map(OwnedValue::Str)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(Schema::curie_field(), curie);
|
||||
|
||||
document
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn ontology(
|
||||
&self,
|
||||
entities: HashMap<NamedNode, ResourceDescription>,
|
||||
) -> Vec<HashMap<Field, OwnedValue>> {
|
||||
let label_field = Schema::field("label", self.language.primary_language());
|
||||
let definition_field = Schema::field("definition", self.language.primary_language());
|
||||
|
||||
entities
|
||||
.iter()
|
||||
.map(|(subject, description)| {
|
||||
let mut document = HashMap::with_capacity(4);
|
||||
|
||||
let discriminant = description
|
||||
.class
|
||||
.as_ref()
|
||||
.and_then(|node| Class::try_from_named_node(node.as_ref()))
|
||||
.map(|doc_type| doc_type as u64)
|
||||
.map(OwnedValue::U64)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(Schema::discriminant_field(), discriminant);
|
||||
|
||||
let curie = self
|
||||
.curie_helper
|
||||
.abbreviate(None, subject.as_str())
|
||||
.map(OwnedValue::Str)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(Schema::curie_field(), curie);
|
||||
|
||||
let subject = OwnedValue::from(subject.as_str());
|
||||
document.insert(Schema::iri_field(), subject);
|
||||
|
||||
let label = description
|
||||
.label
|
||||
.clone()
|
||||
.map(OwnedValue::from)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(label_field, label);
|
||||
|
||||
let definition = description
|
||||
.description
|
||||
.clone()
|
||||
.map(OwnedValue::from)
|
||||
.unwrap_or(OwnedValue::Null);
|
||||
document.insert(definition_field, definition);
|
||||
|
||||
document
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
+43
-15
@@ -1,15 +1,16 @@
|
||||
use oxigraph::model::TermRef;
|
||||
use oxigraph::model::{Literal, TermRef};
|
||||
use oxilangtag::LanguageTag;
|
||||
use spargebra::algebra::{Expression, Function, GraphPattern};
|
||||
use spargebra::term::Variable;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub const ENGLISH_PRIMARY: &str = "en";
|
||||
pub static ENGLISH_TAG: LazyLock<LanguageTag<String>> =
|
||||
LazyLock::new(|| LanguageTag::parse("en".to_string()).unwrap());
|
||||
|
||||
pub static ENGLISH_OR_UNTAGGED: LazyLock<LanguageCondition> = LazyLock::new(|| {
|
||||
LanguageCondition::ExactMatchOrUntagged(
|
||||
LanguageTag::parse(ENGLISH_PRIMARY.to_string()).unwrap(),
|
||||
)
|
||||
});
|
||||
pub static ENGLISH_OR_UNTAGGED: LazyLock<LanguageCondition> =
|
||||
LazyLock::new(|| LanguageCondition::ExactMatchOrUntagged(ENGLISH_TAG.clone()));
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum LanguageCondition {
|
||||
ExactMatchOnly(LanguageTag<String>),
|
||||
ExactMatchOrUntagged(LanguageTag<String>),
|
||||
@@ -48,16 +49,43 @@ impl LanguageCondition {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_filter_expression(&self, var: &str) -> String {
|
||||
pub fn filter(&self, variable: impl Into<String>) -> String {
|
||||
let variable = variable.into();
|
||||
|
||||
let exact = |language: &LanguageTag<String>| {
|
||||
Expression::FunctionCall(
|
||||
Function::LangMatches,
|
||||
vec![
|
||||
Expression::FunctionCall(
|
||||
Function::Lang,
|
||||
vec![Expression::Variable(Variable::new_unchecked(&variable))],
|
||||
),
|
||||
Expression::Literal(Literal::new_simple_literal(language.to_string())),
|
||||
],
|
||||
)
|
||||
};
|
||||
|
||||
let untagged = Expression::Not(Box::new(Expression::FunctionCall(
|
||||
Function::HasLang,
|
||||
vec![Expression::Variable(Variable::new_unchecked(&variable))],
|
||||
)));
|
||||
|
||||
match self {
|
||||
LanguageCondition::ExactMatchOnly(language) => {
|
||||
format!(r#"FILTER(langMATCHES(LANG(?{var}), "{language}"))"#)
|
||||
Self::ExactMatchOnly(language) => Some(exact(language)),
|
||||
Self::ExactMatchOrUntagged(language) => Some(Expression::Or(
|
||||
Box::new(exact(language)),
|
||||
Box::new(untagged),
|
||||
)),
|
||||
Self::UntaggedOnly => Some(untagged),
|
||||
Self::AnyOrNone => None,
|
||||
}
|
||||
LanguageCondition::ExactMatchOrUntagged(language) => {
|
||||
format!(r#"FILTER(langMATCHES(LANG(?{var}), "{language}") || !hasLANG(?{var}))"#)
|
||||
}
|
||||
LanguageCondition::UntaggedOnly => format!("FILTER(!hasLANG(?{var}))"),
|
||||
LanguageCondition::AnyOrNone => "".to_string(),
|
||||
.map(|expr| {
|
||||
GraphPattern::Filter {
|
||||
expr,
|
||||
inner: Box::new(GraphPattern::Bgp { patterns: vec![] }),
|
||||
}
|
||||
.to_string()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,13 +1,13 @@
|
||||
mod curie;
|
||||
//mod materialize;
|
||||
mod error;
|
||||
|
||||
pub mod vocab;
|
||||
pub mod class;
|
||||
pub mod category;
|
||||
pub mod language;
|
||||
pub mod class;
|
||||
mod helpers;
|
||||
pub mod index;
|
||||
pub mod indexer;
|
||||
pub mod language;
|
||||
pub mod ontology;
|
||||
pub mod vocab;
|
||||
|
||||
pub use curie::{CurieHelper, PREFIXES};
|
||||
pub use error::{Error, Result};
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
use crate::helpers::{term_as_str, term_to_named_node};
|
||||
use crate::language::LanguageCondition;
|
||||
use crate::vocab;
|
||||
use gl_inference::proto::OntologyQueryRequest;
|
||||
use gl_inference::proto::ontology_client::OntologyClient;
|
||||
use gl_inference::tonic::transport::{Channel, Endpoint};
|
||||
use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
|
||||
use oxigraph::model::{Graph, NamedNode, Triple};
|
||||
use oxigraph::sparql::results::{
|
||||
QueryResultsFormat, QueryResultsParser, SliceQueryResultsParserOutput,
|
||||
};
|
||||
use spargebra::algebra::GraphPattern;
|
||||
use spargebra::term::{GroundTerm, NamedNodePattern, TermPattern, TriplePattern, Variable};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Debug;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ResourceDescription {
|
||||
pub label: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub class: Option<NamedNode>,
|
||||
}
|
||||
|
||||
pub enum ResourceSelector {
|
||||
Classes,
|
||||
Subjects,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum ReadOnlyEntity {
|
||||
Property(NamedNode),
|
||||
Class(NamedNode),
|
||||
}
|
||||
|
||||
pub struct OntologyBuilder {
|
||||
endpoint: Endpoint,
|
||||
language: LanguageCondition,
|
||||
}
|
||||
|
||||
impl OntologyBuilder {
|
||||
pub fn from_string(endpoint: &str, language: LanguageCondition) -> crate::Result<Self> {
|
||||
let endpoint = Endpoint::from_str(endpoint)?
|
||||
.connect_timeout(std::time::Duration::from_secs(10))
|
||||
.tcp_keepalive(Some(std::time::Duration::from_secs(30)))
|
||||
.http2_keep_alive_interval(std::time::Duration::from_secs(15))
|
||||
.keep_alive_timeout(std::time::Duration::from_secs(20))
|
||||
.keep_alive_while_idle(true);
|
||||
|
||||
Ok(Self { endpoint, language })
|
||||
}
|
||||
|
||||
pub async fn connect(self) -> crate::Result<ConnectedOntology> {
|
||||
let client = OntologyClient::connect(self.endpoint)
|
||||
.await?
|
||||
.max_decoding_message_size(1024 * 1024 * 1024);
|
||||
|
||||
Ok(ConnectedOntology {
|
||||
client,
|
||||
language: self.language,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConnectedOntology {
|
||||
client: OntologyClient<Channel>,
|
||||
language: LanguageCondition,
|
||||
}
|
||||
|
||||
impl Debug for ConnectedOntology {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("ontology")
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectedOntology {
|
||||
pub async fn run_inference(&mut self, graph: &Graph) -> crate::Result<Graph> {
|
||||
let mut output_buffer = Vec::new();
|
||||
let mut serializer =
|
||||
RdfSerializer::from_format(RdfFormat::Turtle).for_writer(output_buffer);
|
||||
for triple in graph {
|
||||
serializer.serialize_triple(triple)?;
|
||||
}
|
||||
output_buffer = serializer.finish()?;
|
||||
let turtle = String::from_utf8_lossy(&output_buffer).to_string();
|
||||
|
||||
let request = OntologyQueryRequest {
|
||||
turtle: Some(turtle),
|
||||
inferences_only: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let response = self.client.query(request).await?;
|
||||
Ok(RdfParser::from_format(RdfFormat::Turtle)
|
||||
.for_slice(&response.get_ref().results)
|
||||
.filter_map(Result::ok)
|
||||
.map(Triple::from)
|
||||
.collect::<Graph>())
|
||||
}
|
||||
|
||||
pub async fn list_read_only(&mut self) -> crate::Result<HashSet<ReadOnlyEntity>> {
|
||||
let sparql_query = r#"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
||||
PREFIX gl: <https://graphofliberty.org/2026/04/ont/>
|
||||
|
||||
SELECT ?subject ?class WHERE {
|
||||
VALUES ?class { rdf:Property rdfs:Class }
|
||||
?subject a ?class ;
|
||||
gl:readOnly "true"^^xsd:boolean .
|
||||
}"#
|
||||
.to_owned();
|
||||
|
||||
let request = OntologyQueryRequest {
|
||||
sparql_query: Some(sparql_query),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let response = self.client.query(request).await?;
|
||||
let parser_output = QueryResultsParser::from_format(QueryResultsFormat::Json)
|
||||
.for_slice(&response.get_ref().results)?;
|
||||
|
||||
let mut results = HashSet::new();
|
||||
if let SliceQueryResultsParserOutput::Solutions(solutions) = parser_output {
|
||||
for solution in solutions.filter_map(Result::ok) {
|
||||
let subject = solution
|
||||
.get("subject")
|
||||
.and_then(term_to_named_node)
|
||||
.cloned();
|
||||
|
||||
let class = solution.get("class").and_then(term_to_named_node).cloned();
|
||||
|
||||
if let Some(subject) = subject
|
||||
&& let Some(class) = class
|
||||
{
|
||||
let entry = match class.as_ref() {
|
||||
vocab::rdf::PROPERTY => ReadOnlyEntity::Property(subject),
|
||||
vocab::rdfs::CLASS => ReadOnlyEntity::Class(subject),
|
||||
_ => continue,
|
||||
};
|
||||
results.insert(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
fn selector_to_sparql_pattern(
|
||||
selector: ResourceSelector,
|
||||
nodes: impl IntoIterator<Item = NamedNode>,
|
||||
) -> String {
|
||||
let bindings = nodes
|
||||
.into_iter()
|
||||
.map(GroundTerm::NamedNode)
|
||||
.map(Some)
|
||||
.map(|item| vec![item])
|
||||
.collect();
|
||||
|
||||
let variable = match selector {
|
||||
ResourceSelector::Classes => Variable::new_unchecked("class"),
|
||||
ResourceSelector::Subjects => Variable::new_unchecked("subject"),
|
||||
};
|
||||
|
||||
let values_pattern = GraphPattern::Values {
|
||||
variables: vec![variable.clone()],
|
||||
bindings,
|
||||
};
|
||||
|
||||
let triple_pattern = match selector {
|
||||
ResourceSelector::Classes => vec![TriplePattern {
|
||||
subject: TermPattern::Variable(Variable::new_unchecked("subject")),
|
||||
predicate: NamedNodePattern::NamedNode(vocab::rdf::TYPE.into_owned()),
|
||||
object: TermPattern::Variable(variable),
|
||||
}],
|
||||
ResourceSelector::Subjects => vec![],
|
||||
};
|
||||
|
||||
let basic_pattern = GraphPattern::Bgp {
|
||||
patterns: triple_pattern,
|
||||
};
|
||||
|
||||
GraphPattern::Join {
|
||||
left: Box::new(basic_pattern),
|
||||
right: Box::new(values_pattern),
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub async fn resource_descriptions(
|
||||
&mut self,
|
||||
selector: ResourceSelector,
|
||||
nodes: impl IntoIterator<Item = NamedNode>,
|
||||
) -> crate::Result<HashMap<NamedNode, ResourceDescription>> {
|
||||
let pattern = Self::selector_to_sparql_pattern(selector, nodes);
|
||||
let label_filter = self.language.filter("label");
|
||||
let comment_filter = self.language.filter("comment");
|
||||
let definition_filter = self.language.filter("definition");
|
||||
|
||||
let sparql_query = format!(
|
||||
r#"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
||||
|
||||
SELECT ?subject ?label ?description ?class WHERE {{
|
||||
{pattern}
|
||||
OPTIONAL {{
|
||||
?subject rdfs:label ?label .
|
||||
{label_filter}
|
||||
}} OPTIONAL {{
|
||||
?subject rdfs:comment ?comment .
|
||||
{comment_filter}
|
||||
}} OPTIONAL {{
|
||||
?subject skos:definition ?definition .
|
||||
{definition_filter}
|
||||
}}
|
||||
BIND(COALESCE(?definition, ?comment) AS ?description)
|
||||
}}"#
|
||||
);
|
||||
|
||||
let request = OntologyQueryRequest {
|
||||
sparql_query: Some(sparql_query),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let response = self.client.query(request).await?;
|
||||
let parser_output = QueryResultsParser::from_format(QueryResultsFormat::Json)
|
||||
.for_slice(&response.get_ref().results)?;
|
||||
|
||||
let mut results = HashMap::new();
|
||||
if let SliceQueryResultsParserOutput::Solutions(solutions) = parser_output {
|
||||
for solution in solutions.filter_map(Result::ok) {
|
||||
let class = solution.get("class").and_then(term_to_named_node).cloned();
|
||||
|
||||
let subject = solution
|
||||
.get("subject")
|
||||
.and_then(term_to_named_node)
|
||||
.cloned();
|
||||
|
||||
if let Some(subject) = subject {
|
||||
let label = solution
|
||||
.get("label")
|
||||
.and_then(term_as_str)
|
||||
.map(String::from);
|
||||
|
||||
let description = solution
|
||||
.get("description")
|
||||
.and_then(term_as_str)
|
||||
.map(String::from);
|
||||
|
||||
results.insert(
|
||||
subject,
|
||||
ResourceDescription {
|
||||
label,
|
||||
description,
|
||||
class,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
}
|
||||
+120
-4
@@ -1,7 +1,7 @@
|
||||
pub use oxigraph::model::vocab::rdf;
|
||||
pub use oxigraph::model::vocab::rdfs;
|
||||
|
||||
pub mod gl {
|
||||
pub mod glo {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const AUDIO_BOOK: NamedNodeRef =
|
||||
@@ -9,13 +9,16 @@ pub mod gl {
|
||||
|
||||
pub const READ_ONLY: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/readOnly");
|
||||
|
||||
pub const NEXT_URL: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/nextUrl");
|
||||
}
|
||||
|
||||
pub mod skos {
|
||||
pub mod lclang {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const CONCEPT: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://www.w3.org/2004/02/skos/core#Concept");
|
||||
pub const ENGLISH: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://id.loc.gov/vocabulary/languages/eng");
|
||||
}
|
||||
|
||||
pub mod owl {
|
||||
@@ -44,6 +47,13 @@ pub mod rdac {
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/c/C10007");
|
||||
}
|
||||
|
||||
pub mod rdact {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const ONLINE_RESOURCE: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/termList/RDACarrierType/1018");
|
||||
}
|
||||
|
||||
pub mod rdaad {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
@@ -56,3 +66,109 @@ pub mod rdaad {
|
||||
pub const NAME_OF_CORPORATE_BODY: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/a/datatype/P50032");
|
||||
}
|
||||
|
||||
pub mod rdaao {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const IDENTIFIER_FOR_PERSON: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/a/object/P50094");
|
||||
|
||||
pub const IDENTIFIER_FOR_CORPORATE_BODY: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/a/object/P50006");
|
||||
}
|
||||
|
||||
pub mod rdawd {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const TITLE_OF_WORK: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/w/datatype/P10088");
|
||||
}
|
||||
|
||||
pub mod rdawo {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const IDENTIFIER_FOR_WORK: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/w/object/P10002");
|
||||
|
||||
pub const EXPRESSION_OF_WORK: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/w/object/P10078");
|
||||
}
|
||||
|
||||
pub mod rdaed {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const TITLE_OF_EXPRESSION: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/e/datatype/P20312");
|
||||
}
|
||||
|
||||
pub mod rdaeo {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const WORK_EXPRESSED: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/e/object/P20231");
|
||||
|
||||
pub const LANGUAGE_OF_EXPRESSION: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/e/object/P20006");
|
||||
|
||||
pub const TITLE_OF_EXPRESSION: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/e/datatype/P20312");
|
||||
|
||||
pub const CONTENT_TYPE: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/e/object/P20001");
|
||||
|
||||
pub const MANIFESTATION_OF_EXPRESSION: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/e/object/P20059");
|
||||
}
|
||||
|
||||
pub mod rdamd {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const TITLE_OF_MANIFESTATION: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/m/datatype/P30335");
|
||||
|
||||
pub const UNIFORM_RESOURCE_LOCATOR: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/m/datatype/P30154");
|
||||
}
|
||||
|
||||
pub mod rdamo {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const CARRIER_TYPE: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/m/object/P30001");
|
||||
|
||||
pub const MEDIA_TYPE: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/m/object/P30002");
|
||||
|
||||
pub const IDENTIFIER_FOR_MANIFESTATION: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/m/object/P30004");
|
||||
|
||||
pub const FILE_TYPE: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/m/object/P30018");
|
||||
|
||||
pub const CATEGORY_OF_MANIFESTATION: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/m/object/P30335");
|
||||
|
||||
pub const EXPRESSION_MANIFESTED: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/m/object/P30139");
|
||||
}
|
||||
|
||||
pub mod rdand {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const NOMEN_STRING: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/n/datatype/P80068");
|
||||
}
|
||||
|
||||
pub mod rdano {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const SCHEME_OF_NOMEN: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/n/object/P80069");
|
||||
}
|
||||
|
||||
pub mod skos {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const CONCEPT: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://www.w3.org/2004/02/skos/core#Concept");
|
||||
}
|
||||
|
||||
+28
-9
@@ -1,5 +1,5 @@
|
||||
use oxigraph::model::GraphNameRef;
|
||||
use oxigraph::sparql::{SparqlEvaluator};
|
||||
use oxigraph::sparql::SparqlEvaluator;
|
||||
use oxigraph::store::Store;
|
||||
use tracing::debug_span;
|
||||
|
||||
@@ -30,24 +30,43 @@ const DOMAIN_UPDATE: &str = r#"INSERT {
|
||||
?x ?p ?y .
|
||||
}"#;
|
||||
|
||||
fn run_update(query_name: &str, query: &str, store: &Store, graph_name: GraphNameRef<'_>) -> crate::error::Result<()> {
|
||||
fn run_update(
|
||||
query_name: &str,
|
||||
query: &str,
|
||||
store: &Store,
|
||||
graph_name: GraphNameRef<'_>,
|
||||
) -> crate::error::Result<()> {
|
||||
let _span = debug_span!("Update", name = query_name).entered();
|
||||
|
||||
SparqlEvaluator::new()
|
||||
.with_prefix("rdfs", RDF_SCHEMA_PREFIX)?
|
||||
.with_prefix("gl", GL_PREFIX)?
|
||||
.parse_update(&format!("WITH {graph_name} {query}"))?
|
||||
.on_store(store).execute()?;
|
||||
.on_store(store)
|
||||
.execute()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn infer(inferences: usize, store: &Store, graph_name: GraphNameRef<'_>) -> crate::error::Result<usize> {
|
||||
let old_count = store.quads_for_pattern(None, None, None, Some(graph_name)).count();
|
||||
run_update("rdfs:subPropertyOf", SUB_PROPERTY_OF_UPDATE, &store, graph_name)?;
|
||||
run_update("rdfs:subClassOf", SUB_CLASS_OF_UPDATE, &store, graph_name)?;
|
||||
run_update("rdfs:domain", DOMAIN_UPDATE, &store, graph_name)?;
|
||||
let new_count = store.quads_for_pattern(None, None, None, Some(graph_name)).count();
|
||||
pub(crate) fn infer(
|
||||
inferences: usize,
|
||||
store: &Store,
|
||||
graph_name: GraphNameRef<'_>,
|
||||
) -> crate::error::Result<usize> {
|
||||
let old_count = store
|
||||
.quads_for_pattern(None, None, None, Some(graph_name))
|
||||
.count();
|
||||
run_update(
|
||||
"rdfs:subPropertyOf",
|
||||
SUB_PROPERTY_OF_UPDATE,
|
||||
store,
|
||||
graph_name,
|
||||
)?;
|
||||
run_update("rdfs:subClassOf", SUB_CLASS_OF_UPDATE, store, graph_name)?;
|
||||
run_update("rdfs:domain", DOMAIN_UPDATE, store, graph_name)?;
|
||||
let new_count = store
|
||||
.quads_for_pattern(None, None, None, Some(graph_name))
|
||||
.count();
|
||||
|
||||
let new_inferences_total = inferences + (new_count - old_count);
|
||||
if new_count > old_count {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use crate::service::OntologyService;
|
||||
use gl_inference::proto::ontology_server::OntologyServer;
|
||||
use tonic::transport::Server;
|
||||
use tracing_subscriber::{fmt, EnvFilter};
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use gl_inference::proto::ontology_server::OntologyServer;
|
||||
use crate::service::OntologyService;
|
||||
use tracing_subscriber::{EnvFilter, fmt};
|
||||
|
||||
mod service;
|
||||
mod logic;
|
||||
mod error;
|
||||
mod logic;
|
||||
mod service;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> color_eyre::Result<()> {
|
||||
|
||||
+105
-38
@@ -1,13 +1,16 @@
|
||||
use gl_inference::proto::ontology_server::Ontology;
|
||||
use gl_inference::proto::{
|
||||
OntologyClearResponse, OntologyLoadRequest, OntologyLoadResponse, OntologyQueryRequest,
|
||||
OntologyQueryResponse,
|
||||
};
|
||||
use num_traits::ToPrimitive;
|
||||
use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
|
||||
use oxigraph::model::{BlankNode, Dataset, GraphName, GraphNameRef, NamedNode, NamedNodeRef};
|
||||
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
||||
use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsSerializer};
|
||||
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
||||
use oxigraph::store::Store;
|
||||
use tonic::{Request, Response, Status};
|
||||
use tracing::{debug_span, field};
|
||||
use gl_inference::proto::ontology_server::Ontology;
|
||||
use gl_inference::proto::{OntologyClearResponse, OntologyLoadRequest, OntologyLoadResponse, OntologyQueryRequest, OntologyQueryResponse};
|
||||
use tracing::{debug, debug_span, field};
|
||||
|
||||
const ONTOLOGY_GRAPH: GraphNameRef = GraphNameRef::NamedNode(NamedNodeRef::new_unchecked(
|
||||
"https://graphofliberty.org/ontology",
|
||||
@@ -27,79 +30,124 @@ impl OntologyService {
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl Ontology for OntologyService {
|
||||
async fn load(&self, request: Request<OntologyLoadRequest>) -> Result<Response<OntologyLoadResponse>, Status> {
|
||||
let span = debug_span!("Load Ontology", input_size = field::Empty, old_size = field::Empty, new_size = field::Empty).entered();
|
||||
async fn load(
|
||||
&self,
|
||||
request: Request<OntologyLoadRequest>,
|
||||
) -> Result<Response<OntologyLoadResponse>, Status> {
|
||||
let span = debug_span!(
|
||||
"Load Ontology",
|
||||
old_size = field::Empty,
|
||||
input_size = field::Empty,
|
||||
inferences = field::Empty,
|
||||
new_size = field::Empty
|
||||
)
|
||||
.entered();
|
||||
|
||||
let request = request.get_ref();
|
||||
let mut response = OntologyLoadResponse::default();
|
||||
|
||||
response.old_size = self.ontology.len()
|
||||
let old_size = self
|
||||
.ontology
|
||||
.len()
|
||||
.map_err(|err| Status::internal(err.to_string()))?
|
||||
.to_u64()
|
||||
.unwrap_or(u64::MAX);
|
||||
|
||||
let path = std::path::Path::new(&request.path);
|
||||
let store = Store::open_read_only(path).unwrap();
|
||||
response.input_size = store.len()
|
||||
let input_size = store
|
||||
.len()
|
||||
.map_err(|err| Status::internal(err.to_string()))?
|
||||
.to_u64()
|
||||
.unwrap_or(u64::MAX);
|
||||
|
||||
let quads = store.iter()
|
||||
.filter_map(Result::ok)
|
||||
.map(|mut quad| {
|
||||
let quads = store.iter().filter_map(Result::ok).map(|mut quad| {
|
||||
quad.graph_name = ONTOLOGY_GRAPH.into_owned();
|
||||
quad
|
||||
});
|
||||
self.ontology.extend(quads).unwrap();
|
||||
|
||||
response.new_size = self.ontology.len()
|
||||
let inferences = if request.infer {
|
||||
crate::logic::infer(0, &self.ontology, ONTOLOGY_GRAPH)
|
||||
.map_err(|err| Status::internal(err.to_string()))?
|
||||
.to_u64()
|
||||
.unwrap_or(u64::MAX)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let new_size = self
|
||||
.ontology
|
||||
.len()
|
||||
.map_err(|err| Status::internal(err.to_string()))?
|
||||
.to_u64()
|
||||
.unwrap_or(u64::MAX);
|
||||
|
||||
span.record("input_size", response.input_size);
|
||||
let response = OntologyLoadResponse {
|
||||
old_size,
|
||||
input_size,
|
||||
inferences,
|
||||
new_size,
|
||||
};
|
||||
|
||||
span.record("old_size", response.old_size);
|
||||
span.record("input_size", response.input_size);
|
||||
span.record("inferences", response.inferences);
|
||||
span.record("new_size", response.new_size);
|
||||
|
||||
Ok(Response::new(response))
|
||||
}
|
||||
|
||||
async fn clear(&self, _request: Request<()>) -> Result<Response<OntologyClearResponse>, Status> {
|
||||
async fn clear(
|
||||
&self,
|
||||
_request: Request<()>,
|
||||
) -> Result<Response<OntologyClearResponse>, Status> {
|
||||
let span = debug_span!("Clear Ontology", size = field::Empty).entered();
|
||||
|
||||
let mut response = OntologyClearResponse::default();
|
||||
response.size = self.ontology.len()
|
||||
let size = self
|
||||
.ontology
|
||||
.len()
|
||||
.map_err(|err| Status::internal(err.to_string()))?
|
||||
.to_u64()
|
||||
.unwrap_or(u64::MAX);
|
||||
|
||||
self.ontology.clear()
|
||||
self.ontology
|
||||
.clear()
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
|
||||
let response = OntologyClearResponse { size };
|
||||
|
||||
span.record("size", response.size);
|
||||
|
||||
Ok(Response::new(response))
|
||||
}
|
||||
|
||||
async fn query(&self, request: Request<OntologyQueryRequest>) -> Result<Response<OntologyQueryResponse>, Status> {
|
||||
async fn query(
|
||||
&self,
|
||||
request: Request<OntologyQueryRequest>,
|
||||
) -> Result<Response<OntologyQueryResponse>, Status> {
|
||||
let span = debug_span!("Query", inferences = field::Empty).entered();
|
||||
|
||||
let request = request.get_ref();
|
||||
let mut response = OntologyQueryResponse::default();
|
||||
|
||||
let provided_dataset;
|
||||
let graph_name = if let Some(turtle) = &request.turtle {
|
||||
let random_graph_identifier = BlankNode::default();
|
||||
let graph_name = GraphName::NamedNode(NamedNode::new_unchecked(format!("https://graphofliberty.org/inference/{}", random_graph_identifier.as_str())));
|
||||
let dataset = RdfParser::from_format(RdfFormat::Turtle)
|
||||
let graph_name = GraphName::NamedNode(NamedNode::new_unchecked(format!(
|
||||
"https://graphofliberty.org/inference/{}",
|
||||
random_graph_identifier.as_str()
|
||||
)));
|
||||
provided_dataset = RdfParser::from_format(RdfFormat::Turtle)
|
||||
.for_slice(&turtle)
|
||||
.filter_map(Result::ok)
|
||||
.map(|mut quad| {
|
||||
quad.graph_name = graph_name.clone();
|
||||
quad
|
||||
}).collect::<Dataset>();
|
||||
})
|
||||
.collect::<Dataset>();
|
||||
|
||||
self.ontology.extend(&dataset)
|
||||
self.ontology
|
||||
.extend(&provided_dataset)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
|
||||
let inferences = crate::logic::infer(0, &self.ontology, graph_name.as_ref())
|
||||
@@ -107,41 +155,52 @@ impl Ontology for OntologyService {
|
||||
span.record("inferences", inferences);
|
||||
graph_name
|
||||
} else {
|
||||
provided_dataset = Dataset::new();
|
||||
ONTOLOGY_GRAPH.into_owned()
|
||||
};
|
||||
|
||||
let mut output_buffer = Vec::new();
|
||||
if let Some(sparql_query) = &request.sparql_query {
|
||||
debug!("SPARQL Query: {sparql_query}");
|
||||
|
||||
let mut evaluator = SparqlEvaluator::new();
|
||||
for (name, iri) in &request.prefixes {
|
||||
evaluator = evaluator.with_prefix(name, iri)
|
||||
evaluator = evaluator
|
||||
.with_prefix(name, iri)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
if let Some(base) = &request.base {
|
||||
evaluator = evaluator.with_base_iri(base)
|
||||
evaluator = evaluator
|
||||
.with_base_iri(base)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
let mut query = evaluator.parse_query(sparql_query)
|
||||
let mut query = evaluator
|
||||
.parse_query(sparql_query)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
|
||||
query.dataset_mut().set_default_graph(vec![graph_name.clone()]);
|
||||
query
|
||||
.dataset_mut()
|
||||
.set_default_graph(vec![graph_name.clone()]);
|
||||
|
||||
let results = query.on_store(&self.ontology)
|
||||
let results = query
|
||||
.on_store(&self.ontology)
|
||||
.execute()
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
|
||||
match results {
|
||||
QueryResults::Boolean(result) => {
|
||||
let serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Json);
|
||||
output_buffer = serializer.serialize_boolean_to_writer(output_buffer, result)
|
||||
output_buffer = serializer
|
||||
.serialize_boolean_to_writer(output_buffer, result)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
QueryResults::Solutions(solutions) => {
|
||||
let serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Json);
|
||||
let variables = Vec::from_iter(solutions.variables().iter().cloned());
|
||||
let mut writer = serializer.serialize_solutions_to_writer(output_buffer, variables)?;
|
||||
let mut writer =
|
||||
serializer.serialize_solutions_to_writer(output_buffer, variables)?;
|
||||
for solution in solutions.filter_map(Result::ok) {
|
||||
writer.serialize(&solution)?;
|
||||
}
|
||||
@@ -150,11 +209,13 @@ impl Ontology for OntologyService {
|
||||
QueryResults::Graph(graph) => {
|
||||
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle);
|
||||
for (name, iri) in &request.prefixes {
|
||||
serializer = serializer.with_prefix(name, iri)
|
||||
serializer = serializer
|
||||
.with_prefix(name, iri)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
if let Some(base) = &request.base {
|
||||
serializer = serializer.with_base_iri(base)
|
||||
serializer = serializer
|
||||
.with_base_iri(base)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
@@ -168,20 +229,25 @@ impl Ontology for OntologyService {
|
||||
} else {
|
||||
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle);
|
||||
for (name, iri) in &request.prefixes {
|
||||
serializer = serializer.with_prefix(name, iri)
|
||||
serializer = serializer
|
||||
.with_prefix(name, iri)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
if let Some(base) = &request.base {
|
||||
serializer = serializer.with_base_iri(base)
|
||||
serializer = serializer
|
||||
.with_base_iri(base)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
let mut serializer = serializer.for_writer(output_buffer);
|
||||
let graph = self.ontology
|
||||
let resulting_dataset = self
|
||||
.ontology
|
||||
.quads_for_pattern(None, None, None, Some(graph_name.as_ref()))
|
||||
.filter_map(Result::ok);
|
||||
for triple in graph {
|
||||
serializer.serialize_triple(triple.as_ref())?;
|
||||
for quad in resulting_dataset {
|
||||
if !(request.inferences_only && provided_dataset.contains(quad.as_ref())) {
|
||||
serializer.serialize_triple(quad.as_ref())?;
|
||||
}
|
||||
}
|
||||
output_buffer = serializer.finish()?;
|
||||
}
|
||||
@@ -189,7 +255,8 @@ impl Ontology for OntologyService {
|
||||
response.results = String::from_utf8_lossy(&output_buffer).to_string();
|
||||
|
||||
if request.turtle.is_some() {
|
||||
self.ontology.clear_graph(graph_name.as_ref())
|
||||
self.ontology
|
||||
.clear_graph(graph_name.as_ref())
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f ldp.ttl -
|
||||
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f owl.ttl --graph http://www.w3.org/2002/07/owl
|
||||
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f skos.rdf --graph https://www.w3.org/TR/skos-reference/skos.rdf
|
||||
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f prov.ttl --graph http://www.w3.org/ns/prov
|
||||
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f premis-1-0-0.rdf --graph https://id.loc.gov/ontologies/premis-1-0-0.rdf
|
||||
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f premis-3-0-0.rdf --graph https://id.loc.gov/ontologies/premis-3-0-0.rdf
|
||||
|
||||
# https://github.com/RDARegistry/RDA-Vocabularies/archive/v5.4.13.tar.gz
|
||||
find Elements -type f -name '*.xml' -exec oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology --graph http://rdaregistry.info/Elements -f {} \;
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
@prefix premis3: <http://www.loc.gov/premis/rdf/v3/> .
|
||||
@base <https://graphofliberty.org/2026/04/ont/> .
|
||||
|
||||
<https://graphofliberty.org/2026/04/ont> rdf:type owl:Ontology .
|
||||
<https://graphofliberty.org/2026/04/ont> rdf:type owl:Ontology ;
|
||||
owl:imports <http://www.w3.org/2004/02/skos/core> .
|
||||
|
||||
#################################################################
|
||||
# Annotation properties
|
||||
@@ -94,6 +95,12 @@ xsd:unsignedShort rdf:type rdfs:Datatype ;
|
||||
rdfs:label "derived with"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/nextUrl
|
||||
:nextUrl rdf:type owl:ObjectProperty ;
|
||||
rdfs:comment "The next URL to use when creating a new document."@en ;
|
||||
rdfs:label "Next URL"@en .
|
||||
|
||||
|
||||
#################################################################
|
||||
# Data properties
|
||||
#################################################################
|
||||
@@ -110,6 +117,7 @@ xsd:unsignedShort rdf:type rdfs:Datatype ;
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/Category
|
||||
:Category rdf:type owl:Class ;
|
||||
rdfs:subClassOf skos:Concept ;
|
||||
rdfs:label "Category"@en .
|
||||
|
||||
|
||||
@@ -133,6 +141,11 @@ fedora:Container rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
|
||||
|
||||
### http://fedora.info/definitions/v4/repository#RepositoryRoot
|
||||
fedora:RepositoryRoot rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
|
||||
|
||||
### http://fedora.info/definitions/v4/repository#Resource
|
||||
fedora:Resource rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
@@ -158,6 +171,11 @@ fedora:hasParent rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
|
||||
|
||||
### http://fedora.info/definitions/v4/repository#hasTransactionProvider
|
||||
fedora:hasTransactionProvider rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
|
||||
|
||||
### http://fedora.info/definitions/v4/repository#lastModified
|
||||
fedora:lastModified rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
@@ -221,7 +239,7 @@ ldp:contains rdf:type owl:NamedIndividual ;
|
||||
### https://graphofliberty.org/2026/04/ont/AudioBook
|
||||
:AudioBook rdf:type owl:NamedIndividual ,
|
||||
:Category ;
|
||||
rdfs:label "Audio Book"@en .
|
||||
rdfs:label "audio book"@en .
|
||||
|
||||
|
||||
### Generated by the OWL API (version 4.5.29.2024-05-13T12:11:03Z) https://github.com/owlcs/owlapi
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,578 @@
|
||||
<rdf:RDF xml:base="http://www.loc.gov/premis/rdf/v3/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:bf="http://id.loc.gov/ontologies/bibframe/" xmlns:bflc="http://id.loc.gov/ontologies/bflc/" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:skos="http://www.w3.org/2004/02/skos/core#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cc="http://creativecommons.org/ns#" xmlns:foaf="http://xmlns.com/foaf/0.1/">
|
||||
<owl:Ontology rdf:about="">
|
||||
<rdfs:label xml:lang="en">PREMIS 3 Ontology</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Ontology for PREMIS 3, the international standard
|
||||
for metadata to support the preservation of digital objects and ensure their
|
||||
long-term usability.</rdfs:comment>
|
||||
<dcterms:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-10-12</dcterms:modified>
|
||||
<!-- Replaced long note and version variation mechanism with actual bonafide conclusion to version debate. -->
|
||||
<owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string">3.0.0</owl:versionInfo>
|
||||
<owl:versionIRI rdf:resource="https://id.loc.gov/ontologies/premis-3-0-0"/>
|
||||
<owl:priorVersion rdf:resource="https://id.loc.gov/ontologies/premis-1-0-0"/>
|
||||
<rdfs:seeAlso rdf:resource="http://www.loc.gov/standards/premis/"/>
|
||||
<rdfs:seeAlso rdf:resource="https://github.com/PREMIS-OWL-Revision-Team/revise-premis-owl/"/>
|
||||
<owl:imports rdf:resource="http://www.w3.org/ns/prov-o-20130430"/>
|
||||
</owl:Ontology>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Action" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Action</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Operation type to perform on an Object. Effectively performing this action may produce an Event.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/actionsGranted"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Agent" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Agent</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Actor (human, machine, or software) associated with one or more Event and/or Rights
|
||||
statement associated with a digital object.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.w3.org/ns/prov#Agent"/>
|
||||
<rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Agent"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Bitstream" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Bitstream</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Contiguous or non-contiguous data within a file that has meaningful properties for
|
||||
preservation purposes.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/IntellectualEntity"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Representation"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Copyright" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Copyright</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Copyright law.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/InstitutionalPolicy"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/License"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Statute"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/copyrightStatus"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Dependency" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Dependency</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Relationship where one Object requires another Object to support its function, delivery, or
|
||||
the coherence of its content.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/EnvironmentCharacteristic" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Environment characteristic</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">An assessment of the extent to which the described environment supports its
|
||||
purpose.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/environmentCharacteristic"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Event" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Event</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Action performed within or outside the repository that affects its capability to preserve Objects over the long term.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.w3.org/ns/prov#Activity"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/eventType"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/File" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">File</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Named and ordered sequence of bytes that is known to an operating system.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Bitstream"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/IntellectualEntity"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Representation"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Fixity" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Fixity</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Information used to verify whether an object has been altered in an undocumented or
|
||||
unauthorized way.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/cryptographicHashFunctions"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/HardwareAgent" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Hardware agent</rdfs:label>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/Agent"/>
|
||||
<owl:sameAs rdf:resource="http://id.loc.gov/vocabulary/preservation/agentType/har"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Organization"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Person"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/SoftwareAgent"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Identifier" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Identifier</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">An unambiguous reference to the PREMIS entity within the preservation
|
||||
repository.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Inhibitor" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Inhibitor</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Feature of a Digital Object intended to inhibit access, copying, dissemination, or
|
||||
migration. Common Inhibitors are encryption and password protection.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/inhibitorType"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/InstitutionalPolicy" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Institutional policy</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">A policy decision made by an organization.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Copyright"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/License"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Statute"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/IntellectualEntity" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Intellectual entity</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">A set of content that is considered a single intellectual unit for purposes of management and
|
||||
description: for example, a particular book, map, photograph, database, or piece of hardware or
|
||||
software. An Intellectual Entity can include other Intellectual Entities; for example, a web site can
|
||||
include a web page; a web page can include an image. An Intellectual Entity may have one or more digital
|
||||
representations. An Intellectual Entity may also describe an environment, defined as technology
|
||||
supporting a digital object in some way (e.g. by rendering or executing it). Environments can consist of
|
||||
software, hardware, or a combination of both.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Bitstream"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Representation"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/environmentFunctionType"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/License" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">License</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">A license agreement or other legal document that grants rights.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Copyright"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/InstitutionalPolicy"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Statute"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Object" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Object</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Discrete unit of information subject to digital preservation. Subclasses of Object are
|
||||
Intellectual Entity, Representation, File and Bitstream.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.w3.org/ns/prov#Entity"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Organization" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Organization</rdfs:label>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/Agent"/>
|
||||
<rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Organization"/>
|
||||
<rdfs:subClassOf rdf:resource="http://www.w3.org/ns/prov#Organization"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/HardwareAgent"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Person"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/SoftwareAgent"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/OutcomeStatus" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Outcome status</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Overall result of the Event in terms of success, partial success, or failure.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/eventOutcome"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Person" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Person</rdfs:label>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/Agent"/>
|
||||
<rdfs:subClassOf rdf:resource="http://www.w3.org/ns/prov#Person"/>
|
||||
<rdfs:subClassOf rdf:resource="http://xmlns.com/foaf/0.1/Person"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/HardwareAgent"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Organization"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/SoftwareAgent"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/PreservationPolicy" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Preservation policy</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Information indicating the decision or policy on the set of preservation functions to be
|
||||
applied to an object and the context in which the decision or policy was made. Note that in addition to
|
||||
subclasses declared at presLevType, SignificantProperties is also a subclass of PreservationPolicy.
|
||||
Implementers may also wish to create locally-defined subclasses.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://purl.org/dc/terms/Policy"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/preservationLevelRole"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Representation" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Representation</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Digital or physical Object instantiating or embodying an Intellectual Entity. A digital
|
||||
representation is the set of stored digital files and structural metadata needed to provide a complete
|
||||
and reasonable rendition of the Intellectual Entity. A physical representation is an item such as a
|
||||
manuscript, video cassette, or printed document.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Bitstream"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/IntellectualEntity"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/RightsBasis" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Rights basis</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Designation of the basis for the right or permission governing the Object.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/rightsBasis"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/RightsStatus" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Rights status</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Information about how a RightsBasis applies to a particular object.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Rule" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Rule</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Statement about the Actions an Agent is permitted to undertake or prohibited from
|
||||
undertaking with respect to an Object.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Signature" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Signature</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Mathematical technique used to validate the authenticity and integrity of a message,
|
||||
software or digital document.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/signatureMethod"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/SignatureEncoding" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Signature encoding</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Encoding used for the signature value and key information.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/signatureEncoding"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/SignificantProperties" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Significant properties</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Characteristics of a particular object subjectively determined to be important to maintain
|
||||
through preservation actions.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/PreservationPolicy"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/SoftwareAgent" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Software agent</rdfs:label>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/Agent"/>
|
||||
<rdfs:subClassOf rdf:resource="http://www.w3.org/ns/prov#SoftwareAgent"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/HardwareAgent"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Organization"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Person"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Statute" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Statute</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">A law that grants or revokes rights, such as laws governing privacy or orphan
|
||||
works.</rdfs:comment>
|
||||
<rdfs:subClassOf rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/Copyright"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/License"/>
|
||||
<owl:disjointWith rdf:resource="http://www.loc.gov/premis/rdf/v3/InstitutionalPolicy"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/StorageLocation" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Storage location</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Information needed to retrieve a physical item from its physical storage location or a file
|
||||
from the storage system, or to access a bitstream within a file.</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/contentLocationType"/>
|
||||
</owl:Class>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/StorageMedium" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">Storage medium</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">The physical medium on which the Object is stored (e.g., magnetic tape, hard disk, CD-ROM,
|
||||
DVD).</rdfs:comment>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/storageMedium"/>
|
||||
</owl:Class>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/act" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">act</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Rule"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Action"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/allows" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">allows</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Rule"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/governs" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">governs</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/basis" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has basis</rdfs:label>
|
||||
<rdfs:comment xml:lang="en">Links from a RightsStatus to the RightsBasis instance that supports or documents
|
||||
it.</rdfs:comment>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsStatus"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/characteristic" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has characteristic</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Dependency"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/EnvironmentCharacteristic"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/dependency" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has dependency</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Dependency"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/documentation" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has documentation</rdfs:label>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/encoding" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has encoding</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Signature"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/SignatureEncoding"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/fixity" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has fixity</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Bitstream"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Fixity"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/identifier" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has identifier</rdfs:label>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Identifier"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/jurisdiction" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has jurisdiction</rdfs:label>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Resource"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/medium" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has medium</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/StorageLocation"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/StorageMedium"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/outcome" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has outcome</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Event"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/OutcomeStatus"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/policy" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has policy</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/PreservationPolicy"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/preservationLevelRole"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/purpose" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has purpose</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Dependency"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Action"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/relationship" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has relationship</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Agent"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<rdfs:seeAlso rdf:resource="http://id.loc.gov/vocabulary/preservation/relationshipSubType"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/rightsStatus" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has rights status</rdfs:label>
|
||||
<rdfs:subPropertyOf rdf:resource="http://purl.org/dc/elements/1.1/rights"/>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Object"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsStatus"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/signature" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has signature</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Bitstream"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Signature"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/inhibitedBy" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">inhibited by</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Bitstream"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Inhibitor"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/inhibits" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">inhibits</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Inhibitor"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Action"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/prohibits" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">prohibits</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/Rule"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:ObjectProperty rdf:about="http://www.loc.gov/premis/rdf/v3/storedAt" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">stored at</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Bitstream"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Representation"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.loc.gov/premis/rdf/v3/StorageLocation"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:ObjectProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/endDate" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">end date</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/RightsStatus"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Rule"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:subPropertyOf rdf:resource="http://purl.org/dc/terms/date"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/citation" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has citation</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/compositionLevel" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has composition level</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#nonNegativeInteger"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/determinationDate" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has determination date</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsStatus"/>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#date"/>
|
||||
<rdfs:subPropertyOf rdf:resource="http://purl.org/dc/terms/date"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/key" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has key</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Inhibitor"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Signature"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/note" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has note</rdfs:label>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:subPropertyOf rdf:resource="http://purl.org/dc/terms/description"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/originalName" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has original name</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/IntellectualEntity"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Representation"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/outcomeNote" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has outcome note</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Event"/>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:subPropertyOf rdf:resource="http://www.loc.gov/premis/rdf/v3/note"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/rationale" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has rationale</rdfs:label>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:subPropertyOf rdf:resource="http://www.loc.gov/premis/rdf/v3/note"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/restriction" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has restriction</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Rule"/>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/size" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has size</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Bitstream"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/File"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#nonNegativeInteger"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
<skos:narrowMatch rdf:resource="http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#fileSize"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/terms" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has terms</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/RightsBasis"/>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:subPropertyOf rdf:resource="http://www.loc.gov/premis/rdf/v3/note"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/validationRules" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has validation rules</rdfs:label>
|
||||
<rdfs:domain rdf:resource="http://www.loc.gov/premis/rdf/v3/Signature"/>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:subPropertyOf rdf:resource="http://www.loc.gov/premis/rdf/v3/note"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/version" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">has version</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://purl.org/dc/terms/FileFormat"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/HardwareAgent"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/IntellectualEntity"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/SoftwareAgent"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:range rdf:resource="http://www.w3.org/2000/01/rdf-schema#Literal"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
<owl:DatatypeProperty rdf:about="http://www.loc.gov/premis/rdf/v3/startDate" xmlns="http://www.loc.gov/premis/rdf/v3/" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:prov="http://www.w3.org/ns/prov#">
|
||||
<rdfs:label xml:lang="en">start date</rdfs:label>
|
||||
<rdfs:domain>
|
||||
<owl:Class>
|
||||
<owl:unionOf rdf:parseType="Collection">
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/RightsStatus"/>
|
||||
<owl:Class rdf:about="http://www.loc.gov/premis/rdf/v3/Rule"/>
|
||||
</owl:unionOf>
|
||||
</owl:Class>
|
||||
</rdfs:domain>
|
||||
<rdfs:subPropertyOf rdf:resource="http://purl.org/dc/terms/date"/>
|
||||
<rdfs:isDefinedBy rdf:resource="http://www.loc.gov/premis/rdf/v3/"/>
|
||||
</owl:DatatypeProperty>
|
||||
</rdf:RDF>
|
||||
@@ -5,12 +5,14 @@ import "google/protobuf/empty.proto";
|
||||
|
||||
message OntologyLoadRequest {
|
||||
string path = 1;
|
||||
bool infer = 2;
|
||||
}
|
||||
|
||||
message OntologyLoadResponse {
|
||||
uint64 input_size = 1;
|
||||
uint64 old_size = 2;
|
||||
uint64 new_size = 3;
|
||||
uint64 old_size = 1;
|
||||
uint64 input_size = 2;
|
||||
uint64 inferences = 3;
|
||||
uint64 new_size = 4;
|
||||
}
|
||||
|
||||
message OntologyClearResponse {
|
||||
@@ -22,6 +24,7 @@ message OntologyQueryRequest {
|
||||
optional string sparql_query = 2;
|
||||
map<string, string> prefixes = 3;
|
||||
optional string base = 4;
|
||||
bool inferences_only = 5;
|
||||
}
|
||||
|
||||
message OntologyQueryResponse {
|
||||
|
||||
@@ -10,7 +10,6 @@ gl-search.workspace = true
|
||||
|
||||
clap.workspace = true
|
||||
color-eyre.workspace = true
|
||||
csv = "1.4"
|
||||
http.workspace = true
|
||||
iced.workspace = true
|
||||
ldp.workspace = true
|
||||
|
||||
+652
-330
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -7,10 +7,13 @@ pub(crate) struct QueryArgs {
|
||||
pub(crate) dataset_path: Option<PathBuf>,
|
||||
|
||||
#[arg(short, long, value_name = "QUERY PATH")]
|
||||
pub(crate) query_path: PathBuf,
|
||||
pub(crate) query_path: Option<PathBuf>,
|
||||
|
||||
#[arg(short, long, value_name = "BASE IRI")]
|
||||
pub(crate) base: Option<String>,
|
||||
|
||||
#[arg(short, long)]
|
||||
pub(crate) inferences_only: bool,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
@@ -18,6 +21,9 @@ pub(crate) struct SearchArgs {
|
||||
#[arg(short, long, value_name = "DOC TYPE")]
|
||||
pub(crate) discriminant: Option<u64>,
|
||||
|
||||
#[arg(short, long, value_name = "LIMIT")]
|
||||
pub(crate) limit: Option<usize>,
|
||||
|
||||
#[arg(value_name = "QUERY")]
|
||||
pub(crate) query: String,
|
||||
}
|
||||
|
||||
@@ -42,4 +42,16 @@ pub(crate) enum Error {
|
||||
|
||||
#[error(transparent)]
|
||||
TonicTransport(#[from] tonic::transport::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
TonicStatus(#[from] tonic::Status),
|
||||
|
||||
#[error(transparent)]
|
||||
Tantivy(#[from] gl_search::tantivy::TantivyError),
|
||||
|
||||
#[error(transparent)]
|
||||
Reqwest(#[from] ldp::reqwest::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
Ldp(#[from] ldp::Error),
|
||||
}
|
||||
+94
-53
@@ -3,33 +3,32 @@ mod args;
|
||||
mod error;
|
||||
mod navigator;
|
||||
mod rdf;
|
||||
mod tasks;
|
||||
mod theme;
|
||||
mod widget;
|
||||
mod windows;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use crate::app::Publisher;
|
||||
use crate::args::{AppArgs, Command};
|
||||
use clap::Parser;
|
||||
use gl_graph::indexer::Indexer;
|
||||
use gl_graph::ontology::{OntologyBuilder, ResourceSelector};
|
||||
use gl_graph::{CurieHelper, language, vocab};
|
||||
use gl_inference::proto::OntologyQueryRequest;
|
||||
use gl_inference::proto::ontology_client::OntologyClient;
|
||||
use gl_search::{Schema, SearchIndex};
|
||||
use iced::futures::StreamExt;
|
||||
use ldp::Traverse;
|
||||
use ldp::middleware::BasicAuthMiddleware;
|
||||
use ldp::reqwest::Client;
|
||||
use ldp::reqwest_middleware::ClientBuilder;
|
||||
use ldp::traverse::Traverse;
|
||||
use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
|
||||
use oxigraph::model::{Dataset, Graph, Triple, TripleRef};
|
||||
use tonic::Status;
|
||||
use tracing::{debug, debug_span, error, field, Instrument};
|
||||
use oxigraph::model::{Graph, TripleRef};
|
||||
use std::collections::HashMap;
|
||||
use tracing::{Instrument, debug_span, error, field};
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::{EnvFilter, fmt};
|
||||
use url::Url;
|
||||
use gl_graph::index::index_ontology;
|
||||
use gl_graph::language;
|
||||
use gl_inference::proto::ontology_client::OntologyClient;
|
||||
use gl_inference::proto::OntologyQueryRequest;
|
||||
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
let appender = tracing_appender::rolling::never("/tmp", "publisher-log");
|
||||
@@ -43,25 +42,32 @@ fn main() -> color_eyre::Result<()> {
|
||||
.init();
|
||||
color_eyre::install()?;
|
||||
|
||||
let mut index = SearchIndex::builder()
|
||||
.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index")
|
||||
.build()
|
||||
.expect("Failed to build search index");
|
||||
|
||||
let args = AppArgs::parse();
|
||||
match args.command {
|
||||
Some(Command::Query(args)) => {
|
||||
let raw_query = String::from_utf8(std::fs::read(&args.query_path)?)?;
|
||||
let raw_query = if let Some(query) = &args.query_path {
|
||||
Some(String::from_utf8(std::fs::read(query)?)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let graph = if let Some(dataset_path) = &args.dataset_path {
|
||||
Some(String::from_utf8(std::fs::read(dataset_path)?)?)
|
||||
} else { None };
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut request = OntologyQueryRequest::default();
|
||||
request.sparql_query = Some(raw_query);
|
||||
request.turtle = graph;
|
||||
request.prefixes = HashMap::from_iter(gl_graph::PREFIXES.iter().map(|(name, iri)| (name.clone(), iri.clone())));
|
||||
request.base = args.base.clone();
|
||||
let request = OntologyQueryRequest {
|
||||
sparql_query: raw_query,
|
||||
turtle: graph,
|
||||
prefixes: HashMap::from_iter(
|
||||
gl_graph::PREFIXES
|
||||
.iter()
|
||||
.map(|(name, iri)| (name.clone(), iri.clone())),
|
||||
),
|
||||
base: args.base.clone(),
|
||||
inferences_only: args.inferences_only,
|
||||
};
|
||||
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
@@ -69,17 +75,34 @@ fn main() -> color_eyre::Result<()> {
|
||||
.build()?;
|
||||
|
||||
runtime.block_on(async {
|
||||
let mut client = OntologyClient::connect("http://[::1]:3000").await.unwrap();
|
||||
let mut client = OntologyClient::connect("http://[::1]:3000")
|
||||
.await
|
||||
.unwrap()
|
||||
.max_decoding_message_size(1024 * 1024 * 1024);
|
||||
|
||||
let response = client.query(request).await.unwrap();
|
||||
println!("{}", response.get_ref().results);
|
||||
});
|
||||
}
|
||||
Some(Command::Search(args)) => {
|
||||
for document in index.query(args.discriminant, &args.query, Schema::all_fields(), 500000)? {
|
||||
let index = SearchIndex::builder()
|
||||
.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index")
|
||||
.build()
|
||||
.expect("Failed to build search index");
|
||||
|
||||
let limit = args.limit.unwrap_or(5);
|
||||
for document in
|
||||
index.query(args.discriminant, &args.query, Schema::all_fields(), limit)?
|
||||
{
|
||||
println!("{}", gl_search::to_json(document));
|
||||
}
|
||||
}
|
||||
Some(Command::Reindex) => {
|
||||
let mut index = SearchIndex::builder()
|
||||
.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index")
|
||||
.build()
|
||||
.expect("Failed to build search index");
|
||||
|
||||
let mut writer = index.writer()?;
|
||||
debug_span!("Clear Index").in_scope(|| {
|
||||
writer.delete_all_documents()?;
|
||||
@@ -92,8 +115,26 @@ fn main() -> color_eyre::Result<()> {
|
||||
.build()?;
|
||||
|
||||
runtime.block_on(async {
|
||||
let mut client = OntologyClient::connect("http://[::1]:3000").await?;
|
||||
let documents = index_ontology(&mut client, &language::ENGLISH_OR_UNTAGGED).await?;
|
||||
let curie_helper = CurieHelper::new(gl_graph::PREFIXES.clone());
|
||||
let indexer = Indexer::new(language::ENGLISH_OR_UNTAGGED.clone(), &curie_helper);
|
||||
|
||||
let mut client = OntologyBuilder::from_string(
|
||||
"http://[::1]:3000",
|
||||
language::ENGLISH_OR_UNTAGGED.clone(),
|
||||
)?
|
||||
.connect()
|
||||
.await?;
|
||||
let resource_descriptions = client
|
||||
.resource_descriptions(
|
||||
ResourceSelector::Classes,
|
||||
[
|
||||
vocab::rdf::PROPERTY.into_owned(),
|
||||
vocab::rdfs::CLASS.into_owned(),
|
||||
vocab::skos::CONCEPT.into_owned(),
|
||||
],
|
||||
)
|
||||
.await?;
|
||||
let documents = indexer.ontology(resource_descriptions);
|
||||
debug_span!("Index Ontology", documents = field::Empty).in_scope(|| {
|
||||
for document in documents {
|
||||
writer.add_document(document).unwrap();
|
||||
@@ -111,47 +152,47 @@ fn main() -> color_eyre::Result<()> {
|
||||
.build();
|
||||
|
||||
let starting_url = Url::parse("http://fedora.quill.lan/rest/")?;
|
||||
let mut dataset = Dataset::new();
|
||||
let mut graph = Graph::new();
|
||||
let mut traversal = Traverse::new(http_client, starting_url, None);
|
||||
let mut rdf_source_count = 0usize;
|
||||
while let Some(result) = traversal.next().await {
|
||||
match result {
|
||||
Ok(rdf_source) => {
|
||||
dataset.extend(rdf_source.dataset());
|
||||
let triples = rdf_source.dataset().iter().map(TripleRef::from);
|
||||
graph.extend(triples);
|
||||
rdf_source_count += 1;
|
||||
},
|
||||
}
|
||||
Err(err) => error!(?err),
|
||||
}
|
||||
}
|
||||
|
||||
let span = debug_span!("Index Repository", rdf_sources = rdf_source_count, triples = field::Empty, documents = field::Empty);
|
||||
let span = debug_span!(
|
||||
"Index Repository",
|
||||
rdf_sources = rdf_source_count,
|
||||
triples = field::Empty,
|
||||
documents = field::Empty
|
||||
);
|
||||
let triple_count = async {
|
||||
let mut client = OntologyClient::connect("http://[::1]:3000").await.unwrap();
|
||||
let mut request = OntologyQueryRequest::default();
|
||||
let curie_helper = CurieHelper::new(gl_graph::PREFIXES.clone());
|
||||
let indexer =
|
||||
Indexer::new(language::ENGLISH_OR_UNTAGGED.clone(), &curie_helper);
|
||||
|
||||
let mut output_buffer = Vec::new();
|
||||
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle)
|
||||
.for_writer(output_buffer);
|
||||
for quad in &dataset {
|
||||
serializer.serialize_triple(TripleRef::from(quad))?;
|
||||
let mut client = OntologyBuilder::from_string(
|
||||
"http://[::1]:3000",
|
||||
language::ENGLISH_OR_UNTAGGED.clone(),
|
||||
)?
|
||||
.connect()
|
||||
.await?;
|
||||
|
||||
let graph_with_inferences = client.run_inference(&graph).await?;
|
||||
for document in indexer.graph(&graph_with_inferences) {
|
||||
writer.add_document(document)?;
|
||||
}
|
||||
output_buffer = serializer.finish()?;
|
||||
let turtle = String::from_utf8_lossy(&output_buffer).to_string();
|
||||
|
||||
request.sparql_query = None;
|
||||
request.turtle = Some(turtle);
|
||||
request.prefixes = HashMap::new();
|
||||
request.base = None;
|
||||
|
||||
let response = client.query(request).await.unwrap();
|
||||
let graph_with_inferences = RdfParser::from_format(RdfFormat::Turtle)
|
||||
.for_slice(&response.get_ref().results)
|
||||
.filter_map(Result::ok)
|
||||
.map(Triple::from)
|
||||
.collect::<Graph>();
|
||||
|
||||
Ok::<usize, crate::error::Error>(graph_with_inferences.len())
|
||||
}.instrument(span.clone()).await?;
|
||||
}
|
||||
.instrument(span.clone())
|
||||
.await?;
|
||||
span.record("triples", triple_count);
|
||||
|
||||
Ok::<_, crate::error::Error>(writer)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
pub(crate) mod conversion;
|
||||
pub(crate) mod ontology;
|
||||
//pub(crate) mod ontology;
|
||||
pub(crate) mod term_helper;
|
||||
|
||||
@@ -1,396 +0,0 @@
|
||||
use crate::error;
|
||||
use crate::rdf::conversion;
|
||||
use gl_graph::language::LanguageCondition;
|
||||
use gl_graph::vocab::gl;
|
||||
use iced::futures::TryFutureExt;
|
||||
use oxigraph::model::vocab::{rdf, rdfs, xsd};
|
||||
use oxigraph::model::{
|
||||
Dataset, Graph, GraphNameRef, LiteralRef, NamedNode, NamedNodeRef, NamedOrBlankNode,
|
||||
NamedOrBlankNodeRef, Term, TermRef, Triple, TripleRef,
|
||||
};
|
||||
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
||||
use oxigraph::store::Store;
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use std::fmt::Display;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::LazyLock;
|
||||
use tracing::{debug_span, field};
|
||||
|
||||
const ONTOLOGY_PREFIX: &str = "https://graphofliberty.org/2026/04/ont/";
|
||||
const ONTOLOGY_GRAPH_NAME: GraphNameRef = GraphNameRef::NamedNode(NamedNodeRef::new_unchecked(
|
||||
"https://graphofliberty.org/2026/04/ont",
|
||||
));
|
||||
|
||||
static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| {
|
||||
BTreeMap::from_iter(
|
||||
[
|
||||
("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"),
|
||||
("rdfs", "http://www.w3.org/2000/01/rdf-schema#"),
|
||||
("owl", "http://www.w3.org/2002/07/owl#"),
|
||||
("xsd", "http://www.w3.org/2001/XMLSchema#"),
|
||||
("ldp", "http://www.w3.org/ns/ldp#"),
|
||||
("dc", "http://purl.org/dc/elements/1.1/"),
|
||||
("posix", "http://www.w3.org/ns/posix/stat#"),
|
||||
(
|
||||
"ebucore",
|
||||
"http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#",
|
||||
),
|
||||
("prov", "http://www.w3.org/ns/prov#"),
|
||||
("locid", "http://id.loc.gov/vocabulary/identifiers/"),
|
||||
("loclang", "http://id.loc.gov/vocabulary/languages/"),
|
||||
("premis", "http://www.loc.gov/premis/rdf/v1#"),
|
||||
("premis3", "http://www.loc.gov/premis/rdf/v3/"),
|
||||
("dcterms", "http://purl.org/dc/terms/"),
|
||||
("fedora", "http://fedora.info/definitions/v4/repository#"),
|
||||
("rdaa", "http://rdaregistry.info/Elements/a/"),
|
||||
("rdac", "http://rdaregistry.info/Elements/c/"),
|
||||
("rdae", "http://rdaregistry.info/Elements/e/"),
|
||||
("rdai", "http://rdaregistry.info/Elements/i/"),
|
||||
("rdam", "http://rdaregistry.info/Elements/m/"),
|
||||
("rdan", "http://rdaregistry.info/Elements/n/"),
|
||||
("rdap", "http://rdaregistry.info/Elements/p/"),
|
||||
("rdaf", "http://rdaregistry.info/Elements/rof/"),
|
||||
("rdat", "http://rdaregistry.info/Elements/t/"),
|
||||
("rdau", "http://rdaregistry.info/Elements/u/"),
|
||||
("rdaw", "http://rdaregistry.info/Elements/w/"),
|
||||
("rdax", "http://rdaregistry.info/Elements/x/"),
|
||||
("rdaco", "http://rdaregistry.info/termList/RDAContentType/"),
|
||||
("rdact", "http://rdaregistry.info/termList/RDACarrierType/"),
|
||||
("rdamt", "http://rdaregistry.info/termList/RDAMediaType/"),
|
||||
("rdaft", "http://rdaregistry.info/termList/fileType/"),
|
||||
("schema", "https://schema.org/"),
|
||||
("gl", "http://fedora.quill.lan/rest/"),
|
||||
("glo", ONTOLOGY_PREFIX),
|
||||
]
|
||||
.map(|(k, v)| (k.to_string(), v.to_string())),
|
||||
)
|
||||
});
|
||||
|
||||
pub struct OntologyBuilder {
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl OntologyBuilder {
|
||||
pub fn with_path(mut self, path: impl AsRef<Path>) -> Self {
|
||||
let path = path.as_ref().to_owned();
|
||||
self.path = Some(path);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> error::Result<Ontology> {
|
||||
let store = if let Some(path) = self.path {
|
||||
Store::open(path)
|
||||
} else {
|
||||
Store::new()
|
||||
}?;
|
||||
|
||||
let prefixes = PREFIXES
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect::<HashMap<String, String>>();
|
||||
|
||||
/*let mut indexed_by = HashMap::new();
|
||||
for quad in store
|
||||
.quads_for_pattern(None, Some(gl::INDEXED_BY_FIELD), None, None)
|
||||
.filter_map(Result::ok)
|
||||
{
|
||||
if let NamedOrBlankNode::NamedNode(subject) = quad.subject
|
||||
&& let Term::NamedNode(field) = quad.object
|
||||
{
|
||||
indexed_by.insert(subject, field);
|
||||
}
|
||||
}*/
|
||||
|
||||
Ok(Ontology { store, prefixes })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IndexEntry {
|
||||
pub category_id: u64,
|
||||
pub fields: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq)]
|
||||
pub struct LabeledIri {
|
||||
pub iri: NamedNode,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
impl PartialEq for LabeledIri {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.iri == other.iri
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for LabeledIri {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
self.label.partial_cmp(&other.label)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for LabeledIri {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.label.cmp(&other.label)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LabeledIri {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.label)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IndexField {
|
||||
pub name: String,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
pub struct Ontology {
|
||||
store: Store,
|
||||
prefixes: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Ontology {
|
||||
pub fn builder() -> OntologyBuilder {
|
||||
OntologyBuilder { path: None }
|
||||
}
|
||||
|
||||
pub fn prefixes() -> &'static BTreeMap<String, String> {
|
||||
&*PREFIXES
|
||||
}
|
||||
|
||||
pub fn to_dataset(&self) -> Dataset {
|
||||
self.store
|
||||
.quads_for_pattern(None, None, None, Some(ONTOLOGY_GRAPH_NAME))
|
||||
.filter_map(Result::ok)
|
||||
.collect::<Dataset>()
|
||||
}
|
||||
|
||||
pub fn store(&self) -> Store {
|
||||
self.store.clone()
|
||||
}
|
||||
|
||||
pub fn query_for_indexable_triples(
|
||||
&self,
|
||||
language: &LanguageCondition,
|
||||
source: Option<Dataset>,
|
||||
) -> impl Future<Output = error::Result<HashMap<NamedNode, IndexEntry>>> + 'static {
|
||||
let language_filter = language.to_filter_expression("fieldValue");
|
||||
let query = format!(
|
||||
r#"SELECT ?individual ?categoryId ?fieldName ?fieldValue
|
||||
WHERE {{
|
||||
?class a gl:SearchableClass ;
|
||||
gl:categoryId ?categoryId ;
|
||||
gl:associatedProperty ?property .
|
||||
|
||||
?property gl:indexedByField/gl:fieldName ?fieldName .
|
||||
|
||||
?individual a ?class ;
|
||||
?property ?fieldValue .
|
||||
|
||||
{language_filter}
|
||||
}}"#
|
||||
);
|
||||
let mut sparql = SparqlEvaluator::new()
|
||||
.with_prefix("gl", ONTOLOGY_PREFIX)
|
||||
.unwrap()
|
||||
.parse_query(&query)
|
||||
.expect("Unable to parse query");
|
||||
sparql.dataset_mut().set_default_graph_as_union();
|
||||
|
||||
let store = self.store.clone();
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let span = debug_span!("Indexable Triples Query", solutions = field::Empty).entered();
|
||||
let query_results = if let Some(source) = &source {
|
||||
sparql.on_queryable_dataset(source).execute()
|
||||
} else {
|
||||
sparql.on_store(&store).execute()
|
||||
}
|
||||
.expect("Unable to execute indexing query");
|
||||
|
||||
let mut results = HashMap::new();
|
||||
if let QueryResults::Solutions(solutions) = query_results {
|
||||
let mut counter = 0usize;
|
||||
for solution in solutions.filter_map(Result::ok) {
|
||||
let individual = solution
|
||||
.get("individual")
|
||||
.and_then(conversion::term_to_named_node);
|
||||
let catalog_id = solution.get("categoryId").and_then(conversion::term_to_u64);
|
||||
let field_name = solution.get("fieldName").and_then(conversion::term_as_str);
|
||||
let field_value = solution.get("fieldValue").and_then(conversion::term_as_str);
|
||||
if let (
|
||||
Some(individual),
|
||||
Some(catalog_id),
|
||||
Some(field_name),
|
||||
Some(field_value),
|
||||
) = (individual, catalog_id, field_name, field_value)
|
||||
{
|
||||
results
|
||||
.entry(individual.to_owned())
|
||||
.and_modify(|entry: &mut IndexEntry| {
|
||||
entry
|
||||
.fields
|
||||
.insert(field_name.to_owned(), field_value.to_owned());
|
||||
})
|
||||
.or_insert(IndexEntry {
|
||||
category_id: catalog_id,
|
||||
fields: HashMap::from_iter([(
|
||||
field_name.to_owned(),
|
||||
field_value.to_owned(),
|
||||
)]),
|
||||
});
|
||||
}
|
||||
counter += 1;
|
||||
}
|
||||
span.record("solutions", counter);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
results
|
||||
})
|
||||
.map_err(error::Error::from)
|
||||
}
|
||||
|
||||
pub fn category_id(&self, class: &NamedNode) -> Option<u64> {
|
||||
None
|
||||
/*self.store
|
||||
.quads_for_pattern(Some(class.into()), Some(gl::CATEGORY_ID), None, None)
|
||||
.filter_map(Result::ok)
|
||||
.map(conversion::quad_into_term)
|
||||
.filter_map(conversion::term_into_u64)
|
||||
.next()*/
|
||||
}
|
||||
|
||||
pub fn fields_for_class(
|
||||
&self,
|
||||
class: &NamedNode,
|
||||
language: &LanguageCondition,
|
||||
) -> error::Result<Vec<IndexField>> {
|
||||
let language_filter = language.to_filter_expression("label");
|
||||
let query = format!(
|
||||
r#"SELECT DISTINCT ?name ?label {{
|
||||
{class} gl:associatedProperty/gl:indexedByField ?field .
|
||||
|
||||
?field gl:fieldName ?name ;
|
||||
gl:fieldLabel ?label .
|
||||
|
||||
{language_filter}
|
||||
}}"#
|
||||
);
|
||||
let mut sparql = SparqlEvaluator::new()
|
||||
.with_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#")?
|
||||
.with_prefix("gl", ONTOLOGY_PREFIX)?
|
||||
.parse_query(&query)?;
|
||||
sparql.dataset_mut().set_default_graph_as_union();
|
||||
|
||||
let mut results = Vec::new();
|
||||
if let QueryResults::Solutions(solutions) = sparql.on_store(&self.store).execute()? {
|
||||
for solution in solutions.filter_map(Result::ok) {
|
||||
let name = solution.get("name").and_then(conversion::term_as_str);
|
||||
let label = solution.get("label").and_then(conversion::term_as_str);
|
||||
|
||||
if let Some(name) = name
|
||||
&& let Some(label) = label
|
||||
{
|
||||
results.push(IndexField {
|
||||
name: name.to_string(),
|
||||
label: label.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
pub fn info(&self, iri: &NamedNode, language: &LanguageCondition) -> LabeledIri {
|
||||
let label = self
|
||||
.store
|
||||
.quads_for_pattern(Some(iri.as_ref().into()), Some(rdfs::LABEL), None, None)
|
||||
.filter_map(Result::ok)
|
||||
.map(conversion::quad_into_term)
|
||||
.filter(|term| language.primary_matches_term(term))
|
||||
.filter_map(conversion::term_into_string)
|
||||
.next()
|
||||
.unwrap_or_default();
|
||||
|
||||
LabeledIri {
|
||||
iri: iri.clone(),
|
||||
label,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subclasses_of(&self, class: &NamedNode) -> BTreeSet<NamedNode> {
|
||||
self.store
|
||||
.quads_for_pattern(None, Some(rdfs::SUB_CLASS_OF), Some(class.into()), None)
|
||||
.filter_map(Result::ok)
|
||||
.filter_map(|quad| {
|
||||
if let NamedOrBlankNode::NamedNode(subject) = quad.subject {
|
||||
Some(subject)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn datatypes(&self) -> BTreeSet<NamedNode> {
|
||||
self.store
|
||||
.quads_for_pattern(
|
||||
None,
|
||||
Some(rdf::TYPE),
|
||||
Some(TermRef::NamedNode(rdfs::DATATYPE)),
|
||||
None,
|
||||
)
|
||||
.filter_map(Result::ok)
|
||||
.filter_map(|quad| match quad.subject {
|
||||
NamedOrBlankNode::NamedNode(subject) => Some(subject),
|
||||
_ => None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn is_read_only<'a>(&self, triple: impl Into<TripleRef<'a>>) -> bool {
|
||||
let triple = triple.into();
|
||||
let true_term = TermRef::Literal(LiteralRef::new_typed_literal("true", xsd::BOOLEAN));
|
||||
|
||||
let subject = match (triple.predicate, triple.object) {
|
||||
(rdf::TYPE, TermRef::NamedNode(class)) => class,
|
||||
(predicate, _) => predicate,
|
||||
};
|
||||
|
||||
self.store
|
||||
.quads_for_pattern(
|
||||
Some(NamedOrBlankNodeRef::NamedNode(subject)),
|
||||
Some(gl::READ_ONLY),
|
||||
Some(true_term),
|
||||
None,
|
||||
)
|
||||
.filter_map(Result::ok)
|
||||
.count()
|
||||
>= 1
|
||||
}
|
||||
|
||||
pub fn exclude_read_only(&self) -> impl Fn(TripleRef<'_>) -> bool + 'static {
|
||||
let true_term = TermRef::Literal(LiteralRef::new_typed_literal("true", xsd::BOOLEAN));
|
||||
let read_only_graph = self
|
||||
.store
|
||||
.quads_for_pattern(None, Some(gl::READ_ONLY), Some(true_term), None)
|
||||
.filter_map(Result::ok)
|
||||
.map(Triple::from)
|
||||
.collect::<Graph>();
|
||||
move |triple| {
|
||||
if triple.predicate == rdf::TYPE
|
||||
&& let TermRef::NamedNode(class) = triple.object
|
||||
{
|
||||
read_only_graph.triples_for_subject(class).count() == 0
|
||||
} else {
|
||||
read_only_graph
|
||||
.triples_for_subject(triple.predicate)
|
||||
.count()
|
||||
== 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
use crate::app::Message;
|
||||
use gl_graph::class::Class;
|
||||
use gl_graph::ontology::{ConnectedOntology, OntologyBuilder, ResourceSelector};
|
||||
use gl_graph::vocab;
|
||||
use iced::Task;
|
||||
use ldp::ResourceRequestBuilder;
|
||||
use ldp::reqwest_middleware::ClientWithMiddleware;
|
||||
use oxigraph::io::RdfFormat;
|
||||
use oxigraph::model::{Dataset, Graph, NamedNode, NamedNodeRef, NamedOrBlankNodeRef, TermRef};
|
||||
use url::Url;
|
||||
|
||||
pub(crate) fn connect_to_ontology_service(builder: OntologyBuilder) -> Task<Message> {
|
||||
Task::perform(builder.connect(), |result| match result {
|
||||
Ok(ontology) => Message::ConnectedToOntologyService(ontology),
|
||||
Err(err) => Message::ShowError(err.to_string()),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn lookup_resource_descriptions(
|
||||
mut ontology: ConnectedOntology,
|
||||
subjects: impl IntoIterator<Item = NamedNode> + Send + 'static,
|
||||
) -> Task<Message> {
|
||||
Task::perform(
|
||||
async move {
|
||||
ontology
|
||||
.resource_descriptions(ResourceSelector::Subjects, subjects)
|
||||
.await
|
||||
},
|
||||
|result| match result {
|
||||
Ok(descriptions) => Message::CacheResourceDescriptions(descriptions),
|
||||
Err(err) => Message::ShowError(err.to_string()),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn list_datatypes(mut ontology: ConnectedOntology) -> Task<Message> {
|
||||
Task::perform(
|
||||
async move {
|
||||
ontology
|
||||
.resource_descriptions(
|
||||
ResourceSelector::Classes,
|
||||
vec![vocab::rdfs::DATATYPE.into_owned()],
|
||||
)
|
||||
.await
|
||||
},
|
||||
|result| match result {
|
||||
Ok(datatypes) => Message::CacheDatatypes(datatypes),
|
||||
Err(err) => Message::ShowError(err.to_string()),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn list_read_only_entities(mut ontology: ConnectedOntology) -> Task<Message> {
|
||||
Task::perform(
|
||||
async move { ontology.list_read_only().await },
|
||||
|result| match result {
|
||||
Ok(entities) => Message::CacheReadOnlyEntities(entities),
|
||||
Err(err) => Message::ShowError(err.to_string()),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn run_inference(mut ontology: ConnectedOntology, graph: Graph) -> Task<Message> {
|
||||
Task::perform(
|
||||
async move { ontology.run_inference(&graph).await },
|
||||
|result| match result {
|
||||
Ok(inferences) => Message::SetInferredTriples(inferences),
|
||||
Err(err) => Message::ShowError(err.to_string()),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn navigate_to_next_url(client: ClientWithMiddleware, class: Class) -> Task<Message> {
|
||||
if let Some(lookup_url) = class.next_url() {
|
||||
Task::future(async move {
|
||||
let request = ResourceRequestBuilder::with_client_and_url(client, lookup_url.clone())
|
||||
.accept_rdf_format(RdfFormat::Turtle)
|
||||
.follow_described_by(true)
|
||||
.build();
|
||||
|
||||
match request.send().await {
|
||||
Ok(resource) => match resource.into_rdf_source::<Dataset>().await {
|
||||
Ok(document) => {
|
||||
let node = NamedNodeRef::new_unchecked(lookup_url.as_str());
|
||||
let result = document
|
||||
.dataset()
|
||||
.quads_for_pattern(
|
||||
Some(NamedOrBlankNodeRef::NamedNode(node)),
|
||||
Some(vocab::glo::NEXT_URL),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.next();
|
||||
if let Some(next_url_quad) = result {
|
||||
if let TermRef::NamedNode(next_url) = next_url_quad.object {
|
||||
let url = Url::parse(next_url.as_str()).unwrap();
|
||||
Message::NewDocument(class, Some(url))
|
||||
} else {
|
||||
Message::None
|
||||
}
|
||||
} else {
|
||||
Message::None
|
||||
}
|
||||
}
|
||||
_ => Message::None,
|
||||
},
|
||||
_ => Message::None,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Task::none()
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use iced::clipboard::Content;
|
||||
use iced::mouse::{Cursor, Interaction};
|
||||
use iced::widget::text_input::{Catalog, Status, Style, StyleFn};
|
||||
use iced::{Element, Event, Length, Rectangle, Size, keyboard, widget};
|
||||
use url::Url;
|
||||
|
||||
pub struct State {
|
||||
control: bool,
|
||||
@@ -19,7 +20,7 @@ where
|
||||
Renderer: text::Renderer,
|
||||
{
|
||||
curie_helper: &'a CurieHelper,
|
||||
base: Option<String>,
|
||||
base: Option<&'a Url>,
|
||||
on_control_click: Option<Message>,
|
||||
on_shift_click: Option<Message>,
|
||||
text_input: widget::TextInput<'a, Message, Theme, Renderer>,
|
||||
@@ -34,7 +35,7 @@ where
|
||||
pub fn new(
|
||||
curie_helper: &'a CurieHelper,
|
||||
placeholder: &'a str,
|
||||
base: Option<&str>,
|
||||
base: Option<&'a Url>,
|
||||
iri: &str,
|
||||
) -> Self {
|
||||
let display_value = curie_helper
|
||||
@@ -43,7 +44,7 @@ where
|
||||
let text_input = widget::TextInput::new(placeholder, display_value);
|
||||
Self {
|
||||
curie_helper,
|
||||
base: base.map(String::from),
|
||||
base,
|
||||
on_control_click: None,
|
||||
on_shift_click: None,
|
||||
text_input,
|
||||
@@ -70,10 +71,9 @@ where
|
||||
|
||||
#[must_use]
|
||||
pub fn on_input(mut self, on_input: impl Fn(String) -> Message + 'a) -> Self {
|
||||
let base_clone = self.base.clone();
|
||||
let wrapped = move |value: String| {
|
||||
let expanded_value = self.curie_helper.expand(base_clone.as_deref(), &value);
|
||||
on_input(expanded_value.unwrap_or_else(|| value))
|
||||
let expanded_value = self.curie_helper.expand(self.base, &value);
|
||||
on_input(expanded_value.unwrap_or(value))
|
||||
};
|
||||
|
||||
self.text_input = self.text_input.on_input(wrapped);
|
||||
@@ -117,7 +117,7 @@ where
|
||||
pub fn iri_input<'a, Message, Theme, Renderer>(
|
||||
curie_helper: &'a CurieHelper,
|
||||
placeholder: &'a str,
|
||||
base: Option<&str>,
|
||||
base: Option<&'a Url>,
|
||||
iri: &str,
|
||||
) -> IriInput<'a, Message, Theme, Renderer>
|
||||
where
|
||||
@@ -213,8 +213,9 @@ where
|
||||
state.control = modifiers.control();
|
||||
state.shift = modifiers.shift();
|
||||
}
|
||||
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
|
||||
if cursor.is_over(layout.bounds()) {
|
||||
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
|
||||
if cursor.is_over(layout.bounds()) =>
|
||||
{
|
||||
if state.control
|
||||
&& let Some(on_control_click) = &self.on_control_click
|
||||
{
|
||||
@@ -229,7 +230,6 @@ where
|
||||
shell.capture_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -245,12 +245,12 @@ where
|
||||
);
|
||||
|
||||
let clipboard = shell.clipboard_mut();
|
||||
if let Some(Content::Text(content)) = &clipboard.write {
|
||||
if let Some(expanded) = self.curie_helper.expand(self.base.as_deref(), &content) {
|
||||
if let Some(Content::Text(content)) = &clipboard.write
|
||||
&& let Some(expanded) = self.curie_helper.expand(self.base, content)
|
||||
{
|
||||
clipboard.write = Some(Content::Text(expanded));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mouse_interaction(
|
||||
&self,
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -2,6 +2,7 @@ mod error;
|
||||
mod index;
|
||||
mod schema;
|
||||
pub mod subtitles;
|
||||
pub use tantivy;
|
||||
pub use tantivy::indexer::IndexWriter;
|
||||
pub use tantivy::schema::Field;
|
||||
pub use tantivy::schema::document::OwnedValue;
|
||||
|
||||
@@ -39,6 +39,8 @@ impl Schema {
|
||||
schema_builder.add_text_field("given_name:en", stored_ngram32.clone());
|
||||
schema_builder.add_text_field("corporate_name:en", stored_ngram32.clone());
|
||||
|
||||
schema_builder.add_text_field("title:en", stored_en_stem.clone());
|
||||
|
||||
schema_builder.add_u64_field("subtitle_start", schema::STORED);
|
||||
schema_builder.add_u64_field("subtitle_end", schema::STORED);
|
||||
schema_builder.add_text_field("subtitle:en", stored_en_stem.clone());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use subtitler;
|
||||
/*use subtitler;
|
||||
use subtitler::SubtitleFormat;
|
||||
|
||||
/*
|
||||
|
||||
pub fn bytes_to_documents(data: &[u8]) -> crate::Result<Vec<SearchDocument>> {
|
||||
let subtitle_start = Schema::field("subtitle_start", None);
|
||||
let subtitle_end = Schema::field("subtitle_end", None);
|
||||
|
||||
Reference in New Issue
Block a user