2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
8 package org.opendaylight.controller.model.parser.builder;
\r
10 import java.io.File;
\r
11 import java.io.FileInputStream;
\r
12 import java.io.IOException;
\r
13 import java.util.ArrayList;
\r
14 import java.util.HashMap;
\r
15 import java.util.HashSet;
\r
16 import java.util.List;
\r
17 import java.util.Map;
\r
18 import java.util.Set;
\r
20 import org.antlr.v4.runtime.ANTLRInputStream;
\r
21 import org.antlr.v4.runtime.CommonTokenStream;
\r
22 import org.antlr.v4.runtime.tree.ParseTree;
\r
23 import org.antlr.v4.runtime.tree.ParseTreeWalker;
\r
24 import org.opendaylight.controller.antlrv4.code.gen.YangLexer;
\r
25 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
\r
26 import org.opendaylight.controller.model.parser.api.AugmentationSchemaBuilder;
\r
27 import org.opendaylight.controller.model.parser.api.AugmentationTargetBuilder;
\r
28 import org.opendaylight.controller.model.parser.api.Builder;
\r
29 import org.opendaylight.controller.model.parser.api.TypeAwareBuilder;
\r
30 import org.opendaylight.controller.model.parser.api.TypeDefinitionBuilder;
\r
31 import org.opendaylight.controller.model.parser.impl.YangModelParserImpl;
\r
32 import org.opendaylight.controller.model.util.UnknownType;
\r
33 import org.opendaylight.controller.yang.common.QName;
\r
34 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
\r
35 import org.opendaylight.controller.yang.model.api.Module;
\r
36 import org.opendaylight.controller.yang.model.api.ModuleImport;
\r
37 import org.opendaylight.controller.yang.model.api.SchemaPath;
\r
38 import org.slf4j.Logger;
\r
39 import org.slf4j.LoggerFactory;
\r
41 public class YangModelBuilder implements Builder {
\r
43 private static final Logger logger = LoggerFactory
\r
44 .getLogger(YangModelBuilder.class);
\r
46 private final Map<String, ModuleBuilder> modules = new HashMap<String, ModuleBuilder>();
\r
48 public YangModelBuilder(String... yangFiles) {
\r
49 final YangModelParserImpl yangModelParser = new YangModelParserImpl();
\r
50 final ParseTreeWalker walker = new ParseTreeWalker();
\r
52 List<ParseTree> trees = parseYangFiles(yangFiles);
\r
54 ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
\r
56 for (int i = 0; i < trees.size(); i++) {
\r
57 walker.walk(yangModelParser, trees.get(i));
\r
58 builders[i] = yangModelParser.getModuleBuilder();
\r
61 for (ModuleBuilder builder : builders) {
\r
62 final String builderName = builder.getName();
\r
63 modules.put(builderName, builder);
\r
68 public Map<String, Module> build() {
\r
69 Map<String, Module> builtModules = new HashMap<String, Module>();
\r
70 for (ModuleBuilder builder : modules.values()) {
\r
71 validateBuilder(builder);
\r
72 builtModules.put(builder.getName(), builder.build());
\r
74 return builtModules;
\r
77 private void validateBuilder(ModuleBuilder builder) {
\r
78 resolveTypedefs(builder);
\r
79 resolveAugments(builder);
\r
82 private void resolveTypedefs(ModuleBuilder builder) {
\r
83 Map<List<String>, TypeAwareBuilder> dirtyNodes = builder
\r
85 if (dirtyNodes.size() == 0) {
\r
88 for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes
\r
90 TypeAwareBuilder tab = entry.getValue();
\r
91 TypeDefinitionBuilder tdb = findTypeAwareBuilder(
\r
92 entry.getValue(), builder);
\r
93 tab.setType(tdb.build());
\r
98 private TypeDefinitionBuilder findTypeAwareBuilder(
\r
99 TypeAwareBuilder typeBuilder, ModuleBuilder builder) {
\r
100 UnknownType type = (UnknownType) typeBuilder.getType();
\r
101 QName typeQName = type.getQName();
\r
102 String typeName = type.getQName().getLocalName();
\r
103 String prefix = typeQName.getPrefix();
\r
105 ModuleBuilder dependentModuleBuilder;
\r
106 if (prefix.equals(builder.getPrefix())) {
\r
107 dependentModuleBuilder = builder;
\r
109 String dependentModuleName = getDependentModuleName(builder, prefix);
\r
110 dependentModuleBuilder = modules.get(dependentModuleName);
\r
113 Set<TypeDefinitionBuilder> typedefs = dependentModuleBuilder
\r
114 .getModuleTypedefs();
\r
116 TypeDefinitionBuilder lookedUpBuilder = null;
\r
117 for (TypeDefinitionBuilder tdb : typedefs) {
\r
118 QName qname = tdb.getQName();
\r
119 if (qname.getLocalName().equals(typeName)) {
\r
120 lookedUpBuilder = tdb;
\r
125 if (lookedUpBuilder.getBaseType() instanceof UnknownType) {
\r
126 return findTypeAwareBuilder((TypeAwareBuilder) lookedUpBuilder,
\r
127 dependentModuleBuilder);
\r
129 return lookedUpBuilder;
\r
133 private void resolveAugments(ModuleBuilder builder) {
\r
134 Set<AugmentationSchemaBuilder> augmentBuilders = builder
\r
135 .getAddedAugments();
\r
137 Set<AugmentationSchema> augments = new HashSet<AugmentationSchema>();
\r
138 for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) {
\r
139 SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
\r
140 String prefix = null;
\r
141 List<String> augmentTargetPath = new ArrayList<String>();
\r
142 for (QName pathPart : augmentTargetSchemaPath.getPath()) {
\r
143 prefix = pathPart.getPrefix();
\r
144 augmentTargetPath.add(pathPart.getLocalName());
\r
146 String dependentModuleName = getDependentModuleName(builder, prefix);
\r
147 augmentTargetPath.add(0, dependentModuleName);
\r
149 ModuleBuilder dependentModule = modules.get(dependentModuleName);
\r
150 AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule
\r
151 .getNode(augmentTargetPath);
\r
152 AugmentationSchema result = augmentBuilder.build();
\r
153 augmentTarget.addAugmentation(result);
\r
154 augments.add(result);
\r
156 builder.setAugmentations(augments);
\r
159 private List<ParseTree> parseYangFiles(String... yangFiles) {
\r
160 List<ParseTree> trees = new ArrayList<ParseTree>();
\r
162 for (String fileName : yangFiles) {
\r
164 yangFile = new File(fileName);
\r
165 FileInputStream inStream = new FileInputStream(yangFile);
\r
166 ANTLRInputStream input = new ANTLRInputStream(inStream);
\r
167 final YangLexer lexer = new YangLexer(input);
\r
168 final CommonTokenStream tokens = new CommonTokenStream(lexer);
\r
169 final YangParser parser = new YangParser(tokens);
\r
170 trees.add(parser.yang());
\r
171 } catch (IOException e) {
\r
172 logger.warn("Exception while reading yang file: " + fileName, e);
\r
179 * Returns name of dependent module based on given prefix.
\r
182 * current builder which contains import
\r
184 * prefix of dependent module used in current builder
\r
185 * @return name of dependent module
\r
187 private String getDependentModuleName(ModuleBuilder builder, String prefix) {
\r
188 ModuleImport moduleImport = null;
\r
189 for (ModuleImport mi : builder.getModuleImports()) {
\r
190 if (mi.getPrefix().equals(prefix)) {
\r
195 return moduleImport.getModuleName();
\r