Initial opendaylight infrastructure commit!!
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / model / parser / builder / YangModelBuilder.java
1 /*\r
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
3  *\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
7  */\r
8 package org.opendaylight.controller.model.parser.builder;\r
9 \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
19 \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
40 \r
41 public class YangModelBuilder implements Builder {\r
42 \r
43     private static final Logger logger = LoggerFactory\r
44             .getLogger(YangModelBuilder.class);\r
45 \r
46     private final Map<String, ModuleBuilder> modules = new HashMap<String, ModuleBuilder>();\r
47 \r
48     public YangModelBuilder(String... yangFiles) {\r
49         final YangModelParserImpl yangModelParser = new YangModelParserImpl();\r
50         final ParseTreeWalker walker = new ParseTreeWalker();\r
51 \r
52         List<ParseTree> trees = parseYangFiles(yangFiles);\r
53 \r
54         ModuleBuilder[] builders = new ModuleBuilder[trees.size()];\r
55 \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
59         }\r
60 \r
61         for (ModuleBuilder builder : builders) {\r
62             final String builderName = builder.getName();\r
63             modules.put(builderName, builder);\r
64         }\r
65     }\r
66 \r
67     @Override\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
73         }\r
74         return builtModules;\r
75     }\r
76 \r
77     private void validateBuilder(ModuleBuilder builder) {\r
78         resolveTypedefs(builder);\r
79         resolveAugments(builder);\r
80     }\r
81 \r
82     private void resolveTypedefs(ModuleBuilder builder) {\r
83         Map<List<String>, TypeAwareBuilder> dirtyNodes = builder\r
84                 .getDirtyNodes();\r
85         if (dirtyNodes.size() == 0) {\r
86             return;\r
87         } else {\r
88             for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes\r
89                     .entrySet()) {\r
90                 TypeAwareBuilder tab = entry.getValue();\r
91                 TypeDefinitionBuilder tdb = findTypeAwareBuilder(\r
92                         entry.getValue(), builder);\r
93                 tab.setType(tdb.build());\r
94             }\r
95         }\r
96     }\r
97 \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
104 \r
105         ModuleBuilder dependentModuleBuilder;\r
106         if (prefix.equals(builder.getPrefix())) {\r
107             dependentModuleBuilder = builder;\r
108         } else {\r
109             String dependentModuleName = getDependentModuleName(builder, prefix);\r
110             dependentModuleBuilder = modules.get(dependentModuleName);\r
111         }\r
112 \r
113         Set<TypeDefinitionBuilder> typedefs = dependentModuleBuilder\r
114                 .getModuleTypedefs();\r
115 \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
121                 break;\r
122             }\r
123         }\r
124 \r
125         if (lookedUpBuilder.getBaseType() instanceof UnknownType) {\r
126             return findTypeAwareBuilder((TypeAwareBuilder) lookedUpBuilder,\r
127                     dependentModuleBuilder);\r
128         } else {\r
129             return lookedUpBuilder;\r
130         }\r
131     }\r
132 \r
133     private void resolveAugments(ModuleBuilder builder) {\r
134         Set<AugmentationSchemaBuilder> augmentBuilders = builder\r
135                 .getAddedAugments();\r
136 \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
145             }\r
146             String dependentModuleName = getDependentModuleName(builder, prefix);\r
147             augmentTargetPath.add(0, dependentModuleName);\r
148 \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
155         }\r
156         builder.setAugmentations(augments);\r
157     }\r
158 \r
159     private List<ParseTree> parseYangFiles(String... yangFiles) {\r
160         List<ParseTree> trees = new ArrayList<ParseTree>();\r
161         File yangFile;\r
162         for (String fileName : yangFiles) {\r
163             try {\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
173             }\r
174         }\r
175         return trees;\r
176     }\r
177 \r
178     /**\r
179      * Returns name of dependent module based on given prefix.\r
180      * \r
181      * @param builder\r
182      *            current builder which contains import\r
183      * @param prefix\r
184      *            prefix of dependent module used in current builder\r
185      * @return name of dependent module\r
186      */\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
191                 moduleImport = mi;\r
192                 break;\r
193             }\r
194         }\r
195         return moduleImport.getModuleName();\r
196     }\r
197 \r
198 }\r