Compare commits
28
Commits
c8778a282e
..
master
| Author | SHA256 | Date | |
|---|---|---|---|
|
|
6d75248bde
|
||
|
|
abe3ac97b5
|
||
|
|
ebad6e6097
|
||
|
|
0c46d08e1d
|
||
|
|
1a122d6ecc
|
||
|
|
277d1d2a2d
|
||
|
|
a8938176be
|
||
|
|
948b415d5a
|
||
|
|
35477a3658
|
||
|
|
78243f53f5
|
||
|
|
70fca07790
|
||
|
|
37248f6ff3
|
||
|
|
8f6e2b3ac6
|
||
|
|
e28cfd1c53
|
||
|
|
631bb539f1
|
||
|
|
fcb1da7e0d
|
||
|
|
025392b129
|
||
|
|
72a39e5baa
|
||
|
|
8dcaa5b61f
|
||
|
|
a723b52191
|
||
|
|
f852da4f4e
|
||
|
|
79894f654d
|
||
|
|
9177c8902b
|
||
|
|
64a2c87346
|
||
|
|
36a105edfc
|
||
|
|
cd47d868c1
|
||
|
|
7ce5ed118d
|
||
|
|
921d56f2b3
|
Generated
+1218
-347
File diff suppressed because it is too large
Load Diff
+18
-3
@@ -1,32 +1,47 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"graph",
|
||||
"inference",
|
||||
"publish",
|
||||
"search",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
gl-graph = { path = "graph" }
|
||||
gl-inference = { path = "inference" }
|
||||
gl-search = { path = "search" }
|
||||
ldp = { path = "../../ldp/ldp", features = ["keyed"] }
|
||||
|
||||
async-trait = "0.1"
|
||||
base64 = "0.22"
|
||||
base64 = "0.23"
|
||||
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"
|
||||
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"
|
||||
thiserror = "2.0"
|
||||
tokio = { version = "1.53", features = ["rt", "rt-multi-thread", "macros", "fs"] }
|
||||
tonic = "0.14"
|
||||
tonic-prost = "0.14"
|
||||
tonic-prost-build = "0.14"
|
||||
tracing = "0.1"
|
||||
tracing-appender = "0.2"
|
||||
tracing-futures = "0.2"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
url = "2.5"
|
||||
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "gl-graph"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
gl-inference.workspace = true
|
||||
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"
|
||||
@@ -0,0 +1,22 @@
|
||||
use crate::vocab;
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub enum Category {
|
||||
AudioBook = 0,
|
||||
}
|
||||
|
||||
impl Category {
|
||||
pub fn to_named_node(&self) -> NamedNodeRef<'_> {
|
||||
match self {
|
||||
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::glo::AUDIO_BOOK => Some(Category::AudioBook),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
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,
|
||||
SkosConcept = 2,
|
||||
Work = 10001,
|
||||
Person = 10004,
|
||||
CorporateBody = 10005,
|
||||
Expression = 10006,
|
||||
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,
|
||||
Class::RdfsClass => vocab::rdfs::CLASS,
|
||||
Class::SkosConcept => vocab::skos::CONCEPT,
|
||||
Class::Work => vocab::rdac::WORK,
|
||||
Class::Person => vocab::rdac::PERSON,
|
||||
Class::CorporateBody => vocab::rdac::CORPORATE_BODY,
|
||||
Class::Expression => vocab::rdac::EXPRESSION,
|
||||
Class::Manifestation => vocab::rdac::MANIFESTATION,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_from_named_node<'a>(node: impl Into<NamedNodeRef<'a>>) -> Option<Self> {
|
||||
let node = node.into();
|
||||
match node {
|
||||
vocab::rdf::PROPERTY => Some(Class::RdfProperty),
|
||||
vocab::rdfs::CLASS => Some(Class::RdfsClass),
|
||||
vocab::skos::CONCEPT => Some(Class::SkosConcept),
|
||||
vocab::rdac::WORK => Some(Class::Work),
|
||||
vocab::rdac::PERSON => Some(Class::Person),
|
||||
vocab::rdac::CORPORATE_BODY => Some(Class::CorporateBody),
|
||||
vocab::rdac::EXPRESSION => Some(Class::Expression),
|
||||
vocab::rdac::MANIFESTATION => Some(Class::Manifestation),
|
||||
_ => 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),
|
||||
]),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::LazyLock;
|
||||
use url::Url;
|
||||
|
||||
const ONTOLOGY_PREFIX: &str = "https://graphofliberty.org/2026/04/ont/";
|
||||
|
||||
pub 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#"),
|
||||
("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/"),
|
||||
("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/"),
|
||||
("glo", ONTOLOGY_PREFIX),
|
||||
]
|
||||
.map(|(k, v)| (k.to_string(), v.to_string())),
|
||||
)
|
||||
});
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CurieHelper {
|
||||
prefixes: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
impl CurieHelper {
|
||||
pub fn new(prefixes: BTreeMap<String, String>) -> Self {
|
||||
Self { prefixes }
|
||||
}
|
||||
|
||||
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)
|
||||
});
|
||||
|
||||
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<&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());
|
||||
|
||||
absolute_iri.split_once(':').and_then(|(prefix, name)| {
|
||||
if prefix.is_empty()
|
||||
&& let Some(base) = base
|
||||
{
|
||||
Some(format!("{base}{name}"))
|
||||
} else {
|
||||
self.prefixes
|
||||
.get(prefix)
|
||||
.map(|base| format!("{base}{name}"))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
use thiserror::Error;
|
||||
|
||||
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),
|
||||
|
||||
#[error(transparent)]
|
||||
Storage(#[from] oxigraph::store::StorageError),
|
||||
|
||||
#[error(transparent)]
|
||||
SparqlSyntax(#[from] oxigraph::sparql::SparqlSyntaxError),
|
||||
|
||||
#[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,
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
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 {
|
||||
Some(node)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn term_as_str(term: &Term) -> Option<&str> {
|
||||
if let Term::Literal(literal) = term {
|
||||
match literal.datatype() {
|
||||
xsd::STRING | xsd::NORMALIZED_STRING | rdf::LANG_STRING | rdf::DIR_LANG_STRING => {
|
||||
Some(literal.value())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn term_ref_as_str(term: TermRef<'_>) -> Option<&str> {
|
||||
if let TermRef::Literal(literal) = term {
|
||||
match literal.datatype() {
|
||||
xsd::STRING | xsd::NORMALIZED_STRING | rdf::LANG_STRING | rdf::DIR_LANG_STRING => {
|
||||
Some(literal.value())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
use oxigraph::model::{Literal, TermRef};
|
||||
use oxilangtag::LanguageTag;
|
||||
use spargebra::algebra::{Expression, Function, GraphPattern};
|
||||
use spargebra::term::Variable;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
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(ENGLISH_TAG.clone()));
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum LanguageCondition {
|
||||
ExactMatchOnly(LanguageTag<String>),
|
||||
ExactMatchOrUntagged(LanguageTag<String>),
|
||||
UntaggedOnly,
|
||||
AnyOrNone,
|
||||
}
|
||||
|
||||
impl LanguageCondition {
|
||||
pub fn primary_matches_term<'a>(&self, term: impl Into<TermRef<'a>>) -> bool {
|
||||
if let TermRef::Literal(literal) = term.into() {
|
||||
let tag = literal
|
||||
.language()
|
||||
.map(LanguageTag::parse_and_normalize)
|
||||
.and_then(Result::ok);
|
||||
|
||||
match (tag, self) {
|
||||
(Some(language), LanguageCondition::ExactMatchOnly(expectation))
|
||||
| (Some(language), LanguageCondition::ExactMatchOrUntagged(expectation)) => {
|
||||
language.primary_language() == expectation.primary_language()
|
||||
}
|
||||
(None, LanguageCondition::ExactMatchOrUntagged(_)) => true,
|
||||
(None, LanguageCondition::UntaggedOnly) => true,
|
||||
(_, LanguageCondition::AnyOrNone) => true,
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn primary_language(&self) -> Option<&str> {
|
||||
match self {
|
||||
LanguageCondition::ExactMatchOnly(tag) => Some(tag.primary_language()),
|
||||
LanguageCondition::ExactMatchOrUntagged(tag) => Some(tag.primary_language()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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,
|
||||
}
|
||||
.map(|expr| {
|
||||
GraphPattern::Filter {
|
||||
expr,
|
||||
inner: Box::new(GraphPattern::Bgp { patterns: vec![] }),
|
||||
}
|
||||
.to_string()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
mod curie;
|
||||
mod error;
|
||||
|
||||
pub mod category;
|
||||
pub mod class;
|
||||
mod helpers;
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
pub use oxigraph::model::vocab::rdf;
|
||||
pub use oxigraph::model::vocab::rdfs;
|
||||
|
||||
pub mod glo {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const AUDIO_BOOK: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/AudioBook");
|
||||
|
||||
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 lclang {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const ENGLISH: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://id.loc.gov/vocabulary/languages/eng");
|
||||
}
|
||||
|
||||
pub mod owl {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const SAME_AS: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://www.w3.org/2002/07/owl#sameAs");
|
||||
}
|
||||
|
||||
pub mod rdac {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const PERSON: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/c/C10004");
|
||||
|
||||
pub const CORPORATE_BODY: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/c/C10005");
|
||||
|
||||
pub const WORK: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/c/C10001");
|
||||
|
||||
pub const EXPRESSION: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/c/C10006");
|
||||
|
||||
pub const MANIFESTATION: NamedNodeRef =
|
||||
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;
|
||||
|
||||
pub const GIVEN_NAME: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/a/datatype/P50292");
|
||||
|
||||
pub const SURNAME: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/a/datatype/P50291");
|
||||
|
||||
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");
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "gl-inference"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
color-eyre.workspace = true
|
||||
num-traits.workspace = true
|
||||
oxigraph.workspace = true
|
||||
prost.workspace = true
|
||||
thiserror.workspace = true
|
||||
tonic.workspace = true
|
||||
tonic-prost.workspace = true
|
||||
tokio.workspace = true
|
||||
tracing.workspace = true
|
||||
tracing-appender.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
tonic-prost-build.workspace = true
|
||||
@@ -0,0 +1,7 @@
|
||||
fn main() {
|
||||
tonic_prost_build::compile_protos("../proto/inference.proto")
|
||||
.unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e));
|
||||
|
||||
println!("cargo::rerun-if-changed=build.rs");
|
||||
println!("cargo::rerun-if-changed=proto/inference.proto");
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
use thiserror::Error;
|
||||
|
||||
pub type Result<R> = std::result::Result<R, Error>;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error(transparent)]
|
||||
IriParse(#[from] oxigraph::model::IriParseError),
|
||||
|
||||
#[error(transparent)]
|
||||
SparqlSyntax(#[from] oxigraph::sparql::SparqlSyntaxError),
|
||||
|
||||
#[error(transparent)]
|
||||
QueryEvaluation(#[from] oxigraph::sparql::QueryEvaluationError),
|
||||
|
||||
#[error(transparent)]
|
||||
UpdateEvaluation(#[from] oxigraph::sparql::UpdateEvaluationError),
|
||||
|
||||
#[error(transparent)]
|
||||
Storage(#[from] oxigraph::store::StorageError),
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
pub mod proto {
|
||||
tonic::include_proto!("org.graphofliberty.inference");
|
||||
}
|
||||
|
||||
pub use tonic;
|
||||
@@ -0,0 +1,77 @@
|
||||
use oxigraph::model::GraphNameRef;
|
||||
use oxigraph::sparql::SparqlEvaluator;
|
||||
use oxigraph::store::Store;
|
||||
use tracing::debug_span;
|
||||
|
||||
const RDF_SCHEMA_PREFIX: &str = "http://www.w3.org/2000/01/rdf-schema#";
|
||||
const GL_PREFIX: &str = "https://graphofliberty.org/";
|
||||
|
||||
/// `prp-spo1`
|
||||
const SUB_PROPERTY_OF_UPDATE: &str = r#"INSERT {
|
||||
?x ?p2 ?y .
|
||||
} WHERE {
|
||||
GRAPH gl:ontology { ?p1 rdfs:subPropertyOf ?p2 . }
|
||||
?x ?p1 ?y .
|
||||
}"#;
|
||||
|
||||
/// `cax-sco`
|
||||
const SUB_CLASS_OF_UPDATE: &str = r#"INSERT {
|
||||
?x a ?c2 .
|
||||
} WHERE {
|
||||
GRAPH gl:ontology { ?c1 rdfs:subClassOf ?c2 . }
|
||||
?x a ?c1 .
|
||||
}"#;
|
||||
|
||||
/// `prp-dom`
|
||||
const DOMAIN_UPDATE: &str = r#"INSERT {
|
||||
?x a ?c .
|
||||
} WHERE {
|
||||
GRAPH gl:ontology { ?p rdfs:domain ?c . }
|
||||
?x ?p ?y .
|
||||
}"#;
|
||||
|
||||
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()?;
|
||||
|
||||
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();
|
||||
|
||||
let new_inferences_total = inferences + (new_count - old_count);
|
||||
if new_count > old_count {
|
||||
infer(new_inferences_total, store, graph_name)
|
||||
} else {
|
||||
Ok(new_inferences_total)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
use crate::service::OntologyService;
|
||||
use gl_inference::proto::ontology_server::OntologyServer;
|
||||
use tonic::transport::Server;
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::{EnvFilter, fmt};
|
||||
|
||||
mod error;
|
||||
mod logic;
|
||||
mod service;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> color_eyre::Result<()> {
|
||||
let appender = tracing_appender::rolling::never("/tmp", "inference");
|
||||
tracing_subscriber::registry()
|
||||
.with(
|
||||
fmt::layer()
|
||||
.with_span_events(FmtSpan::CLOSE)
|
||||
.with_writer(appender),
|
||||
)
|
||||
.with(EnvFilter::from_default_env())
|
||||
.init();
|
||||
color_eyre::install()?;
|
||||
|
||||
let ontology_service = OntologyService::new();
|
||||
let server = OntologyServer::new(ontology_service);
|
||||
|
||||
let addr = String::from("[::1]:3000");
|
||||
println!("Inference engine listening on: {addr}");
|
||||
|
||||
Server::builder()
|
||||
.add_service(server)
|
||||
.serve(addr.parse().unwrap())
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
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::results::{QueryResultsFormat, QueryResultsSerializer};
|
||||
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
||||
use oxigraph::store::Store;
|
||||
use tonic::{Request, Response, Status};
|
||||
use tracing::{debug, debug_span, field};
|
||||
|
||||
const ONTOLOGY_GRAPH: GraphNameRef = GraphNameRef::NamedNode(NamedNodeRef::new_unchecked(
|
||||
"https://graphofliberty.org/ontology",
|
||||
));
|
||||
|
||||
pub struct OntologyService {
|
||||
ontology: Store,
|
||||
}
|
||||
|
||||
impl OntologyService {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
ontology: Store::new().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl Ontology for OntologyService {
|
||||
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 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();
|
||||
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| {
|
||||
quad.graph_name = ONTOLOGY_GRAPH.into_owned();
|
||||
quad
|
||||
});
|
||||
self.ontology.extend(quads).unwrap();
|
||||
|
||||
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);
|
||||
|
||||
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> {
|
||||
let span = debug_span!("Clear Ontology", size = field::Empty).entered();
|
||||
|
||||
let size = self
|
||||
.ontology
|
||||
.len()
|
||||
.map_err(|err| Status::internal(err.to_string()))?
|
||||
.to_u64()
|
||||
.unwrap_or(u64::MAX);
|
||||
|
||||
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> {
|
||||
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()
|
||||
)));
|
||||
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>();
|
||||
|
||||
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())
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
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)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
if let Some(base) = &request.base {
|
||||
evaluator = evaluator
|
||||
.with_base_iri(base)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
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()]);
|
||||
|
||||
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)
|
||||
.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)?;
|
||||
for solution in solutions.filter_map(Result::ok) {
|
||||
writer.serialize(&solution)?;
|
||||
}
|
||||
output_buffer = writer.finish()?;
|
||||
}
|
||||
QueryResults::Graph(graph) => {
|
||||
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle);
|
||||
for (name, iri) in &request.prefixes {
|
||||
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)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
let mut serializer = serializer.for_writer(output_buffer);
|
||||
for triple in graph.filter_map(Result::ok) {
|
||||
serializer.serialize_triple(triple.as_ref())?;
|
||||
}
|
||||
output_buffer = serializer.finish()?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle);
|
||||
for (name, iri) in &request.prefixes {
|
||||
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)
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
let mut serializer = serializer.for_writer(output_buffer);
|
||||
let resulting_dataset = self
|
||||
.ontology
|
||||
.quads_for_pattern(None, None, None, Some(graph_name.as_ref()))
|
||||
.filter_map(Result::ok);
|
||||
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()?;
|
||||
}
|
||||
|
||||
response.results = String::from_utf8_lossy(&output_buffer).to_string();
|
||||
|
||||
if request.turtle.is_some() {
|
||||
self.ontology
|
||||
.clear_graph(graph_name.as_ref())
|
||||
.map_err(|err| Status::internal(err.to_string()))?;
|
||||
}
|
||||
|
||||
Ok(Response::new(response))
|
||||
}
|
||||
}
|
||||
@@ -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 {} \;
|
||||
|
||||
+33
-155
@@ -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
|
||||
@@ -87,60 +88,23 @@ xsd:unsignedShort rdf:type rdfs:Datatype ;
|
||||
# Object Properties
|
||||
#################################################################
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/associatedProperty
|
||||
:associatedProperty rdf:type owl:ObjectProperty ;
|
||||
rdfs:label "associated property"@en .
|
||||
### https://graphofliberty.org/2026/04/ont/derivedWith
|
||||
:derivedWith rdf:type owl:ObjectProperty ;
|
||||
rdfs:range :DerivationMethodology ;
|
||||
rdfs:comment "Relates a File to a Derivation Methodology."@en ;
|
||||
rdfs:label "derived with"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/fullText
|
||||
:fullText rdf:type owl:ObjectProperty ;
|
||||
rdfs:comment "A URL to a file which is intended to be passed to a full-text search database."@en ;
|
||||
rdfs:label "has full text"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/indexedByField
|
||||
:indexedByField rdf:type owl:ObjectProperty ;
|
||||
rdfs:range :IndexDocumentField ;
|
||||
rdfs:comment "The property is associated with the given field in a full-text search database."@en ;
|
||||
rdfs:label "indexed by field"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/template
|
||||
:template rdf:type owl:ObjectProperty ;
|
||||
rdfs:comment "A default set of triples used during the creation of new entities of the associated class."@en ;
|
||||
rdfs:label "has template"@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
|
||||
#################################################################
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/categoryId
|
||||
:categoryId rdf:type owl:DatatypeProperty ;
|
||||
rdfs:domain :SearchableClass ;
|
||||
rdfs:range xsd:nonNegativeInteger ;
|
||||
rdfs:comment "An integer associated with the class for fast lookup in a database."@en ;
|
||||
rdfs:label "category id" .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/fieldLabel
|
||||
:fieldLabel rdf:type owl:DatatypeProperty ;
|
||||
rdfs:domain :IndexDocumentField ;
|
||||
rdfs:range rdf:dirLangString ,
|
||||
rdf:langString ,
|
||||
xsd:string ;
|
||||
rdfs:comment "The label of a field, which shall be displayed to the user."@en ;
|
||||
rdfs:label "field label"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/fieldName
|
||||
:fieldName rdf:type owl:DatatypeProperty ;
|
||||
rdfs:domain :IndexDocumentField ;
|
||||
rdfs:range xsd:string ;
|
||||
rdfs:comment "The name of the field, as defined in the full-text search document schema."@en ;
|
||||
rdfs:label "field name"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/readOnly
|
||||
:readOnly rdf:type owl:DatatypeProperty ;
|
||||
rdfs:comment "Indicates that the property or class is read only (server managed) and should not be made editable in user-facing applications."@en ;
|
||||
@@ -151,22 +115,16 @@ xsd:unsignedShort rdf:type rdfs:Datatype ;
|
||||
# Classes
|
||||
#################################################################
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/Entity
|
||||
:Entity rdf:type owl:Class ;
|
||||
rdfs:comment "An Entity is a first-class citizen of the Graph of Liberty catalog. It is the class of all cultural artifacts which are to be preserved."@en ;
|
||||
rdfs:label "Graph of Liberty Entity"@en .
|
||||
### https://graphofliberty.org/2026/04/ont/Category
|
||||
:Category rdf:type owl:Class ;
|
||||
rdfs:subClassOf skos:Concept ;
|
||||
rdfs:label "Category"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/IndexDocumentField
|
||||
:IndexDocumentField rdf:type owl:Class ;
|
||||
rdfs:comment "Describes a single field present within a document that is indexed in a full-text search database."@en ;
|
||||
rdfs:label "Index Document Field"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/SearchableClass
|
||||
:SearchableClass rdf:type owl:Class ;
|
||||
rdfs:comment "The class of classes which are to be indexed in the full-text search database."@en ;
|
||||
rdfs:label "Searchable Class"@en .
|
||||
### https://graphofliberty.org/2026/04/ont/DerivationMethodology
|
||||
:DerivationMethodology rdf:type owl:Class ;
|
||||
rdfs:comment "The methodology used to derive content. Individuals of this class should provide enough information to replicate the process by which the content was generated. For example, if Whisper was used derive captions for an audio book, the precise model used (e.g. large v3), a link to the source code (e.g. HuggingFace) and/or a paper should be provided."@en ;
|
||||
rdfs:label "Derivation Methodology"@en .
|
||||
|
||||
|
||||
#################################################################
|
||||
@@ -183,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 .
|
||||
@@ -208,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 .
|
||||
@@ -218,24 +186,6 @@ fedora:lastModifiedBy rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
|
||||
|
||||
### http://rdaregistry.info/Elements/a/datatype/P50291
|
||||
<http://rdaregistry.info/Elements/a/datatype/P50291> rdf:type owl:NamedIndividual ;
|
||||
:indexedByField :Surname .
|
||||
|
||||
|
||||
### http://rdaregistry.info/Elements/a/datatype/P50292
|
||||
<http://rdaregistry.info/Elements/a/datatype/P50292> rdf:type owl:NamedIndividual ;
|
||||
:indexedByField :GivenName .
|
||||
|
||||
|
||||
### http://rdaregistry.info/Elements/c/C10004
|
||||
rdac:C10004 rdf:type owl:NamedIndividual ,
|
||||
:SearchableClass ;
|
||||
:associatedProperty <http://rdaregistry.info/Elements/a/datatype/P50291> ,
|
||||
<http://rdaregistry.info/Elements/a/datatype/P50292> ;
|
||||
:categoryId "3"^^xsd:nonNegativeInteger .
|
||||
|
||||
|
||||
### http://www.loc.gov/premis/rdf/v1#hasMessageDigest
|
||||
premis:hasMessageDigest rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
@@ -256,52 +206,6 @@ premis3:size rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
|
||||
|
||||
### http://www.w3.org/1999/02/22-rdf-syntax-ns#Property
|
||||
rdf:Property rdf:type owl:NamedIndividual ,
|
||||
:SearchableClass ;
|
||||
:associatedProperty rdfs:comment ,
|
||||
rdfs:label ,
|
||||
skos:definition ;
|
||||
:categoryId "0"^^xsd:nonNegativeInteger .
|
||||
|
||||
|
||||
### http://www.w3.org/2000/01/rdf-schema#Class
|
||||
rdfs:Class rdf:type owl:NamedIndividual ,
|
||||
:SearchableClass ;
|
||||
:associatedProperty rdfs:comment ,
|
||||
rdfs:label ,
|
||||
skos:definition ;
|
||||
:categoryId "1"^^xsd:nonNegativeInteger .
|
||||
|
||||
|
||||
### http://www.w3.org/2000/01/rdf-schema#comment
|
||||
rdfs:comment rdf:type owl:NamedIndividual ;
|
||||
:indexedByField :Definition .
|
||||
|
||||
|
||||
### http://www.w3.org/2000/01/rdf-schema#label
|
||||
rdfs:label rdf:type owl:NamedIndividual ;
|
||||
:indexedByField :Label .
|
||||
|
||||
|
||||
### http://www.w3.org/2004/02/skos/core#Concept
|
||||
skos:Concept rdf:type owl:NamedIndividual ,
|
||||
:SearchableClass ;
|
||||
:associatedProperty skos:definition ,
|
||||
skos:prefLabel ;
|
||||
:categoryId "2"^^xsd:nonNegativeInteger .
|
||||
|
||||
|
||||
### http://www.w3.org/2004/02/skos/core#definition
|
||||
skos:definition rdf:type owl:NamedIndividual ;
|
||||
:indexedByField :Definition .
|
||||
|
||||
|
||||
### http://www.w3.org/2004/02/skos/core#prefLabel
|
||||
skos:prefLabel rdf:type owl:NamedIndividual ;
|
||||
:indexedByField :Label .
|
||||
|
||||
|
||||
### http://www.w3.org/ns/ldp#BasicContainer
|
||||
ldp:BasicContainer rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
@@ -332,36 +236,10 @@ ldp:contains rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/Definition
|
||||
:Definition rdf:type owl:NamedIndividual ,
|
||||
:IndexDocumentField ;
|
||||
:fieldLabel "Definition"@en ;
|
||||
:fieldName "definition" ;
|
||||
rdfs:label "Definition Field"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/GivenName
|
||||
:GivenName rdf:type owl:NamedIndividual ,
|
||||
:IndexDocumentField ;
|
||||
:fieldLabel "Given Name"@en ;
|
||||
:fieldName "given_name" ;
|
||||
rdfs:label "Given Name Field"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/Label
|
||||
:Label rdf:type owl:NamedIndividual ,
|
||||
:IndexDocumentField ;
|
||||
:fieldLabel "Label"@en ;
|
||||
:fieldName "label" ;
|
||||
rdfs:label "Label Field"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/Surname
|
||||
:Surname rdf:type owl:NamedIndividual ,
|
||||
:IndexDocumentField ;
|
||||
:fieldLabel "Surname"@en ;
|
||||
:fieldName "surname" ;
|
||||
rdfs:label "Surname Field"@en .
|
||||
### https://graphofliberty.org/2026/04/ont/AudioBook
|
||||
:AudioBook rdf:type owl:NamedIndividual ,
|
||||
:Category ;
|
||||
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>
|
||||
@@ -0,0 +1,106 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option go_package = "google.golang.org/protobuf/types/known/anypb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "AnyProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
||||
// URL that describes the type of the serialized message.
|
||||
//
|
||||
// In its binary encoding, an `Any` is an ordinary message; but in other wire
|
||||
// forms like JSON, it has a special encoding. The format of the type URL is
|
||||
// described on the `type_url` field.
|
||||
//
|
||||
// Protobuf APIs provide utilities to interact with `Any` values:
|
||||
//
|
||||
// - A 'pack' operation accepts a message and constructs a generic `Any` wrapper
|
||||
// around it.
|
||||
// - An 'unpack' operation reads the content of an `Any` message, either into an
|
||||
// existing message or a new one. Unpack operations must check the type of the
|
||||
// value they unpack against the declared `type_url`.
|
||||
// - An 'is' operation decides whether an `Any` contains a message of the given
|
||||
// type, i.e. whether it can 'unpack' that type.
|
||||
//
|
||||
// The JSON format representation of an `Any` follows one of these cases:
|
||||
//
|
||||
// - For types without special-cased JSON encodings, the JSON format
|
||||
// representation of the `Any` is the same as that of the message, with an
|
||||
// additional `@type` field which contains the type URL.
|
||||
// - For types with special-cased JSON encodings (typically called 'well-known'
|
||||
// types, listed in https://protobuf.dev/programming-guides/json/#any), the
|
||||
// JSON format representation has a key `@type` which contains the type URL
|
||||
// and a key `value` which contains the JSON-serialized value.
|
||||
//
|
||||
// The text format representation of an `Any` is like a message with one field
|
||||
// whose name is the type URL in brackets. For example, an `Any` containing a
|
||||
// `foo.Bar` message may be written `[type.googleapis.com/foo.Bar] { a: 2 }`.
|
||||
message Any {
|
||||
// Identifies the type of the serialized Protobuf message with a URI reference
|
||||
// consisting of a prefix ending in a slash and the fully-qualified type name.
|
||||
//
|
||||
// Example: type.googleapis.com/google.protobuf.StringValue
|
||||
//
|
||||
// This string must contain at least one `/` character, and the content after
|
||||
// the last `/` must be the fully-qualified name of the type in canonical
|
||||
// form, without a leading dot. Do not write a scheme on these URI references
|
||||
// so that clients do not attempt to contact them.
|
||||
//
|
||||
// The prefix is arbitrary and Protobuf implementations are expected to
|
||||
// simply strip off everything up to and including the last `/` to identify
|
||||
// the type. `type.googleapis.com/` is a common default prefix that some
|
||||
// legacy implementations require. This prefix does not indicate the origin of
|
||||
// the type, and URIs containing it are not expected to respond to any
|
||||
// requests.
|
||||
//
|
||||
// All type URL strings must be legal URI references with the additional
|
||||
// restriction (for the text format) that the content of the reference
|
||||
// must consist only of alphanumeric characters, percent-encoded escapes, and
|
||||
// characters in the following set (not including the outer backticks):
|
||||
// `/-.~_!$&()*+,;=`. Despite our allowing percent encodings, implementations
|
||||
// should not unescape them to prevent confusion with existing parsers. For
|
||||
// example, `type.googleapis.com%2FFoo` should be rejected.
|
||||
//
|
||||
// In the original design of `Any`, the possibility of launching a type
|
||||
// resolution service at these type URLs was considered but Protobuf never
|
||||
// implemented one and considers contacting these URLs to be problematic and
|
||||
// a potential security issue. Do not attempt to contact type URLs.
|
||||
string type_url = 1;
|
||||
|
||||
// Holds a Protobuf serialization of the type described by type_url.
|
||||
bytes value = 2;
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
import "google/protobuf/source_context.proto";
|
||||
import "google/protobuf/type.proto";
|
||||
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "ApiProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "google.golang.org/protobuf/types/known/apipb";
|
||||
|
||||
// Api is a light-weight descriptor for an API Interface.
|
||||
//
|
||||
// Interfaces are also described as "protocol buffer services" in some contexts,
|
||||
// such as by the "service" keyword in a .proto file, but they are different
|
||||
// from API Services, which represent a concrete implementation of an interface
|
||||
// as opposed to simply a description of methods and bindings. They are also
|
||||
// sometimes simply referred to as "APIs" in other contexts, such as the name of
|
||||
// this message itself. See https://cloud.google.com/apis/design/glossary for
|
||||
// detailed terminology.
|
||||
//
|
||||
// New usages of this message as an alternative to ServiceDescriptorProto are
|
||||
// strongly discouraged. This message does not reliability preserve all
|
||||
// information necessary to model the schema and preserve semantics. Instead
|
||||
// make use of FileDescriptorSet which preserves the necessary information.
|
||||
message Api {
|
||||
// The fully qualified name of this interface, including package name
|
||||
// followed by the interface's simple name.
|
||||
string name = 1;
|
||||
|
||||
// The methods of this interface, in unspecified order.
|
||||
repeated Method methods = 2;
|
||||
|
||||
// Any metadata attached to the interface.
|
||||
repeated Option options = 3;
|
||||
|
||||
// A version string for this interface. If specified, must have the form
|
||||
// `major-version.minor-version`, as in `1.10`. If the minor version is
|
||||
// omitted, it defaults to zero. If the entire version field is empty, the
|
||||
// major version is derived from the package name, as outlined below. If the
|
||||
// field is not empty, the version in the package name will be verified to be
|
||||
// consistent with what is provided here.
|
||||
//
|
||||
// The versioning schema uses [semantic
|
||||
// versioning](http://semver.org) where the major version number
|
||||
// indicates a breaking change and the minor version an additive,
|
||||
// non-breaking change. Both version numbers are signals to users
|
||||
// what to expect from different versions, and should be carefully
|
||||
// chosen based on the product plan.
|
||||
//
|
||||
// The major version is also reflected in the package name of the
|
||||
// interface, which must end in `v<major-version>`, as in
|
||||
// `google.feature.v1`. For major versions 0 and 1, the suffix can
|
||||
// be omitted. Zero major versions must only be used for
|
||||
// experimental, non-GA interfaces.
|
||||
//
|
||||
string version = 4;
|
||||
|
||||
// Source context for the protocol buffer service represented by this
|
||||
// message.
|
||||
SourceContext source_context = 5;
|
||||
|
||||
// Included interfaces. See [Mixin][].
|
||||
repeated Mixin mixins = 6;
|
||||
|
||||
// The source syntax of the service.
|
||||
Syntax syntax = 7;
|
||||
|
||||
// The source edition string, only valid when syntax is SYNTAX_EDITIONS.
|
||||
string edition = 8;
|
||||
}
|
||||
|
||||
// Method represents a method of an API interface.
|
||||
//
|
||||
// New usages of this message as an alternative to MethodDescriptorProto are
|
||||
// strongly discouraged. This message does not reliability preserve all
|
||||
// information necessary to model the schema and preserve semantics. Instead
|
||||
// make use of FileDescriptorSet which preserves the necessary information.
|
||||
message Method {
|
||||
// The simple name of this method.
|
||||
string name = 1;
|
||||
|
||||
// A URL of the input message type.
|
||||
string request_type_url = 2;
|
||||
|
||||
// If true, the request is streamed.
|
||||
bool request_streaming = 3;
|
||||
|
||||
// The URL of the output message type.
|
||||
string response_type_url = 4;
|
||||
|
||||
// If true, the response is streamed.
|
||||
bool response_streaming = 5;
|
||||
|
||||
// Any metadata attached to the method.
|
||||
repeated Option options = 6;
|
||||
|
||||
// The source syntax of this method.
|
||||
//
|
||||
// This field should be ignored, instead the syntax should be inherited from
|
||||
// Api. This is similar to Field and EnumValue.
|
||||
Syntax syntax = 7 [deprecated = true];
|
||||
|
||||
// The source edition string, only valid when syntax is SYNTAX_EDITIONS.
|
||||
//
|
||||
// This field should be ignored, instead the edition should be inherited from
|
||||
// Api. This is similar to Field and EnumValue.
|
||||
string edition = 8 [deprecated = true];
|
||||
}
|
||||
|
||||
// Declares an API Interface to be included in this interface. The including
|
||||
// interface must redeclare all the methods from the included interface, but
|
||||
// documentation and options are inherited as follows:
|
||||
//
|
||||
// - If after comment and whitespace stripping, the documentation
|
||||
// string of the redeclared method is empty, it will be inherited
|
||||
// from the original method.
|
||||
//
|
||||
// - Each annotation belonging to the service config (http,
|
||||
// visibility) which is not set in the redeclared method will be
|
||||
// inherited.
|
||||
//
|
||||
// - If an http annotation is inherited, the path pattern will be
|
||||
// modified as follows. Any version prefix will be replaced by the
|
||||
// version of the including interface plus the [root][] path if
|
||||
// specified.
|
||||
//
|
||||
// Example of a simple mixin:
|
||||
//
|
||||
// package google.acl.v1;
|
||||
// service AccessControl {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v1/{resource=**}:getAcl";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// package google.storage.v2;
|
||||
// service Storage {
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl);
|
||||
//
|
||||
// // Get a data record.
|
||||
// rpc GetData(GetDataRequest) returns (Data) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}";
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Example of a mixin configuration:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
//
|
||||
// The mixin construct implies that all methods in `AccessControl` are
|
||||
// also declared with same name and request/response types in
|
||||
// `Storage`. A documentation generator or annotation processor will
|
||||
// see the effective `Storage.GetAcl` method after inheriting
|
||||
// documentation and annotations as follows:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// Note how the version in the path pattern changed from `v1` to `v2`.
|
||||
//
|
||||
// If the `root` field in the mixin is specified, it should be a
|
||||
// relative path under which inherited HTTP paths are placed. Example:
|
||||
//
|
||||
// apis:
|
||||
// - name: google.storage.v2.Storage
|
||||
// mixins:
|
||||
// - name: google.acl.v1.AccessControl
|
||||
// root: acls
|
||||
//
|
||||
// This implies the following inherited HTTP annotation:
|
||||
//
|
||||
// service Storage {
|
||||
// // Get the underlying ACL object.
|
||||
// rpc GetAcl(GetAclRequest) returns (Acl) {
|
||||
// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
message Mixin {
|
||||
// The fully qualified name of the interface which is included.
|
||||
string name = 1;
|
||||
|
||||
// If non-empty specifies a path under which inherited HTTP paths
|
||||
// are rooted.
|
||||
string root = 2;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2026 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package pb;
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.Reflection";
|
||||
option java_multiple_files = true;
|
||||
option java_outer_classname = "CSharpFeaturesOuterClass";
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
extend google.protobuf.FeatureSet {
|
||||
optional CSharpFeatures csharp = 1004;
|
||||
}
|
||||
|
||||
message CSharpFeatures {
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
// Author: kenton@google.com (Kenton Varda)
|
||||
//
|
||||
// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is
|
||||
// just a program that reads a CodeGeneratorRequest from stdin and writes a
|
||||
// CodeGeneratorResponse to stdout.
|
||||
//
|
||||
// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
|
||||
// of dealing with the raw protocol defined here.
|
||||
//
|
||||
// A plugin executable needs only to be placed somewhere in the path. The
|
||||
// plugin should be named "protoc-gen-$NAME", and will then be used when the
|
||||
// flag "--${NAME}_out" is passed to protoc.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package google.protobuf.compiler;
|
||||
option java_package = "com.google.protobuf.compiler";
|
||||
option java_outer_classname = "PluginProtos";
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option csharp_namespace = "Google.Protobuf.Compiler";
|
||||
option go_package = "google.golang.org/protobuf/types/pluginpb";
|
||||
|
||||
// The version number of protocol compiler.
|
||||
message Version {
|
||||
optional int32 major = 1;
|
||||
optional int32 minor = 2;
|
||||
optional int32 patch = 3;
|
||||
// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
|
||||
// be empty for mainline stable releases.
|
||||
optional string suffix = 4;
|
||||
}
|
||||
|
||||
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
|
||||
message CodeGeneratorRequest {
|
||||
// The .proto files that were explicitly listed on the command-line. The
|
||||
// code generator should generate code only for these files. Each file's
|
||||
// descriptor will be included in proto_file, below.
|
||||
repeated string file_to_generate = 1;
|
||||
|
||||
// The generator parameter passed on the command-line.
|
||||
optional string parameter = 2;
|
||||
|
||||
// FileDescriptorProtos for all files in files_to_generate and everything
|
||||
// they import. The files will appear in topological order, so each file
|
||||
// appears before any file that imports it.
|
||||
//
|
||||
// Note: the files listed in files_to_generate will include runtime-retention
|
||||
// options only, but all other files will include source-retention options.
|
||||
// The source_file_descriptors field below is available in case you need
|
||||
// source-retention options for files_to_generate.
|
||||
//
|
||||
// protoc guarantees that all proto_files will be written after
|
||||
// the fields above, even though this is not technically guaranteed by the
|
||||
// protobuf wire format. This theoretically could allow a plugin to stream
|
||||
// in the FileDescriptorProtos and handle them one by one rather than read
|
||||
// the entire set into memory at once. However, as of this writing, this
|
||||
// is not similarly optimized on protoc's end -- it will store all fields in
|
||||
// memory at once before sending them to the plugin.
|
||||
//
|
||||
// Type names of fields and extensions in the FileDescriptorProto are always
|
||||
// fully qualified.
|
||||
repeated FileDescriptorProto proto_file = 15;
|
||||
|
||||
// File descriptors with all options, including source-retention options.
|
||||
// These descriptors are only provided for the files listed in
|
||||
// files_to_generate.
|
||||
repeated FileDescriptorProto source_file_descriptors = 17;
|
||||
|
||||
// The version number of protocol compiler.
|
||||
optional Version compiler_version = 3;
|
||||
}
|
||||
|
||||
// The plugin writes an encoded CodeGeneratorResponse to stdout.
|
||||
message CodeGeneratorResponse {
|
||||
// Error message. If non-empty, code generation failed. The plugin process
|
||||
// should exit with status code zero even if it reports an error in this way.
|
||||
//
|
||||
// This should be used to indicate errors in .proto files which prevent the
|
||||
// code generator from generating correct code. Errors which indicate a
|
||||
// problem in protoc itself -- such as the input CodeGeneratorRequest being
|
||||
// unparseable -- should be reported by writing a message to stderr and
|
||||
// exiting with a non-zero status code.
|
||||
optional string error = 1;
|
||||
|
||||
// A bitmask of supported features that the code generator supports.
|
||||
// This is a bitwise "or" of values from the Feature enum.
|
||||
optional uint64 supported_features = 2;
|
||||
|
||||
// Sync with code_generator.h.
|
||||
enum Feature {
|
||||
FEATURE_NONE = 0;
|
||||
FEATURE_PROTO3_OPTIONAL = 1;
|
||||
FEATURE_SUPPORTS_EDITIONS = 2;
|
||||
}
|
||||
|
||||
// The minimum edition this plugin supports. This will be treated as an
|
||||
// Edition enum, but we want to allow unknown values. It should be specified
|
||||
// according the edition enum value, *not* the edition number. Only takes
|
||||
// effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
|
||||
optional int32 minimum_edition = 3;
|
||||
|
||||
// The maximum edition this plugin supports. This will be treated as an
|
||||
// Edition enum, but we want to allow unknown values. It should be specified
|
||||
// according the edition enum value, *not* the edition number. Only takes
|
||||
// effect for plugins that have FEATURE_SUPPORTS_EDITIONS set.
|
||||
optional int32 maximum_edition = 4;
|
||||
|
||||
// Represents a single generated file.
|
||||
message File {
|
||||
// The file name, relative to the output directory. The name must not
|
||||
// contain "." or ".." components and must be relative, not be absolute (so,
|
||||
// the file cannot lie outside the output directory). "/" must be used as
|
||||
// the path separator, not "\".
|
||||
//
|
||||
// If the name is omitted, the content will be appended to the previous
|
||||
// file. This allows the generator to break large files into small chunks,
|
||||
// and allows the generated text to be streamed back to protoc so that large
|
||||
// files need not reside completely in memory at one time. Note that as of
|
||||
// this writing protoc does not optimize for this -- it will read the entire
|
||||
// CodeGeneratorResponse before writing files to disk.
|
||||
optional string name = 1;
|
||||
|
||||
// If non-empty, indicates that the named file should already exist, and the
|
||||
// content here is to be inserted into that file at a defined insertion
|
||||
// point. This feature allows a code generator to extend the output
|
||||
// produced by another code generator. The original generator may provide
|
||||
// insertion points by placing special annotations in the file that look
|
||||
// like:
|
||||
// @@protoc_insertion_point(NAME)
|
||||
// The annotation can have arbitrary text before and after it on the line,
|
||||
// which allows it to be placed in a comment. NAME should be replaced with
|
||||
// an identifier naming the point -- this is what other generators will use
|
||||
// as the insertion_point. Code inserted at this point will be placed
|
||||
// immediately above the line containing the insertion point (thus multiple
|
||||
// insertions to the same point will come out in the order they were added).
|
||||
// The double-@ is intended to make it unlikely that the generated code
|
||||
// could contain things that look like insertion points by accident.
|
||||
//
|
||||
// For example, the C++ code generator places the following line in the
|
||||
// .pb.h files that it generates:
|
||||
// // @@protoc_insertion_point(namespace_scope)
|
||||
// This line appears within the scope of the file's package namespace, but
|
||||
// outside of any particular class. Another plugin can then specify the
|
||||
// insertion_point "namespace_scope" to generate additional classes or
|
||||
// other declarations that should be placed in this scope.
|
||||
//
|
||||
// Note that if the line containing the insertion point begins with
|
||||
// whitespace, the same whitespace will be added to every line of the
|
||||
// inserted text. This is useful for languages like Python, where
|
||||
// indentation matters. In these languages, the insertion point comment
|
||||
// should be indented the same amount as any inserted code will need to be
|
||||
// in order to work correctly in that context.
|
||||
//
|
||||
// The code generator that generates the initial file and the one which
|
||||
// inserts into it must both run as part of a single invocation of protoc.
|
||||
// Code generators are executed in the order in which they appear on the
|
||||
// command line.
|
||||
//
|
||||
// If |insertion_point| is present, |name| must also be present.
|
||||
optional string insertion_point = 2;
|
||||
|
||||
// The file contents.
|
||||
optional string content = 15;
|
||||
|
||||
// Information describing the file content being inserted. If an insertion
|
||||
// point is used, this information will be appropriately offset and inserted
|
||||
// into the code generation metadata for the generated files.
|
||||
optional GeneratedCodeInfo generated_code_info = 16;
|
||||
}
|
||||
repeated File file = 15;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2023 Google LLC. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package pb;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
extend google.protobuf.FeatureSet {
|
||||
optional CppFeatures cpp = 1000;
|
||||
}
|
||||
|
||||
message CppFeatures {
|
||||
// Whether or not to treat an enum field as closed. This option is only
|
||||
// applicable to enum fields, and will be removed in the future. It is
|
||||
// consistent with the legacy behavior of using proto3 enum types for proto2
|
||||
// fields.
|
||||
optional bool legacy_closed_enum = 1 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_FIELD,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2023,
|
||||
edition_deprecated: EDITION_2023,
|
||||
deprecation_warning: "The legacy closed enum behavior in C++ is "
|
||||
"deprecated and is scheduled to be removed in "
|
||||
"edition 2025. See http://protobuf.dev/programming-guides/enum/#cpp for "
|
||||
"more information",
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "true" },
|
||||
edition_defaults = { edition: EDITION_PROTO3, value: "false" }
|
||||
];
|
||||
|
||||
enum StringType {
|
||||
STRING_TYPE_UNKNOWN = 0;
|
||||
VIEW = 1;
|
||||
CORD = 2;
|
||||
STRING = 3;
|
||||
}
|
||||
|
||||
optional StringType string_type = 2 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_FIELD,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2023,
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "STRING" },
|
||||
edition_defaults = { edition: EDITION_2024, value: "VIEW" }
|
||||
];
|
||||
|
||||
optional bool enum_name_uses_string_view = 3 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_ENUM,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2024,
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "false" },
|
||||
edition_defaults = { edition: EDITION_2024, value: "true" }
|
||||
];
|
||||
|
||||
enum RepeatedType {
|
||||
REPEATED_TYPE_UNKNOWN = 0;
|
||||
// The repeated field will be backed by proto2::Repeated(Ptr)Field, and
|
||||
// accessors will return a reference/pointer to this type.
|
||||
LEGACY = 1;
|
||||
// The repeated field has an opaque backing type, and accessors will return
|
||||
// a RepeatedFieldProxy.
|
||||
PROXY = 2;
|
||||
}
|
||||
|
||||
optional RepeatedType repeated_type = 4 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_FIELD,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_UNSTABLE,
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "LEGACY" }
|
||||
];
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,115 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/protobuf/types/known/durationpb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "DurationProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// A Duration represents a signed, fixed-length span of time represented
|
||||
// as a count of seconds and fractions of seconds at nanosecond
|
||||
// resolution. It is independent of any calendar and concepts like "day"
|
||||
// or "month". It is related to Timestamp in that the difference between
|
||||
// two Timestamp values is a Duration and it can be added or subtracted
|
||||
// from a Timestamp. Range is approximately +-10,000 years.
|
||||
//
|
||||
// # Examples
|
||||
//
|
||||
// Example 1: Compute Duration from two Timestamps in pseudo code.
|
||||
//
|
||||
// Timestamp start = ...;
|
||||
// Timestamp end = ...;
|
||||
// Duration duration = ...;
|
||||
//
|
||||
// duration.seconds = end.seconds - start.seconds;
|
||||
// duration.nanos = end.nanos - start.nanos;
|
||||
//
|
||||
// if (duration.seconds < 0 && duration.nanos > 0) {
|
||||
// duration.seconds += 1;
|
||||
// duration.nanos -= 1000000000;
|
||||
// } else if (duration.seconds > 0 && duration.nanos < 0) {
|
||||
// duration.seconds -= 1;
|
||||
// duration.nanos += 1000000000;
|
||||
// }
|
||||
//
|
||||
// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
|
||||
//
|
||||
// Timestamp start = ...;
|
||||
// Duration duration = ...;
|
||||
// Timestamp end = ...;
|
||||
//
|
||||
// end.seconds = start.seconds + duration.seconds;
|
||||
// end.nanos = start.nanos + duration.nanos;
|
||||
//
|
||||
// if (end.nanos < 0) {
|
||||
// end.seconds -= 1;
|
||||
// end.nanos += 1000000000;
|
||||
// } else if (end.nanos >= 1000000000) {
|
||||
// end.seconds += 1;
|
||||
// end.nanos -= 1000000000;
|
||||
// }
|
||||
//
|
||||
// Example 3: Compute Duration from datetime.timedelta in Python.
|
||||
//
|
||||
// td = datetime.timedelta(days=3, minutes=10)
|
||||
// duration = Duration()
|
||||
// duration.FromTimedelta(td)
|
||||
//
|
||||
// # JSON Mapping
|
||||
//
|
||||
// In JSON format, the Duration type is encoded as a string rather than an
|
||||
// object, where the string ends in the suffix "s" (indicating seconds) and
|
||||
// is preceded by the number of seconds, with nanoseconds expressed as
|
||||
// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
|
||||
// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
|
||||
// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
|
||||
// microsecond should be expressed in JSON format as "3.000001s".
|
||||
//
|
||||
message Duration {
|
||||
// Signed seconds of the span of time. Must be from -315,576,000,000
|
||||
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
|
||||
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
|
||||
int64 seconds = 1;
|
||||
|
||||
// Signed fractions of a second at nanosecond resolution of the span
|
||||
// of time. Durations less than one second are represented with a 0
|
||||
// `seconds` field and a positive or negative `nanos` field. For durations
|
||||
// of one second or more, a non-zero value for the `nanos` field must be
|
||||
// of the same sign as the `seconds` field. Must be from -999,999,999
|
||||
// to +999,999,999 inclusive.
|
||||
int32 nanos = 2;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option go_package = "google.golang.org/protobuf/types/known/emptypb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "EmptyProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option cc_enable_arenas = true;
|
||||
|
||||
// A generic empty message that you can re-use to avoid defining duplicated
|
||||
// empty messages in your APIs. A typical example is to use it as the request
|
||||
// or the response type of an API method. For instance:
|
||||
//
|
||||
// service Foo {
|
||||
// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
|
||||
// }
|
||||
//
|
||||
message Empty {}
|
||||
@@ -0,0 +1,243 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "FieldMaskProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb";
|
||||
option cc_enable_arenas = true;
|
||||
|
||||
// `FieldMask` represents a set of symbolic field paths, for example:
|
||||
//
|
||||
// paths: "f.a"
|
||||
// paths: "f.b.d"
|
||||
//
|
||||
// Here `f` represents a field in some root message, `a` and `b`
|
||||
// fields in the message found in `f`, and `d` a field found in the
|
||||
// message in `f.b`.
|
||||
//
|
||||
// Field masks are used to specify a subset of fields that should be
|
||||
// returned by a get operation or modified by an update operation.
|
||||
// Field masks also have a custom JSON encoding (see below).
|
||||
//
|
||||
// # Field Masks in Projections
|
||||
//
|
||||
// When used in the context of a projection, a response message or
|
||||
// sub-message is filtered by the API to only contain those fields as
|
||||
// specified in the mask. For example, if the mask in the previous
|
||||
// example is applied to a response message as follows:
|
||||
//
|
||||
// f {
|
||||
// a : 22
|
||||
// b {
|
||||
// d : 1
|
||||
// x : 2
|
||||
// }
|
||||
// y : 13
|
||||
// }
|
||||
// z: 8
|
||||
//
|
||||
// The result will not contain specific values for fields x,y and z
|
||||
// (their value will be set to the default, and omitted in proto text
|
||||
// output):
|
||||
//
|
||||
//
|
||||
// f {
|
||||
// a : 22
|
||||
// b {
|
||||
// d : 1
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// A repeated field is not allowed except at the last position of a
|
||||
// paths string.
|
||||
//
|
||||
// If a FieldMask object is not present in a get operation, the
|
||||
// operation applies to all fields (as if a FieldMask of all fields
|
||||
// had been specified).
|
||||
//
|
||||
// Note that a field mask does not necessarily apply to the
|
||||
// top-level response message. In case of a REST get operation, the
|
||||
// field mask applies directly to the response, but in case of a REST
|
||||
// list operation, the mask instead applies to each individual message
|
||||
// in the returned resource list. In case of a REST custom method,
|
||||
// other definitions may be used. Where the mask applies will be
|
||||
// clearly documented together with its declaration in the API. In
|
||||
// any case, the effect on the returned resource/resources is required
|
||||
// behavior for APIs.
|
||||
//
|
||||
// # Field Masks in Update Operations
|
||||
//
|
||||
// A field mask in update operations specifies which fields of the
|
||||
// targeted resource are going to be updated. The API is required
|
||||
// to only change the values of the fields as specified in the mask
|
||||
// and leave the others untouched. If a resource is passed in to
|
||||
// describe the updated values, the API ignores the values of all
|
||||
// fields not covered by the mask.
|
||||
//
|
||||
// If a repeated field is specified for an update operation, new values will
|
||||
// be appended to the existing repeated field in the target resource. Note that
|
||||
// a repeated field is only allowed in the last position of a `paths` string.
|
||||
//
|
||||
// If a sub-message is specified in the last position of the field mask for an
|
||||
// update operation, then new value will be merged into the existing sub-message
|
||||
// in the target resource.
|
||||
//
|
||||
// For example, given the target message:
|
||||
//
|
||||
// f {
|
||||
// b {
|
||||
// d: 1
|
||||
// x: 2
|
||||
// }
|
||||
// c: [1]
|
||||
// }
|
||||
//
|
||||
// And an update message:
|
||||
//
|
||||
// f {
|
||||
// b {
|
||||
// d: 10
|
||||
// }
|
||||
// c: [2]
|
||||
// }
|
||||
//
|
||||
// then if the field mask is:
|
||||
//
|
||||
// paths: ["f.b", "f.c"]
|
||||
//
|
||||
// then the result will be:
|
||||
//
|
||||
// f {
|
||||
// b {
|
||||
// d: 10
|
||||
// x: 2
|
||||
// }
|
||||
// c: [1, 2]
|
||||
// }
|
||||
//
|
||||
// An implementation may provide options to override this default behavior for
|
||||
// repeated and message fields.
|
||||
//
|
||||
// Note that libraries which implement FieldMask resolution have various
|
||||
// different behaviors in the face of empty masks or the special "*" mask.
|
||||
// When implementing a service you should confirm these cases have the
|
||||
// appropriate behavior in the underlying FieldMask library that you desire,
|
||||
// and you may need to special case those cases in your application code if
|
||||
// the underlying field mask library behavior differs from your intended
|
||||
// service semantics.
|
||||
//
|
||||
// Update methods implementing https://google.aip.dev/134
|
||||
// - MUST support the special value * meaning "full replace"
|
||||
// - MUST treat an omitted field mask as "replace fields which are present".
|
||||
//
|
||||
// Other methods implementing https://google.aip.dev/157
|
||||
// - SHOULD support the special value "*" to mean "get all".
|
||||
// - MUST treat an omitted field mask to mean "get all", unless otherwise
|
||||
// documented.
|
||||
//
|
||||
// ## Considerations for HTTP REST
|
||||
//
|
||||
// The HTTP kind of an update operation which uses a field mask must
|
||||
// be set to PATCH instead of PUT in order to satisfy HTTP semantics
|
||||
// (PUT must only be used for full updates).
|
||||
//
|
||||
// # JSON Encoding of Field Masks
|
||||
//
|
||||
// In JSON, a field mask is encoded as a single string where paths are
|
||||
// separated by a comma. Fields name in each path are converted
|
||||
// to/from lower-camel naming conventions.
|
||||
//
|
||||
// As an example, consider the following message declarations:
|
||||
//
|
||||
// message Profile {
|
||||
// User user = 1;
|
||||
// Photo photo = 2;
|
||||
// }
|
||||
// message User {
|
||||
// string display_name = 1;
|
||||
// string address = 2;
|
||||
// }
|
||||
//
|
||||
// In proto a field mask for `Profile` may look as such:
|
||||
//
|
||||
// mask {
|
||||
// paths: "user.display_name"
|
||||
// paths: "photo"
|
||||
// }
|
||||
//
|
||||
// In JSON, the same mask is represented as below:
|
||||
//
|
||||
// {
|
||||
// mask: "user.displayName,photo"
|
||||
// }
|
||||
//
|
||||
// # Field Masks and Oneof Fields
|
||||
//
|
||||
// Field masks treat fields in oneofs just as regular fields. Consider the
|
||||
// following message:
|
||||
//
|
||||
// message SampleMessage {
|
||||
// oneof test_oneof {
|
||||
// string name = 4;
|
||||
// SubMessage sub_message = 9;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// The field mask can be:
|
||||
//
|
||||
// mask {
|
||||
// paths: "name"
|
||||
// }
|
||||
//
|
||||
// Or:
|
||||
//
|
||||
// mask {
|
||||
// paths: "sub_message"
|
||||
// }
|
||||
//
|
||||
// Note that oneof type names ("test_oneof" in this case) cannot be used in
|
||||
// paths.
|
||||
//
|
||||
// ## Field Mask Verification
|
||||
//
|
||||
// The implementation of any API method which has a FieldMask type field in the
|
||||
// request should verify the included field paths, and return an
|
||||
// `INVALID_ARGUMENT` error if any path is unmappable.
|
||||
message FieldMask {
|
||||
// The set of field mask paths.
|
||||
repeated string paths = 1;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package pb;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option go_package = "google.golang.org/protobuf/types/gofeaturespb";
|
||||
|
||||
extend google.protobuf.FeatureSet {
|
||||
optional GoFeatures go = 1002;
|
||||
}
|
||||
|
||||
message GoFeatures {
|
||||
// Whether or not to generate the deprecated UnmarshalJSON method for enums.
|
||||
// Can only be true for proto using the Open Struct api.
|
||||
optional bool legacy_unmarshal_json_enum = 1 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_ENUM,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2023,
|
||||
edition_deprecated: EDITION_2023,
|
||||
deprecation_warning: "The legacy UnmarshalJSON API is deprecated and "
|
||||
"will be removed in a future edition.",
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "true" },
|
||||
edition_defaults = { edition: EDITION_PROTO3, value: "false" }
|
||||
];
|
||||
|
||||
enum APILevel {
|
||||
// API_LEVEL_UNSPECIFIED results in selecting the OPEN API,
|
||||
// but needs to be a separate value to distinguish between
|
||||
// an explicitly set api level or a missing api level.
|
||||
API_LEVEL_UNSPECIFIED = 0;
|
||||
API_OPEN = 1;
|
||||
API_HYBRID = 2;
|
||||
API_OPAQUE = 3;
|
||||
}
|
||||
|
||||
// One of OPEN, HYBRID or OPAQUE.
|
||||
optional APILevel api_level = 2 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_MESSAGE,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2023,
|
||||
},
|
||||
edition_defaults = {
|
||||
edition: EDITION_LEGACY,
|
||||
value: "API_LEVEL_UNSPECIFIED"
|
||||
},
|
||||
edition_defaults = { edition: EDITION_2024, value: "API_OPAQUE" }
|
||||
];
|
||||
|
||||
enum StripEnumPrefix {
|
||||
STRIP_ENUM_PREFIX_UNSPECIFIED = 0;
|
||||
STRIP_ENUM_PREFIX_KEEP = 1;
|
||||
STRIP_ENUM_PREFIX_GENERATE_BOTH = 2;
|
||||
STRIP_ENUM_PREFIX_STRIP = 3;
|
||||
}
|
||||
|
||||
optional StripEnumPrefix strip_enum_prefix = 3 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_ENUM,
|
||||
targets = TARGET_TYPE_ENUM_ENTRY,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2024,
|
||||
},
|
||||
// TODO: change the default to STRIP_ENUM_PREFIX_STRIP for edition 2025.
|
||||
edition_defaults = {
|
||||
edition: EDITION_LEGACY,
|
||||
value: "STRIP_ENUM_PREFIX_KEEP"
|
||||
}
|
||||
];
|
||||
|
||||
// Wrap the OptimizeMode enum in a message for scoping:
|
||||
// This way, users can type shorter names (SPEED, CODE_SIZE).
|
||||
message OptimizeModeFeature {
|
||||
// The name of this enum matches OptimizeMode in descriptor.proto.
|
||||
enum OptimizeMode {
|
||||
// OPTIMIZE_MODE_UNSPECIFIED results in falling back to the default
|
||||
// (optimize for code size), but needs to be a separate value to distinguish
|
||||
// between an explicitly set optimize mode or a missing optimize mode.
|
||||
OPTIMIZE_MODE_UNSPECIFIED = 0;
|
||||
SPEED = 1;
|
||||
CODE_SIZE = 2;
|
||||
// There is no enum entry for LITE_RUNTIME (descriptor.proto),
|
||||
// because Go Protobuf does not have the concept of a lite runtime.
|
||||
}
|
||||
}
|
||||
|
||||
optional OptimizeModeFeature.OptimizeMode optimize_mode = 4 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_MESSAGE,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2024,
|
||||
},
|
||||
edition_defaults = {
|
||||
edition: EDITION_LEGACY,
|
||||
value: "OPTIMIZE_MODE_UNSPECIFIED"
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2023 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package pb;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "JavaFeaturesProto";
|
||||
|
||||
extend google.protobuf.FeatureSet {
|
||||
optional JavaFeatures java = 1001;
|
||||
}
|
||||
|
||||
message JavaFeatures {
|
||||
// Whether or not to treat an enum field as closed. This option is only
|
||||
// applicable to enum fields, and will be removed in the future. It is
|
||||
// consistent with the legacy behavior of using proto3 enum types for proto2
|
||||
// fields.
|
||||
optional bool legacy_closed_enum = 1 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_FIELD,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2023,
|
||||
edition_deprecated: EDITION_2023,
|
||||
deprecation_warning: "The legacy closed enum behavior in Java is "
|
||||
"deprecated and is scheduled to be removed in "
|
||||
"edition 2025. See http://protobuf.dev/programming-guides/enum/#java for "
|
||||
"more information.",
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "true" },
|
||||
edition_defaults = { edition: EDITION_PROTO3, value: "false" }
|
||||
];
|
||||
|
||||
// The UTF8 validation strategy to use.
|
||||
enum Utf8Validation {
|
||||
// Invalid default, which should never be used.
|
||||
UTF8_VALIDATION_UNKNOWN = 0;
|
||||
// Respect the UTF8 validation behavior specified by the global
|
||||
// utf8_validation feature.
|
||||
DEFAULT = 1;
|
||||
// Verifies UTF8 validity overriding the global utf8_validation
|
||||
// feature. This represents the legacy java_string_check_utf8 option.
|
||||
VERIFY = 2;
|
||||
}
|
||||
optional Utf8Validation utf8_validation = 2 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_FIELD,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2023,
|
||||
edition_deprecated: EDITION_2024,
|
||||
deprecation_warning: "The Java-specific utf8 validation feature is "
|
||||
"deprecated and is scheduled to be removed in "
|
||||
"edition 2025. Utf8 validation behavior should "
|
||||
"use the global cross-language utf8_validation "
|
||||
"feature.",
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "DEFAULT" }
|
||||
];
|
||||
|
||||
// Allows creation of large Java enums, extending beyond the standard
|
||||
// constant limits imposed by the Java language.
|
||||
optional bool large_enum = 3 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_ENUM,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2024,
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "false" }
|
||||
];
|
||||
|
||||
// Whether to use the old default outer class name scheme, or the new feature
|
||||
// which adds a "Proto" suffix to the outer class name.
|
||||
//
|
||||
// Users will not be able to set this option, because we removed it in the
|
||||
// same edition that it was introduced. But we use it to determine which
|
||||
// naming scheme to use for outer class name defaults.
|
||||
optional bool use_old_outer_classname_default = 4 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_FILE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2024,
|
||||
edition_removed: EDITION_2024,
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "true" },
|
||||
edition_defaults = { edition: EDITION_2024, value: "false" }
|
||||
];
|
||||
|
||||
message NestInFileClassFeature {
|
||||
enum NestInFileClass {
|
||||
// Invalid default, which should never be used.
|
||||
NEST_IN_FILE_CLASS_UNKNOWN = 0;
|
||||
// Do not nest the generated class in the file class.
|
||||
NO = 1;
|
||||
// Nest the generated class in the file class.
|
||||
YES = 2;
|
||||
// Fall back to the `java_multiple_files` option. Users won't be able to
|
||||
// set this option.
|
||||
LEGACY = 3 [feature_support = {
|
||||
edition_introduced: EDITION_2024
|
||||
edition_removed: EDITION_2024
|
||||
}];
|
||||
}
|
||||
reserved 1 to max;
|
||||
}
|
||||
|
||||
// Whether to nest the generated class in the generated file class. This is
|
||||
// only applicable to *top-level* messages, enums, and services.
|
||||
optional NestInFileClassFeature.NestInFileClass nest_in_file_class = 5 [
|
||||
retention = RETENTION_RUNTIME,
|
||||
targets = TARGET_TYPE_MESSAGE,
|
||||
targets = TARGET_TYPE_ENUM,
|
||||
targets = TARGET_TYPE_SERVICE,
|
||||
feature_support = {
|
||||
edition_introduced: EDITION_2024,
|
||||
},
|
||||
edition_defaults = { edition: EDITION_LEGACY, value: "LEGACY" },
|
||||
edition_defaults = { edition: EDITION_2024, value: "NO" }
|
||||
];
|
||||
|
||||
reserved 6; // field `mutable_nest_in_file_class` removed.
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "SourceContextProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb";
|
||||
|
||||
// `SourceContext` represents information about the source of a
|
||||
// protobuf element, like the file in which it is defined.
|
||||
message SourceContext {
|
||||
// The path-qualified name of the .proto file that contained the associated
|
||||
// protobuf element. For example: `"google/protobuf/source_context.proto"`.
|
||||
string file_name = 1;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/protobuf/types/known/structpb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "StructProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// Represents a JSON object.
|
||||
//
|
||||
// An unordered key-value map, intending to perfectly capture the semantics of a
|
||||
// JSON object. This enables parsing any arbitrary JSON payload as a message
|
||||
// field in ProtoJSON format.
|
||||
//
|
||||
// This follows RFC 8259 guidelines for interoperable JSON: notably this type
|
||||
// cannot represent large Int64 values or `NaN`/`Infinity` numbers,
|
||||
// since the JSON format generally does not support those values in its number
|
||||
// type.
|
||||
//
|
||||
// If you do not intend to parse arbitrary JSON into your message, a custom
|
||||
// typed message should be preferred instead of using this type.
|
||||
message Struct {
|
||||
// Unordered map of dynamically typed values.
|
||||
map<string, Value> fields = 1;
|
||||
}
|
||||
|
||||
// Represents a JSON value.
|
||||
//
|
||||
// `Value` represents a dynamically typed value which can be either
|
||||
// null, a number, a string, a boolean, a recursive struct value, or a
|
||||
// list of values. A producer of value is expected to set one of these
|
||||
// variants. Absence of any variant is an invalid state.
|
||||
message Value {
|
||||
// The kind of value.
|
||||
oneof kind {
|
||||
// Represents a JSON `null`.
|
||||
NullValue null_value = 1;
|
||||
|
||||
// Represents a JSON number. Must not be `NaN`, `Infinity` or
|
||||
// `-Infinity`, since those are not supported in JSON. This also cannot
|
||||
// represent large Int64 values, since JSON format generally does not
|
||||
// support them in its number type.
|
||||
double number_value = 2;
|
||||
|
||||
// Represents a JSON string.
|
||||
string string_value = 3;
|
||||
|
||||
// Represents a JSON boolean (`true` or `false` literal in JSON).
|
||||
bool bool_value = 4;
|
||||
|
||||
// Represents a JSON object.
|
||||
Struct struct_value = 5;
|
||||
|
||||
// Represents a JSON array.
|
||||
ListValue list_value = 6;
|
||||
}
|
||||
}
|
||||
|
||||
// Represents a JSON `null`.
|
||||
//
|
||||
// `NullValue` is a sentinel, using an enum with only one value to represent
|
||||
// the null value for the `Value` type union.
|
||||
//
|
||||
// A field of type `NullValue` with any value other than `0` is considered
|
||||
// invalid. Most ProtoJSON serializers will emit a Value with a `null_value` set
|
||||
// as a JSON `null` regardless of the integer value, and so will round trip to
|
||||
// a `0` value.
|
||||
enum NullValue {
|
||||
// Null value.
|
||||
NULL_VALUE = 0;
|
||||
}
|
||||
|
||||
// Represents a JSON array.
|
||||
message ListValue {
|
||||
// Repeated field of dynamically typed values.
|
||||
repeated Value values = 1;
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/protobuf/types/known/timestamppb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "TimestampProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// A Timestamp represents a point in time independent of any time zone or local
|
||||
// calendar, encoded as a count of seconds and fractions of seconds at
|
||||
// nanosecond resolution. The count is relative to an epoch at UTC midnight on
|
||||
// January 1, 1970, in the proleptic Gregorian calendar which extends the
|
||||
// Gregorian calendar backwards to year one.
|
||||
//
|
||||
// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
|
||||
// second table is needed for interpretation, using a [24-hour linear
|
||||
// smear](https://developers.google.com/time/smear).
|
||||
//
|
||||
// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
|
||||
// restricting to that range, we ensure that we can convert to and from [RFC
|
||||
// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
|
||||
//
|
||||
// # Examples
|
||||
//
|
||||
// Example 1: Compute Timestamp from POSIX `time()`.
|
||||
//
|
||||
// Timestamp timestamp;
|
||||
// timestamp.set_seconds(time(NULL));
|
||||
// timestamp.set_nanos(0);
|
||||
//
|
||||
// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
|
||||
//
|
||||
// struct timeval tv;
|
||||
// gettimeofday(&tv, NULL);
|
||||
//
|
||||
// Timestamp timestamp;
|
||||
// timestamp.set_seconds(tv.tv_sec);
|
||||
// timestamp.set_nanos(tv.tv_usec * 1000);
|
||||
//
|
||||
// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
|
||||
//
|
||||
// FILETIME ft;
|
||||
// GetSystemTimeAsFileTime(&ft);
|
||||
// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
||||
//
|
||||
// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
|
||||
// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
|
||||
// Timestamp timestamp;
|
||||
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
|
||||
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
|
||||
//
|
||||
// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
|
||||
//
|
||||
// long millis = System.currentTimeMillis();
|
||||
//
|
||||
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
|
||||
// .setNanos((int) ((millis % 1000) * 1000000)).build();
|
||||
//
|
||||
// Example 5: Compute Timestamp from Java `Instant.now()`.
|
||||
//
|
||||
// Instant now = Instant.now();
|
||||
//
|
||||
// Timestamp timestamp =
|
||||
// Timestamp.newBuilder().setSeconds(now.getEpochSecond())
|
||||
// .setNanos(now.getNano()).build();
|
||||
//
|
||||
// Example 6: Compute Timestamp from current time in Python.
|
||||
//
|
||||
// timestamp = Timestamp()
|
||||
// timestamp.GetCurrentTime()
|
||||
//
|
||||
// # JSON Mapping
|
||||
//
|
||||
// In JSON format, the Timestamp type is encoded as a string in the
|
||||
// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
|
||||
// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
|
||||
// where {year} is always expressed using four digits while {month}, {day},
|
||||
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
||||
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
||||
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
||||
// is required. A ProtoJSON serializer should always use UTC (as indicated by
|
||||
// "Z") when printing the Timestamp type and a ProtoJSON parser should be
|
||||
// able to accept both UTC and other timezones (as indicated by an offset).
|
||||
//
|
||||
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
||||
// 01:30 UTC on January 15, 2017.
|
||||
//
|
||||
// In JavaScript, one can convert a Date object to this format using the
|
||||
// standard
|
||||
// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
|
||||
// method. In Python, a standard `datetime.datetime` object can be converted
|
||||
// to this format using
|
||||
// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
|
||||
// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
|
||||
// the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||
// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()
|
||||
// ) to obtain a formatter capable of generating timestamps in this format.
|
||||
//
|
||||
message Timestamp {
|
||||
// Represents seconds of UTC time since Unix epoch 1970-01-01T00:00:00Z. Must
|
||||
// be between -62135596800 and 253402300799 inclusive (which corresponds to
|
||||
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z).
|
||||
int64 seconds = 1;
|
||||
|
||||
// Non-negative fractions of a second at nanosecond resolution. This field is
|
||||
// the nanosecond portion of the duration, not an alternative to seconds.
|
||||
// Negative second values with fractions must still have non-negative nanos
|
||||
// values that count forward in time. Must be between 0 and 999,999,999
|
||||
// inclusive.
|
||||
int32 nanos = 2;
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/source_context.proto";
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "TypeProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
option go_package = "google.golang.org/protobuf/types/known/typepb";
|
||||
|
||||
// A protocol buffer message type.
|
||||
//
|
||||
// New usages of this message as an alternative to DescriptorProto are strongly
|
||||
// discouraged. This message does not reliability preserve all information
|
||||
// necessary to model the schema and preserve semantics. Instead make use of
|
||||
// FileDescriptorSet which preserves the necessary information.
|
||||
message Type {
|
||||
// The fully qualified message name.
|
||||
string name = 1;
|
||||
// The list of fields.
|
||||
repeated Field fields = 2;
|
||||
// The list of types appearing in `oneof` definitions in this type.
|
||||
repeated string oneofs = 3;
|
||||
// The protocol buffer options.
|
||||
repeated Option options = 4;
|
||||
// The source context.
|
||||
SourceContext source_context = 5;
|
||||
// The source syntax.
|
||||
Syntax syntax = 6;
|
||||
// The source edition string, only valid when syntax is SYNTAX_EDITIONS.
|
||||
string edition = 7;
|
||||
}
|
||||
|
||||
// A single field of a message type.
|
||||
//
|
||||
// New usages of this message as an alternative to FieldDescriptorProto are
|
||||
// strongly discouraged. This message does not reliability preserve all
|
||||
// information necessary to model the schema and preserve semantics. Instead
|
||||
// make use of FileDescriptorSet which preserves the necessary information.
|
||||
message Field {
|
||||
// Basic field types.
|
||||
enum Kind {
|
||||
// Field type unknown.
|
||||
TYPE_UNKNOWN = 0;
|
||||
// Field type double.
|
||||
TYPE_DOUBLE = 1;
|
||||
// Field type float.
|
||||
TYPE_FLOAT = 2;
|
||||
// Field type int64.
|
||||
TYPE_INT64 = 3;
|
||||
// Field type uint64.
|
||||
TYPE_UINT64 = 4;
|
||||
// Field type int32.
|
||||
TYPE_INT32 = 5;
|
||||
// Field type fixed64.
|
||||
TYPE_FIXED64 = 6;
|
||||
// Field type fixed32.
|
||||
TYPE_FIXED32 = 7;
|
||||
// Field type bool.
|
||||
TYPE_BOOL = 8;
|
||||
// Field type string.
|
||||
TYPE_STRING = 9;
|
||||
// Field type group. Proto2 syntax only, and deprecated.
|
||||
TYPE_GROUP = 10;
|
||||
// Field type message.
|
||||
TYPE_MESSAGE = 11;
|
||||
// Field type bytes.
|
||||
TYPE_BYTES = 12;
|
||||
// Field type uint32.
|
||||
TYPE_UINT32 = 13;
|
||||
// Field type enum.
|
||||
TYPE_ENUM = 14;
|
||||
// Field type sfixed32.
|
||||
TYPE_SFIXED32 = 15;
|
||||
// Field type sfixed64.
|
||||
TYPE_SFIXED64 = 16;
|
||||
// Field type sint32.
|
||||
TYPE_SINT32 = 17;
|
||||
// Field type sint64.
|
||||
TYPE_SINT64 = 18;
|
||||
}
|
||||
|
||||
// Whether a field is optional, required, or repeated.
|
||||
enum Cardinality {
|
||||
// For fields with unknown cardinality.
|
||||
CARDINALITY_UNKNOWN = 0;
|
||||
// For optional fields.
|
||||
CARDINALITY_OPTIONAL = 1;
|
||||
// For required fields. Proto2 syntax only.
|
||||
CARDINALITY_REQUIRED = 2;
|
||||
// For repeated fields.
|
||||
CARDINALITY_REPEATED = 3;
|
||||
}
|
||||
|
||||
// The field type.
|
||||
Kind kind = 1;
|
||||
// The field cardinality.
|
||||
Cardinality cardinality = 2;
|
||||
// The field number.
|
||||
int32 number = 3;
|
||||
// The field name.
|
||||
string name = 4;
|
||||
// The field type URL, without the scheme, for message or enumeration
|
||||
// types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
|
||||
string type_url = 6;
|
||||
// The index of the field type in `Type.oneofs`, for message or enumeration
|
||||
// types. The first type has index 1; zero means the type is not in the list.
|
||||
int32 oneof_index = 7;
|
||||
// Whether to use alternative packed wire representation.
|
||||
bool packed = 8;
|
||||
// The protocol buffer options.
|
||||
repeated Option options = 9;
|
||||
// The field JSON name.
|
||||
string json_name = 10;
|
||||
// The string value of the default value of this field. Proto2 syntax only.
|
||||
string default_value = 11;
|
||||
}
|
||||
|
||||
// Enum type definition.
|
||||
//
|
||||
// New usages of this message as an alternative to EnumDescriptorProto are
|
||||
// strongly discouraged. This message does not reliability preserve all
|
||||
// information necessary to model the schema and preserve semantics. Instead
|
||||
// make use of FileDescriptorSet which preserves the necessary information.
|
||||
message Enum {
|
||||
// Enum type name.
|
||||
string name = 1;
|
||||
// Enum value definitions.
|
||||
repeated EnumValue enumvalue = 2;
|
||||
// Protocol buffer options.
|
||||
repeated Option options = 3;
|
||||
// The source context.
|
||||
SourceContext source_context = 4;
|
||||
// The source syntax.
|
||||
Syntax syntax = 5;
|
||||
// The source edition string, only valid when syntax is SYNTAX_EDITIONS.
|
||||
string edition = 6;
|
||||
}
|
||||
|
||||
// Enum value definition.
|
||||
//
|
||||
// New usages of this message as an alternative to EnumValueDescriptorProto are
|
||||
// strongly discouraged. This message does not reliability preserve all
|
||||
// information necessary to model the schema and preserve semantics. Instead
|
||||
// make use of FileDescriptorSet which preserves the necessary information.
|
||||
message EnumValue {
|
||||
// Enum value name.
|
||||
string name = 1;
|
||||
// Enum value number.
|
||||
int32 number = 2;
|
||||
// Protocol buffer options.
|
||||
repeated Option options = 3;
|
||||
}
|
||||
|
||||
// A protocol buffer option, which can be attached to a message, field,
|
||||
// enumeration, etc.
|
||||
//
|
||||
// New usages of this message as an alternative to FileOptions, MessageOptions,
|
||||
// FieldOptions, EnumOptions, EnumValueOptions, ServiceOptions, or MethodOptions
|
||||
// are strongly discouraged.
|
||||
message Option {
|
||||
// The option's name. For protobuf built-in options (options defined in
|
||||
// descriptor.proto), this is the short name. For example, `"map_entry"`.
|
||||
// For custom options, it should be the fully-qualified name. For example,
|
||||
// `"google.api.http"`.
|
||||
string name = 1;
|
||||
// The option's value packed in an Any message. If the value is a primitive,
|
||||
// the corresponding wrapper type defined in google/protobuf/wrappers.proto
|
||||
// should be used. If the value is an enum, it should be stored as an int32
|
||||
// value using the google.protobuf.Int32Value type.
|
||||
Any value = 2;
|
||||
}
|
||||
|
||||
// The syntax in which a protocol buffer element is defined.
|
||||
enum Syntax {
|
||||
// Syntax `proto2`.
|
||||
SYNTAX_PROTO2 = 0;
|
||||
// Syntax `proto3`.
|
||||
SYNTAX_PROTO3 = 1;
|
||||
// Syntax `editions`.
|
||||
SYNTAX_EDITIONS = 2;
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// https://developers.google.com/protocol-buffers/
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Wrappers for primitive (non-message) types. These types were needed
|
||||
// for legacy reasons and are not recommended for use in new APIs.
|
||||
//
|
||||
// Historically these wrappers were useful to have presence on proto3 primitive
|
||||
// fields, but proto3 syntax has been updated to support the `optional` keyword.
|
||||
// Using that keyword is now the strongly preferred way to add presence to
|
||||
// proto3 primitive fields.
|
||||
//
|
||||
// A secondary usecase was to embed primitives in the `google.protobuf.Any`
|
||||
// type: it is now recommended that you embed your value in your own wrapper
|
||||
// message which can be specifically documented.
|
||||
//
|
||||
// These wrappers have no meaningful use within repeated fields as they lack
|
||||
// the ability to detect presence on individual elements.
|
||||
// These wrappers have no meaningful use within a map or a oneof since
|
||||
// individual entries of a map or fields of a oneof can already detect presence.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.protobuf;
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/protobuf/types/known/wrapperspb";
|
||||
option java_package = "com.google.protobuf";
|
||||
option java_outer_classname = "WrappersProto";
|
||||
option java_multiple_files = true;
|
||||
option objc_class_prefix = "GPB";
|
||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
||||
|
||||
// Wrapper message for `double`.
|
||||
//
|
||||
// The JSON representation for `DoubleValue` is JSON number.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message DoubleValue {
|
||||
// The double value.
|
||||
double value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `float`.
|
||||
//
|
||||
// The JSON representation for `FloatValue` is JSON number.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message FloatValue {
|
||||
// The float value.
|
||||
float value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `int64`.
|
||||
//
|
||||
// The JSON representation for `Int64Value` is JSON string.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message Int64Value {
|
||||
// The int64 value.
|
||||
int64 value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `uint64`.
|
||||
//
|
||||
// The JSON representation for `UInt64Value` is JSON string.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message UInt64Value {
|
||||
// The uint64 value.
|
||||
uint64 value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `int32`.
|
||||
//
|
||||
// The JSON representation for `Int32Value` is JSON number.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message Int32Value {
|
||||
// The int32 value.
|
||||
int32 value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `uint32`.
|
||||
//
|
||||
// The JSON representation for `UInt32Value` is JSON number.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message UInt32Value {
|
||||
// The uint32 value.
|
||||
uint32 value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `bool`.
|
||||
//
|
||||
// The JSON representation for `BoolValue` is JSON `true` and `false`.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message BoolValue {
|
||||
// The bool value.
|
||||
bool value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `string`.
|
||||
//
|
||||
// The JSON representation for `StringValue` is JSON string.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message StringValue {
|
||||
// The string value.
|
||||
string value = 1;
|
||||
}
|
||||
|
||||
// Wrapper message for `bytes`.
|
||||
//
|
||||
// The JSON representation for `BytesValue` is JSON string.
|
||||
//
|
||||
// Not recommended for use in new APIs, but still useful for legacy APIs and
|
||||
// has no plan to be removed.
|
||||
message BytesValue {
|
||||
// The bytes value.
|
||||
bytes value = 1;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
syntax = "proto3";
|
||||
package org.graphofliberty.inference;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
message OntologyLoadRequest {
|
||||
string path = 1;
|
||||
bool infer = 2;
|
||||
}
|
||||
|
||||
message OntologyLoadResponse {
|
||||
uint64 old_size = 1;
|
||||
uint64 input_size = 2;
|
||||
uint64 inferences = 3;
|
||||
uint64 new_size = 4;
|
||||
}
|
||||
|
||||
message OntologyClearResponse {
|
||||
uint64 size = 1;
|
||||
}
|
||||
|
||||
message OntologyQueryRequest {
|
||||
optional string turtle = 1;
|
||||
optional string sparql_query = 2;
|
||||
map<string, string> prefixes = 3;
|
||||
optional string base = 4;
|
||||
bool inferences_only = 5;
|
||||
}
|
||||
|
||||
message OntologyQueryResponse {
|
||||
string results = 1;
|
||||
}
|
||||
|
||||
service Ontology {
|
||||
rpc Load(OntologyLoadRequest) returns (OntologyLoadResponse);
|
||||
rpc Clear(google.protobuf.Empty) returns (OntologyClearResponse);
|
||||
rpc Query(OntologyQueryRequest) returns (OntologyQueryResponse);
|
||||
}
|
||||
+6
-4
@@ -4,21 +4,23 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
#gl-ldp.workspace = true
|
||||
gl-graph.workspace = true
|
||||
gl-inference.workspace = true
|
||||
gl-search.workspace = true
|
||||
ldp.workspace = true
|
||||
|
||||
clap.workspace = true
|
||||
color-eyre.workspace = true
|
||||
csv = "1.4"
|
||||
http.workspace = true
|
||||
iced.workspace = true
|
||||
ldp.workspace = true
|
||||
rfd.workspace = true
|
||||
oxigraph.workspace = true
|
||||
oxilangtag.workspace = true
|
||||
tar.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
tonic.workspace = true
|
||||
tracing.workspace = true
|
||||
tracing-appender.workspace = true
|
||||
tracing-futures.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
url.workspace = true
|
||||
+716
-352
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Args)]
|
||||
pub(crate) struct QueryArgs {
|
||||
#[arg(short, long, value_name = "DATASET PATH")]
|
||||
pub(crate) dataset_path: Option<PathBuf>,
|
||||
|
||||
#[arg(short, long, value_name = "QUERY PATH")]
|
||||
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)]
|
||||
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,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
pub(crate) enum Command {
|
||||
Query(QueryArgs),
|
||||
Search(SearchArgs),
|
||||
Reindex,
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(version, long_about = None)]
|
||||
pub(crate) struct AppArgs {
|
||||
#[command(subcommand)]
|
||||
pub(crate) command: Option<Command>,
|
||||
}
|
||||
+22
-1
@@ -11,7 +11,10 @@ pub(crate) enum Error {
|
||||
Storage(#[from] oxigraph::store::StorageError),
|
||||
|
||||
#[error(transparent)]
|
||||
IriParse(#[from] oxigraph::model::IriParseError),
|
||||
ParseIri(#[from] oxigraph::model::IriParseError),
|
||||
|
||||
#[error(transparent)]
|
||||
ParseUrl(#[from] url::ParseError),
|
||||
|
||||
#[error(transparent)]
|
||||
RdfSyntax(#[from] oxigraph::io::RdfSyntaxError),
|
||||
@@ -19,6 +22,9 @@ pub(crate) enum Error {
|
||||
#[error(transparent)]
|
||||
ParseInt(#[from] std::num::ParseIntError),
|
||||
|
||||
#[error(transparent)]
|
||||
Graph(#[from] gl_graph::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
Search(#[from] gl_search::SearchError),
|
||||
|
||||
@@ -33,4 +39,19 @@ pub(crate) enum Error {
|
||||
|
||||
#[error(transparent)]
|
||||
Join(#[from] tokio::task::JoinError),
|
||||
|
||||
#[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),
|
||||
}
|
||||
|
||||
+188
-5
@@ -1,29 +1,212 @@
|
||||
mod app;
|
||||
mod args;
|
||||
mod error;
|
||||
mod rdf;
|
||||
mod windows;
|
||||
mod widget;
|
||||
mod navigator;
|
||||
mod rdf;
|
||||
mod tasks;
|
||||
mod theme;
|
||||
mod widget;
|
||||
|
||||
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 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 tracing_subscriber::fmt::format::FmtSpan;
|
||||
use url::Url;
|
||||
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
let appender = tracing_appender::rolling::never("/tmp", "publisher-log");
|
||||
tracing_subscriber::registry()
|
||||
.with(fmt::layer().with_span_events(FmtSpan::CLOSE).with_writer(appender))
|
||||
.with(
|
||||
fmt::layer()
|
||||
.with_span_events(FmtSpan::CLOSE)
|
||||
.with_writer(appender),
|
||||
)
|
||||
.with(EnvFilter::from_default_env())
|
||||
.init();
|
||||
color_eyre::install()?;
|
||||
|
||||
let args = AppArgs::parse();
|
||||
match args.command {
|
||||
Some(Command::Query(args)) => {
|
||||
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
|
||||
};
|
||||
|
||||
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()
|
||||
.name("inference-client")
|
||||
.build()?;
|
||||
|
||||
runtime.block_on(async {
|
||||
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)) => {
|
||||
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()?;
|
||||
writer.commit()
|
||||
})?;
|
||||
|
||||
let runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.name("reindex")
|
||||
.build()?;
|
||||
|
||||
runtime.block_on(async {
|
||||
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();
|
||||
}
|
||||
});
|
||||
Ok::<_, crate::error::Error>(())
|
||||
})?;
|
||||
|
||||
let mut writer = runtime.block_on(async move {
|
||||
let http_client = ClientBuilder::new(Client::new())
|
||||
.with(BasicAuthMiddleware::new(
|
||||
"fedoraAdmin".to_string(),
|
||||
Some("fedoraAdmin".to_string()),
|
||||
))
|
||||
.build();
|
||||
|
||||
let starting_url = Url::parse("http://fedora.quill.lan/rest/")?;
|
||||
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) => {
|
||||
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 triple_count = async {
|
||||
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 graph_with_inferences = client.run_inference(&graph).await?;
|
||||
for document in indexer.graph(&graph_with_inferences) {
|
||||
writer.add_document(document)?;
|
||||
}
|
||||
|
||||
Ok::<usize, crate::error::Error>(graph_with_inferences.len())
|
||||
}
|
||||
.instrument(span.clone())
|
||||
.await?;
|
||||
span.record("triples", triple_count);
|
||||
|
||||
Ok::<_, crate::error::Error>(writer)
|
||||
})?;
|
||||
|
||||
debug_span!("Commit").in_scope(|| writer.commit())?;
|
||||
}
|
||||
None => {
|
||||
iced::daemon(Publisher::new, Publisher::update, Publisher::view)
|
||||
.title(Publisher::title)
|
||||
.subscription(Publisher::subscription)
|
||||
.run()?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use oxigraph::model::{NamedNode, Quad, Term};
|
||||
use oxigraph::model::vocab::{rdf, xsd};
|
||||
use oxigraph::model::{NamedNode, Quad, Term};
|
||||
|
||||
pub fn quad_into_term(quad: Quad) -> Term {
|
||||
quad.object
|
||||
@@ -51,11 +51,17 @@ pub fn term_to_boolean(term: &Term) -> Option<bool> {
|
||||
}
|
||||
|
||||
pub fn term_to_u64(term: &Term) -> Option<u64> {
|
||||
if let Term::Literal(literal) = term &&
|
||||
(literal.datatype() == xsd::NON_NEGATIVE_INTEGER || literal.datatype() == xsd::INTEGER) {
|
||||
let value: u64 = literal.value().parse().expect("Failed to parse u64 from ontology. It ought to be a non-negative integer.");
|
||||
if let Term::Literal(literal) = term
|
||||
&& (literal.datatype() == xsd::NON_NEGATIVE_INTEGER || literal.datatype() == xsd::INTEGER)
|
||||
{
|
||||
let value: u64 = literal
|
||||
.value()
|
||||
.parse()
|
||||
.expect("Failed to parse u64 from ontology. It ought to be a non-negative integer.");
|
||||
Some(value)
|
||||
} else { None }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn term_into_u64(term: Term) -> Option<u64> {
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CurieHelper {
|
||||
prefixes: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
impl CurieHelper {
|
||||
pub fn new(prefixes: BTreeMap<String, String>) -> Self {
|
||||
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}"));
|
||||
}
|
||||
|
||||
for (name, base) in &self.prefixes {
|
||||
if let Some(local_name) = iri.strip_prefix(base) {
|
||||
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(':')?;
|
||||
|
||||
if prefix == "" && let Some(base) = base {
|
||||
Some(format!("{base}{name}"))
|
||||
} else {
|
||||
self.prefixes
|
||||
.get(prefix)
|
||||
.map(|base| format!("{base}{name}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
use std::sync::LazyLock;
|
||||
use oxigraph::model::Term;
|
||||
use oxilangtag::LanguageTag;
|
||||
|
||||
pub const ENGLISH_PRIMARY: &str = "en";
|
||||
|
||||
pub static ENGLISH_OR_UNTAGGED: LazyLock<LanguageCondition> = LazyLock::new(|| {
|
||||
LanguageCondition::ExactMatchOrUntagged(LanguageTag::parse(ENGLISH_PRIMARY.to_string()).unwrap())
|
||||
});
|
||||
|
||||
pub enum LanguageCondition {
|
||||
ExactMatchOnly(LanguageTag<String>),
|
||||
ExactMatchOrUntagged(LanguageTag<String>),
|
||||
UntaggedOnly,
|
||||
AnyOrNone,
|
||||
}
|
||||
|
||||
impl LanguageCondition {
|
||||
pub fn primary_matches_term(&self, term: &Term) -> bool {
|
||||
if let Term::Literal(literal) = term {
|
||||
let tag = literal.language()
|
||||
.map(LanguageTag::parse_and_normalize)
|
||||
.and_then(Result::ok);
|
||||
|
||||
match (tag, self) {
|
||||
(Some(language), LanguageCondition::ExactMatchOnly(expectation)) |
|
||||
(Some(language), LanguageCondition::ExactMatchOrUntagged(expectation)) => language.primary_language() == expectation.primary_language(),
|
||||
(None, LanguageCondition::ExactMatchOrUntagged(_)) => true,
|
||||
(None, LanguageCondition::UntaggedOnly) => true,
|
||||
(_, LanguageCondition::AnyOrNone) => true,
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_filter_expression(&self, var: &str) -> String {
|
||||
match self {
|
||||
LanguageCondition::ExactMatchOnly(language) => format!(r#"FILTER(langMATCHES(LANG(?{var}), "{language}"))"#),
|
||||
LanguageCondition::ExactMatchOrUntagged(language) => format!(r#"FILTER(langMATCHES(LANG(?{var}), "{language}") || !hasLANG(?{var}))"#),
|
||||
LanguageCondition::UntaggedOnly => format!("FILTER(!hasLANG(?{var}))"),
|
||||
LanguageCondition::AnyOrNone => "".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
use oxigraph::model::{Dataset, GraphName, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Term};
|
||||
use oxigraph::sparql::SparqlEvaluator;
|
||||
use oxigraph::store::Store;
|
||||
use tracing::{debug, debug_span};
|
||||
use crate::error;
|
||||
use crate::rdf::vocab::owl;
|
||||
|
||||
const INFERENCE_GRAPH: NamedNodeRef = NamedNodeRef::new_unchecked("https://graphofliberty.org/inference");
|
||||
const RDF_SCHEMA: NamedNodeRef = NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#");
|
||||
|
||||
pub fn same_as(store: &mut Store) -> error::Result<()> {
|
||||
let _span = debug_span!("Materialize owl:sameAs").entered();
|
||||
|
||||
let additional_quads = store
|
||||
.quads_for_pattern(None, Some(owl::SAME_AS), None, None)
|
||||
.filter_map(Result::ok)
|
||||
.fold(Dataset::new(), |mut new_dataset, alias| {
|
||||
if let NamedOrBlankNode::NamedNode(x) = alias.subject
|
||||
&& let Term::NamedNode(y) = alias.object
|
||||
{
|
||||
for mut quad in store.quads_for_pattern(
|
||||
Some(NamedOrBlankNodeRef::NamedNode(x.as_ref())),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
).filter_map(Result::ok) {
|
||||
quad.subject = NamedOrBlankNode::NamedNode(y.clone());
|
||||
quad.graph_name = GraphName::NamedNode(INFERENCE_GRAPH.into_owned());
|
||||
new_dataset.insert(quad.as_ref());
|
||||
}
|
||||
|
||||
for mut quad in store.quads_for_pattern(
|
||||
Some(NamedOrBlankNodeRef::NamedNode(y.as_ref())),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
).filter_map(Result::ok) {
|
||||
quad.subject = NamedOrBlankNode::NamedNode(x.clone());
|
||||
quad.graph_name = GraphName::NamedNode(INFERENCE_GRAPH.into_owned());
|
||||
new_dataset.insert(quad.as_ref());
|
||||
}
|
||||
}
|
||||
new_dataset
|
||||
});
|
||||
|
||||
let old_size = store.len()?;
|
||||
store.extend(&additional_quads)?;
|
||||
let new_size = store.len()?;
|
||||
|
||||
if new_size > old_size {
|
||||
let difference = new_size - old_size;
|
||||
debug!(?old_size, ?new_size, ?difference, "same_as");
|
||||
same_as(store)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn super_properties(store: &mut Store) -> error::Result<()> {
|
||||
let _span = debug_span!("Materialize rdfs:subPropertyOf").entered();
|
||||
|
||||
let update = SparqlEvaluator::new()
|
||||
.with_prefix("rdfs", RDF_SCHEMA.as_str())?
|
||||
.with_prefix("inference", INFERENCE_GRAPH.as_str())?
|
||||
.parse_update(r#"INSERT {
|
||||
GRAPH inference: {
|
||||
?property rdfs:subPropertyOf ?parent .
|
||||
?subject ?parent ?object .
|
||||
}
|
||||
} WHERE {
|
||||
GRAPH ?g1 { ?property rdfs:subPropertyOf+ ?parent }
|
||||
OPTIONAL { GRAPH ?g2 { ?subject ?property ?object } }
|
||||
}"#)?;
|
||||
|
||||
let old_size = store.len()?;
|
||||
update.on_store(&store).execute()?;
|
||||
let new_size = store.len()?;
|
||||
|
||||
if new_size > old_size {
|
||||
let difference = new_size - old_size;
|
||||
debug!(?old_size, ?new_size, ?difference, "super_properties");
|
||||
super_properties(store)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn super_classes(store: &mut Store) -> error::Result<()> {
|
||||
let _span = debug_span!("Materialize rdfs:subClassOf").entered();
|
||||
|
||||
let update = SparqlEvaluator::new()
|
||||
.with_prefix("rdfs", RDF_SCHEMA.as_str())?
|
||||
.with_prefix("inference", INFERENCE_GRAPH.as_str())?
|
||||
.parse_update(r#"INSERT {
|
||||
GRAPH inference: {
|
||||
?class rdfs:subClassOf ?parent .
|
||||
?item a ?parent .
|
||||
}
|
||||
} WHERE {
|
||||
GRAPH ?g1 { ?class rdfs:subClassOf+ ?parent }
|
||||
OPTIONAL { GRAPH ?g2 { ?item a ?class } }
|
||||
}"#)?;
|
||||
|
||||
let old_size = store.len()?;
|
||||
update.on_store(&store).execute()?;
|
||||
let new_size = store.len()?;
|
||||
|
||||
if new_size > old_size {
|
||||
let difference = new_size - old_size;
|
||||
debug!(?old_size, ?new_size, ?difference, "super_classes");
|
||||
super_classes(store)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
pub(crate) mod ontology;
|
||||
pub(crate) mod term_helper;
|
||||
pub mod vocab;
|
||||
pub(crate) mod materialize;
|
||||
pub(crate) mod conversion;
|
||||
pub(crate) mod language;
|
||||
pub(crate) mod curie;
|
||||
//pub(crate) mod ontology;
|
||||
pub(crate) mod term_helper;
|
||||
|
||||
@@ -1,403 +0,0 @@
|
||||
use crate::error;
|
||||
use crate::rdf::vocab::gl;
|
||||
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 std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
use std::fmt::Display;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::LazyLock;
|
||||
use iced::futures::TryFutureExt;
|
||||
use oxigraph::store::Store;
|
||||
use tracing::{debug_span, field};
|
||||
use crate::rdf::{conversion, materialize};
|
||||
use crate::rdf::language::LanguageCondition;
|
||||
|
||||
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/"),
|
||||
("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>,
|
||||
materialize_inferences: bool,
|
||||
}
|
||||
|
||||
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 materialize_inferences(mut self) -> Self {
|
||||
self.materialize_inferences = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> error::Result<Ontology> {
|
||||
let mut store = if let Some(path) = self.path {
|
||||
if self.materialize_inferences {
|
||||
Store::open(path)
|
||||
} else {
|
||||
Store::open_read_only(path)
|
||||
}
|
||||
} else {
|
||||
Store::new()
|
||||
}?;
|
||||
|
||||
let prefixes = PREFIXES
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect::<HashMap<String, String>>();
|
||||
|
||||
if self.materialize_inferences {
|
||||
materialize::same_as(&mut store)?;
|
||||
materialize::super_properties(&mut store)?;
|
||||
materialize::super_classes(&mut store)?;
|
||||
debug_span!("Optimize Ontology").in_scope(|| store.optimize())?;
|
||||
}
|
||||
|
||||
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,
|
||||
materialize_inferences: false,
|
||||
}
|
||||
}
|
||||
|
||||
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 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> {
|
||||
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 searchable_classes(&self, language: &LanguageCondition) -> BTreeSet<LabeledIri> {
|
||||
self.store.quads_for_pattern(None, Some(rdf::TYPE), Some(gl::SEARCHABLE_CLASS.into()), None)
|
||||
.filter_map(Result::ok)
|
||||
.filter_map(|quad| {
|
||||
let label = self.store.quads_for_pattern(Some(quad.subject.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();
|
||||
if let Some(label) = label && let NamedOrBlankNode::NamedNode(subject) = quad.subject {
|
||||
Some(LabeledIri {
|
||||
iri: subject,
|
||||
label,
|
||||
})
|
||||
} else { None }
|
||||
}).collect()
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn template_triples<'a>(
|
||||
&'a self,
|
||||
class: NamedNodeRef<'a>,
|
||||
subject: NamedNodeRef<'_>,
|
||||
) -> Option<impl Iterator<Item = Triple>> {
|
||||
if let Some(quad) = self
|
||||
.store
|
||||
.quads_for_pattern(
|
||||
Some(NamedOrBlankNodeRef::NamedNode(class)),
|
||||
Some(gl::TEMPLATE),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.filter_map(Result::ok)
|
||||
.next()
|
||||
{
|
||||
if let Term::BlankNode(blank_node) = quad.object {
|
||||
let iter = self
|
||||
.store
|
||||
.quads_for_pattern(Some(NamedOrBlankNodeRef::BlankNode(blank_node.as_ref())), None, None, None)
|
||||
.filter_map(Result::ok)
|
||||
.map(Triple::from)
|
||||
.map(move |mut triple| {
|
||||
triple.subject = NamedOrBlankNode::NamedNode(subject.into_owned());
|
||||
triple
|
||||
});
|
||||
Some(iter)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,8 @@ impl<'a> TermHelper<'a> {
|
||||
match self.term.as_ref() {
|
||||
TermRef::Literal(literal) => literal.value(),
|
||||
TermRef::NamedNode(node) => node.as_str(),
|
||||
_ => unimplemented!(),
|
||||
TermRef::BlankNode(node) => node.as_str(),
|
||||
TermRef::Triple(_) => "«triple»",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +163,7 @@ impl<'a> TermHelperMut<'a> {
|
||||
*self.term = Term::Literal(new_literal)
|
||||
}
|
||||
TermRef::NamedNode(_) => *self.term = Term::NamedNode(NamedNode::new_unchecked(value)),
|
||||
TermRef::BlankNode(_) => *self.term = Term::NamedNode(NamedNode::new_unchecked(value)),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
pub mod gl {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const TEMPLATE: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/template");
|
||||
|
||||
pub const INDEXED_BY_FIELD: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/indexedByField");
|
||||
|
||||
pub const CATEGORY_ID: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/categoryId");
|
||||
|
||||
pub const SEARCHABLE_CLASS: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/SearchableClass");
|
||||
|
||||
pub const ENTITY: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/Entity");
|
||||
|
||||
pub const ASSOCIATED_PROPERTY: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/associatedProperty");
|
||||
|
||||
pub const READ_ONLY: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("https://graphofliberty.org/2026/04/ont/readOnly");
|
||||
}
|
||||
|
||||
pub mod owl {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const SAME_AS: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://www.w3.org/2002/07/owl#sameAs");
|
||||
}
|
||||
|
||||
pub mod rda {
|
||||
use oxigraph::model::NamedNodeRef;
|
||||
|
||||
pub const ENTITY: NamedNodeRef =
|
||||
NamedNodeRef::new_unchecked("http://rdaregistry.info/Elements/c/C10013");
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
pub mod text_input {
|
||||
use iced::{color, Theme};
|
||||
use iced::widget::text_input;
|
||||
use iced::widget::text_input::{Status, Style};
|
||||
use iced::{Theme, color};
|
||||
|
||||
pub fn required(invalid: bool) -> impl Fn(&Theme, Status) -> Style {
|
||||
move |theme: &Theme, status| {
|
||||
|
||||
+125
-36
@@ -1,12 +1,13 @@
|
||||
use iced::{alignment, keyboard, widget, Element, Event, Length, Rectangle, Size, Theme, Background, Border};
|
||||
use iced::advanced::{mouse, text, Shell, renderer};
|
||||
use gl_graph::CurieHelper;
|
||||
use iced::advanced::layout::{Limits, Node};
|
||||
use iced::advanced::widget::{Operation, Tree, tree};
|
||||
use iced::advanced::{Layout, Widget};
|
||||
use iced::advanced::widget::{tree, Tree};
|
||||
use iced::advanced::{Shell, mouse, renderer, text};
|
||||
use iced::clipboard::Content;
|
||||
use iced::mouse::{Cursor, Interaction};
|
||||
use iced::widget::text_input::{Catalog, Status, Style, StyleFn};
|
||||
use crate::rdf::curie::CurieHelper;
|
||||
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>,
|
||||
@@ -31,12 +32,19 @@ where
|
||||
Theme: Catalog,
|
||||
Renderer: text::Renderer,
|
||||
{
|
||||
pub fn new(curie_helper: &'a CurieHelper, placeholder: &str, base: Option<&str>, iri: &str) -> Self {
|
||||
let display_value = curie_helper.abbreviate(base, iri).unwrap_or_else(|| iri.to_string());
|
||||
let text_input = widget::TextInput::new(placeholder, &display_value);
|
||||
pub fn new(
|
||||
curie_helper: &'a CurieHelper,
|
||||
placeholder: &'a str,
|
||||
base: Option<&'a Url>,
|
||||
iri: &str,
|
||||
) -> Self {
|
||||
let display_value = curie_helper
|
||||
.abbreviate(base, iri)
|
||||
.unwrap_or_else(|| iri.to_string());
|
||||
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,
|
||||
@@ -44,7 +52,7 @@ where
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn align_x(mut self, alignment: impl Into<alignment::Horizontal>) -> Self {
|
||||
pub fn align_x(mut self, alignment: impl Into<text::Alignment>) -> Self {
|
||||
self.text_input = self.text_input.align_x(alignment);
|
||||
self
|
||||
}
|
||||
@@ -63,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);
|
||||
@@ -87,6 +94,12 @@ where
|
||||
self.text_input = self.text_input.style(style);
|
||||
self
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn id(mut self, id: impl Into<widget::Id>) -> Self {
|
||||
self.text_input = self.text_input.id(id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer> From<IriInput<'a, Message, Theme, Renderer>>
|
||||
@@ -94,14 +107,19 @@ for Element<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Message: Clone + 'a,
|
||||
Theme: Catalog + 'a,
|
||||
Renderer: text::Renderer + 'a,
|
||||
Renderer: text::Renderer + 'static,
|
||||
{
|
||||
fn from(value: IriInput<'a, Message, Theme, Renderer>) -> Self {
|
||||
Element::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iri_input<'a, Message, Theme, Renderer>(curie_helper: &'a CurieHelper, placeholder: &str, base: Option<&str>, iri: &str) -> IriInput<'a, Message, Theme, Renderer>
|
||||
pub fn iri_input<'a, Message, Theme, Renderer>(
|
||||
curie_helper: &'a CurieHelper,
|
||||
placeholder: &'a str,
|
||||
base: Option<&'a Url>,
|
||||
iri: &str,
|
||||
) -> IriInput<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Message: Clone,
|
||||
Theme: Catalog,
|
||||
@@ -110,22 +128,46 @@ where
|
||||
IriInput::new(curie_helper, placeholder, base, iri)
|
||||
}
|
||||
|
||||
impl <Message, Theme, Renderer> Widget<Message, Theme, Renderer> for IriInput<'_, Message, Theme, Renderer>
|
||||
impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
|
||||
for IriInput<'_, Message, Theme, Renderer>
|
||||
where
|
||||
Message: Clone,
|
||||
Theme: Catalog,
|
||||
Renderer: text::Renderer,
|
||||
Renderer: text::Renderer + 'static,
|
||||
{
|
||||
fn size(&self) -> Size<Length> {
|
||||
Widget::size(&self.text_input)
|
||||
}
|
||||
|
||||
fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &Limits) -> Node {
|
||||
Widget::layout(&mut self.text_input, &mut tree.children[0], renderer, limits)
|
||||
Widget::layout(
|
||||
&mut self.text_input,
|
||||
&mut tree.children[0],
|
||||
renderer,
|
||||
limits,
|
||||
)
|
||||
}
|
||||
|
||||
fn draw(&self, tree: &Tree, renderer: &mut Renderer, theme: &Theme, style: &renderer::Style, layout: Layout<'_>, cursor: Cursor, viewport: &Rectangle) {
|
||||
Widget::draw(&self.text_input, &tree.children[0], renderer, theme, style, layout, cursor, viewport)
|
||||
fn draw(
|
||||
&self,
|
||||
tree: &Tree,
|
||||
renderer: &mut Renderer,
|
||||
theme: &Theme,
|
||||
style: &renderer::Style,
|
||||
layout: Layout<'_>,
|
||||
cursor: Cursor,
|
||||
viewport: &Rectangle,
|
||||
) {
|
||||
Widget::draw(
|
||||
&self.text_input,
|
||||
&tree.children[0],
|
||||
renderer,
|
||||
theme,
|
||||
style,
|
||||
layout,
|
||||
cursor,
|
||||
viewport,
|
||||
)
|
||||
}
|
||||
|
||||
fn tag(&self) -> tree::Tag {
|
||||
@@ -143,7 +185,27 @@ where
|
||||
tree.diff_children(&mut [&mut self.text_input as &mut dyn Widget<_, _, _>]);
|
||||
}
|
||||
|
||||
fn update(&mut self, tree: &mut Tree, event: &Event, layout: Layout<'_>, cursor: Cursor, renderer: &Renderer, shell: &mut Shell<'_, Message>, viewport: &Rectangle) {
|
||||
fn operate(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
renderer: &Renderer,
|
||||
operation: &mut dyn Operation,
|
||||
) {
|
||||
self.text_input
|
||||
.operate(&mut tree.children[0], layout, renderer, operation);
|
||||
}
|
||||
|
||||
fn update(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
event: &Event,
|
||||
layout: Layout<'_>,
|
||||
cursor: Cursor,
|
||||
renderer: &Renderer,
|
||||
shell: &mut Shell<'_, Message>,
|
||||
viewport: &Rectangle,
|
||||
) {
|
||||
let state = tree.state.downcast_mut::<State>();
|
||||
|
||||
match event {
|
||||
@@ -151,41 +213,68 @@ where
|
||||
state.control = modifiers.control();
|
||||
state.shift = modifiers.shift();
|
||||
}
|
||||
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 {
|
||||
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
|
||||
{
|
||||
shell.publish(on_control_click.clone());
|
||||
shell.capture_event();
|
||||
}
|
||||
|
||||
if state.shift && let Some(on_shift_click) = &self.on_shift_click {
|
||||
if state.shift
|
||||
&& let Some(on_shift_click) = &self.on_shift_click
|
||||
{
|
||||
shell.publish(on_shift_click.clone());
|
||||
shell.capture_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Widget::update(&mut self.text_input, &mut tree.children[0], event, layout, cursor, renderer, shell, viewport);
|
||||
Widget::update(
|
||||
&mut self.text_input,
|
||||
&mut tree.children[0],
|
||||
event,
|
||||
layout,
|
||||
cursor,
|
||||
renderer,
|
||||
shell,
|
||||
viewport,
|
||||
);
|
||||
|
||||
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, tree: &Tree, layout: Layout<'_>, cursor: Cursor, viewport: &Rectangle, renderer: &Renderer) -> Interaction {
|
||||
fn mouse_interaction(
|
||||
&self,
|
||||
tree: &Tree,
|
||||
layout: Layout<'_>,
|
||||
cursor: Cursor,
|
||||
viewport: &Rectangle,
|
||||
renderer: &Renderer,
|
||||
) -> Interaction {
|
||||
let state = tree.state.downcast_ref::<State>();
|
||||
let interaction = if cursor.is_over(layout.bounds()) {
|
||||
if (state.control && self.on_control_click.is_some()) ||
|
||||
(state.shift && self.on_shift_click.is_some()) {
|
||||
if (state.control && self.on_control_click.is_some())
|
||||
|| (state.shift && self.on_shift_click.is_some())
|
||||
{
|
||||
Some(Interaction::Pointer)
|
||||
} else { None }
|
||||
} else { None };
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
interaction.unwrap_or_else(|| Widget::mouse_interaction(&self.text_input, tree, layout, cursor, viewport, renderer))
|
||||
interaction.unwrap_or_else(|| {
|
||||
Widget::mouse_interaction(&self.text_input, tree, layout, cursor, viewport, renderer)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
use iced::advanced::{mouse, text, Layout, Shell, Widget, overlay};
|
||||
use iced::{Element, Event, Length, Rectangle, Size, Vector};
|
||||
use iced::advanced::layout::{Limits, Node};
|
||||
use iced::advanced::renderer::Style;
|
||||
use iced::advanced::widget::{Operation, Tree};
|
||||
use iced::advanced::{Layout, Shell, Widget, mouse, overlay, text};
|
||||
use iced::mouse::Cursor;
|
||||
use iced::widget::text_input::Catalog;
|
||||
use iced::{Element, Event, Length, Rectangle, Size, Vector};
|
||||
|
||||
pub struct NavigationArea<'a, Message, Theme, Renderer>
|
||||
where
|
||||
@@ -56,7 +56,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn navigation_area<'a, Message, Theme, Renderer>(content: impl Into<Element<'a, Message, Theme, Renderer>>) -> NavigationArea<'a, Message, Theme, Renderer>
|
||||
pub fn navigation_area<'a, Message, Theme, Renderer>(
|
||||
content: impl Into<Element<'a, Message, Theme, Renderer>>,
|
||||
) -> NavigationArea<'a, Message, Theme, Renderer>
|
||||
where
|
||||
Message: Clone,
|
||||
Theme: Catalog,
|
||||
@@ -65,7 +67,8 @@ where
|
||||
NavigationArea::new(content)
|
||||
}
|
||||
|
||||
impl <Message, Theme, Renderer> Widget<Message, Theme, Renderer> for NavigationArea<'_, Message, Theme, Renderer>
|
||||
impl<Message, Theme, Renderer> Widget<Message, Theme, Renderer>
|
||||
for NavigationArea<'_, Message, Theme, Renderer>
|
||||
where
|
||||
Message: Clone,
|
||||
Theme: Catalog,
|
||||
@@ -81,7 +84,16 @@ where
|
||||
.layout(&mut tree.children[0], renderer, limits)
|
||||
}
|
||||
|
||||
fn draw(&self, tree: &Tree, renderer: &mut Renderer, theme: &Theme, style: &Style, layout: Layout<'_>, cursor: Cursor, viewport: &Rectangle) {
|
||||
fn draw(
|
||||
&self,
|
||||
tree: &Tree,
|
||||
renderer: &mut Renderer,
|
||||
theme: &Theme,
|
||||
style: &Style,
|
||||
layout: Layout<'_>,
|
||||
cursor: Cursor,
|
||||
viewport: &Rectangle,
|
||||
) {
|
||||
self.content.as_widget().draw(
|
||||
&tree.children[0],
|
||||
renderer,
|
||||
@@ -97,13 +109,28 @@ where
|
||||
tree.diff_children(std::slice::from_mut(&mut self.content));
|
||||
}
|
||||
|
||||
fn operate(&mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation) {
|
||||
fn operate(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
renderer: &Renderer,
|
||||
operation: &mut dyn Operation,
|
||||
) {
|
||||
self.content
|
||||
.as_widget_mut()
|
||||
.operate(&mut tree.children[0], layout, renderer, operation);
|
||||
}
|
||||
|
||||
fn update(&mut self, tree: &mut Tree, event: &Event, layout: Layout<'_>, cursor: Cursor, renderer: &Renderer, shell: &mut Shell<'_, Message>, viewport: &Rectangle) {
|
||||
fn update(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
event: &Event,
|
||||
layout: Layout<'_>,
|
||||
cursor: Cursor,
|
||||
renderer: &Renderer,
|
||||
shell: &mut Shell<'_, Message>,
|
||||
viewport: &Rectangle,
|
||||
) {
|
||||
self.content.as_widget_mut().update(
|
||||
&mut tree.children[0],
|
||||
event,
|
||||
|
||||
+4
-1
@@ -5,11 +5,14 @@ edition = "2024"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
#gl-graph.workspace = true
|
||||
|
||||
futures.workspace = true
|
||||
tantivy.workspace = true
|
||||
thiserror.workspace = true
|
||||
|
||||
#poppler-rs = "0.26.0-alpha.0"
|
||||
subtitler.workspace = true
|
||||
tracing.workspace = true
|
||||
#oxidize-pdf = { version = "1.6", features = ["ocr-tesseract"] }
|
||||
oxigraph.workspace = true
|
||||
#xml = "1.2"
|
||||
@@ -14,4 +14,13 @@ pub enum SearchError {
|
||||
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
#[error(transparent)]
|
||||
Parse(#[from] subtitler::error::ParseError),
|
||||
|
||||
#[error(transparent)]
|
||||
QueryEvaluation(#[from] oxigraph::sparql::QueryEvaluationError),
|
||||
|
||||
#[error(transparent)]
|
||||
SparqlSyntax(#[from] oxigraph::sparql::SparqlSyntaxError),
|
||||
}
|
||||
|
||||
+16
-17
@@ -1,13 +1,14 @@
|
||||
use std::fs;
|
||||
use crate::error;
|
||||
use crate::schema::Schema;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use tantivy::collector::TopDocs;
|
||||
use tantivy::directory::{ManagedDirectory, MmapDirectory};
|
||||
use tantivy::query::{BooleanQuery, Occur, QueryParser, TermQuery};
|
||||
use tantivy::schema::{Field, IndexRecordOption};
|
||||
use tantivy::schema::{Field, IndexRecordOption, OwnedValue};
|
||||
use tantivy::tokenizer::{LowerCaser, NgramTokenizer, TextAnalyzer, TokenizerManager};
|
||||
use tantivy::{Index, IndexReader, IndexWriter, ReloadPolicy, TantivyDocument, Term};
|
||||
use tantivy::{Document, Index, IndexReader, IndexWriter, ReloadPolicy, Term};
|
||||
use tracing::debug_span;
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -23,9 +24,7 @@ impl SearchIndexBuilder {
|
||||
|
||||
pub fn build(self) -> error::Result<SearchIndex> {
|
||||
let ngram_32 = NgramTokenizer::new(1, 32, false)?;
|
||||
let ngram_32_lowercase = TextAnalyzer::builder(ngram_32)
|
||||
.filter(LowerCaser)
|
||||
.build();
|
||||
let ngram_32_lowercase = TextAnalyzer::builder(ngram_32).filter(LowerCaser).build();
|
||||
|
||||
let tokenizer_manager = TokenizerManager::default();
|
||||
tokenizer_manager.register("ngram_32", ngram_32_lowercase);
|
||||
@@ -48,10 +47,7 @@ impl SearchIndexBuilder {
|
||||
.reload_policy(ReloadPolicy::OnCommitWithDelay)
|
||||
.try_into()?;
|
||||
|
||||
Ok(SearchIndex {
|
||||
index,
|
||||
reader,
|
||||
})
|
||||
Ok(SearchIndex { index, reader })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +61,7 @@ impl SearchIndex {
|
||||
SearchIndexBuilder::default()
|
||||
}
|
||||
|
||||
pub fn writer(&mut self) -> crate::Result<IndexWriter> {
|
||||
pub fn writer(&mut self) -> crate::Result<IndexWriter<HashMap<Field, OwnedValue>>> {
|
||||
Ok(self.index.writer(128 * 1024 * 1024)?)
|
||||
}
|
||||
|
||||
@@ -75,25 +71,24 @@ impl SearchIndex {
|
||||
user_query: &str,
|
||||
default_fields: Vec<Field>,
|
||||
limit: usize,
|
||||
) -> error::Result<Vec<TantivyDocument>> {
|
||||
) -> error::Result<Vec<HashMap<Field, OwnedValue>>> {
|
||||
let _enter = debug_span!("Search Query").entered();
|
||||
|
||||
let parser = QueryParser::for_index(&self.index, default_fields);
|
||||
let (user_query, _) = parser.parse_query_lenient(user_query);
|
||||
|
||||
let mut subqueries = vec![
|
||||
(Occur::Must, user_query)
|
||||
];
|
||||
let mut subqueries = vec![(Occur::Must, user_query)];
|
||||
|
||||
if let Some(type_) = type_ {
|
||||
let doc_type_term = Term::from_field_u64(Schema::type_field(), type_);
|
||||
let doc_type_term = Term::from_field_u64(Schema::discriminant_field(), type_);
|
||||
let doc_type_query = Box::new(TermQuery::new(doc_type_term, IndexRecordOption::Basic));
|
||||
subqueries.push((Occur::Must, doc_type_query));
|
||||
}
|
||||
|
||||
let query = BooleanQuery::new(subqueries);
|
||||
let searcher = self.reader.searcher();
|
||||
let results: Vec<TantivyDocument> = searcher.search(&query, &TopDocs::with_limit(limit).order_by_score())?
|
||||
let results = searcher
|
||||
.search(&query, &TopDocs::with_limit(limit).order_by_score())?
|
||||
.iter()
|
||||
.map(|(_, address)| searcher.doc(*address))
|
||||
.filter_map(Result::ok)
|
||||
@@ -101,3 +96,7 @@ impl SearchIndex {
|
||||
Ok(results)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_json(document: HashMap<Field, OwnedValue>) -> String {
|
||||
document.to_json(Schema::schema())
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,11 +1,12 @@
|
||||
mod error;
|
||||
mod index;
|
||||
mod schema;
|
||||
|
||||
pub use tantivy::TantivyDocument as SearchDocument;
|
||||
pub use tantivy::doc;
|
||||
pub use tantivy::schema::document::Value;
|
||||
pub mod subtitles;
|
||||
pub use tantivy;
|
||||
pub use tantivy::indexer::IndexWriter;
|
||||
pub use tantivy::schema::Field;
|
||||
pub use tantivy::schema::document::OwnedValue;
|
||||
|
||||
pub use error::{Result, SearchError};
|
||||
pub use index::{SearchIndex, SearchIndexBuilder};
|
||||
pub use index::{SearchIndex, SearchIndexBuilder, to_json};
|
||||
pub use schema::Schema;
|
||||
+26
-9
@@ -11,20 +11,24 @@ pub struct Schema;
|
||||
impl Schema {
|
||||
pub fn schema() -> &'static TantivySchema {
|
||||
SCHEMA.get_or_init(|| {
|
||||
let stored_ngram32 = TextOptions::default().set_indexing_options(
|
||||
let stored_ngram32 = TextOptions::default()
|
||||
.set_indexing_options(
|
||||
TextFieldIndexing::default()
|
||||
.set_index_option(IndexRecordOption::WithFreqsAndPositions)
|
||||
.set_tokenizer("ngram_32"),
|
||||
).set_stored();
|
||||
)
|
||||
.set_stored();
|
||||
|
||||
let stored_en_stem = TextOptions::default().set_indexing_options(
|
||||
let stored_en_stem = TextOptions::default()
|
||||
.set_indexing_options(
|
||||
TextFieldIndexing::default()
|
||||
.set_index_option(IndexRecordOption::WithFreqsAndPositions)
|
||||
.set_tokenizer("en_stem"),
|
||||
).set_stored();
|
||||
)
|
||||
.set_stored();
|
||||
|
||||
let mut schema_builder = TantivySchema::builder();
|
||||
schema_builder.add_u64_field("type", schema::FAST | schema::INDEXED);
|
||||
schema_builder.add_u64_field("discriminant", schema::FAST | schema::INDEXED);
|
||||
schema_builder.add_text_field("iri", schema::STORED | schema::STRING);
|
||||
schema_builder.add_text_field("curie", stored_ngram32.clone());
|
||||
|
||||
@@ -33,13 +37,20 @@ impl Schema {
|
||||
|
||||
schema_builder.add_text_field("surname:en", stored_ngram32.clone());
|
||||
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());
|
||||
|
||||
schema_builder.build()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn type_field() -> Field {
|
||||
Self::schema().get_field("type").unwrap()
|
||||
pub fn discriminant_field() -> Field {
|
||||
Self::schema().get_field("discriminant").unwrap()
|
||||
}
|
||||
|
||||
pub fn iri_field() -> Field {
|
||||
@@ -50,9 +61,15 @@ impl Schema {
|
||||
Self::schema().get_field("curie").unwrap()
|
||||
}
|
||||
|
||||
pub fn field(name: &str, language: &str) -> Field {
|
||||
pub fn field(name: &str, language: Option<&str>) -> Field {
|
||||
let field_name = if let Some(language) = language {
|
||||
format!("{name}:{language}")
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
|
||||
Schema::schema()
|
||||
.get_field(&format!("{name}:{language}"))
|
||||
.get_field(&field_name)
|
||||
.expect("Field not found in schema")
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*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);
|
||||
let subtitle_content = Schema::field("subtitle", Some("en"));
|
||||
|
||||
let subtitle_file = subtitler::parse_bytes(data)?;
|
||||
let subtitles = subtitle_file.subtitles();
|
||||
let documents = subtitles
|
||||
.iter()
|
||||
.map(|subtitle| {
|
||||
doc!(
|
||||
subtitle_start => subtitle.start,
|
||||
subtitle_end => subtitle.end,
|
||||
subtitle_content => subtitle.text,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
Ok(documents)
|
||||
}*/
|
||||
Reference in New Issue
Block a user