2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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/epl-v10.html
8 package org.opendaylight.controller.yang.model.parser.impl;
11 import java.io.FileInputStream;
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Calendar;
15 import java.util.Date;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.List;
21 import java.util.TreeMap;
23 import org.antlr.v4.runtime.ANTLRInputStream;
24 import org.antlr.v4.runtime.CommonTokenStream;
25 import org.antlr.v4.runtime.tree.ParseTree;
26 import org.antlr.v4.runtime.tree.ParseTreeWalker;
27 import org.opendaylight.controller.antlrv4.code.gen.YangLexer;
28 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
29 import org.opendaylight.controller.model.util.UnknownType;
30 import org.opendaylight.controller.yang.common.QName;
31 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
32 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
33 import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
34 import org.opendaylight.controller.yang.model.api.Module;
35 import org.opendaylight.controller.yang.model.api.ModuleImport;
36 import org.opendaylight.controller.yang.model.api.NotificationDefinition;
37 import org.opendaylight.controller.yang.model.api.RpcDefinition;
38 import org.opendaylight.controller.yang.model.api.SchemaContext;
39 import org.opendaylight.controller.yang.model.api.SchemaPath;
40 import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
41 import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder;
42 import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationTargetBuilder;
43 import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder;
44 import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder;
45 import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder;
46 import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder;
47 import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 public class YangModelParserImpl implements YangModelParser {
53 private static final Logger logger = LoggerFactory
54 .getLogger(YangModelParserImpl.class);
57 public Module parseYangModel(String yangFile) {
58 final Map<String, TreeMap<Date, ModuleBuilder>> modules = loadFiles(yangFile);
59 Set<Module> result = build(modules);
60 return result.iterator().next();
64 public Set<Module> parseYangModels(String... yangFiles) {
65 final Map<String, TreeMap<Date, ModuleBuilder>> modules = loadFiles(yangFiles);
66 Set<Module> result = build(modules);
71 public SchemaContext resolveSchemaContext(Set<Module> modules) {
72 return new SchemaContextImpl(modules);
75 private Set<Module> build(Map<String, TreeMap<Date, ModuleBuilder>> modules) {
77 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
78 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
79 ModuleBuilder moduleBuilder = childEntry.getValue();
80 validateBuilder(modules, moduleBuilder);
85 final Set<Module> result = new HashSet<Module>();
86 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
87 final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
88 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
89 ModuleBuilder moduleBuilder = childEntry.getValue();
90 modulesByRevision.put(childEntry.getKey(),moduleBuilder.build());
91 result.add(moduleBuilder.build());
98 private void validateBuilder(Map<String, TreeMap<Date, ModuleBuilder>> modules, ModuleBuilder builder) {
99 resolveTypedefs(modules, builder);
100 resolveAugments(modules, builder);
103 private void resolveTypedefs(Map<String, TreeMap<Date, ModuleBuilder>> modules, ModuleBuilder builder) {
104 Map<List<String>, TypeAwareBuilder> dirtyNodes = builder.getDirtyNodes();
105 if (dirtyNodes.size() == 0) {
108 for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes.entrySet()) {
109 TypeAwareBuilder tab = entry.getValue();
110 TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(modules,entry.getValue(), builder);
111 tab.setType(tdb.build());
116 private TypeDefinitionBuilder findTypeDefinitionBuilder(Map<String, TreeMap<Date, ModuleBuilder>> modules, TypeAwareBuilder typeBuilder, ModuleBuilder builder) {
117 UnknownType type = (UnknownType) typeBuilder.getType();
118 QName typeQName = type.getQName();
119 String typeName = type.getQName().getLocalName();
120 String prefix = typeQName.getPrefix();
122 ModuleBuilder dependentModuleBuilder;
123 if (prefix.equals(builder.getPrefix())) {
124 dependentModuleBuilder = builder;
126 ModuleImport dependentModuleImport = getDependentModuleImport(builder, prefix);
127 String dependentModuleName = dependentModuleImport.getModuleName();
128 Date dependentModuleRevision = dependentModuleImport.getRevision();
129 TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
130 if(dependentModuleRevision == null) {
131 dependentModuleBuilder = moduleBuildersByRevision.lastEntry().getValue();
133 dependentModuleBuilder = moduleBuildersByRevision.get(dependentModuleRevision);
137 final Set<TypeDefinitionBuilder> typedefs = dependentModuleBuilder.getModuleTypedefs();
139 TypeDefinitionBuilder lookedUpBuilder = null;
140 for (TypeDefinitionBuilder tdb : typedefs) {
141 QName qname = tdb.getQName();
142 if (qname.getLocalName().equals(typeName)) {
143 lookedUpBuilder = tdb;
148 if (lookedUpBuilder.getBaseType() instanceof UnknownType) {
149 return findTypeDefinitionBuilder(modules, (TypeAwareBuilder) lookedUpBuilder, dependentModuleBuilder);
151 return lookedUpBuilder;
155 private void resolveAugments(Map<String, TreeMap<Date, ModuleBuilder>> modules, ModuleBuilder builder) {
156 Set<AugmentationSchemaBuilder> augmentBuilders = builder.getAddedAugments();
158 Set<AugmentationSchema> augments = new HashSet<AugmentationSchema>();
159 for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) {
160 SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
161 String prefix = null;
162 List<String> augmentTargetPath = new ArrayList<String>();
163 for (QName pathPart : augmentTargetSchemaPath.getPath()) {
164 prefix = pathPart.getPrefix();
165 augmentTargetPath.add(pathPart.getLocalName());
167 ModuleImport dependentModuleImport = getDependentModuleImport(builder, prefix);
168 String dependentModuleName = dependentModuleImport.getModuleName();
169 augmentTargetPath.add(0, dependentModuleName);
171 Date dependentModuleRevision = dependentModuleImport.getRevision();
173 TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
174 ModuleBuilder dependentModule;
175 if(dependentModuleRevision == null) {
176 dependentModule = moduleBuildersByRevision.lastEntry().getValue();
178 dependentModule = moduleBuildersByRevision.get(dependentModuleRevision);
181 AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule.getNode(augmentTargetPath);
182 AugmentationSchema result = augmentBuilder.build();
183 augmentTarget.addAugmentation(result);
184 fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget);
185 augments.add(result);
187 builder.setAugmentations(augments);
190 private void fillAugmentTarget(AugmentationSchemaBuilder augment,
191 ChildNodeBuilder target) {
192 for (DataSchemaNodeBuilder builder : augment.getChildNodes()) {
193 builder.setAugmenting(true);
194 target.addChildNode(builder);
198 private Map<String, TreeMap<Date, ModuleBuilder>> loadFiles(String... yangFiles) {
199 final Map<String, TreeMap<Date, ModuleBuilder>> modules = new HashMap<String, TreeMap<Date, ModuleBuilder>>();
201 final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl();
202 final ParseTreeWalker walker = new ParseTreeWalker();
204 List<ParseTree> trees = parseFiles(yangFiles);
206 ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
208 for (int i = 0; i < trees.size(); i++) {
209 walker.walk(yangModelParser, trees.get(i));
210 builders[i] = yangModelParser.getModuleBuilder();
213 for (ModuleBuilder builder : builders) {
214 final String builderName = builder.getName();
215 Date builderRevision = builder.getRevision();
216 if(builderRevision == null) {
217 builderRevision = createEpochTime();
220 TreeMap<Date, ModuleBuilder> builderByRevision = modules.get(builderName);
221 if (builderByRevision == null) {
222 builderByRevision = new TreeMap<Date, ModuleBuilder>();
224 builderByRevision.put(builderRevision, builder);
226 modules.put(builderName, builderByRevision);
231 private List<ParseTree> parseFiles(String... yangFileNames) {
232 List<ParseTree> trees = new ArrayList<ParseTree>();
233 for (String fileName : yangFileNames) {
234 trees.add(parseFile(fileName));
239 private ParseTree parseFile(String yangFileName) {
240 ParseTree result = null;
242 final File yangFile = new File(yangFileName);
243 final FileInputStream inStream = new FileInputStream(yangFile);
244 final ANTLRInputStream input = new ANTLRInputStream(inStream);
245 final YangLexer lexer = new YangLexer(input);
246 final CommonTokenStream tokens = new CommonTokenStream(lexer);
247 final YangParser parser = new YangParser(tokens);
248 result = parser.yang();
249 } catch (IOException e) {
250 logger.warn("Exception while reading yang file: " + yangFileName, e);
255 private ModuleImport getDependentModuleImport(ModuleBuilder builder, String prefix) {
256 ModuleImport moduleImport = null;
257 for (ModuleImport mi : builder.getModuleImports()) {
258 if (mi.getPrefix().equals(prefix)) {
266 private Date createEpochTime() {
267 Calendar c = Calendar.getInstance();
268 c.setTimeInMillis(0);
272 private static class SchemaContextImpl implements SchemaContext {
273 private final Set<Module> modules;
275 private SchemaContextImpl(Set<Module> modules) {
276 this.modules = modules;
280 public Set<DataSchemaNode> getDataDefinitions() {
281 final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();
282 for (Module m : modules) {
283 dataDefs.addAll(m.getChildNodes());
289 public Set<Module> getModules() {
294 public Set<NotificationDefinition> getNotifications() {
295 final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
296 for (Module m : modules) {
297 notifications.addAll(m.getNotifications());
299 return notifications;
303 public Set<RpcDefinition> getOperations() {
304 final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
305 for (Module m : modules) {
306 rpcs.addAll(m.getRpcs());
312 public Set<ExtensionDefinition> getExtensions() {
313 final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();
314 for (Module m : modules) {
315 extensions.addAll(m.getExtensionSchemaNodes());