private String getFunctionName(BaseNode name) { String functionName = null; if ( name instanceof NameRefNode ) { // simple name functionName = name.getText(); } else if (name instanceof QualifiedNameNode) { QualifiedNameNode qn = (QualifiedNameNode) name; functionName = qn.getParts().stream().map( p -> p.getText() ).collect( Collectors.joining( " ") ); } return functionName; }
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; }
@Override public UnaryTestSubexpr visit(QualifiedNameNode n) { // wildcard is allowed only as the first part UnaryTestSubexpr leading = n.getParts().get(0).accept(this); if (leading.isWildcard()) { return new WildCardUnaryExpression(n); } else { return new SimpleUnaryExpression(n); } }
private Object fetchValue(Object o) throws IllegalAccessException, InvocationTargetException { if ( name instanceof NameRefNode ) { o = EvalHelper.getValue( o, name.getText() ); } else if ( name instanceof QualifiedNameNode ) { for ( NameRefNode nr : ((QualifiedNameNode) name).getParts() ) { o = EvalHelper.getValue( o, nr.getText() ); } } return o; }
@Override public DirectCompilerResult visit(QualifiedNameNode n) { List<NameRefNode> parts = n.getParts(); DirectCompilerResult nameRef0 = parts.get(0).accept(this); Type typeCursor = nameRef0.resultType; Expression currentContext = nameRef0.getExpression(); for (int i = 1; i < parts.size(); i++) { NameRefNode acc = parts.get(i); String key = acc.getText(); if (typeCursor instanceof CompositeType) { CompositeType currentContextType = (CompositeType) typeCursor; currentContext = Contexts.getKey(currentContext, currentContextType, key); typeCursor = currentContextType.getFields().get(key); } else { // degraded mode, or accessing fields of DATE etc. currentContext = Expressions.path(currentContext, new StringLiteralExpr(key)); typeCursor = BuiltInType.UNKNOWN; } } // If it was a NameRef expression, the number coercion is directly performed by the EvaluationContext for the simple variable. // Otherwise in case of QualifiedName expression, for a structured type like this case, it need to be coerced on the last accessor: return DirectCompilerResult.of( Expressions.coerceNumber(currentContext), typeCursor); }
@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); } }
@Test public void testQualifiedName() { String inputExpression = "My Person.Full Name"; MapBackedType personType = new MapBackedType("Person", mapOf( entry("Full Name", BuiltInType.STRING), entry("Age", BuiltInType.NUMBER) ) ); BaseNode qualRef = parse( inputExpression, mapOf( entry("My Person", personType) ) ); assertThat( qualRef, is( instanceOf( QualifiedNameNode.class ) ) ); assertThat( qualRef.getResultType(), is( BuiltInType.STRING ) ); List<NameRefNode> parts = ((QualifiedNameNode) qualRef).getParts(); // `My Person` ... assertThat( parts.get(0), is( instanceOf( NameRefNode.class ) ) ); assertThat( parts.get(0).getResultType(), is( personType ) ); // ... `.Full Name` assertThat( parts.get(1), is( instanceOf( NameRefNode.class ) ) ); assertThat( parts.get(1).getResultType(), is( BuiltInType.STRING ) ); assertLocation( inputExpression, qualRef ); }
@Test public void testNestedContexts2() { String inputExpression = "{ an applicant : { " + " home address : {" + " street name: \"broadway st\"," + " city : \"New York\" " + " } " + " },\n " + " street : an applicant.home address.street name \n" + "}"; BaseNode ctxbase = parse( inputExpression ); assertThat( ctxbase, is( instanceOf( ContextNode.class ) ) ); assertThat( ctxbase.getText(), is( inputExpression ) ); ContextNode ctx = (ContextNode) ctxbase; assertThat( ctx.getEntries().size(), is( 2 ) ); ContextEntryNode entry = ctx.getEntries().get( 1 ); assertThat( entry.getName(), is( instanceOf( NameDefNode.class ) ) ); assertThat( entry.getResultType(), is( BuiltInType.STRING ) ); NameDefNode name = (NameDefNode) entry.getName(); assertThat( name.getText(), is("street") ); assertThat( entry.getValue(), is( instanceOf( QualifiedNameNode.class ) ) ); QualifiedNameNode qnn = (QualifiedNameNode) entry.getValue(); assertThat( qnn.getParts().get( 0 ).getText(), is("an applicant") ); assertThat( qnn.getParts().get( 1 ).getText(), is("home address") ); assertThat( qnn.getParts().get( 2 ).getText(), is("street name") ); }