1
2
3
4
5
6 package dev.metaschema.core.metapath.cst.path;
7
8 import java.util.stream.Stream;
9
10 import dev.metaschema.core.metapath.DynamicContext;
11 import dev.metaschema.core.metapath.IExpression;
12 import dev.metaschema.core.metapath.item.ISequence;
13 import dev.metaschema.core.metapath.item.ItemUtils;
14 import dev.metaschema.core.metapath.item.node.ICycledAssemblyNodeItem;
15 import dev.metaschema.core.metapath.item.node.INodeItem;
16 import dev.metaschema.core.util.ObjectUtils;
17 import edu.umd.cs.findbugs.annotations.NonNull;
18
19
20
21
22
23
24 public abstract class AbstractSearchPathExpression
25 extends AbstractPathExpression<INodeItem> {
26 @NonNull
27 private final Class<? extends INodeItem> staticResultType;
28
29
30
31
32
33
34
35
36
37 public AbstractSearchPathExpression(
38 @NonNull String text,
39 @NonNull Class<? extends INodeItem> staticResultType) {
40 super(text);
41 this.staticResultType = staticResultType;
42 }
43
44 @Override
45 public final Class<INodeItem> getBaseResultType() {
46 return INodeItem.class;
47 }
48
49 @Override
50 public Class<? extends INodeItem> getStaticResultType() {
51 return staticResultType;
52 }
53
54
55
56
57
58
59
60
61
62
63
64
65
66 @NonNull
67 protected Stream<? extends INodeItem> search(
68 @NonNull IExpression expression,
69 @NonNull DynamicContext dynamicContext,
70 @NonNull ISequence<?> outerFocus) {
71
72 ISequence<?> focus = outerFocus.reusable();
73
74
75 @SuppressWarnings("unchecked")
76 Stream<? extends INodeItem> nodeMatches
77 = (Stream<? extends INodeItem>) expression.accept(dynamicContext, focus).stream();
78
79 Stream<? extends INodeItem> childMatches = focus.stream()
80 .map(item -> ItemUtils.checkItemIsNodeItem(dynamicContext, item))
81 .flatMap(focusedNode -> {
82
83 Stream<? extends INodeItem> matches;
84 if (focusedNode instanceof ICycledAssemblyNodeItem) {
85
86 matches = Stream.empty();
87 } else {
88 assert focusedNode != null;
89
90 Stream<? extends INodeItem> flags = focusedNode.flags();
91 Stream<? extends INodeItem> modelItems = focusedNode.modelItems();
92
93 matches = search(
94 expression,
95 dynamicContext,
96 ISequence.of(ObjectUtils.notNull(Stream.concat(flags, modelItems))));
97 }
98 return matches;
99 });
100
101 return ObjectUtils.notNull(Stream.concat(nodeMatches, childMatches).distinct());
102 }
103 }