001package io.jstach.jstachio.formatters; 002 003import java.io.IOException; 004import java.net.URI; 005import java.net.URL; 006 007import org.eclipse.jdt.annotation.Nullable; 008 009import io.jstach.jstache.JStacheFormatter; 010import io.jstach.jstache.JStacheFormatterTypes; 011import io.jstach.jstachio.Appender; 012import io.jstach.jstachio.Formatter; 013import io.jstach.jstachio.context.ContextNode; 014 015/** 016 * Formatter that follows the spec rules that if a variable is <code>null</code> it will 017 * be an empty string (ie NOOP). 018 */ 019@JStacheFormatter 020@JStacheFormatterTypes(types = { URI.class, URL.class }) 021public interface SpecFormatter extends Formatter { 022 023 /** 024 * {@inheritDoc} 025 */ 026 @Override 027 default <A extends Appendable, APPENDER extends Appender<A>> void format(APPENDER downstream, A a, String path, 028 Class<?> c, @Nullable Object o) throws IOException { 029 if (o instanceof ContextNode m) { 030 downstream.append(a, m.renderString()); 031 } 032 else if (o != null) { 033 downstream.append(a, String.valueOf(o)); 034 } 035 } 036 037 /** 038 * {@inheritDoc} <strong> Unlike the normal behavior of {@link String#valueOf(Object)} 039 * if a String is null then nothing will be rendered per the mustache spec. </strong>. 040 */ 041 @Override 042 default <A extends Appendable, APPENDER extends Appender<A>> void format(APPENDER downstream, A a, String path, 043 String s) throws IOException { 044 if (s != null) { 045 downstream.append(a, s); 046 } 047 } 048 049 /** 050 * Provides the formatter for static lookup. 051 * @return the single instance of the spec formatter 052 */ 053 public static Formatter provider() { 054 return SpecFormatterSingleton.SpecFormatter; 055 } 056 057} 058 059enum SpecFormatterSingleton implements SpecFormatter { 060 061 SpecFormatter; 062 063}