diff --git a/README.md b/README.md index fd4ec3e6..c8b7b966 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ app.date=12.11.2005 - apply custom converter implementation 1. `@LocalDateParser`, `@LocalDateTimeParser`, `@ZonedDateTimeParser` - `@Target(METHOD)` - - apply a parameterised (formats) converter to the relevant java-time.* type + - apply a parameterised by formats converter to the relevant java.time.* type ### Property not found : `@Default` or `Optional` There are three ways for dealing with properties that are not found in sources: @@ -227,10 +227,13 @@ The return type of the interface methods must either: 1. Be - `java.net.URL` - `java.net.URI` + - `java.nio.file.Path` - `java.time.Instant` - `java.time.Duration` - `java.time.Period` - - `java.nio.file.Path` + - `java.time.LocalDate` + - `java.time.LocalDateTime` + - `java.time.ZonedDateTime` - `net.cactusthorn.config.core.converter.bytesize.ByteSize` 1. Be `List`, `Set` or `SortedSet`, where **T** satisfies 2, 3 or 4 above. The resulting collection is read-only. 1. Be `Map` or `SortedMap`, where @@ -354,8 +357,8 @@ This can be achieved with converter-annotation for the custom-converter: ```java @Retention(SOURCE) @Target(METHOD) -@ConverterClass(LocalDateConverter.class) //converter implementation -public @interface LocalDateParser { +@ConverterClass(MyClassConverter.class) //converter implementation +public @interface MySuperParser { String[] value() default ""; } @@ -369,14 +372,8 @@ usage: @Config public interface MyConfig { - @LocalDateParser({"dd.MM.yyyy", "yyyy-MM-dd"}) - LocalDate localDate(); - - @LocalDateParser //default format - LocalDate localDateA(); - - @ConverterClass(LocalDateConverter.class) //in fact it's same with @LocalDateParser without parameters - LocalDate localDateB(); + @MySuperParser({"param1", "param1"}) + MyClass localDate(); } ``` diff --git a/compiler/src/main/java/net/cactusthorn/config/compiler/methodvalidator/DefaultConvertorValidator.java b/compiler/src/main/java/net/cactusthorn/config/compiler/methodvalidator/DefaultConvertorValidator.java index 6ce12147..397761a7 100644 --- a/compiler/src/main/java/net/cactusthorn/config/compiler/methodvalidator/DefaultConvertorValidator.java +++ b/compiler/src/main/java/net/cactusthorn/config/compiler/methodvalidator/DefaultConvertorValidator.java @@ -25,12 +25,17 @@ import java.nio.file.Path; import java.time.Duration; import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.Period; +import java.time.ZonedDateTime; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.type.DeclaredType; @@ -39,15 +44,19 @@ import net.cactusthorn.config.compiler.ProcessorException; import net.cactusthorn.config.core.converter.Converter; +import net.cactusthorn.config.core.converter.ConverterClass; import net.cactusthorn.config.core.converter.bytesize.ByteSize; import net.cactusthorn.config.core.converter.standard.ByteSizeConverter; import net.cactusthorn.config.core.converter.standard.CharacterConverter; import net.cactusthorn.config.core.converter.standard.DurationConverter; import net.cactusthorn.config.core.converter.standard.InstantConverter; +import net.cactusthorn.config.core.converter.standard.LocalDateConverter; +import net.cactusthorn.config.core.converter.standard.LocalDateTimeConverter; import net.cactusthorn.config.core.converter.standard.PathConverter; import net.cactusthorn.config.core.converter.standard.PeriodConverter; import net.cactusthorn.config.core.converter.standard.URIConverter; import net.cactusthorn.config.core.converter.standard.URLConverter; +import net.cactusthorn.config.core.converter.standard.ZonedDateTimeConverter; public class DefaultConvertorValidator extends MethodValidatorAncestor { @@ -56,12 +65,15 @@ public class DefaultConvertorValidator extends MethodValidatorAncestor { CONVERTERS = new HashMap<>(); CONVERTERS.put(URL.class, URLConverter.class.getName()); CONVERTERS.put(URI.class, URIConverter.class.getName()); - CONVERTERS.put(Instant.class, InstantConverter.class.getName()); CONVERTERS.put(Path.class, PathConverter.class.getName()); - CONVERTERS.put(Duration.class, DurationConverter.class.getName()); - CONVERTERS.put(Period.class, PeriodConverter.class.getName()); CONVERTERS.put(ByteSize.class, ByteSizeConverter.class.getName()); CONVERTERS.put(Character.class, CharacterConverter.class.getName()); + CONVERTERS.put(Instant.class, InstantConverter.class.getName()); + CONVERTERS.put(Duration.class, DurationConverter.class.getName()); + CONVERTERS.put(Period.class, PeriodConverter.class.getName()); + CONVERTERS.put(LocalDate.class, LocalDateConverter.class.getName()); + CONVERTERS.put(LocalDateTime.class, LocalDateTimeConverter.class.getName()); + CONVERTERS.put(ZonedDateTime.class, ZonedDateTimeConverter.class.getName()); } private final Map classTypes = new HashMap<>(); @@ -79,6 +91,9 @@ public DefaultConvertorValidator(ProcessingEnvironment processingEnv) { } DeclaredType declaredType = (DeclaredType) typeMirror; Element element = declaredType.asElement(); + if (existConverterAnnotation(methodElement)) { + return next(methodElement, typeMirror); + } // @formatter:off Optional classType = classTypes.entrySet().stream() @@ -92,4 +107,19 @@ public DefaultConvertorValidator(ProcessingEnvironment processingEnv) { TypeMirror converter = processingEnv().getElementUtils().getTypeElement(CONVERTERS.get(classType.get())).asType(); return new MethodInfo(methodElement).withConverter(converter, Converter.EMPTY); } + + private boolean existConverterAnnotation(ExecutableElement methodElement) { + ConverterClass annotation = methodElement.getAnnotation(ConverterClass.class); + if (annotation != null) { + return true; + } + List annotationMirrors = methodElement.getAnnotationMirrors(); + for (AnnotationMirror annotationMirror : annotationMirrors) { + ConverterClass superAnnotation = annotationMirror.getAnnotationType().asElement().getAnnotation(ConverterClass.class); + if (superAnnotation != null) { + return true; + } + } + return false; + } } diff --git a/tests/src/test/java/net/cactusthorn/config/tests/converter/ConfigParamConverter.java b/tests/src/test/java/net/cactusthorn/config/tests/converter/ConfigParamConverter.java index cfc3686b..6db69718 100644 --- a/tests/src/test/java/net/cactusthorn/config/tests/converter/ConfigParamConverter.java +++ b/tests/src/test/java/net/cactusthorn/config/tests/converter/ConfigParamConverter.java @@ -36,4 +36,6 @@ @LocalDateTimeParser({"dd.MM.yyyy' 'HH:mm:ss"}) Optional localDateTime(); @ZonedDateTimeParser({"dd.MM.yyyy' 'HH:mm:sszzz"}) Optional zonedDateTime(); + + Optional localDateDefault(); } diff --git a/tests/src/test/java/net/cactusthorn/config/tests/converter/ConfigParamConverterTest.java b/tests/src/test/java/net/cactusthorn/config/tests/converter/ConfigParamConverterTest.java index 33898667..76ff0867 100644 --- a/tests/src/test/java/net/cactusthorn/config/tests/converter/ConfigParamConverterTest.java +++ b/tests/src/test/java/net/cactusthorn/config/tests/converter/ConfigParamConverterTest.java @@ -54,4 +54,12 @@ public class ConfigParamConverterTest { ConfigParamConverter config = ConfigFactory.builder().setSource(properties).build().create(ConfigParamConverter.class); assertTrue(config.zonedDateTime().isPresent()); } + + @Test public void localDateDefault() { + Map properties = new HashMap<>(); + properties.put("localDate", "12.11.2011"); + properties.put("localDateDefault", "2011-11-12"); + ConfigParamConverter config = ConfigFactory.builder().setSource(properties).build().create(ConfigParamConverter.class); + assertEquals(LocalDate.of(2011, 11, 12), config.localDateDefault().get()); + } }