Skip to content

Commit 5add9ea

Browse files
authored
allow enum values to have arbitrary casing in YAML (#2719)
1 parent 4c4c4c3 commit 5add9ea

6 files changed

Lines changed: 133 additions & 6 deletions

File tree

annot/src/main/java/com/predic8/membrane/annot/generator/kubernetes/model/SchemaObject.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package com.predic8.membrane.annot.generator.kubernetes.model;
1515

1616
import com.fasterxml.jackson.databind.node.*;
17+
import org.jetbrains.annotations.NotNull;
1718

1819
import java.util.*;
1920

@@ -148,11 +149,22 @@ private void addProperties(ObjectNode node) {
148149
private static ObjectNode createPropertyNode(AbstractSchema<?> property) {
149150
ObjectNode propertyNode = property.json(jnf.objectNode());
150151
if (property.getEnumValues() != null && !property.getEnumValues().isEmpty()) {
151-
propertyNode.set("enum", getEnumNode(property));
152+
propertyNode = createEnumNode(property, propertyNode);
152153
}
153154
return propertyNode;
154155
}
155156

157+
private static @NotNull ObjectNode createEnumNode(AbstractSchema<?> property, ObjectNode propertyNode) {
158+
ObjectNode unlimitedNode = propertyNode.deepCopy(); // a string (unrestricted)
159+
ObjectNode limitedNode = propertyNode; // a string restricted by 'enum'
160+
limitedNode.set("enum", getEnumNode(property));
161+
propertyNode = jnf.objectNode();
162+
// The 'anyOf' construction will suggest the pre-defined enum values (lowercase enum values) but allow other
163+
// spellings.
164+
propertyNode.set("anyOf", jnf.arrayNode().add(limitedNode).add(unlimitedNode));
165+
return propertyNode;
166+
}
167+
156168
private static ArrayNode getEnumNode(AbstractSchema<?> property) {
157169
var enumValues = jnf.arrayNode();
158170
property.getEnumValues().forEach(enumValues::add);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.predic8.membrane.annot;
2+
3+
import com.predic8.membrane.annot.beanregistry.BeanRegistry;
4+
import com.predic8.membrane.annot.util.CompilerHelper;
5+
import com.predic8.membrane.annot.util.CompilerResult;
6+
import org.junit.jupiter.api.Test;
7+
8+
import static com.predic8.membrane.annot.SpringConfigurationXSDGeneratingAnnotationProcessorTest.MC_MAIN_DEMO;
9+
import static com.predic8.membrane.annot.util.CompilerHelper.*;
10+
import static com.predic8.membrane.annot.util.StructureAssertionUtil.*;
11+
12+
public class SpringEnumParsingTest {
13+
14+
private static final String TRIVIAL_ENUM_EXAMPLE = """
15+
package com.predic8.membrane.demo;
16+
import com.predic8.membrane.annot.*;
17+
import java.util.List;
18+
@MCElement(name="root")
19+
public class DemoElement {
20+
MyEnum value;
21+
22+
public MyEnum getValue() { return value; }
23+
@MCAttribute
24+
public void setValue(MyEnum value) { this.value = value; }
25+
}
26+
---
27+
package com.predic8.membrane.demo;
28+
public enum MyEnum {
29+
VALUE1, VALUE2;
30+
}
31+
""";
32+
33+
@Test
34+
public void checkEnumParsing() {
35+
var sources = splitSources(MC_MAIN_DEMO + TRIVIAL_ENUM_EXAMPLE);
36+
var result = CompilerHelper.compile(sources, false);
37+
assertCompilerResult(true, result);
38+
39+
assertThatXMLValueWasTranslatedTo(result, "VALUE1", "VALUE1");
40+
assertThatXMLValueWasTranslatedTo(result, "value1", "VALUE1");
41+
}
42+
43+
private static void assertThatXMLValueWasTranslatedTo(CompilerResult result, String xmlValue, String expectedToStringValue) {
44+
BeanRegistry br = parseXML(result, SpringParsingTest.wrapSpring("""
45+
<root value="%s" />""".formatted(xmlValue)));
46+
47+
assertStructure(
48+
br,
49+
clazz("DemoElement",
50+
property("value", convertedToString(expectedToStringValue))));
51+
}
52+
53+
}

annot/src/test/java/com/predic8/membrane/annot/ParsingTest.java renamed to annot/src/test/java/com/predic8/membrane/annot/SpringParsingTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import com.predic8.membrane.annot.beanregistry.BeanRegistry;
1818
import com.predic8.membrane.annot.beanregistry.SpringContextAdapter;
1919
import com.predic8.membrane.annot.util.CompilerHelper;
20-
import org.junit.jupiter.api.Assertions;
2120
import org.junit.jupiter.api.Test;
2221
import org.springframework.context.ConfigurableApplicationContext;
2322

@@ -28,9 +27,9 @@
2827
import static com.predic8.membrane.annot.util.StructureAssertionUtil.*;
2928
import static com.predic8.membrane.annot.util.StructureAssertionUtil.clazz;
3029

31-
public class ParsingTest {
30+
public class SpringParsingTest {
3231

33-
private String wrapSpring(String content) {
32+
public static String wrapSpring(String content) {
3433
return """
3534
<spring:beans xmlns="http://membrane-soa.org/demo/1/"
3635
xmlns:spring="http://www.springframework.org/schema/beans"
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.predic8.membrane.annot;
2+
3+
import com.predic8.membrane.annot.beanregistry.BeanRegistry;
4+
import com.predic8.membrane.annot.util.CompilerHelper;
5+
import com.predic8.membrane.annot.util.CompilerResult;
6+
import org.junit.jupiter.api.Test;
7+
8+
import static com.predic8.membrane.annot.SpringConfigurationXSDGeneratingAnnotationProcessorTest.MC_MAIN_DEMO;
9+
import static com.predic8.membrane.annot.util.CompilerHelper.*;
10+
import static com.predic8.membrane.annot.util.StructureAssertionUtil.*;
11+
import static com.predic8.membrane.annot.util.StructureAssertionUtil.convertedToString;
12+
13+
public class YAMLEnumParsingTest {
14+
15+
private static final String TRIVIAL_ENUM_EXAMPLE = """
16+
package com.predic8.membrane.demo;
17+
import com.predic8.membrane.annot.*;
18+
import java.util.List;
19+
@MCElement(name="root", topLevel=true, component=false)
20+
public class DemoElement {
21+
MyEnum value;
22+
23+
public MyEnum getValue() { return value; }
24+
@MCAttribute
25+
public void setValue(MyEnum value) { this.value = value; }
26+
}
27+
---
28+
package com.predic8.membrane.demo;
29+
public enum MyEnum {
30+
VALUE1, VALUE2;
31+
}
32+
""";
33+
34+
@Test
35+
public void checkEnumParsing() {
36+
var sources = splitSources(MC_MAIN_DEMO + TRIVIAL_ENUM_EXAMPLE);
37+
var result = CompilerHelper.compile(sources, false);
38+
assertCompilerResult(true, result);
39+
40+
assertThatXMLValueWasTranslatedTo(result, "value1", "VALUE1");
41+
assertThatXMLValueWasTranslatedTo(result, "VALUE1", "VALUE1");
42+
}
43+
44+
private static void assertThatXMLValueWasTranslatedTo(CompilerResult result, String xmlValue, String expectedToStringValue) {
45+
BeanRegistry br = parseYAML(result, """
46+
root:
47+
value: %s""".formatted(xmlValue));
48+
49+
assertStructure(
50+
br,
51+
clazz("DemoElement",
52+
property("value", convertedToString(expectedToStringValue))));
53+
}
54+
55+
}

annot/src/test/java/com/predic8/membrane/annot/util/CompilerHelper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public class CompilerHelper {
4545
public static final String ANNOTATION_PROCESSOR_CLASSNAME = "com.predic8.membrane.annot.SpringConfigurationXSDGeneratingAnnotationProcessor";
4646
public static final String APPLICATION_CONTEXT_CLASSNAME = "org.springframework.context.support.ClassPathXmlApplicationContext";
4747
private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([^;]+)\\s*;");
48-
private static final Pattern CLASS_PATTERN = Pattern.compile("class\\s+([^\\s]+)\\s");
48+
private static final Pattern CLASS_PATTERN = Pattern.compile("(class|enum|interface)\\s+([^\\s]+)\\s");
4949

5050
/**
5151
* Compile the given source files.
@@ -199,7 +199,7 @@ private static String extractName(String source) {
199199
Matcher m = CLASS_PATTERN.matcher(source);
200200
if (!m.find())
201201
throw new RuntimeException("No class name found in source:\n" + source);
202-
return m.group(1);
202+
return m.group(2);
203203
}
204204

205205
private static String extractPackage(String source) {

annot/src/test/java/com/predic8/membrane/annot/util/StructureAssertionUtil.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ public static Asserter value(Object value) {
8383
return bean -> Assertions.assertEquals(value, bean);
8484
}
8585

86+
public static Asserter isNull() {
87+
return bean -> Assertions.assertNull(bean);
88+
}
89+
90+
public static Asserter convertedToString(String value) {
91+
return bean -> Assertions.assertEquals(value, bean.toString());
92+
}
93+
8694
public static Asserter list(Asserter... asserters) {
8795
return bean -> {
8896
assertInstanceOf(List.class, bean);

0 commit comments

Comments
 (0)