(final QueryContext qc, final InputInfo ii)
| 40 | private final Map<Long, byte[]> cachedSteps = Collections.synchronizedMap(new StepCache()); |
| 41 | |
| 42 | @Override |
| 43 | public Item item(final QueryContext qc, final InputInfo ii) throws QueryException { |
| 44 | GNode node = toGNodeOrNull(context(qc), qc); |
| 45 | final XQMap map = toEmptyMap(arg(1), qc); |
| 46 | final PathOptions options = toOptions(map, new PathOptions(), qc); |
| 47 | if(node == null) return Empty.VALUE; |
| 48 | |
| 49 | final boolean indexes = options.get(PathOptions.INDEXES); |
| 50 | final Value ns = options.get(PathOptions.NAMESPACES); |
| 51 | final XQMap namespaces = ns.isEmpty() ? XQMap.empty() : toMap(ns, qc); |
| 52 | final boolean lexical = options.get(PathOptions.LEXICAL); |
| 53 | final Value origin = options.get(PathOptions.ORIGIN); |
| 54 | final boolean cache = map.structSize() == 0; |
| 55 | |
| 56 | final TokenList steps = new TokenList(); |
| 57 | final TokenBuilder tb = new TokenBuilder(); |
| 58 | boolean relative = false; |
| 59 | while(true) { |
| 60 | // check if string representation of step was cached |
| 61 | final Long cacheKey = cache && node instanceof final DBNode dbnode ? |
| 62 | (long) dbnode.data().dbid << 32L | dbnode.pre() : null; |
| 63 | byte[] step = cacheKey != null ? cachedSteps.get(cacheKey) : null; |
| 64 | |
| 65 | final GNode parent = node.parent(); |
| 66 | if(step == null) { |
| 67 | final Type type = node.type; |
| 68 | final Kind kind = type instanceof final NodeType nt ? nt.kind() : null; |
| 69 | if(parent == null) { |
| 70 | if(!kind.oneOf(Kind.DOCUMENT, Kind.JNODE)) { |
| 71 | tb.add(name(Function.ROOT.definition().name, false, lexical, namespaces, qc)).add("()"); |
| 72 | } |
| 73 | break; |
| 74 | } |
| 75 | // step: name/type |
| 76 | final QNm qname = node.qname(); |
| 77 | if(kind == Kind.ATTRIBUTE) { |
| 78 | tb.add('@').add(name(qname, true, lexical, namespaces, qc)); |
| 79 | } else if(kind == Kind.ELEMENT) { |
| 80 | tb.add(name(qname, false, lexical, namespaces, qc)); |
| 81 | } else if(kind == Kind.PROCESSING_INSTRUCTION) { |
| 82 | tb.add(kind.toString(Token.string(qname.local()))); |
| 83 | } else if(kind.oneOf(Kind.COMMENT, Kind.TEXT)) { |
| 84 | tb.add(type.toString()); |
| 85 | } else if(parent instanceof final JNode jparent) { |
| 86 | final JNode jnode = (JNode) node; |
| 87 | final Item key = jnode.key; |
| 88 | byte[] get = null; |
| 89 | final byte[] string = key.string(info); |
| 90 | if(jparent.value instanceof XQArray) { |
| 91 | tb.add("*[").add(key).add("]"); |
| 92 | } else if(key instanceof AStr || key instanceof Atm || key instanceof Uri) { |
| 93 | if(XMLToken.isNCName(string)) { |
| 94 | tb.add(string); |
| 95 | } else { |
| 96 | get = QueryString.toQuoted(string); |
| 97 | } |
| 98 | } else if(key instanceof ANum) { |
| 99 | get = string; |
nothing calls this directly
no test coverage detected