001package io.jstach.opt.spring.webflux; 002 003import java.util.Map; 004 005import org.eclipse.jdt.annotation.Nullable; 006import org.springframework.core.ResolvableType; 007import org.springframework.core.codec.AbstractSingleValueEncoder; 008import org.springframework.core.codec.Hints; 009import org.springframework.core.io.buffer.DataBuffer; 010import org.springframework.core.io.buffer.DataBufferFactory; 011import org.springframework.http.MediaType; 012import org.springframework.util.MimeType; 013 014import io.jstach.jstachio.JStachio; 015import io.jstach.jstachio.Template; 016import reactor.core.publisher.Flux; 017 018/** 019 * Encodes a JStachio model into a bytes to be used as output from a webflux reactive 020 * controller. 021 * 022 * @author agentgt 023 * @author dsyer 024 */ 025@SuppressWarnings("exports") 026public class JStachioEncoder extends AbstractSingleValueEncoder<Object> { 027 028 private final JStachio jstachio; 029 030 private final int allocateBufferSize; 031 032 /** 033 * Create the encoder from a JStachio 034 * @param jstachio not <code>null</code>. 035 */ 036 public JStachioEncoder(JStachio jstachio) { 037 this(jstachio, 4 * 1024); 038 } 039 040 /** 041 * Create the encoder from a JStachio 042 * @param jstachio not <code>null</code>. 043 * @param allocateBufferSize how much to initially allocate from the buffer factory 044 */ 045 public JStachioEncoder(JStachio jstachio, int allocateBufferSize) { 046 super(MediaType.TEXT_HTML); 047 this.jstachio = jstachio; 048 this.allocateBufferSize = allocateBufferSize; 049 } 050 051 @Override 052 public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { 053 Class<?> clazz = elementType.toClass(); 054 return clazz != Object.class && !CharSequence.class.isAssignableFrom(clazz) && jstachio.supportsType(clazz); 055 } 056 057 @Override 058 protected Flux<DataBuffer> encode(Object event, DataBufferFactory bufferFactory, ResolvableType type, 059 @Nullable MimeType mimeType, @Nullable Map<String, Object> hints) { 060 return Flux.just(encodeValue(event, bufferFactory, type, mimeType, hints)); 061 } 062 063 @Override 064 public DataBuffer encodeValue(Object event, DataBufferFactory bufferFactory, ResolvableType valueType, 065 MimeType mimeType, Map<String, Object> hints) { 066 if (logger.isDebugEnabled() && !Hints.isLoggingSuppressed(hints)) { 067 String logPrefix = Hints.getLogPrefix(hints); 068 logger.debug(logPrefix + "Writing [" + event + "]"); 069 } 070 071 Template<Object> template; 072 try { 073 template = jstachio.findTemplate(event); 074 } 075 catch (Exception e) { 076 throw new RuntimeException(e); 077 } 078 079 DataBufferOutput output = new DataBufferOutput(bufferFactory.allocateBuffer(allocateBufferSize), 080 template.templateCharset()); 081 082 return template.write(event, output).getBuffer(); 083 084 } 085 086}