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

[ENG-5494] simplest simple json #818

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
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)
Loading