Skip to content

Commit 0cc7fdf

Browse files
committed
[feature] Add support for setting XQuery external variables of type map(*) via the eXist-db REST API
1 parent 5d64541 commit 0cc7fdf

File tree

3 files changed

+415
-15
lines changed

3 files changed

+415
-15
lines changed

exist-core/src/main/java/org/exist/xqj/Marshaller.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
*/
4646
package org.exist.xqj;
4747

48+
import com.evolvedbinary.j8fu.tuple.Tuple2;
4849
import org.exist.dom.QName;
4950
import org.exist.dom.memtree.*;
5051
import org.exist.storage.DBBroker;
@@ -54,11 +55,13 @@
5455
import org.exist.xquery.XPathException;
5556
import org.exist.xquery.XQueryContext;
5657
import org.exist.xquery.functions.array.ArrayType;
58+
import org.exist.xquery.functions.map.MapType;
5759
import org.exist.xquery.value.*;
5860
import org.w3c.dom.Comment;
5961
import org.w3c.dom.Document;
6062
import org.w3c.dom.Element;
6163
import org.w3c.dom.Node;
64+
import org.w3c.dom.NodeList;
6265
import org.w3c.dom.ProcessingInstruction;
6366
import org.w3c.dom.Text;
6467
import org.xml.sax.ContentHandler;
@@ -80,6 +83,7 @@
8083
import java.util.List;
8184
import java.util.Properties;
8285

86+
import static com.evolvedbinary.j8fu.tuple.Tuple.Tuple;
8387
import static org.exist.util.StringUtil.nullIfEmpty;
8488

8589

@@ -111,6 +115,8 @@ public class Marshaller {
111115
private final static String ATTR_NAME = "name";
112116

113117
public final static QName SEQUENCE_ELEMENT_QNAME = new QName(SEQ_ELEMENT, NAMESPACE, PREFIX);
118+
public final static QName ENTRY_ELEMENT_QNAME = new QName("entry", NAMESPACE, PREFIX);
119+
public final static QName KEY_ELEMENT_QNAME = new QName("key", NAMESPACE, PREFIX);
114120

115121
/**
116122
* Marshall a sequence in an xml based string representation.
@@ -300,6 +306,9 @@ private static Item demarshallValue(final XQueryContext context, final ElementIm
300306
final InMemoryNodeSet sxSequences = new InMemoryNodeSet();
301307
sxValue.selectChildren(new NameTest(Type.ELEMENT, SEQUENCE_ELEMENT_QNAME), sxSequences);
302308

309+
final InMemoryNodeSet sxEntries = new InMemoryNodeSet();
310+
sxValue.selectChildren(new NameTest(Type.ELEMENT, ENTRY_ELEMENT_QNAME), sxEntries);
311+
303312
Node item = sxValue.getFirstChild();
304313

305314
if (type == Type.ATTRIBUTE || (type == Type.ITEM && attrNameString != null)) {
@@ -393,6 +402,24 @@ private static Item demarshallValue(final XQueryContext context, final ElementIm
393402
}
394403
return new ArrayType(context, arrayValues);
395404

405+
} else if (type == Type.MAP_ITEM || (type == Type.ITEM && !sxEntries.isEmpty())) {
406+
// map(*) type
407+
final List<Tuple2<AtomicValue, Sequence>> mapEntries = new ArrayList<>();
408+
409+
for (final SequenceIterator itSxEntry = sxEntries.iterate(); itSxEntry.hasNext();) {
410+
final ElementImpl sxEntry = (ElementImpl) itSxEntry.nextItem();
411+
final NodeList entryKeys = sxEntry.getElementsByTagNameNS(KEY_ELEMENT_QNAME.getNamespaceURI(), KEY_ELEMENT_QNAME.getLocalPart());
412+
final Element entryKey = (Element) entryKeys.item(0);
413+
final int keyType = Type.getType(entryKey.getAttribute(ATTR_TYPE));
414+
final String keyStr = entryKey.getTextContent();
415+
final AtomicValue key = new StringValue(keyStr).convertTo(keyType);
416+
final NodeList entrySequences = sxEntry.getElementsByTagNameNS(SEQUENCE_ELEMENT_QNAME.getNamespaceURI(), SEQUENCE_ELEMENT_QNAME.getLocalPart());
417+
final ElementImpl entrySequence = (ElementImpl) entrySequences.item(0);
418+
final Sequence value = demarshallSequence(context, entrySequence);
419+
mapEntries.add(Tuple(key, value));
420+
}
421+
return new MapType(context, null, mapEntries);
422+
396423
} else {
397424
// specific non-node type or text()
398425
final StringBuilder data = new StringBuilder();

0 commit comments

Comments
 (0)