Improved parse method to read only files which are required by imports. 69/1569/1
authorMartin Vitez <mvitez@cisco.com>
Tue, 1 Oct 2013 08:28:13 +0000 (10:28 +0200)
committerMartin Vitez <mvitez@cisco.com>
Tue, 1 Oct 2013 08:28:13 +0000 (10:28 +0200)
Added tests.

Signed-off-by: Martin Vitez <mvitez@cisco.com>
19 files changed:
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/TypesResolutionTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/YangParserTest.java
yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m2@2013-10-01.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m2@2013-30-09.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m3.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m4.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m5.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m6.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/unused.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/m1.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/m2@2013-10-01.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/m2@2013-30-09.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/m3.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/m4.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/m5.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/m6.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/parse-methods/unused.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/resources/types/custom-types-test@2012-4-4.yang

index 1a017758eb10eb7cb7473be38c93da4a735c673e..eeae990a2daecccbffd38101f4d1872314b27bb6 100644 (file)
@@ -42,6 +42,7 @@ import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.ModuleImport;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
@@ -89,16 +90,46 @@ public final class YangParserImpl implements YangModelParser {
         final String[] fileList = directory.list();
         Preconditions.checkNotNull(fileList, directory + " not found");
 
-        final List<File> modules = new ArrayList<>();
+        FileInputStream yangFileStream = null;
+        LinkedHashMap<InputStream, File> streamToFileMap = new LinkedHashMap<>();
+
+        try {
+            yangFileStream = new FileInputStream(yangFile);
+            streamToFileMap.put(yangFileStream, yangFile);
+        } catch(FileNotFoundException e) {
+            LOG.warn("Exception while reading yang file: " + yangFile.getName(), e);
+        }
+
         for (String fileName : fileList) {
             if (fileName.equals(yangFileName)) {
                 continue;
             }
-            modules.add(new File(directory, fileName));
+            File dependency = new File(directory, fileName);
+            try {
+                if (dependency.isFile()) {
+                    streamToFileMap.put(new FileInputStream(dependency), dependency);
+                }
+            } catch(FileNotFoundException e) {
+                LOG.warn("Exception while reading yang file: " + fileName, e);
+            }
         }
-        modules.add(yangFile);
 
-        return parseYangModels(modules);
+        Map<InputStream, ModuleBuilder> parsedBuilders = parseModuleBuilders(
+                new ArrayList<>(streamToFileMap.keySet()), new HashMap<ModuleBuilder, InputStream>());
+        ModuleBuilder main = parsedBuilders.get(yangFileStream);
+
+        List<ModuleBuilder> moduleBuilders = new ArrayList<>();
+        moduleBuilders.add(main);
+        filterImports(main, new ArrayList<>(parsedBuilders.values()), moduleBuilders);
+
+        ModuleBuilder[] builders = new ModuleBuilder[moduleBuilders.size()];
+        moduleBuilders.toArray(builders);
+
+        // module dependency graph sorted
+        List<ModuleBuilder> sorted = ModuleDependencySort.sort(builders);
+
+        final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = orderModules(sorted);
+        return new LinkedHashSet<>(buildWithContext(modules, null).values());
     }
 
     @Override
@@ -120,7 +151,6 @@ public final class YangParserImpl implements YangModelParser {
             }
 
             Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
-
             final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
                     Lists.newArrayList(inputStreams.keySet()), builderToStreamMap);
 
@@ -211,26 +241,27 @@ public final class YangParserImpl implements YangModelParser {
         return new SchemaContextImpl(modules);
     }
 
