1
2
3
4
5
6 package dev.metaschema.core.metapath.cst.items;
7
8 import java.util.List;
9 import java.util.Map;
10 import java.util.stream.Collectors;
11
12 import dev.metaschema.core.metapath.DynamicContext;
13 import dev.metaschema.core.metapath.IExpression;
14 import dev.metaschema.core.metapath.cst.AbstractExpression;
15 import dev.metaschema.core.metapath.cst.IExpressionVisitor;
16 import dev.metaschema.core.metapath.item.ICollectionValue;
17 import dev.metaschema.core.metapath.item.ISequence;
18 import dev.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
19 import dev.metaschema.core.metapath.item.function.IMapItem;
20 import dev.metaschema.core.metapath.type.InvalidTypeMetapathException;
21 import dev.metaschema.core.util.ObjectUtils;
22 import edu.umd.cs.findbugs.annotations.NonNull;
23
24
25
26
27
28
29 public class MapConstructor
30 extends AbstractExpression {
31 @NonNull
32 private final List<MapConstructor.Entry> entries;
33
34
35
36
37
38
39
40
41
42
43 public MapConstructor(@NonNull String text, @NonNull List<MapConstructor.Entry> entries) {
44 super(text);
45 this.entries = entries;
46 }
47
48 @Override
49 public List<MapConstructor.Entry> getChildren() {
50 return entries;
51 }
52
53 @Override
54 protected ISequence<?> evaluate(DynamicContext dynamicContext, ISequence<?> focus) {
55 return IMapItem.ofCollection(
56 ObjectUtils.notNull(getChildren().stream()
57 .map(item -> {
58 IExpression keyExpression = item.getKeyExpression();
59 IAnyAtomicItem key = ISequence.of(keyExpression.accept(dynamicContext, focus).atomize())
60 .getFirstItem(true);
61 if (key == null) {
62 throw new InvalidTypeMetapathException(
63 null,
64 String.format("The expression '%s' did not result in a single key atomic value.",
65 keyExpression.toCSTString()))
66 .registerEvaluationContext(dynamicContext);
67 }
68 ICollectionValue value = item.getValueExpression().accept(dynamicContext, focus).toCollectionValue();
69
70 return IMapItem.entry(key, value);
71 }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))))
72 .toSequence();
73 }
74
75 @Override
76 public <RESULT, CONTEXT> RESULT accept(IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) {
77 return visitor.visitMapConstructor(this, context);
78 }
79
80
81
82
83 public static class Entry
84 extends AbstractExpression {
85 @NonNull
86 private final IExpression keyExpression;
87 @NonNull
88 private final IExpression valueExpression;
89
90
91
92
93
94
95
96
97
98
99
100
101 public Entry(@NonNull String text, @NonNull IExpression keyExpression, @NonNull IExpression valueExpression) {
102 super(text);
103 this.keyExpression = keyExpression;
104 this.valueExpression = valueExpression;
105 }
106
107
108
109
110
111
112 @NonNull
113 public IExpression getKeyExpression() {
114 return keyExpression;
115 }
116
117
118
119
120
121
122 @NonNull
123 public IExpression getValueExpression() {
124 return valueExpression;
125 }
126
127 @SuppressWarnings("null")
128 @Override
129 public List<? extends IExpression> getChildren() {
130 return List.of(keyExpression, valueExpression);
131 }
132
133 @Override
134 protected ISequence<?> evaluate(DynamicContext dynamicContext, ISequence<?> focus) {
135 throw new UnsupportedOperationException("handled by the map constructor");
136 }
137
138 @Override
139 public <RESULT, CONTEXT> RESULT accept(IExpressionVisitor<RESULT, CONTEXT> visitor, CONTEXT context) {
140 return visitor.visitMapConstructorEntry(this, context);
141 }
142 }
143 }