From 0094ffa9b222a17fc202504b929dc309e309e707 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Fri, 4 Aug 2023 16:11:40 +1000 Subject: [PATCH 01/15] Add rdf:type to construct queries for vocab top concepts and narrowers --- prez/queries/vocprez.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prez/queries/vocprez.py b/prez/queries/vocprez.py index 7378fac7..a1412b23 100644 --- a/prez/queries/vocprez.py +++ b/prez/queries/vocprez.py @@ -63,11 +63,15 @@ def get_concept_scheme_top_concepts_query(iri: str, page: int, per_page: int) -> ?concept prez:childrenCount ?narrowerChildrenCount . ?iri prez:childrenCount ?childrenCount . ?iri skos:hasTopConcept ?concept . + ?iri rdf:type ?type . + ?concept rdf:type ?conceptType . } WHERE { BIND(<{{ iri }}> as ?iri) ?iri skos:hasTopConcept ?concept . ?concept skos:prefLabel ?label . + ?iri rdf:type ?type . + ?concept rdf:type ?conceptType . { SELECT (COUNT(?childConcept) AS ?childrenCount) @@ -113,11 +117,15 @@ def get_concept_narrowers_query(iri: str, page: int, per_page: int) -> str: ?concept prez:childrenCount ?narrowerChildrenCount . ?iri prez:childrenCount ?childrenCount . ?iri skos:narrower ?concept . + ?iri rdf:type ?type . + ?concept rdf:type ?conceptType . } WHERE { BIND(<{{ iri }}> as ?iri) ?concept skos:broader ?iri . ?concept skos:prefLabel ?label . + ?iri rdf:type ?type . + ?concept rdf:type ?conceptType . { SELECT (COUNT(?childConcept) AS ?childrenCount) From 70ab24e91a32882e6b37bb75d21a2dc249132e79 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Fri, 4 Aug 2023 16:12:01 +1000 Subject: [PATCH 02/15] Add reg:status to vocpub profile as an otherAnnotationsProps --- prez/reference_data/profiles/vocprez_default_profiles.ttl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prez/reference_data/profiles/vocprez_default_profiles.ttl b/prez/reference_data/profiles/vocprez_default_profiles.ttl index e7adf7fa..505453ef 100644 --- a/prez/reference_data/profiles/vocprez_default_profiles.ttl +++ b/prez/reference_data/profiles/vocprez_default_profiles.ttl @@ -69,7 +69,7 @@ prez:VocPrezProfile dcterms:identifier "vocpub"^^xsd:token ; dcterms:title "VocPub" ; altr-ext:hasLabelPredicate skos:prefLabel ; - altr-ext:otherAnnotationProps schema:color ; + altr-ext:otherAnnotationProps schema:color, reg:status ; altr-ext:constrainsClass skos:ConceptScheme , skos:Concept , From ad8667d9fa1c068766b2d48864531fbadf8fb616 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Fri, 4 Aug 2023 16:12:33 +1000 Subject: [PATCH 03/15] Add duplicated code fragment to ensure new predicates and values added to the graph object also get their annotations added on the second time --- prez/renderers/renderer.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/prez/renderers/renderer.py b/prez/renderers/renderer.py index 78ee6d81..adb76d22 100644 --- a/prez/renderers/renderer.py +++ b/prez/renderers/renderer.py @@ -98,6 +98,29 @@ async def return_annotated_rdf( annotations_graph += anots_from_triplestore cache += anots_from_triplestore + # TODO: this portion of the code requires refactoring. + # Duplicated fragment code below is required to ensure new predicates and values + # defined in the profiles get added to the `graph` and the labels of those + # values also get added to the `graph`. + + # start of duplicated code fragment + graph += annotations_graph + + profile_annotation_props = get_annotation_predicates(profile) + queries_for_uncached, annotations_graph = await get_annotation_properties( + graph, **profile_annotation_props + ) + + if queries_for_uncached is None: + anots_from_triplestore = Graph() + else: + anots_from_triplestore = await queries_to_graph([queries_for_uncached]) + + if len(anots_from_triplestore) > 1: + annotations_graph += anots_from_triplestore + cache += anots_from_triplestore + # end duplicated code fragment + generate_prez_links(graph, predicates_for_link_addition) obj = io.BytesIO( From dba28ac44edd322640ed7a9679d50c3c759a6f9a Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Fri, 4 Aug 2023 16:21:05 +1000 Subject: [PATCH 04/15] Revert "Add rdf:type to construct queries for vocab top concepts and narrowers" This reverts commit 0094ffa9b222a17fc202504b929dc309e309e707. --- prez/queries/vocprez.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/prez/queries/vocprez.py b/prez/queries/vocprez.py index a1412b23..7378fac7 100644 --- a/prez/queries/vocprez.py +++ b/prez/queries/vocprez.py @@ -63,15 +63,11 @@ def get_concept_scheme_top_concepts_query(iri: str, page: int, per_page: int) -> ?concept prez:childrenCount ?narrowerChildrenCount . ?iri prez:childrenCount ?childrenCount . ?iri skos:hasTopConcept ?concept . - ?iri rdf:type ?type . - ?concept rdf:type ?conceptType . } WHERE { BIND(<{{ iri }}> as ?iri) ?iri skos:hasTopConcept ?concept . ?concept skos:prefLabel ?label . - ?iri rdf:type ?type . - ?concept rdf:type ?conceptType . { SELECT (COUNT(?childConcept) AS ?childrenCount) @@ -117,15 +113,11 @@ def get_concept_narrowers_query(iri: str, page: int, per_page: int) -> str: ?concept prez:childrenCount ?narrowerChildrenCount . ?iri prez:childrenCount ?childrenCount . ?iri skos:narrower ?concept . - ?iri rdf:type ?type . - ?concept rdf:type ?conceptType . } WHERE { BIND(<{{ iri }}> as ?iri) ?concept skos:broader ?iri . ?concept skos:prefLabel ?label . - ?iri rdf:type ?type . - ?concept rdf:type ?conceptType . { SELECT (COUNT(?childConcept) AS ?childrenCount) From c500f834bff9bf13c5130a4717f6a820cf571a78 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Fri, 4 Aug 2023 16:21:44 +1000 Subject: [PATCH 05/15] Revert "Revert "Add rdf:type to construct queries for vocab top concepts and narrowers"" This reverts commit dba28ac44edd322640ed7a9679d50c3c759a6f9a. --- prez/queries/vocprez.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/prez/queries/vocprez.py b/prez/queries/vocprez.py index 7378fac7..a1412b23 100644 --- a/prez/queries/vocprez.py +++ b/prez/queries/vocprez.py @@ -63,11 +63,15 @@ def get_concept_scheme_top_concepts_query(iri: str, page: int, per_page: int) -> ?concept prez:childrenCount ?narrowerChildrenCount . ?iri prez:childrenCount ?childrenCount . ?iri skos:hasTopConcept ?concept . + ?iri rdf:type ?type . + ?concept rdf:type ?conceptType . } WHERE { BIND(<{{ iri }}> as ?iri) ?iri skos:hasTopConcept ?concept . ?concept skos:prefLabel ?label . + ?iri rdf:type ?type . + ?concept rdf:type ?conceptType . { SELECT (COUNT(?childConcept) AS ?childrenCount) @@ -113,11 +117,15 @@ def get_concept_narrowers_query(iri: str, page: int, per_page: int) -> str: ?concept prez:childrenCount ?narrowerChildrenCount . ?iri prez:childrenCount ?childrenCount . ?iri skos:narrower ?concept . + ?iri rdf:type ?type . + ?concept rdf:type ?conceptType . } WHERE { BIND(<{{ iri }}> as ?iri) ?concept skos:broader ?iri . ?concept skos:prefLabel ?label . + ?iri rdf:type ?type . + ?concept rdf:type ?conceptType . { SELECT (COUNT(?childConcept) AS ?childrenCount) From a94ed536dc59b892b28d1a7dd3e64d86799556e9 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Fri, 4 Aug 2023 16:50:15 +1000 Subject: [PATCH 06/15] Fix tests --- .../beddingsurfacestructure_top_concepts.ttl | 255 ++++++++++++ .../collection_listing_anot.ttl | 31 +- .../collection_listing_item.ttl | 363 ++++++++++++------ .../expected_responses/concept-coal.ttl | 21 +- .../concept-open-cut-coal-mining.ttl | 21 +- .../concept-with-2-narrower-concepts.ttl | 15 +- .../concept_scheme_no_children.ttl | 15 +- ...cept_scheme_top_concepts_with_children.ttl | 30 ++ .../concept_scheme_with_children.ttl | 15 +- .../expected_responses/vocab_listing_anot.ttl | 21 +- .../vocprez/input/beddingsurfacestructure.ttl | 177 +++++++++ 11 files changed, 812 insertions(+), 152 deletions(-) create mode 100644 tests/data/vocprez/expected_responses/beddingsurfacestructure_top_concepts.ttl create mode 100644 tests/data/vocprez/input/beddingsurfacestructure.ttl diff --git a/tests/data/vocprez/expected_responses/beddingsurfacestructure_top_concepts.ttl b/tests/data/vocprez/expected_responses/beddingsurfacestructure_top_concepts.ttl new file mode 100644 index 00000000..8a27098b --- /dev/null +++ b/tests/data/vocprez/expected_responses/beddingsurfacestructure_top_concepts.ttl @@ -0,0 +1,255 @@ +PREFIX dcterms: +PREFIX ns1: +PREFIX ns2: +PREFIX rdfs: +PREFIX schema: +PREFIX skos: +PREFIX xsd: + + + a skos:ConceptScheme ; + ns2:status ; + skos:hasTopConcept + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + skos:prefLabel "BeddingSurfaceStructure"@en ; + ns1:childrenCount 21 ; +. + +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; +. + +dcterms:identifier + rdfs:label "Identifier"@en ; + dcterms:description "Recommended practice is to identify the resource by means of a string conforming to an identification system. Examples include International Standard Book Number (ISBN), Digital Object Identifier (DOI), and Uniform Resource Name (URN). Persistent identifiers should be provided as HTTP URIs."@en ; +. + + + a skos:Concept ; + rdfs:label "Shrinkage (Desiccation) Cracks"@en ; + dcterms:identifier "bddngsrfcstrctr:CRACKDES"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Shrinkage (Desiccation) Cracks"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:CRACKDES" ; +. + + + a skos:Concept ; + rdfs:label "Synaeresis Cracks"@en ; + dcterms:identifier "bddngsrfcstrctr:CRACKSYN"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Synaeresis Cracks"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:CRACKSYN" ; +. + + + a skos:Concept ; + rdfs:label "Parting Lineation (Primary Current Lineation)"@en ; + dcterms:identifier "bddngsrfcstrctr:PART"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Parting Lineation (Primary Current Lineation)"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:PART" ; +. + + + a skos:Concept ; + rdfs:label "Rainspots"@en ; + dcterms:identifier "bddngsrfcstrctr:RAIN"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Rainspots"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RAIN" ; +. + + + a skos:Concept ; + rdfs:label "Ripples"@en ; + dcterms:identifier "bddngsrfcstrctr:RIP"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Ripples"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RIP" ; +. + + + a skos:Concept ; + rdfs:label "Current Ripples"@en ; + dcterms:identifier "bddngsrfcstrctr:RIPCUR"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Current Ripples"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RIPCUR" ; +. + + + a skos:Concept ; + rdfs:label "Linguoid Current Ripples"@en ; + dcterms:identifier "bddngsrfcstrctr:RIPCURLIN"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Linguoid Current Ripples"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RIPCURLIN" ; +. + + + a skos:Concept ; + rdfs:label "Sinuous-Crested Current Rippled"@en ; + dcterms:identifier "bddngsrfcstrctr:RIPCURSIN"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Sinuous-Crested Current Rippled"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RIPCURSIN" ; +. + + + a skos:Concept ; + rdfs:label "Straight-Crested Current Ripples"@en ; + dcterms:identifier "bddngsrfcstrctr:RIPCURSTR"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Straight-Crested Current Ripples"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RIPCURSTR" ; +. + + + a skos:Concept ; + rdfs:label "Wave-Formed Ripples"@en ; + dcterms:identifier "bddngsrfcstrctr:RIPWAV"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Wave-Formed Ripples"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RIPWAV" ; +. + + + a skos:Concept ; + rdfs:label "Interference Wave-Formed Ripples"@en ; + dcterms:identifier "bddngsrfcstrctr:RIPWAVINT"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Interference Wave-Formed Ripples"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RIPWAVINT" ; +. + + + a skos:Concept ; + rdfs:label "Modified Wave-Formed Ripples"@en ; + dcterms:identifier "bddngsrfcstrctr:RIPWAVMOD"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Modified Wave-Formed Ripples"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:RIPWAVMOD" ; +. + + + a skos:Concept ; + rdfs:label "Trace Fossils"@en ; + dcterms:identifier "bddngsrfcstrctr:TF"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Trace Fossils"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:TF" ; +. + + + a skos:Concept ; + rdfs:label "Crawling / Walking Tracks and Trails"@en ; + dcterms:identifier "bddngsrfcstrctr:TFCR"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Crawling / Walking Tracks and Trails"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:TFCR" ; +. + + + a skos:Concept ; + rdfs:label "Foot Prints"@en ; + dcterms:identifier "bddngsrfcstrctr:TFCRFOOT"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Foot Prints"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:TFCRFOOT" ; +. + + + a skos:Concept ; + rdfs:label "Grazing Traces"@en ; + dcterms:identifier "bddngsrfcstrctr:TFGRZ"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Grazing Traces"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:TFGRZ" ; +. + + + a skos:Concept ; + rdfs:label "Coiled Grazing Traces"@en ; + dcterms:identifier "bddngsrfcstrctr:TFGRZCOIL"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Coiled Grazing Traces"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:TFGRZCOIL" ; +. + + + a skos:Concept ; + rdfs:label "Meandering Grazing Traces"@en ; + dcterms:identifier "bddngsrfcstrctr:TFGRZMEAND"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Meandering Grazing Traces"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:TFGRZMEAND" ; +. + + + a skos:Concept ; + rdfs:label "Radial Grazing Traces"@en ; + dcterms:identifier "bddngsrfcstrctr:TFGRZRAD"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Radial Grazing Traces"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:TFGRZRAD" ; +. + + + a skos:Concept ; + rdfs:label "Resting Traces"@en ; + dcterms:identifier "bddngsrfcstrctr:TFREST"^^ns1:identifier ; + ns2:status ; + skos:prefLabel "Resting Traces"@en ; + ns1:childrenCount 0 ; + ns1:link "/v/vocab/ref:BeddingSurfaceStructure/bddngsrfcstrctr:TFREST" ; +. + + + skos:prefLabel "experimental"@en ; + schema:color "#eae72c" ; +. + + + skos:prefLabel "valid"@en ; + schema:color "#36a80d" ; +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/collection_listing_anot.ttl b/tests/data/vocprez/expected_responses/collection_listing_anot.ttl index 617a244e..ea27d347 100644 --- a/tests/data/vocprez/expected_responses/collection_listing_anot.ttl +++ b/tests/data/vocprez/expected_responses/collection_listing_anot.ttl @@ -1,19 +1,30 @@ -@prefix dcterms: . -@prefix ns1: . -@prefix skos: . -@prefix xsd: . +PREFIX dcterms: +PREFIX ns1: +PREFIX rdfs: +PREFIX skos: +PREFIX xsd: - a skos:Collection ; + + a skos:Collection ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:definition "Borehole purposes applicable to regulatory notification forms."@en ; skos:prefLabel "PGGD selection"@en ; - ns1:link "/v/collection/brhl-prps:pggd" . + ns1:link "/v/collection/brhl-prps:pggd" ; +. - a skos:Collection ; +dcterms:provenance + rdfs:label "Provenance"@en ; + dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en ; +. + + + a skos:Collection ; dcterms:provenance "this vocabulary" ; skos:definition "All Concepts in this vocabulary" ; skos:prefLabel "Contact Type - All Concepts"@en ; - ns1:link "/v/collection/cgi:contacttype" . - -skos:Collection ns1:count 2 . + ns1:link "/v/collection/cgi:contacttype" ; +. +skos:Collection + ns1:count 2 ; +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/collection_listing_item.ttl b/tests/data/vocprez/expected_responses/collection_listing_item.ttl index 921b20cc..47585167 100644 --- a/tests/data/vocprez/expected_responses/collection_listing_item.ttl +++ b/tests/data/vocprez/expected_responses/collection_listing_item.ttl @@ -1,197 +1,318 @@ -@prefix dcterms: . -@prefix ns1: . -@prefix rdfs: . -@prefix skos: . -@prefix xsd: . - -dcterms:identifier rdfs:label "Identifier"@en ; - dcterms:description "Recommended practice is to identify the resource by means of a string conforming to an identification system. Examples include International Standard Book Number (ISBN), Digital Object Identifier (DOI), and Uniform Resource Name (URN). Persistent identifiers should be provided as HTTP URIs."@en . - -dcterms:provenance rdfs:label "Provenance"@en ; - dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en . - - a skos:Collection ; +PREFIX dcterms: +PREFIX ns1: +PREFIX ns2: +PREFIX rdfs: +PREFIX skos: +PREFIX xsd: + +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; +. + +dcterms:identifier + rdfs:label "Identifier"@en ; + dcterms:description "Recommended practice is to identify the resource by means of a string conforming to an identification system. Examples include International Standard Book Number (ISBN), Digital Object Identifier (DOI), and Uniform Resource Name (URN). Persistent identifiers should be provided as HTTP URIs."@en ; +. + +dcterms:provenance + rdfs:label "Provenance"@en ; + dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en ; +. + + + a skos:Collection ; dcterms:identifier "contacttype"^^xsd:token ; dcterms:provenance "this vocabulary" ; skos:definition "All Concepts in this vocabulary" ; - skos:member , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , + skos:member + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , ; - skos:prefLabel "Contact Type - All Concepts"@en . + skos:prefLabel "Contact Type - All Concepts"@en ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "alteration facies contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:alteration_facies_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:alteration_facies_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "angular unconformable contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:angular_unconformable_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:angular_unconformable_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "buttress unconformity"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:buttress_unconformity" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:buttress_unconformity" ; +. - dcterms:provenance "FGDC"@en ; + + dcterms:provenance "FGDC"@en ; + ns2:status ; skos:prefLabel "chronostratigraphic-zone contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:chronostratigraphic_zone_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:chronostratigraphic_zone_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "conductivity contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:conductivity_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:conductivity_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "conformable contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:conformable_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:conformable_contact" ; +. - dcterms:provenance "adapted from Jackson, 1997, page 137, NADM C1 2004"@en ; + + dcterms:provenance "adapted from Jackson, 1997, page 137, NADM C1 2004"@en ; + ns2:status ; skos:prefLabel "contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "deformation zone contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:deformation_zone_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:deformation_zone_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "density contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:density_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:density_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "depositional contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:depositional_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:depositional_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "disconformable contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:disconformable_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:disconformable_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "faulted contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:faulted_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:faulted_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "geologic province contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:geologic_province_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:geologic_province_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "geophysical contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:geophysical_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:geophysical_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "glacial stationary line"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:glacial_stationary_line" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:glacial_stationary_line" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "igneous intrusive contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:igneous_intrusive_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:igneous_intrusive_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "igneous phase contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:igneous_phase_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:igneous_phase_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "impact structure boundary"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:impact_structure_boundary" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:impact_structure_boundary" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "lithogenetic contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:lithogenetic_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:lithogenetic_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "magnetic contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:magnetic_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:magnetic_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "magnetic polarity contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:magnetic_polarity_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:magnetic_polarity_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "magnetic susceptiblity contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:magnetic_susceptiblity_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:magnetic_susceptiblity_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "magnetization contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:magnetization_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:magnetization_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "metamorphic contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:metamorphic_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:metamorphic_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "metamorphic facies contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:metamorphic_facies_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:metamorphic_facies_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "metasomatic facies contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:metasomatic_facies_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:metasomatic_facies_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "mineralisation assemblage contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:mineralisation_assemblage_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:mineralisation_assemblage_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "nonconformable contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:nonconformable_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:nonconformable_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "paraconformable contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:paraconformable_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:paraconformable_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "radiometric contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:radiometric_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:radiometric_contact" ; +. - dcterms:provenance "base on Nichols, Gary, 1999, Sedimentology and stratigraphy, Blackwell, p. 62-63."@en ; + + dcterms:provenance "base on Nichols, Gary, 1999, Sedimentology and stratigraphy, Blackwell, p. 62-63."@en ; + ns2:status ; skos:prefLabel "sedimentary facies contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:sedimentary_facies_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:sedimentary_facies_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "sedimentary intrusive contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:sedimentary_intrusive_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:sedimentary_intrusive_contact" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "seismic contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:seismic_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:seismic_contact" ; +. - dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + + dcterms:provenance "Neuendorf, K.K.E, Mehl, J.P. & Jackson, J.A. (eds), 2005. Glossary of geology, 5th Edition. American Geological Institute, Alexandria, 779 p."@en ; + ns2:status ; skos:prefLabel "unconformable contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:unconformable_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:unconformable_contact" ; +. - dcterms:provenance "this vocabulary, concept to encompass boundary of caldron, caldera, or crater."@en ; + + dcterms:provenance "this vocabulary, concept to encompass boundary of caldron, caldera, or crater."@en ; + ns2:status ; skos:prefLabel "volcanic subsidence zone boundary"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:volcanic_subsidence_zone_boundary" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:volcanic_subsidence_zone_boundary" ; +. - dcterms:provenance "this vocabulary"@en ; + + dcterms:provenance "this vocabulary"@en ; + ns2:status ; skos:prefLabel "weathering contact"@en ; - ns1:link "/v/collection/cgi:contacttype/cntcttyp:weathering_contact" . + ns1:link "/v/collection/cgi:contacttype/cntcttyp:weathering_contact" ; +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/concept-coal.ttl b/tests/data/vocprez/expected_responses/concept-coal.ttl index 9bc5d8ce..2eb96cbf 100644 --- a/tests/data/vocprez/expected_responses/concept-coal.ttl +++ b/tests/data/vocprez/expected_responses/concept-coal.ttl @@ -1,20 +1,27 @@ PREFIX bhpur: PREFIX cs4: PREFIX dcterms: -PREFIX ns1: +PREFIX ns1: +PREFIX ns2: PREFIX rdfs: +PREFIX schema: PREFIX skos: bhpur:coal a skos:Concept ; - dcterms:identifier "brhl-prps:coal"^^ns1:identifier ; + dcterms:identifier "brhl-prps:coal"^^ns2:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; rdfs:isDefinedBy cs4: ; skos:definition "Wells and bores drilled to facilitate the mining of coal under permits governed by the Queensland Mineral Resources Act 1989"@en ; skos:inScheme cs4: ; skos:prefLabel "Coal"@en ; skos:topConceptOf cs4: ; - ns1:link "/v/vocab/df:borehole-purpose/brhl-prps:coal" ; + ns2:link "/v/vocab/df:borehole-purpose/brhl-prps:coal" ; +. + +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; . dcterms:identifier @@ -27,7 +34,13 @@ dcterms:provenance dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en ; . + + skos:prefLabel "stable"@en ; + schema:color "#2e8c09" ; +. + cs4: dcterms:provenance "Compiled by the Geological Survey of Queensland" ; + ns1:status ; skos:prefLabel "Borehole Purpose"@en ; -. +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/concept-open-cut-coal-mining.ttl b/tests/data/vocprez/expected_responses/concept-open-cut-coal-mining.ttl index b529b7b6..76b88c71 100644 --- a/tests/data/vocprez/expected_responses/concept-open-cut-coal-mining.ttl +++ b/tests/data/vocprez/expected_responses/concept-open-cut-coal-mining.ttl @@ -1,20 +1,27 @@ PREFIX bhpur: PREFIX cs4: PREFIX dcterms: -PREFIX ns1: +PREFIX ns1: +PREFIX ns2: PREFIX rdfs: +PREFIX schema: PREFIX skos: bhpur:open-cut-coal-mining a skos:Concept ; - dcterms:identifier "brhl-prps:open-cut-coal-mining"^^ns1:identifier ; + dcterms:identifier "brhl-prps:open-cut-coal-mining"^^ns2:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; rdfs:isDefinedBy cs4: ; skos:broader bhpur:coal ; skos:definition "Wells drilled for the purpose of assessing coal resources for an open cut coal mine."@en ; skos:inScheme cs4: ; skos:prefLabel "Open-Cut Coal Mining"@en ; - ns1:link "/v/vocab/df:borehole-purpose/brhl-prps:open-cut-coal-mining" ; + ns2:link "/v/vocab/df:borehole-purpose/brhl-prps:open-cut-coal-mining" ; +. + +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; . dcterms:identifier @@ -32,7 +39,13 @@ bhpur:coal skos:prefLabel "Coal"@en ; . + + skos:prefLabel "stable"@en ; + schema:color "#2e8c09" ; +. + cs4: dcterms:provenance "Compiled by the Geological Survey of Queensland" ; + ns1:status ; skos:prefLabel "Borehole Purpose"@en ; -. +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/concept-with-2-narrower-concepts.ttl b/tests/data/vocprez/expected_responses/concept-with-2-narrower-concepts.ttl index 34197ca2..ec1cb428 100644 --- a/tests/data/vocprez/expected_responses/concept-with-2-narrower-concepts.ttl +++ b/tests/data/vocprez/expected_responses/concept-with-2-narrower-concepts.ttl @@ -5,6 +5,7 @@ PREFIX skos: PREFIX xsd: + a skos:Concept ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:narrower , @@ -13,12 +14,23 @@ PREFIX xsd: ns1:childrenCount 2 ; . +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; +. + dcterms:identifier rdfs:label "Identifier"@en ; dcterms:description "Recommended practice is to identify the resource by means of a string conforming to an identification system. Examples include International Standard Book Number (ISBN), Digital Object Identifier (DOI), and Uniform Resource Name (URN). Persistent identifiers should be provided as HTTP URIs."@en ; . +dcterms:provenance + rdfs:label "Provenance"@en ; + dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en ; +. + + a skos:Concept ; dcterms:identifier "brhl-prps:open-cut-coal-mining"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Open-Cut Coal Mining"@en ; @@ -27,9 +39,10 @@ dcterms:identifier . + a skos:Concept ; dcterms:identifier "brhl-prps:underground-coal-mining"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Underground Coal Mining"@en ; ns1:childrenCount 0 ; ns1:link "/v/vocab/def2:borehole-purpose/brhl-prps:underground-coal-mining" ; -. +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/concept_scheme_no_children.ttl b/tests/data/vocprez/expected_responses/concept_scheme_no_children.ttl index 27d246dd..824637d6 100644 --- a/tests/data/vocprez/expected_responses/concept_scheme_no_children.ttl +++ b/tests/data/vocprez/expected_responses/concept_scheme_no_children.ttl @@ -1,6 +1,6 @@ PREFIX dcterms: -PREFIX ns1: -PREFIX ns2: +PREFIX ns1: +PREFIX ns2: PREFIX owl: PREFIX prov: PREFIX rdfs: @@ -17,14 +17,14 @@ PREFIX xsd: dcterms:modified "2023-03-16"^^xsd:date ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; dcterms:publisher ; - ns2:status ; + ns1:status ; skos:definition "The primary purpose of a borehole based on the legislative State Act and/or the resources industry sector."@en ; skos:prefLabel "Borehole Purpose no children"@en ; prov:qualifiedDerivation [ prov:entity ; prov:hadRole ] ; - ns1:childrenCount 0 ; + ns2:childrenCount 0 ; . dcterms:created @@ -37,6 +37,11 @@ dcterms:creator dcterms:description "Recommended practice is to identify the creator with a URI. If this is not possible or feasible, a literal value that identifies the creator may be provided."@en ; . +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; +. + dcterms:modified rdfs:label "Date Modified"@en ; dcterms:description "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty."@en ; @@ -54,4 +59,4 @@ dcterms:publisher skos:prefLabel "stable"@en ; schema:color "#2e8c09" ; -. +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/concept_scheme_top_concepts_with_children.ttl b/tests/data/vocprez/expected_responses/concept_scheme_top_concepts_with_children.ttl index 75b1de09..f800d098 100644 --- a/tests/data/vocprez/expected_responses/concept_scheme_top_concepts_with_children.ttl +++ b/tests/data/vocprez/expected_responses/concept_scheme_top_concepts_with_children.ttl @@ -1,11 +1,18 @@ PREFIX dcterms: PREFIX ns1: +PREFIX ns2: +PREFIX owl: PREFIX rdfs: +PREFIX schema: PREFIX skos: PREFIX xsd: + a + owl:Ontology , + skos:ConceptScheme ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; + ns2:status ; skos:hasTopConcept , , @@ -19,12 +26,23 @@ PREFIX xsd: ns1:childrenCount 8 ; . +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; +. + dcterms:identifier rdfs:label "Identifier"@en ; dcterms:description "Recommended practice is to identify the resource by means of a string conforming to an identification system. Examples include International Standard Book Number (ISBN), Digital Object Identifier (DOI), and Uniform Resource Name (URN). Persistent identifiers should be provided as HTTP URIs."@en ; . +dcterms:provenance + rdfs:label "Provenance"@en ; + dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en ; +. + + a skos:Concept ; dcterms:identifier "brhl-prps:coal"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Coal"@en ; @@ -33,6 +51,7 @@ dcterms:identifier . + a skos:Concept ; dcterms:identifier "brhl-prps:geothermal"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Geothermal"@en ; @@ -41,6 +60,7 @@ dcterms:identifier . + a skos:Concept ; dcterms:identifier "brhl-prps:greenhouse-gas-storage"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Greenhouse Gas Storage"@en ; @@ -49,6 +69,7 @@ dcterms:identifier . + a skos:Concept ; dcterms:identifier "brhl-prps:mineral"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Mineral"@en ; @@ -57,6 +78,7 @@ dcterms:identifier . + a skos:Concept ; dcterms:identifier "brhl-prps:non-industry"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Non-Industry"@en ; @@ -65,6 +87,7 @@ dcterms:identifier . + a skos:Concept ; dcterms:identifier "brhl-prps:oil-shale"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Oil Shale"@en ; @@ -73,6 +96,7 @@ dcterms:identifier . + a skos:Concept ; dcterms:identifier "brhl-prps:petroleum"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Petroleum"@en ; @@ -81,9 +105,15 @@ dcterms:identifier . + a skos:Concept ; dcterms:identifier "brhl-prps:water"^^ns1:identifier ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; skos:prefLabel "Water"@en ; ns1:childrenCount 0 ; ns1:link "/v/vocab/def2:borehole-purpose/brhl-prps:water" ; . + + + skos:prefLabel "stable"@en ; + schema:color "#2e8c09" ; +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/concept_scheme_with_children.ttl b/tests/data/vocprez/expected_responses/concept_scheme_with_children.ttl index 86aadff0..012a004b 100644 --- a/tests/data/vocprez/expected_responses/concept_scheme_with_children.ttl +++ b/tests/data/vocprez/expected_responses/concept_scheme_with_children.ttl @@ -1,6 +1,6 @@ PREFIX dcterms: -PREFIX ns1: -PREFIX ns2: +PREFIX ns1: +PREFIX ns2: PREFIX owl: PREFIX prov: PREFIX rdfs: @@ -17,14 +17,14 @@ PREFIX xsd: dcterms:modified "2023-03-16"^^xsd:date ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; dcterms:publisher ; - ns1:status ; + ns2:status ; skos:definition "The primary purpose of a borehole based on the legislative State Act and/or the resources industry sector."@en ; skos:prefLabel "Borehole Purpose"@en ; prov:qualifiedDerivation [ prov:entity ; prov:hadRole ] ; - ns2:childrenCount 8 ; + ns1:childrenCount 8 ; . dcterms:created @@ -37,6 +37,11 @@ dcterms:creator dcterms:description "Recommended practice is to identify the creator with a URI. If this is not possible or feasible, a literal value that identifies the creator may be provided."@en ; . +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; +. + dcterms:modified rdfs:label "Date Modified"@en ; dcterms:description "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty."@en ; @@ -54,4 +59,4 @@ dcterms:publisher skos:prefLabel "stable"@en ; schema:color "#2e8c09" ; -. +. \ No newline at end of file diff --git a/tests/data/vocprez/expected_responses/vocab_listing_anot.ttl b/tests/data/vocprez/expected_responses/vocab_listing_anot.ttl index db0eb520..1ede6a7a 100644 --- a/tests/data/vocprez/expected_responses/vocab_listing_anot.ttl +++ b/tests/data/vocprez/expected_responses/vocab_listing_anot.ttl @@ -7,6 +7,13 @@ PREFIX schema: PREFIX skos: PREFIX xsd: + + a skos:ConceptScheme ; + ns1:status ; + skos:prefLabel "BeddingSurfaceStructure"@en ; + ns2:link "/v/vocab/ref:BeddingSurfaceStructure" ; +. + a skos:ConceptScheme ; dcterms:provenance "Compiled by the Geological Survey of Queensland" ; @@ -33,6 +40,11 @@ PREFIX xsd: ns2:link "/v/vocab/def2:borehole-purpose-no-children" ; . +dcterms:provenance + rdfs:label "Provenance"@en ; + dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en ; +. + dcterms:publisher rdfs:label "Publisher"@en ; . @@ -68,11 +80,16 @@ dcterms:publisher ns2:link "/v/vocab/def:warox-alteration-types" ; . + + skos:prefLabel "experimental"@en ; + schema:color "#eae72c" ; +. + skos:prefLabel "stable"@en ; schema:color "#2e8c09" ; . skos:ConceptScheme - ns2:count 6 ; -. + ns2:count 7 ; +. \ No newline at end of file diff --git a/tests/data/vocprez/input/beddingsurfacestructure.ttl b/tests/data/vocprez/input/beddingsurfacestructure.ttl new file mode 100644 index 00000000..eeca1838 --- /dev/null +++ b/tests/data/vocprez/input/beddingsurfacestructure.ttl @@ -0,0 +1,177 @@ + . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + . + . + "A dictionary of bed surface structures, eg. ripples, dessication cracks."@en . + "Created for internal use in corporate BGS relational database"@en . + "BeddingSurfaceStructure"@en . + "2003-06-04"^^ . + "2003-06-04"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure"^^ . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "Shrinkage (Desiccation) Cracks"@en . + "Synaeresis Cracks"@en . + "Parting Lineation (Primary Current Lineation)"@en . + "Rainspots"@en . + "Ripples"@en . + "Current Ripples"@en . + "Linguoid Current Ripples"@en . + "Sinuous-Crested Current Rippled"@en . + "Straight-Crested Current Ripples"@en . + "Wave-Formed Ripples"@en . + "Interference Wave-Formed Ripples"@en . + "Modified Wave-Formed Ripples"@en . + "Wind Ripples"@en . + "Trace Fossils"@en . + "Crawling / Walking Tracks and Trails"@en . + "Foot Prints"@en . + "Grazing Traces"@en . + "Coiled Grazing Traces"@en . + "Meandering Grazing Traces"@en . + "Radial Grazing Traces"@en . + "Resting Traces"@en . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "SHRINKAGE (DESICCATION) CRACKS"@en . + "SYNAERESIS CRACKS"@en . + "PARTING LINEATION (PRIMARY CURRENT LINEATION)"@en . + "RAINSPOTS"@en . + "RIPPLES, TYPE UNDEFINED"@en . + "CURRENT RIPPLES"@en . + "LINGUOID CURRENT RIPPLES"@en . + "SINUOUS-CRESTED CURRENT RIPPLED"@en . + "STRAIGHT-CRESTED CURRENT RIPPLES"@en . + "WAVE-FORMED RIPPLES"@en . + "INTERFERENCE WAVE-FORMED RIPPLES"@en . + "MODIFIED WAVE-FORMED RIPPLES"@en . + "WIND RIPPLES"@en . + "TRACE FOSSILS, TYPE UNDEFINED"@en . + "CRAWLING / WALKING TRACKS AND TRAILS"@en . + "FOOT PRINTS"@en . + "GRAZING TRACES"@en . + "COILED GRAZING TRACES"@en . + "MEANDERING GRAZING TRACES"@en . + "RADIAL GRAZING TRACES"@en . + "RESTING TRACES"@en . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "Shrinkage (Desiccation) Cracks"@en . + "Synaeresis Cracks"@en . + "Parting Lineation (Primary Current Lineation)"@en . + "Rainspots"@en . + "Ripples"@en . + "Current Ripples"@en . + "Linguoid Current Ripples"@en . + "Sinuous-Crested Current Rippled"@en . + "Straight-Crested Current Ripples"@en . + "Wave-Formed Ripples"@en . + "Interference Wave-Formed Ripples"@en . + "Modified Wave-Formed Ripples"@en . + "Wind Ripples"@en . + "Trace Fossils"@en . + "Crawling / Walking Tracks and Trails"@en . + "Foot Prints"@en . + "Grazing Traces"@en . + "Coiled Grazing Traces"@en . + "Meandering Grazing Traces"@en . + "Radial Grazing Traces"@en . + "Resting Traces"@en . From 1825bbbf3d79d7540c649db6aeaa79279eec95a1 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Fri, 4 Aug 2023 16:50:42 +1000 Subject: [PATCH 07/15] Add test to showcase annotation values are included in response for reg:status and color --- tests/vocprez/test_endpoints_vocprez.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/vocprez/test_endpoints_vocprez.py b/tests/vocprez/test_endpoints_vocprez.py index cd099809..b4a572fa 100644 --- a/tests/vocprez/test_endpoints_vocprez.py +++ b/tests/vocprez/test_endpoints_vocprez.py @@ -92,6 +92,11 @@ def test_concept_scheme( "empty.ttl", "Return concept scheme and a prez:childrenCount of 0", ], + [ + "http://data.bgs.ac.uk/ref/BeddingSurfaceStructure", + "beddingsurfacestructure_top_concepts.ttl", + "Top concepts have the correct annotation values for reg:status and color", + ], ], ) def test_concept_scheme_top_concepts( From 3b1758bc7fe9084ec280af2337928d42e7ed5e71 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Sat, 5 Aug 2023 16:01:35 +1000 Subject: [PATCH 08/15] Rename curie router to identifier router and add identifier redirect endpoint --- prez/app.py | 4 +-- prez/queries/identifier.py | 18 ++++++++++++++ prez/routers/{curie.py => identifier.py} | 31 +++++++++++++++++++++++- prez/routers/object.py | 2 +- prez/routers/vocprez.py | 2 +- 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 prez/queries/identifier.py rename prez/routers/{curie.py => identifier.py} (65%) diff --git a/prez/app.py b/prez/app.py index 530f669e..f9f0324c 100644 --- a/prez/app.py +++ b/prez/app.py @@ -25,7 +25,7 @@ from prez.routers.spaceprez import router as spaceprez_router from prez.routers.sparql import router as sparql_router from prez.routers.vocprez import router as vocprez_router -from prez.routers.curie import router as curie_router +from prez.routers.identifier import router as identifier_router from prez.services.app_service import healthcheck_sparql_endpoints, count_objects from prez.services.app_service import populate_api_info, add_prefixes_to_prefix_graph from prez.services.exception_catchers import ( @@ -61,7 +61,7 @@ app.include_router(catprez_router) app.include_router(vocprez_router) app.include_router(spaceprez_router) -app.include_router(curie_router) +app.include_router(identifier_router) @app.middleware("http") diff --git a/prez/queries/identifier.py b/prez/queries/identifier.py new file mode 100644 index 00000000..3a2eaae0 --- /dev/null +++ b/prez/queries/identifier.py @@ -0,0 +1,18 @@ +from textwrap import dedent + +from jinja2 import Template + + +def get_foaf_homepage(iri: str) -> str: + query = Template( + """ + PREFIX foaf: + + SELECT DISTINCT ?url + WHERE { + <{{ iri }}> foaf:homepage ?url . + } + """ + ).render(iri=iri) + + return dedent(query) diff --git a/prez/routers/curie.py b/prez/routers/identifier.py similarity index 65% rename from prez/routers/curie.py rename to prez/routers/identifier.py index 8cff8c83..dd7cce00 100644 --- a/prez/routers/curie.py +++ b/prez/routers/identifier.py @@ -1,13 +1,42 @@ from fastapi import APIRouter, HTTPException, status -from fastapi.responses import PlainTextResponse +from fastapi.responses import PlainTextResponse, RedirectResponse from rdflib import URIRef from rdflib.term import _is_valid_uri from prez.services.curie_functions import get_uri_for_curie_id, get_curie_id_for_uri +from prez.queries.identifier import get_foaf_homepage +from prez.sparql.methods import sparql_query_non_async router = APIRouter(tags=["Identifier Resolution"]) +@router.get( + "/identifier/redirect", + summary="Get a redirect response to the resource landing page", + response_class=RedirectResponse, + responses={ + status.HTTP_404_NOT_FOUND: {"content": {"application/json": {}}}, + }, +) +def get_identifier_redirect_route(iri: str): + """ + The `iri` query parameter is used to return a redirect response with the value from the `foaf:homepage` lookup. + If no value is found, a 404 HTTP response is returned. + """ + query = get_foaf_homepage(iri) + _, result = sparql_query_non_async(query) + url = None + for row in result: + url = row["url"]["value"] + + if url is None: + raise HTTPException( + status.HTTP_404_NOT_FOUND, f"No homepage found for IRI {iri}." + ) + + return RedirectResponse(url) + + @router.get( "/identifier/curie/{iri:path}", summary="Get the IRI's CURIE identifier", diff --git a/prez/routers/object.py b/prez/routers/object.py index 8f9a941d..90176124 100644 --- a/prez/routers/object.py +++ b/prez/routers/object.py @@ -2,7 +2,7 @@ from starlette.responses import PlainTextResponse from prez.models import SpatialItem, VocabItem, CatalogItem -from prez.routers.curie import get_iri_route +from prez.routers.identifier import get_iri_route from prez.sparql.methods import sparql_query_non_async from prez.queries.object import object_inbound_query, object_outbound_query diff --git a/prez/routers/vocprez.py b/prez/routers/vocprez.py index 8b50d71c..a679cee2 100644 --- a/prez/routers/vocprez.py +++ b/prez/routers/vocprez.py @@ -29,7 +29,7 @@ get_concept_narrowers_query, ) from prez.response import StreamingTurtleAnnotatedResponse -from prez.routers.curie import get_iri_route +from prez.routers.identifier import get_iri_route router = APIRouter(tags=["VocPrez"]) From de0697f68c5596f431ff0f5af76c1c4764a98419 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Sun, 6 Aug 2023 16:04:13 +1000 Subject: [PATCH 09/15] Add tests for /identifier/redirect --- .github/workflows/on_pr_to_main.yaml | 2 +- .github/workflows/on_push_to_feature.yaml | 1 + prez/queries/identifier.py | 2 +- prez/routers/identifier.py | 4 +- .../input/redirect-foaf-homepage.ttl | 3 + tests/{curies => identifier}/conftest.py | 0 .../test_curie_endpoint.py | 0 .../test_curie_generation.py | 0 tests/identifier/test_redirect_endpoint.py | 61 +++++++++++++++++++ 9 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 tests/data/spaceprez/input/redirect-foaf-homepage.ttl rename tests/{curies => identifier}/conftest.py (100%) rename tests/{curies => identifier}/test_curie_endpoint.py (100%) rename tests/{curies => identifier}/test_curie_generation.py (100%) create mode 100644 tests/identifier/test_redirect_endpoint.py diff --git a/.github/workflows/on_pr_to_main.yaml b/.github/workflows/on_pr_to_main.yaml index f41485b4..b8dec758 100644 --- a/.github/workflows/on_pr_to_main.yaml +++ b/.github/workflows/on_pr_to_main.yaml @@ -63,6 +63,6 @@ jobs: cd ../catprez && poetry run pytest cd ../profiles && poetry run pytest cd ../services && poetry run pytest - cd ../curies && poetry run pytest + cd ../identifier && poetry run pytest cd ../object && poetry run pytest cd ../caching && poetry run pytest diff --git a/.github/workflows/on_push_to_feature.yaml b/.github/workflows/on_push_to_feature.yaml index c37b07f7..1064d0c5 100644 --- a/.github/workflows/on_push_to_feature.yaml +++ b/.github/workflows/on_push_to_feature.yaml @@ -61,4 +61,5 @@ jobs: cd ../catprez && poetry run pytest cd ../profiles && poetry run pytest cd ../services && poetry run pytest + cd ../identifier && poetry run pytest # cd ../local_sparql_store && poetry run pytest diff --git a/prez/queries/identifier.py b/prez/queries/identifier.py index 3a2eaae0..149170a3 100644 --- a/prez/queries/identifier.py +++ b/prez/queries/identifier.py @@ -3,7 +3,7 @@ from jinja2 import Template -def get_foaf_homepage(iri: str) -> str: +def get_foaf_homepage_query(iri: str) -> str: query = Template( """ PREFIX foaf: diff --git a/prez/routers/identifier.py b/prez/routers/identifier.py index dd7cce00..d5c2c5b6 100644 --- a/prez/routers/identifier.py +++ b/prez/routers/identifier.py @@ -4,7 +4,7 @@ from rdflib.term import _is_valid_uri from prez.services.curie_functions import get_uri_for_curie_id, get_curie_id_for_uri -from prez.queries.identifier import get_foaf_homepage +from prez.queries.identifier import get_foaf_homepage_query from prez.sparql.methods import sparql_query_non_async router = APIRouter(tags=["Identifier Resolution"]) @@ -23,7 +23,7 @@ def get_identifier_redirect_route(iri: str): The `iri` query parameter is used to return a redirect response with the value from the `foaf:homepage` lookup. If no value is found, a 404 HTTP response is returned. """ - query = get_foaf_homepage(iri) + query = get_foaf_homepage_query(iri) _, result = sparql_query_non_async(query) url = None for row in result: diff --git a/tests/data/spaceprez/input/redirect-foaf-homepage.ttl b/tests/data/spaceprez/input/redirect-foaf-homepage.ttl new file mode 100644 index 00000000..1274566e --- /dev/null +++ b/tests/data/spaceprez/input/redirect-foaf-homepage.ttl @@ -0,0 +1,3 @@ +PREFIX foaf: + + foaf:homepage . diff --git a/tests/curies/conftest.py b/tests/identifier/conftest.py similarity index 100% rename from tests/curies/conftest.py rename to tests/identifier/conftest.py diff --git a/tests/curies/test_curie_endpoint.py b/tests/identifier/test_curie_endpoint.py similarity index 100% rename from tests/curies/test_curie_endpoint.py rename to tests/identifier/test_curie_endpoint.py diff --git a/tests/curies/test_curie_generation.py b/tests/identifier/test_curie_generation.py similarity index 100% rename from tests/curies/test_curie_generation.py rename to tests/identifier/test_curie_generation.py diff --git a/tests/identifier/test_redirect_endpoint.py b/tests/identifier/test_redirect_endpoint.py new file mode 100644 index 00000000..92fdc04f --- /dev/null +++ b/tests/identifier/test_redirect_endpoint.py @@ -0,0 +1,61 @@ +import os +import subprocess +from time import sleep + +import pytest +from fastapi.testclient import TestClient + +PREZ_DIR = os.getenv("PREZ_DIR") +LOCAL_SPARQL_STORE = os.getenv("LOCAL_SPARQL_STORE") + + +@pytest.fixture(scope="module") +def test_client(request): + print("Run Local SPARQL Store") + p1 = subprocess.Popen(["python", str(LOCAL_SPARQL_STORE), "-p", "3032"]) + sleep(1) + + def teardown(): + print("\nDoing teardown") + p1.kill() + + request.addfinalizer(teardown) + + # must only import app after config.py has been altered above so config is retained + from prez.app import app + + return TestClient(app) + + +@pytest.mark.parametrize( + "iri, url, expected_response_code", + [ + [ + "http://data.bgs.ac.uk/id/dataHolding/13603129", + "http://metadata.bgs.ac.uk/geonetwork/srv/eng/catalog.search#/metadata/9df8df53-2a1d-37a8-e044-0003ba9b0d98", + 307, + ], + [ + "http://example.com/non-existent", + None, + 404, + ], + ], +) +def test_redirect_endpoint( + test_client: TestClient, iri: str, url: str, expected_response_code +): + params = {"iri": iri} + response = test_client.get( + "/identifier/redirect", params=params, follow_redirects=False + ) + + if expected_response_code != 404: + assert response.status_code == expected_response_code + assert response.headers.get("location") == url + else: + assert response.status_code == expected_response_code + assert response.headers.get("content-type") == "application/json" + data = response.json() + assert data.get("status_code") == expected_response_code + assert data.get("detail") == f"No homepage found for IRI {iri}." From 40225bd1cbf4210bd940de2e62ed4e3e01cc5275 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Mon, 7 Aug 2023 10:19:10 +1000 Subject: [PATCH 10/15] Add annotations from profile until graph stops expanding --- prez/renderers/renderer.py | 56 ++++++++++++++------------------------ 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/prez/renderers/renderer.py b/prez/renderers/renderer.py index adb76d22..a4d3f1b5 100644 --- a/prez/renderers/renderer.py +++ b/prez/renderers/renderer.py @@ -72,18 +72,7 @@ async def return_rdf(graph, mediatype, profile_headers): return StreamingResponse(content=obj, media_type=mediatype, headers=profile_headers) -async def return_annotated_rdf( - graph: Graph, - profile_headers, - profile, - predicates_for_link_addition: dict, - mediatype="text/anot+turtle", -): - from prez.cache import tbox_cache - - non_anot_mediatype = mediatype.replace("anot+", "") - - cache = tbox_cache +async def get_annotations_graph(profile, graph, cache): profile_annotation_props = get_annotation_predicates(profile) queries_for_uncached, annotations_graph = await get_annotation_properties( graph, **profile_annotation_props @@ -98,36 +87,33 @@ async def return_annotated_rdf( annotations_graph += anots_from_triplestore cache += anots_from_triplestore - # TODO: this portion of the code requires refactoring. - # Duplicated fragment code below is required to ensure new predicates and values - # defined in the profiles get added to the `graph` and the labels of those - # values also get added to the `graph`. + return annotations_graph - # start of duplicated code fragment - graph += annotations_graph - profile_annotation_props = get_annotation_predicates(profile) - queries_for_uncached, annotations_graph = await get_annotation_properties( - graph, **profile_annotation_props - ) +async def return_annotated_rdf( + graph: Graph, + profile_headers, + profile, + predicates_for_link_addition: dict, + mediatype="text/anot+turtle", +): + from prez.cache import tbox_cache - if queries_for_uncached is None: - anots_from_triplestore = Graph() - else: - anots_from_triplestore = await queries_to_graph([queries_for_uncached]) + non_anot_mediatype = mediatype.replace("anot+", "") - if len(anots_from_triplestore) > 1: - annotations_graph += anots_from_triplestore - cache += anots_from_triplestore - # end duplicated code fragment + cache = tbox_cache + + previous_triples_count = len(graph) + + while True: + graph += await get_annotations_graph(profile, graph, cache) + if len(graph) == previous_triples_count: + break + previous_triples_count = len(graph) generate_prez_links(graph, predicates_for_link_addition) - obj = io.BytesIO( - (graph + annotations_graph).serialize( - format=non_anot_mediatype, encoding="utf-8" - ) - ) + obj = io.BytesIO(graph.serialize(format=non_anot_mediatype, encoding="utf-8")) return StreamingResponse( content=obj, media_type=non_anot_mediatype, headers=profile_headers ) From 0303b6a22312e89be036f7b4f2564cdf35fcdae3 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Mon, 7 Aug 2023 10:19:29 +1000 Subject: [PATCH 11/15] Fix tests for new annotations expansion behaviour --- .../vocprez/expected_responses/collection_listing_anot.ttl | 5 +++++ tests/data/vocprez/expected_responses/vocab_listing_anot.ttl | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/tests/data/vocprez/expected_responses/collection_listing_anot.ttl b/tests/data/vocprez/expected_responses/collection_listing_anot.ttl index ea27d347..3f2a822e 100644 --- a/tests/data/vocprez/expected_responses/collection_listing_anot.ttl +++ b/tests/data/vocprez/expected_responses/collection_listing_anot.ttl @@ -12,6 +12,11 @@ PREFIX xsd: ns1:link "/v/collection/brhl-prps:pggd" ; . +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; +. + dcterms:provenance rdfs:label "Provenance"@en ; dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en ; diff --git a/tests/data/vocprez/expected_responses/vocab_listing_anot.ttl b/tests/data/vocprez/expected_responses/vocab_listing_anot.ttl index 1ede6a7a..ff6a8fa5 100644 --- a/tests/data/vocprez/expected_responses/vocab_listing_anot.ttl +++ b/tests/data/vocprez/expected_responses/vocab_listing_anot.ttl @@ -40,6 +40,11 @@ PREFIX xsd: ns2:link "/v/vocab/def2:borehole-purpose-no-children" ; . +dcterms:description + rdfs:label "Description"@en ; + dcterms:description "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en ; +. + dcterms:provenance rdfs:label "Provenance"@en ; dcterms:description "The statement may include a description of any changes successive custodians made to the resource."@en ; From 3b1fc159b84b4edb1c158c4f1fbfaaff09ce6c57 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Mon, 7 Aug 2023 10:38:40 +1000 Subject: [PATCH 12/15] Add comment --- prez/renderers/renderer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/prez/renderers/renderer.py b/prez/renderers/renderer.py index a4d3f1b5..8fa48b80 100644 --- a/prez/renderers/renderer.py +++ b/prez/renderers/renderer.py @@ -105,6 +105,7 @@ async def return_annotated_rdf( previous_triples_count = len(graph) + # Expand the graph with annotations specified in the profile until no new statements are added. while True: graph += await get_annotations_graph(profile, graph, cache) if len(graph) == previous_triples_count: From 5e49e68efe0dca1fcfc127f829e1f4744afd7fb0 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Tue, 8 Aug 2023 14:08:28 +1000 Subject: [PATCH 13/15] Update README.md with Redirect Service section --- README.md | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 075a9a78..d080c94d 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,14 @@ It expects "high quality" data to work well: Prez itself won't patch up bad or m Prez accesses data stored in an RDF database - a 'triplestore' - and uses the SPARQL Protocol to do so. Any SPARQL Protocol-compliant DB may be used. +## Redirect Service + +As a Linked Data server, Prez provides a redirect service at `/identifier/redirect` that accepts a query parameter `iri`, looks up the `iri` in the database for a `foaf:homepage` predicate with a value, and if it exists, return a redirect response to the value. + +This functionality is useful for institutions who issue their own persistent identifiers under a domain name that they control. The mapping from the persistent identifier to the target web resource is stored in the backend SPARQL store. + +This is an alternative solution to persistent identifier services such as the [w3id.org](https://w3id.org/). In some cases, it can be used together with such persistent identifier services to avoid the need to provide the redirect mapping in webserver config (NGINX, Apache HTTP, etc.) and instead, define the config as RDF data. + ## Development This section is for developing Prez locally. See the [Running](#running) options below for running Prez in production. @@ -84,20 +92,20 @@ via python-dotenv, or directly in the environment in which Prez is run. The envi instantiate a Pydantic `Settings` object which is used throughout Prez to configure its behaviour. To see how prez interprets/uses these environment variables see the `prez/config.py` file. -| Environment Variable | Description | -|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| SPARQL_ENDPOINT | Read-only SPARQL endpoint for SpacePrez | -| SPARQL_USERNAME | A username for Basic Auth against the SPARQL endpoint, if required by the SPARQL endpoint. | -| SPARQL_PASSWORD | A password for Basic Auth against the SPARQL endpoint, if required by the SPARQL endpoint. | -| PROTOCOL | The protocol used to deliver Prez. Usually 'http'. | -| HOST | The host on which to server prez, typically 'localhost'. | -| PORT | The port Prez is made accessible on. Default is 8000, could be 80 or anything else that your system has permission to use | -| SYSTEM_URI | Documentation property. An IRI for the Prez system as a whole. This value appears in the landing page RDF delivered by Prez ('/') | -| LOG_LEVEL | One of CRITICAL, ERROR, WARNING, INFO, DEBUG. Defaults to INFO. | -| LOG_OUTPUT | "file", "stdout", or "both" ("file" and "stdout"). Defaults to stdout. | -| PREZ_TITLE | The title to use for Prez instance | -| PREZ_DESC | A description to use for the Prez instance | -| DISABLE_PREFIX_GENERATION | Default value is `false`. Very large datasets may want to disable this setting and provide a predefined set of prefixes for namespaces as described in [Link Generation](README-Dev.md#link-generation). | +| Environment Variable | Description | +| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| SPARQL_ENDPOINT | Read-only SPARQL endpoint for SpacePrez | +| SPARQL_USERNAME | A username for Basic Auth against the SPARQL endpoint, if required by the SPARQL endpoint. | +| SPARQL_PASSWORD | A password for Basic Auth against the SPARQL endpoint, if required by the SPARQL endpoint. | +| PROTOCOL | The protocol used to deliver Prez. Usually 'http'. | +| HOST | The host on which to server prez, typically 'localhost'. | +| PORT | The port Prez is made accessible on. Default is 8000, could be 80 or anything else that your system has permission to use | +| SYSTEM_URI | Documentation property. An IRI for the Prez system as a whole. This value appears in the landing page RDF delivered by Prez ('/') | +| LOG_LEVEL | One of CRITICAL, ERROR, WARNING, INFO, DEBUG. Defaults to INFO. | +| LOG_OUTPUT | "file", "stdout", or "both" ("file" and "stdout"). Defaults to stdout. | +| PREZ_TITLE | The title to use for Prez instance | +| PREZ_DESC | A description to use for the Prez instance | +| DISABLE_PREFIX_GENERATION | Default value is `false`. Very large datasets may want to disable this setting and provide a predefined set of prefixes for namespaces as described in [Link Generation](README-Dev.md#link-generation). | ### Running in a Container From 1d77b66219daf05531f7d8417789110293ff32b7 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Tue, 8 Aug 2023 14:27:38 +1000 Subject: [PATCH 14/15] Forward on request headers so downstream redirected service can perform content negotiation --- prez/routers/identifier.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/prez/routers/identifier.py b/prez/routers/identifier.py index d5c2c5b6..3e05f47e 100644 --- a/prez/routers/identifier.py +++ b/prez/routers/identifier.py @@ -1,4 +1,4 @@ -from fastapi import APIRouter, HTTPException, status +from fastapi import APIRouter, HTTPException, status, Request from fastapi.responses import PlainTextResponse, RedirectResponse from rdflib import URIRef from rdflib.term import _is_valid_uri @@ -18,7 +18,7 @@ status.HTTP_404_NOT_FOUND: {"content": {"application/json": {}}}, }, ) -def get_identifier_redirect_route(iri: str): +def get_identifier_redirect_route(iri: str, request: Request): """ The `iri` query parameter is used to return a redirect response with the value from the `foaf:homepage` lookup. If no value is found, a 404 HTTP response is returned. @@ -34,7 +34,8 @@ def get_identifier_redirect_route(iri: str): status.HTTP_404_NOT_FOUND, f"No homepage found for IRI {iri}." ) - return RedirectResponse(url) + # Note: currently does not forward query parameters but we may want to implement this in the future. + return RedirectResponse(url, headers=request.headers) @router.get( From 62a2f0c7a8fc3b1b072563245f04b5ef3e80c5e2 Mon Sep 17 00:00:00 2001 From: Edmond Chuc Date: Tue, 8 Aug 2023 14:33:09 +1000 Subject: [PATCH 15/15] Update test to ensure headers are forwarded on. Mainly used for content negotiation with accept header. --- tests/identifier/test_redirect_endpoint.py | 23 ++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/identifier/test_redirect_endpoint.py b/tests/identifier/test_redirect_endpoint.py index 92fdc04f..26ce540b 100644 --- a/tests/identifier/test_redirect_endpoint.py +++ b/tests/identifier/test_redirect_endpoint.py @@ -28,31 +28,42 @@ def teardown(): @pytest.mark.parametrize( - "iri, url, expected_response_code", + "iri, url, expected_response_code, accept_header_value", [ [ "http://data.bgs.ac.uk/id/dataHolding/13603129", "http://metadata.bgs.ac.uk/geonetwork/srv/eng/catalog.search#/metadata/9df8df53-2a1d-37a8-e044-0003ba9b0d98", 307, + "", ], + ["http://example.com/non-existent", None, 404, ""], [ - "http://example.com/non-existent", - None, - 404, + "http://data.bgs.ac.uk/id/dataHolding/13603129", + "http://metadata.bgs.ac.uk/geonetwork/srv/eng/catalog.search#/metadata/9df8df53-2a1d-37a8-e044-0003ba9b0d98", + 307, + "text/turtle", ], ], ) def test_redirect_endpoint( - test_client: TestClient, iri: str, url: str, expected_response_code + test_client: TestClient, + iri: str, + url: str, + expected_response_code, + accept_header_value: str | None, ): params = {"iri": iri} + headers = {"accept": accept_header_value} response = test_client.get( - "/identifier/redirect", params=params, follow_redirects=False + "/identifier/redirect", params=params, headers=headers, follow_redirects=False ) if expected_response_code != 404: assert response.status_code == expected_response_code assert response.headers.get("location") == url + + if accept_header_value: + assert response.headers.get("accept") == accept_header_value else: assert response.status_code == expected_response_code assert response.headers.get("content-type") == "application/json"