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 dev.metaschema.core.metapath.item.node.INodeItem;
13  import edu.umd.cs.findbugs.annotations.NonNull;
14  
15  /**
16   * An expression that finds an ancestor of the {@code left} expression using the
17   * {@code right} expression.
18   * <p>
19   * Based on the XPath 3.1 <a href=
20   * "https://www.w3.org/TR/xpath-31/#id-relative-path-expressions">relative path
21   * expressions</a>.
22   */
23  public class RelativeDoubleSlashPath
24      extends AbstractRelativePathExpression {
25  
26    /**
27     * Construct a new expression that finds an ancestor of the {@code left}
28     * expression using the {@code right} expression.
29     *
30     * @param text
31     *          the parsed text of the expression
32     * @param left
33     *          the context path
34     * @param right
35     *          the path to evaluate in the context of the left
36     */
37    public RelativeDoubleSlashPath(
38        @NonNull String text,
39        @NonNull IExpression left,
40        @NonNull IExpression right) {
41      super(text, left, right);
42    }
43  
44    @Override
45    public <RESULT, CONTEXT> RESULT accept(IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) {
46      return visitor.visitRelativeDoubleSlashPath(this, context);
47    }
48  
49    @Override
50    protected ISequence<? extends INodeItem> evaluate(
51        DynamicContext dynamicContext,
52        ISequence<?> focus) {
53      ISequence<?> leftResult = getLeft().accept(dynamicContext, focus);
54  
55      // evaluate the right path in the context of the left
56      return ISequence.of(search(getRight(), dynamicContext, leftResult));
57    }
58  }