Fix union losing patterns 05/96505/2
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 9 Jun 2021 20:34:46 +0000 (22:34 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 9 Jun 2021 22:16:21 +0000 (00:16 +0200)
Union typedefs need to generate type enforcement patterns for their
constituent types. Make sure that happens.

Change-Id: Id4512f17e1ca6b2f9a5157d3b44dd3d03d5dfcec
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/reactor/AbstractTypeObjectGenerator.java
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/test/CompilationTest.java
binding/mdsal-binding-java-api-generator/src/test/resources/compilation/union-string-pattern/foo.yang [new file with mode: 0644]

index b8a14451f36c3e6a0f00c7f21e21f342759f082d..c05debf7322810bab9101ca198a73518f8cf00ac 100644 (file)
@@ -631,7 +631,9 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
 
         annotateDeprecatedIfNecessary(typedef, builder);
 
-        if (javaType instanceof ConcreteType && "String".equals(javaType.getName()) && typedef.getBaseType() != null) {
+        if (javaType instanceof ConcreteType
+            // FIXME: This looks very suspicious: we should by checking for Types.STRING
+            && "String".equals(javaType.getName()) && typedef.getBaseType() != null) {
             addStringRegExAsConstant(builder, resolveRegExpressions(typedef));
         }
         addUnits(builder, typedef);
@@ -703,7 +705,7 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
                 } else {
                     Type baseType = SIMPLE_TYPES.get(subName);
                     if (baseType == null) {
-                        // This has to be a reference to a typedef, let's lookup it up and pick the its type
+                        // This has to be a reference to a typedef, let's lookup it up and pick up its type
                         final AbstractTypeObjectGenerator<?> baseGen = verifyNotNull(
                             dependencies.baseTypes.get(subName), "Cannot resolve base type %s in %s", subName,
                             definingStatement);
@@ -730,6 +732,8 @@ abstract class AbstractTypeObjectGenerator<T extends EffectiveStatement<?, ?>> e
                         }
                     }
 
+                    expressions.putAll(resolveRegExpressions(subType.getTypeDefinition()));
+
                     generatedType = restrictType(baseType,
                         BindingGeneratorUtil.getRestrictions(type.getTypeDefinition()), builderFactory);
                 }
index 9b7bdaeee36fec1158f5d7df0b0e6a8450c55c0b..b1c9e3d628b7c4c9441f68f814704cfe921fcff9 100644 (file)
@@ -35,6 +35,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.junit.Test;
+import org.opendaylight.mdsal.binding.model.util.TypeConstants;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
 import org.opendaylight.yangtools.yang.common.Empty;
@@ -734,6 +735,22 @@ public class CompilationTest extends BaseCompilationTest {
         CompilationTestUtils.cleanUp(sourcesOutputDir, compiledOutputDir);
     }
 
+    @Test
+    public void testUnionStringPatterns() throws Exception {
+        final File sourcesOutputDir = CompilationTestUtils.generatorOutput("union-string-pattern");
+        final File compiledOutputDir = CompilationTestUtils.compilerOutput("union-string-pattern");
+        generateTestSources("/compilation/union-string-pattern", sourcesOutputDir);
+        CompilationTestUtils.testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        final ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        final Class<?> fooClass = Class.forName(CompilationTestUtils.BASE_PKG + ".foo.norev.Foo", true, loader);
+
+        final Field patterns = fooClass.getDeclaredField(TypeConstants.PATTERN_CONSTANT_NAME);
+        assertEquals(List.class, patterns.getType());
+
+        CompilationTestUtils.cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
     private static void testReturnTypeIdentityref(final Class<?> clazz, final String methodName,
             final String returnTypeStr) throws NoSuchMethodException {
         Method method = clazz.getMethod(methodName);
diff --git a/binding/mdsal-binding-java-api-generator/src/test/resources/compilation/union-string-pattern/foo.yang b/binding/mdsal-binding-java-api-generator/src/test/resources/compilation/union-string-pattern/foo.yang
new file mode 100644 (file)
index 0000000..8555c52
--- /dev/null
@@ -0,0 +1,19 @@
+module foo {
+  namespace foo;
+  prefix foo;
+
+  description
+    "When we have overlapping types for a union we need to be mindful of squashed patterns. In this case the TypeObject
+     generated for union needs to contain constants for each pattern.";
+
+  typedef foo {
+    type union {
+      type string {
+        pattern a.+;
+      }
+      type string {
+        pattern b.+;
+      }
+    }
+  }
+}