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