BUG-8123: be better at guessing identifiers 67/54867/3
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 12 Apr 2017 13:54:23 +0000 (15:54 +0200)
committerRobert Varga <nite@hq.sk>
Wed, 12 Apr 2017 22:41:31 +0000 (22:41 +0000)
Given an URI we need to attempt to interpret it to improve our
guess of the module name and revision.

Change-Id: I4d74b06fb9f949c538911d215b6d90a383560f1f
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/repo/api/RevisionSourceIdentifier.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java

index 5ec07d04ef64b32874522bbb1f3151469272405f..0f47513fae59cabca2d4eeac176e5f9c4ebaca50 100644 (file)
@@ -7,10 +7,16 @@
  */
 package org.opendaylight.yangtools.yang.model.repo.api;
 
+import static org.opendaylight.yangtools.yang.common.YangConstants.RFC6020_YANG_FILE_EXTENSION;
+
 import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import java.text.ParseException;
+import java.util.AbstractMap.SimpleImmutableEntry;
+import java.util.Map.Entry;
 import java.util.Objects;
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
 
 /**
  * YANG Schema revision source identifier
@@ -113,6 +119,46 @@ public final class RevisionSourceIdentifier extends SourceIdentifier {
         return new RevisionSourceIdentifier(moduleName);
     }
 
+    /**
+     * Creates a new RevisionSourceIdentifier based on the provided file name.
+     *
+     * @param fileName file name
+     * @throws IllegalArgumentException when fileName does not have correct format
+     * @throws NullPointerException when fileName is null
+     * @throws ParseException if the revision part has invalid format
+     */
+    public static RevisionSourceIdentifier fromFileName(final String fileName) throws ParseException {
+        final Entry<String, String> split = splitFileName(fileName);
+        if (split.getValue() != null) {
+            SimpleDateFormatUtil.getRevisionFormat().parse(split.getValue());
+        }
+
+        return new RevisionSourceIdentifier(split.getKey(), Optional.fromNullable(split.getValue()));
+    }
+
+    /**
+     * Creates a new RevisionSourceIdentifier based on the provided file name. This variant ignores any revision
+     * part.
+     *
+     * @param fileName file name
+     * @throws IllegalArgumentException when fileName does not have correct format
+     * @throws NullPointerException when fileName is null
+     */
+    public static RevisionSourceIdentifier fromFileNameLenientRevision(final String fileName) {
+        final Entry<String, String> split = splitFileName(fileName);
+        return new RevisionSourceIdentifier(split.getKey(), Optional.fromNullable(split.getValue()));
+    }
+
+    private static Entry<String, String> splitFileName(final String fileName) {
+        Preconditions.checkArgument(fileName.endsWith(RFC6020_YANG_FILE_EXTENSION),
+            "File name '%s' does not end with %s", fileName, RFC6020_YANG_FILE_EXTENSION);
+
+        final String noExt = fileName.substring(0, fileName.length() - RFC6020_YANG_FILE_EXTENSION.length());
+        final int atIndex = noExt.indexOf('@');
+        return atIndex == -1 ? new SimpleImmutableEntry<>(noExt, null)
+                : new SimpleImmutableEntry<>(noExt.substring(0, atIndex), noExt.substring(atIndex + 1));
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
index 7880f38b37cfc3aaf8467bc4804d25d9d8214ec4..0b0cdb4ff93a5f1054e71b54f1991d14f84340c1 100644 (file)
@@ -20,6 +20,7 @@ import com.google.common.util.concurrent.Futures;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.text.ParseException;
 import java.util.Collection;
 import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedDeque;
@@ -163,7 +164,7 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem
             IOException, YangSyntaxErrorException {
         checkArgument(url != null, "Supplied URL must not be null");
 
-        final SourceIdentifier guessedId = RevisionSourceIdentifier.create(url.getFile(), Optional.absent());
+        final SourceIdentifier guessedId = guessSourceIdentifier(url.getFile());
         return registerSource(new YangTextSchemaSource(guessedId) {
             @Override
             public InputStream openStream() throws IOException {
@@ -177,6 +178,18 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem
         });
     }
 
+    private static SourceIdentifier guessSourceIdentifier(final String fileName) {
+        try {
+            return RevisionSourceIdentifier.fromFileName(fileName);
+        } catch (ParseException e) {
+            LOG.debug("Malformed revision in '{}'", fileName, e);
+            return RevisionSourceIdentifier.fromFileNameLenientRevision(fileName);
+        } catch (IllegalArgumentException e) {
+            LOG.debug("Invalid file name format in '{}'", fileName, e);
+            return RevisionSourceIdentifier.create(fileName);
+        }
+    }
+
     /**
      * Try to parse all currently available yang files and build new schema context.
      * @return new schema context iif there is at least 1 yang file registered and