1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.metapath.cst.path;
7   
8   import dev.metaschema.core.metapath.DynamicContext;
9   import dev.metaschema.core.metapath.IExpression;
10  import dev.metaschema.core.metapath.cst.IExpressionVisitor;
11  import dev.metaschema.core.metapath.item.ISequence;
12  import edu.umd.cs.findbugs.annotations.NonNull;
13  
14  /**
15   * An expression that finds a child of the {@code left} expression using the
16   * {@code right} expression.
17   * <p>
18   * Based on the XPath 3.1 <a href=
19   * "https://www.w3.org/TR/xpath-31/#id-relative-path-expressions">relative path
20   * expressions</a>.
21   */
22  public class RelativeSlashPath
23      extends AbstractRelativePathExpression {
24  
25    /**
26     * Construct a new expression that finds a child of the {@code left} expression
27     * using the {@code right} expression.
28     *
29     * @param text
30     *          the parsed text of the expression
31     * @param left
32     *          the context path
33     * @param right
34     *          the path to evaluate in the context of the left
35     */
36    public RelativeSlashPath(
37        @NonNull String text,
38        @NonNull IExpression left,
39        @NonNull IExpression right) {
40      super(text, left, right);
41    }
42  
43    @Override
44    public <RESULT, CONTEXT> RESULT accept(IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) {
45      return visitor.visitRelativeSlashPath(this, context);
46    }
47  
48    @Override
49    protected ISequence<?> evaluate(
50        DynamicContext dynamicContext,
51        ISequence<?> focus) {
52      ISequence<?> leftResult = getLeft().accept(dynamicContext, focus);
53  
54      // ensures the left sequence is list backed
55      return leftResult.isEmpty()
56          ? ISequence.empty()
57          : getRight().accept(dynamicContext, leftResult);
58    }
59  }