1 /*
2 * SPDX-FileCopyrightText: none
3 * SPDX-License-Identifier: CC0-1.0
4 */
5
6 package dev.metaschema.core.metapath;
7
8 import dev.metaschema.core.metapath.item.IItem;
9 import edu.umd.cs.findbugs.annotations.NonNull;
10
11 /**
12 * Represents the focus context for Metapath evaluation, containing the context
13 * item, position, and size as defined in the
14 * <a href="https://www.w3.org/TR/xpath-31/#eval_context">XPath 3.1 evaluation
15 * context</a>.
16 * <p>
17 * The focus context is established when evaluating predicates and provides the
18 * information needed by the {@code fn:position()} and {@code fn:last()}
19 * functions.
20 */
21 public final class FocusContext {
22 @NonNull
23 private final IItem contextItem;
24 private final int position;
25 private final int size;
26
27 private FocusContext(@NonNull IItem contextItem, int position, int size) {
28 this.contextItem = contextItem;
29 this.position = position;
30 this.size = size;
31 }
32
33 /**
34 * Create a new focus context for the given item at the specified position
35 * within a sequence.
36 *
37 * @param item
38 * the context item
39 * @param position
40 * the 1-based position of the item within the sequence
41 * @param size
42 * the total number of items in the sequence
43 * @return a new focus context
44 * @throws IllegalArgumentException
45 * if position is less than 1, size is less than 1, or position is
46 * greater than size
47 */
48 @NonNull
49 public static FocusContext of(@NonNull IItem item, int position, int size) {
50 if (position < 1) {
51 throw new IllegalArgumentException("Position must be >= 1, got: " + position);
52 }
53 if (size < 1) {
54 throw new IllegalArgumentException("Size must be >= 1, got: " + size);
55 }
56 if (position > size) {
57 throw new IllegalArgumentException(
58 String.format("Position (%d) cannot be greater than size (%d)", position, size));
59 }
60 return new FocusContext(item, position, size);
61 }
62
63 /**
64 * Get the context item.
65 *
66 * @return the context item
67 */
68 @NonNull
69 public IItem getContextItem() {
70 return contextItem;
71 }
72
73 /**
74 * Get the context position.
75 * <p>
76 * This is the 1-based position of the context item within the sequence
77 * currently being processed, as returned by {@code fn:position()}.
78 *
79 * @return the context position (1-based)
80 */
81 public int getPosition() {
82 return position;
83 }
84
85 /**
86 * Get the context size.
87 * <p>
88 * This is the total number of items in the sequence currently being processed,
89 * as returned by {@code fn:last()}.
90 *
91 * @return the context size
92 */
93 public int getSize() {
94 return size;
95 }
96 }