Skip to content

Commit

Permalink
feat(configuration): add ConvertWith and DefaultConverter annotations.
Browse files Browse the repository at this point in the history
Adds a default enum converter for hyphenated values to override implicit enum default converter.
Fixes quarkusio#2678
  • Loading branch information
machi1990 committed Jun 28, 2019
1 parent 430bd74 commit 42dda97
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.runtime.annotations;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import org.eclipse.microprofile.config.spi.Converter;

/**
* Defines a {@link Converter} to be used for conversion of a config property.
* This will override the default converter on the target config item.
*/
@Retention(RUNTIME)
@Target({ FIELD, PARAMETER })
@Documented
public @interface ConvertWith {
/**
* Specify the relative name of the configuration item.
*
* @return the name
*/
Class<? extends Converter<?>> value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.quarkus.runtime.annotations;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
* Indicates that a config item should be converted using a default converter: built-in/implicit converters or a custom
* converter.
*/
@Retention(RUNTIME)
@Target({ FIELD, PARAMETER })
@Documented
public @interface DefaultConverter {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package io.quarkus.runtime.configuration;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.microprofile.config.spi.Converter;

/**
* A converter for enums that are hyphenated
*/
final public class HyphenateEnumConverter implements Converter<Enum> {
private static final String HYPHEN = "-";
private static final Pattern PATTERN = Pattern.compile("([-_]+)");

private final Class<? extends Enum> enumType;

public HyphenateEnumConverter(Class<? extends Enum> enumType) {
this.enumType = enumType;
}

@Override
public Enum convert(String value) {
if (value == null || value.trim().isEmpty()) {
return null;
}

final Enum[] enums = enumType.getEnumConstants();

for (Enum enumValue : enums) {
final String name = enumValue.name();
final String hyphenated = hyphenate(name);
if (name.equals(value) || hyphenated.equals(value)) {
return enumValue;
}
}

try {
return Enum.valueOf(enumType, value);
} catch (Exception e) {
throw new IllegalArgumentException(String.format("Cannot convert %s to enum %s", value, enumType));
}
}

private String hyphenate(String value) {
StringBuffer target = new StringBuffer();
String hyphenate = io.quarkus.runtime.util.StringUtil.hyphenate(value);
Matcher matcher = PATTERN.matcher(hyphenate);
while (matcher.find()) {
matcher.appendReplacement(target, HYPHEN);
}
matcher.appendTail(target);
return target.toString();
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.deployment.util;
package io.quarkus.runtime.util;

import java.util.Iterator;
import java.util.Locale;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package io.quarkus.runtime.configuration;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class HyphenateEnumConverterTest {
enum MyEnum {
DISCARD,
READ_UNCOMMITTED,
SIGUSR1,
TrendBreaker,
MAKING_LifeDifficult,
YeOldeJBoss,
}

enum MyOtherEnum {
makingLifeDifficult,
READ__UNCOMMITTED
}

HyphenateEnumConverter hyphenateEnumConverter;

@Before
public void setUp() throws Exception {

}

@Test
public void convertMyEnum() {
hyphenateEnumConverter = new HyphenateEnumConverter(MyEnum.class);
MyEnum myEnum = (MyEnum) hyphenateEnumConverter.convert("DISCARD");
Assert.assertEquals(myEnum, MyEnum.DISCARD);
myEnum = (MyEnum) hyphenateEnumConverter.convert("discard");
Assert.assertEquals(myEnum, MyEnum.DISCARD);
myEnum = (MyEnum) hyphenateEnumConverter.convert("READ_UNCOMMITTED");
Assert.assertEquals(myEnum, MyEnum.READ_UNCOMMITTED);
myEnum = (MyEnum) hyphenateEnumConverter.convert("read-uncommitted");
Assert.assertEquals(myEnum, MyEnum.READ_UNCOMMITTED);
myEnum = (MyEnum) hyphenateEnumConverter.convert("SIGUSR1");
Assert.assertEquals(myEnum, MyEnum.SIGUSR1);
myEnum = (MyEnum) hyphenateEnumConverter.convert("sigusr1");
Assert.assertEquals(myEnum, MyEnum.SIGUSR1);
myEnum = (MyEnum) hyphenateEnumConverter.convert("TrendBreaker");
Assert.assertEquals(myEnum, MyEnum.TrendBreaker);
myEnum = (MyEnum) hyphenateEnumConverter.convert("trend-breaker");
Assert.assertEquals(myEnum, MyEnum.TrendBreaker);
myEnum = (MyEnum) hyphenateEnumConverter.convert("MAKING_LifeDifficult");
Assert.assertEquals(myEnum, MyEnum.MAKING_LifeDifficult);
myEnum = (MyEnum) hyphenateEnumConverter.convert("making-life-difficult");
Assert.assertEquals(myEnum, MyEnum.MAKING_LifeDifficult);
myEnum = (MyEnum) hyphenateEnumConverter.convert("YeOldeJBoss");
Assert.assertEquals(myEnum, MyEnum.YeOldeJBoss);
myEnum = (MyEnum) hyphenateEnumConverter.convert("ye-olde-jboss");
Assert.assertEquals(myEnum, MyEnum.YeOldeJBoss);
}

@Test
public void convertMyOtherEnum() {
hyphenateEnumConverter = new HyphenateEnumConverter(MyOtherEnum.class);
MyOtherEnum myOtherEnum = (MyOtherEnum) hyphenateEnumConverter.convert("makingLifeDifficult");
Assert.assertEquals(myOtherEnum, MyOtherEnum.makingLifeDifficult);
myOtherEnum = (MyOtherEnum) hyphenateEnumConverter.convert("making-life-difficult");
Assert.assertEquals(myOtherEnum, MyOtherEnum.makingLifeDifficult);
myOtherEnum = (MyOtherEnum) hyphenateEnumConverter.convert("READ__UNCOMMITTED");
Assert.assertEquals(myOtherEnum, MyOtherEnum.READ__UNCOMMITTED);
myOtherEnum = (MyOtherEnum) hyphenateEnumConverter.convert("read-uncommitted");
Assert.assertEquals(myOtherEnum, MyOtherEnum.READ__UNCOMMITTED);
}

@Test(expected = IllegalArgumentException.class)
public void testIllegalEnumConfigUtilConversion() {
hyphenateEnumConverter = new HyphenateEnumConverter(MyEnum.class);
hyphenateEnumConverter.convert("READ__UNCOMMITTED");
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package io.quarkus.deployment.util;
package io.quarkus.runtime.util;

import static io.quarkus.deployment.util.StringUtil.camelHumpsIterator;
import static io.quarkus.deployment.util.StringUtil.join;
import static io.quarkus.deployment.util.StringUtil.lowerCase;
import static io.quarkus.deployment.util.StringUtil.lowerCaseFirst;
import static io.quarkus.deployment.util.StringUtil.withoutSuffix;
import static io.quarkus.runtime.util.StringUtil.camelHumpsIterator;
import static io.quarkus.runtime.util.StringUtil.join;
import static io.quarkus.runtime.util.StringUtil.lowerCase;
import static io.quarkus.runtime.util.StringUtil.lowerCaseFirst;
import static io.quarkus.runtime.util.StringUtil.withoutSuffix;

import org.junit.Assert;
import org.junit.Test;
Expand Down

0 comments on commit 42dda97

Please sign in to comment.