Purge warnings in IDE
This commit is contained in:
@@ -35,7 +35,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class AbstractFunctionCompiler<F> {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(AbstractFunctionCompiler.class);
|
||||
private static Logger logger = LoggerFactory
|
||||
.getLogger(AbstractFunctionCompiler.class);
|
||||
|
||||
// Newlines in the property are escaped
|
||||
private static final String NEWLINE_ESCAPE = Matcher.quoteReplacement("\\n");
|
||||
@@ -44,20 +45,25 @@ public abstract class AbstractFunctionCompiler<F> {
|
||||
private static final String DOUBLE_DOUBLE_QUOTE = Matcher.quoteReplacement("\"\"");
|
||||
|
||||
/**
|
||||
* The user supplied code snippet is inserted into the template and then the result is compiled
|
||||
* The user supplied code snippet is inserted into the template and then the result is
|
||||
* compiled
|
||||
*/
|
||||
private static String SOURCE_CODE_TEMPLATE =
|
||||
"package " + AbstractFunctionCompiler.class.getPackage().getName() + ";\n" +
|
||||
"import java.util.*;\n" + // Helpful to include this
|
||||
"import java.util.function.*;\n" +
|
||||
"import reactor.core.publisher.Flux;\n" +
|
||||
"public class %s implements %sFactory {\n" +
|
||||
" public %s<%s> getResult() {\n" +
|
||||
" %s\n" +
|
||||
" }\n" +
|
||||
"}\n";
|
||||
// @formatter:off
|
||||
private static String SOURCE_CODE_TEMPLATE = "package "
|
||||
+ AbstractFunctionCompiler.class.getPackage().getName() + ";\n"
|
||||
+ "import java.util.*;\n" // Helpful to include this
|
||||
+ "import java.util.function.*;\n"
|
||||
+ "import reactor.core.publisher.Flux;\n"
|
||||
+ "public class %s implements %sFactory {\n"
|
||||
+ " public %s<%s> getResult() {\n"
|
||||
+ " %s\n"
|
||||
+ " }\n"
|
||||
+ "}\n";
|
||||
// @formatter:on
|
||||
|
||||
static enum ResultType { Consumer, Function, Supplier }
|
||||
static enum ResultType {
|
||||
Consumer, Function, Supplier
|
||||
}
|
||||
|
||||
private final ResultType resultType;
|
||||
|
||||
@@ -65,82 +71,98 @@ public abstract class AbstractFunctionCompiler<F> {
|
||||
|
||||
private final RuntimeJavaCompiler compiler = new RuntimeJavaCompiler();
|
||||
|
||||
AbstractFunctionCompiler(ResultType type, String... defaultResultTypeParameterizations) {
|
||||
AbstractFunctionCompiler(ResultType type,
|
||||
String... defaultResultTypeParameterizations) {
|
||||
this.resultType = type;
|
||||
this.defaultResultTypeParameterizations = defaultResultTypeParameterizations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce a factory instance by:<ul>
|
||||
* Produce a factory instance by:
|
||||
* <ul>
|
||||
* <li>Decoding the code String to process any newlines/double-double-quotes
|
||||
* <li>Insert the code into the source code template for a class
|
||||
* <li>Compiling the class using the JDK provided Java Compiler
|
||||
* <li>Loading the compiled class
|
||||
* <li>Invoking a well known method on the factory class to produce a Consumer, Function, or Supplier instance
|
||||
* <li>Invoking a well known method on the factory class to produce a Consumer,
|
||||
* Function, or Supplier instance
|
||||
* <li>Returning that instance.
|
||||
* </ul>
|
||||
*
|
||||
* @return a factory instance
|
||||
*/
|
||||
public CompiledFunctionFactory<F> compile(String name, String code, String... resultTypeParameterizations) {
|
||||
public CompiledFunctionFactory<F> compile(String name, String code,
|
||||
String... resultTypeParameterizations) {
|
||||
if (name == null || name.length() == 0) {
|
||||
throw new IllegalArgumentException("name must not be empty");
|
||||
}
|
||||
logger.info("Initial code property value :'{}'", code);
|
||||
String parameterizations = StringUtils.arrayToCommaDelimitedString(
|
||||
(!ObjectUtils.isEmpty(resultTypeParameterizations)) ? resultTypeParameterizations : this.defaultResultTypeParameterizations);
|
||||
code = decode(code);
|
||||
if (code.startsWith("\"") && code.endsWith("\"")) {
|
||||
code = code.substring(1,code.length()-1);
|
||||
}
|
||||
if (!code.startsWith("return ") && !code.endsWith(";")) {
|
||||
code = String.format("return (%s<%s> & java.io.Serializable) %s;", resultType, parameterizations, code);
|
||||
String parameterizations = StringUtils.arrayToCommaDelimitedString(
|
||||
(!ObjectUtils.isEmpty(resultTypeParameterizations))
|
||||
? resultTypeParameterizations
|
||||
: this.defaultResultTypeParameterizations);
|
||||
code = decode(code);
|
||||
if (code.startsWith("\"") && code.endsWith("\"")) {
|
||||
code = code.substring(1, code.length() - 1);
|
||||
}
|
||||
if (!code.startsWith("return ") && !code.endsWith(";")) {
|
||||
code = String.format("return (%s<%s> & java.io.Serializable) %s;", resultType,
|
||||
parameterizations, code);
|
||||
}
|
||||
logger.info("Processed code property value :\n{}\n", code);
|
||||
String firstLetter = name.substring(0, 1).toUpperCase();
|
||||
name = (name.length() > 1) ? firstLetter + name.substring(1) : firstLetter;
|
||||
String className = String.format("%s.%s%sFactory", this.getClass().getPackage().getName(), name, resultType);
|
||||
CompilationResult compilationResult = buildAndCompileSourceCode(className, code, parameterizations);
|
||||
String className = String.format("%s.%s%sFactory",
|
||||
this.getClass().getPackage().getName(), name, resultType);
|
||||
CompilationResult compilationResult = buildAndCompileSourceCode(className, code,
|
||||
parameterizations);
|
||||
if (compilationResult.wasSuccessful()) {
|
||||
return new CompiledFunctionFactory(className, compilationResult);
|
||||
return new CompiledFunctionFactory<F>(className, compilationResult);
|
||||
}
|
||||
List<CompilationMessage> compilationMessages = compilationResult.getCompilationMessages();
|
||||
List<CompilationMessage> compilationMessages = compilationResult
|
||||
.getCompilationMessages();
|
||||
throw new CompilationFailedException(compilationMessages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the source for and then compile and load a class that embodies
|
||||
* the supplied methodBody. The methodBody is inserted into a class template that
|
||||
* returns the specified parameterized type.
|
||||
* This method can return more than one class if the method body includes local class
|
||||
* declarations. An example methodBody would be <tt>return input -> input.buffer(5).map(list->list.get(0));</tt>.
|
||||
* Create the source for and then compile and load a class that embodies the supplied
|
||||
* methodBody. The methodBody is inserted into a class template that returns the
|
||||
* specified parameterized type. This method can return more than one class if the
|
||||
* method body includes local class declarations. An example methodBody would be
|
||||
* <tt>return input -> input.buffer(5).map(list->list.get(0));</tt>.
|
||||
*
|
||||
* @param className the name of the class
|
||||
* @param methodBody the source code for a method
|
||||
* @param parameterTypeString the String representation for the parameterized return type, e.g.:
|
||||
* <tt><Flux<Object>,Flux<Object></tt>
|
||||
* @return the list of Classes produced by compiling and then loading the snippet of code
|
||||
* @param parameterTypeString the String representation for the parameterized return
|
||||
* type, e.g.: <tt><Flux<Object>,Flux<Object></tt>
|
||||
* @return the list of Classes produced by compiling and then loading the snippet of
|
||||
* code
|
||||
*/
|
||||
private CompilationResult buildAndCompileSourceCode(String className, String methodBody, String parameterTypeString) {
|
||||
String sourceCode = makeSourceClassDefinition(className, methodBody, parameterTypeString);
|
||||
private CompilationResult buildAndCompileSourceCode(String className,
|
||||
String methodBody, String parameterTypeString) {
|
||||
String sourceCode = makeSourceClassDefinition(className, methodBody,
|
||||
parameterTypeString);
|
||||
return compiler.compile(className, sourceCode);
|
||||
}
|
||||
|
||||
private static String decode(String input) {
|
||||
return input.replaceAll(NEWLINE_ESCAPE, "\n").replaceAll(DOUBLE_DOUBLE_QUOTE, "\"");
|
||||
return input.replaceAll(NEWLINE_ESCAPE, "\n").replaceAll(DOUBLE_DOUBLE_QUOTE,
|
||||
"\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a full source code definition for a class by applying the specified method body
|
||||
* to the Reactive template.
|
||||
* Make a full source code definition for a class by applying the specified method
|
||||
* body to the Reactive template.
|
||||
*
|
||||
* @param className the name of the class
|
||||
* @param methodBody the code to insert into the Reactive source class template
|
||||
* @return a complete Java Class definition
|
||||
*/
|
||||
private String makeSourceClassDefinition(String className, String methodBody, String types) {
|
||||
private String makeSourceClassDefinition(String className, String methodBody,
|
||||
String types) {
|
||||
String shortClassName = className.substring(className.lastIndexOf('.') + 1);
|
||||
String s = String.format(SOURCE_CODE_TEMPLATE, shortClassName, resultType, resultType, types, methodBody);
|
||||
String s = String.format(SOURCE_CODE_TEMPLATE, shortClassName, resultType,
|
||||
resultType, types, methodBody);
|
||||
System.out.println(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user