BUG-7062: add revision awareness to Yin/YangTextSchemaSource 52/47752/7
authorRobert Varga <rovarga@cisco.com>
Sat, 29 Oct 2016 21:30:04 +0000 (23:30 +0200)
committerRobert Varga <nite@hq.sk>
Fri, 4 Nov 2016 10:09:06 +0000 (10:09 +0000)
This adds support for parsing file names according
to https://tools.ietf.org/html/rfc6020#section-5.2.

Change-Id: I497aeba2cd801f618fa6a1075558325332623e31
Signed-off-by: Robert Varga <rovarga@cisco.com>
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/YangConstants.java
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/YangNames.java [new file with mode: 0644]
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/repo/api/YangTextSchemaSource.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/repo/api/YinTextSchemaSource.java

index 5adc588e0f04a0fb51c23894350b78209aa6bd80..06547cd04b689481c577305cb91e9d7c2651425c 100644 (file)
@@ -14,20 +14,51 @@ import java.net.URI;
  */
 public final class YangConstants {
     /**
-     * YANG namespace, as defined in RFC 6020.
+     * YANG File Extension, as defined in https://tools.ietf.org/html/rfc6020#section-14.1.
      */
-    public static final URI RFC6020_YANG_NAMESPACE = URI.create("urn:ietf:params:xml:ns:yang:1");
+    public static final String RFC6020_YANG_FILE_EXTENSION = ".yang";
 
     /**
-     * YIN namespace, as defined in RFC 6020.
+     * YANG Media Type, as defined in https://tools.ietf.org/html/rfc6020#section-14.1.
      */
-    public static final URI RFC6020_YIN_NAMESPACE = URI.create("urn:ietf:params:xml:ns:yang:yin:1");
+    public static final String RFC6020_YANG_MAC_FILE_TYPE = "TEXT";
+
+
+    /**
+     * YANG Media Type, as defined in https://tools.ietf.org/html/rfc6020#section-14.1.
+     */
+    public static final String RFC6020_YANG_MEDIA_TYPE = "application/yang";
+
+    /**
+     * YANG namespace, as defined in https://tools.ietf.org/html/rfc6020#section-14.
+     */
+    public static final URI RFC6020_YANG_NAMESPACE = URI.create("urn:ietf:params:xml:ns:yang:1");
 
     /**
      * Base QNameModule for all YANG statements.
      */
     public static final QNameModule RFC6020_YANG_MODULE = QNameModule.create(RFC6020_YANG_NAMESPACE, null).intern();
 
+    /**
+     * YIN File Extension, as defined in https://tools.ietf.org/html/rfc6020#section-14.2.
+     */
+    public static final String RFC6020_YIN_FILE_EXTENSION = ".yin";
+
+    /**
+     * YANG Media Type, as defined in https://tools.ietf.org/html/rfc6020#section-14.1.
+     */
+    public static final String RFC6020_MAC_FILE_TYPE = "TEXT";
+
+    /**
+     * YANG Media Type, as defined in https://tools.ietf.org/html/rfc6020#section-14.1.
+     */
+    public static final String RFC6020_YIN_MEDIA_TYPE = "application/xml+yin";
+
+    /**
+     * YIN namespace, as defined in https://tools.ietf.org/html/rfc6020#section-14.
+     */
+    public static final URI RFC6020_YIN_NAMESPACE = URI.create("urn:ietf:params:xml:ns:yang:yin:1");
+
     /**
      * Base QNameModule for all YIN statements.
      */
@@ -36,5 +67,4 @@ public final class YangConstants {
     private YangConstants() {
         throw new UnsupportedOperationException("Utility class");
     }
-
 }
diff --git a/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/YangNames.java b/yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/YangNames.java
new file mode 100644 (file)
index 0000000..1e27ee3
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.common;
+
+import com.google.common.annotations.Beta;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Map.Entry;
+
+/**
+ * Utility class for handling various naming conventions mentioned in YANG and related specifications.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class YangNames {
+    private YangNames() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Parse a file name according to rules outlined in https://tools.ietf.org/html/rfc6020#section-5.2. Input string
+     * should be the base path with file extension stripped.
+     *
+     * @param baseName file base name
+     * @return A tuple containing the module name and parsed revision, if present.
+     */
+    public static Entry<String, String> parseFilename(final String baseName) {
+        final int zavinac = baseName.lastIndexOf('@');
+        if (zavinac < 0) {
+            return new SimpleEntry<>(baseName, null);
+        }
+
+        return new SimpleEntry<>(baseName.substring(0, zavinac), baseName.substring(zavinac + 1));
+    }
+}
index 1c3783f98e5d362f674c59d0cdff57aaca5bbcfe..82651b466a791c5b4da5af0d258b192423f0b5d7 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.model.repo.api;
 
 import static com.google.common.base.Preconditions.checkArgument;
