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