Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow multiple template SPARQL queries for an object/item endpo… #319

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README-Dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -687,7 +687,7 @@ PREFIX prez: <https://prez.dev/ont/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
INSERT DATA { GRAPH <https://prez/system> {
[ a prez:TemplateQuery ;
rdf:value """<template_query>
rdf:value """<template_queries>
""" ;
prez:forEndpoint "http://www.opengis.net/ogcapi-features-1/1.0/feature" ;
]
Expand Down
1 change: 0 additions & 1 deletion prez/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ class Settings(BaseSettings):
custom_endpoints: bool = False
configuration_mode: bool = False
temporal_predicate: Optional[URIRef] = SDO.temporal
endpoint_to_template_query_filename: Optional[Dict[str, str]] = {}
prez_ui_url: Optional[str] = None
search_method: SearchMethod = SearchMethod.DEFAULT
required_header: dict[str, str] | None = None
Expand Down
16 changes: 6 additions & 10 deletions prez/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,24 +626,20 @@ async def get_ogc_features_mediatype(
return default_mt


async def get_template_query(
async def get_template_queries(
endpoint_uri_type: tuple[URIRef, URIRef] = Depends(get_endpoint_uri_type),
):
) -> list[str] | None:
endpoint_uri = endpoint_uri_type[0]
filename = settings.endpoint_to_template_query_filename.get(str(endpoint_uri))

# check local files
if filename:
return (
Path(__file__).parent / "reference_data/template_queries" / filename
).read_text()

template_queries = []
# check prez_system_graph
for s in prez_system_graph.subjects(RDF.type, ONT.TemplateQuery):
endpoint_in_sys_graph = prez_system_graph.value(s, ONT.forEndpoint, None)
if str(endpoint_uri) == str(endpoint_in_sys_graph):
template_query = prez_system_graph.value(s, RDF.value, None)
return str(template_query)
template_queries.append(str(template_query))
if template_queries:
return template_queries
return None


Expand Down
6 changes: 3 additions & 3 deletions prez/routers/ogc_features_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
get_ogc_features_path_params,
get_profile_nodeshape,
get_system_repo,
get_template_query,
get_template_queries,
get_url,
)
from prez.exceptions.model_exceptions import (
Expand Down Expand Up @@ -190,7 +190,7 @@ async def listings_with_feature_collection(
openapi_extra=ogc_features_openapi_extras.get("feature"),
)
async def objects(
template_query: Optional[str] = Depends(get_template_query),
template_queries: Optional[str] = Depends(get_template_queries),
mediatype: str = Depends(get_ogc_features_mediatype),
url: str = Depends(get_url),
path_params: dict = Depends(get_ogc_features_path_params),
Expand All @@ -199,7 +199,7 @@ async def objects(
):
try:
content, headers = await ogc_features_object_function(
template_query,
template_queries,
mediatype,
url,
data_repo,
Expand Down
48 changes: 27 additions & 21 deletions prez/services/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@


async def object_function(
data_repo,
system_repo,
endpoint_structure,
pmts,
profile_nodeshape,
data_repo,
system_repo,
endpoint_structure,
pmts,
profile_nodeshape,
):
if pmts.selected["profile"] == ALTREXT["alt-profile"]:
none_keys = [
Expand Down Expand Up @@ -126,23 +126,27 @@ def create_parent_link(url):


async def ogc_features_object_function(
template_query,
selected_mediatype,
url,
data_repo,
system_repo,
path_params,
template_queries,
selected_mediatype,
url,
data_repo,
system_repo,
path_params,
):
collection_uri = path_params.get("collection_uri")
feature_uri = path_params.get("feature_uri")
if template_query:
queries = []
if template_queries:
if feature_uri:
focus_uri = feature_uri
else:
focus_uri = collection_uri
query = template_query.replace(
"VALUES ?focusNode { UNDEF }", f"VALUES ?focusNode {{ {focus_uri.n3()} }}"
)
for query in template_queries:
queries.append(
query.replace(
"VALUES ?focusNode { UNDEF }", f"VALUES ?focusNode {{ {focus_uri.n3()} }}"
)
)
else:
if feature_uri is None: # feature collection
collection_iri = IRI(value=collection_uri)
Expand All @@ -167,13 +171,15 @@ async def ogc_features_object_function(
construct_tss_list = [
TriplesSameSubject.from_spo(*triple) for triple in triples
]
query = PrezQueryConstructor(
construct_tss_list=construct_tss_list,
profile_triples=tssp_list,
).to_string()
queries.append(
PrezQueryConstructor(
construct_tss_list=construct_tss_list,
profile_triples=tssp_list,
).to_string()
)

query_start_time = time.time()
item_graph, _ = await data_repo.send_queries([query], [])
item_graph, _ = await data_repo.send_queries(queries, [])
if len(item_graph) == 0:
uri = feature_uri if feature_uri else collection_uri
raise URINotFoundException(uri=uri)
Expand All @@ -182,7 +188,7 @@ async def ogc_features_object_function(

link_headers = None
if selected_mediatype == "application/sparql-query":
content = io.BytesIO(query.encode("utf-8"))
content = io.BytesIO("\n".join(queries).encode("utf-8"))
elif selected_mediatype == "application/json":
collectionId = get_curie_id_for_uri(collection_uri)
collection = create_collection_json(
Expand Down
Loading