mirror of
https://github.com/JHUAPL/Jackfruit.git
synced 2026-01-08 20:08:02 -05:00
Merge branch '14-throw-runtime-exception-if-key-not-found' into 'main'
Resolve "throw runtime exception if key not found" Closes #14 See merge request nairah1/jackfruit!14
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.idea
|
||||
12
demo/pom.xml
12
demo/pom.xml
@@ -25,23 +25,11 @@
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.jhuapl.ses.saa</groupId>
|
||||
<artifactId>crucible-all</artifactId>
|
||||
<version>1.0.0-b74-7d477359</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.jhuapl.ses.srn</groupId>
|
||||
<artifactId>jackfruit</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
package crucible.crust.logging;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.Appender;
|
||||
import org.apache.logging.log4j.core.LoggerContext;
|
||||
import org.apache.logging.log4j.core.appender.ConsoleAppender;
|
||||
import org.apache.logging.log4j.core.appender.FileAppender;
|
||||
import org.apache.logging.log4j.core.config.Configuration;
|
||||
import org.apache.logging.log4j.core.config.Configurator;
|
||||
import org.apache.logging.log4j.core.config.DefaultConfiguration;
|
||||
import org.apache.logging.log4j.core.config.LoggerConfig;
|
||||
import org.apache.logging.log4j.core.layout.PatternLayout;
|
||||
|
||||
/**
|
||||
* A simple configuration class.
|
||||
* <p>
|
||||
* Default settings:
|
||||
* <ul>
|
||||
* <li>Pattern is "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%c{1}:%L] %msg%n%throwable"<br>
|
||||
* (e.g. 2021-11-09 19:32:37.119 INFO [LoggingTest:25] Level INFO)</li>
|
||||
* <li>Log level is {@link Level#INFO}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author nairah1
|
||||
*
|
||||
*/
|
||||
public class Log4j2Configurator {
|
||||
|
||||
private PatternLayout layout;
|
||||
private final Map<String, FileAppender> fileAppenders;
|
||||
|
||||
private static Log4j2Configurator instance = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return an instance of this singleton class.
|
||||
*/
|
||||
synchronized public static Log4j2Configurator getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Log4j2Configurator();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Log4j2Configurator() {
|
||||
final LoggerContext loggerContext = LoggerContext.getContext(false);
|
||||
final Configuration config = loggerContext.getConfiguration();
|
||||
layout = PatternLayout.newBuilder().withPattern(DefaultConfiguration.DEFAULT_PATTERN)
|
||||
.withConfiguration(config).build();
|
||||
fileAppenders = new HashMap<>();
|
||||
setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%c{1}:%L] %msg%n%throwable");
|
||||
setLevel(Level.INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return a map of logger names to {@link LoggerConfig}
|
||||
*/
|
||||
private Map<String, LoggerConfig> getLoggerMap() {
|
||||
final LoggerContext loggerContext = LoggerContext.getContext(false);
|
||||
final Configuration config = loggerContext.getConfiguration();
|
||||
|
||||
Map<String, LoggerConfig> loggerMap = new HashMap<>(config.getLoggers());
|
||||
loggerMap.put(LogManager.getRootLogger().getName(),
|
||||
config.getLoggerConfig(LogManager.getRootLogger().getName()));
|
||||
return Collections.unmodifiableMap(loggerMap);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param filename Append log to named file, or create it if it doesn't exist.
|
||||
*/
|
||||
public void addFile(String filename) {
|
||||
final LoggerContext loggerContext = LoggerContext.getContext(false);
|
||||
Map<String, LoggerConfig> loggerMap = getLoggerMap();
|
||||
|
||||
FileAppender appender = FileAppender.newBuilder().setName(filename).withFileName(filename)
|
||||
.setLayout(layout).build();
|
||||
appender.start();
|
||||
|
||||
for (String loggerName : loggerMap.keySet()) {
|
||||
LoggerConfig loggerConfig = loggerMap.get(loggerName);
|
||||
loggerConfig.addAppender(appender, null, null);
|
||||
}
|
||||
loggerContext.updateLoggers();
|
||||
fileAppenders.put(filename, appender);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param filename Stop logging to named file.
|
||||
*/
|
||||
public void removeFile(String filename) {
|
||||
if (fileAppenders.containsKey(filename)) {
|
||||
final LoggerContext loggerContext = LoggerContext.getContext(false);
|
||||
Map<String, LoggerConfig> loggerMap = getLoggerMap();
|
||||
|
||||
FileAppender appender = fileAppenders.get(filename);
|
||||
for (String loggerName : loggerMap.keySet()) {
|
||||
LoggerConfig loggerConfig = loggerMap.get(loggerName);
|
||||
loggerConfig.removeAppender(appender.getName());
|
||||
}
|
||||
loggerContext.updateLoggers();
|
||||
fileAppenders.remove(filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pattern layout pattern for all {@link ConsoleAppender} and {@link FileAppender} objects.
|
||||
*/
|
||||
public void setPattern(String pattern) {
|
||||
final LoggerContext loggerContext = LoggerContext.getContext(false);
|
||||
final Configuration config = loggerContext.getConfiguration();
|
||||
|
||||
layout = PatternLayout.newBuilder().withConfiguration(config).withPattern(pattern).build();
|
||||
|
||||
Map<String, LoggerConfig> loggerMap = getLoggerMap();
|
||||
for (String loggerName : loggerMap.keySet()) {
|
||||
LoggerConfig loggerConfig = loggerMap.get(loggerName);
|
||||
Map<String, Appender> appenderMap = loggerConfig.getAppenders();
|
||||
for (String appenderName : appenderMap.keySet()) {
|
||||
Appender newAppender = null;
|
||||
Appender oldAppender = appenderMap.get(appenderName);
|
||||
|
||||
// there should be a better way to do this - a toBuilder() method on the appender would be
|
||||
// really useful
|
||||
if (oldAppender instanceof ConsoleAppender) {
|
||||
newAppender = ConsoleAppender.newBuilder().setName(appenderName).setConfiguration(config)
|
||||
.setLayout(layout).build();
|
||||
} else if (oldAppender instanceof FileAppender) {
|
||||
newAppender = FileAppender.newBuilder().setName(appenderName).setConfiguration(config)
|
||||
.withFileName(((FileAppender) oldAppender).getFileName()).setLayout(layout).build();
|
||||
}
|
||||
if (newAppender != null) {
|
||||
newAppender.start();
|
||||
loggerConfig.removeAppender(appenderName);
|
||||
loggerConfig.addAppender(newAppender, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
loggerContext.updateLoggers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the levels of <code>parentLogger</code> and all 'child' loggers to the given
|
||||
* <code>level</code>. This is simply a call to
|
||||
*
|
||||
* <pre>
|
||||
* Configurator.setAllLevels(parentLogger, level)
|
||||
* </pre>
|
||||
*
|
||||
* @param parentLogger
|
||||
* @param level
|
||||
*/
|
||||
public void setLevel(String parentLogger, Level level) {
|
||||
Configurator.setAllLevels(parentLogger, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all logger levels. This is simply a call to
|
||||
*
|
||||
* <pre>
|
||||
* setLevel(LogManager.getRootLogger().getName(), level)
|
||||
* </pre>
|
||||
*
|
||||
* @param level
|
||||
*/
|
||||
public void setLevel(Level level) {
|
||||
setLevel(LogManager.getRootLogger().getName(), level);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package jackfruit.demo;
|
||||
|
||||
public class SomeRandomClass {
|
||||
|
||||
private String internalString;
|
||||
private final String internalString;
|
||||
|
||||
public String getInternalString() {
|
||||
return internalString;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package jackfruit.demo;
|
||||
|
||||
import crucible.crust.logging.Log4j2Configurator;
|
||||
import jackfruit.processor.ConfigProcessor;
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaCompiler.CompilationTask;
|
||||
@@ -13,8 +15,6 @@ import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.StandardLocation;
|
||||
import javax.tools.ToolProvider;
|
||||
import org.junit.Test;
|
||||
import crucible.crust.logging.Log4j2Configurator;
|
||||
import jackfruit.processor.ConfigProcessor;
|
||||
|
||||
/**
|
||||
* From <a href=
|
||||
@@ -48,7 +48,7 @@ public class TestProcessor {
|
||||
|
||||
CompilationTask task =
|
||||
compiler.getTask(new PrintWriter(System.out), null, null, null, null, files);
|
||||
task.setProcessors(Arrays.asList(new ConfigProcessor()));
|
||||
task.setProcessors(List.of(new ConfigProcessor()));
|
||||
|
||||
task.call();
|
||||
}
|
||||
@@ -58,7 +58,7 @@ public class TestProcessor {
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
StandardJavaFileManager files = compiler.getStandardFileManager(null, null, null);
|
||||
|
||||
files.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(new File(p_path)));
|
||||
files.setLocation(StandardLocation.SOURCE_PATH, List.of(new File(p_path)));
|
||||
|
||||
Set<Kind> fileKinds = Collections.singleton(Kind.SOURCE);
|
||||
return files.list(StandardLocation.SOURCE_PATH, "", fileKinds, true);
|
||||
|
||||
@@ -30,17 +30,11 @@
|
||||
<maven-compiler-plugin.version>
|
||||
3.10.1
|
||||
</maven-compiler-plugin.version>
|
||||
<log4j-version>2.19.0</log4j-version>
|
||||
<log4j-version>2.20.0</log4j-version>
|
||||
<immutables.version>2.9.2</immutables.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service</artifactId>
|
||||
|
||||
@@ -2,23 +2,29 @@
|
||||
|
||||
# This script is run from maven. See the exec-maven-plugin block in the pom.xml file.
|
||||
|
||||
cd $(dirname $0)
|
||||
package=jackfruit
|
||||
srcFile="../java/jackfruit/JackfruitVersion.java"
|
||||
|
||||
rev=$(git rev-parse --verify --short=8 HEAD)
|
||||
if [ $? -gt 0 ]; then
|
||||
rev="UNKNOWN"
|
||||
fi
|
||||
|
||||
branch=$(git symbolic-ref --short HEAD)
|
||||
if [ $? -gt 0 ]; then
|
||||
branch="UNKNOWN"
|
||||
fi
|
||||
cd $(dirname "$0")
|
||||
|
||||
date=$(date -u +"%y.%m.%d")
|
||||
|
||||
package=jackfruit
|
||||
srcFile="../java/jackfruit/JackfruitVersion.java"
|
||||
mkdir -p $(dirname $srcFile)
|
||||
rev=$(git rev-parse --verify --short HEAD)
|
||||
if [ $? -gt 0 ]; then
|
||||
lastCommit=$(date -u +"%y.%m.%d")
|
||||
rev="UNVERSIONED"
|
||||
else
|
||||
lastCommit=$(git log -1 --format=%cd --date=format:%y.%m.%d)
|
||||
rev=$(git rev-parse --verify --short HEAD)
|
||||
|
||||
if [[ $(git diff --stat) != '' ]]; then
|
||||
if [[ $(git status -s | grep -v pom.xml | grep -v pom.bak | grep -v .m2 | grep -v $srcFile) != '' ]]; then
|
||||
rev=${rev}M
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p $(dirname "$srcFile")
|
||||
|
||||
touch $srcFile
|
||||
|
||||
@@ -27,10 +33,11 @@ cat <<EOF > $srcFile
|
||||
package jackfruit;
|
||||
|
||||
public class JackfruitVersion {
|
||||
public final static String rev = new String("$rev");
|
||||
public final static String packageName = new String("$package");
|
||||
public final static String dateString = new String("$date");
|
||||
public final static String branch = new String("$branch");
|
||||
public final static String lastCommit = "$lastCommit";
|
||||
// an M at the end of gitRevision means this was built from a "dirty" git repository
|
||||
public final static String rev = "$rev";
|
||||
public final static String packageName = "$package";
|
||||
public final static String dateString = "$date";
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
package jackfruit;
|
||||
|
||||
public class JackfruitVersion {
|
||||
public final static String rev = new String("9ad69b62");
|
||||
public final static String packageName = new String("jackfruit");
|
||||
public final static String dateString = new String("22.11.27");
|
||||
public final static String branch = new String("UNKNOWN");
|
||||
public final static String lastCommit = "23.03.29";
|
||||
// an M at the end of gitRevision means this was built from a "dirty" git repository
|
||||
public final static String rev = "b200487M";
|
||||
public final static String packageName = "jackfruit";
|
||||
public final static String dateString = "23.03.29";
|
||||
}
|
||||
|
||||
|
||||
@@ -15,5 +15,5 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Comment {
|
||||
public String value() default "";
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface DefaultValue {
|
||||
public String value() default "";
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
@@ -21,5 +21,5 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Jackfruit {
|
||||
public String prefix() default "";
|
||||
String prefix() default "";
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Key {
|
||||
public String value() default "";
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ package jackfruit.annotations;
|
||||
* @param <T>
|
||||
*/
|
||||
public interface Parser<T> {
|
||||
public T fromString(String s);
|
||||
T fromString(String s);
|
||||
|
||||
public String toString(T t);
|
||||
String toString(T t);
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ import java.lang.annotation.Target;
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ParserClass {
|
||||
public Class<?> value();
|
||||
Class<?> value();
|
||||
}
|
||||
|
||||
@@ -1,64 +1,51 @@
|
||||
package jackfruit.processor;
|
||||
|
||||
import jackfruit.annotations.Parser;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import org.immutables.value.Value;
|
||||
import jackfruit.annotations.Parser;
|
||||
|
||||
/**
|
||||
* Holds annotation information and other metadata about an annotated method.
|
||||
*
|
||||
* @author nairah1
|
||||
*
|
||||
* @author nairah1
|
||||
*/
|
||||
@Value.Immutable
|
||||
public abstract class AnnotationBundle {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the return type of this method without any parameters (e.g. return List rather than
|
||||
* List<String>)
|
||||
* List<String>)
|
||||
*/
|
||||
public abstract TypeMirror erasure();
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the parameterized types, if any of this method (e.g. return String if the annotated
|
||||
* method returns List<String>)
|
||||
* method returns List<String>)
|
||||
*/
|
||||
public abstract List<TypeMirror> typeArgs();
|
||||
|
||||
/**
|
||||
* Comment for this configuration parameter. This can be blank.
|
||||
*
|
||||
* @return
|
||||
* @return Comment for this configuration parameter. This can be blank.
|
||||
*/
|
||||
public abstract String comment();
|
||||
|
||||
/**
|
||||
* Default value for this configuration parameter. This is required.
|
||||
*
|
||||
* @return
|
||||
* @return Default value for this configuration parameter. This is required.
|
||||
*/
|
||||
public abstract String defaultValue();
|
||||
|
||||
/**
|
||||
* Key used in the configuration file. If omitted, default value is the name of the configuration
|
||||
* parameter (the method name).
|
||||
*
|
||||
* @return
|
||||
* @return Key used in the configuration file. If omitted, default value is the name of the
|
||||
* configuration parameter (the method name).
|
||||
*/
|
||||
public abstract String key();
|
||||
|
||||
/**
|
||||
* If this configuration parameter is not a string or primitive/boxed type, this class will
|
||||
* convert the string to the proper object and vice versa. This class must implement
|
||||
* {@link Parser}.
|
||||
*
|
||||
* @return
|
||||
* @return If this configuration parameter is not a string or primitive/boxed type, this class
|
||||
* will convert the string to the proper object and vice versa. This class must implement
|
||||
* {@link Parser}.
|
||||
*/
|
||||
public abstract Optional<TypeMirror> parserClass();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,47 +7,38 @@ import org.apache.commons.configuration2.PropertiesConfigurationLayout;
|
||||
/**
|
||||
* This interface converts instances of annotated interfaces of type T to Apache Commons
|
||||
* Configuration files and vice versa.
|
||||
*
|
||||
* @author nairah1
|
||||
*
|
||||
* @author nairah1
|
||||
* @param <T>
|
||||
*/
|
||||
public interface ConfigFactory<T> {
|
||||
|
||||
/**
|
||||
* This returns an object of type T with default values.
|
||||
*
|
||||
* @return
|
||||
* @return This returns an object of type T with default values.
|
||||
*/
|
||||
T getTemplate();
|
||||
|
||||
/**
|
||||
* This creates an object of type T from the supplied Apache Commons {@link Configuration}.
|
||||
*
|
||||
* @param config
|
||||
* @return
|
||||
* @param config configuration to turn into an object of type T
|
||||
* @return an object of type T from the supplied Apache Commons {@link Configuration}.
|
||||
*/
|
||||
T fromConfig(Configuration config);
|
||||
|
||||
/**
|
||||
* This creates an Apache Commons {@link PropertiesConfiguration} from the supplied object T.
|
||||
*
|
||||
* @param t
|
||||
* @param t object to convert to a configuration
|
||||
* @param layout used for formatting the returned PropertiesConfiguration
|
||||
* @return
|
||||
* @return an Apache Commons {@link PropertiesConfiguration} from the supplied object T.
|
||||
*/
|
||||
PropertiesConfiguration toConfig(T t, PropertiesConfigurationLayout layout);
|
||||
|
||||
/**
|
||||
* This creates an Apache Commons {@link PropertiesConfiguration} from the supplied object T. This
|
||||
* is simply a call to {@link #toConfig(Object, PropertiesConfigurationLayout)} with a new
|
||||
* This is simply a call to {@link #toConfig(Object, PropertiesConfigurationLayout)} with a new
|
||||
* PropertiesConfigurationLayout().
|
||||
*
|
||||
* @param t
|
||||
* @return
|
||||
*
|
||||
* @param t object to convert to a configuration
|
||||
* @return an Apache Commons {@link PropertiesConfiguration} from the supplied object T.
|
||||
*/
|
||||
default PropertiesConfiguration toConfig(T t) {
|
||||
return toConfig(t, new PropertiesConfigurationLayout());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -95,10 +95,9 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
for (Element element : annotatedElements) {
|
||||
|
||||
try {
|
||||
if (element instanceof TypeElement) {
|
||||
TypeElement annotatedType = (TypeElement) element;
|
||||
if (element instanceof TypeElement annotatedType) {
|
||||
|
||||
Jackfruit configParams = (Jackfruit) annotatedType.getAnnotation(Jackfruit.class);
|
||||
Jackfruit configParams = annotatedType.getAnnotation(Jackfruit.class);
|
||||
String prefix = configParams.prefix().strip();
|
||||
if (prefix.length() > 0 && !prefix.endsWith("."))
|
||||
prefix += ".";
|
||||
@@ -161,9 +160,9 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
Map<Name, AnnotationBundle> defaultAnnotationsMap = new LinkedHashMap<>();
|
||||
for (DeclaredType thisType : classHierarchy) {
|
||||
for (Element e : thisType.asElement().getEnclosedElements()) {
|
||||
if (e.getKind() == ElementKind.METHOD && e.getAnnotation(DefaultValue.class) != null
|
||||
&& e instanceof ExecutableElement) {
|
||||
ExecutableElement ex = (ExecutableElement) e;
|
||||
if (e.getKind() == ElementKind.METHOD
|
||||
&& e.getAnnotation(DefaultValue.class) != null
|
||||
&& e instanceof ExecutableElement ex) {
|
||||
enclosedMethods.put(ex.getSimpleName(), ex);
|
||||
AnnotationBundle defaultValues = defaultAnnotationsMap.get(ex.getSimpleName());
|
||||
defaultAnnotationsMap.put(ex.getSimpleName(),
|
||||
@@ -301,8 +300,7 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
builder.comment(((Comment) annotation).value());
|
||||
} else if (annotation instanceof DefaultValue) {
|
||||
builder.defaultValue(((DefaultValue) annotation).value());
|
||||
} else if (annotation instanceof ParserClass) {
|
||||
ParserClass pc = (ParserClass) annotation;
|
||||
} else if (annotation instanceof ParserClass pc) {
|
||||
|
||||
// this works, but there has to be a better way?
|
||||
TypeMirror tm;
|
||||
@@ -334,7 +332,7 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
* @param tvn
|
||||
* @param m
|
||||
* @param annotationsMap
|
||||
* @param prefix
|
||||
* @param prefixMemberName
|
||||
* @return
|
||||
*/
|
||||
private MethodSpec buildToConfig(TypeVariableName tvn, Method m,
|
||||
@@ -554,6 +552,12 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
.addModifiers(Modifier.PUBLIC).addAnnotation(Override.class)
|
||||
.returns(TypeName.get(method.getReturnType())).addJavadoc(bundle.comment());
|
||||
|
||||
builder.addStatement("String key = $N + $S", prefix, bundle.key());
|
||||
builder
|
||||
.beginControlFlow("if (!config.containsKey(key))")
|
||||
.addStatement("throw new $T($S + key)", RuntimeException.class, "No such key")
|
||||
.endControlFlow();
|
||||
|
||||
TypeMirror parser = null;
|
||||
String parserName = null;
|
||||
if (bundle.parserClass().isPresent()) {
|
||||
@@ -570,8 +574,7 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
ParameterizedTypeName.get(ClassName.get(java.util.ArrayList.class), argType);
|
||||
String listName = method.getSimpleName() + "List";
|
||||
builder.addStatement("$T " + listName + " = new $T()", listType, arrayListType);
|
||||
builder.addStatement("String [] parts = config.getStringArray($N + $S)", prefix,
|
||||
bundle.key());
|
||||
builder.addStatement("String [] parts = config.getStringArray(key)");
|
||||
builder.beginControlFlow("for (String part : parts)");
|
||||
builder.beginControlFlow("if (part.trim().length() > 0)");
|
||||
if (bundle.parserClass().isPresent()) {
|
||||
@@ -600,25 +603,24 @@ public class ConfigProcessor extends AbstractProcessor {
|
||||
builder.addStatement("return $L", listName);
|
||||
} else {
|
||||
if (bundle.parserClass().isPresent()) {
|
||||
builder.addStatement("return $L.fromString(config.getString($N + $S))", parserName,
|
||||
prefix, bundle.key());
|
||||
builder.addStatement("return $L.fromString(config.getString(key))", parserName);
|
||||
} else {
|
||||
if (ConfigProcessorUtils.isBoolean(bundle.erasure(), processingEnv)) {
|
||||
builder.addStatement("return config.getBoolean($N + $S)", prefix, bundle.key());
|
||||
builder.addStatement("return config.getBoolean(key)");
|
||||
} else if (ConfigProcessorUtils.isByte(bundle.erasure(), processingEnv)) {
|
||||
builder.addStatement("return config.getByte($N + $S)", prefix, bundle.key());
|
||||
builder.addStatement("return config.getByte(key)");
|
||||
} else if (ConfigProcessorUtils.isDouble(bundle.erasure(), processingEnv)) {
|
||||
builder.addStatement("return config.getDouble($N + $S)", prefix, bundle.key());
|
||||
builder.addStatement("return config.getDouble(key)");
|
||||
} else if (ConfigProcessorUtils.isFloat(bundle.erasure(), processingEnv)) {
|
||||
builder.addStatement("return config.getFloat($N + $S)", prefix, bundle.key());
|
||||
builder.addStatement("return config.getFloat(key)");
|
||||
} else if (ConfigProcessorUtils.isInteger(bundle.erasure(), processingEnv)) {
|
||||
builder.addStatement("return config.getInt($N + $S)", prefix, bundle.key());
|
||||
builder.addStatement("return config.getInt(key)");
|
||||
} else if (ConfigProcessorUtils.isLong(bundle.erasure(), processingEnv)) {
|
||||
builder.addStatement("return config.getLong($N + $S)", prefix, bundle.key());
|
||||
builder.addStatement("return config.getLong(key)");
|
||||
} else if (ConfigProcessorUtils.isShort(bundle.erasure(), processingEnv)) {
|
||||
builder.addStatement("return config.getShort($N + $S)", prefix, bundle.key());
|
||||
builder.addStatement("return config.getShort(key)");
|
||||
} else if (ConfigProcessorUtils.isString(bundle.erasure(), processingEnv)) {
|
||||
builder.addStatement("return config.getString($N + $S)", prefix, bundle.key());
|
||||
builder.addStatement("return config.getString(key)");
|
||||
} else {
|
||||
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
|
||||
"Can't handle return type " + m.getReturnType().getCanonicalName());
|
||||
|
||||
@@ -10,123 +10,114 @@ import javax.tools.Diagnostic;
|
||||
|
||||
public class ConfigProcessorUtils {
|
||||
/**
|
||||
*
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link List}
|
||||
*/
|
||||
public final static boolean isList(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
public static boolean isList(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.util.List.class);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeMirror either {@link #erasure()} for the return value, or an element of
|
||||
* {@link #typeArgs()} for a parameterized type
|
||||
* @param typeMirror either {@link AnnotationBundle#erasure()} for the return value, or an element of {@link
|
||||
* AnnotationBundle#typeArgs()} for a parameterized type
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link Boolean} or primitive boolean
|
||||
*/
|
||||
public final static boolean isBoolean(TypeMirror typeMirror,
|
||||
ProcessingEnvironment processingEnv) {
|
||||
public static boolean isBoolean(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.lang.Boolean.class)
|
||||
|| typeMirror.getKind() == TypeKind.BOOLEAN;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeMirror either {@link #erasure()} for the return value, or an element of
|
||||
* {@link #typeArgs()} for a parameterized type
|
||||
* @param typeMirror either {@link AnnotationBundle#erasure()} for the return value, or an element of {@link
|
||||
* AnnotationBundle#typeArgs()} for a parameterized type
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link Byte} or primitive byte
|
||||
*/
|
||||
public final static boolean isByte(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
public static boolean isByte(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.lang.Byte.class)
|
||||
|| typeMirror.getKind() == TypeKind.BYTE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeMirror either {@link #erasure()} for the return value, or an element of
|
||||
* {@link #typeArgs()} for a parameterized type
|
||||
* @param typeMirror either {@link AnnotationBundle#erasure()} for the return value, or an element of {@link
|
||||
* AnnotationBundle#typeArgs()} for a parameterized type
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link Double} or primitive double
|
||||
*/
|
||||
public final static boolean isDouble(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
public static boolean isDouble(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.lang.Double.class)
|
||||
|| typeMirror.getKind() == TypeKind.DOUBLE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeMirror either {@link #erasure()} for the return value, or an element of
|
||||
* {@link #typeArgs()} for a parameterized type
|
||||
* @param typeMirror either {@link AnnotationBundle#erasure()} for the return value, or an element of {@link
|
||||
* AnnotationBundle#typeArgs()} for a parameterized type
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link Float} or primitive float
|
||||
*/
|
||||
public final static boolean isFloat(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
public static boolean isFloat(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.lang.Float.class)
|
||||
|| typeMirror.getKind() == TypeKind.FLOAT;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeMirror either {@link #erasure()} for the return value, or an element of
|
||||
* {@link #typeArgs()} for a parameterized type
|
||||
* @param typeMirror either {@link AnnotationBundle#erasure()} for the return value, or an element of {@link
|
||||
* AnnotationBundle#typeArgs()} for a parameterized type
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link Integer} or primitive int
|
||||
*/
|
||||
public final static boolean isInteger(TypeMirror typeMirror,
|
||||
ProcessingEnvironment processingEnv) {
|
||||
public static boolean isInteger(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.lang.Integer.class)
|
||||
|| typeMirror.getKind() == TypeKind.INT;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeMirror either {@link #erasure()} for the return value, or an element of
|
||||
* {@link #typeArgs()} for a parameterized type
|
||||
* @param typeMirror either {@link AnnotationBundle#erasure()} for the return value, or an element of {@link
|
||||
* AnnotationBundle#typeArgs()} for a parameterized type
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link Long} or primitive long
|
||||
*/
|
||||
public final static boolean isLong(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
public static boolean isLong(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.lang.Long.class)
|
||||
|| typeMirror.getKind() == TypeKind.LONG;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeMirror either {@link #erasure()} for the return value, or an element of
|
||||
* {@link #typeArgs()} for a parameterized type
|
||||
* @param typeMirror either {@link AnnotationBundle#erasure()} for the return value, or an element of {@link
|
||||
* AnnotationBundle#typeArgs()} for a parameterized type
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link Short} or primitive float
|
||||
*/
|
||||
public final static boolean isShort(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
public static boolean isShort(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.lang.Short.class)
|
||||
|| typeMirror.getKind() == TypeKind.SHORT;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param typeMirror either {@link #erasure()} for the return value, or an element of
|
||||
* {@link #typeArgs()} for a parameterized type
|
||||
* @param typeMirror either {@link AnnotationBundle#erasure()} for the return value, or an element of {@link
|
||||
* AnnotationBundle#typeArgs()} for a parameterized type
|
||||
* @param processingEnv
|
||||
* @return true if this annotated member returns a {@link String}
|
||||
*/
|
||||
public final static boolean isString(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
public static boolean isString(TypeMirror typeMirror, ProcessingEnvironment processingEnv) {
|
||||
return isClass(typeMirror, processingEnv, java.lang.String.class);
|
||||
}
|
||||
|
||||
private final static boolean isClass(TypeMirror typeMirror, ProcessingEnvironment processingEnv,
|
||||
Class<?> compareTo) {
|
||||
private static boolean isClass(
|
||||
TypeMirror typeMirror, ProcessingEnvironment processingEnv, Class<?> compareTo) {
|
||||
Elements elements = processingEnv.getElementUtils();
|
||||
Types types = processingEnv.getTypeUtils();
|
||||
|
||||
if (elements.getTypeElement(compareTo.getCanonicalName()) == null) {
|
||||
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
|
||||
String.format("Cannot recognize %s\n", compareTo.getCanonicalName()));
|
||||
processingEnv
|
||||
.getMessager()
|
||||
.printMessage(
|
||||
Diagnostic.Kind.ERROR,
|
||||
String.format("Cannot recognize %s\n", compareTo.getCanonicalName()));
|
||||
}
|
||||
|
||||
return types.isSubtype(typeMirror,
|
||||
types.erasure(elements.getTypeElement(compareTo.getCanonicalName()).asType()));
|
||||
return types.isSubtype(
|
||||
typeMirror, types.erasure(elements.getTypeElement(compareTo.getCanonicalName()).asType()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user