BUG-4688: Make SourceIdentifier use Revision
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / util / YangModelDependencyInfo.java
index e92fb61edf292edb66cba5f65667080508920740..09bf8a2588a2a4b2bd09737b0ca4ea57766beaa9 100644 (file)
@@ -7,46 +7,37 @@
  */
 package org.opendaylight.yangtools.yang.parser.impl.util;
 
-import static org.opendaylight.yangtools.yang.parser.impl.ParserListenerUtils.getArgumentString;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableSet;
-import java.io.InputStream;
-import java.util.Date;
+import java.io.IOException;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
+import javax.annotation.Nullable;
 import org.antlr.v4.runtime.ParserRuleContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Import_stmtContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Include_stmtContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Module_stmtContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Revision_stmtContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Revision_stmtsContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Submodule_stmtContext;
-import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser;
 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
 import org.opendaylight.yangtools.concepts.SemVer;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
-import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
+import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
-import org.opendaylight.yangtools.yang.parser.impl.ParserListenerUtils;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc6020.repo.YangStatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.SupportedExtensionsMapping;
 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
-import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
 
 /**
  * Helper transfer object which holds basic and dependency information for YANG
  * model.
  *
- *
- *
+ * <p>
  * There are two concrete implementations of this interface:
  * <ul>
  * <li>{@link ModuleDependencyInfo} - Dependency information for module</li>
@@ -55,15 +46,22 @@ import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceIm
  *
  * @see ModuleDependencyInfo
  * @see SubmoduleDependencyInfo
- *
  */