+
 import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
@@ -16,7 +17,10 @@ import com.google.common.base.Preconditions;
 import com.google.common.io.ByteSource;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Map.Entry;
 import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.yang.common.YangConstants;
+import org.opendaylight.yangtools.yang.common.YangNames;
 
 /**
  * YANG text schema source representation. Exposes an RFC6020 text representation
@@ -31,9 +35,12 @@ public abstract class YangTextSchemaSource extends ByteSource implements YangSch
     }
 
     public static SourceIdentifier identifierFromFilename(final String name) {
-        checkArgument(name.endsWith(".yang"), "Filename %s does not have a .yang extension", name);
-        // FIXME: add revision-awareness
-        return SourceIdentifier.create(name.substring(0, name.length() - 5), Optional.absent());
+        checkArgument(name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION), "Filename %s does not have a .yang extension",
+            name);
+
+        final String baseName = name.substring(0, name.length() - YangConstants.RFC6020_YANG_FILE_EXTENSION.length());
+        final Entry<String, String> parsed = YangNames.parseFilename(baseName);
+        return RevisionSourceIdentifier.create(parsed.getKey(), Optional.fromNullable(parsed.getValue()));
     }
 
     /**
index ce6e3ce4f4d114e75077ecced4d25c023f868456..970df9e3a07c9a64a6efa6e97512138810b987b7 100644 (file)
@@ -15,13 +15,21 @@ import com.google.common.base.Preconditions;
 import com.google.common.io.ByteSource;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Map.Entry;
 import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.yang.common.YangConstants;
+import org.opendaylight.yangtools.yang.common.YangNames;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * YIN text schema source representation. Exposes an RFC6020 XML representation as an {@link InputStream}.
  */
 @Beta
 public abstract class YinTextSchemaSource extends ByteSource implements YinSchemaSourceRepresentation {
+    private static final Logger LOG = LoggerFactory.getLogger(YinTextSchemaSource.class);
+    private static final String XML_EXTENSION = ".xml";
+
     private final SourceIdentifier identifier;
 
     protected YinTextSchemaSource(final SourceIdentifier identifier) {
@@ -30,14 +38,18 @@ public abstract class YinTextSchemaSource extends ByteSource implements YinSchem
 
     public static SourceIdentifier identifierFromFilename(final String name) {
         final String baseName;
-        if (name.endsWith(".xml") || name.endsWith(".yin")) {
-            baseName = name.substring(0, name.length() - 4);
+        if (name.endsWith(YangConstants.RFC6020_YIN_FILE_EXTENSION)) {
+            baseName = name.substring(0, name.length() - YangConstants.RFC6020_YIN_FILE_EXTENSION.length());
+        } else if (name.endsWith(XML_EXTENSION)) {
+            // FIXME: BUG-7061: remove this once we do not need it
+            LOG.warn("XML file {} being loaded as YIN", name);
+            baseName = name.substring(0, name.length() - XML_EXTENSION.length());
         } else {
             throw new IllegalArgumentException("Filename " + name + " does not have a .yin or .xml extension");
         }
 
-        // FIXME: add revision-awareness
-        return SourceIdentifier.create(baseName, Optional.absent());
+        final Entry<String, String> parsed = YangNames.parseFilename(baseName);
+        return RevisionSourceIdentifier.create(parsed.getKey(), Optional.fromNullable(parsed.getValue()));
     }
 
     /**