Skip to content

Commit fb4d4fe

Browse files
committed
add/update functions
for new endpoint `/{schema}/{version}/elements/{id}`
1 parent 81e6146 commit fb4d4fe

File tree

2 files changed

+116
-7
lines changed

2 files changed

+116
-7
lines changed

source/xql/common.xqm

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module namespace common="http://odd-api.edirom.de/xql/common";
88
declare namespace http="http://expath.org/ns/http-client";
99
declare namespace rest="http://exquery.org/ns/restxq";
1010
declare namespace tei="http://www.tei-c.org/ns/1.0";
11+
declare namespace util="http://exist-db.org/xquery/util";
1112
declare namespace xmldb="http://exist-db.org/xquery/xmldb";
1213

1314
import module namespace config="http://odd-api.edirom.de/xql/config" at "config.xqm";
@@ -85,26 +86,33 @@ declare function common:get-offset($offset as xs:string*) as xs:positiveInteger
8586
: @param $docLang Language code for documentation (e.g., "en")
8687
: @return A map with 'ident', 'desc', 'gloss', 'type', 'namespace', and 'module' entries
8788
:)
88-
declare function common:get-spec-basic-data($spec as element(), $docLang as xs:string) as map(*) {
89-
let $desc := $spec/tei:desc[@xml:lang = $docLang] => normalize-space()
90-
let $gloss := $spec/tei:gloss[@xml:lang = $docLang] => normalize-space()
89+
declare function common:get-spec-basic-data($spec as element(), $docLang as xs:string*) as map(*) {
9190
let $module := $spec/data(@module)
9291
let $type :=
9392
if($spec/@type = 'atts') then 'attributeClass'
9493
else if($spec/@type = 'model') then 'modelClass'
9594
else fn:substring-before($spec/fn:local-name(), 'Spec')
96-
let $namespace := $spec/data(@ns)
95+
let $namespace := common:work-out-namespace($spec)
9796
let $spec-basic-data :=
9897
map {
9998
'ident': $spec/data(@ident),
100-
'desc': $desc,
101-
'type': $type
99+
'desc':
100+
array {
101+
if($docLang)
102+
then $spec/tei:desc[@xml:lang = $docLang] ! map { "lang": string(./@xml:lang), "text": normalize-space(.) }
103+
else $spec/tei:desc ! map { "lang": string(./@xml:lang), "text": normalize-space(.) }
104+
} => array:sort((), function($obj) {$obj?lang})
102105
}
103106
return
104107
switch($type)
105108
case 'element' return
106109
map:merge(($spec-basic-data, map {
107-
'gloss': $gloss,
110+
'gloss':
111+
array {
112+
if($docLang)
113+
then $spec/tei:gloss[@xml:lang = $docLang] ! map { "lang": string(./@xml:lang), "text": normalize-space(.) }
114+
else $spec/tei:gloss ! map { "lang": string(./@xml:lang), "text": normalize-space(.) }
115+
} => array:sort((), function($obj) {$obj?lang}),
108116
'module': $module,
109117
'namespace': $namespace
110118
}))

source/xql/elements.xqm

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,34 @@ declare
3939
elements:get-element-attributes-v1($schema, $version, $element, $docLang[1])
4040
};
4141

42+
declare
43+
%rest:GET
44+
%rest:path("/v2/{$schema}/{$version}/elements/{$id}")
45+
%rest:query-param("docLang", "{$docLang}", "")
46+
%rest:produces("application/vnd.api+json")
47+
%output:media-type("application/vnd.api+json")
48+
%output:method("json")
49+
function elements:get-element(
50+
$schema as xs:string, $version as xs:string,
51+
$id as xs:string, $docLang as xs:string*
52+
) {
53+
let $response := elements:get-element-details($schema, $version, $id, $docLang)
54+
return
55+
if(exists($response?errors))
56+
then (
57+
common:set-status($common:response-headers, 404),
58+
$response
59+
)
60+
else (
61+
$common:response-headers,
62+
$response
63+
)
64+
};
4265

66+
(:~
67+
: Retrieve all elements defined in a specific module
68+
: Helper function for elements:elements-v1
69+
:)
4370
declare %private function elements:get-elements-v1(
4471
$schema as xs:string, $version as xs:string,
4572
$module as xs:string, $docLang as xs:string
@@ -58,6 +85,12 @@ declare %private function elements:get-elements-v1(
5885
array { $elements } => array:sort((), function($elem) {$elem?name})
5986
};
6087

88+
(:~
89+
: Retrieve all attributes defined directly for an element and
90+
: all attributes defined in attribute classes the element is member of, including
91+
: nested attribute classes.
92+
: Helper function for elements:element-attributes-v1
93+
:)
6194
declare %private function elements:get-element-attributes-v1(
6295
$schema as xs:string, $version as xs:string,
6396
$element as xs:string, $docLang as xs:string
@@ -75,3 +108,71 @@ declare %private function elements:get-element-attributes-v1(
75108
'classes': classes:get-attribute-classes-recursively-v1($elem, $odd.source, $docLang)
76109
}
77110
};
111+
112+
declare function elements:get-element-context() {};
113+
114+
declare function elements:get-element-content() {};
115+
116+
(:~
117+
: Recursive retrieval of all attributes defined directly for an element and
118+
: all attributes defined in attribute classes the element is member of, including
119+
: nested attribute classes.
120+
: Local attributes are marked with 'class': 'local', attributes from attribute classes
121+
: are marked with 'class': '$className'.
122+
:
123+
: @param $odd-source The ODD source document
124+
: @param $elementSpec The elementSpec element for which to retrieve attributes
125+
: @return An array of maps with 'name' and 'class' keys
126+
:)
127+
declare function elements:get-element-attributes(
128+
$odd-source as element(tei:TEI),
129+
$elementSpec as element(tei:elementSpec),
130+
$docLang as xs:string*
131+
) as array(*) {
132+
array {
133+
$elementSpec//tei:attDef ! map {
134+
'name': string(./@ident),
135+
'class': 'local',
136+
'gloss':
137+
array {
138+
if($docLang)
139+
then ./tei:gloss[@xml:lang = $docLang] ! map { "lang": string(./@xml:lang), "text": normalize-space(.) }
140+
else ./tei:gloss ! map { "lang": string(./@xml:lang), "text": normalize-space(.) }
141+
} => array:sort((), function($obj) {$obj?lang}),
142+
'desc':
143+
array {
144+
if($docLang)
145+
then ./tei:desc[@xml:lang = $docLang] ! map { "lang": string(./@xml:lang), "text": normalize-space(.) }
146+
else ./tei:desc ! map { "lang": string(./@xml:lang), "text": normalize-space(.) }
147+
} => array:sort((), function($obj) {$obj?lang})
148+
}
149+
}
150+
=> array:sort((), function($attr) {$attr?name})
151+
};
152+
153+
declare %private function elements:get-element-details(
154+
$schema as xs:string,
155+
$version as xs:string,
156+
$id as xs:string,
157+
$docLang as xs:string*) as map(*) {
158+
let $odd-source := common:odd-source($schema, $version)
159+
let $decoded-id := common:decode-jsonapi-id($id)?ident
160+
let $elementIdent :=
161+
if($decoded-id) then $decoded-id
162+
else $id
163+
let $elementSpec := $odd-source//tei:elementSpec[@ident = $elementIdent]
164+
return
165+
if($elementSpec)
166+
then
167+
let $basic-data := common:get-spec-basic-data($elementSpec, $docLang[1])
168+
let $attributes := elements:get-element-attributes($odd-source, $elementSpec, $docLang)
169+
return
170+
map {
171+
'data': map {
172+
'type': 'elementDetails',
173+
'id': common:encode-jsonapi-id($schema, $version, 'elements', $elementIdent),
174+
'attributes': map:put($basic-data, 'attributes', $attributes)
175+
}
176+
}
177+
else common:error-not-found('No elementSpec found for ident "' || $elementIdent || '".', common:build-absolute-uri(req:hostname#0, req:scheme#0, req:port#0, rest:uri()))
178+
};

0 commit comments

Comments
 (0)