-
 public abstract class YangModelDependencyInfo {
+    private static final String BELONGS_TO = YangStmtMapping.BELONGS_TO.getStatementName().getLocalName();
+    private static final String IMPORT = YangStmtMapping.IMPORT.getStatementName().getLocalName();
+    private static final String INCLUDE = YangStmtMapping.INCLUDE.getStatementName().getLocalName();
+    private static final String MODULE = YangStmtMapping.MODULE.getStatementName().getLocalName();
+    private static final String REVISION = YangStmtMapping.REVISION.getStatementName().getLocalName();
+    private static final String REVISION_DATE = YangStmtMapping.REVISION_DATE.getStatementName().getLocalName();
+    private static final String SUBMODULE = YangStmtMapping.SUBMODULE.getStatementName().getLocalName();
+
+    private static final String OPENCONFIG_VERSION = SupportedExtensionsMapping.OPENCONFIG_VERSION.getStatementName()
+            .getLocalName();
 
     private final String name;
-    private final String formattedRevision;
-    private final Date revision;
-    private final Optional<SemVer> semVer;
+    private final Revision revision;
+    private final SemVer semVer;
     private final ImmutableSet<ModuleImport> submoduleIncludes;
     private final ImmutableSet<ModuleImport> moduleImports;
     private final ImmutableSet<ModuleImport> dependencies;
@@ -71,7 +69,7 @@ public abstract class YangModelDependencyInfo {
     YangModelDependencyInfo(final String name, final String formattedRevision,
             final ImmutableSet<ModuleImport> imports,
             final ImmutableSet<ModuleImport> includes) {
-        this(name, formattedRevision, imports, includes, Optional.absent());
+        this(name, formattedRevision, imports, includes, Optional.empty());
     }
 
     YangModelDependencyInfo(final String name, final String formattedRevision,
@@ -79,21 +77,17 @@ public abstract class YangModelDependencyInfo {
             final ImmutableSet<ModuleImport> includes,
             final Optional<SemVer> semVer) {
         this.name = name;
-        this.formattedRevision = formattedRevision;
-        this.revision = formattedRevision == null ? null : QName
-                .parseRevision(formattedRevision);
+        this.revision = formattedRevision == null ? null : Revision.valueOf(formattedRevision);
         this.moduleImports = imports;
         this.submoduleIncludes = includes;
-        this.dependencies = ImmutableSet.<ModuleImport> builder()
+        this.dependencies = ImmutableSet.<ModuleImport>builder()
                 .addAll(moduleImports).addAll(submoduleIncludes).build();
-        this.semVer = semVer;
+        this.semVer = semVer.orElse(null);
     }
 
     /**
-     * Returns immutable collection of all module imports.
-     *
-     * This collection contains both <code>import</code> statements and
-     * <code>include</code> statements for submodules.
+     * Returns immutable collection of all module imports. This collection contains both <code>import</code> statements
+     * and <code>include</code> statements for submodules.
      *
      * @return Immutable collection of imports.
      */
@@ -102,7 +96,7 @@ public abstract class YangModelDependencyInfo {
     }
 
     /**
-     * Returns model name
+     * Returns model name.
      *
      * @return model name
      */
@@ -111,38 +105,38 @@ public abstract class YangModelDependencyInfo {
     }
 
     /**
-     * Returns formatted revision string
+     * Returns formatted revision string.
      *
      * @return formatted revision string
      */
     public String getFormattedRevision() {
-        return formattedRevision;
+        return revision != null ? revision.toString() : null;
     }
 
     /**
-     * Returns revision
+     * Returns revision.
      *
-     * @return revision
+     * @return revision, potentially null
      */
-    Date getRevision() {
-        return revision;
+    public Optional<Revision> getRevision() {
+        return Optional.ofNullable(revision);
     }
 
     /**
-     * Returns semantic version of module
+     * Returns semantic version of module.
      *
      * @return semantic version
      */
     public Optional<SemVer> getSemanticVersion() {
-        return semVer;
+        return Optional.ofNullable(semVer);
     }
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + Objects.hashCode(formattedRevision);
         result = prime * result + Objects.hashCode(name);
+        result = prime * result + Objects.hashCode(revision);
         result = prime * result + Objects.hashCode(semVer);
         return result;
     }
@@ -159,227 +153,131 @@ public abstract class YangModelDependencyInfo {
             return false;
         }
         final YangModelDependencyInfo other = (YangModelDependencyInfo) obj;
-        if (formattedRevision == null) {
-            if (other.formattedRevision != null) {
-                return false;
-            }
-        } else if (!formattedRevision.equals(other.formattedRevision)) {
-            return false;
-        }
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
-        if(!Objects.equals(semVer, other.semVer)) {
-            return false;
-        }
-
-        return true;
+        return Objects.equals(name, other.name) && Objects.equals(revision, other.revision)
+                && Objects.equals(semVer, other.semVer);
     }
 
     /**
-     * Extracts {@link YangModelDependencyInfo} from an abstract syntax tree of
-     * a YANG model.
+     * Extracts {@link YangModelDependencyInfo} from an abstract syntax tree of a YANG model.
      *
-     * @param tree
-     *            Abstract syntax tree
+     * @param tree Abstract syntax tree
      * @return {@link YangModelDependencyInfo}
-     * @throws YangSyntaxErrorException
-     *             If the AST is not a valid YANG module/submodule
+     * @throws YangSyntaxErrorException If the AST is not a valid YANG module/submodule
      */
     public static YangModelDependencyInfo fromAST(final String name,
             final ParserRuleContext tree) throws YangSyntaxErrorException {
 
-        if (tree instanceof YangStatementParser.StatementContext) {
-            final YangStatementParser.StatementContext rootStatement = (YangStatementParser.StatementContext) tree;
-            return parseAST(rootStatement);
-        }
-
-        final Optional<Module_stmtContext> moduleCtx = ParserListenerUtils
-                .getFirstContext(tree, Module_stmtContext.class);
-        if (moduleCtx.isPresent()) {
-            return parseModuleContext(moduleCtx.get());
-        }
-
-        final Optional<Submodule_stmtContext> submoduleCtx = ParserListenerUtils
-                .getFirstContext(tree, Submodule_stmtContext.class);
-        if (submoduleCtx.isPresent()) {
-            return parseSubmoduleContext(submoduleCtx.get());
+        if (tree instanceof StatementContext) {
+            final StatementContext rootStatement = (StatementContext) tree;
+            return parseAST(rootStatement, name);
         }
 
         throw new YangSyntaxErrorException(name, 0, 0, "Unknown YANG text type");
     }
 
-    private static YangModelDependencyInfo parseAST(
-            final YangStatementParser.StatementContext rootStatement) {
-        if (rootStatement
-                .keyword()
-                .getText()
-                .equals(Rfc6020Mapping.MODULE.getStatementName().getLocalName())) {
-            return parseModuleContext(rootStatement);
-        } else if (rootStatement
-                .keyword()
-                .getText()
-                .equals(Rfc6020Mapping.SUBMODULE.getStatementName()
-                        .getLocalName())) {
-            return parseSubmoduleContext(rootStatement);
+    private static YangModelDependencyInfo parseAST(final StatementContext rootStatement, final String sourceName) {
+        final String keyWordText = rootStatement.keyword().getText();
+        if (MODULE.equals(keyWordText)) {
+            return parseModuleContext(rootStatement, sourceName);
         }
-
-        throw new IllegalArgumentException(
-                "Root of parsed AST must be either module or submodule");
+        if (SUBMODULE.equals(keyWordText)) {
+            return parseSubmoduleContext(rootStatement, sourceName);
+        }
+        throw new IllegalArgumentException("Root of parsed AST must be either module or submodule");
     }
 
     /**
-     * Extracts {@link YangModelDependencyInfo} from input stream containing
-     * YANG model.
+     * Extracts {@link YangModelDependencyInfo} from input stream containing a YANG model. This parsing does not
+     * validate full YANG module, only parses header up to the revisions and imports.
      *
-     * This parsing does not validate full YANG module, only parses header up to
-     * the revisions and imports.
-     *
-     * @param yangStream
-     *            Opened Input stream containing text source of YANG model
+     * @param refClass Base search class
+     * @param resourceName resource name, relative to refClass
      * @return {@link YangModelDependencyInfo}
+     * @throws YangSyntaxErrorException If the resource does not pass syntactic analysis
+     * @throws IOException When the resource cannot be read
      * @throws IllegalArgumentException
      *             If input stream is not valid YANG stream
      */
-    public static YangModelDependencyInfo fromInputStream(
-            final InputStream yangStream) {
-        final StatementContext yangAST = new YangStatementSourceImpl(yangStream)
-                .getYangAST();
-        return parseAST(yangAST);
+    public static YangModelDependencyInfo forResource(final Class<?> refClass, final String resourceName)
+            throws IOException, YangSyntaxErrorException {
+        final YangStatementStreamSource source = YangStatementStreamSource.create(
+            YangTextSchemaSource.forResource(refClass, resourceName));
+        final ParserRuleContext ast = source.getYangAST();
+        checkArgument(ast instanceof StatementContext);
+        return parseAST((StatementContext) ast, source.getIdentifier().toYangFilename());
     }
 
-    private static YangModelDependencyInfo parseModuleContext(
-            final Module_stmtContext module) {
-        final String name = getArgumentString(module);
-        final String latestRevision = getLatestRevision(module.revision_stmts());
-        final ImmutableSet<ModuleImport> imports = parseImports(module
-                .linkage_stmts().import_stmt());
-        final ImmutableSet<ModuleImport> includes = parseIncludes(module
-                .linkage_stmts().include_stmt());
-
-        return new ModuleDependencyInfo(name, latestRevision, imports, includes);
-    }
-
-    private static YangModelDependencyInfo parseModuleContext(
-            final YangStatementParser.StatementContext module) {
-        final String name = Utils.stringFromStringContext(module.argument());
-        final String latestRevision = getLatestRevision(module);
-        final Optional<SemVer> semVer = Optional.fromNullable(getSemanticVersion(module));
-        final ImmutableSet<ModuleImport> imports = parseImports(module);
-        final ImmutableSet<ModuleImport> includes = parseIncludes(module);
+    private static YangModelDependencyInfo parseModuleContext(final StatementContext module, final String sourceName) {
+        final String name = Utils.stringFromStringContext(module.argument(), getReference(sourceName, module));
+        final String latestRevision = getLatestRevision(module, sourceName);
+        final Optional<SemVer> semVer = Optional.ofNullable(findSemanticVersion(module, sourceName));
+        final ImmutableSet<ModuleImport> imports = parseImports(module, sourceName);
+        final ImmutableSet<ModuleImport> includes = parseIncludes(module, sourceName);
 
         return new ModuleDependencyInfo(name, latestRevision, imports, includes, semVer);
     }
 
-    private static ImmutableSet<ModuleImport> parseImports(
-            final YangStatementParser.StatementContext module) {
+    private static ImmutableSet<ModuleImport> parseImports(final StatementContext module, final String sourceName) {
         final Set<ModuleImport> result = new HashSet<>();
-        final List<StatementContext> subStatements = module.statement();
-        for (final StatementContext subStatementContext : subStatements) {
-            if (subStatementContext
-                    .keyword()
-                    .getText()
-                    .equals(Rfc6020Mapping.IMPORT.getStatementName()
-                            .getLocalName())) {
-                final String revisionDateStr = getRevisionDateString(subStatementContext);
-                final String importedModuleName = Utils
-                        .stringFromStringContext(subStatementContext.argument());
-                final Date revisionDate = (revisionDateStr == null) ? null : QName
-                        .parseRevision(revisionDateStr);
-                final Optional<SemVer> importSemVer = Optional.fromNullable(getSemanticVersion(subStatementContext));
-                result.add(new ModuleImportImpl(importedModuleName,
-                        revisionDate, importSemVer));
+        for (final StatementContext subStatementContext : module.statement()) {
+            if (IMPORT.equals(subStatementContext.keyword().getText())) {
+                final String revisionDateStr = getRevisionDateString(subStatementContext, sourceName);
+                final String importedModuleName = Utils.stringFromStringContext(subStatementContext.argument(),
+                        getReference(sourceName, subStatementContext));
+                final Revision revisionDate = revisionDateStr == null ? null : Revision.valueOf(revisionDateStr);
+                final SemVer importSemVer = findSemanticVersion(subStatementContext, sourceName);
+                result.add(new ModuleImportImpl(importedModuleName, revisionDate, importSemVer));
             }
         }
         return ImmutableSet.copyOf(result);
     }
 
-    private static SemVer getSemanticVersion(final StatementContext statement) {
-        final List<StatementContext> subStatements = statement.statement();
+    private static SemVer findSemanticVersion(final StatementContext statement, final String sourceName) {
         String semVerString = null;
-        final String semVerStmtName = SupportedExtensionsMapping.SEMANTIC_VERSION.getStatementName().getLocalName();
-        for (final StatementContext subStatement : subStatements) {
+        for (final StatementContext subStatement : statement.statement()) {
             final String subStatementName = Utils.trimPrefix(subStatement.keyword().getText());
-            if (semVerStmtName.equals(subStatementName)) {
-                semVerString = Utils.stringFromStringContext(subStatement.argument());
+            if (OPENCONFIG_VERSION.equals(subStatementName)) {
+                semVerString = Utils.stringFromStringContext(subStatement.argument(),
+                        getReference(sourceName, subStatement));
                 break;
             }
         }
 
-        if (Strings.isNullOrEmpty(semVerString)) {
-            return null;
-        }
-
-        return SemVer.valueOf(semVerString);
+        return Strings.isNullOrEmpty(semVerString) ? null : SemVer.valueOf(semVerString);
     }
 
-    private static ImmutableSet<ModuleImport> parseIncludes(
-            final YangStatementParser.StatementContext module) {
+    private static ImmutableSet<ModuleImport> parseIncludes(final StatementContext module, final String sourceName) {
         final Set<ModuleImport> result = new HashSet<>();
-        final List<StatementContext> subStatements = module.statement();
-        for (final StatementContext subStatementContext : subStatements) {
-            if (subStatementContext
-                    .keyword()
-                    .getText()
-                    .equals(Rfc6020Mapping.INCLUDE.getStatementName()
-                            .getLocalName())) {
-                final String revisionDateStr = getRevisionDateString(subStatementContext);
-                final String IncludeModuleName = Utils
-                        .stringFromStringContext(subStatementContext.argument());
-                final Date revisionDate = (revisionDateStr == null) ? null : QName
-                        .parseRevision(revisionDateStr);
+        for (final StatementContext subStatementContext : module.statement()) {
+            if (INCLUDE.equals(subStatementContext.keyword().getText())) {
+                final String revisionDateStr = getRevisionDateString(subStatementContext, sourceName);
+                final String IncludeModuleName = Utils.stringFromStringContext(subStatementContext.argument(),
+                        getReference(sourceName, subStatementContext));
+                final Revision revisionDate = revisionDateStr == null ? null : Revision.valueOf(revisionDateStr);
                 result.add(new ModuleImportImpl(IncludeModuleName, revisionDate));
             }
         }
         return ImmutableSet.copyOf(result);
     }
 
-    private static String getRevisionDateString(final StatementContext importStatement) {
-        final List<StatementContext> importSubStatements = importStatement
-                .statement();
+    private static String getRevisionDateString(final StatementContext importStatement, final String sourceName) {
         String revisionDateStr = null;
-        for (final StatementContext importSubStatement : importSubStatements) {
-            if (importSubStatement
-                    .keyword()
-                    .getText()
-                    .equals(Rfc6020Mapping.REVISION_DATE.getStatementName()
-                            .getLocalName())) {
-                revisionDateStr = Utils
-                        .stringFromStringContext(importSubStatement.argument());
+        for (final StatementContext importSubStatement : importStatement.statement()) {
+            if (REVISION_DATE.equals(importSubStatement.keyword().getText())) {
+                revisionDateStr = Utils.stringFromStringContext(importSubStatement.argument(),
+                        getReference(sourceName, importSubStatement));
             }
         }
         return revisionDateStr;
     }
 
-    private static ImmutableSet<ModuleImport> parseImports(
-            final List<Import_stmtContext> importStatements) {
-        final ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
-        for (final Import_stmtContext importStmt : importStatements) {
-            final String moduleName = getArgumentString(importStmt);
-            final Date revision = getRevision(importStmt.revision_date_stmt());
-            builder.add(new ModuleImportImpl(moduleName, revision));
-        }
-        return builder.build();
-    }
-
-    public static String getLatestRevision(
-            final YangStatementParser.StatementContext module) {
-        final List<StatementContext> subStatements = module.statement();
+    public static String getLatestRevision(final StatementContext module, final String sourceName) {
         String latestRevision = null;
-        for (final StatementContext subStatementContext : subStatements) {
-            if (subStatementContext
-                    .keyword()
-                    .getText()
-                    .equals(Rfc6020Mapping.REVISION.getStatementName()
-                            .getLocalName())) {
-                final String currentRevision = Utils
-                        .stringFromStringContext(subStatementContext.argument());
-                if (latestRevision == null
-                        || latestRevision.compareTo(currentRevision) == -1) {
+        for (final StatementContext subStatementContext : module.statement()) {
+            if (REVISION.equals(subStatementContext.keyword().getText())) {
+                final String currentRevision = Utils.stringFromStringContext(subStatementContext.argument(),
+                        getReference(sourceName, subStatementContext));
+                if (latestRevision == null || latestRevision.compareTo(currentRevision) == -1) {
                     latestRevision = currentRevision;
                 }
             }
@@ -387,103 +285,44 @@ public abstract class YangModelDependencyInfo {
         return latestRevision;
     }
 
-    public static String getLatestRevision(
-            final Revision_stmtsContext revisionStmts) {
-        final List<Revision_stmtContext> revisions = revisionStmts
-                .getRuleContexts(Revision_stmtContext.class);
-        String latestRevision = null;
-        for (final Revision_stmtContext revisionStmt : revisions) {
-            final String currentRevision = getArgumentString(revisionStmt);
-            if (latestRevision == null
-                    || latestRevision.compareTo(currentRevision) == -1) {
-                latestRevision = currentRevision;
-            }
-        }
-        return latestRevision;
-    }
-
-    private static YangModelDependencyInfo parseSubmoduleContext(
-            final YangStatementParser.StatementContext submodule) {
-        final String name = Utils.stringFromStringContext(submodule.argument());
-        final String belongsTo = parseBelongsTo(submodule);
+    private static YangModelDependencyInfo parseSubmoduleContext(final StatementContext submodule,
+            final String sourceName) {
+        final String name = Utils.stringFromStringContext(submodule.argument(), getReference(sourceName, submodule));
+        final String belongsTo = parseBelongsTo(submodule, sourceName);
 
-        final String latestRevision = getLatestRevision(submodule);
-        final ImmutableSet<ModuleImport> imports = parseImports(submodule);
-        final ImmutableSet<ModuleImport> includes = parseIncludes(submodule);
+        final String latestRevision = getLatestRevision(submodule, sourceName);
+        final ImmutableSet<ModuleImport> imports = parseImports(submodule, sourceName);
+        final ImmutableSet<ModuleImport> includes = parseIncludes(submodule, sourceName);
 
-        return new SubmoduleDependencyInfo(name, latestRevision, belongsTo,
-                imports, includes);
+        return new SubmoduleDependencyInfo(name, latestRevision, belongsTo, imports, includes);
     }
 
-    private static String parseBelongsTo(final StatementContext submodule) {
-        final List<StatementContext> subStatements = submodule.statement();
-        for (final StatementContext subStatementContext : subStatements) {
-            if (subStatementContext
-                    .keyword()
-                    .getText()
-                    .equals(Rfc6020Mapping.BELONGS_TO.getStatementName()
-                            .getLocalName())) {
-                return Utils.stringFromStringContext(subStatementContext
-                        .argument());
+    private static String parseBelongsTo(final StatementContext submodule, final String sourceName) {
+        for (final StatementContext subStatementContext : submodule.statement()) {
+            if (BELONGS_TO.equals(subStatementContext.keyword().getText())) {
+                return Utils.stringFromStringContext(subStatementContext.argument(),
+                    getReference(sourceName, subStatementContext));
             }
         }
         return null;
     }
 
-    private static YangModelDependencyInfo parseSubmoduleContext(
-            final Submodule_stmtContext submodule) {
-        final String name = getArgumentString(submodule);
-        final Belongs_to_stmtContext belongsToStmt = submodule
-                .submodule_header_stmts().belongs_to_stmt(0);
-        final String belongsTo = getArgumentString(belongsToStmt);
-
-        final String latestRevision = getLatestRevision(submodule.revision_stmts());
-        final ImmutableSet<ModuleImport> imports = parseImports(submodule
-                .linkage_stmts().import_stmt());
-        final ImmutableSet<ModuleImport> includes = parseIncludes(submodule
-                .linkage_stmts().include_stmt());
-
-        return new SubmoduleDependencyInfo(name, latestRevision, belongsTo,
-                imports, includes);
-    }
-
-    private static ImmutableSet<ModuleImport> parseIncludes(
-            final List<Include_stmtContext> importStatements) {
-        final ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
-        for (final Include_stmtContext importStmt : importStatements) {
-            final String moduleName = getArgumentString(importStmt);
-            final Date revision = getRevision(importStmt.revision_date_stmt());
-            builder.add(new ModuleImportImpl(moduleName, revision));
-        }
-        return builder.build();
-    }
-
-    private static Date getRevision(
-            final Revision_date_stmtContext revisionDateStmt) {
-        if (revisionDateStmt == null) {
-            return null;
-        }
-        final String formatedDate = getArgumentString(revisionDateStmt);
-        return QName.parseRevision(formatedDate);
+    private static StatementSourceReference getReference(final String sourceName,
+            final StatementContext context) {
+        return DeclarationInTextSource.atPosition(sourceName, context.getStart().getLine(),
+            context.getStart().getCharPositionInLine());
     }
 
     /**
-     *
      * Dependency information for YANG module.
-     *
      */
-    public static class ModuleDependencyInfo extends
-            YangModelDependencyInfo {
-
-        private ModuleDependencyInfo(final String name,
-                final String latestRevision,
-                final ImmutableSet<ModuleImport> imports,
-                final ImmutableSet<ModuleImport> includes) {
+    public static class ModuleDependencyInfo extends YangModelDependencyInfo {
+        private ModuleDependencyInfo(final String name, final String latestRevision,
+                final ImmutableSet<ModuleImport> imports, final ImmutableSet<ModuleImport> includes) {
             super(name, latestRevision, imports, includes);
         }
 
-        private ModuleDependencyInfo(final String name,
-                final String latestRevision,
+        private ModuleDependencyInfo(final String name, final String latestRevision,
                 final ImmutableSet<ModuleImport> imports,
                 final ImmutableSet<ModuleImport> includes,
                 final Optional<SemVer> semVer) {
@@ -492,34 +331,27 @@ public abstract class YangModelDependencyInfo {
 
         @Override
         public String toString() {
-            return "Module [name=" + getName() + ", revision=" + getRevision() + ", semanticVersion="
-                    + getSemanticVersion().or(Module.DEFAULT_SEMANTIC_VERSION) + ", dependencies=" + getDependencies()
-                    + "]";
+            return "Module [name=" + getName() + ", revision=" + getRevision()
+            + ", semanticVersion=" + getSemanticVersion().orElse(null)
+            + ", dependencies=" + getDependencies()
+            + "]";
         }
     }
 
     /**
-     *
-     * Dependency information for submodule, also provides name for parent
-     * module.
-     *
+     * Dependency information for submodule, also provides name for parent module.
      */
-    public static final class SubmoduleDependencyInfo extends
-            YangModelDependencyInfo {
-
+    public static final class SubmoduleDependencyInfo extends YangModelDependencyInfo {
         private final String belongsTo;
 
-        private SubmoduleDependencyInfo(final String name,
-                final String latestRevision, final String belongsTo,
-                final ImmutableSet<ModuleImport> imports,
-                final ImmutableSet<ModuleImport> includes) {
+        private SubmoduleDependencyInfo(final String name, final String latestRevision, final String belongsTo,
+                final ImmutableSet<ModuleImport> imports, final ImmutableSet<ModuleImport> includes) {
             super(name, latestRevision, imports, includes);
             this.belongsTo = belongsTo;
         }
 
         /**
          * Returns name of parent module.
-         *
          */
         public String getParentModule() {
             return belongsTo;
@@ -534,39 +366,37 @@ public abstract class YangModelDependencyInfo {
     }
 
     /**
-     * Utility implementation of {@link ModuleImport} to be used by
-     * {@link YangModelDependencyInfo}.
-     *
+     * Utility implementation of {@link ModuleImport} to be used by {@link YangModelDependencyInfo}.
      */
     private static final class ModuleImportImpl implements ModuleImport {
 
-        private final Date revision;
+        private final Revision revision;
         private final SemVer semVer;
         private final String name;
 
-        public ModuleImportImpl(final String moduleName, final Date revision) {
-            this(moduleName, revision, Optional.absent());
+        ModuleImportImpl(final String moduleName, final Revision revision) {
+            this(moduleName, revision, null);
         }
 
-        public ModuleImportImpl(final String moduleName, final Date revision, final Optional<SemVer> semVer) {
-            this.name = Preconditions.checkNotNull(moduleName, "Module name must not be null.");
+        ModuleImportImpl(final String moduleName, @Nullable final Revision revision, @Nullable final SemVer semVer) {
+            this.name = requireNonNull(moduleName, "Module name must not be null.");
             this.revision = revision;
-            this.semVer = semVer.or(Module.DEFAULT_SEMANTIC_VERSION);
+            this.semVer = semVer;
         }
 
         @Override
         public String getModuleName() {
-            return this.name;
+            return name;
         }
 
         @Override
-        public Date getRevision() {
-            return this.revision;
+        public Optional<Revision> getRevision() {
+            return Optional.ofNullable(revision);
         }
 
         @Override
-        public SemVer getSemanticVersion() {
-            return this.semVer;
+        public Optional<SemVer> getSemanticVersion() {
+            return Optional.ofNullable(semVer);
         }
 
         @Override
@@ -620,7 +450,7 @@ public abstract class YangModelDependencyInfo {
         @Override
         public String toString() {
             return "ModuleImportImpl [name=" + name + ", revision="
-                    + QName.formattedRevision(revision) + ", semanticVersion=" + getSemanticVersion() + "]";
+                    + QName.formattedRevision(Optional.ofNullable(revision)) + ", semanticVersion=" + semVer + "]";
         }
     }
 }