Compare commits

..

2 Commits

Author SHA1 Message Date
00asdf cce991e5f5 added static initialize methods 2023-06-18 02:12:25 +02:00
00asdf 4ab6b7072a added ConfigProcessor 2023-04-09 22:56:11 +02:00
21 changed files with 521 additions and 30 deletions

4
.gitignore vendored
View File

@ -26,4 +26,6 @@ bin/
.vscode/ .vscode/
### Mac OS ### ### Mac OS ###
.DS_Store .DS_Store
.idea/workspace.xml

12
.idea/compiler.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default">
<processorPath useProcessorModulePath="true">
<entry name="$PROJECT_DIR$/src/dev/asdf00/confindibus/processor/ConfigProcessor.java" />
</processorPath>
</profile>
</annotationProcessing>
</component>
</project>

View File

@ -2,7 +2,7 @@
<project version="4"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/Confidibus.iml" filepath="$PROJECT_DIR$/Confidibus.iml" /> <module fileurl="file://$PROJECT_DIR$/Confindibus.iml" filepath="$PROJECT_DIR$/Confindibus.iml" />
</modules> </modules>
</component> </component>
</project> </project>

View File

@ -1,14 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ArtifactsWorkspaceSettings">
<artifacts-to-build>
<artifact name="Confindibus:jar" />
</artifacts-to-build>
</component>
<component name="AutoImportSettings"> <component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" /> <option name="autoReloadType" value="SELECTIVE" />
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="d8897652-66f5-4f30-9dbf-a6b280944ebf" name="Changes" comment=""> <list default="true" id="d8897652-66f5-4f30-9dbf-a6b280944ebf" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/.idea/libraries/google_auto_service.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/resources/META-INF/services/javax.annotation.processing.Processor" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/dev/asdf00/confindibus/processor/ConfigProcessor.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/ProcessorTest.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/testclasses/BrokenConfig.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/testclasses/BrokenSection1.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/testclasses/BrokenSection2.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/testclasses/BrokenValue1.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/testclasses/BrokenValue2.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/testclasses/BrokenValue3.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/testclasses/BrokenValue4.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/test/dev/asdf00/confindibus/testclasses/SimpleTestConfig.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/modules.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/dev/asdf00/confidibus/Confidibus.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/dev/asdf00/confidibus/Configurator.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/Confindibus.iml" beforeDir="false" afterPath="$PROJECT_DIR$/Confindibus.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/dev/asdf00/confidibus/annotations/Config.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/dev/asdf00/confidibus/annotations/Configuration.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/dev/asdf00/confindibus/ConfigurationException.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/dev/asdf00/confindibus/ConfigurationException.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/dev/asdf00/confidibus/annotations/Value.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/dev/asdf00/confidibus/annotations/Value.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/dev/asdf00/confindibus/Configurator.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/dev/asdf00/confindibus/Configurator.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/dev/asdf00/confindibus/annotations/Configuration.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/dev/asdf00/confindibus/annotations/Configuration.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/dev/asdf00/confindibus/annotations/Section.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/dev/asdf00/confindibus/annotations/Section.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/dev/asdf00/confindibus/annotations/Value.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/dev/asdf00/confindibus/annotations/Value.java" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -19,6 +41,7 @@
<option name="RECENT_TEMPLATES"> <option name="RECENT_TEMPLATES">
<list> <list>
<option value="AnnotationType" /> <option value="AnnotationType" />
<option value="module-info" />
<option value="Class" /> <option value="Class" />
</list> </list>
</option> </option>
@ -32,30 +55,124 @@
<option name="hideEmptyMiddlePackages" value="true" /> <option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" /> <option name="showLibraryContents" value="true" />
</component> </component>
<component name="PropertiesComponent">{ <component name="PropertiesComponent"><![CDATA[{
&quot;keyToString&quot;: { "keyToString": {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;, "Downloaded.Files.Path.Enabled": "false",
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;, "Repository.Attach.Annotations": "false",
&quot;last_opened_file_path&quot;: &quot;C:/Users/chris/Documents/HomeAuto/Confindibus&quot;, "Repository.Attach.JavaDocs": "false",
&quot;project.structure.last.edited&quot;: &quot;Artifacts&quot;, "Repository.Attach.Sources": "false",
&quot;project.structure.proportion&quot;: &quot;0.0&quot;, "RunOnceActivity.OpenProjectViewOnStart": "true",
&quot;project.structure.side.proportion&quot;: &quot;0.2&quot; "RunOnceActivity.ShowReadmeOnStart": "true",
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
"last_opened_file_path": "C:/Users/Christoph/Documents/HomeAutomation/Confindibus/resources/META-INF/services",
"project.structure.last.edited": "Modules",
"project.structure.proportion": "0.15",
"project.structure.side.proportion": "0.2",
"settings.editor.selected.configurable": "reference.projectsettings.compiler.annotationProcessors"
} }
}</component> }]]></component>
<component name="RecentsManager"> <component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\Christoph\Documents\HomeAutomation\Confindibus\resources\META-INF\services" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="C:\Users\Christoph\Documents\HomeAutomation\Confindibus" />
</key>
<key name="MoveClassesOrPackagesDialog.RECENTS_KEY"> <key name="MoveClassesOrPackagesDialog.RECENTS_KEY">
<recent name="dev.asdf00.confidibus.config" /> <recent name="dev.asdf00.confidibus.config" />
<recent name="dev.asdf00.confidibus" /> <recent name="dev.asdf00.confidibus" />
</key> </key>
</component> </component>
<component name="RunManager"> <component name="RunManager" selected="JUnit.Test">
<configuration name="MainTest" type="Application" factoryName="Application"> <configuration name="ProcessorTest.testBrokenSection" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="dev.asdf00.confidibus.Main" /> <module name="Confindibus" />
<module name="Confidibus" /> <extension name="coverage">
<pattern>
<option name="PATTERN" value="dev.asdf00.confindibus.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="dev.asdf00.confindibus" />
<option name="MAIN_CLASS_NAME" value="dev.asdf00.confindibus.ProcessorTest" />
<option name="METHOD_NAME" value="testBrokenSection" />
<option name="TEST_OBJECT" value="method" />
<method v="2"> <method v="2">
<option name="Make" enabled="true" /> <option name="Make" enabled="true" />
</method> </method>
</configuration> </configuration>
<configuration name="ProcessorTest.testBrokenValue2" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<module name="Confindibus" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="dev.asdf00.confindibus.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="dev.asdf00.confindibus" />
<option name="MAIN_CLASS_NAME" value="dev.asdf00.confindibus.ProcessorTest" />
<option name="METHOD_NAME" value="testBrokenValue2" />
<option name="TEST_OBJECT" value="method" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="ProcessorTest.testProcSimpleConfig" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<module name="Confindibus" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="dev.asdf00.confindibus.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="dev.asdf00.confindibus" />
<option name="MAIN_CLASS_NAME" value="dev.asdf00.confindibus.ProcessorTest" />
<option name="METHOD_NAME" value="testProcSimpleConfig" />
<option name="TEST_OBJECT" value="method" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="ProcessorTest.testSimpleConfig" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<module name="Confindibus" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="dev.asdf00.confindibus.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="dev.asdf00.confindibus" />
<option name="MAIN_CLASS_NAME" value="dev.asdf00.confindibus.ProcessorTest" />
<option name="METHOD_NAME" value="testSimpleConfig" />
<option name="TEST_OBJECT" value="method" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="Test" type="JUnit" factoryName="JUnit">
<module name="Confindibus" />
<option name="PACKAGE_NAME" value="dev.asdf00.confindibus" />
<option name="MAIN_CLASS_NAME" value="dev.asdf00.confindibus.ProcessorTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<list>
<item itemvalue="JUnit.Test" />
<item itemvalue="JUnit.ProcessorTest.testBrokenSection" />
<item itemvalue="JUnit.ProcessorTest.testBrokenValue2" />
<item itemvalue="JUnit.ProcessorTest.testSimpleConfig" />
<item itemvalue="JUnit.ProcessorTest.testProcSimpleConfig" />
</list>
<recent_temporary>
<list>
<item itemvalue="JUnit.ProcessorTest.testSimpleConfig" />
<item itemvalue="JUnit.ProcessorTest.testBrokenSection" />
<item itemvalue="JUnit.ProcessorTest.testBrokenValue2" />
<item itemvalue="JUnit.ProcessorTest.testProcSimpleConfig" />
</list>
</recent_temporary>
</component> </component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" /> <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager"> <component name="TaskManager">

