Fix yang resource parse failure if filename matches IETF recommended format 41/117741/5
authorRuslan Kashapov <ruslan.kashapov@pantheon.tech>
Thu, 11 Feb 2021 11:36:30 +0000 (13:36 +0200)
committerRuslan Kashapov <ruslan.kashapov@pantheon.tech>
Tue, 16 Feb 2021 08:33:20 +0000 (10:33 +0200)
Issue-ID: CPS-237
Change-Id: I9a8f95552b9814f02886d1b5074aa6e7a09f582d
Signed-off-by: Ruslan Kashapov <ruslan.kashapov@pantheon.tech>
cps-service/src/main/java/org/onap/cps/yang/YangTextSchemaSourceSetBuilder.java
cps-service/src/test/groovy/org/onap/cps/utils/YangTextSchemaSourceSetSpec.groovy

index b1462cd..712d9a0 100644 (file)
@@ -30,13 +30,14 @@ import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import lombok.NoArgsConstructor;
 import org.onap.cps.spi.exceptions.CpsException;
 import org.onap.cps.spi.exceptions.ModelValidationException;
 import org.onap.cps.spi.model.ModuleReference;
 import org.opendaylight.yangtools.yang.common.Revision;
-import org.opendaylight.yangtools.yang.common.YangNames;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
@@ -50,6 +51,9 @@ import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementR
 @NoArgsConstructor
 public final class YangTextSchemaSourceSetBuilder {
 
+    private static final Pattern RFC6020_RECOMMENDED_FILENAME_PATTERN =
+        Pattern.compile("([\\w-]+)@(\\d{4}-\\d{2}-\\d{2})(?:\\.yang)?", Pattern.CASE_INSENSITIVE);
+
     private final ImmutableMap.Builder<String, String> yangModelMap = new ImmutableMap.Builder<>();
 
     public YangTextSchemaSourceSetBuilder putAll(final Map<String, String> yangResourceNameToContent) {
@@ -143,11 +147,9 @@ public final class YangTextSchemaSourceSetBuilder {
             .collect(Collectors.toList());
     }
 
-    private static YangTextSchemaSource toYangTextSchemaSource(final String sourceName,
-            final String source) {
-        final Map.Entry<String, String> sourceNameParsed = checkNotNull(YangNames.parseFilename(sourceName));
-        final RevisionSourceIdentifier revisionSourceIdentifier = RevisionSourceIdentifier
-            .create(sourceNameParsed.getKey(), Revision.ofNullable(sourceNameParsed.getValue()));
+    private static YangTextSchemaSource toYangTextSchemaSource(final String sourceName, final String source) {
+        final RevisionSourceIdentifier revisionSourceIdentifier =
+            createIdentifierFromSourceName(checkNotNull(sourceName));
 
         return new YangTextSchemaSource(revisionSourceIdentifier) {
             @Override
@@ -162,4 +164,12 @@ public final class YangTextSchemaSourceSetBuilder {
             }
         };
     }
+
+    private static RevisionSourceIdentifier createIdentifierFromSourceName(final String sourceName) {
+        final Matcher matcher = RFC6020_RECOMMENDED_FILENAME_PATTERN.matcher(sourceName);
+        if (matcher.matches()) {
+            return RevisionSourceIdentifier.create(matcher.group(1), Revision.of(matcher.group(2)));
+        }
+        return RevisionSourceIdentifier.create(sourceName);
+    }
 }
index 9a19def..f7efd5d 100644 (file)
@@ -23,25 +23,29 @@ import org.onap.cps.TestUtils
 import org.onap.cps.spi.exceptions.ModelValidationException
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import org.opendaylight.yangtools.yang.common.Revision
-import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException
 import spock.lang.Specification
 import spock.lang.Unroll
 
 class YangTextSchemaSourceSetSpec extends Specification {
 
-    def 'Generating a valid YangTextSchemaSource Set '() {
+    @Unroll
+    def 'Building a valid YangTextSchemaSourceSet using #filenameCase filename.'() {
         given: 'a yang model (file)'
-            def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('bookstore.yang')
+            def yangResourceNameToContent = [filename: TestUtils.getResourceFileContent('bookstore.yang')]
         when: 'the content is parsed'
             def result = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext();
         then: 'the result contains 1 module of the correct name and revision'
             result.modules.size() == 1
             def optionalModule = result.findModule('stores', Revision.of('2020-09-15'))
             optionalModule.isPresent()
+        where:
+            filenameCase           | filename
+            'generic'              | 'bookstore'
+            'RFC-6020 recommended' | 'bookstore-test@2020-09-15.YANG'
     }
 
     @Unroll
-    def 'Generating invalid YangTextSchemaSource Set (#description).'() {
+    def 'Building YangTextSchemaSourceSet error case: #description.'() {
         given: 'a file with #description'
             def yangResourceNameToContent = TestUtils.getYangResourcesAsMap(filename)
         when: 'the content is parsed'