Skip to content

Commit

Permalink
Generation updated.
Browse files Browse the repository at this point in the history
  • Loading branch information
noboomu committed Apr 3, 2017
1 parent 3a47fe0 commit 714520a
Showing 1 changed file with 119 additions and 50 deletions.
169 changes: 119 additions & 50 deletions src/com/wurrly/tests/TestGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,24 @@
*/
package com.wurrly.tests;

import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import io.undertow.util.MimeMappings;

import java.io.File;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.lang.model.element.Modifier;
Expand All @@ -35,10 +41,6 @@
import com.wurrly.server.ServerRequest;
import com.wurrly.utilities.HandleGenerator;

import io.undertow.server.HttpServerExchange;
import io.undertow.util.HttpString;
import io.undertow.util.MimeMappings;

/**
* @author jbauer
*
Expand All @@ -47,15 +49,17 @@ public class TestGenerator
{
private static Logger log = LoggerFactory.getLogger(TestGenerator.class.getCanonicalName());

private static final Pattern TYPE_NAME_PATTERN = Pattern.compile("(java\\.util\\.[A-Za-z]+)<([^>]+)",Pattern.DOTALL | Pattern.UNIX_LINES);

public static enum StatementParameterType
{
STRING,LITERAL,TYPE
}

public static void generateTypeLiteral( MethodSpec.Builder builder, Type type, String name, String reference )
public static void generateTypeLiteral( MethodSpec.Builder builder, Type type, String name)
{

builder.addCode(CodeBlock.of("\n\ncom.jsoniter.spi.TypeLiteral<$T> $LType = com.jsoniter.spi.TypeLiteral.create($L);\n\n",type,name,reference));
builder.addCode(CodeBlock.of("\n\ncom.jsoniter.spi.TypeLiteral<$T> $L = new com.jsoniter.spi.TypeLiteral<$L>(){};\n\n",type,name,type));

}

Expand All @@ -79,6 +83,7 @@ public static enum TypeHandler
JsonIteratorType("JsonIterator $L = Extractors.jsonIterator(exchange)",true,StatementParameterType.LITERAL),
ModelType("$T $L = Extractors.typed(exchange,$L)",true,StatementParameterType.TYPE,StatementParameterType.LITERAL,StatementParameterType.LITERAL),
EnumType("$T $L = Extractors.extractEnum(exchange,$L.class,$S)",true,StatementParameterType.TYPE,StatementParameterType.LITERAL,StatementParameterType.LITERAL,StatementParameterType.STRING),
ByteBufferType("ByteBuffer $L = Extractors.fileBytes(exchange,$S)",false,StatementParameterType.LITERAL,StatementParameterType.STRING),

OptionalJsonIteratorType("Optional<JsonIterator> $L = Extractors.Optional.jsonIterator(exchange)",true,StatementParameterType.LITERAL),
OptionalAnyType("Optional<Any> $L = Extractors.Optional.any(exchange)",true,StatementParameterType.LITERAL),
Expand All @@ -87,7 +92,8 @@ public static enum TypeHandler
OptionalIntegerType("Optional<Integer> $L = Extractors.Optional.integerValue(exchange,$S)",false,StatementParameterType.LITERAL,StatementParameterType.STRING),
OptionalBooleanType("Optional<Boolean> $L = Extractors.Optional.booleanValue(exchange,$S)",false,StatementParameterType.LITERAL,StatementParameterType.STRING),
OptionalPathType("Optional<Path> $L = Extractors.Optional.filePath(exchange,$S)",true,StatementParameterType.LITERAL,StatementParameterType.STRING),

OptionalModelType("Optional<Model> $L = Extractors.Optional.typed(exchange,$L)",true,StatementParameterType.LITERAL,StatementParameterType.LITERAL),

;

public boolean isBlocking()
Expand Down Expand Up @@ -143,7 +149,7 @@ public static void addStatement(MethodSpec.Builder builder, Parameter parameter)
builder.addStatement( handler.statement, args);
}

public static TypeHandler forType( Type type ) throws Exception
public static TypeHandler forType( Type type )
{
boolean isEnum = false;

Expand All @@ -157,7 +163,7 @@ public static TypeHandler forType( Type type ) throws Exception
// TODO: handle exception
}

log.debug(type.getTypeName() + " " + type.toString() + " is enum " + isEnum);
// log.debug(type.getTypeName() + " " + type.toString() + " is enum " + isEnum);

if( type.equals( Long.class ) )
{
Expand All @@ -167,6 +173,10 @@ else if( type.equals( Integer.class ) )
{
return IntegerType;
}
else if( type.equals( java.nio.ByteBuffer.class ) )
{
return ByteBufferType;
}
else if( type.equals( Boolean.class ) )
{
return BooleanType;
Expand Down Expand Up @@ -211,7 +221,8 @@ else if( type.getTypeName().contains("java.nio.file.Path"))
}
else
{
throw new Exception("No type handler found!");
return StringType;
//throw new Exception("No type handler found!");
}
}
else if( isEnum )
Expand All @@ -225,6 +236,44 @@ else if( isEnum )
}
}

public static String typeLiteralNameForType( Type type )
{
String typeName = type.getTypeName();

Matcher matcher = TYPE_NAME_PATTERN.matcher(typeName);

if (matcher.find()) {

int matches = matcher.groupCount();

if( matches == 2 )
{
String genericInterface = matcher.group(1);
String erasedType = matcher.group(2).replaceAll("\\$", ".");

String[] genericParts = genericInterface.split("\\.");
String[] erasedParts = erasedType.split("\\.");

String genericTypeName = genericParts[genericParts.length-1];
String erasedTypeName = null;

if(erasedParts.length > 1)
{
erasedTypeName = erasedParts[erasedParts.length-2] + erasedParts[erasedParts.length-1];
}
else
{
erasedTypeName = erasedParts[0];
}

return String.format("%s%s%s",Character.toLowerCase(erasedTypeName.charAt(0)),erasedTypeName.substring(1,erasedTypeName.length()),genericTypeName);
}

}

return typeName;
}

public static void main(String[] args)
{

Expand Down Expand Up @@ -294,7 +343,6 @@ public static void addClassMethodHandlers( TypeSpec.Builder typeBuilder, Class<?
ClassName exchangeClass = ClassName.get("io.undertow.server","HttpServerExchange");



String controllerName = clazz.getSimpleName().toLowerCase() + "Controller";

FieldSpec.Builder fieldBuilder = FieldSpec.builder(clazz, controllerName, Modifier.PROTECTED);
Expand All @@ -306,9 +354,37 @@ public static void addClassMethodHandlers( TypeSpec.Builder typeBuilder, Class<?
typeBuilder.addField(fieldBuilder.build());



MethodSpec.Builder initBuilder = MethodSpec.methodBuilder("addRouteHandlers").addModifiers(Modifier.PUBLIC)
.addParameter(ParameterSpec.builder( io.undertow.server.RoutingHandler.class, "router", Modifier.FINAL).build());

final Map<Type,String> allParameterTypeMap = Arrays.stream(clazz.getDeclaredMethods())
.flatMap( m -> {
return Arrays.stream(m.getParameters())
.map( Parameter::getParameterizedType )
.filter( t -> t.getTypeName().contains("<"));
})
.distinct()
.filter( t -> {
TypeHandler handler = TypeHandler.forType(t);
return (handler.equals(TypeHandler.ModelType) || handler.equals(TypeHandler.OptionalModelType));
} )
.collect(Collectors.toMap(java.util.function.Function.identity(), TestGenerator::typeLiteralNameForType));


initBuilder.addCode("$L","\n");


allParameterTypeMap.forEach( (t,n) -> {

initBuilder.addStatement("final TypeLiteral<$L> $LType = new TypeLiteral<$L>(){}",t,n,t);

});

initBuilder.addCode("$L","\n");



for( Method m : com.wurrly.controllers.Users.class.getDeclaredMethods() )
{
String methodPath = HandleGenerator.extractPathTemplate.apply(m);
Expand Down Expand Up @@ -337,11 +413,9 @@ public static void addClassMethodHandlers( TypeSpec.Builder typeBuilder, Class<?



System.out.println(" " + (new LinkedList<String>()).getClass());

for( Parameter p : m.getParameters() )
{
System.out.println(" p type: " + p.getParameterizedType());

if(p.getParameterizedType().equals(ServerRequest.class))
{
Expand All @@ -351,23 +425,12 @@ public static void addClassMethodHandlers( TypeSpec.Builder typeBuilder, Class<?
try
{
TypeHandler t = TypeHandler.forType(p.getParameterizedType());

if( t.equals(TypeHandler.ModelType) )
{
generateTypeLiteral(initBuilder,(Type)p.getParameterizedType(),p.getName(),"");


}


Method m2 = Extractors.class.getMethod("string", HttpServerExchange.class, String.class);

log.debug(m2.getName());
log.debug(m2.toString());

log.debug("t handler: " + t.name());

if(t.isBlocking())
{
methodBuilder.addCode("$L","\n");

methodBuilder.beginControlFlow("if(exchange.isInIoThread())");
methodBuilder.addStatement("exchange.dispatch(this)");
methodBuilder.endControlFlow();
Expand All @@ -381,59 +444,61 @@ public static void addClassMethodHandlers( TypeSpec.Builder typeBuilder, Class<?
}
};


methodBuilder.addCode("$L","\n");


Arrays.stream(m.getParameters()).forEachOrdered( p -> {

Type type = p.getParameterizedType();

try
{





if(p.getType().equals(ServerRequest.class))
{
methodBuilder.addCode(CodeBlock.of("ServerRequest serverRequest = new ServerRequest(exchange);\n"));
methodBuilder.addCode("$L","\n");

}
else
{
TypeHandler.addStatement(methodBuilder,p);
TypeHandler t = TypeHandler.forType(type);

if(t.equals(TypeHandler.OptionalModelType) || t.equals(TypeHandler.ModelType))
{
methodBuilder.addStatement(t.statement,type,allParameterTypeMap.get(type),type);
}
else
{
TypeHandler.addStatement(methodBuilder,p);
}
}
// else if(p.getType().equals(Long.class))
// {
// methodBuilder.addStatement("\nLong $L = extractLong.apply(exchange, $S)", p.getName(), p.getName());
// }
// else if(p.getType().equals(File.class))
// {
// methodBuilder.addStatement("\nFile $L = extractFile.apply(exchange, $S)", p.getName(), p.getName());
// }
// else if(p.getParameterizedType().equals(Optional.class))
// {
//
// methodBuilder.addStatement("\n$T $L = extractOptionalString.apply(exchange, $S)",p.getParameterizedType(), p.getName(), p.getName());
// }


} catch (Exception e)
{
log.error(e.getMessage(),e);
}

});

methodBuilder.addCode("$L","\n");

CodeBlock.Builder functionBlockBuilder = CodeBlock.builder();

String controllerMethodArgs = Arrays.stream(m.getParameters()).map( p -> p.getName() ).collect(Collectors.joining(","));

if( !m.getReturnType().equals(Void.class))
{
log.debug("return : " + m.getReturnType());
functionBlockBuilder.add("$T $L = $L.$L($L);\n", m.getReturnType(), "response", controllerName, m.getName(), controllerMethodArgs );
functionBlockBuilder.add("$T $L = $L.$L($L);", m.getReturnType(), "response", controllerName, m.getName(), controllerMethodArgs );

}

methodBuilder.addCode(functionBlockBuilder.build());


methodBuilder.addCode("$L","\n");

String returnContentType = MimeMappings.DEFAULT.getMimeType("json");

Optional<javax.ws.rs.Produces> producesAnnotation = Optional.ofNullable(m.getAnnotation(javax.ws.rs.Produces.class));
Expand All @@ -452,8 +517,10 @@ public static void addClassMethodHandlers( TypeSpec.Builder typeBuilder, Class<?
returnContentType = producesAnnotation.get().value()[0];
}

methodBuilder.addStatement("exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, $S)",returnContentType);
methodBuilder.addCode("$L","\n");

methodBuilder.addStatement("exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, $S)",returnContentType);

if( m.getReturnType().equals(String.class))
{
methodBuilder.addStatement("exchange.getResponseHeaders().send($L)","response");
Expand All @@ -478,6 +545,8 @@ public static void addClassMethodHandlers( TypeSpec.Builder typeBuilder, Class<?
initBuilder.addCode("$L\n",handlerField.toString());

initBuilder.addStatement("$L.add(io.undertow.util.Methods.$L,$S,$L)", "router", httpMethod,methodPath, methodName);

initBuilder.addCode("$L","\n");
}

typeBuilder.addMethod(initBuilder.build());
Expand Down

0 comments on commit 714520a

Please sign in to comment.