1
2
3
4
5
6 package dev.metaschema.core.metapath.cst.logic;
7
8 import java.math.BigInteger;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Map.Entry;
12 import java.util.concurrent.atomic.AtomicInteger;
13 import java.util.stream.Collectors;
14 import java.util.stream.Stream;
15
16 import dev.metaschema.core.metapath.DynamicContext;
17 import dev.metaschema.core.metapath.FocusContext;
18 import dev.metaschema.core.metapath.IExpression;
19 import dev.metaschema.core.metapath.MetapathEvaluationFeature;
20 import dev.metaschema.core.metapath.cst.AbstractExpression;
21 import dev.metaschema.core.metapath.cst.IExpressionVisitor;
22 import dev.metaschema.core.metapath.cst.items.IntegerLiteral;
23 import dev.metaschema.core.metapath.function.library.FnBoolean;
24 import dev.metaschema.core.metapath.item.IItem;
25 import dev.metaschema.core.metapath.item.ISequence;
26 import dev.metaschema.core.util.ObjectUtils;
27 import edu.umd.cs.findbugs.annotations.NonNull;
28
29
30
31
32
33
34
35
36
37
38 public class PredicateExpression
39 extends AbstractExpression {
40 @NonNull
41 private final IExpression base;
42 @NonNull
43 private final List<IExpression> predicates;
44
45
46
47
48
49
50
51
52
53
54
55 public PredicateExpression(
56 @NonNull String text,
57 @NonNull IExpression base,
58 @NonNull List<IExpression> predicates) {
59 super(text);
60 this.base = base;
61 this.predicates = predicates;
62 }
63
64
65
66
67
68
69 @NonNull
70 public IExpression getBase() {
71 return base;
72 }
73
74
75
76
77
78
79 @NonNull
80 public List<IExpression> getPredicates() {
81 return predicates;
82 }
83
84 @Override
85 public List<? extends IExpression> getChildren() {
86 return ObjectUtils.notNull(
87 Stream.concat(Stream.of(getBase()), getPredicates().stream()).collect(Collectors.toList()));
88 }
89
90 @Override
91 protected ISequence<?> evaluate(@NonNull DynamicContext dynamicContext,
92 @NonNull ISequence<?> focus) {
93
94 ISequence<?> retval = getBase().accept(dynamicContext, focus);
95
96 if (dynamicContext.getConfiguration().isFeatureEnabled(MetapathEvaluationFeature.METAPATH_EVALUATE_PREDICATES)) {
97
98 AtomicInteger index = new AtomicInteger();
99 int size = retval.size();
100
101 Stream<? extends IItem> stream = ObjectUtils.notNull(
102 retval.stream().map(item -> {
103 assert item != null;
104 int pos = index.incrementAndGet();
105 DynamicContext subContext = dynamicContext.subContext(
106 FocusContext.of(item, pos, size));
107 return Map.entry(subContext, item);
108 }).filter(entry -> {
109 IItem item = ObjectUtils.notNull(entry.getValue());
110 DynamicContext subContext = ObjectUtils.notNull(entry.getKey());
111
112
113 return !predicates.stream()
114 .map(predicateExpr -> {
115 boolean bool;
116 if (predicateExpr instanceof IntegerLiteral) {
117
118 BigInteger predicateIndex = ((IntegerLiteral) predicateExpr).getValue().asInteger();
119
120
121
122 final BigInteger position = BigInteger.valueOf(
123 ObjectUtils.requireNonNull(subContext.getFocusContext()).getPosition());
124
125
126 bool = position.equals(predicateIndex);
127 } else {
128 ISequence<?> innerFocus = ISequence.of(item);
129 ISequence<?> predicateResult = predicateExpr.accept(subContext, innerFocus);
130 bool = FnBoolean.fnBoolean(predicateResult).toBoolean();
131 }
132 return bool;
133 }).anyMatch(x -> !x);
134 }).map(Entry::getValue));
135
136 retval = ISequence.of(stream);
137 }
138 return retval;
139 }
140
141 @Override
142 public <RESULT, CONTEXT> RESULT accept(@NonNull IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) {
143 return visitor.visitPredicate(this, context);
144 }
145
146 }