Skip to content

Commit

Permalink
simplest simple json
Browse files Browse the repository at this point in the history
  • Loading branch information
aaxelb committed May 20, 2024
1 parent fb8de52 commit 5be7f2d
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 2 deletions.
4 changes: 4 additions & 0 deletions share/search/search_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
class BaseTroveParams:
iri_shorthand: primitive_rdf.IriShorthand
include: frozenset[tuple[str, ...]]
accept_mediatype: str | None

@classmethod
def from_querystring(cls, querystring: str) -> 'BaseTroveParams': # TODO py3.11: typing.Self
Expand All @@ -74,6 +75,7 @@ def parse_queryparams(cls, queryparams: QueryparamDict) -> dict:
return {
'iri_shorthand': cls._gather_shorthand(queryparams),
'include': cls._gather_include(queryparams.get('include', [])),
'accept_mediatype': _get_single_value(queryparams, QueryparamName('acceptMediatype')),
}

def to_querystring(self) -> str:
Expand All @@ -82,6 +84,8 @@ def to_querystring(self) -> str:
def to_querydict(self) -> QueryDict:
# subclasses should override and add their fields to super().to_querydict()
_querydict = QueryDict(mutable=True)
if self.accept_mediatype:
_querydict['acceptMediatype'] = self.accept_mediatype
# TODO: self.iri_shorthand, self.include
return _querydict

Expand Down
2 changes: 2 additions & 0 deletions trove/render/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .html_browse import RdfHtmlBrowseRenderer
from .turtle import RdfTurtleRenderer
from .jsonld import RdfJsonldRenderer
from .simple_json import TrovesearchSimpleJsonRenderer


RENDERER_BY_MEDIATYPE = {
Expand All @@ -13,6 +14,7 @@
RdfJsonapiRenderer,
RdfTurtleRenderer,
RdfJsonldRenderer,
TrovesearchSimpleJsonRenderer,
)
}

Expand Down
100 changes: 100 additions & 0 deletions trove/render/simple_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import json

from primitive_metadata import primitive_rdf as rdf

from trove.vocab.jsonapi import (
JSONAPI_LINK_OBJECT,
JSONAPI_MEMBERNAME,
)
from trove.vocab.namespaces import TROVE, RDF
from ._base import BaseRenderer


class TrovesearchSimpleJsonRenderer(BaseRenderer):
'''for "simple json" search api -- very entangled with trove/trovesearch_gathering.py
'''
MEDIATYPE = 'application/json'

def render_document(self, data: rdf.RdfTripleDictionary, focus_iri: str) -> str:
_focustypes = data[focus_iri][RDF.type]
_graph = rdf.RdfGraph(data)
if TROVE.Cardsearch in _focustypes:
_jsonable = self._render_cardsearch(_graph, focus_iri)
elif TROVE.Valuesearch in _focustypes:
_jsonable = self._render_valuesearch(_graph, focus_iri)
elif TROVE.Indexcard in _focustypes:
_jsonable = self._render_card(_graph, focus_iri)
else:
raise NotImplementedError(f'simplejson not implemented for any of {_focustypes}')
# TODO: links, total in 'meta'
return json.dumps({
'data': _jsonable,
'links': self._render_links(_graph, focus_iri),
'meta': self._render_meta(_graph, focus_iri),
}, indent=2)

def _render_cardsearch(self, graph: rdf.RdfGraph, cardsearch_iri: str):
return self._render_searchresultpage(graph, cardsearch_iri)

def _render_valuesearch(self, graph: rdf.RdfGraph, valuesearch_iri: str):
return self._render_searchresultpage(graph, valuesearch_iri)

def _render_searchresultpage(self, graph: rdf.RdfGraph, focus_iri: str):
# just each card's contents
_results_sequence = next(
_page
for _page in graph.q(focus_iri, TROVE.searchResultPage)
if rdf.is_container(_page) # filter out page links
)
return [
self._render_result(graph, _search_result_blanknode)
for _search_result_blanknode in rdf.sequence_objects_in_order(_results_sequence)
]

def _render_result(self, graph: rdf.RdfGraph, search_result_blanknode: rdf.RdfBlanknode):
_card = next(
_obj
for _pred, _obj in search_result_blanknode
if _pred == TROVE.indexCard
)
return self._render_card(graph, _card)

def _render_card(self, graph: rdf.RdfGraph, card: str | rdf.RdfBlanknode):
# just the card contents
if isinstance(card, str):
_card_contents = next(graph.q(card, TROVE.resourceMetadata))
elif isinstance(card, frozenset):
_card_contents = next(
_obj
for _pred, _obj in card
if _pred == TROVE.resourceMetadata
)
else:
raise NotImplementedError
assert isinstance(_card_contents, rdf.Literal)
assert RDF.JSON in _card_contents.datatype_iris
return json.loads(_card_contents.unicode_value)

def _render_meta(self, graph: rdf.RdfGraph, focus_iri: str):
_meta = {}
try:
_total = next(graph.q(focus_iri, TROVE.totalResultCount))
if isinstance(_total, int):
_meta['total'] = _total
elif isinstance(_total, rdf.Literal):
_meta['total'] = int(_total.unicode_value)
elif _total == TROVE['ten-thousands-and-more']:
_meta['total'] = 'trove:ten-thousands-and-more'
except StopIteration:
pass
return _meta

def _render_links(self, graph: rdf.RdfGraph, focus_iri: str):
_links = {}
for _pagelink in graph.q(focus_iri, TROVE.searchResultPage):
_twopledict = rdf.twopledict_from_twopleset(_pagelink)
if JSONAPI_LINK_OBJECT in _twopledict.get(RDF.type, ()):
(_membername,) = _twopledict[JSONAPI_MEMBERNAME]
(_link_url,) = _twopledict[RDF.value]
_links[_membername.unicode_value] = _link_url
return _links
2 changes: 1 addition & 1 deletion trove/views/indexcard.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def get(self, request, indexcard_uuid):
# TODO (gather): allow omitting kwargs that go unused
'search_params': None,
'specific_index': None,
'use_osfmap_json': (_renderer.MEDIATYPE == JSONAPI_MEDIATYPE)
'use_osfmap_json': (_renderer.MEDIATYPE in {'application/json', JSONAPI_MEDIATYPE})
})
_indexcard_iri = trove_indexcard_iri(indexcard_uuid)
_search_gathering.ask(
Expand Down
2 changes: 1 addition & 1 deletion trove/views/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,6 @@ def _parse_request(request: http.HttpRequest, search_params_dataclass):
_search_gathering = trovesearch_by_indexstrategy.new_gathering({
'search_params': _search_params,
'specific_index': _specific_index,
'use_osfmap_json': (_renderer.MEDIATYPE == JSONAPI_MEDIATYPE),
'use_osfmap_json': (_renderer.MEDIATYPE in {'application/json', JSONAPI_MEDIATYPE})
})
return (_search_iri, _search_gathering, _renderer)

0 comments on commit 5be7f2d

Please sign in to comment.