package org.esmerilprogramming.overtown.http; import java.io.StringWriter; import java.math.BigDecimal; import java.math.BigInteger; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.json.Json; import javax.json.JsonObject; import javax.json.stream.JsonGenerator; import io.undertow.io.Sender; import io.undertow.server.HttpServerExchange; import org.esmerilprogramming.overtown.http.converter.DefaultObjectToJsonConverter; import org.esmerilprogramming.overtown.http.converter.ObjectToJsonConverter; import org.esmerilprogramming.overtown.view.ViewAttributes; public class JsonResponse extends Response { private Map<String, ObjectToJsonConverter> converters; public JsonResponse(HttpServerExchange exchange, ViewAttributes viewAttributes) { super(exchange, viewAttributes); super.setContentType( "application/json; charset=UTF-8;" ); converters = new HashMap<>(); } @Override public void sendRedirect(String toPath) { throw new IllegalStateException("Json response does not suport redirect"); } @Override public void setContentType(String contentType) { throw new IllegalStateException("Content-type can't be changed"); } @Override public void setHeader(String headerName, String value) { if("content-type".equalsIgnoreCase(headerName)){ throw new IllegalStateException("Content-type can't be changed"); }else{ super.setHeader(headerName, value); } } @Override public void addAttribute(String name, Object value) { super.addAttribute(name , value); } @Override public void sendAsResponse(String jsonAsString) { if(!exchange.isComplete()){ Sender responseSender = exchange.getResponseSender(); responseSender.send(jsonAsString); responseSender.close(); } } public void addObjectToJsonConnveter(String attributeName , ObjectToJsonConverter conveter){ if(converters == null){ converters = new HashMap<>(); } converters.put(attributeName , conveter ); } @Override public void finishResponse() { sendAsResponse( generateStringResponse() ); } protected String generateStringResponse(){ Set<Entry<String, Object>> entrySet = viewAttributes.getAsMap().entrySet(); StringWriter stringWriter = new StringWriter(); JsonGenerator generator = Json.createGenerator( stringWriter ); generator.writeStartObject(); for (Entry<String, Object> entry : entrySet) { String attrName = entry.getKey(); ObjectToJsonConverter objectToJsonConverter = converters.get(attrName); objectToJsonConverter = objectToJsonConverter == null ? new DefaultObjectToJsonConverter() : objectToJsonConverter; Object value = entry.getValue(); if(isSimpleValue(value) ){ writeSimpleValueEntry( entry, generator ); }else{ JsonObject jsonObject = objectToJsonConverter.converter( value ); generator.write( entry.getKey() , jsonObject ); } } generator.writeEnd(); generator.flush(); return stringWriter.toString(); } private void writeSimpleValueEntry(Entry<String, Object> entry, JsonGenerator generator) { Object value = entry.getValue(); if( value.getClass().isAssignableFrom( String.class ) ){ generator.write( entry.getKey() , (String) value ); }else if( value.getClass().isAssignableFrom( Integer.class ) || value.getClass().isAssignableFrom( int.class ) ){ generator.write( entry.getKey() , (Integer) value ); }else if ( value.getClass().isAssignableFrom( Double.class ) || value.getClass().isAssignableFrom( double.class ) ){ generator.write( entry.getKey() , (Double) value ); }else if ( value.getClass().isAssignableFrom( Long.class ) || value.getClass().isAssignableFrom( double.class ) ){ generator.write( entry.getKey() , (Long) value ); }else if ( value.getClass().isAssignableFrom( Float.class ) || value.getClass().isAssignableFrom( float.class ) ){ generator.write( entry.getKey() , (Float) value ); }else if ( value.getClass().isAssignableFrom( Boolean.class ) || value.getClass().isAssignableFrom( boolean.class ) ){ generator.write( entry.getKey() , (Boolean) value ); }else if ( value.getClass().isAssignableFrom( BigDecimal.class ) ){ generator.write( entry.getKey() , (BigDecimal) value ); }else if ( value.getClass().isAssignableFrom( BigInteger.class ) ){ generator.write( entry.getKey() , (BigInteger) value ); } } private boolean isSimpleValue(Object value) { Class<? extends Object> clazz = value.getClass(); return clazz.isAssignableFrom( String.class ) || clazz.isAssignableFrom( Integer.class ) || clazz.isAssignableFrom( int.class ) || clazz.isAssignableFrom( Double.class ) || clazz.isAssignableFrom( double.class ) || clazz.isAssignableFrom( Long.class ) || clazz.isAssignableFrom( double.class ) || clazz.isAssignableFrom( Float.class ) || clazz.isAssignableFrom( float.class ) || clazz.isAssignableFrom( Boolean.class ) || clazz.isAssignableFrom( boolean.class ) || clazz.isAssignableFrom( BigDecimal.class ) || clazz.isAssignableFrom( BigInteger.class ); } protected JsonGenerator writeSimpleValue(String attrName , Object value , JsonGenerator generator){ Class<? extends Object> clazz = value.getClass(); if( clazz.isAssignableFrom( String.class ) ){ generator.write( attrName , value.toString() ); }else if( clazz.isAssignableFrom( Double.class ) ){ generator.write( attrName , (Double) value ); }else if( clazz.isAssignableFrom( Integer.class ) ){ generator.write( attrName , (Integer) value ); }else if(value.getClass().isAssignableFrom(Boolean.class)){ generator.write( attrName , new Boolean( value.toString() ) ); }else{ generator.write( attrName , value.toString() ); } return generator; } public Map<String, ObjectToJsonConverter> getConverters() { return converters; } }