-    private ModuleBuilder[] parseModuleBuilders(List<InputStream> inputStreams,
+    private Map<InputStream, ModuleBuilder> parseModuleBuilders(List<InputStream> inputStreams,
             Map<ModuleBuilder, InputStream> streamToBuilderMap) {
 
         final ParseTreeWalker walker = new ParseTreeWalker();
-        final List<ParseTree> trees = parseStreams(inputStreams);
-        final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
+        final Map<InputStream, ParseTree> trees = parseStreams(inputStreams);
+        final Map<InputStream, ModuleBuilder> builders = new LinkedHashMap<>();
 
         // validate yang
-        new YangModelBasicValidator(walker).validate(trees);
+        new YangModelBasicValidator(walker).validate(new ArrayList<ParseTree>(trees.values()));
 
         YangParserListenerImpl yangModelParser;
-        for (int i = 0; i < trees.size(); i++) {
+        for(Map.Entry<InputStream, ParseTree> entry : trees.entrySet()) {
             yangModelParser = new YangParserListenerImpl();
-            walker.walk(yangModelParser, trees.get(i));
+            walker.walk(yangModelParser, entry.getValue());
             ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
 
             // We expect the order of trees and streams has to be the same
-            streamToBuilderMap.put(moduleBuilder, inputStreams.get(i));
-            builders[i] = moduleBuilder;
+            streamToBuilderMap.put(moduleBuilder, entry.getKey());
+            builders.put(entry.getKey(), moduleBuilder);
         }
+
         return builders;
     }
 
@@ -242,10 +273,9 @@ public final class YangParserImpl implements YangModelParser {
     private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersWithContext(
             final List<InputStream> yangFileStreams, final Map<ModuleBuilder, InputStream> streamToBuilderMap,
             final SchemaContext context) {
-        final ModuleBuilder[] builders = parseModuleBuilders(yangFileStreams, streamToBuilderMap);
-
-        // LinkedHashMap must be used to preserve order
-        final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = new LinkedHashMap<String, TreeMap<Date, ModuleBuilder>>();
+        Map<InputStream, ModuleBuilder> parsedBuilders = parseModuleBuilders(yangFileStreams, streamToBuilderMap);
+        ModuleBuilder[] builders = new ModuleBuilder[parsedBuilders.size()];
+        final ModuleBuilder[] moduleBuilders = new ArrayList<>(parsedBuilders.values()).toArray(builders);
 
         // module dependency graph sorted
         List<ModuleBuilder> sorted;
@@ -255,7 +285,20 @@ public final class YangParserImpl implements YangModelParser {
             sorted = ModuleDependencySort.sortWithContext(context, builders);
         }
 
-        for (final ModuleBuilder builder : sorted) {
+        return orderModules(sorted);
+    }
+
+    /**
+     * Order modules by name and revision.
+     *
+     * @param modules
+     *            modules to order
+     * @return modules ordered by name and revision
+     */
+    private LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> orderModules(List<ModuleBuilder> modules) {
+        // LinkedHashMap must be used to preserve order
+        LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> result = new LinkedHashMap<>();
+        for (final ModuleBuilder builder : modules) {
             if (builder == null) {
                 continue;
             }
@@ -264,20 +307,42 @@ public final class YangParserImpl implements YangModelParser {
             if (builderRevision == null) {
                 builderRevision = new Date(0L);
             }
-            TreeMap<Date, ModuleBuilder> builderByRevision = modules.get(builderName);
+            TreeMap<Date, ModuleBuilder> builderByRevision = result.get(builderName);
             if (builderByRevision == null) {
                 builderByRevision = new TreeMap<Date, ModuleBuilder>();
             }
             builderByRevision.put(builderRevision, builder);
-            modules.put(builderName, builderByRevision);
+            result.put(builderName, builderByRevision);
+        }
+        return result;
+    }
+
+    private void filterImports(ModuleBuilder main, List<ModuleBuilder> other, List<ModuleBuilder> filtered) {
+        for (ModuleImport mi : main.getModuleImports()) {
+            for (ModuleBuilder builder : other) {
+                if (mi.getModuleName().equals(builder.getModuleName())) {
+                    if (mi.getRevision() == null) {
+                        if (!filtered.contains(builder)) {
+                            filtered.add(builder);
+                            filterImports(builder, other, filtered);
+                        }
+                    } else {
+                        if (mi.getRevision().equals(builder.getRevision())) {
+                            if (!filtered.contains(builder)) {
+                                filtered.add(builder);
+                                filterImports(builder, other, filtered);
+                            }
+                        }
+                    }
+                }
+            }
         }
-        return modules;
     }
 
-    private List<ParseTree> parseStreams(final List<InputStream> yangStreams) {
-        final List<ParseTree> trees = new ArrayList<ParseTree>();
+    private Map<InputStream, ParseTree> parseStreams(final List<InputStream> yangStreams) {
+        final Map<InputStream, ParseTree> trees = new HashMap<>();
         for (InputStream yangStream : yangStreams) {
-            trees.add(parseStream(yangStream));
+            trees.put(yangStream, parseStream(yangStream));
         }
         return trees;
     }
index 0f2807efaa505f93120e32179f30de598690fdf9..d80ebd778528cd40bf0fc2685ef37bff8e58eba7 100644 (file)
@@ -46,6 +46,7 @@ public class TypesResolutionTest {
         File dependenciesDir = new File(getClass().getResource("/ietf").getPath());
         YangModelParser parser = new YangParserImpl();
         testedModules = parser.parseYangModels(yangFile, dependenciesDir);
+        assertEquals(4, testedModules.size());
     }
 
     @Test
index d946e07356fb521745f742397f80fe93df0808eb..6f2c354072d6368b8696ef85d0dd0049001e38aa 100644 (file)
@@ -8,7 +8,9 @@
 package org.opendaylight.yangtools.yang.parser.impl;
 
 import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.net.URI;
 import java.text.ParseException;
@@ -45,6 +47,7 @@ import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
 import org.opendaylight.yangtools.yang.model.util.Decimal64;
 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
 import org.opendaylight.yangtools.yang.model.util.Int16;
@@ -815,4 +818,22 @@ public class YangParserTest {
         assertEquals(dec64QName, dec64Path.get(1));
     }
 
+    @Test
+    public void testParseMethod1() throws ParseException {
+        File yangFile = new File(getClass().getResource("/parse-methods/m1.yang").getPath());
+        File dependenciesDir = new File(getClass().getResource("/parse-methods").getPath());
+        YangModelParser parser = new YangParserImpl();
+        modules = parser.parseYangModels(yangFile, dependenciesDir);
+        assertEquals(6, modules.size());
+    }
+
+    @Test
+    public void testParseMethod2() throws ParseException {
+        File yangFile = new File(getClass().getResource("/parse-methods/m1.yang").getPath());
+        File dependenciesDir = new File(getClass().getResource("/parse-methods/dependencies").getPath());
+        YangModelParser parser = new YangParserImpl();
+        modules = parser.parseYangModels(yangFile, dependenciesDir);
+        assertEquals(6, modules.size());
+    }
+
 }
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m2@2013-10-01.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m2@2013-10-01.yang
new file mode 100644 (file)
index 0000000..1eb8f26
--- /dev/null
@@ -0,0 +1,17 @@
+module m2 {
+
+    yang-version 1;
+    namespace "urn:test.m2";
+    prefix "m2";
+
+    import m4 {
+        prefix "m4";
+    }
+    import m5 {
+        prefix "m5";
+    }
+
+     revision 2013-10-01 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m2@2013-30-09.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m2@2013-30-09.yang
new file mode 100644 (file)
index 0000000..af6ca8b
--- /dev/null
@@ -0,0 +1,17 @@
+module m2 {
+
+    yang-version 1;
+    namespace "urn:test.m2";
+    prefix "m2";
+
+    import m4 {
+        prefix "m4";
+    }
+    import m5 {
+        prefix "m5";
+    }
+
+     revision 2013-30-09 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m3.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m3.yang
new file mode 100644 (file)
index 0000000..ffa687a
--- /dev/null
@@ -0,0 +1,17 @@
+module m3 {
+
+    yang-version 1;
+    namespace "urn:test.m3";
+    prefix "m3";
+
+    import m4 {
+        prefix "m4";
+    }
+    import m6 {
+        prefix "m6";
+    }
+
+     revision 2013-09-30 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m4.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m4.yang
new file mode 100644 (file)
index 0000000..f4ccdc6
--- /dev/null
@@ -0,0 +1,10 @@
+module m4 {
+
+    yang-version 1;
+    namespace "urn:test.m4";
+    prefix "m4";
+
+     revision 2013-09-30 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m5.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m5.yang
new file mode 100644 (file)
index 0000000..88fc73d
--- /dev/null
@@ -0,0 +1,10 @@
+module m5 {
+
+    yang-version 1;
+    namespace "urn:test.m5";
+    prefix "m5";
+
+     revision 2012-04-16 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m6.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/m6.yang
new file mode 100644 (file)
index 0000000..70dd8d6
--- /dev/null
@@ -0,0 +1,10 @@
+module m6 {
+
+    yang-version 1;
+    namespace "urn:test.m6";
+    prefix "m6";
+
+     revision 2012-04-16 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/unused.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/dependencies/unused.yang
new file mode 100644 (file)
index 0000000..778043a
--- /dev/null
@@ -0,0 +1,17 @@
+module unused {
+
+    yang-version 1;
+    namespace "urn:test.unused";
+    prefix "u";
+
+    import m2 {
+        prefix "m2";
+    }
+    import m3 {
+        prefix "m3";
+    }
+
+     revision 2012-04-16 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/m1.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/m1.yang
new file mode 100644 (file)
index 0000000..c7063ab
--- /dev/null
@@ -0,0 +1,18 @@
+module m1 {
+
+    yang-version 1;
+    namespace "urn:test.m1";
+    prefix "m1";
+
+    import m2 {
+        prefix "m2";
+        revision-date 2013-30-09;
+    }
+    import m3 {
+        prefix "m3";
+    }
+
+     revision 2013-10-16 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/m2@2013-10-01.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/m2@2013-10-01.yang
new file mode 100644 (file)
index 0000000..1eb8f26
--- /dev/null
@@ -0,0 +1,17 @@
+module m2 {
+
+    yang-version 1;
+    namespace "urn:test.m2";
+    prefix "m2";
+
+    import m4 {
+        prefix "m4";
+    }
+    import m5 {
+        prefix "m5";
+    }
+
+     revision 2013-10-01 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/m2@2013-30-09.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/m2@2013-30-09.yang
new file mode 100644 (file)
index 0000000..af6ca8b
--- /dev/null
@@ -0,0 +1,17 @@
+module m2 {
+
+    yang-version 1;
+    namespace "urn:test.m2";
+    prefix "m2";
+
+    import m4 {
+        prefix "m4";
+    }
+    import m5 {
+        prefix "m5";
+    }
+
+     revision 2013-30-09 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/m3.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/m3.yang
new file mode 100644 (file)
index 0000000..ffa687a
--- /dev/null
@@ -0,0 +1,17 @@
+module m3 {
+
+    yang-version 1;
+    namespace "urn:test.m3";
+    prefix "m3";
+
+    import m4 {
+        prefix "m4";
+    }
+    import m6 {
+        prefix "m6";
+    }
+
+     revision 2013-09-30 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/m4.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/m4.yang
new file mode 100644 (file)
index 0000000..f4ccdc6
--- /dev/null
@@ -0,0 +1,10 @@
+module m4 {
+
+    yang-version 1;
+    namespace "urn:test.m4";
+    prefix "m4";
+
+     revision 2013-09-30 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/m5.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/m5.yang
new file mode 100644 (file)
index 0000000..88fc73d
--- /dev/null
@@ -0,0 +1,10 @@
+module m5 {
+
+    yang-version 1;
+    namespace "urn:test.m5";
+    prefix "m5";
+
+     revision 2012-04-16 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/m6.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/m6.yang
new file mode 100644 (file)
index 0000000..70dd8d6
--- /dev/null
@@ -0,0 +1,10 @@
+module m6 {
+
+    yang-version 1;
+    namespace "urn:test.m6";
+    prefix "m6";
+
+     revision 2012-04-16 {
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/test/resources/parse-methods/unused.yang b/yang/yang-parser-impl/src/test/resources/parse-methods/unused.yang
new file mode 100644 (file)
index 0000000..778043a
--- /dev/null
@@ -0,0 +1,17 @@
+module unused {
+
+    yang-version 1;
+    namespace "urn:test.unused";
+    prefix "u";
+
+    import m2 {
+        prefix "m2";
+    }
+    import m3 {
+        prefix "m3";
+    }
+
+     revision 2012-04-16 {
+    }
+
+}
index b7f07fcae194a1482d8bdc9679bd53699c3efeb2..68e008c1d5910b912ba01a3d4e6825145cea4315 100644 (file)
@@ -5,12 +5,6 @@ module custom-types-test {
     prefix "iit";
 
     // imports added only for testing purposes
-    import iana-afn-safi {
-        prefix "afn";
-    }
-    import iana-if-type {
-        prefix "if";
-    }
     import iana-timezones {
         prefix "tz";
     }