.
This commit is contained in:
Generated
+1
@@ -1368,6 +1368,7 @@ dependencies = [
|
||||
"iced",
|
||||
"ldp",
|
||||
"oxigraph",
|
||||
"oxilangtag",
|
||||
"rfd",
|
||||
"tar",
|
||||
"thiserror 2.0.18",
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -14,6 +14,7 @@ http.workspace = true
|
||||
iced.workspace = true
|
||||
rfd.workspace = true
|
||||
oxigraph.workspace = true
|
||||
oxilangtag.workspace = true
|
||||
tar.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
+55
-100
@@ -1,7 +1,6 @@
|
||||
use crate::rdf::ontology::{LabeledIri, Ontology};
|
||||
use crate::rdf::term_helper::{TermHelper, TermHelperMut};
|
||||
use crate::rdf::vocab::{gl, rda};
|
||||
use gl_search::{Schema, SearchDocument, SearchIndex, NamedFieldDocument, OwnedValue, doc, IndexWriter};
|
||||
use gl_search::{Schema, SearchDocument, SearchIndex, doc, IndexWriter};
|
||||
use http::StatusCode;
|
||||
use iced::alignment::Horizontal;
|
||||
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::window::Settings;
|
||||
use iced::{Background, Color, Element, Length, Subscription, Task, color, window};
|
||||
use iced::widget::text::Wrapping;
|
||||
use ldp::middleware::BasicAuthMiddleware;
|
||||
use ldp::model::{KeyedDataset, QuadKey};
|
||||
use ldp::reqwest::{Client, Url};
|
||||
@@ -19,10 +17,11 @@ use ldp::{RdfSource, RdfSourceUpdateResponse, ResourceRequestBuilder, Serializat
|
||||
use oxigraph::io::RdfFormat;
|
||||
use oxigraph::model::vocab::{rdf, rdfs};
|
||||
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;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum Message {
|
||||
None,
|
||||
Traverse,
|
||||
@@ -43,7 +42,7 @@ pub(crate) enum Message {
|
||||
HoverRow(QuadKey),
|
||||
UnhoverRow(QuadKey),
|
||||
QueryUpdated(String),
|
||||
SetSearchResults(Vec<NamedFieldDocument>),
|
||||
SetSearchResults(Vec<SearchDocument>),
|
||||
QueryTypeUpdated(NamedNode),
|
||||
SearchResultClicked(NamedNode),
|
||||
DatatypeUpdated(QuadKey, Option<String>),
|
||||
@@ -76,7 +75,7 @@ struct SearchState {
|
||||
action: SearchResultClickAction,
|
||||
query: String,
|
||||
type_: LabeledIri,
|
||||
results: Vec<NamedFieldDocument>,
|
||||
results: Vec<SearchDocument>,
|
||||
}
|
||||
|
||||
pub(crate) struct Publisher {
|
||||
@@ -97,32 +96,31 @@ pub(crate) struct Publisher {
|
||||
|
||||
impl Publisher {
|
||||
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()
|
||||
.with_path("/home/alex/.local/share/org.graphofliberty.desktop/ontology")
|
||||
.build()
|
||||
.expect("Failed to build ontology")
|
||||
});
|
||||
|
||||
let index = info_span!("Ontology Indexing").in_scope(|| {
|
||||
let mut index = SearchIndex::builder()
|
||||
//.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index")
|
||||
.build()
|
||||
.expect("Failed to build search index");
|
||||
let index = SearchIndex::builder()
|
||||
//.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index")
|
||||
.build()
|
||||
.expect("Failed to build search index");
|
||||
|
||||
let writer = index.writer().expect("Failed to create search index writer");
|
||||
|
||||
let classes_to_index = [
|
||||
rdf::PROPERTY,
|
||||
rdfs::CLASS,
|
||||
];
|
||||
let classes_to_index = [
|
||||
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 {
|
||||
let class = class.into_owned();
|
||||
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) {
|
||||
let info = ontology.info(&individual);
|
||||
let info = ontology.info(&individual, &conversion::english());
|
||||
if info.label.is_some() || info.comment.is_some() {
|
||||
let mut document = doc!(
|
||||
Schema::type_field() => id,
|
||||
@@ -137,13 +135,12 @@ impl Publisher {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index
|
||||
writer.commit().expect("Failed to commit changes to search index");
|
||||
});
|
||||
|
||||
let mut abbreviated_datatypes = ontology
|
||||
@@ -187,7 +184,7 @@ impl Publisher {
|
||||
|
||||
pub(crate) fn update(&mut self, message: Message) -> Task<Message> {
|
||||
let mut task = Task::none();
|
||||
debug!(?message);
|
||||
trace!(?message);
|
||||
|
||||
match message {
|
||||
Message::Traverse => {
|
||||
@@ -223,13 +220,14 @@ impl Publisher {
|
||||
}
|
||||
|
||||
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 => {
|
||||
if let Some(writer) = &mut self.index_writer {
|
||||
writer.commit().expect("Unable to commit updates to search index");
|
||||
self.index_writer = None;
|
||||
}
|
||||
}
|
||||
Message::WindowClosed(id) => {
|
||||
@@ -368,15 +366,20 @@ impl Publisher {
|
||||
SearchResultClickAction::URLInput => self.ontology.catalog_id(&search_state.type_.iri),
|
||||
};
|
||||
|
||||
search_state.query = new_query.clone();
|
||||
let index = self.index.clone();
|
||||
task = Task::future(async move {
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let result = index.query(catalog_id, new_query.as_str(), Schema::all_fields())
|
||||
.expect("Error encountered while querying index");
|
||||
Message::SetSearchResults(result)
|
||||
}).await.unwrap()
|
||||
let query = new_query.clone();
|
||||
let search_task = tokio::task::spawn_blocking(move || {
|
||||
index.query(catalog_id, query.as_str(), Schema::all_fields(), 25)
|
||||
});
|
||||
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) => {
|
||||
@@ -551,11 +554,11 @@ impl Publisher {
|
||||
container(space()).width(BUTTON_WIDTH)
|
||||
};
|
||||
|
||||
let property_label = "foo"; /*self
|
||||
let property_label = self
|
||||
.ontology
|
||||
.info(triple.predicate.as_ref())
|
||||
.and_then(|info| info.label.clone())
|
||||
.unwrap_or(self.ontology.abbreviate(triple.predicate.as_ref()));*/
|
||||
.info(&triple.predicate, &conversion::english())
|
||||
.label
|
||||
.unwrap_or(self.ontology.abbreviate(triple.predicate.as_ref()));
|
||||
|
||||
let property: Element<Message> = if state.read_only {
|
||||
text(property_label).into()
|
||||
@@ -572,14 +575,13 @@ impl Publisher {
|
||||
|
||||
let value_label = term.value_as_named_node().and_then(|node| {
|
||||
self.ontology
|
||||
.info(&node.into_owned())
|
||||
.info(&node.into_owned(), &conversion::english())
|
||||
.label
|
||||
.map(|label| container(text(label)))
|
||||
});
|
||||
|
||||
let value = term
|
||||
.value_as_named_node()
|
||||
//.map(|node| self.ontology.abbreviate(node))
|
||||
.map(|node| node.as_str().to_string())
|
||||
.unwrap_or(term.value().to_string());
|
||||
|
||||
@@ -591,7 +593,8 @@ impl Publisher {
|
||||
})
|
||||
.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_control_click(Message::OpenQueryWindow(SearchResultClickAction::Object(key)));
|
||||
|
||||
@@ -608,8 +611,7 @@ impl Publisher {
|
||||
.on_input(move |input| {
|
||||
let value = if input.is_empty() { None } else { Some(input) };
|
||||
Message::DatatypeUpdated(key, value)
|
||||
})
|
||||
.into()
|
||||
}).into()
|
||||
};
|
||||
|
||||
let language_input = match term.datatype() {
|
||||
@@ -647,9 +649,7 @@ impl Publisher {
|
||||
button_area,
|
||||
property,
|
||||
value_label,
|
||||
//value_input,
|
||||
foo,
|
||||
//search_launcher,
|
||||
object_input,
|
||||
datatype_selector,
|
||||
language_input,
|
||||
direction_slider,
|
||||
@@ -668,7 +668,7 @@ impl Publisher {
|
||||
let buttons = entities.map(|entity| {
|
||||
let label = self
|
||||
.ontology
|
||||
.info(&entity)
|
||||
.info(&entity, &conversion::english())
|
||||
.label
|
||||
.unwrap_or(entity.as_str().to_string());
|
||||
button(text(label))
|
||||
@@ -699,17 +699,15 @@ impl Publisher {
|
||||
let mut columns = vec![];
|
||||
for field in self.ontology.fields_for_class(&search_state.type_.iri) {
|
||||
let header_text = field.label.as_ref().unwrap_or(&field.name);
|
||||
columns.push(table::column(text(header_text), |document: &NamedFieldDocument| {
|
||||
let cell_value = document.0
|
||||
.get(&field.name)
|
||||
/*columns.push(table::column(text(header_text), |document: &QueryResult| {
|
||||
let cell_value = document.0.get(&field.name)
|
||||
.and_then(|values| values.first())
|
||||
.map(|value| match value {
|
||||
OwnedValue::Str(string) => string,
|
||||
_ => "???",
|
||||
}).unwrap_or("");
|
||||
|
||||
let iri = document.0
|
||||
.get("iri")
|
||||
let iri = document.get("iri")
|
||||
.and_then(|values| values.first())
|
||||
.map(|value| match value {
|
||||
OwnedValue::Str(string) => string,
|
||||
@@ -719,50 +717,9 @@ impl Publisher {
|
||||
button(text(cell_value).wrapping(Wrapping::Word))
|
||||
.on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri)))
|
||||
.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() {
|
||||
None
|
||||
} else {
|
||||
@@ -779,9 +736,10 @@ impl Publisher {
|
||||
|
||||
let index_button = button("Index").on_press(Message::Traverse);
|
||||
|
||||
let search_launcher = button(text("\u{1f50e}"))
|
||||
.on_press(Message::OpenQueryWindow(SearchResultClickAction::URLInput))
|
||||
.style(button::text);
|
||||
let address_input = iri_input(self.ontology.prefixes(), "URL", &self.url_input)
|
||||
.on_input(Message::URLInputChanged)
|
||||
.on_submit(Message::URLInputSubmitted)
|
||||
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::URLInput));
|
||||
|
||||
let mut rows: Vec<Element<Message>> = vec![];
|
||||
rows = self
|
||||
@@ -812,10 +770,7 @@ impl Publisher {
|
||||
row![
|
||||
add_row_button,
|
||||
index_button,
|
||||
search_launcher,
|
||||
text_input("URL", &self.url_input)
|
||||
.on_input(Message::URLInputChanged)
|
||||
.on_submit(Message::URLInputSubmitted),
|
||||
address_input,
|
||||
save_button,
|
||||
],
|
||||
scrollable(body),
|
||||
|
||||
@@ -24,4 +24,10 @@ pub(crate) enum Error {
|
||||
|
||||
#[error(transparent)]
|
||||
QueryEvaluation(#[from] oxigraph::sparql::QueryEvaluationError),
|
||||
|
||||
#[error(transparent)]
|
||||
UpdateEvaluation(#[from] oxigraph::sparql::UpdateEvaluationError),
|
||||
|
||||
#[error(transparent)]
|
||||
SparqlSyntax(#[from] oxigraph::sparql::SparqlSyntaxError),
|
||||
}
|
||||
|
||||
@@ -1,9 +1,37 @@
|
||||
use oxigraph::model::{NamedNode, Quad, Term};
|
||||
use oxigraph::model::vocab::{rdf, xsd};
|
||||
use tracing::info;
|
||||
use oxilangtag::LanguageTag;
|
||||
|
||||
pub fn quad_to_term(quad: &Quad) -> &Term {
|
||||
&quad.object
|
||||
pub enum LanguageCondition {
|
||||
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> {
|
||||
@@ -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 {
|
||||
match literal.datatype() {
|
||||
xsd::STRING | xsd::NORMALIZED_STRING | rdf::LANG_STRING | rdf::DIR_LANG_STRING => {
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
use oxigraph::model::{Dataset, GraphName, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, Term};
|
||||
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
||||
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");
|
||||
let _enter = span.enter();
|
||||
|
||||
let additional_quads = store
|
||||
.quads_for_pattern(None, Some(owl::SAME_AS), None, None)
|
||||
.filter_map(Result::ok)
|
||||
@@ -19,6 +26,7 @@ pub fn same_as(store: &mut Store) -> error::Result<()> {
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -29,6 +37,7 @@ pub fn same_as(store: &mut Store) -> error::Result<()> {
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -40,97 +49,70 @@ pub fn same_as(store: &mut Store) -> error::Result<()> {
|
||||
let new_size = store.len()?;
|
||||
|
||||
if new_size > old_size {
|
||||
same_as(store)
|
||||
} else {
|
||||
Ok(())
|
||||
let difference = new_size - old_size;
|
||||
debug!(?old_size, ?new_size, ?difference, "same_as");
|
||||
same_as(store)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn super_classes(store: &mut Store) -> error::Result<()> {
|
||||
let query = SparqlEvaluator::new()
|
||||
.parse_query(
|
||||
r#"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
pub fn super_properties(store: &mut Store) -> error::Result<()> {
|
||||
let span = debug_span!("Materialize rdfs:subPropertyOf");
|
||||
let _enter = span.enter();
|
||||
|
||||
CONSTRUCT {
|
||||
?item a ?parent
|
||||
} WHERE {
|
||||
?item a ?class .
|
||||
?class rdfs:subClassOf ?parent .
|
||||
}"#,
|
||||
)
|
||||
.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,
|
||||
)
|
||||
}));
|
||||
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 ?parent ?object } }
|
||||
}"#)?;
|
||||
|
||||
let old_size = store.len()?;
|
||||
store.extend(&additional_quads)?;
|
||||
update.on_store(&store).execute()?;
|
||||
let new_size = store.len()?;
|
||||
|
||||
if new_size > old_size {
|
||||
super_classes(store)
|
||||
} else {
|
||||
Ok(())
|
||||
let difference = new_size - old_size;
|
||||
debug!(?old_size, ?new_size, ?difference, "super_properties");
|
||||
super_properties(store)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/*fn iri_information(dataset: &Dataset) -> HashMap<NamedNode, IriInformation> {
|
||||
let query = SparqlEvaluator::new()
|
||||
.parse_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 gl: <https://graphofliberty.org/2026/04/ont/>
|
||||
pub fn super_classes(store: &mut Store) -> error::Result<()> {
|
||||
let span = debug_span!("Materialize rdfs:subClassOf");
|
||||
let _enter = span.enter();
|
||||
|
||||
SELECT DISTINCT ?class ?subject ?label ?comment ?read_only {
|
||||
VALUES ?class { rdf:Property rdfs:Class }
|
||||
?subject a ?class .
|
||||
OPTIONAL {
|
||||
?subject rdfs:label ?label
|
||||
FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?label))
|
||||
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 .
|
||||
}
|
||||
OPTIONAL {
|
||||
?subject rdfs:comment ?comment
|
||||
FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?comment))
|
||||
}
|
||||
OPTIONAL { ?subject gl:readOnly ?read_only }
|
||||
}"#,
|
||||
)
|
||||
.expect("Unable to parse property query");
|
||||
} WHERE {
|
||||
GRAPH ?g1 { ?item a ?class }
|
||||
GRAPH ?g2 { ?class rdfs:subClassOf+ ?parent }
|
||||
}"#)?;
|
||||
|
||||
let mut results = HashMap::new();
|
||||
if let QueryResults::Solutions(solutions) =
|
||||
query.on_queryable_dataset(dataset).execute().unwrap()
|
||||
{
|
||||
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);
|
||||
let old_size = store.len()?;
|
||||
update.on_store(&store).execute()?;
|
||||
let new_size = store.len()?;
|
||||
|
||||
if let Some(subject) = subject && let Some(type_) = type_ {
|
||||
let info = IriInformation {
|
||||
type_: type_.clone(),
|
||||
label: label.map(String::from),
|
||||
comment: comment.map(String::from),
|
||||
read_only,
|
||||
};
|
||||
results.insert(subject.to_owned(), info);
|
||||
}
|
||||
}
|
||||
if new_size > old_size {
|
||||
let difference = new_size - old_size;
|
||||
debug!(?old_size, ?new_size, ?difference, "super_classes");
|
||||
super_classes(store)?;
|
||||
}
|
||||
results
|
||||
}*/
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
@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/> .
|
||||
|
||||
@@ -212,6 +213,14 @@ fedora:lastModifiedBy rdf:type owl:NamedIndividual ;
|
||||
: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
|
||||
rdf:Property rdf:type owl:NamedIndividual ;
|
||||
:associatedProperty rdfs:comment ,
|
||||
@@ -228,12 +237,17 @@ rdfs:Class rdf:type owl:NamedIndividual ;
|
||||
|
||||
### http://www.w3.org/2000/01/rdf-schema#comment
|
||||
rdfs:comment rdf:type owl:NamedIndividual ;
|
||||
:indexedByField :comment .
|
||||
:indexedByField :Comment .
|
||||
|
||||
|
||||
### http://www.w3.org/2000/01/rdf-schema#label
|
||||
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
|
||||
@@ -261,16 +275,24 @@ ldp:contains rdf:type owl:NamedIndividual ;
|
||||
:readOnly "true"^^xsd:boolean .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/comment
|
||||
:comment rdf:type owl:NamedIndividual ,
|
||||
### https://graphofliberty.org/2026/04/ont/Comment
|
||||
:Comment rdf:type owl:NamedIndividual ,
|
||||
:IndexDocumentField ;
|
||||
:fieldLabel "Comment"@en ;
|
||||
:fieldName "comment" ;
|
||||
rdfs:label "Comment Field"@en .
|
||||
|
||||
|
||||
### https://graphofliberty.org/2026/04/ont/label
|
||||
:label rdf:type owl:NamedIndividual ,
|
||||
### 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" ;
|
||||
|
||||
+26
-20
@@ -1,16 +1,16 @@
|
||||
use crate::error;
|
||||
use crate::rdf::vocab::{gl, owl, rda};
|
||||
use oxigraph::io::{RdfFormat, RdfParser};
|
||||
use crate::rdf::vocab::gl;
|
||||
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 std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::fmt::Display;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::LazyLock;
|
||||
use oxigraph::store::Store;
|
||||
use tracing::{info, instrument};
|
||||
use tracing::debug_span;
|
||||
use crate::rdf::{conversion, materialize};
|
||||
use crate::rdf::conversion::LanguageCondition;
|
||||
|
||||
static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| {
|
||||
BTreeMap::from_iter([
|
||||
@@ -70,8 +70,9 @@ impl OntologyBuilder {
|
||||
.collect::<HashMap<String, String>>();
|
||||
|
||||
materialize::same_as(&mut store)?;
|
||||
materialize::super_properties(&mut store)?;
|
||||
materialize::super_classes(&mut store)?;
|
||||
store.optimize()?;
|
||||
debug_span!("Optimize Ontology").in_scope(|| store.optimize())?;
|
||||
|
||||
// Full-text search index field names
|
||||
let fields = Self::fields(&store)?;
|
||||
@@ -82,12 +83,16 @@ impl OntologyBuilder {
|
||||
.filter_map(Result::ok) {
|
||||
let label = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::LABEL), None, None)
|
||||
.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();
|
||||
|
||||
let comment = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::COMMENT), None, None)
|
||||
.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();
|
||||
|
||||
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>> {
|
||||
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(
|
||||
r#"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
PREFIX gl: <https://graphofliberty.org/2026/04/ont/>
|
||||
|
||||
SELECT DISTINCT ?subject ?name ?label {
|
||||
r#"SELECT DISTINCT ?subject ?name ?label {
|
||||
GRAPH ?graph {
|
||||
?subject a gl:IndexDocumentField ;
|
||||
gl:fieldName ?name ;
|
||||
gl:fieldLabel ?label .
|
||||
FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?label))
|
||||
}
|
||||
}"#,
|
||||
)
|
||||
.expect("Unable to parse field query");
|
||||
}"#)?;
|
||||
|
||||
let mut results = HashMap::new();
|
||||
if let QueryResults::Solutions(solutions) = query.on_store(store).execute()?
|
||||
{
|
||||
for solution in solutions.filter_map(Result::ok) {
|
||||
let subject = solution.get("subject").and_then(conversion::term_to_named_node);
|
||||
let name = solution.get("name").and_then(conversion::term_to_string);
|
||||
let label = solution.get("label").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_as_str);
|
||||
|
||||
if let Some(subject) = subject && let Some(name) = name {
|
||||
let field = IndexField {
|
||||
@@ -306,15 +308,19 @@ impl Ontology {
|
||||
} 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)
|
||||
.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();
|
||||
|
||||
let comment = self.store.quads_for_pattern(Some(iri.as_ref().into()), Some(rdfs::COMMENT), None, None)
|
||||
.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();
|
||||
|
||||
LabeledIri {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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::layout::{Limits, Node};
|
||||
use iced::advanced::renderer::Style;
|
||||
@@ -53,6 +53,12 @@ where
|
||||
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 {
|
||||
self.on_control_click = Some(on_control_click);
|
||||
self
|
||||
@@ -67,6 +73,11 @@ where
|
||||
self.text_input = self.text_input.on_input(wrapped);
|
||||
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>>
|
||||
|
||||
+13
-18
@@ -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 std::path::PathBuf;
|
||||
use tantivy::collector::TopDocs;
|
||||
use tantivy::directory::{ManagedDirectory, MmapDirectory};
|
||||
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::{Document, Index, IndexReader, IndexWriter, ReloadPolicy, Score, TantivyDocument, Term};
|
||||
use tantivy::indexer::UserOperation;
|
||||
use tracing::{info, instrument, span, Level};
|
||||
use tantivy::{Index, IndexReader, ReloadPolicy, TantivyDocument, Term};
|
||||
use tracing::{span, Level};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SearchIndexBuilder {
|
||||
@@ -65,15 +66,9 @@ impl SearchIndex {
|
||||
SearchIndexBuilder::default()
|
||||
}
|
||||
|
||||
pub fn writer(&self) -> crate::Result<IndexWriter> {
|
||||
Ok(self.index.writer(128_000_000)?)
|
||||
}
|
||||
|
||||
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 writer(&self) -> crate::Result<update::IndexWriter> {
|
||||
let inner = self.index.writer(128 * 1024usize.pow(2))?;
|
||||
Ok(crate::IndexWriter { inner })
|
||||
}
|
||||
|
||||
pub fn query(
|
||||
@@ -81,8 +76,9 @@ impl SearchIndex {
|
||||
type_: Option<u64>,
|
||||
user_query: &str,
|
||||
default_fields: Vec<Field>,
|
||||
) -> error::Result<Vec<NamedFieldDocument>> {
|
||||
let span = span!(Level::INFO, "Search Query");
|
||||
limit: usize,
|
||||
) -> error::Result<Vec<TantivyDocument>> {
|
||||
let span = span!(Level::DEBUG, "Search Query");
|
||||
let _enter = span.enter();
|
||||
|
||||
let parser = QueryParser::for_index(&self.index, default_fields);
|
||||
@@ -100,11 +96,10 @@ impl SearchIndex {
|
||||
|
||||
let query = BooleanQuery::new(subqueries);
|
||||
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()
|
||||
.map(|(_, address)| searcher.doc(*address))
|
||||
.filter_map(Result::ok)
|
||||
.map(|doc: SearchDocument| doc.to_named_doc(Schema::schema()))
|
||||
.collect();
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,12 +1,13 @@
|
||||
mod error;
|
||||
mod index;
|
||||
mod schema;
|
||||
mod update;
|
||||
|
||||
pub use tantivy::TantivyDocument as SearchDocument;
|
||||
pub use tantivy::doc;
|
||||
pub use tantivy::schema::{NamedFieldDocument, OwnedValue};
|
||||
pub use tantivy::IndexWriter;
|
||||
pub use tantivy::schema::OwnedValue;
|
||||
|
||||
pub use error::{Result, SearchError};
|
||||
pub use index::{SearchIndex, SearchIndexBuilder};
|
||||
pub use schema::Schema;
|
||||
pub use update::IndexWriter;
|
||||
@@ -28,11 +28,7 @@ impl Schema {
|
||||
schema_builder.add_text_field("iri", schema::STORED | schema::STRING);
|
||||
|
||||
schema_builder.add_text_field("label", stored_ngram32.clone());
|
||||
schema_builder.add_text_field("comment", 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("definition", stored_en_stem.clone());
|
||||
|
||||
/*schema_builder.add_text_field("title", en_stem.clone());
|
||||
schema_builder.add_text_field("description", en_stem.clone());
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user