PlaceholderFilter { public static void validate(final String template, final Placeholder<?>... placeholders) { applyOrElseRetain(template, PlaceholderFactory.newExpressionResolverForValidation(placeholders)); } private  PlaceholderFilter(); static AuthorizationContext applyHeadersPlaceholderToAuthContext(
            final AuthorizationContext authorizationContext,
            final Map<String, String> headers); static String apply(final String template, final T placeholderSource, final Placeholder<T> placeholder); static String apply(final String template, final ExpressionResolver expressionResolver); static Optional<String> applyOrElseDelete(final String template, final ExpressionResolver resolver); static String applyOrElseRetain(final String template, final ExpressionResolver resolver); static void validate(final String template, final Placeholder<?>... placeholders); static String validateAndReplace(final String template, final String stringUsedInPlaceholderReplacement,
            final Placeholder<?>... placeholders);  }
@Test public void testValidate() { PlaceholderFilter.validate("{{thing:namespace}}/{{thing:name}}:{{header:device-id}}", placeholders); PlaceholderFilter.validate("{{ thing:namespace }}/{{ thing:name }}:{{ header:device-id }}", placeholders); PlaceholderFilter.validate("{{thing:namespace }}/{{ thing:name }}:{{header:device-id }}", placeholders); PlaceholderFilter.validate("{{thing:namespace }}{{ thing:name }}{{header:device-id }}", placeholders); PlaceholderFilter.validate("{{thing:namespace }} {{ thing:name }} {{header:device-id }}", placeholders); PlaceholderFilter.validate(" {{thing:namespace }}{{ thing:name }}{{header:device-id }} ", placeholders); PlaceholderFilter.validate("-----{{thing:namespace }}{{ thing:name }}{{header:device-id }}-----", placeholders); PlaceholderFilter.validate("-----{{thing:namespace }} placeholders); PlaceholderFilter.validate("{{ thing:namespace }}:{{thing:id | fn:substring-after(':')}}", placeholders); }
@Test public void testValidateFails() { assertThatExceptionOfType(UnresolvedPlaceholderException.class).isThrownBy( () -> PlaceholderFilter.validate("{{ header:xxx | fn:default(ing:namespace) }}", placeholders)); assertThatExceptionOfType(UnresolvedPlaceholderException.class).isThrownBy( () -> PlaceholderFilter.validate("{{th{{ing:namespace }}{{ thing:name }}{{header:device-id }}", placeholders)); assertThatExceptionOfType(UnresolvedPlaceholderException.class).isThrownBy( () -> PlaceholderFilter.validate("{{th}}ing:namespace }}{{ thing:name }}{{header:device-id }}", placeholders)); assertThatExceptionOfType(UnresolvedPlaceholderException.class).isThrownBy( () -> PlaceholderFilter.validate("{{thing:nam{{espace }}{{ thing:name }}{{header:device-id }}", placeholders)); assertThatExceptionOfType(UnresolvedPlaceholderException.class).isThrownBy( () -> PlaceholderFilter.validate("{{thing:nam}}espace }}{{ thing:name }}{{header:device-id }}", placeholders)); assertThatExceptionOfType(PlaceholderFunctionTooComplexException.class).isThrownBy( () -> PlaceholderFilter.validate( "{{ header:unknown | fn:default('fallback') | fn:upper() | fn:lower() | fn:upper() | fn:lower() | fn:upper() | fn:lower() | fn:upper() | fn:lower() | fn:upper() | fn:lower() }}", placeholders)); }