View File

@ -3,9 +3,21 @@
<component name="NewModuleRootManager" inherit-compiler-output="true"> <component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library" scope="TEST">
<library name="JUnit4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.13.1/junit-4.13.1.jar!/" />
<root url="jar://$MAVEN_REPOSITORY$/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component> </component>
</module> </module>

View File

@ -0,0 +1 @@
dev.asdf00.confindibus.processor.ConfigProcessor

View File

@ -1,4 +1,4 @@
package dev.asdf00.confidibus; package dev.asdf00.confindibus;
public class ConfigurationException extends RuntimeException { public class ConfigurationException extends RuntimeException {
public ConfigurationException(String format, Object... params) { public ConfigurationException(String format, Object... params) {

View File

@ -1,11 +1,13 @@
package dev.asdf00.confidibus; package dev.asdf00.confindibus;
import dev.asdf00.confidibus.annotations.Configuration; import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confidibus.annotations.Section; import dev.asdf00.confindibus.annotations.Section;
import dev.asdf00.confidibus.annotations.Value; import dev.asdf00.confindibus.annotations.Value;
import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.nio.file.Files; import java.nio.file.Files;
@ -40,8 +42,7 @@ import java.util.Iterator;
* @Value(comment = "enables debug mode", standard = "false") * @Value(comment = "enables debug mode", standard = "false")
* public static boolean DEBUG; * public static boolean DEBUG;
* } * }
* } * }}</pre>
* </pre>
*/ */
public class Configurator { public class Configurator {
private final Class<?> _class; private final Class<?> _class;
@ -55,12 +56,56 @@ public class Configurator {
_debug = debugMsgStream; _debug = debugMsgStream;
} }
/**
* Provides easy access for initializing a config class.
*
* @param configClass class containing the annotations for a config
* @param createIfMissing permission to create new config file if none is found
*/
public static void initialize(Class<?> configClass, boolean createIfMissing) {
Configurator.of(configClass, null).init(createIfMissing);
}
/**
* Provides easy access for initializing a config class. If no or a faulty config is found,
* the user is queried if they want to (re)initialize the config file.
*
* @param configClass class containing the annotations for a config
* @param out the PrintWriter the user query is written to
* @param in the BufferedReader where the user response is expected
* @return true if a valid config file was found
*/
public static boolean initialize(Class<?> configClass, PrintWriter out, BufferedReader in) {
var conf = Configurator.of(configClass, null);
try {
initialize(configClass, false);
return true;
} catch (ConfigurationException e) {
try {
out.print("Configuration file is missing or faulty. Reset config and exit? [yN] ");
var input = in.readLine().toLowerCase();
if ("y".equals(input)) {
var confAnnot = configClass.getAnnotation(Configuration.class);
var cPath = Path.of(".").resolve(confAnnot.path());
if (Files.exists(cPath)) {
Files.delete(cPath);
}
initialize(configClass, true);
out.println("Config has been reset successfully!");
}
} catch (IOException ex) {
throw new ConfigurationException(ex, "Initialization of config failed!");
}
return false;
}
}
/** /**
* Creates helper instance. * Creates helper instance.
* @param configClass class containing the annotations for a config *
* @param configClass class containing the annotations for a config
* @param debugMsgStream {@link PrintStream} where debug output shall be written to. * @param debugMsgStream {@link PrintStream} where debug output shall be written to.
* Can be {@code null} if no debug output should be written * Can be {@code null} if no debug output should be written
*/ */
public static Configurator of(Class<?> configClass, PrintStream debugMsgStream) { public static Configurator of(Class<?> configClass, PrintStream debugMsgStream) {
return new Configurator(configClass, debugMsgStream); return new Configurator(configClass, debugMsgStream);
@ -68,6 +113,7 @@ public class Configurator {
/** /**
* Initialize values in {@code configClass}. * Initialize values in {@code configClass}.
*
* @param createIfMissing permission to create new config file if none is found * @param createIfMissing permission to create new config file if none is found
*/ */
public void init(boolean createIfMissing) { public void init(boolean createIfMissing) {

View File

@ -1,4 +1,4 @@
package dev.asdf00.confidibus.annotations; package dev.asdf00.confindibus.annotations;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package dev.asdf00.confidibus.annotations; package dev.asdf00.confindibus.annotations;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -1,4 +1,4 @@
package dev.asdf00.confidibus.annotations; package dev.asdf00.confindibus.annotations;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;

View File

@ -0,0 +1,122 @@
package dev.asdf00.confindibus.processor;
import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confindibus.annotations.Section;
import dev.asdf00.confindibus.annotations.Value;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import java.util.Set;
@SupportedAnnotationTypes("dev.asdf00.confindibus.annotations.*")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
public class ConfigProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
boolean processedAllAns = true;
for (TypeElement anno : annotations) {
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(anno);
for (Element elem : annotatedElements) {
if (anno.getQualifiedName().contentEquals("dev.asdf00.confindibus.annotations.Configuration")) {
configuration(elem);
} else if (anno.getQualifiedName().contentEquals("dev.asdf00.confindibus.annotations.Section")) {
section(elem);
} else if (anno.getQualifiedName().contentEquals("dev.asdf00.confindibus.annotations.Value")) {
value(elem);
} else {
processedAllAns = false;
}
}
}
return processedAllAns;
}
private void configuration(Element config) {
if (config.getAnnotation(Section.class) == null) {
printError("Classes annotated with @Configuration also need to be annotated with @Section!", config);
}
}
private void section(Element section) {
Element inner = section;
Element outer = inner.getEnclosingElement();
while (outer.getClass().getName().equals("com.sun.tools.javac.code.Symbol$ClassSymbol")) {
if (outer.getAnnotation(Section.class) == null) {
printError("Subsection '%s' needs to be part of an outer @Section!".formatted(inner.getSimpleName()), section);
}
Set<Modifier> clsMods = inner.getModifiers();
if (!clsMods.contains(Modifier.PUBLIC) || !clsMods.contains(Modifier.STATIC)) {
printError("Classes that represent subsections need to be 'public static'!", section);
}
inner = outer;
outer = inner.getEnclosingElement();
}
if (inner.getAnnotation(Configuration.class) == null) {
printError("Class '%s' annotated with @Section found outside of valid configuration!".formatted(section.getSimpleName()), section);
}
Section sect = section.getAnnotation(Section.class);
if (sect.title().indexOf('{') != -1 || sect.title().indexOf('\n') != -1) {
printError("The title of a section must not contain '{' or '\\n'! (title = '%s')".formatted(sect.title()), section);
}
}
private void value(Element value) {
Set<Modifier> modifiers = value.getModifiers();
if (!modifiers.contains(Modifier.PUBLIC) || !modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.FINAL)) {
printError("Field '%s' annotated with @Value needs to be exactly 'public static'!".formatted(value.getSimpleName()), value);
}
if (value.getEnclosingElement().getAnnotation(Section.class) == null) {
printError("Field '%s' annotated with @Value needs to be inside a class annotated with @Section!".formatted(value.getSimpleName()), value);
}
checkParsableAsType(value, value.getAnnotation(Value.class).standard());
Value val = value.getAnnotation(Value.class);
if (val.name().indexOf(':') != -1 || val.name().indexOf('\n') != -1) {
printError("The name of a field must not contain ':' or '\\n'! (name = '%s')".formatted(val.name()), value);
}
}
// =================================================================================================================
static volatile Object temp;
private void checkParsableAsType(Element elem, String value) {
TypeMirror type = elem.asType();
try {
String tst = type.toString();
if (tst.equals("byte")) {
temp = Byte.parseByte(value);
} else if (tst.equals("short")) {
temp = Short.parseShort(value);
} else if (tst.equals("int")) {
temp = Integer.parseInt(value);
} else if (tst.equals("long")) {
temp = Long.parseLong(value);
} else if (tst.equals("float")) {
temp = Float.parseFloat(value);
} else if (tst.equals("double")) {
temp = Double.parseDouble(value);
} else if (tst.equals("boolean")) {
temp = Boolean.parseBoolean(value);
} else if (tst.equals("char")) {
temp = value.charAt(0);
} else if (tst.equals("java.lang.String")) {
temp = value;
} else {
printError("'%s' is not a valid type for a field annotated with @Value!".formatted(type), elem);
}
} catch (NumberFormatException | IndexOutOfBoundsException e) {
printError("Standard value of '%s' is not parsable as %s!".formatted(value, type), elem);
}
}
private void printError(CharSequence msg, Element elem) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, elem);
}
}

View File

@ -0,0 +1,67 @@
package dev.asdf00.confindibus;
import dev.asdf00.confindibus.testclasses.*;
import org.junit.Assert;
import org.junit.Test;
import static com.sun.tools.javac.Main.compile;
public class ProcessorTest {
@Test
public void testSimpleConfig() {
Assert.assertEquals(0, compileWithProc(SimpleTestConfig.class));
}
@Test
public void testBrokenConfig() {
Assert.assertEquals(1, compileWithProc(BrokenConfig.class));
}
@Test
public void testBrokenSection1() {
Assert.assertEquals(1, compileWithProc(BrokenSection1.class));
}
@Test
public void testBrokenSection2() {
Assert.assertEquals(1, compileWithProc(BrokenSection2.class));
}
@Test
public void testBrokenValue1() {
Assert.assertEquals(1, compileWithProc(BrokenValue1.class));
}
@Test
public void testBrokenValue2() {
Assert.assertEquals(1, compileWithProc(BrokenValue2.class));
}
@Test
public void testBrokenValue3() {
Assert.assertEquals(1, compileWithProc(BrokenValue3.class));
}
@Test
public void testBrokenValue4() {
Assert.assertEquals(1, compileWithProc(BrokenValue4.class));
}
// =================================================================================================================
private int compileWithProc(Class<?>... classes) {
int fixedArgCnt = 3;
String[] args = new String[classes.length + fixedArgCnt];
args[0] = "-proc:only";
args[1] = "-processor";
args[2] = "dev.asdf00.confindibus.processor.ConfigProcessor";
for (int i = fixedArgCnt; i < args.length; i++) {
args[i] = testClass(classes[i - fixedArgCnt]);
}
return compile(args);
}
private String testClass(Class cls) {
return "test/" + cls.getName().replace('.', '/') + ".java";
}
}

View File

@ -0,0 +1,10 @@
package dev.asdf00.confindibus.testclasses;
import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confindibus.annotations.Value;
@Configuration(path = "test")
public class BrokenConfig {
@Value(standard = "value")
public static String VALUE;
}

View File

@ -0,0 +1,10 @@
package dev.asdf00.confindibus.testclasses;
import dev.asdf00.confindibus.annotations.Section;
import dev.asdf00.confindibus.annotations.Value;
@Section(title = "test")
public class BrokenSection1 {
@Value(standard = "value")
public static String VALUE;
}

View File

@ -0,0 +1,11 @@
package dev.asdf00.confindibus.testclasses;
import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confindibus.annotations.Section;
@Configuration(path = "test")
@Section(title = "sect")
public class BrokenSection2 {
@Section(title = "broken subsect")
public class Subsect { }
}

View File

@ -0,0 +1,12 @@
package dev.asdf00.confindibus.testclasses;
import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confindibus.annotations.Section;
import dev.asdf00.confindibus.annotations.Value;
@Configuration(path = "test")
@Section(title = "sect")
public class BrokenValue1 {
@Value(standard = "test")
public String TEST;
}

View File

@ -0,0 +1,14 @@
package dev.asdf00.confindibus.testclasses;
import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confindibus.annotations.Section;
import dev.asdf00.confindibus.annotations.Value;
@Configuration(path = "test")
@Section(title = "sect outer")
public class BrokenValue2 {
public static class InnerSection {
@Value(standard = "value")
public static String VALUE;
}
}

View File

@ -0,0 +1,12 @@
package dev.asdf00.confindibus.testclasses;
import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confindibus.annotations.Section;
import dev.asdf00.confindibus.annotations.Value;
@Configuration(path = "test")
@Section(title = "sect")
public class BrokenValue3 {
@Value(standard = "")
public static Object VALUE;
}

View File

@ -0,0 +1,12 @@
package dev.asdf00.confindibus.testclasses;
import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confindibus.annotations.Section;
import dev.asdf00.confindibus.annotations.Value;
@Configuration(path = "test")
@Section(title = "sect")
public class BrokenValue4 {
@Value(standard = "256")
public static byte VALUE;
}

View File

@ -0,0 +1,31 @@
package dev.asdf00.confindibus.testclasses;
import dev.asdf00.confindibus.annotations.Configuration;
import dev.asdf00.confindibus.annotations.Section;
import dev.asdf00.confindibus.annotations.Value;
@Configuration(path = "test")
@Section(title = "sect")
public class SimpleTestConfig {
@Value(standard = "1")
public static byte BYTE;
@Value(standard = "1")
public static short SHORT;
@Value(standard = "1")
public static int INT;
@Value(standard = "1")
public static long LONG;
@Value(standard = "1.0")
public static float FLOAT;
@Value(standard = "1.0")
public static double DOUBLE;
@Value(standard = "true")
public static boolean BOOLEAN;
@Value(standard = "c")
public static char CHAR;
@Value(standard = "string")
public static String STRING;
@Section(title = "test inner section")
public static class SubSection { }
}