public static PathExpressionNode newPathExpressionNode(ParserRuleContext ctx, BaseNode expr, BaseNode name) { return new PathExpressionNode( ctx, expr, name ); }
@Override public Object evaluate(EvaluationContext ctx) { try { Object o = this.expression.evaluate( ctx ); if ( o instanceof List ) { List list = (List) o; // list of contexts/elements as defined in the spec, page 114 List results = new ArrayList(); for( Object element : list ) { Object r = fetchValue( element ); if( r != null ) { results.add( r ); } } return results; } else { return fetchValue( o ); } } catch ( Exception e ) { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.ERROR_EVALUATING_PATH_EXPRESSION, expression.getText(), name.getText()), e) ); } return null; }
@Override public Type getResultType() { return findType(expression.getResultType(), name); }
@Override public DirectCompilerResult visit(PathExpressionNode n) { DirectCompilerResult expr = n.getExpression().accept(this); BaseNode nameNode = n.getName(); if (nameNode instanceof QualifiedNameNode) { QualifiedNameNode qualifiedNameNode = (QualifiedNameNode) n.getName(); List<Expression> exprs = qualifiedNameNode.getParts().stream() .map(name -> new StringLiteralExpr(name.getText())) .collect(Collectors.toList()); return DirectCompilerResult.of( Expressions.path(expr.getExpression(), exprs), // here we could still try to infer the result type, but presently use ANY BuiltInType.UNKNOWN).withFD(expr); } else { return DirectCompilerResult.of( Expressions.path(expr.getExpression(), new StringLiteralExpr(nameNode.getText())), // here we could still try to infer the result type, but presently use ANY BuiltInType.UNKNOWN).withFD(expr); } }
} else if (name instanceof PathExpressionNode) { PathExpressionNode pathExpressionNode = (PathExpressionNode) name; value = pathExpressionNode.evaluate(ctx);
@Test public void testPathExpression() { String inputExpression = "[ 10, 15 ].size"; BaseNode pathBase = parse( inputExpression ); assertThat( pathBase, is( instanceOf( PathExpressionNode.class ) ) ); assertThat( pathBase.getText(), is( inputExpression ) ); PathExpressionNode pathExpr = (PathExpressionNode) pathBase; assertThat( pathExpr.getExpression(), is( instanceOf( ListNode.class ) ) ); assertThat( pathExpr.getExpression().getText(), is( "10, 15" ) ); assertThat( pathExpr.getName(), is( instanceOf( NameRefNode.class ) ) ); assertThat( pathExpr.getName().getText(), is( "size" ) ); }
@Test public void testContextPathExpression3() { String inputExpression = "{ first name : \"bob\" }.first name"; BaseNode pathBase = parse( inputExpression ); assertThat( pathBase, is( instanceOf( PathExpressionNode.class ) ) ); assertThat( pathBase.getText(), is( inputExpression ) ); assertThat( pathBase.getResultType(), is( BuiltInType.STRING ) ); PathExpressionNode pathExpr = (PathExpressionNode) pathBase; assertThat( pathExpr.getExpression(), is( instanceOf( ContextNode.class ) ) ); assertThat( pathExpr.getExpression().getText(), is( "{ first name : \"bob\" }" ) ); assertThat( pathExpr.getName(), is( instanceOf( NameRefNode.class ) ) ); assertThat( pathExpr.getName().getText(), is( "first name" ) ); }
private static Type findType(Type startType, BaseNode accessor) { if (!(startType instanceof CompositeType)) { return BuiltInType.UNKNOWN; } CompositeType compositeType = (CompositeType) startType; if ( accessor instanceof NameRefNode ) { NameRefNode nameRefNode = (NameRefNode) accessor; return compositeType.getFields().getOrDefault(nameRefNode.getText() , BuiltInType.UNKNOWN); } else if ( accessor instanceof QualifiedNameNode ) { QualifiedNameNode qualifiedNameNode = (QualifiedNameNode) accessor; Type typeCursor = startType; for ( NameRefNode part : qualifiedNameNode.getParts() ) { typeCursor = findType(typeCursor, part); } return typeCursor; } return BuiltInType.UNKNOWN; }
@Test public void testContextPathExpression() { String inputExpression = "{ x : \"foo\" }.x"; BaseNode pathBase = parse( inputExpression ); assertThat( pathBase, is( instanceOf( PathExpressionNode.class ) ) ); assertThat( pathBase.getText(), is( inputExpression ) ); assertThat( pathBase.getResultType(), is( BuiltInType.STRING ) ); PathExpressionNode pathExpr = (PathExpressionNode) pathBase; assertThat( pathExpr.getExpression(), is( instanceOf( ContextNode.class ) ) ); assertThat( pathExpr.getExpression().getText(), is( "{ x : \"foo\" }" ) ); assertThat( pathExpr.getName(), is( instanceOf( NameRefNode.class ) ) ); assertThat( pathExpr.getName().getText(), is( "x" ) ); }
@Test public void testContextPathExpression2() { String inputExpression = "{ x : { y : \"foo\" } }.x.y"; BaseNode pathBase = parse( inputExpression ); assertThat( pathBase, is( instanceOf( PathExpressionNode.class ) ) ); assertThat( pathBase.getText(), is( inputExpression ) ); assertThat( pathBase.getResultType(), is( BuiltInType.STRING ) ); PathExpressionNode pathExpr = (PathExpressionNode) pathBase; assertThat( pathExpr.getExpression(), is( instanceOf( ContextNode.class ) ) ); assertThat( pathExpr.getExpression().getText(), is( "{ x : { y : \"foo\" } }" ) ); assertThat( pathExpr.getName(), is( instanceOf( QualifiedNameNode.class ) ) ); assertThat( pathExpr.getName().getText(), is( "x.y" ) ); }