Skip to content

Commit 7af34c0

Browse files
Implemented array postfix and unary lookups.
1 parent b83d36f commit 7af34c0

24 files changed

+733
-42
lines changed

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/AbstractCodedMetapathException.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public String getMessage() {
9797
*
9898
* @return the error code value
9999
*/
100-
protected int getCode() {
100+
public int getCode() {
101101
return code;
102102
}
103103

@@ -106,7 +106,7 @@ protected int getCode() {
106106
*
107107
* @return the error code family
108108
*/
109-
protected abstract String getCodePrefix();
109+
public abstract String getCodePrefix();
110110

111111
/**
112112
* Get a combination of the error code family and value.

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/DynamicMetapathException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public DynamicMetapathException(int code, Throwable cause) {
105105
}
106106

107107
@Override
108-
protected String getCodePrefix() {
108+
public String getCodePrefix() {
109109
return "MPDY";
110110
}
111111
}

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/StaticMetapathException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public StaticMetapathException(int code, Throwable cause) {
129129
}
130130

131131
@Override
132-
protected String getCodePrefix() {
132+
public String getCodePrefix() {
133133
return "MPST";
134134
}
135135

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/TypeMetapathException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public TypeMetapathException(int code, Throwable cause) {
106106
}
107107

108108
@Override
109-
protected String getCodePrefix() {
109+
public String getCodePrefix() {
110110
return "MPTY";
111111
}
112112
}

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/antlr/AbstractAstVisitor.java

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,10 @@
5050
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.GeneralcompContext;
5151
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.IfexprContext;
5252
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.IntersectexceptexprContext;
53+
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.KeyspecifierContext;
5354
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.LetexprContext;
5455
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.LiteralContext;
56+
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.LookupContext;
5557
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.MetapathContext;
5658
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.MultiplicativeexprContext;
5759
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.NametestContext;
@@ -78,6 +80,7 @@
7880
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.StepexprContext;
7981
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.StringconcatexprContext;
8082
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.UnaryexprContext;
83+
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.UnarylookupContext;
8184
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.UnionexprContext;
8285
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ValuecompContext;
8386
import gov.nist.secauto.metaschema.core.metapath.antlr.Metapath10.ValueexprContext;
@@ -358,10 +361,34 @@ public R visitPostfixexpr(PostfixexprContext ctx) {
358361
return handle(ctx, (context) -> handlePostfixexpr(ctx));
359362
}
360363

364+
/**
365+
* Handle the provided expression.
366+
*
367+
* @param ctx
368+
* the provided expression context
369+
* @return the result
370+
*/
371+
protected abstract R handlePredicate(@NonNull PredicateContext ctx);
372+
361373
@Override
362374
public R visitPredicate(PredicateContext ctx) {
363-
// should never be called, since this is handled by the parent expression
364-
throw new IllegalStateException();
375+
assert ctx != null;
376+
return handlePredicate(ctx);
377+
}
378+
379+
/**
380+
* Handle the provided expression.
381+
*
382+
* @param ctx
383+
* the provided expression context
384+
* @return the result
385+
*/
386+
protected abstract R handleLookup(@NonNull LookupContext ctx);
387+
388+
@Override
389+
public R visitLookup(LookupContext ctx) {
390+
assert ctx != null;
391+
return handleLookup(ctx);
365392
}
366393

367394
/*
@@ -880,6 +907,27 @@ public R visitCurlyarrayconstructor(CurlyarrayconstructorContext ctx) {
880907
return handleArrayConstructor(ctx);
881908
}
882909

910+
@Override
911+
public R visitKeyspecifier(KeyspecifierContext ctx) {
912+
// should never be called, since this is handled by the parent expression
913+
throw new IllegalStateException();
914+
}
915+
916+
/**
917+
* Handle the provided expression.
918+
*
919+
* @param ctx
920+
* the provided expression context
921+
* @return the result
922+
*/
923+
protected abstract R handleUnarylookup(@NonNull UnarylookupContext ctx);
924+
925+
@Override
926+
public R visitUnarylookup(UnarylookupContext ctx) {
927+
assert ctx != null;
928+
return handleUnarylookup(ctx);
929+
}
930+
883931
// =========================================================================
884932
// Conditional Expressions - https://www.w3.org/TR/xpath-31/#id-conditionals
885933
// =========================================================================

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractCSTVisitorBase.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,11 @@ protected <CONTEXT extends ParserRuleContext> IExpression handleGroupedNAiry(
295295
IExpression retval = null;
296296
if (numChildren > 0) {
297297
ParseTree leftTree = context.getChild(startingIndex);
298-
IExpression result = ObjectUtils.notNull(leftTree.accept(this));
298+
retval = ObjectUtils.notNull(leftTree.accept(this));
299299

300300
for (int i = startingIndex + 1; i < numChildren; i = i + step) {
301-
result = parser.apply(context, i, result);
301+
retval = parser.apply(context, i, retval);
302302
}
303-
retval = result;
304303
}
305304
return retval;
306305
}

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/cst/AbstractExpressionVisitor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,4 +362,19 @@ public RESULT visitArray(ArraySequence expr, CONTEXT context) {
362362
public RESULT visitArray(ArraySquare expr, CONTEXT context) {
363363
return visitChildren(expr, context);
364364
}
365+
366+
@Override
367+
public RESULT visitPostfixLookup(PostfixLookup expr, CONTEXT context) {
368+
return visitChildren(expr, context);
369+
}
370+
371+
@Override
372+
public RESULT visitFunctionCallAccessor(FunctionCallAccessor expr, CONTEXT context) {
373+
return visitChildren(expr, context);
374+
}
375+
376+
@Override
377+
public RESULT visitUnaryLookup(UnaryLookup expr, CONTEXT context) {
378+
return defaultResult();
379+
}
365380
}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
* Portions of this software was developed by employees of the National Institute
3+
* of Standards and Technology (NIST), an agency of the Federal Government and is
4+
* being made available as a public service. Pursuant to title 17 United States
5+
* Code Section 105, works of NIST employees are not subject to copyright
6+
* protection in the United States. This software may be subject to foreign
7+
* copyright. Permission in the United States and in foreign countries, to the
8+
* extent that NIST may hold copyright, to use, copy, modify, create derivative
9+
* works, and distribute this software and its documentation without fee is hereby
10+
* granted on a non-exclusive basis, provided that this notice and disclaimer
11+
* of warranty appears in all copies.
12+
*
13+
* THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14+
* EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15+
* THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17+
* INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18+
* SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
19+
* SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20+
* INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21+
* OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22+
* CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23+
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24+
* OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25+
*/
26+
27+
package gov.nist.secauto.metaschema.core.metapath.cst;
28+
29+
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
30+
import gov.nist.secauto.metaschema.core.metapath.ISequence;
31+
import gov.nist.secauto.metaschema.core.metapath.InvalidTypeMetapathException;
32+
import gov.nist.secauto.metaschema.core.metapath.function.library.FnData;
33+
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
34+
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
35+
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
36+
import gov.nist.secauto.metaschema.core.metapath.item.function.ArrayException;
37+
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
38+
39+
import java.util.stream.Stream;
40+
41+
import edu.umd.cs.findbugs.annotations.NonNull;
42+
43+
public abstract class AbstractLookup implements IExpression {
44+
@NonNull
45+
private final IKeySpecifier keySpecifier;
46+
47+
protected AbstractLookup(@NonNull IKeySpecifier keySpecifier) {
48+
this.keySpecifier = keySpecifier;
49+
}
50+
51+
@NonNull
52+
public IKeySpecifier getKeySpecifier() {
53+
return keySpecifier;
54+
}
55+
56+
protected interface IKeySpecifier {
57+
58+
default Stream<? extends IItem> lookup(
59+
@NonNull IItem item,
60+
@NonNull DynamicContext dynamicContext,
61+
@NonNull ISequence<?> focus) {
62+
Stream<? extends IItem> result;
63+
if (item instanceof IArrayItem) {
64+
result = lookupInArray((IArrayItem<?>) item, dynamicContext, focus);
65+
} else {
66+
throw new InvalidTypeMetapathException(item,
67+
String.format("Item type '%s' is not an array or map.", item.getClass().getName()));
68+
}
69+
return result;
70+
}
71+
72+
Stream<? extends IItem> lookupInArray(
73+
@NonNull IArrayItem<?> item,
74+
@NonNull DynamicContext dynamicContext,
75+
@NonNull ISequence<?> focus);
76+
}
77+
78+
protected static class NCNameKeySpecifier implements IKeySpecifier {
79+
@NonNull
80+
private final String name;
81+
82+
public NCNameKeySpecifier(String name) {
83+
this.name = name;
84+
}
85+
86+
public String getName() {
87+
return name;
88+
}
89+
90+
@Override
91+
public Stream<? extends IItem> lookupInArray(
92+
IArrayItem<?> item,
93+
DynamicContext dynamicContext,
94+
ISequence<?> focus) {
95+
throw new InvalidTypeMetapathException(item,
96+
String.format("The key name-based lookup '%s' is not appropriate for an array.", getName()));
97+
}
98+
}
99+
100+
protected static class IntegerLiteralKeySpecifier implements IKeySpecifier {
101+
private final int index;
102+
103+
public IntegerLiteralKeySpecifier(IIntegerItem literal) {
104+
index = literal.asInteger().intValueExact() - 1;
105+
}
106+
107+
@Override
108+
public Stream<? extends IItem> lookupInArray(
109+
IArrayItem<?> item,
110+
DynamicContext dynamicContext,
111+
ISequence<?> focus) {
112+
try {
113+
return Stream.of(item.get(index));
114+
} catch (IndexOutOfBoundsException ex) {
115+
throw new ArrayException(
116+
ArrayException.INDEX_OUT_OF_BOUNDS,
117+
String.format("The index %d is outside the range of values for the array size '%d'.",
118+
index + 1,
119+
item.size()),
120+
ex);
121+
}
122+
}
123+
}
124+
125+
protected static class WildcardKeySpecifier implements IKeySpecifier {
126+
127+
@Override
128+
public Stream<? extends IItem> lookupInArray(
129+
IArrayItem<?> item,
130+
DynamicContext dynamicContext,
131+
ISequence<?> focus) {
132+
return item.stream();
133+
}
134+
}
135+
136+
public static class ParenthesizedExprKeySpecifier implements IKeySpecifier {
137+
@NonNull
138+
private final IExpression keyExpression;
139+
140+
public ParenthesizedExprKeySpecifier(@NonNull IExpression keyExpression) {
141+
this.keyExpression = keyExpression;
142+
}
143+
144+
public IExpression getKeyExpression() {
145+
return keyExpression;
146+
}
147+
148+
@Override
149+
public Stream<? extends IItem> lookupInArray(
150+
IArrayItem<?> item,
151+
DynamicContext dynamicContext,
152+
ISequence<?> focus) {
153+
ISequence<IAnyAtomicItem> keys = FnData.fnData(getKeyExpression().accept(dynamicContext, focus));
154+
155+
return keys.stream()
156+
.map(key -> {
157+
if (key instanceof IIntegerItem) {
158+
int index = ((IIntegerItem) key).asInteger().intValueExact() - 1;
159+
try {
160+
return item.get(index);
161+
} catch (IndexOutOfBoundsException ex) {
162+
throw new ArrayException(
163+
ArrayException.INDEX_OUT_OF_BOUNDS,
164+
String.format("The index %d is outside the range of values for the array size '%d'.",
165+
index + 1,
166+
item.size()),
167+
ex);
168+
}
169+
}
170+
throw new InvalidTypeMetapathException(item,
171+
String.format("The key '%s' of type '%s' is not appropriate for an array lookup.",
172+
key.asString(),
173+
key.getClass().getName()));
174+
175+
});
176+
}
177+
}
178+
179+
}

0 commit comments

Comments
 (0)