Merge "BUG-648: add missing copy builders"
[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(final String name, final String formattedRevision, final ImmutableSet<ModuleImport> imports,
43             final 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(final Object obj) {
82         if (this == obj) {
83             return true;
84         }
85         if (obj == null) {
86             return false;
87         }
88         if (!(obj instanceof YangModelDependencyInfo)) {
89             return false;
90         }
91         YangModelDependencyInfo other = (YangModelDependencyInfo) obj;
92         if (formattedRevision == null) {
93             if (other.formattedRevision != null) {
94                 return false;
95             }
96         } else if (!formattedRevision.equals(other.formattedRevision)) {
97             return false;
98         }
99         if (name == null) {
100             if (other.name != null) {
101                 return false;
102             }
103         } else if (!name.equals(other.name)) {
104             return false;
105         }
106         return true;
107     }
108
109     public static YangModelDependencyInfo fromInputStream(final InputStream yangStream) {
110         YangContext yangContext = YangParserImpl.parseStreamWithoutErrorListeners(yangStream);
111
112         Optional<Module_stmtContext> moduleCtx = getFirstContext(yangContext, Module_stmtContext.class);
113         if (moduleCtx.isPresent()) {
114             return fromModuleContext(moduleCtx.get());
115         }
116         Optional<Submodule_stmtContext> submoduleCtx = getFirstContext(yangContext, Submodule_stmtContext.class);
117         if (submoduleCtx.isPresent()) {
118             return fromSubmoduleContext(submoduleCtx.get());
119         }
120         throw new IllegalArgumentException("Supplied stream is not valid yang file.");
121     }
122
123     private static YangModelDependencyInfo fromModuleContext(final Module_stmtContext module) {
124         String name = getArgumentString(module);
125         // String prefix =
126         // getArgumentString(module.module_header_stmts().prefix_stmt(0));
127         String namespace = getArgumentString(module.module_header_stmts().namespace_stmt(0));
128         String latestRevision = getLatestRevision(module.revision_stmts());
129         ImmutableSet<ModuleImport> imports = getImports(module.linkage_stmts().import_stmt());
130         ImmutableSet<ModuleImport> includes = getIncludes(module.linkage_stmts().include_stmt());
131
132         return new ModuleDependencyInfo(name, latestRevision, namespace, imports, includes);
133     }
134
135     private static ImmutableSet<ModuleImport> getImports(final List<Import_stmtContext> importStatements) {
136         ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
137         for (Import_stmtContext importStmt : importStatements) {
138             String moduleName = getArgumentString(importStmt);
139             Date revision = getRevision(importStmt.revision_date_stmt());
140             builder.add(new ModuleImportImpl(moduleName, revision));
141         }
142         return builder.build();
143     }
144
145     private static String getLatestRevision(final Revision_stmtsContext revision_stmts) {
146         List<Revision_stmtContext> revisions = revision_stmts.getRuleContexts(Revision_stmtContext.class);
147         String latestRevision = null;
148         for (Revision_stmtContext revisionStmt : revisions) {
149             String currentRevision = getArgumentString(revisionStmt);
150             if (latestRevision == null || latestRevision.compareTo(currentRevision) == -1) {
151                 latestRevision = currentRevision;
152             }
153         }
154         return latestRevision;
155     }
156
157     private static YangModelDependencyInfo fromSubmoduleContext(final Submodule_stmtContext submodule) {
158         String name = getArgumentString(submodule);
159         Belongs_to_stmtContext belongsToStmt = submodule.submodule_header_stmts().belongs_to_stmt(0);
160         String belongsTo = getArgumentString(belongsToStmt);
161
162         String latestRevision = getLatestRevision(submodule.revision_stmts());
163         ImmutableSet<ModuleImport> imports = getImports(submodule.linkage_stmts().import_stmt());
164         ImmutableSet<ModuleImport> includes = getIncludes(submodule.linkage_stmts().include_stmt());
165
166         return new SubmoduleDependencyInfo(name, latestRevision, belongsTo, imports, includes);
167     }
168
169     private static ImmutableSet<ModuleImport> getIncludes(final List<Include_stmtContext> importStatements) {
170         ImmutableSet.Builder<ModuleImport> builder = ImmutableSet.builder();
171         for (Include_stmtContext importStmt : importStatements) {
172             String moduleName = getArgumentString(importStmt);
173             Date revision = getRevision(importStmt.revision_date_stmt());
174             builder.add(new ModuleImportImpl(moduleName, revision));
175         }
176         return builder.build();
177     }
178
179     private static Date getRevision(final Revision_date_stmtContext revision_date_stmt) {
180         if (revision_date_stmt == null) {
181             return null;
182         }
183         String formatedDate = getArgumentString(revision_date_stmt);
184         return QName.parseRevision(formatedDate);
185     }
186
187     public static final class ModuleDependencyInfo extends YangModelDependencyInfo {
188
189         private ModuleDependencyInfo(final String name, final String latestRevision, final String namespace,
190                 final ImmutableSet<ModuleImport> imports, final ImmutableSet<ModuleImport> includes) {
191             super(name, latestRevision, imports, includes);
192         }
193
194         @Override
195         public String toString() {
196             return "Module [name=" + getName() + ", revision=" + getRevision()
197                     + ", dependencies=" + getDependencies() + "]";
198         }
199     }
200
201     public static final class SubmoduleDependencyInfo extends YangModelDependencyInfo {
202
203         private final String belongsTo;
204
205         public String getParentModule() {
206             return belongsTo;
207         }
208
209         private SubmoduleDependencyInfo(final String name, final String latestRevision, final String belongsTo,
210                 final ImmutableSet<ModuleImport> imports, final ImmutableSet<ModuleImport> includes) {
211             super(name, latestRevision, imports, includes);
212             this.belongsTo = belongsTo;
213         }
214
215         @Override
216         public String toString() {
217             return "Submodule [name=" + getName() + ", revision=" + getRevision()
218                     + ", dependencies=" + getDependencies() + "]";
219         }
220     }
221
222     private static final class ModuleImportImpl implements ModuleImport {
223
224         private final Date revision;
225         private final String name;
226
227         public ModuleImportImpl(final String moduleName, final Date revision) {
228             this.name = moduleName;
229             this.revision = revision;
230         }
231
232         @Override
233         public String getModuleName() {
234             return this.name;
235         }
236
237         @Override
238         public Date getRevision() {
239             return this.revision;
240         }
241
242         @Override
243         public String getPrefix() {
244             return null;
245         }
246
247         @Override
248         public int hashCode() {
249             final int prime = 31;
250             int result = 1;
251             result = prime * result + ((name == null) ? 0 : name.hashCode());
252             result = prime * result + ((revision == null) ? 0 : revision.hashCode());
253             return result;
254         }
255
256         @Override
257         public boolean equals(final Object obj) {
258             if (this == obj) {
259                 return true;
260             }
261             if (obj == null) {
262                 return false;
263             }
264             if (getClass() != obj.getClass()) {
265                 return false;
266             }
267             ModuleImportImpl other = (ModuleImportImpl) obj;
268             if (name == null) {
269                 if (other.name != null) {
270                     return false;
271                 }
272             } else if (!name.equals(other.name)) {
273                 return false;
274             }
275             if (revision == null) {
276                 if (other.revision != null) {
277                     return false;
278                 }
279             } else if (!revision.equals(other.revision)) {
280                 return false;
281             }
282             return true;
283         }
284
285         @Override
286         public String toString() {
287             return "ModuleImportImpl [name=" + name + ", revision=" + QName.formattedRevision(revision) + "]";
288         }
289     }
290 }