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 java.util.function.Function;
9 import java.util.stream.Stream;
10
11 import dev.metaschema.core.metapath.StaticMetapathException;
12 import dev.metaschema.core.metapath.item.node.INodeItem;
13 import dev.metaschema.core.util.ObjectUtils;
14 import edu.umd.cs.findbugs.annotations.NonNull;
15
16 /**
17 * An implementation of <a href="https://www.w3.org/TR/xpath-31/#axes">Metapath
18 * axes</a>.
19 */
20 public enum Axis {
21 /**
22 * The {@code self::} axis, referring to the current context node.
23 */
24 SELF(Stream::of),
25 /**
26 * The {@code parent::} axis, referring to the current context node's parent.
27 *
28 * @see INodeItem#getParentNodeItem()
29 */
30 PARENT(focus -> Stream.ofNullable(focus.getParentNodeItem())),
31 /**
32 * The {@code flag::} axis, referring to the current context node's flags.
33 *
34 * @see INodeItem#getFlags()
35 */
36 FLAG(INodeItem::flags),
37 /**
38 * The {@code ancestor::} axis, referring to the current context node's
39 * parentage.
40 *
41 * @see INodeItem#ancestor()
42 */
43 ANCESTOR(INodeItem::ancestor),
44 /**
45 * The {@code ancestor-or-self::} axis, referring to the current context node
46 * and its parentage.
47 *
48 * @see INodeItem#ancestorOrSelf()
49 */
50 ANCESTOR_OR_SELF(INodeItem::ancestorOrSelf),
51 /**
52 * The {@code children::} axis, referring to the current context node's direct
53 * children.
54 *
55 * @see INodeItem#modelItems()
56 */
57 CHILDREN(INodeItem::modelItems),
58 /**
59 * The {@code descendant::} axis, referring to all of the current context node's
60 * descendants (i.e., the children, the children of the children, etc).
61 *
62 * @see INodeItem#descendant()
63 */
64 DESCENDANT(INodeItem::descendant),
65 /**
66 * The {@code descendant-or-self::} axis, referring to the current context node
67 * and all of the current context node's descendants (i.e., the children, the
68 * children of the children, etc).
69 *
70 * @see INodeItem#descendantOrSelf()
71 */
72 DESCENDANT_OR_SELF(INodeItem::descendantOrSelf),
73 /**
74 * The {@code following-sibling::} axis, referring to those children of the
75 * context node's parent that occur after the context node in
76 * <a href="https://www.w3.org/TR/xpath-31/#dt-document-order">document
77 * order</a>.
78 */
79 FOLLOWING_SIBLING(INodeItem::followingSibling),
80 /**
81 * The {@code preceding-sibling::} axis, referring to those children of the
82 * context node's parent that occur before the context node in
83 * <a href="https://www.w3.org/TR/xpath-31/#dt-document-order">document
84 * order</a>.
85 */
86 PRECEDING_SIBLING(INodeItem::precedingSibling),
87 /**
88 * The {@code preceding-sibling::} axis, referring to all nodes that are
89 * descendants of the root of the tree in which the context node is found, are
90 * not descendants of the context node, and occur after the context node in
91 * <a href="https://www.w3.org/TR/xpath-31/#dt-document-order">document
92 * order</a>.
93 */
94 FOLLOWING(INodeItem::following),
95 /**
96 * The {@code preceding-sibling::} axis, referring to all nodes that are
97 * descendants of the root of the tree in which the context node is found, are
98 * not ancestors of the context node, and occur before the context node in
99 * <a href="https://www.w3.org/TR/xpath-31/#dt-document-order">document
100 * order</a>.
101 */
102 PRECEDING(INodeItem::preceding),
103 /**
104 * This axis is not supported.
105 */
106 NAMESPACE(focus -> {
107 throw new StaticMetapathException(
108 StaticMetapathException.AXIS_NAMESPACE_UNSUPPORTED,
109 "The 'namespace' axis is not supported");
110 });
111
112 @NonNull
113 private final Function<INodeItem, Stream<? extends INodeItem>> action;
114
115 Axis(@NonNull Function<INodeItem, Stream<? extends INodeItem>> action) {
116 this.action = action;
117 }
118
119 /**
120 * Execute the axis operation on the provided {@code focus}.
121 *
122 * @param focus
123 * the node to operate on
124 * @return the result of the axis operation
125 */
126 @NonNull
127 public Stream<? extends INodeItem> execute(@NonNull INodeItem focus) {
128 return ObjectUtils.notNull(action.apply(focus));
129 }
130 }