|
@@ -74,6 +74,26 @@ def parse_accept_header(accept: str) -> List[str]:
|
|
|
return [pref[0] for pref in preferences]
|
|
|
|
|
|
|
|
|
+def add_cell_to_graph(graph: ConjunctiveGraph, iri: str, row: int, column: int, cell_value: Any, verbose: bool) -> None:
|
|
|
+ """Adds a Cell as known in the SDO2L ontology to the graph."""
|
|
|
+ tabular_prefix = "http://ua.be/sdo2l/vocabulary/formalism/tabular"
|
|
|
+ cell = URIRef(f"{iri}-cell-{row}-{column}")
|
|
|
+ # Store the triples in a temporary graph. This allows us to use the rdflib query engine for the sub-query instead of finding the matching pairs manually.
|
|
|
+ graph.add((cell, URIRef(f"{tabular_prefix}#holdsContent"), Literal(cell_value)))
|
|
|
+ graph.add((cell, URIRef(f"{tabular_prefix}#hasRowPosition"), Literal(int(row))))
|
|
|
+ graph.add((cell, URIRef(f"{tabular_prefix}#hasColumnPosition"), Literal(int(column))))
|
|
|
+
|
|
|
+ if verbose:
|
|
|
+ graph.add((cell, URIRef(f"{tabular_prefix}#isCellOfTabularData"), URIRef(f"{iri}")))
|
|
|
+ graph.add((cell, URIRef(f"{tabular_prefix}#isInCollection"), URIRef(f"{iri}-column-{int(column)}")))
|
|
|
+ graph.add((cell, URIRef(f"{tabular_prefix}#isInCollection"), URIRef(f"{iri}-row-{int(row)}")))
|
|
|
+
|
|
|
+ graph.add((cell, RDF.type, OWL.Thing))
|
|
|
+ graph.add((cell, RDF.type, URIRef("http://ua.be/sdo2l/vocabulary/formalism/tabular#Cell")))
|
|
|
+ graph.add((cell, RDF.type, URIRef("http://ua.be/sdo2l/vocabulary/formalism/file#Data")))
|
|
|
+ graph.add((cell, OWL.sameAs, URIRef(f"{iri}-cell-{int(row)}-{int(column)}")))
|
|
|
+
|
|
|
+
|
|
|
class SparqlRouter(APIRouter):
|
|
|
"""Class to deploy a SPARQL endpoint using a RDFLib Graph."""
|
|
|
|
|
@@ -105,7 +125,7 @@ class SparqlRouter(APIRouter):
|
|
|
|
|
|
@self.get("/")
|
|
|
async def sparql_endpoint_get(request: Request, query: Optional[str] = Query(None)) -> Response:
|
|
|
- """"""
|
|
|
+ """Returns an empty result."""
|
|
|
# The graph is empty, so you would expect this to never return any pairs.
|
|
|
# But we inject pairs in the custom functions!
|
|
|
logging.debug("Received GET request.")
|
|
@@ -124,7 +144,7 @@ class SparqlRouter(APIRouter):
|
|
|
|
|
|
@self.post("/")
|
|
|
async def sparql_endpoint_post(request: Request, query: Optional[str] = Query(None)) -> Response:
|
|
|
- """"""
|
|
|
+ """Returns an empty result."""
|
|
|
logging.debug("Received POST request.")
|
|
|
if not query:
|
|
|
query_body = await request.body()
|
|
@@ -150,26 +170,7 @@ class SparqlRouter(APIRouter):
|
|
|
# graph_ns["tabular"] = "http://ua.be/sdo2l/vocabulary/formalisms/tabular#"
|
|
|
df = pd.read_csv(f"data/{file_name}", index_col=None, header=None)
|
|
|
cell_value = df.iat[int(row), int(column)]
|
|
|
-
|
|
|
- tabular_prefix = "http://ua.be/sdo2l/vocabulary/formalism/tabular"
|
|
|
-
|
|
|
- # instance_prefix, instance_designator = iri.split("#")
|
|
|
- cell = URIRef(f"{iri}-cell-{row}-{column}")
|
|
|
- # Store the triples in a temporary graph. This allows us to use the rdflib query engine for the sub-query instead of finding the matching pairs manually.
|
|
|
- graph.add((cell, URIRef(f"{tabular_prefix}#holdsContent"), Literal(cell_value)))
|
|
|
- graph.add((cell, URIRef(f"{tabular_prefix}#hasRowPosition"), Literal(int(row))))
|
|
|
- graph.add((cell, URIRef(f"{tabular_prefix}#hasColumnPosition"), Literal(int(column))))
|
|
|
-
|
|
|
- if verbose:
|
|
|
- graph.add((cell, URIRef(f"{tabular_prefix}#isCellOfTabularData"), URIRef(f"{iri}")))
|
|
|
- graph.add((cell, URIRef(f"{tabular_prefix}#isInCollection"), URIRef(f"{iri}-column-{int(column)}")))
|
|
|
- graph.add((cell, URIRef(f"{tabular_prefix}#isInCollection"), URIRef(f"{iri}-row-{int(row)}")))
|
|
|
-
|
|
|
- graph.add((cell, RDF.type, OWL.Thing))
|
|
|
- graph.add((cell, RDF.type, URIRef("http://ua.be/sdo2l/vocabulary/formalism/tabular#Cell")))
|
|
|
- graph.add((cell, RDF.type, URIRef("http://ua.be/sdo2l/vocabulary/formalism/file#Data")))
|
|
|
- graph.add((cell, OWL.sameAs, URIRef(f"{iri}-cell-{int(row)}-{int(column)}")))
|
|
|
-
|
|
|
+ add_cell_to_graph(graph, iri, int(row), int(column),cell_value, verbose)
|
|
|
logging.debug(f"{cell_value=}")
|
|
|
|
|
|
try:
|
|
@@ -179,9 +180,9 @@ class SparqlRouter(APIRouter):
|
|
|
return JSONResponse(status_code=400, content={"message": "Error executing the SPARQL query on the RDFLib Graph."})
|
|
|
return await encode_graph_query_results(request, query_results)
|
|
|
|
|
|
-
|
|
|
- @self.get("/cell/{file_name}/")
|
|
|
- async def sparql_sheet_endpoint_get(request: Request, file_name, query: Optional[str] = Query(None)) -> Response:
|
|
|
+ @self.get("/cell/{iri}/{file_name}/")
|
|
|
+ async def sparql_sheet_endpoint_get(request: Request, iri, file_name, query: Optional[str] = Query(None), verbose: bool = True) -> Response:
|
|
|
+ """Return all cell in SDO2L notation for a file."""
|
|
|
logging.debug(f"Received sheet GET request [{file_name}].")
|
|
|
graph = ConjunctiveGraph()
|
|
|
graph_ns = dict(graph.namespaces())
|
|
@@ -190,13 +191,10 @@ class SparqlRouter(APIRouter):
|
|
|
df.reset_index()
|
|
|
|
|
|
# Please forgive me pandas gods
|
|
|
- for i in range(df.shape[0]):
|
|
|
- for j in range(df.shape[1]):
|
|
|
- cell_value = df.at[i, j]
|
|
|
- cell = URIRef(f"http://ua.be/sdo2l/vocabulary/formalisms/tabular#Cell_{i}_{j}")
|
|
|
- graph.add((cell, URIRef("http://ua.be/sdo2l/vocabulary/formalisms/tabular#holdsContent"), Literal(cell_value)))
|
|
|
- graph.add((cell, URIRef("http://ua.be/sdo2l/vocabulary/formalisms/tabular#hasRowPosition"), Literal(int(i))))
|
|
|
- graph.add((cell, URIRef("http://ua.be/sdo2l/vocabulary/formalisms/tabular#hasColumnPosition"), Literal(int(j))))
|
|
|
+ for row in range(df.shape[0]):
|
|
|
+ for column in range(df.shape[1]):
|
|
|
+ cell_value = df.at[row, column]
|
|
|
+ add_cell_to_graph(graph, iri, int(row), int(column), cell_value, verbose)
|
|
|
|
|
|
try:
|
|
|
query_results = graph.query(query, initNs=graph_ns)
|
|
@@ -205,12 +203,13 @@ class SparqlRouter(APIRouter):
|
|
|
return JSONResponse(status_code=400, content={"message": "Error executing the SPARQL query on the RDFLib Graph."})
|
|
|
return await encode_graph_query_results(request, query_results)
|
|
|
|
|
|
- @self.get("/cell/{file_name}/{row}/{column}/")
|
|
|
- async def sparql_cell_endpoint_get(request: Request, file_name, row, column, query: Optional[str] = Query(None)) -> Response:
|
|
|
+ @self.get("/cell/{iri}/{file_name}/{row}/{column}/")
|
|
|
+ async def sparql_cell_endpoint_get(request: Request, iri, file_name, row, column, query: Optional[str] = Query(None), verbose: bool = True) -> Response:
|
|
|
"""
|
|
|
Create an ephemeral graph store based on the call parameters and perform the requested query.
|
|
|
SELECT ?s ?p ?o WHERE {
|
|
|
bind(str('http://localhost:8000') as ?base)
|
|
|
+ bind(str('iri') as ?iri)
|
|
|
bind(str('cell') as ?operation)
|
|
|
bind(str('example.csv') as ?file)
|
|
|
bind(str(2) as ?row)
|
|
@@ -225,11 +224,7 @@ class SparqlRouter(APIRouter):
|
|
|
# graph_ns["tabular"] = "http://ua.be/sdo2l/vocabulary/formalisms/tabular#"
|
|
|
df = pd.read_csv(f"data/{file_name}", index_col=None, header=None)
|
|
|
cell_value = df.iat[int(row), int(column)]
|
|
|
- cell = URIRef(f"http://ua.be/sdo2l/vocabulary/formalisms/tabular#Cell_{row}_{column}")
|
|
|
- # Store the triples in a temporary graph. This allows us to use the rdflib query engine for the sub-query instead of finding the matching pairs manually.
|
|
|
- graph.add((cell, URIRef("http://ua.be/sdo2l/vocabulary/formalisms/tabular#holdsContent"), Literal(cell_value)))
|
|
|
- graph.add((cell, URIRef("http://ua.be/sdo2l/vocabulary/formalisms/tabular#hasRowPosition"), Literal(int(row))))
|
|
|
- graph.add((cell, URIRef("http://ua.be/sdo2l/vocabulary/formalisms/tabular#hasColumnPosition"), Literal(int(column))))
|
|
|
+ add_cell_to_graph(graph, iri, int(row), int(column), cell_value, verbose)
|
|
|
logging.debug(f"{cell_value=}")
|
|
|
|
|
|
try:
|