ImmutableFunctionExpression implements FunctionExpression { @Override public PipelineElement resolve(final String expression, final PipelineElement resolvedInputValue, final ExpressionResolver expressionResolver) { if (!supports(expression.replaceFirst(getPrefix() + ":", ""))) { throw PlaceholderFunctionUnknownException.newBuilder(expression).build(); } return SUPPORTED.stream() .filter(pf -> expression.startsWith(getPrefix() + ":" + pf.getName() + "(")) .map(pf -> pf.apply(resolvedInputValue, expression.replaceFirst(getPrefix() + ":" + pf.getName(), "").trim(), expressionResolver) ) .findFirst() .orElse(PipelineElement.unresolved()); }  @Override String getPrefix(); @Override List<String> getSupportedNames(); @Override boolean supports(final String expressionName); @Override PipelineElement resolve(final String expression, final PipelineElement resolvedInputValue,
            final ExpressionResolver expressionResolver);  }
@Test public void testUnknownFunction() { assertThatExceptionOfType(PlaceholderFunctionUnknownException.class).isThrownBy(() -> UNDER_TEST.resolve("fn:unknown", PipelineElement.resolved(THING_ID.toString()), EXPRESSION_RESOLVER)); }
@Test public void testFunctionUpper() { assertThat(UNDER_TEST.resolve("fn:upper()", PipelineElement.resolved(THING_ID.toString()), EXPRESSION_RESOLVER)) .contains(THING_ID.toString().toUpperCase()); }
@Test public void testFunctionUpperWrongSignature() { assertThatExceptionOfType(PlaceholderFunctionSignatureInvalidException.class).isThrownBy(() -> UNDER_TEST.resolve("fn:upper('foo')", PipelineElement.resolved(THING_ID.toString()), EXPRESSION_RESOLVER)); }
@Test public void testFunctionLower() { assertThat(UNDER_TEST.resolve("fn:lower()", PipelineElement.resolved(HEADER_VAL), EXPRESSION_RESOLVER)) .contains(HEADER_VAL.toLowerCase()); }
@Test public void testFunctionLowerWrongSignature() { assertThatExceptionOfType(PlaceholderFunctionUnknownException.class).isThrownBy(() -> UNDER_TEST.resolve("fn:lower", PipelineElement.resolved(THING_ID.toString()), EXPRESSION_RESOLVER)); }
@Test public void testFunctionDefaultWhenInputPresent() { assertThat( UNDER_TEST.resolve("fn:default('constant')", PipelineElement.resolved(HEADER_VAL), EXPRESSION_RESOLVER)) .contains(HEADER_VAL); }
@Test public void testFunctionDefaultWhenInputEmptyWithConstant() { assertThat(UNDER_TEST.resolve("fn:default('constant')", PipelineElement.unresolved(), EXPRESSION_RESOLVER)) .contains("constant"); }
@Test public void testFunctionDefaultWhenInputEmptyWithConstantDoubleQuotes() { assertThat(UNDER_TEST.resolve("fn:default(\"constant\")", PipelineElement.unresolved(), EXPRESSION_RESOLVER)) .contains("constant"); }
@Test public void testFunctionDefaultWhenInputEmptyWithPlaceholder() { assertThat(UNDER_TEST.resolve("fn:default(thing:id)", PipelineElement.unresolved(), EXPRESSION_RESOLVER)) .contains(THING_ID.toString()); }
@Test public void testFunctionDefaultWithWrongSignature() { assertThatExceptionOfType(PlaceholderFunctionSignatureInvalidException.class).isThrownBy(() -> UNDER_TEST.resolve("fn:default('constant',2)", PipelineElement.unresolved(), EXPRESSION_RESOLVER)); }
@Test public void testFunctionSubstringBefore() { assertThat(UNDER_TEST.resolve("fn:substring-before(\"-\")", PipelineElement.resolved(THING_NAME), EXPRESSION_RESOLVER)) .contains("test"); }
@Test public void testFunctionSubstringAfter() { assertThat(UNDER_TEST.resolve("fn:substring-after(\"-\")", PipelineElement.resolved(THING_NAME), EXPRESSION_RESOLVER)) .contains("id"); }
@Test public void testFunctionFilterWhenConditionSucceeds() { assertThat(UNDER_TEST.resolve("fn:filter('true','eq','true')", PipelineElement.resolved(HEADER_VAL), EXPRESSION_RESOLVER)) .contains(HEADER_VAL); }
@Test public void testFunctionFilterWhenConditionFails() { assertThat(UNDER_TEST.resolve("fn:filter('false','eq','true')", PipelineElement.resolved(HEADER_VAL), EXPRESSION_RESOLVER)) .isEmpty(); }
@Test public void testFunctionFilterWhenConditionSucceedsWithPlaceholder() { assertThat(UNDER_TEST.resolve(String.format("fn:filter(thing:id,'eq','%s')", THING_ID.toString()), PipelineElement.resolved(HEADER_VAL), EXPRESSION_RESOLVER)) .contains(HEADER_VAL); }