Fixed validation bug of YANG import statement
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / model / parser / impl / YangModelParserListenerImpl.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.yang.model.parser.impl;\r
9 \r
10 import static org.opendaylight.controller.yang.model.parser.util.YangModelBuilderUtil.*;\r
11 \r
12 import java.net.URI;\r
13 import java.text.DateFormat;\r
14 import java.text.ParseException;\r
15 import java.text.SimpleDateFormat;\r
16 import java.util.ArrayList;\r
17 import java.util.Collections;\r
18 import java.util.Date;\r
19 import java.util.List;\r
20 import java.util.Stack;\r
21 \r
22 import org.antlr.v4.runtime.tree.ParseTree;\r
23 import org.opendaylight.controller.antlrv4.code.gen.YangParser;\r
24 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;\r
25 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;\r
26 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Contact_stmtContext;\r
27 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext;\r
28 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext;\r
29 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;\r
30 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext;\r
31 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_not_supported_stmtContext;\r
32 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_replace_stmtContext;\r
33 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;\r
34 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext;\r
35 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_list_stmtContext;\r
36 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext;\r
37 import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext;\r
38 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;\r
39 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;\r
40 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext;\r
41 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Organization_stmtContext;\r
42 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;\r
43 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Presence_stmtContext;\r
44 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext;\r
45 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;\r
46 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;\r
47 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext;\r
48 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext;\r
49 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext;\r
50 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;\r
51 import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener;\r
52 import org.opendaylight.controller.yang.common.QName;\r
53 import org.opendaylight.controller.yang.model.api.Status;\r
54 import org.opendaylight.controller.yang.model.api.TypeDefinition;\r
55 import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder;\r
56 import org.opendaylight.controller.yang.model.parser.builder.api.GroupingBuilder;\r
57 import org.opendaylight.controller.yang.model.parser.builder.impl.ContainerSchemaNodeBuilder;\r
58 import org.opendaylight.controller.yang.model.parser.builder.impl.DeviationBuilder;\r
59 import org.opendaylight.controller.yang.model.parser.builder.impl.ExtensionBuilder;\r
60 import org.opendaylight.controller.yang.model.parser.builder.impl.FeatureBuilder;\r
61 import org.opendaylight.controller.yang.model.parser.builder.impl.IdentitySchemaNodeBuilder;\r
62 import org.opendaylight.controller.yang.model.parser.builder.impl.LeafListSchemaNodeBuilder;\r
63 import org.opendaylight.controller.yang.model.parser.builder.impl.LeafSchemaNodeBuilder;\r
64 import org.opendaylight.controller.yang.model.parser.builder.impl.ListSchemaNodeBuilder;\r
65 import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder;\r
66 import org.opendaylight.controller.yang.model.parser.builder.impl.NotificationBuilder;\r
67 import org.opendaylight.controller.yang.model.parser.builder.impl.RpcDefinitionBuilder;\r
68 import org.opendaylight.controller.yang.model.parser.builder.impl.TypedefBuilder;\r
69 import org.opendaylight.controller.yang.model.parser.builder.impl.UnknownSchemaNodeBuilder;\r
70 import org.opendaylight.controller.yang.model.util.YangTypesConverter;\r
71 import org.slf4j.Logger;\r
72 import org.slf4j.LoggerFactory;\r
73 \r
74 final class YangModelParserListenerImpl extends YangParserBaseListener {\r
75 \r
76     private static final Logger logger = LoggerFactory\r
77             .getLogger(YangModelParserListenerImpl.class);\r
78 \r
79     private ModuleBuilder moduleBuilder;\r
80 \r
81     private String moduleName;\r
82     private URI namespace;\r
83     private String yangModelPrefix;\r
84     private Date revision = new Date(0L);\r
85 \r
86     final static DateFormat simpleDateFormat = new SimpleDateFormat(\r
87             "yyyy-mm-dd");\r
88     private final Stack<String> actualPath = new Stack<String>();\r
89 \r
90     @Override\r
91     public void enterModule_stmt(YangParser.Module_stmtContext ctx) {\r
92         moduleName = stringFromNode(ctx);\r
93         actualPath.push(moduleName);\r
94         moduleBuilder = new ModuleBuilder(moduleName);\r
95 \r
96         String description = null;\r
97         String reference = null;\r
98 \r
99         for (int i = 0; i < ctx.getChildCount(); i++) {\r
100             ParseTree child = ctx.getChild(i);\r
101             if (child instanceof Description_stmtContext) {\r
102                 description = stringFromNode(child);\r
103             } else if (child instanceof Reference_stmtContext) {\r
104                 reference = stringFromNode(child);\r
105             } else {\r
106                 if (description != null && reference != null) {\r
107                     break;\r
108                 }\r
109             }\r
110         }\r
111         moduleBuilder.setDescription(description);\r
112         moduleBuilder.setReference(reference);\r
113     }\r
114 \r
115     @Override\r
116     public void exitModule_stmt(YangParser.Module_stmtContext ctx) {\r
117         final String moduleName = actualPath.pop();\r
118         logger.debug("Exiting module " + moduleName);\r
119     }\r
120 \r
121     @Override\r
122     public void enterModule_header_stmts(final Module_header_stmtsContext ctx) {\r
123         super.enterModule_header_stmts(ctx);\r
124 \r
125         String yangVersion = null;\r
126         for (int i = 0; i < ctx.getChildCount(); ++i) {\r
127             final ParseTree treeNode = ctx.getChild(i);\r
128             if (treeNode instanceof Namespace_stmtContext) {\r
129                 final String namespaceStr = stringFromNode(treeNode);\r
130                 namespace = URI.create(namespaceStr);\r
131                 moduleBuilder.setNamespace(namespace);\r
132             } else if (treeNode instanceof Prefix_stmtContext) {\r
133                 yangModelPrefix = stringFromNode(treeNode);\r
134                 moduleBuilder.setPrefix(yangModelPrefix);\r
135             } else if (treeNode instanceof Yang_version_stmtContext) {\r
136                 yangVersion = stringFromNode(treeNode);\r
137             }\r
138         }\r
139 \r
140         if (yangVersion == null) {\r
141             yangVersion = "1";\r
142         }\r
143         moduleBuilder.setYangVersion(yangVersion);\r
144     }\r
145 \r
146     @Override\r
147     public void enterMeta_stmts(YangParser.Meta_stmtsContext ctx) {\r
148         for (int i = 0; i < ctx.getChildCount(); i++) {\r
149             ParseTree child = ctx.getChild(i);\r
150             if (child instanceof Organization_stmtContext) {\r
151                 final String organization = stringFromNode(child);\r
152                 moduleBuilder.setOrganization(organization);\r
153             } else if (child instanceof Contact_stmtContext) {\r
154                 final String contact = stringFromNode(child);\r
155                 moduleBuilder.setContact(contact);\r
156             } else if (child instanceof Description_stmtContext) {\r
157                 final String description = stringFromNode(child);\r
158                 moduleBuilder.setDescription(description);\r
159             } else if (child instanceof Reference_stmtContext) {\r
160                 final String reference = stringFromNode(child);\r
161                 moduleBuilder.setReference(reference);\r
162             }\r
163         }\r
164     }\r
165 \r
166     @Override\r
167     public void exitSubmodule_header_stmts(\r
168             YangParser.Submodule_header_stmtsContext ctx) {\r
169         final String submodule = actualPath.pop();\r
170         logger.debug("exiting submodule " + submodule);\r
171     }\r
172 \r
173     @Override\r
174     public void enterRevision_stmts(Revision_stmtsContext ctx) {\r
175         if (ctx != null) {\r
176             for (int i = 0; i < ctx.getChildCount(); ++i) {\r
177                 final ParseTree treeNode = ctx.getChild(i);\r
178                 if (treeNode instanceof Revision_stmtContext) {\r
179                     updateRevisionForRevisionStatement(treeNode);\r
180                 }\r
181             }\r
182         }\r
183     }\r
184 \r
185     private void updateRevisionForRevisionStatement(final ParseTree treeNode) {\r
186         final String revisionDateStr = stringFromNode(treeNode);\r
187         try {\r
188             final Date revision = simpleDateFormat.parse(revisionDateStr);\r
189             if ((revision != null) && (this.revision.compareTo(revision) < 0)) {\r
190                 this.revision = revision;\r
191                 moduleBuilder.setRevision(this.revision);\r
192                 for (int i = 0; i < treeNode.getChildCount(); ++i) {\r
193                     ParseTree child = treeNode.getChild(i);\r
194                     if (child instanceof Reference_stmtContext) {\r
195                         moduleBuilder.setReference(stringFromNode(child));\r
196                     }\r
197                 }\r
198             }\r
199         } catch (ParseException e) {\r
200             final String message = "Failed to parse revision string: "\r
201                     + revisionDateStr;\r
202             logger.warn(message);\r
203         }\r
204     }\r
205 \r
206     @Override\r
207     public void enterImport_stmt(Import_stmtContext ctx) {\r
208         super.enterImport_stmt(ctx);\r
209 \r
210         final String importName = stringFromNode(ctx);\r
211         String importPrefix = null;\r
212         Date importRevision = null;\r
213 \r
214         for (int i = 0; i < ctx.getChildCount(); ++i) {\r
215             final ParseTree treeNode = ctx.getChild(i);\r
216             if (treeNode instanceof Prefix_stmtContext) {\r
217                 importPrefix = stringFromNode(treeNode);\r
218             }\r
219             if (treeNode instanceof Revision_date_stmtContext) {\r
220                 String importRevisionStr = stringFromNode(treeNode);\r
221                 try {\r
222                     importRevision = simpleDateFormat.parse(importRevisionStr);\r
223                 } catch(ParseException e) {\r
224                     logger.warn("Failed to parse import revision-date: "+ importRevisionStr);\r
225                 }\r
226             }\r
227         }\r
228         moduleBuilder.addModuleImport(importName, importRevision, importPrefix);\r
229     }\r
230 \r
231     @Override\r
232     public void enterAugment_stmt(YangParser.Augment_stmtContext ctx) {\r
233         final String augmentPath = stringFromNode(ctx);\r
234         AugmentationSchemaBuilder builder = moduleBuilder.addAugment(\r
235                 augmentPath, getActualPath());\r
236         updatePath(augmentPath);\r
237 \r
238         for (int i = 0; i < ctx.getChildCount(); i++) {\r
239             ParseTree child = ctx.getChild(i);\r
240             if (child instanceof Description_stmtContext) {\r
241                 String desc = stringFromNode(child);\r
242                 builder.setDescription(desc);\r
243             } else if (child instanceof Reference_stmtContext) {\r
244                 String ref = stringFromNode(child);\r
245                 builder.setReference(ref);\r
246             } else if (child instanceof Status_stmtContext) {\r
247                 Status status = parseStatus((Status_stmtContext) child);\r
248                 builder.setStatus(status);\r
249             }\r
250         }\r
251     }\r
252 \r
253     @Override\r
254     public void exitAugment_stmt(YangParser.Augment_stmtContext ctx) {\r
255         final String augment = actualPath.pop();\r
256         logger.debug("exiting augment " + augment);\r
257     }\r
258 \r
259     @Override\r
260     public void enterExtension_stmt(YangParser.Extension_stmtContext ctx) {\r
261         String extName = stringFromNode(ctx);\r
262         QName qname = new QName(namespace, revision, yangModelPrefix, extName);\r
263         ExtensionBuilder builder = moduleBuilder.addExtension(qname);\r
264         parseSchemaNodeArgs(ctx, builder);\r
265 \r
266         String argument = null;\r
267         boolean yin = false;\r
268         for (int i = 0; i < ctx.getChildCount(); i++) {\r
269             ParseTree child = ctx.getChild(i);\r
270             if (child instanceof Argument_stmtContext) {\r
271                 argument = stringFromNode(child);\r
272                 yin = parseYinValue((Argument_stmtContext) child);\r
273                 break;\r
274             }\r
275         }\r
276         builder.setArgument(argument);\r
277         builder.setYinElement(yin);\r
278     }\r
279 \r
280     @Override\r
281     public void enterTypedef_stmt(YangParser.Typedef_stmtContext ctx) {\r
282         String typedefName = stringFromNode(ctx);\r
283         QName typedefQName = new QName(namespace, revision, yangModelPrefix,\r
284                 typedefName);\r
285         TypedefBuilder builder = moduleBuilder.addTypedef(typedefQName,\r
286                 getActualPath());\r
287         updatePath(typedefName);\r
288 \r
289         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,\r
290                 yangModelPrefix));\r
291         parseSchemaNodeArgs(ctx, builder);\r
292         builder.setUnits(parseUnits(ctx));\r
293     }\r
294 \r
295     @Override\r
296     public void exitTypedef_stmt(YangParser.Typedef_stmtContext ctx) {\r
297         final String actContainer = actualPath.pop();\r
298         logger.debug("exiting " + actContainer);\r
299     }\r
300 \r
301     @Override\r
302     public void enterType_stmt(YangParser.Type_stmtContext ctx) {\r
303         String typeName = stringFromNode(ctx);\r
304         QName typeQName = parseQName(typeName);\r
305 \r
306         TypeDefinition<?> type = null;\r
307         Type_body_stmtsContext typeBody = null;\r
308         for (int i = 0; i < ctx.getChildCount(); i++) {\r
309             if (ctx.getChild(i) instanceof Type_body_stmtsContext) {\r
310                 typeBody = (Type_body_stmtsContext) ctx.getChild(i);\r
311                 break;\r
312             }\r
313         }\r
314 \r
315         // if this is base yang type...\r
316         if (YangTypesConverter.isBaseYangType(typeName)) {\r
317             if (typeBody == null) {\r
318                 // if there are no constraints, just grab default base yang type\r
319                 type = YangTypesConverter.javaTypeForBaseYangType(typeName);\r
320                 moduleBuilder.setType(type, getActualPath());\r
321             } else {\r
322                 if ("union".equals(typeName)) {\r
323                     moduleBuilder.addUnionType(getActualPath());\r
324                 } else {\r
325                     List<String> typePath = new ArrayList<String>(actualPath);\r
326                     typePath.remove(0);\r
327                     type = parseTypeBody(typeName, typeBody, typePath,\r
328                             namespace, revision, yangModelPrefix);\r
329                     moduleBuilder.setType(type, getActualPath());\r
330                 }\r
331             }\r
332         } else {\r
333             type = parseUnknownTypeBody(typeQName, typeBody);\r
334             // mark parent node of this type statement as dirty\r
335             moduleBuilder.addDirtyNode(getActualPath());\r
336             moduleBuilder.setType(type, getActualPath());\r
337         }\r
338 \r
339         updatePath(typeName);\r
340     }\r
341 \r
342     private QName parseQName(String typeName) {\r
343         QName typeQName;\r
344         if (typeName.contains(":")) {\r
345             String[] splittedName = typeName.split(":");\r
346             String prefix = splittedName[0];\r
347             String name = splittedName[1];\r
348             if (prefix.equals(yangModelPrefix)) {\r
349                 typeQName = new QName(namespace, revision, prefix, name);\r
350             } else {\r
351                 typeQName = new QName(null, null, prefix, name);\r
352             }\r
353         } else {\r
354             typeQName = new QName(namespace, revision, yangModelPrefix,\r
355                     typeName);\r
356         }\r
357         return typeQName;\r
358     }\r
359 \r
360     @Override\r
361     public void exitType_stmt(YangParser.Type_stmtContext ctx) {\r
362         final String actContainer = actualPath.pop();\r
363         logger.debug("exiting " + actContainer);\r
364     }\r
365 \r
366     @Override\r
367     public void enterGrouping_stmt(YangParser.Grouping_stmtContext ctx) {\r
368         final String groupName = stringFromNode(ctx);\r
369         QName groupQName = new QName(namespace, revision, yangModelPrefix,\r
370                 groupName);\r
371         GroupingBuilder groupBuilder = moduleBuilder.addGrouping(groupQName,\r
372                 actualPath);\r
373         updatePath("grouping");\r
374         updatePath(groupName);\r
375         parseSchemaNodeArgs(ctx, groupBuilder);\r
376     }\r
377 \r
378     @Override\r
379     public void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx) {\r
380         String actContainer = actualPath.pop();\r
381         actContainer += "-" + actualPath.pop();\r
382         logger.debug("exiting " + actContainer);\r
383     }\r
384 \r
385     @Override\r
386     public void enterContainer_stmt(Container_stmtContext ctx) {\r
387         super.enterContainer_stmt(ctx);\r
388         String containerName = stringFromNode(ctx);\r
389         QName containerQName = new QName(namespace, revision, yangModelPrefix,\r
390                 containerName);\r
391         ContainerSchemaNodeBuilder containerBuilder = moduleBuilder\r
392                 .addContainerNode(containerQName, actualPath);\r
393         updatePath(containerName);\r
394 \r
395         containerBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));\r
396         parseSchemaNodeArgs(ctx, containerBuilder);\r
397         parseConstraints(ctx, containerBuilder.getConstraintsBuilder());\r
398 \r
399         for (int i = 0; i < ctx.getChildCount(); ++i) {\r
400             final ParseTree childNode = ctx.getChild(i);\r
401             if (childNode instanceof Presence_stmtContext) {\r
402                 containerBuilder.setPresenceContainer(true);\r
403                 break;\r
404             }\r
405         }\r
406     }\r
407 \r
408     @Override\r
409     public void exitContainer_stmt(Container_stmtContext ctx) {\r
410         super.exitContainer_stmt(ctx);\r
411         final String actContainer = actualPath.pop();\r
412         logger.debug("exiting " + actContainer);\r
413     }\r
414 \r
415     @Override\r
416     public void enterLeaf_stmt(Leaf_stmtContext ctx) {\r
417         super.enterLeaf_stmt(ctx);\r
418 \r
419         final String leafName = stringFromNode(ctx);\r
420         QName leafQName = new QName(namespace, revision, yangModelPrefix,\r
421                 leafName);\r
422         LeafSchemaNodeBuilder leafBuilder = moduleBuilder.addLeafNode(\r
423                 leafQName, actualPath);\r
424         updatePath(leafName);\r
425 \r
426         leafBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));\r
427         parseSchemaNodeArgs(ctx, leafBuilder);\r
428         parseConstraints(ctx, leafBuilder.getConstraintsBuilder());\r
429     }\r
430 \r
431     @Override\r
432     public void exitLeaf_stmt(YangParser.Leaf_stmtContext ctx) {\r
433         final String actLeaf = actualPath.pop();\r
434         logger.debug("exiting " + actLeaf);\r
435     }\r
436 \r
437     @Override\r
438     public void enterUses_stmt(YangParser.Uses_stmtContext ctx) {\r
439         final String groupingPathStr = stringFromNode(ctx);\r
440         moduleBuilder.addUsesNode(groupingPathStr, actualPath);\r
441         updatePath(groupingPathStr);\r
442     }\r
443 \r
444     @Override\r
445     public void exitUses_stmt(YangParser.Uses_stmtContext ctx) {\r
446         final String actContainer = actualPath.pop();\r
447         logger.debug("exiting " + actContainer);\r
448     }\r
449 \r
450     @Override\r
451     public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) {\r
452         super.enterLeaf_list_stmt(ctx);\r
453 \r
454         final String leafListName = stringFromNode(ctx);\r
455         QName leafListQName = new QName(namespace, revision, yangModelPrefix,\r
456                 leafListName);\r
457         LeafListSchemaNodeBuilder leafListBuilder = moduleBuilder\r
458                 .addLeafListNode(leafListQName, actualPath);\r
459         updatePath(leafListName);\r
460 \r
461         parseSchemaNodeArgs(ctx, leafListBuilder);\r
462         parseConstraints(ctx, leafListBuilder.getConstraintsBuilder());\r
463 \r
464         for (int i = 0; i < ctx.getChildCount(); ++i) {\r
465             final ParseTree childNode = ctx.getChild(i);\r
466             if (childNode instanceof Ordered_by_stmtContext) {\r
467                 final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;\r
468                 final boolean userOrdered = parseUserOrdered(orderedBy);\r
469                 leafListBuilder.setUserOrdered(userOrdered);\r
470                 break;\r
471             }\r
472         }\r
473     }\r
474 \r
475     @Override\r
476     public void exitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) {\r
477         final String actContainer = actualPath.pop();\r
478         logger.debug("exiting " + actContainer);\r
479     }\r
480 \r
481     @Override\r
482     public void enterList_stmt(List_stmtContext ctx) {\r
483         super.enterList_stmt(ctx);\r
484 \r
485         final String containerName = stringFromNode(ctx);\r
486         QName containerQName = new QName(namespace, revision, yangModelPrefix,\r
487                 containerName);\r
488         ListSchemaNodeBuilder listBuilder = moduleBuilder.addListNode(\r
489                 containerQName, actualPath);\r
490         updatePath(containerName);\r
491 \r
492         listBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));\r
493         parseSchemaNodeArgs(ctx, listBuilder);\r
494         parseConstraints(ctx, listBuilder.getConstraintsBuilder());\r
495 \r
496         String keyDefinition = "";\r
497         for (int i = 0; i < ctx.getChildCount(); ++i) {\r
498             ParseTree childNode = ctx.getChild(i);\r
499             if (childNode instanceof Ordered_by_stmtContext) {\r
500                 final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;\r
501                 final boolean userOrdered = parseUserOrdered(orderedBy);\r
502                 listBuilder.setUserOrdered(userOrdered);\r
503             } else if (childNode instanceof Key_stmtContext) {\r
504                 keyDefinition = stringFromNode(childNode);\r
505                 List<QName> key = createListKey(keyDefinition, namespace,\r
506                         revision, yangModelPrefix);\r
507                 listBuilder.setKeyDefinition(key);\r
508             }\r
509         }\r
510     }\r
511 \r
512     @Override\r
513     public void exitList_stmt(List_stmtContext ctx) {\r
514         final String actContainer = actualPath.pop();\r
515         logger.debug("exiting " + actContainer);\r
516     }\r
517 \r
518     @Override\r
519     public void enterNotification_stmt(YangParser.Notification_stmtContext ctx) {\r
520         final String notificationName = stringFromNode(ctx);\r
521         QName notificationQName = new QName(namespace, revision,\r
522                 yangModelPrefix, notificationName);\r
523         NotificationBuilder notificationBuilder = moduleBuilder\r
524                 .addNotification(notificationQName, actualPath);\r
525         updatePath(notificationName);\r
526 \r
527         notificationBuilder.setPath(createActualSchemaPath(actualPath, namespace,\r
528                 revision, yangModelPrefix));\r
529         parseSchemaNodeArgs(ctx, notificationBuilder);\r
530     }\r
531 \r
532     @Override\r
533     public void exitNotification_stmt(YangParser.Notification_stmtContext ctx) {\r
534         final String actContainer = actualPath.pop();\r
535         logger.debug("exiting " + actContainer);\r
536     }\r
537 \r
538     // Unknown types\r
539     @Override\r
540     public void enterIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {\r
541         String name = stringFromNode(ctx);\r
542 \r
543         QName qname;\r
544         if(name != null) {\r
545             String[] splittedName = name.split(":");\r
546             if(splittedName.length == 2) {\r
547                 qname = new QName(null, null, splittedName[0], splittedName[1]);\r
548             } else {\r
549                 qname = new QName(namespace, revision, yangModelPrefix, splittedName[0]);\r
550             }\r
551         } else {\r
552             qname = new QName(namespace, revision, yangModelPrefix, name);\r
553         }\r
554 \r
555         UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(qname, getActualPath());\r
556         updatePath(name);\r
557 \r
558         builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));\r
559         parseSchemaNodeArgs(ctx, builder);\r
560     }\r
561 \r
562     @Override\r
563     public void exitIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {\r
564         final String actContainer = actualPath.pop();\r
565         logger.debug("exiting " + actContainer);\r
566     }\r
567 \r
568     @Override\r
569     public void enterRpc_stmt(YangParser.Rpc_stmtContext ctx) {\r
570         final String rpcName = stringFromNode(ctx);\r
571         QName rpcQName = new QName(namespace, revision, yangModelPrefix,\r
572                 rpcName);\r
573         RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(rpcQName,\r
574                 actualPath);\r
575         updatePath(rpcName);\r
576 \r
577         rpcBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision,\r
578                 yangModelPrefix));\r
579         parseSchemaNodeArgs(ctx, rpcBuilder);\r
580     }\r
581 \r
582     @Override\r
583     public void exitRpc_stmt(YangParser.Rpc_stmtContext ctx) {\r
584         final String actContainer = actualPath.pop();\r
585         logger.debug("exiting " + actContainer);\r
586     }\r
587 \r
588     @Override\r
589     public void enterInput_stmt(YangParser.Input_stmtContext ctx) {\r
590         updatePath("input");\r
591     }\r
592 \r
593     @Override\r
594     public void exitInput_stmt(YangParser.Input_stmtContext ctx) {\r
595         final String actContainer = actualPath.pop();\r
596         logger.debug("exiting " + actContainer);\r
597     }\r
598 \r
599     @Override\r
600     public void enterOutput_stmt(YangParser.Output_stmtContext ctx) {\r
601         updatePath("output");\r
602     }\r
603 \r
604     @Override\r
605     public void exitOutput_stmt(YangParser.Output_stmtContext ctx) {\r
606         final String actContainer = actualPath.pop();\r
607         logger.debug("exiting " + actContainer);\r
608     }\r
609 \r
610     @Override\r
611     public void enterFeature_stmt(YangParser.Feature_stmtContext ctx) {\r
612         final String featureName = stringFromNode(ctx);\r
613         QName featureQName = new QName(namespace, revision, yangModelPrefix,\r
614                 featureName);\r
615         FeatureBuilder featureBuilder = moduleBuilder.addFeature(featureQName,\r
616                 actualPath);\r
617         updatePath(featureName);\r
618 \r
619         featureBuilder.setPath(createActualSchemaPath(actualPath, namespace,\r
620                 revision, yangModelPrefix));\r
621         parseSchemaNodeArgs(ctx, featureBuilder);\r
622     }\r
623 \r
624     @Override\r
625     public void exitFeature_stmt(YangParser.Feature_stmtContext ctx) {\r
626         final String actContainer = actualPath.pop();\r
627         logger.debug("exiting " + actContainer);\r
628     }\r
629 \r
630     @Override\r
631     public void enterDeviation_stmt(YangParser.Deviation_stmtContext ctx) {\r
632         final String targetPath = stringFromNode(ctx);\r
633         String reference = null;\r
634         String deviate = null;\r
635         DeviationBuilder builder = moduleBuilder.addDeviation(targetPath);\r
636         updatePath(targetPath);\r
637 \r
638         for (int i = 0; i < ctx.getChildCount(); i++) {\r
639             ParseTree child = ctx.getChild(i);\r
640             if (child instanceof Reference_stmtContext) {\r
641                 reference = stringFromNode(child);\r
642             } else if (child instanceof Deviate_not_supported_stmtContext) {\r
643                 deviate = stringFromNode(child);\r
644             } else if (child instanceof Deviate_add_stmtContext) {\r
645                 deviate = stringFromNode(child);\r
646             } else if (child instanceof Deviate_replace_stmtContext) {\r
647                 deviate = stringFromNode(child);\r
648             } else if (child instanceof Deviate_delete_stmtContext) {\r
649                 deviate = stringFromNode(child);\r
650             }\r
651         }\r
652         builder.setReference(reference);\r
653         builder.setDeviate(deviate);\r
654     }\r
655 \r
656     @Override\r
657     public void exitDeviation_stmt(YangParser.Deviation_stmtContext ctx) {\r
658         final String actContainer = actualPath.pop();\r
659         logger.debug("exiting " + actContainer);\r
660     }\r
661 \r
662     @Override\r
663     public void enterConfig_stmt(YangParser.Config_stmtContext ctx) {\r
664         boolean configuration = parseConfig(ctx);\r
665         moduleBuilder.addConfiguration(configuration, actualPath);\r
666     }\r
667 \r
668     @Override\r
669     public void enterIdentity_stmt(YangParser.Identity_stmtContext ctx) {\r
670         final String identityName = stringFromNode(ctx);\r
671         final QName identityQName = new QName(namespace, revision,\r
672                 yangModelPrefix, identityName);\r
673         IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(identityQName);\r
674         updatePath(identityName);\r
675 \r
676         builder.setPath(createActualSchemaPath(actualPath, namespace,\r
677                 revision, yangModelPrefix));\r
678         parseSchemaNodeArgs(ctx, builder);\r
679 \r
680         for(int i = 0; i < ctx.getChildCount(); i++) {\r
681             ParseTree child = ctx.getChild(i);\r
682             if(child instanceof Base_stmtContext) {\r
683                 String baseIdentityName = stringFromNode(child);\r
684                 builder.setBaseIdentityName(baseIdentityName);\r
685             }\r
686         }\r
687     }\r
688 \r
689     @Override\r
690     public void exitIdentity_stmt(YangParser.Identity_stmtContext ctx) {\r
691         final String actContainer = actualPath.pop();\r
692         logger.debug("exiting " + actContainer);\r
693     }\r
694 \r
695     public ModuleBuilder getModuleBuilder() {\r
696         return moduleBuilder;\r
697     }\r
698 \r
699     private void updatePath(String containerName) {\r
700         actualPath.push(containerName);\r
701     }\r
702 \r
703     private List<String> getActualPath() {\r
704         return Collections.unmodifiableList(actualPath);\r
705     }\r
706 \r
707 }\r