Added support for parsing submodules & added dependency utility parser
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / util / YangModelDependencyInfo.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/eplv10.html
7  */
8 package org.opendaylight.yangtools.yang.parser.impl.util;
9
10 import static org.opendaylight.yangtools.yang.parser.util.ParserListenerUtils.getArgumentString;
11 import static org.opendaylight.yangtools.yang.parser.util.ParserListenerUtils.getFirstContext;
12
13 import java.io.InputStream;
14 import java.util.Date;
15 import java.util.List;
16
17 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
18 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Import_stmtContext;
19 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Include_stmtContext;
20 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Module_stmtContext;
21 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
22 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Revision_stmtContext;
23 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Revision_stmtsContext;
24 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Submodule_stmtContext;
25 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.YangContext;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
28 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
29
30 import com.google.common.base.Optional;
31 import com.google.common.collect.ImmutableSet;
32
33 public abstract class YangModelDependencyInfo {
34
35     private final String name;
36     private final String formattedRevision;
37     private final Date revision;
38     private final ImmutableSet<ModuleImport> submoduleIncludes;
39     private final ImmutableSet<ModuleImport> moduleImports;
40     private final ImmutableSet<ModuleImport> dependencies;
41
42     public YangModelDependencyInfo(String name, String formattedRevision, ImmutableSet<ModuleImport> imports,
43             ImmutableSet<ModuleImport> includes) {
44         this.name = name;
45         this.formattedRevision = formattedRevision;
46         this.revision = QName.parseRevision(formattedRevision);
47         this.moduleImports = imports;
48         this.submoduleIncludes = includes;
49         this.dependencies = ImmutableSet.<ModuleImport> builder() //
50                 .addAll(moduleImports) //
51                 .addAll(submoduleIncludes) //
52                 .build();
53     }
54
55     public ImmutableSet<ModuleImport> getDependencies() {
56         return dependencies;
57     }
58
59     public String getName() {
60         return name;
61     }
62
63     public String getFormattedRevision() {
64         return formattedRevision;
65     }
66
67     public Date getRevision() {
68         return revision;
69     }
70
71     @Override
72     public int hashCode() {
73         final int prime = 31;
74         int result = 1;
75         result = prime * result + ((formattedRevision == null) ? 0 : formattedRevision.hashCode());
76         result = prime * result + ((name == null) ? 0 : name.hashCode());
77         return result;
78     }
79
80     @Override
81     public boolean equals(Object obj) {
82         if (this == obj)
83             return true;
84         if (obj == null)
85             return false;
86         if (!(obj instanceof YangModelDependencyInfo))
87             return false;
88         YangModelDependencyInfo other = (YangModelDependencyInfo) obj;
89         if (formattedRevision == null) {
90             if (other.formattedRevision != null)
91                 return false;
92         } else if (!formattedRevision.equals(other.formattedRevision))
93             return false;
94         if (name == null) {
95             if (other.name != null)
96                 return false;
97         } else if (!name.equals(other.name))
98             return false;
99         return true;
100     }
101
102     public static YangModelDependencyInfo fromInputStream(InputStream yangStream) {
103         YangContext yangContext = YangParserImpl.parseStreamWithoutErrorListeners(yangStream);
104
105         Optional<Module_stmtContext> moduleCtx = getFirstContext(yangContext, Module_stmtContext.class);
106         if (moduleCtx.isPresent()) {
107             return fromModuleContext(moduleCtx.get());
108         }
109         Optional<Submodule_stmtContext> submoduleCtx = getFirstContext(yangContext, Submodule_stmtContext.class);
110         if (submoduleCtx.isPresent()) {
111             return fromSubmoduleContext(submoduleCtx.get());
112         }
113         throw new IllegalArgumentException("Supplied stream is not valid yang file.");
114     }
115
116     private static YangModelDependencyInfo fromModuleContext(Module_stmtContext module) {
117         String name = getArgumentString(module);
118         // String prefix =
119         // getArgumentString(module.module_header_stmts().prefix_stmt(0));
120         String namespace = getArgumentString(module.module_header_stmts().namespace_stmt(0));
121         String latestRevision = getLatestRevision(module.revision_stmts());
122         ImmutableSet<ModuleImport> imports = getImports(module.linkage_stmts().import_stmt());
123         ImmutableSet<ModuleImport> includes = getIncludes(module.linkage_stmts().include_stmt());
124
125         return new ModuleDependencyInfo(name, latestRevision, namespace, imports, includes);
126     }
127
128     private static ImmutableSet<ModuleImport> getImports(List<Import_stmtContext> importStatements) {
129         ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
130         for (Import_stmtContext importStmt : importStatements) {
131             String moduleName = getArgumentString(importStmt);
132             Date revision = getRevision(importStmt.revision_date_stmt());
133             String prefix = getArgumentString(importStmt.prefix_stmt());
134             builder.add(new ModuleImportImpl(moduleName, revision));
135         }
136         return builder.build();
137     }
138
139     private static String getLatestRevision(Revision_stmtsContext revision_stmts) {
140         List<Revision_stmtContext> revisions = revision_stmts.getRuleContexts(Revision_stmtContext.class);
141         String latestRevision = null;
142         for (Revision_stmtContext revisionStmt : revisions) {
143             String currentRevision = getArgumentString(revisionStmt);
144             if (latestRevision == null || latestRevision.compareTo(currentRevision) == 1) {
145                 latestRevision = currentRevision;
146             }
147         }
148         return latestRevision;
149     }
150
151     private static YangModelDependencyInfo fromSubmoduleContext(Submodule_stmtContext submodule) {
152         String name = getArgumentString(submodule);
153         Belongs_to_stmtContext belongsToStmt = submodule.submodule_header_stmts().belongs_to_stmt(0);
154         String belongsTo = getArgumentString(belongsToStmt);
155
156         String latestRevision = getLatestRevision(submodule.revision_stmts());
157         ImmutableSet<ModuleImport> imports = getImports(submodule.linkage_stmts().import_stmt());
158         ImmutableSet<ModuleImport> includes = getIncludes(submodule.linkage_stmts().include_stmt());
159
160         return new SubmoduleDependencyInfo(name, latestRevision, belongsTo, imports, includes);
161     }
162
163     private static ImmutableSet<ModuleImport> getIncludes(List<Include_stmtContext> importStatements) {
164         ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
165         for (Include_stmtContext importStmt : importStatements) {
166             String moduleName = getArgumentString(importStmt);
167             Date revision = getRevision(importStmt.revision_date_stmt());
168             builder.add(new ModuleImportImpl(moduleName, revision));
169         }
170         return builder.build();
171     }
172
173     private static Date getRevision(Revision_date_stmtContext revision_date_stmt) {
174         if (revision_date_stmt == null) {
175             return null;
176         }
177         String formatedDate = getArgumentString(revision_date_stmt);
178         return QName.parseRevision(formatedDate);
179     }
180
181     public static final class ModuleDependencyInfo extends YangModelDependencyInfo {
182
183         private ModuleDependencyInfo(String name, String latestRevision, String namespace,
184                 ImmutableSet<ModuleImport> imports, ImmutableSet<ModuleImport> includes) {
185             super(name, latestRevision, imports, includes);
186         }
187
188         @Override
189         public String toString() {
190             return "Module [name=" + getName() + ", revision=" + getRevision()
191                     + ", dependencies=" + getDependencies() + "]";
192         }
193
194     }
195
196     public static final class SubmoduleDependencyInfo extends YangModelDependencyInfo {
197
198         private final String belongsTo;
199
200         public String getParentModule() {
201             return belongsTo;
202         }
203
204         private SubmoduleDependencyInfo(String name, String latestRevision, String belongsTo,
205                 ImmutableSet<ModuleImport> imports, ImmutableSet<ModuleImport> includes) {
206             super(name, latestRevision, imports, includes);
207             this.belongsTo = belongsTo;
208         }
209         
210         @Override
211         public String toString() {
212             return "Submodule [name=" + getName() + ", revision=" + getRevision()
213                     + ", dependencies=" + getDependencies() + "]";
214         }
215
216     }
217
218     private static final class ModuleImportImpl implements ModuleImport {
219
220         private Date revision;
221         private String name;
222
223         public ModuleImportImpl(String moduleName, Date revision) {
224             this.name = moduleName;
225             this.revision = revision;
226         }
227
228         @Override
229         public String getModuleName() {
230             return this.name;
231         }
232
233         @Override
234         public Date getRevision() {
235             return this.revision;
236         }
237
238         @Override
239         public String getPrefix() {
240             return null;
241         }
242
243         @Override
244         public int hashCode() {
245             final int prime = 31;
246             int result = 1;
247             result = prime * result + ((name == null) ? 0 : name.hashCode());
248             result = prime * result + ((revision == null) ? 0 : revision.hashCode());
249             return result;
250         }
251
252         @Override
253         public boolean equals(Object obj) {
254             if (this == obj)
255                 return true;
256             if (obj == null)
257                 return false;
258             if (getClass() != obj.getClass())
259                 return false;
260             ModuleImportImpl other = (ModuleImportImpl) obj;
261             if (name == null) {
262                 if (other.name != null)
263                     return false;
264             } else if (!name.equals(other.name))
265                 return false;
266             if (revision == null) {
267                 if (other.revision != null)
268                     return false;
269             } else if (!revision.equals(other.revision))
270                 return false;
271             return true;
272         }
273
274         @Override
275         public String toString() {
276             return "ModuleImportImpl [name=" + name + ", revision=" + QName.formattedRevision(revision) + "]";
277         }
278         
279         
280     }
281 }