This commit is contained in:
Alex Wied
2026-06-30 19:25:15 -04:00
parent 5cea8e8307
commit 2a6e9432d9
21 changed files with 1039 additions and 235 deletions
Generated
+1
View File
@@ -1368,6 +1368,7 @@ dependencies = [
"iced", "iced",
"ldp", "ldp",
"oxigraph", "oxigraph",
"oxilangtag",
"rfd", "rfd",
"tar", "tar",
"thiserror 2.0.18", "thiserror 2.0.18",
+18
View File
@@ -0,0 +1,18 @@
```
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f 22-rdf-syntax-ns.ttl --graph http://www.w3.org/1999/02/22-rdf-syntax-ns
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f rdf-schema.ttl --graph http://www.w3.org/2000/01/rdf-schema
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f fedora.xml --graph http://fedora.info/definitions/v4/repository
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f ldp.ttl --graph http://www.w3.org/ns/ldp
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
# 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 {} \;
find Maps -type f -name '*.xml' -exec oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology --graph http://rdaregistry.info/Maps -f {} \;
find termList -type f -name '*.xml' -exec oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology --graph http://rdaregistry.info/termList -f {} \;
```
```
oxigraph update -l ~/.local/share/org.graphofliberty.desktop/ontology -u "DROP GRAPH <https://graphofliberty.org/2026/04/ont>"
oxigraph load -l ~/.local/share/org.graphofliberty.desktop/ontology -f graphofliberty.ttl --graph https://graphofliberty.org/2026/04/ont
```
+286
View File
@@ -0,0 +1,286 @@
@prefix : <https://graphofliberty.org/2026/04/ont/> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdaa: <http://rdaregistry.info/Elements/a/> .
@prefix rdac: <http://rdaregistry.info/Elements/c/> .
@prefix rdae: <http://rdaregistry.info/Elements/e/> .
@prefix rdai: <http://rdaregistry.info/Elements/i/> .
@prefix rdam: <http://rdaregistry.info/Elements/m/> .
@prefix rdan: <http://rdaregistry.info/Elements/n/> .
@prefix rdap: <http://rdaregistry.info/Elements/p/> .
@prefix rdat: <http://rdaregistry.info/Elements/t/> .
@prefix rdaw: <http://rdaregistry.info/Elements/w/> .
@prefix rdax: <http://rdaregistry.info/Elements/x/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix fedora: <http://fedora.info/definitions/v4/repository#> .
@base <https://graphofliberty.org/2026/04/ont/> .
<https://graphofliberty.org/2026/04/ont> rdf:type owl:Ontology .
#################################################################
# Annotation properties
#################################################################
### http://www.w3.org/2000/01/rdf-schema#value
rdfs:value rdf:type owl:AnnotationProperty .
#################################################################
# Datatypes
#################################################################
### http://www.w3.org/1999/02/22-rdf-syntax-ns#dirLangString
rdf:dirLangString rdf:type rdfs:Datatype ;
rdfs:label "Directional language-tagged string"@en .
### http://www.w3.org/1999/02/22-rdf-syntax-ns#langString
rdf:langString rdf:type rdfs:Datatype ;
rdfs:label "Language-tagged string"@en .
### http://www.w3.org/2001/XMLSchema#boolean
xsd:boolean rdf:type rdfs:Datatype ;
rdfs:label "Boolean"@en .
### http://www.w3.org/2001/XMLSchema#dateTime
xsd:dateTime rdf:type rdfs:Datatype ;
rdfs:comment "Date and time with or without timezone"@en .
### http://www.w3.org/2001/XMLSchema#decimal
xsd:decimal rdf:type rdfs:Datatype ;
rdfs:comment "Arbitrary-precision decimal numbers"@en ;
rdfs:label "Decimal"@en .
### http://www.w3.org/2001/XMLSchema#integer
xsd:integer rdf:type rdfs:Datatype ;
rdfs:comment "Arbitrary-size integer numbers"@en ;
rdfs:label "Integer"@en .
### http://www.w3.org/2001/XMLSchema#nonNegativeInteger
xsd:nonNegativeInteger rdf:type rdfs:Datatype ;
rdfs:label "Non-negative Integer"@en .
### http://www.w3.org/2001/XMLSchema#string
xsd:string rdf:type rdfs:Datatype ;
rdfs:label "String"@en .
### http://www.w3.org/2001/XMLSchema#unsignedShort
xsd:unsignedShort rdf:type rdfs:Datatype ;
rdfs:label "Unsigned short"@en .
#################################################################
# Object Properties
#################################################################
### http://fedora.info/definitions/v4/repository#hasParent
fedora:hasParent rdf:type owl:ObjectProperty .
### https://graphofliberty.org/2026/04/ont/associatedProperty
:associatedProperty rdf:type owl:ObjectProperty ;
rdfs:label "associated property"@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 .
#################################################################
# Data properties
#################################################################
### http://fedora.info/definitions/v4/repository#created
fedora:created rdf:type owl:DatatypeProperty ;
rdfs:subPropertyOf owl:topDataProperty .
### http://fedora.info/definitions/v4/repository#createdBy
fedora:createdBy rdf:type owl:DatatypeProperty ;
rdfs:subPropertyOf owl:topDataProperty .
### http://fedora.info/definitions/v4/repository#lastModified
fedora:lastModified rdf:type owl:DatatypeProperty .
### http://fedora.info/definitions/v4/repository#lastModifiedBy
fedora:lastModifiedBy rdf:type owl:DatatypeProperty .
### http://www.w3.org/ns/ldp#contains
ldp:contains rdf:type owl:DatatypeProperty ;
rdfs:subPropertyOf owl:topDataProperty .
### https://graphofliberty.org/2026/04/ont/catalogId
:catalogId rdf:type owl:DatatypeProperty ;
rdfs:comment "An integer associated with the class for fast lookup in a database."@en ;
rdfs:label "catalog id" .
### https://graphofliberty.org/2026/04/ont/fieldLabel
:fieldLabel rdf:type owl:DatatypeProperty ;
rdfs:domain :IndexDocumentField ;
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: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 ;
rdfs:label "read only"@en .
#################################################################
# Classes
#################################################################
### https://graphofliberty.org/2026/04/ont/Entity
:Entity rdf:type owl:Class ;
rdfs:label "Graph of Liberty Entity"@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 .
#################################################################
# Individuals
#################################################################
### http://fedora.info/definitions/v4/repository#Container
fedora:Container 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 .
### http://fedora.info/definitions/v4/repository#created
fedora:created rdf:type owl:NamedIndividual ;
:readOnly "true"^^xsd:boolean .
### http://fedora.info/definitions/v4/repository#createdBy
fedora:createdBy rdf:type owl:NamedIndividual ;
:readOnly "true"^^xsd:boolean .
### http://fedora.info/definitions/v4/repository#hasParent
fedora:hasParent 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 .
### http://fedora.info/definitions/v4/repository#lastModifiedBy
fedora:lastModifiedBy 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 ;
:associatedProperty rdfs:comment ,
rdfs:label ;
:catalogId "0"^^xsd:nonNegativeInteger .
### http://www.w3.org/2000/01/rdf-schema#Class
rdfs:Class rdf:type owl:NamedIndividual ;
:associatedProperty rdfs:comment ,
rdfs:label ;
:catalogId "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#definition
skos:definition rdf:type owl:NamedIndividual ;
:indexedByField :Definition .
### http://www.w3.org/ns/ldp#BasicContainer
ldp:BasicContainer rdf:type owl:NamedIndividual ;
:readOnly "true"^^xsd:boolean .
### http://www.w3.org/ns/ldp#Container
ldp:Container rdf:type owl:NamedIndividual ;
:readOnly "true"^^xsd:boolean .
### http://www.w3.org/ns/ldp#RDFSource
ldp:RDFSource rdf:type owl:NamedIndividual ;
:readOnly "true"^^xsd:boolean .
### http://www.w3.org/ns/ldp#Resource
ldp:Resource rdf:type owl:NamedIndividual ;
:readOnly "true"^^xsd:boolean .
### http://www.w3.org/ns/ldp#contains
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/Label
:Label rdf:type owl:NamedIndividual ,
:IndexDocumentField ;
:fieldLabel "Label"@en ;
:fieldName "label" ;
rdfs:label "Label Field"@en .
### Generated by the OWL API (version 4.5.29.2024-05-13T12:11:03Z) https://github.com/owlcs/owlapi
+468
View File
@@ -0,0 +1,468 @@
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xmlns:dct="http://purl.org/dc/terms/"
xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:skos="http://www.w3.org/2004/02/skos/core#"
xml:base="http://www.w3.org/2004/02/skos/core">
<!-- This schema represents a formalisation of a subset of the semantic conditions
described in the SKOS Reference document dated 18 August 2009, accessible
at http://www.w3.org/TR/2009/REC-skos-reference-20090818/. XML comments of the form Sn are used to
indicate the semantic conditions that are being expressed. Comments of the form
[Sn] refer to assertions that are, strictly speaking, redundant as they follow
from the RDF(S) or OWL semantics.
A number of semantic conditions are *not* expressed formally in this schema. These are:
S12
S13
S14
S27
S36
S46
For the conditions listed above, rdfs:comments are used to indicate the conditions.
-->
<owl:Ontology rdf:about="http://www.w3.org/2004/02/skos/core">
<dct:title xml:lang="en">SKOS Vocabulary</dct:title>
<dct:contributor>Dave Beckett</dct:contributor>
<dct:contributor>Nikki Rogers</dct:contributor>
<dct:contributor>Participants in W3C's Semantic Web Deployment Working Group.</dct:contributor>
<dct:description xml:lang="en">An RDF vocabulary for describing the basic structure and content of concept schemes such as thesauri, classification schemes, subject heading lists, taxonomies, 'folksonomies', other types of controlled vocabulary, and also concept schemes embedded in glossaries and terminologies.</dct:description>
<dct:creator>Alistair Miles</dct:creator>
<dct:creator>Sean Bechhofer</dct:creator>
<rdfs:seeAlso rdf:resource="http://www.w3.org/TR/skos-reference/"/>
</owl:Ontology>
<rdf:Description rdf:about="#Concept">
<rdfs:label xml:lang="en">Concept</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">An idea or notion; a unit of thought.</skos:definition>
<!-- S1 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
</rdf:Description>
<rdf:Description rdf:about="#ConceptScheme">
<rdfs:label xml:lang="en">Concept Scheme</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A set of concepts, optionally including statements about semantic relationships between those concepts.</skos:definition>
<skos:scopeNote xml:lang="en">A concept scheme may be defined to include concepts from different sources.</skos:scopeNote>
<skos:example xml:lang="en">Thesauri, classification schemes, subject heading lists, taxonomies, 'folksonomies', and other types of controlled vocabulary are all examples of concept schemes. Concept schemes are also embedded in glossaries and terminologies.</skos:example>
<!-- S2 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
<!-- S9 -->
<owl:disjointWith rdf:resource="#Concept"/>
</rdf:Description>
<rdf:Description rdf:about="#Collection">
<rdfs:label xml:lang="en">Collection</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A meaningful collection of concepts.</skos:definition>
<skos:scopeNote xml:lang="en">Labelled collections can be used where you would like a set of concepts to be displayed under a 'node label' in the hierarchy.</skos:scopeNote>
<!-- S28 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
<!-- S37 -->
<owl:disjointWith rdf:resource="#Concept"/>
<!-- S37 -->
<owl:disjointWith rdf:resource="#ConceptScheme"/>
</rdf:Description>
<rdf:Description rdf:about="#OrderedCollection">
<rdfs:label xml:lang="en">Ordered Collection</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">An ordered collection of concepts, where both the grouping and the ordering are meaningful.</skos:definition>
<skos:scopeNote xml:lang="en">Ordered collections can be used where you would like a set of concepts to be displayed in a specific order, and optionally under a 'node label'.</skos:scopeNote>
<!-- S28 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Class"/>
<!-- S29 -->
<rdfs:subClassOf rdf:resource="#Collection"/>
</rdf:Description>
<rdf:Description rdf:about="#inScheme">
<rdfs:label xml:lang="en">is in scheme</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates a resource (for example a concept) to a concept scheme in which it is included.</skos:definition>
<skos:scopeNote xml:lang="en">A concept may be a member of more than one concept scheme.</skos:scopeNote>
<!-- S3 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S4 -->
<rdfs:range rdf:resource="#ConceptScheme"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#hasTopConcept">
<rdfs:label xml:lang="en">has top concept</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates, by convention, a concept scheme to a concept which is topmost in the broader/narrower concept hierarchies for that scheme, providing an entry point to these hierarchies.</skos:definition>
<!-- S3 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S5 -->
<rdfs:domain rdf:resource="#ConceptScheme"/>
<!-- S6 -->
<rdfs:range rdf:resource="#Concept"/>
<!-- S8 -->
<owl:inverseOf rdf:resource="#topConceptOf"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#topConceptOf">
<rdfs:label xml:lang="en">is top concept in scheme</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates a concept to the concept scheme that it is a top level concept of.</skos:definition>
<!-- S3 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S7 -->
<rdfs:subPropertyOf rdf:resource="#inScheme"/>
<!-- S8 -->
<owl:inverseOf rdf:resource="#hasTopConcept"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
<rdfs:domain rdf:resource="#Concept"/>
<rdfs:range rdf:resource="#ConceptScheme"/>
</rdf:Description>
<rdf:Description rdf:about="#prefLabel">
<rdfs:label xml:lang="en">preferred label</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">The preferred lexical label for a resource, in a given language.</skos:definition>
<!-- S10 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S11 -->
<rdfs:subPropertyOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#label"/>
<!-- S14 (not formally stated) -->
<rdfs:comment xml:lang="en">A resource has no more than one value of skos:prefLabel per language tag, and no more than one value of skos:prefLabel without language tag.</rdfs:comment>
<!-- S12 (not formally stated) -->
<rdfs:comment xml:lang="en">The range of skos:prefLabel is the class of RDF plain literals.</rdfs:comment>
<!-- S13 (not formally stated) -->
<rdfs:comment xml:lang="en">skos:prefLabel, skos:altLabel and skos:hiddenLabel are pairwise
disjoint properties.</rdfs:comment>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#altLabel">
<rdfs:label xml:lang="en">alternative label</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">An alternative lexical label for a resource.</skos:definition>
<skos:example xml:lang="en">Acronyms, abbreviations, spelling variants, and irregular plural/singular forms may be included among the alternative labels for a concept. Mis-spelled terms are normally included as hidden labels (see skos:hiddenLabel).</skos:example>
<!-- S10 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S11 -->
<rdfs:subPropertyOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#label"/>
<!-- S12 (not formally stated) -->
<rdfs:comment xml:lang="en">The range of skos:altLabel is the class of RDF plain literals.</rdfs:comment>
<!-- S13 (not formally stated) -->
<rdfs:comment xml:lang="en">skos:prefLabel, skos:altLabel and skos:hiddenLabel are pairwise disjoint properties.</rdfs:comment>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#hiddenLabel">
<rdfs:label xml:lang="en">hidden label</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A lexical label for a resource that should be hidden when generating visual displays of the resource, but should still be accessible to free text search operations.</skos:definition>
<!-- S10 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S11 -->
<rdfs:subPropertyOf rdf:resource="http://www.w3.org/2000/01/rdf-schema#label"/>
<!-- S12 (not formally stated) -->
<rdfs:comment xml:lang="en">The range of skos:hiddenLabel is the class of RDF plain literals.</rdfs:comment>
<!-- S13 (not formally stated) -->
<rdfs:comment xml:lang="en">skos:prefLabel, skos:altLabel and skos:hiddenLabel are pairwise disjoint properties.</rdfs:comment>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#notation">
<rdfs:label xml:lang="en">notation</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A notation, also known as classification code, is a string of characters such as "T58.5" or "303.4833" used to uniquely identify a concept within the scope of a given concept scheme.</skos:definition>
<skos:scopeNote xml:lang="en">By convention, skos:notation is used with a typed literal in the object position of the triple.</skos:scopeNote>
<!-- S15 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#note">
<rdfs:label xml:lang="en">note</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A general note, for any purpose.</skos:definition>
<skos:scopeNote xml:lang="en">This property may be used directly, or as a super-property for more specific note types.</skos:scopeNote>
<!-- S16 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#changeNote">
<rdfs:label xml:lang="en">change note</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A note about a modification to a concept.</skos:definition>
<!-- S16 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S17 -->
<rdfs:subPropertyOf rdf:resource="#note"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#definition">
<rdfs:label xml:lang="en">definition</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A statement or formal explanation of the meaning of a concept.</skos:definition>
<!-- S16 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S17 -->
<rdfs:subPropertyOf rdf:resource="#note"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#editorialNote">
<rdfs:label xml:lang="en">editorial note</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A note for an editor, translator or maintainer of the vocabulary.</skos:definition>
<!-- S16 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S17 -->
<rdfs:subPropertyOf rdf:resource="#note"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#example">
<rdfs:label xml:lang="en">example</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">An example of the use of a concept.</skos:definition>
<!-- S16 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S17 -->
<rdfs:subPropertyOf rdf:resource="#note"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#historyNote">
<rdfs:label xml:lang="en">history note</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A note about the past state/use/meaning of a concept.</skos:definition>
<!-- S16 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S17 -->
<rdfs:subPropertyOf rdf:resource="#note"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#scopeNote">
<rdfs:label xml:lang="en">scope note</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">A note that helps to clarify the meaning and/or the use of a concept.</skos:definition>
<!-- S16 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AnnotationProperty"/>
<!-- S17 -->
<rdfs:subPropertyOf rdf:resource="#note"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#semanticRelation">
<rdfs:label xml:lang="en">is in semantic relation with</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Links a concept to a concept related by meaning.</skos:definition>
<skos:scopeNote xml:lang="en">This property should not be used directly, but as a super-property for all properties denoting a relationship of meaning between concepts.</skos:scopeNote>
<!-- S18 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S19 -->
<rdfs:domain rdf:resource="#Concept"/>
<!-- S20 -->
<rdfs:range rdf:resource="#Concept"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#broader">
<rdfs:label xml:lang="en">has broader</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates a concept to a concept that is more general in meaning.</skos:definition>
<rdfs:comment xml:lang="en">Broader concepts are typically rendered as parents in a concept hierarchy (tree).</rdfs:comment>
<skos:scopeNote xml:lang="en">By convention, skos:broader is only used to assert an immediate (i.e. direct) hierarchical link between two conceptual resources.</skos:scopeNote>
<!-- S18 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S22 -->
<rdfs:subPropertyOf rdf:resource="#broaderTransitive"/>
<!-- S25 -->
<owl:inverseOf rdf:resource="#narrower"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#narrower">
<rdfs:label xml:lang="en">has narrower</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates a concept to a concept that is more specific in meaning.</skos:definition>
<skos:scopeNote xml:lang="en">By convention, skos:broader is only used to assert an immediate (i.e. direct) hierarchical link between two conceptual resources.</skos:scopeNote>
<rdfs:comment xml:lang="en">Narrower concepts are typically rendered as children in a concept hierarchy (tree).</rdfs:comment>
<!-- S18 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S22 -->
<rdfs:subPropertyOf rdf:resource="#narrowerTransitive"/>
<!-- S25 -->
<owl:inverseOf rdf:resource="#broader"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#related">
<rdfs:label xml:lang="en">has related</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates a concept to a concept with which there is an associative semantic relationship.</skos:definition>
<!-- S18 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S21 -->
<rdfs:subPropertyOf rdf:resource="#semanticRelation"/>
<!-- S23 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#SymmetricProperty"/>
<!-- S27 (not formally stated) -->
<rdfs:comment xml:lang="en">skos:related is disjoint with skos:broaderTransitive</rdfs:comment>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#broaderTransitive">
<rdfs:label xml:lang="en">has broader transitive</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition>skos:broaderTransitive is a transitive superproperty of skos:broader.</skos:definition>
<skos:scopeNote xml:lang="en">By convention, skos:broaderTransitive is not used to make assertions. Rather, the properties can be used to draw inferences about the transitive closure of the hierarchical relation, which is useful e.g. when implementing a simple query expansion algorithm in a search application.</skos:scopeNote>
<!-- S18 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S21 -->
<rdfs:subPropertyOf rdf:resource="#semanticRelation"/>
<!-- S24 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"/>
<!-- S26 -->
<owl:inverseOf rdf:resource="#narrowerTransitive"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#narrowerTransitive">
<rdfs:label xml:lang="en">has narrower transitive</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition>skos:narrowerTransitive is a transitive superproperty of skos:narrower.</skos:definition>
<skos:scopeNote xml:lang="en">By convention, skos:narrowerTransitive is not used to make assertions. Rather, the properties can be used to draw inferences about the transitive closure of the hierarchical relation, which is useful e.g. when implementing a simple query expansion algorithm in a search application.</skos:scopeNote>
<!-- S18 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S21 -->
<rdfs:subPropertyOf rdf:resource="#semanticRelation"/>
<!-- S24 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"/>
<!-- S26 -->
<owl:inverseOf rdf:resource="#broaderTransitive"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#member">
<rdfs:label xml:lang="en">has member</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates a collection to one of its members.</skos:definition>
<!-- S30 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S31 -->
<rdfs:domain rdf:resource="#Collection"/>
<!-- S32 -->
<rdfs:range>
<owl:Class>
<owl:unionOf rdf:parseType="Collection">
<owl:Class rdf:about="#Concept"/>
<owl:Class rdf:about="#Collection"/>
</owl:unionOf>
</owl:Class>
</rdfs:range>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#memberList">
<rdfs:label xml:lang="en">has member list</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates an ordered collection to the RDF list containing its members.</skos:definition>
<!-- S30 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S33 -->
<rdfs:domain rdf:resource="#OrderedCollection"/>
<!-- S35 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/>
<!-- S34 -->
<rdfs:range rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#List"/>
<!-- S36 (not formally stated) -->
<rdfs:comment xml:lang="en">For any resource, every item in the list given as the value of the
skos:memberList property is also a value of the skos:member property.</rdfs:comment>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#mappingRelation">
<rdfs:label xml:lang="en">is in mapping relation with</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">Relates two concepts coming, by convention, from different schemes, and that have comparable meanings</skos:definition>
<rdfs:comment xml:lang="en">These concept mapping relations mirror semantic relations, and the data model defined below is similar (with the exception of skos:exactMatch) to the data model defined for semantic relations. A distinct vocabulary is provided for concept mapping relations, to provide a convenient way to differentiate links within a concept scheme from links between concept schemes. However, this pattern of usage is not a formal requirement of the SKOS data model, and relies on informal definitions of best practice.</rdfs:comment>
<!-- S38 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S39 -->
<rdfs:subPropertyOf rdf:resource="#semanticRelation"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#broadMatch">
<rdfs:label xml:lang="en">has broader match</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">skos:broadMatch is used to state a hierarchical mapping link between two conceptual resources in different concept schemes.</skos:definition>
<!-- S38 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S40 -->
<rdfs:subPropertyOf rdf:resource="#mappingRelation"/>
<!-- S41 -->
<rdfs:subPropertyOf rdf:resource="#broader"/>
<!-- S43 -->
<owl:inverseOf rdf:resource="#narrowMatch"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#narrowMatch">
<rdfs:label xml:lang="en">has narrower match</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">skos:narrowMatch is used to state a hierarchical mapping link between two conceptual resources in different concept schemes.</skos:definition>
<!-- S38 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S40 -->
<rdfs:subPropertyOf rdf:resource="#mappingRelation"/>
<!-- S41 -->
<rdfs:subPropertyOf rdf:resource="#narrower"/>
<!-- S43 -->
<owl:inverseOf rdf:resource="#broadMatch"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#relatedMatch">
<rdfs:label xml:lang="en">has related match</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">skos:relatedMatch is used to state an associative mapping link between two conceptual resources in different concept schemes.</skos:definition>
<!-- S38 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S40 -->
<rdfs:subPropertyOf rdf:resource="#mappingRelation"/>
<!-- S41 -->
<rdfs:subPropertyOf rdf:resource="#related"/>
<!-- S44 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#SymmetricProperty"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#exactMatch">
<rdfs:label xml:lang="en">has exact match</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">skos:exactMatch is used to link two concepts, indicating a high degree of confidence that the concepts can be used interchangeably across a wide range of information retrieval applications. skos:exactMatch is a transitive property, and is a sub-property of skos:closeMatch.</skos:definition>
<!-- S38 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S42 -->
<rdfs:subPropertyOf rdf:resource="#closeMatch"/>
<!-- S44 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#SymmetricProperty"/>
<!-- S45 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"/>
<!-- S46 (not formally stated) -->
<rdfs:comment xml:lang="en">skos:exactMatch is disjoint with each of the properties skos:broadMatch and skos:relatedMatch.</rdfs:comment>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
<rdf:Description rdf:about="#closeMatch">
<rdfs:label xml:lang="en">has close match</rdfs:label>
<rdfs:isDefinedBy rdf:resource="http://www.w3.org/2004/02/skos/core"/>
<skos:definition xml:lang="en">skos:closeMatch is used to link two concepts that are sufficiently similar that they can be used interchangeably in some information retrieval applications. In order to avoid the possibility of "compound errors" when combining mappings across more than two concept schemes, skos:closeMatch is not declared to be a transitive property.</skos:definition>
<!-- S38 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
<!-- S40 -->
<rdfs:subPropertyOf rdf:resource="#mappingRelation"/>
<!-- S44 -->
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#SymmetricProperty"/>
<!-- For non-OWL aware applications -->
<rdf:type rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"/>
</rdf:Description>
</rdf:RDF>
+1
View File
@@ -14,6 +14,7 @@ http.workspace = true
iced.workspace = true iced.workspace = true
rfd.workspace = true rfd.workspace = true
oxigraph.workspace = true oxigraph.workspace = true
oxilangtag.workspace = true
tar.workspace = true tar.workspace = true
thiserror.workspace = true thiserror.workspace = true
tokio.workspace = true tokio.workspace = true
+55 -100
View File
@@ -1,7 +1,6 @@
use crate::rdf::ontology::{LabeledIri, Ontology}; use crate::rdf::ontology::{LabeledIri, Ontology};
use crate::rdf::term_helper::{TermHelper, TermHelperMut}; use crate::rdf::term_helper::{TermHelper, TermHelperMut};
use crate::rdf::vocab::{gl, rda}; use gl_search::{Schema, SearchDocument, SearchIndex, doc, IndexWriter};
use gl_search::{Schema, SearchDocument, SearchIndex, NamedFieldDocument, OwnedValue, doc, IndexWriter};
use http::StatusCode; use http::StatusCode;
use iced::alignment::Horizontal; use iced::alignment::Horizontal;
use iced::widget::button::Style; use iced::widget::button::Style;
@@ -9,7 +8,6 @@ use iced::widget::grid::Sizing;
use iced::widget::{button, center, column, combo_box, container, grid, mouse_area, opaque, pick_list, row, scrollable, space, stack, table, text, text_input, toggler}; use iced::widget::{button, center, column, combo_box, container, grid, mouse_area, opaque, pick_list, row, scrollable, space, stack, table, text, text_input, toggler};
use iced::window::Settings; use iced::window::Settings;
use iced::{Background, Color, Element, Length, Subscription, Task, color, window}; use iced::{Background, Color, Element, Length, Subscription, Task, color, window};
use iced::widget::text::Wrapping;
use ldp::middleware::BasicAuthMiddleware; use ldp::middleware::BasicAuthMiddleware;
use ldp::model::{KeyedDataset, QuadKey}; use ldp::model::{KeyedDataset, QuadKey};
use ldp::reqwest::{Client, Url}; use ldp::reqwest::{Client, Url};
@@ -19,10 +17,11 @@ use ldp::{RdfSource, RdfSourceUpdateResponse, ResourceRequestBuilder, Serializat
use oxigraph::io::RdfFormat; use oxigraph::io::RdfFormat;
use oxigraph::model::vocab::{rdf, rdfs}; use oxigraph::model::vocab::{rdf, rdfs};
use oxigraph::model::{BaseDirection, Dataset, NamedNode, Quad, Term, TermRef}; use oxigraph::model::{BaseDirection, Dataset, NamedNode, Quad, Term, TermRef};
use tracing::{debug, error, info, info_span, span, Level}; use tracing::{debug_span, error, trace};
use crate::rdf::conversion;
use crate::widget::iri_input::iri_input; use crate::widget::iri_input::iri_input;
#[derive(Debug, Clone)] #[derive(Clone, Debug)]
pub(crate) enum Message { pub(crate) enum Message {
None, None,
Traverse, Traverse,
@@ -43,7 +42,7 @@ pub(crate) enum Message {
HoverRow(QuadKey), HoverRow(QuadKey),
UnhoverRow(QuadKey), UnhoverRow(QuadKey),
QueryUpdated(String), QueryUpdated(String),
SetSearchResults(Vec<NamedFieldDocument>), SetSearchResults(Vec<SearchDocument>),
QueryTypeUpdated(NamedNode), QueryTypeUpdated(NamedNode),
SearchResultClicked(NamedNode), SearchResultClicked(NamedNode),
DatatypeUpdated(QuadKey, Option<String>), DatatypeUpdated(QuadKey, Option<String>),
@@ -76,7 +75,7 @@ struct SearchState {
action: SearchResultClickAction, action: SearchResultClickAction,
query: String, query: String,
type_: LabeledIri, type_: LabeledIri,
results: Vec<NamedFieldDocument>, results: Vec<SearchDocument>,
} }
pub(crate) struct Publisher { pub(crate) struct Publisher {
@@ -97,32 +96,31 @@ pub(crate) struct Publisher {
impl Publisher { impl Publisher {
pub(crate) fn new() -> (Self, Task<Message>) { pub(crate) fn new() -> (Self, Task<Message>) {
let ontology = info_span!("Ontology Creation").in_scope(|| { let ontology = debug_span!("Ontology Creation").in_scope(|| {
Ontology::builder() Ontology::builder()
.with_path("/home/alex/.local/share/org.graphofliberty.desktop/ontology") .with_path("/home/alex/.local/share/org.graphofliberty.desktop/ontology")
.build() .build()
.expect("Failed to build ontology") .expect("Failed to build ontology")
}); });
let index = info_span!("Ontology Indexing").in_scope(|| { let index = SearchIndex::builder()
let mut index = SearchIndex::builder() //.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index")
//.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index") .build()
.build() .expect("Failed to build search index");
.expect("Failed to build search index");
let writer = index.writer().expect("Failed to create search index writer"); let classes_to_index = [
rdf::PROPERTY,
let classes_to_index = [ rdfs::CLASS,
rdf::PROPERTY, ];
rdfs::CLASS,
];
debug_span!("Ontology Indexing").in_scope(|| {
let mut writer = index.writer().expect("Failed to build index writer");
for class in &classes_to_index { for class in &classes_to_index {
let class = class.into_owned(); let class = class.into_owned();
if let Some(id) = ontology.catalog_id(&class) { if let Some(id) = ontology.catalog_id(&class) {
index.remove_all_of_type(id).expect("Failed to remove documents from search index"); writer.remove_all_of_type(id).expect("Failed to remove documents from search index");
for individual in ontology.individuals(&class) { for individual in ontology.individuals(&class) {
let info = ontology.info(&individual); let info = ontology.info(&individual, &conversion::english());
if info.label.is_some() || info.comment.is_some() { if info.label.is_some() || info.comment.is_some() {
let mut document = doc!( let mut document = doc!(
Schema::type_field() => id, Schema::type_field() => id,
@@ -137,13 +135,12 @@ impl Publisher {
document.add_text(Schema::field(&field.name), info.comment.unwrap_or_default()); document.add_text(Schema::field(&field.name), info.comment.unwrap_or_default());
} }
writer.add_document(document).expect("Failed to add document to search index"); writer.add(document).expect("Failed to add document to search index");
} }
} }
} }
} }
writer.commit().expect("Failed to commit changes to search index");
index
}); });
let mut abbreviated_datatypes = ontology let mut abbreviated_datatypes = ontology
@@ -187,7 +184,7 @@ impl Publisher {
pub(crate) fn update(&mut self, message: Message) -> Task<Message> { pub(crate) fn update(&mut self, message: Message) -> Task<Message> {
let mut task = Task::none(); let mut task = Task::none();
debug!(?message); trace!(?message);
match message { match message {
Message::Traverse => { Message::Traverse => {
@@ -223,13 +220,14 @@ impl Publisher {
} }
if let Some(writer) = &self.index_writer { if let Some(writer) = &self.index_writer {
writer.add_document(document).expect("Unable to add document to search index"); writer.add(document).expect("Unable to add document to search index");
} }
} }
} }
Message::CommitIndex => { Message::CommitIndex => {
if let Some(writer) = &mut self.index_writer { if let Some(writer) = &mut self.index_writer {
writer.commit().expect("Unable to commit updates to search index"); writer.commit().expect("Unable to commit updates to search index");
self.index_writer = None;
} }
} }
Message::WindowClosed(id) => { Message::WindowClosed(id) => {
@@ -368,15 +366,20 @@ impl Publisher {
SearchResultClickAction::URLInput => self.ontology.catalog_id(&search_state.type_.iri), SearchResultClickAction::URLInput => self.ontology.catalog_id(&search_state.type_.iri),
}; };
search_state.query = new_query.clone();
let index = self.index.clone(); let index = self.index.clone();
task = Task::future(async move { let query = new_query.clone();
tokio::task::spawn_blocking(move || { let search_task = tokio::task::spawn_blocking(move || {
let result = index.query(catalog_id, new_query.as_str(), Schema::all_fields()) index.query(catalog_id, query.as_str(), Schema::all_fields(), 25)
.expect("Error encountered while querying index");
Message::SetSearchResults(result)
}).await.unwrap()
}); });
task = Task::future(async {
match search_task.await {
Ok(Ok(documents)) => Message::SetSearchResults(documents),
Ok(Err(err)) => Message::ShowError(err.to_string()),
Err(err) => Message::ShowError(err.to_string()),
}
});
search_state.query = new_query;
}; };
} }
Message::SetSearchResults(results) => { Message::SetSearchResults(results) => {
@@ -551,11 +554,11 @@ impl Publisher {
container(space()).width(BUTTON_WIDTH) container(space()).width(BUTTON_WIDTH)
}; };
let property_label = "foo"; /*self let property_label = self
.ontology .ontology
.info(triple.predicate.as_ref()) .info(&triple.predicate, &conversion::english())
.and_then(|info| info.label.clone()) .label
.unwrap_or(self.ontology.abbreviate(triple.predicate.as_ref()));*/ .unwrap_or(self.ontology.abbreviate(triple.predicate.as_ref()));
let property: Element<Message> = if state.read_only { let property: Element<Message> = if state.read_only {
text(property_label).into() text(property_label).into()
@@ -572,14 +575,13 @@ impl Publisher {
let value_label = term.value_as_named_node().and_then(|node| { let value_label = term.value_as_named_node().and_then(|node| {
self.ontology self.ontology
.info(&node.into_owned()) .info(&node.into_owned(), &conversion::english())
.label .label
.map(|label| container(text(label))) .map(|label| container(text(label)))
}); });
let value = term let value = term
.value_as_named_node() .value_as_named_node()
//.map(|node| self.ontology.abbreviate(node))
.map(|node| node.as_str().to_string()) .map(|node| node.as_str().to_string())
.unwrap_or(term.value().to_string()); .unwrap_or(term.value().to_string());
@@ -591,7 +593,8 @@ impl Publisher {
}) })
.unwrap_or(Horizontal::Left); .unwrap_or(Horizontal::Left);
let foo = iri_input(self.ontology.prefixes(), "Object", value.as_str()) let object_input = iri_input(self.ontology.prefixes(), "Object", value.as_str())
.align_x(value_alignment)
.on_input(move |value| Message::ValueUpdated(key, value)) .on_input(move |value| Message::ValueUpdated(key, value))
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::Object(key))); .on_control_click(Message::OpenQueryWindow(SearchResultClickAction::Object(key)));
@@ -608,8 +611,7 @@ impl Publisher {
.on_input(move |input| { .on_input(move |input| {
let value = if input.is_empty() { None } else { Some(input) }; let value = if input.is_empty() { None } else { Some(input) };
Message::DatatypeUpdated(key, value) Message::DatatypeUpdated(key, value)
}) }).into()
.into()
}; };
let language_input = match term.datatype() { let language_input = match term.datatype() {
@@ -647,9 +649,7 @@ impl Publisher {
button_area, button_area,
property, property,
value_label, value_label,
//value_input, object_input,
foo,
//search_launcher,
datatype_selector, datatype_selector,
language_input, language_input,
direction_slider, direction_slider,
@@ -668,7 +668,7 @@ impl Publisher {
let buttons = entities.map(|entity| { let buttons = entities.map(|entity| {
let label = self let label = self
.ontology .ontology
.info(&entity) .info(&entity, &conversion::english())
.label .label
.unwrap_or(entity.as_str().to_string()); .unwrap_or(entity.as_str().to_string());
button(text(label)) button(text(label))
@@ -699,17 +699,15 @@ impl Publisher {
let mut columns = vec![]; let mut columns = vec![];
for field in self.ontology.fields_for_class(&search_state.type_.iri) { for field in self.ontology.fields_for_class(&search_state.type_.iri) {
let header_text = field.label.as_ref().unwrap_or(&field.name); let header_text = field.label.as_ref().unwrap_or(&field.name);
columns.push(table::column(text(header_text), |document: &NamedFieldDocument| { /*columns.push(table::column(text(header_text), |document: &QueryResult| {
let cell_value = document.0 let cell_value = document.0.get(&field.name)
.get(&field.name)
.and_then(|values| values.first()) .and_then(|values| values.first())
.map(|value| match value { .map(|value| match value {
OwnedValue::Str(string) => string, OwnedValue::Str(string) => string,
_ => "???", _ => "???",
}).unwrap_or(""); }).unwrap_or("");
let iri = document.0 let iri = document.get("iri")
.get("iri")
.and_then(|values| values.first()) .and_then(|values| values.first())
.map(|value| match value { .map(|value| match value {
OwnedValue::Str(string) => string, OwnedValue::Str(string) => string,
@@ -719,50 +717,9 @@ impl Publisher {
button(text(cell_value).wrapping(Wrapping::Word)) button(text(cell_value).wrapping(Wrapping::Word))
.on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri))) .on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri)))
.style(button::text) .style(button::text)
}).width(Length::Fixed(256.0))); }).width(Length::Fixed(256.0)));*/
} }
/*let label_column = table::column("Label", |result: &NamedNode| {
let header_text = self
.ontology
.info(result.as_ref())
.and_then(|info| info.label.clone())
.unwrap_or("".to_string());
button(text(header_text))
.on_press(Message::SearchResultClicked(result.clone()))
.style(button::text)
});
let type_column = table::column("Type", |result: &NamedNode| {
let header_text = self
.ontology
.info(result.as_ref())
.and_then(|info| self.ontology.info(info.type_.as_ref()))
.and_then(|info| info.label.clone())
.unwrap_or("Unknown".to_string());
button(text(header_text))
.on_press(Message::SearchResultClicked(result.clone()))
.style(button::text)
});
let description_column = table::column("Description", |result: &NamedNode| {
let header_text = self.ontology.info(result.as_ref())
.and_then(|info| info.comment.clone())
.unwrap_or("Unknown".to_string());
button(text(header_text))
.on_press(Message::SearchResultClicked(result.clone()))
.style(button::text)
});
let iri_column = table::column("IRI", |result: &NamedNode| {
button(text(result.as_str()))
.on_press(Message::SearchResultClicked(result.clone()))
.style(button::text)
});*/
let results_table = if columns.is_empty() { let results_table = if columns.is_empty() {
None None
} else { } else {
@@ -779,9 +736,10 @@ impl Publisher {
let index_button = button("Index").on_press(Message::Traverse); let index_button = button("Index").on_press(Message::Traverse);
let search_launcher = button(text("\u{1f50e}")) let address_input = iri_input(self.ontology.prefixes(), "URL", &self.url_input)
.on_press(Message::OpenQueryWindow(SearchResultClickAction::URLInput)) .on_input(Message::URLInputChanged)
.style(button::text); .on_submit(Message::URLInputSubmitted)
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::URLInput));
let mut rows: Vec<Element<Message>> = vec![]; let mut rows: Vec<Element<Message>> = vec![];
rows = self rows = self
@@ -812,10 +770,7 @@ impl Publisher {
row![ row![
add_row_button, add_row_button,
index_button, index_button,
search_launcher, address_input,
text_input("URL", &self.url_input)
.on_input(Message::URLInputChanged)
.on_submit(Message::URLInputSubmitted),
save_button, save_button,
], ],
scrollable(body), scrollable(body),
+6
View File
@@ -24,4 +24,10 @@ pub(crate) enum Error {
#[error(transparent)] #[error(transparent)]
QueryEvaluation(#[from] oxigraph::sparql::QueryEvaluationError), QueryEvaluation(#[from] oxigraph::sparql::QueryEvaluationError),
#[error(transparent)]
UpdateEvaluation(#[from] oxigraph::sparql::UpdateEvaluationError),
#[error(transparent)]
SparqlSyntax(#[from] oxigraph::sparql::SparqlSyntaxError),
} }
+36 -4
View File
@@ -1,9 +1,37 @@
use oxigraph::model::{NamedNode, Quad, Term}; use oxigraph::model::{NamedNode, Quad, Term};
use oxigraph::model::vocab::{rdf, xsd}; use oxigraph::model::vocab::{rdf, xsd};
use tracing::info; use oxilangtag::LanguageTag;
pub fn quad_to_term(quad: &Quad) -> &Term { pub enum LanguageCondition {
&quad.object ExactMatch(LanguageTag<String>),
RelaxedMatch(LanguageTag<String>),
Untagged,
}
pub fn quad_into_term(quad: Quad) -> Term {
quad.object
}
pub fn english() -> LanguageCondition {
LanguageCondition::RelaxedMatch(LanguageTag::parse("en".to_string()).unwrap())
}
pub fn language_matches(term: &Term, condition: &LanguageCondition) -> bool {
if let Term::Literal(literal) = term {
let tag = literal.language()
.map(LanguageTag::parse_and_normalize)
.and_then(Result::ok);
match (tag, condition) {
(Some(language), LanguageCondition::ExactMatch(expectation)) |
(Some(language), LanguageCondition::RelaxedMatch(expectation)) => language == *expectation,
(None, LanguageCondition::RelaxedMatch(_)) => true,
(None, LanguageCondition::Untagged) => true,
_ => false,
}
} else {
false
}
} }
pub fn term_to_named_node(term: &Term) -> Option<&NamedNode> { pub fn term_to_named_node(term: &Term) -> Option<&NamedNode> {
@@ -14,7 +42,11 @@ pub fn term_to_named_node(term: &Term) -> Option<&NamedNode> {
} }
} }
pub fn term_to_string(term: &Term) -> Option<&str> { pub fn term_into_string(term: Term) -> Option<String> {
term_as_str(&term).map(String::from)
}
pub fn term_as_str(term: &Term) -> Option<&str> {
if let Term::Literal(literal) = term { if let Term::Literal(literal) = term {
match literal.datatype() { match literal.datatype() {
xsd::STRING | xsd::NORMALIZED_STRING | rdf::LANG_STRING | rdf::DIR_LANG_STRING => { xsd::STRING | xsd::NORMALIZED_STRING | rdf::LANG_STRING | rdf::DIR_LANG_STRING => {
+60 -78
View File
@@ -1,10 +1,17 @@
use oxigraph::model::{Dataset, GraphName, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, Term}; use oxigraph::model::{Dataset, GraphName, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Term};
use oxigraph::sparql::{QueryResults, SparqlEvaluator}; use oxigraph::sparql::SparqlEvaluator;
use oxigraph::store::Store; use oxigraph::store::Store;
use tracing::{debug, debug_span};
use crate::error; use crate::error;
use crate::rdf::vocab::owl; 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<()> { pub fn same_as(store: &mut Store) -> error::Result<()> {
let span = debug_span!("Materialize owl:sameAs");
let _enter = span.enter();
let additional_quads = store let additional_quads = store
.quads_for_pattern(None, Some(owl::SAME_AS), None, None) .quads_for_pattern(None, Some(owl::SAME_AS), None, None)
.filter_map(Result::ok) .filter_map(Result::ok)
@@ -19,6 +26,7 @@ pub fn same_as(store: &mut Store) -> error::Result<()> {
None, None,
).filter_map(Result::ok) { ).filter_map(Result::ok) {
quad.subject = NamedOrBlankNode::NamedNode(y.clone()); quad.subject = NamedOrBlankNode::NamedNode(y.clone());
quad.graph_name = GraphName::NamedNode(INFERENCE_GRAPH.into_owned());
new_dataset.insert(quad.as_ref()); new_dataset.insert(quad.as_ref());
} }
@@ -29,6 +37,7 @@ pub fn same_as(store: &mut Store) -> error::Result<()> {
None, None,
).filter_map(Result::ok) { ).filter_map(Result::ok) {
quad.subject = NamedOrBlankNode::NamedNode(x.clone()); quad.subject = NamedOrBlankNode::NamedNode(x.clone());
quad.graph_name = GraphName::NamedNode(INFERENCE_GRAPH.into_owned());
new_dataset.insert(quad.as_ref()); new_dataset.insert(quad.as_ref());
} }
} }
@@ -40,97 +49,70 @@ pub fn same_as(store: &mut Store) -> error::Result<()> {
let new_size = store.len()?; let new_size = store.len()?;
if new_size > old_size { if new_size > old_size {
same_as(store) let difference = new_size - old_size;
} else { debug!(?old_size, ?new_size, ?difference, "same_as");
Ok(()) same_as(store)?;
} }
Ok(())
} }
pub fn super_classes(store: &mut Store) -> error::Result<()> { pub fn super_properties(store: &mut Store) -> error::Result<()> {
let query = SparqlEvaluator::new() let span = debug_span!("Materialize rdfs:subPropertyOf");
.parse_query( let _enter = span.enter();
r#"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
CONSTRUCT { let update = SparqlEvaluator::new()
?item a ?parent .with_prefix("rdfs", RDF_SCHEMA.as_str())?
} WHERE { .with_prefix("inference", INFERENCE_GRAPH.as_str())?
?item a ?class . .parse_update(r#"INSERT {
?class rdfs:subClassOf ?parent . GRAPH inference: {
}"#, ?property rdfs:subPropertyOf ?parent .
) ?subject ?parent ?object .
.expect("Unable to parse superclass query");
let mut additional_quads = Dataset::new();
if let QueryResults::Graph(graph) = query.on_store(&store).execute().unwrap()
{
additional_quads.extend(graph.filter_map(Result::ok).map(|triple| {
Quad::new(
triple.subject,
triple.predicate,
triple.object,
GraphName::DefaultGraph,
)
}));
} }
} WHERE {
GRAPH ?g1 { ?property rdfs:subPropertyOf+ ?parent }
OPTIONAL { GRAPH ?g2 { ?subject ?parent ?object } }
}"#)?;
let old_size = store.len()?; let old_size = store.len()?;
store.extend(&additional_quads)?; update.on_store(&store).execute()?;
let new_size = store.len()?; let new_size = store.len()?;
if new_size > old_size { if new_size > old_size {
super_classes(store) let difference = new_size - old_size;
} else { debug!(?old_size, ?new_size, ?difference, "super_properties");
Ok(()) super_properties(store)?;
} }
Ok(())
} }
/*fn iri_information(dataset: &Dataset) -> HashMap<NamedNode, IriInformation> { pub fn super_classes(store: &mut Store) -> error::Result<()> {
let query = SparqlEvaluator::new() let span = debug_span!("Materialize rdfs:subClassOf");
.parse_query( let _enter = span.enter();
r#"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX gl: <https://graphofliberty.org/2026/04/ont/>
SELECT DISTINCT ?class ?subject ?label ?comment ?read_only { let update = SparqlEvaluator::new()
VALUES ?class { rdf:Property rdfs:Class } .with_prefix("rdfs", RDF_SCHEMA.as_str())?
?subject a ?class . .with_prefix("inference", INFERENCE_GRAPH.as_str())?
OPTIONAL { .parse_update(r#"INSERT {
?subject rdfs:label ?label GRAPH inference: {
FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?label)) ?class rdfs:subClassOf ?parent .
?item a ?parent .
} }
OPTIONAL { } WHERE {
?subject rdfs:comment ?comment GRAPH ?g1 { ?item a ?class }
FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?comment)) GRAPH ?g2 { ?class rdfs:subClassOf+ ?parent }
} }"#)?;
OPTIONAL { ?subject gl:readOnly ?read_only }
}"#,
)
.expect("Unable to parse property query");
let mut results = HashMap::new(); let old_size = store.len()?;
if let QueryResults::Solutions(solutions) = update.on_store(&store).execute()?;
query.on_queryable_dataset(dataset).execute().unwrap() let new_size = store.len()?;
{
for solution in solutions.filter_map(Result::ok) {
let type_ = solution.get("class").and_then(crate::rdf::ontology::term_to_named_node);
let subject = solution.get("subject").and_then(crate::rdf::ontology::term_to_named_node);
let label = solution.get("label").and_then(crate::rdf::ontology::term_to_string);
let comment = solution.get("comment").and_then(crate::rdf::ontology::term_to_string);
let read_only = solution
.get("read_only")
.and_then(crate::rdf::ontology::term_to_boolean)
.unwrap_or(false);
if let Some(subject) = subject && let Some(type_) = type_ { if new_size > old_size {
let info = IriInformation { let difference = new_size - old_size;
type_: type_.clone(), debug!(?old_size, ?new_size, ?difference, "super_classes");
label: label.map(String::from), super_classes(store)?;
comment: comment.map(String::from),
read_only,
};
results.insert(subject.to_owned(), info);
}
}
} }
results
}*/ Ok(())
}
+28 -6
View File
@@ -15,6 +15,7 @@
@prefix rdaw: <http://rdaregistry.info/Elements/w/> . @prefix rdaw: <http://rdaregistry.info/Elements/w/> .
@prefix rdax: <http://rdaregistry.info/Elements/x/> . @prefix rdax: <http://rdaregistry.info/Elements/x/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix fedora: <http://fedora.info/definitions/v4/repository#> . @prefix fedora: <http://fedora.info/definitions/v4/repository#> .
@base <https://graphofliberty.org/2026/04/ont/> . @base <https://graphofliberty.org/2026/04/ont/> .
@@ -212,6 +213,14 @@ fedora:lastModifiedBy rdf:type owl:NamedIndividual ;
:readOnly "true"^^xsd:boolean . :readOnly "true"^^xsd:boolean .
### http://rdaregistry.info/Elements/x/P00028
rdax:P00028 rdf:type owl:NamedIndividual ;
:associatedProperty rdfs:label ,
skos:definition ;
:catalogId "2"^^xsd:nonNegativeInteger ;
rdfs:label "has related entity of RDA entity"@en .
### http://www.w3.org/1999/02/22-rdf-syntax-ns#Property ### http://www.w3.org/1999/02/22-rdf-syntax-ns#Property
rdf:Property rdf:type owl:NamedIndividual ; rdf:Property rdf:type owl:NamedIndividual ;
:associatedProperty rdfs:comment , :associatedProperty rdfs:comment ,
@@ -228,12 +237,17 @@ rdfs:Class rdf:type owl:NamedIndividual ;
### http://www.w3.org/2000/01/rdf-schema#comment ### http://www.w3.org/2000/01/rdf-schema#comment
rdfs:comment rdf:type owl:NamedIndividual ; rdfs:comment rdf:type owl:NamedIndividual ;
:indexedByField :comment . :indexedByField :Comment .
### http://www.w3.org/2000/01/rdf-schema#label ### http://www.w3.org/2000/01/rdf-schema#label
rdfs:label rdf:type owl:NamedIndividual ; rdfs:label rdf:type owl:NamedIndividual ;
:indexedByField :label . :indexedByField :Label .
### http://www.w3.org/2004/02/skos/core#definition
skos:definition rdf:type owl:NamedIndividual ;
:indexedByField :Definition .
### http://www.w3.org/ns/ldp#BasicContainer ### http://www.w3.org/ns/ldp#BasicContainer
@@ -261,16 +275,24 @@ ldp:contains rdf:type owl:NamedIndividual ;
:readOnly "true"^^xsd:boolean . :readOnly "true"^^xsd:boolean .
### https://graphofliberty.org/2026/04/ont/comment ### https://graphofliberty.org/2026/04/ont/Comment
:comment rdf:type owl:NamedIndividual , :Comment rdf:type owl:NamedIndividual ,
:IndexDocumentField ; :IndexDocumentField ;
:fieldLabel "Comment"@en ; :fieldLabel "Comment"@en ;
:fieldName "comment" ; :fieldName "comment" ;
rdfs:label "Comment Field"@en . rdfs:label "Comment Field"@en .
### https://graphofliberty.org/2026/04/ont/label ### https://graphofliberty.org/2026/04/ont/Definition
:label rdf:type owl:NamedIndividual , :Definition rdf:type owl:NamedIndividual ,
:IndexDocumentField ;
:fieldLabel "Definition"@en ;
:fieldName "definition" ;
rdfs:label "Definition Field"@en .
### https://graphofliberty.org/2026/04/ont/Label
:Label rdf:type owl:NamedIndividual ,
:IndexDocumentField ; :IndexDocumentField ;
:fieldLabel "Label"@en ; :fieldLabel "Label"@en ;
:fieldName "label" ; :fieldName "label" ;
+26 -20
View File
@@ -1,16 +1,16 @@
use crate::error; use crate::error;
use crate::rdf::vocab::{gl, owl, rda}; use crate::rdf::vocab::gl;
use oxigraph::io::{RdfFormat, RdfParser};
use oxigraph::model::vocab::{rdf, rdfs, xsd}; use oxigraph::model::vocab::{rdf, rdfs, xsd};
use oxigraph::model::{Dataset, GraphName, LiteralRef, NamedNode, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, Term, TermRef, Triple, TripleRef}; use oxigraph::model::{LiteralRef, NamedNode, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Term, TermRef, Triple, TripleRef};
use oxigraph::sparql::{QueryResults, SparqlEvaluator}; use oxigraph::sparql::{QueryResults, SparqlEvaluator};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap, HashSet};
use std::fmt::Display; use std::fmt::Display;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::LazyLock; use std::sync::LazyLock;
use oxigraph::store::Store; use oxigraph::store::Store;
use tracing::{info, instrument}; use tracing::debug_span;
use crate::rdf::{conversion, materialize}; use crate::rdf::{conversion, materialize};
use crate::rdf::conversion::LanguageCondition;
static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| { static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| {
BTreeMap::from_iter([ BTreeMap::from_iter([
@@ -70,8 +70,9 @@ impl OntologyBuilder {
.collect::<HashMap<String, String>>(); .collect::<HashMap<String, String>>();
materialize::same_as(&mut store)?; materialize::same_as(&mut store)?;
materialize::super_properties(&mut store)?;
materialize::super_classes(&mut store)?; materialize::super_classes(&mut store)?;
store.optimize()?; debug_span!("Optimize Ontology").in_scope(|| store.optimize())?;
// Full-text search index field names // Full-text search index field names
let fields = Self::fields(&store)?; let fields = Self::fields(&store)?;
@@ -82,12 +83,16 @@ impl OntologyBuilder {
.filter_map(Result::ok) { .filter_map(Result::ok) {
let label = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::LABEL), None, None) let label = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::LABEL), None, None)
.filter_map(Result::ok) .filter_map(Result::ok)
.filter_map(|quad| conversion::term_to_string(&quad.object).map(String::from)) .map(conversion::quad_into_term)
.filter(|term| conversion::language_matches(term, &conversion::english()))
.filter_map(conversion::term_into_string)
.next(); .next();
let comment = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::COMMENT), None, None) let comment = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::COMMENT), None, None)
.filter_map(Result::ok) .filter_map(Result::ok)
.filter_map(|quad| conversion::term_to_string(&quad.object).map(String::from)) .map(conversion::quad_into_term)
.filter(|term| conversion::language_matches(term, &conversion::english()))
.filter_map(conversion::term_into_string)
.next(); .next();
if let Some(catalog_id) = conversion::term_to_u64(&quad.object) && if let Some(catalog_id) = conversion::term_to_u64(&quad.object) &&
@@ -130,28 +135,25 @@ impl OntologyBuilder {
fn fields(store: &Store) -> error::Result<HashMap<NamedNode, IndexField>> { fn fields(store: &Store) -> error::Result<HashMap<NamedNode, IndexField>> {
let query = SparqlEvaluator::new() let query = SparqlEvaluator::new()
.with_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#")?
.with_prefix("gl", "https://graphofliberty.org/2026/04/ont/")?
.parse_query( .parse_query(
r#"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> r#"SELECT DISTINCT ?subject ?name ?label {
PREFIX gl: <https://graphofliberty.org/2026/04/ont/>
SELECT DISTINCT ?subject ?name ?label {
GRAPH ?graph { GRAPH ?graph {
?subject a gl:IndexDocumentField ; ?subject a gl:IndexDocumentField ;
gl:fieldName ?name ; gl:fieldName ?name ;
gl:fieldLabel ?label . gl:fieldLabel ?label .
FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?label)) FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?label))
} }
}"#, }"#)?;
)
.expect("Unable to parse field query");
let mut results = HashMap::new(); let mut results = HashMap::new();
if let QueryResults::Solutions(solutions) = query.on_store(store).execute()? if let QueryResults::Solutions(solutions) = query.on_store(store).execute()?
{ {
for solution in solutions.filter_map(Result::ok) { for solution in solutions.filter_map(Result::ok) {
let subject = solution.get("subject").and_then(conversion::term_to_named_node); let subject = solution.get("subject").and_then(conversion::term_to_named_node);
let name = solution.get("name").and_then(conversion::term_to_string); let name = solution.get("name").and_then(conversion::term_as_str);
let label = solution.get("label").and_then(conversion::term_to_string); let label = solution.get("label").and_then(conversion::term_as_str);
if let Some(subject) = subject && let Some(name) = name { if let Some(subject) = subject && let Some(name) = name {
let field = IndexField { let field = IndexField {
@@ -306,15 +308,19 @@ impl Ontology {
} else { None }) } else { None })
} }
pub fn info(&self, iri: &NamedNode) -> LabeledIri { 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) let label = self.store.quads_for_pattern(Some(iri.as_ref().into()), Some(rdfs::LABEL), None, None)
.filter_map(Result::ok) .filter_map(Result::ok)
.filter_map(|quad| conversion::term_to_string(&quad.object).map(String::from)) .map(conversion::quad_into_term)
.filter(|term| conversion::language_matches(term, language))
.filter_map(conversion::term_into_string)
.next(); .next();
let comment = self.store.quads_for_pattern(Some(iri.as_ref().into()), Some(rdfs::COMMENT), None, None) let comment = self.store.quads_for_pattern(Some(iri.as_ref().into()), Some(rdfs::COMMENT), None, None)
.filter_map(Result::ok) .filter_map(Result::ok)
.filter_map(|quad| conversion::term_to_string(&quad.object).map(String::from)) .map(conversion::quad_into_term)
.filter(|term| conversion::language_matches(term, language))
.filter_map(conversion::term_into_string)
.next(); .next();
LabeledIri { LabeledIri {
+12 -1
View File
@@ -1,5 +1,5 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use iced::{keyboard, widget, Element, Event, Length, Rectangle, Size}; use iced::{alignment, keyboard, widget, Element, Event, Length, Rectangle, Size};
use iced::advanced::{mouse, text, Shell}; use iced::advanced::{mouse, text, Shell};
use iced::advanced::layout::{Limits, Node}; use iced::advanced::layout::{Limits, Node};
use iced::advanced::renderer::Style; use iced::advanced::renderer::Style;
@@ -53,6 +53,12 @@ where
text_input, text_input,
} }
} }
pub fn align_x(mut self, alignment: impl Into<alignment::Horizontal>) -> Self {
self.text_input = self.text_input.align_x(alignment);
self
}
pub fn on_control_click(mut self, on_control_click: Message) -> Self { pub fn on_control_click(mut self, on_control_click: Message) -> Self {
self.on_control_click = Some(on_control_click); self.on_control_click = Some(on_control_click);
self self
@@ -67,6 +73,11 @@ where
self.text_input = self.text_input.on_input(wrapped); self.text_input = self.text_input.on_input(wrapped);
self self
} }
pub fn on_submit(mut self, message: Message) -> Self {
self.text_input = self.text_input.on_submit(message);
self
}
} }
impl<'a, Message, Theme, Renderer> From<IriInput<'a, Message, Theme, Renderer>> impl<'a, Message, Theme, Renderer> From<IriInput<'a, Message, Theme, Renderer>>
+14 -19
View File
@@ -1,14 +1,15 @@
use crate::{error, SearchDocument}; use std::cmp::Ordering;
use std::collections::{BTreeMap, BTreeSet};
use crate::{error, update};
use crate::schema::Schema; use crate::schema::Schema;
use std::path::PathBuf; use std::path::PathBuf;
use tantivy::collector::TopDocs; use tantivy::collector::TopDocs;
use tantivy::directory::{ManagedDirectory, MmapDirectory}; use tantivy::directory::{ManagedDirectory, MmapDirectory};
use tantivy::query::{BooleanQuery, Occur, QueryParser, TermQuery}; use tantivy::query::{BooleanQuery, Occur, QueryParser, TermQuery};
use tantivy::schema::{Field, IndexRecordOption, NamedFieldDocument, Value}; use tantivy::schema::{Field, IndexRecordOption};
use tantivy::tokenizer::{LowerCaser, NgramTokenizer, TextAnalyzer, TokenizerManager}; use tantivy::tokenizer::{LowerCaser, NgramTokenizer, TextAnalyzer, TokenizerManager};
use tantivy::{Document, Index, IndexReader, IndexWriter, ReloadPolicy, Score, TantivyDocument, Term}; use tantivy::{Index, IndexReader, ReloadPolicy, TantivyDocument, Term};
use tantivy::indexer::UserOperation; use tracing::{span, Level};
use tracing::{info, instrument, span, Level};
#[derive(Default)] #[derive(Default)]
pub struct SearchIndexBuilder { pub struct SearchIndexBuilder {
@@ -65,15 +66,9 @@ impl SearchIndex {
SearchIndexBuilder::default() SearchIndexBuilder::default()
} }
pub fn writer(&self) -> crate::Result<IndexWriter> { pub fn writer(&self) -> crate::Result<update::IndexWriter> {
Ok(self.index.writer(128_000_000)?) let inner = self.index.writer(128 * 1024usize.pow(2))?;
} Ok(crate::IndexWriter { inner })
pub fn remove_all_of_type(&mut self, type_: u64) -> crate::Result<()> {
let mut writer: IndexWriter<TantivyDocument> = self.index.writer(64_000_000)?;
writer.delete_term(Term::from_field_u64(Schema::type_field(), type_));
writer.commit()?;
Ok(())
} }
pub fn query( pub fn query(
@@ -81,8 +76,9 @@ impl SearchIndex {
type_: Option<u64>, type_: Option<u64>,
user_query: &str, user_query: &str,
default_fields: Vec<Field>, default_fields: Vec<Field>,
) -> error::Result<Vec<NamedFieldDocument>> { limit: usize,
let span = span!(Level::INFO, "Search Query"); ) -> error::Result<Vec<TantivyDocument>> {
let span = span!(Level::DEBUG, "Search Query");
let _enter = span.enter(); let _enter = span.enter();
let parser = QueryParser::for_index(&self.index, default_fields); let parser = QueryParser::for_index(&self.index, default_fields);
@@ -100,12 +96,11 @@ impl SearchIndex {
let query = BooleanQuery::new(subqueries); let query = BooleanQuery::new(subqueries);
let searcher = self.reader.searcher(); let searcher = self.reader.searcher();
let results = searcher.search(&query, &TopDocs::with_limit(10000).order_by_score())? let results: Vec<TantivyDocument> = searcher.search(&query, &TopDocs::with_limit(limit).order_by_score())?
.iter() .iter()
.map(|(_, address)| searcher.doc(*address)) .map(|(_, address)| searcher.doc(*address))
.filter_map(Result::ok) .filter_map(Result::ok)
.map(|doc: SearchDocument| doc.to_named_doc(Schema::schema()))
.collect(); .collect();
Ok(results) Ok(results)
} }
} }
+3 -2
View File
@@ -1,12 +1,13 @@
mod error; mod error;
mod index; mod index;
mod schema; mod schema;
mod update;
pub use tantivy::TantivyDocument as SearchDocument; pub use tantivy::TantivyDocument as SearchDocument;
pub use tantivy::doc; pub use tantivy::doc;
pub use tantivy::schema::{NamedFieldDocument, OwnedValue}; pub use tantivy::schema::OwnedValue;
pub use tantivy::IndexWriter;
pub use error::{Result, SearchError}; pub use error::{Result, SearchError};
pub use index::{SearchIndex, SearchIndexBuilder}; pub use index::{SearchIndex, SearchIndexBuilder};
pub use schema::Schema; pub use schema::Schema;
pub use update::IndexWriter;
+1 -5
View File
@@ -28,11 +28,7 @@ impl Schema {
schema_builder.add_text_field("iri", schema::STORED | schema::STRING); schema_builder.add_text_field("iri", schema::STORED | schema::STRING);
schema_builder.add_text_field("label", stored_ngram32.clone()); schema_builder.add_text_field("label", stored_ngram32.clone());
schema_builder.add_text_field("comment", stored_en_stem.clone()); schema_builder.add_text_field("definition", stored_en_stem.clone());
/*schema_builder.add_text_field("nomen", stored_ngram32.clone());
schema_builder.add_text_field("givenName", stored_ngram32.clone());
schema_builder.add_text_field("surname", stored_ngram32);*/
/*schema_builder.add_text_field("title", en_stem.clone()); /*schema_builder.add_text_field("title", en_stem.clone());
schema_builder.add_text_field("description", en_stem.clone()); schema_builder.add_text_field("description", en_stem.clone());
+24
View File
@@ -0,0 +1,24 @@
use tantivy::Term;
use crate::Schema;
pub struct IndexWriter {
pub(crate) inner: tantivy::IndexWriter,
}
impl IndexWriter {
pub fn add(&self, document: crate::SearchDocument) -> crate::Result<()> {
let _ = self.inner.add_document(document)?;
Ok(())
}
pub fn remove_all_of_type(&mut self, type_: u64) -> crate::Result<()> {
self.inner.delete_term(Term::from_field_u64(Schema::type_field(), type_));
self.inner.commit()?;
Ok(())
}
pub fn commit(&mut self) -> crate::Result<()> {
self.inner.commit()?;
Ok(())
}
}