abaev-basex/xq/restx_api.xq
2025-03-22 23:43:48 +03:00

201 lines
No EOL
6.6 KiB
Text

declare namespace api = 'http://ossetic-studies.org/ns/abaevdict-api';
declare namespace tei = "http://www.tei-c.org/ns/1.0";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
(: ======================================================= :)
(: ==================== API STUFF ======================== :)
(: ======================================================= :)
declare option output:method 'json';
declare option output:json "format=xquery";
declare variable $langs-index := doc('abaevdict_index/langnames.xml');
declare variable $lookup := doc('abaevdict_index/lookup.xml');
(: Get the mentioned index for the right metalanguage :)
declare function api:ment-index($db-lang as xs:string) {
doc(`abaevdict_index/mentioned_{$db-lang}.xml`)
};
(: Short entry info (only forms for now). Hash is used because URLs don't handle
some Unicode characters very well in this system :)
declare function api:entry-info-short($n as node())
as map(xs:string, item()) {
map{'id': string(hash($n/@xml:id)),
'xmlid': string($n/@xml:id),
'form': $n/text()
}
};
declare function api:entry-info-long($n as node(), $db-lang as xs:string)
as map(xs:string, item()) {
map:merge(
(
api:entry-info-short($n),
map{'glosses': array:build(data(doc(`abaevdict_{$db-lang}/xml/{$n/@xml:id}.xml`)
/tei:entry[1]/tei:sense/(tei:sense|tei:sense/tei:sense|.)/tei:cit/tei:quote))}
)
)
};
(: Short language info -- for the language list :)
declare function api:lang-info-short($n as node(), $db-lang as xs:string) {
map{
'id': $n/code/text(),
'glottolog': $n/glottolog/text(),
'name': map{'full': if ($db-lang = 'ru') then $n/ru/text() else $n/en/text(),
'abbr': if ($db-lang = 'ru') then $n/ru/text() else $n/en_abbr/text()}
}
};
(: Longer info -- for individual languages :)
declare function api:lang-info-full($n as node(), $db-lang as xs:string) {
map:merge(
(api:lang-info-short($n, $db-lang),
map{'words':
array:build(api:ment-index($db-lang)/lang-index[1]/lang[@id=$n/code]/word,
api:word-info-short#1)
}
)
)
};
declare function api:word-info-short($n as node()) {
let $text := xs:string($n/@text)
return map{
(: I am using a hash function as ID, because the words are uniquely
identified within a language by their text. And the mentioned index is not
persistent enough (at least yet) to use persistent ids :)
'id': string(hash($text)),
'text': $text
}
};
declare function api:word-info-long($n as node()) {
map:merge(
(
api:word-info-short($n),
map{
'entries': array:build($n/entry,
fn {
map{'id': string(hash(./@id)),
'xmlid': string(./@id),
'refs': array:build(./ref,
fn {
map:merge((
map:entry('path', string(./@path)),
if(./gloss) then
{'glosses': array:build(distinct-values(./gloss/@text), string#1)}
else ()
)
)
})
}
}
)
(: 'nodes': array:build(string($n/ref/@node-id)),
'glosses': array:build(string($n/gloss/@text)) :)
}
)
)
};
(: RETURN JSON FOR PLOTLY MAP :)
(: English as default language :)
declare %rest:path("dict/map-info/{$entry}")
%rest:GET
function api:map-info($entry) {
(: In this case we do not redirect, but simply give the JSON via
another function :)
api:map-info('en', $entry)
};
(: This has to be remade to use the /api path. But keep it like this for now :)
declare %rest:path("{$lang}/dict/map-info/{$entry}")
%rest:GET
function api:map-info($lang, $entry) {
let $ments := abv-m:make-geomap(doc(`abaevdict_{$lang}/xml/{$entry}.xml`),
$lang)
return $ments
};
(: API FOR THE MENTIONED INDEX :)
(: Default to English :)
declare %rest:path("/api/{$path=.+}")
%rest:GET
function api:default($path as xs:string) {
web:forward(`/en/api/{$path}`)
};
(: Get languages :)
declare %rest:path("{$db-lang}/api/languages")
%rest:GET
function api:langs($db-lang as xs:string := 'en') {
array:build(
$langs-index/csv[1]/record,
api:lang-info-short(?,$db-lang)
)
};
(: Get one language :)
declare %rest:path("{$db-lang}/api/languages/{$lang}")
%rest:GET
function api:langs-lang($db-lang as xs:string, $lang as xs:string) {
api:lang-info-full(
$langs-index/csv[1]/record[code=$lang], $db-lang
)
};
(: Get words for a language :)
declare %rest:path("{$db-lang}/api/languages/{$lang}/words")
%rest:GET
function api:langs-lang-words($db-lang as xs:string, $lang as xs:string) {
array:build(api:ment-index($db-lang)/lang-index[1]/lang[@id=$lang]/word,
api:word-info-short#1)
};
(: Get info on a particular word.
Db-lang is a placeholder, it does nothing here, used only for consistency :)
declare %rest:path("{$db-lang}/api/languages/{$lang}/words/{$word-id}")
%rest:GET
function api:langs-lang-words-word($db-lang as xs:string,
$lang as xs:string,
$word-id as xs:string) {
api:word-info-long(
api:ment-index($db-lang)/lang-index[1]/lang[@id=$lang]/word[string(hash(@text))=$word-id]
)
};
(: Entry info :)
declare %rest:path("{$db-lang}/api/entries")
%rest:GET
function api:entries($db-lang as xs:string) {
array:build(
$lookup/tei:table[1]/tei:entry,
api:entry-info-short#1
)
};
declare %rest:path("{$db-lang}/api/entries/{$entry-id}")
%rest:GET
function api:entries($db-lang as xs:string,
$entry-id as xs:string) {
api:entry-info-long(
$lookup/tei:table[1]/tei:entry[string(hash(@xml:id))=$entry-id],
$db-lang)
};
(: Search API :)
declare %rest:path("{$db-lang}/api/search")
%rest:query-param("type","{$type}",'full')
%rest:query-param("query","{$query}")
%rest:GET
function api:search($db-lang as xs:string,
$type as xs:string,
$query as xs:string) {
abv-m:search($db-lang,$type,$query)
};
0