Merge "Bumped version of YANG tools to 0.5.2-SNAPSHOT"
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / parser / impl / YangParserListenerImpl.java
1 /*
2  * Copyright (c) 2013 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/epl-v10.html
7  */
8 package org.opendaylight.controller.yang.parser.impl;
9
10 import static org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil.*;
11
12 import java.net.URI;
13 import java.text.DateFormat;
14 import java.text.ParseException;
15 import java.text.SimpleDateFormat;
16 import java.util.ArrayList;
17 import java.util.Date;
18 import java.util.List;
19 import java.util.Stack;
20
21 import org.antlr.v4.runtime.tree.ParseTree;
22 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
23 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
24 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;
25 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Contact_stmtContext;
26 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext;
27 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
28 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext;
29 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
30 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_delete_stmtContext;
31 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_not_supported_stmtContext;
32 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_replace_stmtContext;
33 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
34 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext;
35 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_list_stmtContext;
36 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext;
37 import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext;
38 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
39 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
40 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext;
41 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Organization_stmtContext;
42 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
43 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Presence_stmtContext;
44 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext;
45 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
46 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
47 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtsContext;
48 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext;
49 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext;
50 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext;
51 import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;
52 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
53 import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener;
54 import org.opendaylight.controller.yang.common.QName;
55 import org.opendaylight.controller.yang.model.api.SchemaPath;
56 import org.opendaylight.controller.yang.model.api.Status;
57 import org.opendaylight.controller.yang.model.api.TypeDefinition;
58 import org.opendaylight.controller.yang.model.util.YangTypesConverter;
59 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
60 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
61 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
62 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
63 import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
64 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
65 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceCaseBuilder;
66 import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
67 import org.opendaylight.controller.yang.parser.builder.impl.DeviationBuilder;
68 import org.opendaylight.controller.yang.parser.builder.impl.ExtensionBuilder;
69 import org.opendaylight.controller.yang.parser.builder.impl.FeatureBuilder;
70 import org.opendaylight.controller.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
71 import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
72 import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
73 import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
74 import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
75 import org.opendaylight.controller.yang.parser.builder.impl.NotificationBuilder;
76 import org.opendaylight.controller.yang.parser.builder.impl.RpcDefinitionBuilder;
77 import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
78 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
79 import org.opendaylight.controller.yang.parser.util.RefineHolder;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
82
83 public final class YangParserListenerImpl extends YangParserBaseListener {
84
85     private static final Logger logger = LoggerFactory
86             .getLogger(YangParserListenerImpl.class);
87
88     private ModuleBuilder moduleBuilder;
89
90     private String moduleName;
91     private URI namespace;
92     private String yangModelPrefix;
93     private Date revision = new Date(0L);
94
95     public final static DateFormat simpleDateFormat = new SimpleDateFormat(
96             "yyyy-MM-dd");
97     private final Stack<String> actualPath = new Stack<String>();
98
99     @Override
100     public void enterModule_stmt(YangParser.Module_stmtContext ctx) {
101         moduleName = stringFromNode(ctx);
102         actualPath.push(moduleName);
103         moduleBuilder = new ModuleBuilder(moduleName);
104
105         String description = null;
106         String reference = null;
107
108         for (int i = 0; i < ctx.getChildCount(); i++) {
109             ParseTree child = ctx.getChild(i);
110             if (child instanceof Description_stmtContext) {
111                 description = stringFromNode(child);
112             } else if (child instanceof Reference_stmtContext) {
113                 reference = stringFromNode(child);
114             } else {
115                 if (description != null && reference != null) {
116                     break;
117                 }
118             }
119         }
120         moduleBuilder.setDescription(description);
121         moduleBuilder.setReference(reference);
122     }
123
124     @Override
125     public void exitModule_stmt(YangParser.Module_stmtContext ctx) {
126         final String moduleName = actualPath.pop();
127         logger.debug("Exiting module " + moduleName);
128     }
129
130     @Override
131     public void enterModule_header_stmts(final Module_header_stmtsContext ctx) {
132         super.enterModule_header_stmts(ctx);
133
134         String yangVersion = null;
135         for (int i = 0; i < ctx.getChildCount(); ++i) {
136             final ParseTree treeNode = ctx.getChild(i);
137             if (treeNode instanceof Namespace_stmtContext) {
138                 final String namespaceStr = stringFromNode(treeNode);
139                 namespace = URI.create(namespaceStr);
140                 moduleBuilder.setNamespace(namespace);
141             } else if (treeNode instanceof Prefix_stmtContext) {
142                 yangModelPrefix = stringFromNode(treeNode);
143                 moduleBuilder.setPrefix(yangModelPrefix);
144             } else if (treeNode instanceof Yang_version_stmtContext) {
145                 yangVersion = stringFromNode(treeNode);
146             }
147         }
148
149         if (yangVersion == null) {
150             yangVersion = "1";
151         }
152         moduleBuilder.setYangVersion(yangVersion);
153     }
154
155     @Override
156     public void enterMeta_stmts(YangParser.Meta_stmtsContext ctx) {
157         for (int i = 0; i < ctx.getChildCount(); i++) {
158             ParseTree child = ctx.getChild(i);
159             if (child instanceof Organization_stmtContext) {
160                 final String organization = stringFromNode(child);
161                 moduleBuilder.setOrganization(organization);
162             } else if (child instanceof Contact_stmtContext) {
163                 final String contact = stringFromNode(child);
164                 moduleBuilder.setContact(contact);
165             } else if (child instanceof Description_stmtContext) {
166                 final String description = stringFromNode(child);
167                 moduleBuilder.setDescription(description);
168             } else if (child instanceof Reference_stmtContext) {
169                 final String reference = stringFromNode(child);
170                 moduleBuilder.setReference(reference);
171             }
172         }
173     }
174
175     @Override
176     public void exitSubmodule_header_stmts(
177             YangParser.Submodule_header_stmtsContext ctx) {
178         final String submodule = actualPath.pop();
179         logger.debug("exiting submodule " + submodule);
180     }
181
182     @Override
183     public void enterRevision_stmts(Revision_stmtsContext ctx) {
184         if (ctx != null) {
185             for (int i = 0; i < ctx.getChildCount(); ++i) {
186                 final ParseTree treeNode = ctx.getChild(i);
187                 if (treeNode instanceof Revision_stmtContext) {
188                     updateRevisionForRevisionStatement(treeNode);
189                 }
190             }
191         }
192     }
193
194     private void updateRevisionForRevisionStatement(final ParseTree treeNode) {
195         final String revisionDateStr = stringFromNode(treeNode);
196         try {
197             final Date revision = simpleDateFormat.parse(revisionDateStr);
198             if ((revision != null) && (this.revision.compareTo(revision) < 0)) {
199                 this.revision = revision;
200                 moduleBuilder.setRevision(this.revision);
201                 for (int i = 0; i < treeNode.getChildCount(); ++i) {
202                     ParseTree child = treeNode.getChild(i);
203                     if (child instanceof Reference_stmtContext) {
204                         moduleBuilder.setReference(stringFromNode(child));
205                     }
206                 }
207             }
208         } catch (ParseException e) {
209             final String message = "Failed to parse revision string: "
210                     + revisionDateStr;
211             logger.warn(message);
212         }
213     }
214
215     @Override
216     public void enterImport_stmt(Import_stmtContext ctx) {
217         final String importName = stringFromNode(ctx);
218         String importPrefix = null;
219         Date importRevision = null;
220
221         for (int i = 0; i < ctx.getChildCount(); ++i) {
222             final ParseTree treeNode = ctx.getChild(i);
223             if (treeNode instanceof Prefix_stmtContext) {
224                 importPrefix = stringFromNode(treeNode);
225             }
226             if (treeNode instanceof Revision_date_stmtContext) {
227                 String importRevisionStr = stringFromNode(treeNode);
228                 try {
229                     importRevision = simpleDateFormat.parse(importRevisionStr);
230                 } catch (ParseException e) {
231                     logger.warn("Failed to parse import revision-date: "
232                             + importRevisionStr);
233                 }
234             }
235         }
236         moduleBuilder.addModuleImport(importName, importRevision, importPrefix);
237     }
238
239     @Override
240     public void enterAugment_stmt(YangParser.Augment_stmtContext ctx) {
241         final String augmentPath = stringFromNode(ctx);
242         AugmentationSchemaBuilder builder = moduleBuilder.addAugment(
243                 augmentPath, actualPath, ctx.getStart().getLine());
244         moduleBuilder.enterNode(builder);
245         updatePath(augmentPath);
246
247         for (int i = 0; i < ctx.getChildCount(); i++) {
248             ParseTree child = ctx.getChild(i);
249             if (child instanceof Description_stmtContext) {
250                 String desc = stringFromNode(child);
251                 builder.setDescription(desc);
252             } else if (child instanceof Reference_stmtContext) {
253                 String ref = stringFromNode(child);
254                 builder.setReference(ref);
255             } else if (child instanceof Status_stmtContext) {
256                 Status status = parseStatus((Status_stmtContext) child);
257                 builder.setStatus(status);
258             } else if (child instanceof When_stmtContext) {
259                 String when = stringFromNode(child);
260                 builder.addWhenCondition(when);
261             }
262         }
263     }
264
265     @Override
266     public void exitAugment_stmt(YangParser.Augment_stmtContext ctx) {
267         final String augment = actualPath.pop();
268         logger.debug("exiting augment " + augment);
269         moduleBuilder.exitNode();
270     }
271
272     @Override
273     public void enterExtension_stmt(YangParser.Extension_stmtContext ctx) {
274         final String extName = stringFromNode(ctx);
275         QName qname = new QName(namespace, revision, yangModelPrefix, extName);
276         ExtensionBuilder builder = moduleBuilder.addExtension(qname, ctx
277                 .getStart().getLine());
278         parseSchemaNodeArgs(ctx, builder);
279
280         String argument = null;
281         boolean yin = false;
282         for (int i = 0; i < ctx.getChildCount(); i++) {
283             ParseTree child = ctx.getChild(i);
284             if (child instanceof Argument_stmtContext) {
285                 argument = stringFromNode(child);
286                 yin = parseYinValue((Argument_stmtContext) child);
287                 break;
288             }
289         }
290         builder.setArgument(argument);
291         builder.setYinElement(yin);
292     }
293
294     @Override
295     public void enterTypedef_stmt(YangParser.Typedef_stmtContext ctx) {
296         final String typedefName = stringFromNode(ctx);
297         QName typedefQName = new QName(namespace, revision, yangModelPrefix,
298                 typedefName);
299         TypeDefinitionBuilder builder = moduleBuilder.addTypedef(typedefQName,
300                 actualPath, ctx.getStart().getLine());
301         moduleBuilder.enterNode(builder);
302         updatePath(typedefName);
303
304         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
305                 yangModelPrefix));
306         parseSchemaNodeArgs(ctx, builder);
307         builder.setUnits(parseUnits(ctx));
308     }
309
310     @Override
311     public void exitTypedef_stmt(YangParser.Typedef_stmtContext ctx) {
312         final String actContainer = actualPath.pop();
313         logger.debug("exiting " + actContainer);
314         moduleBuilder.exitNode();
315     }
316
317     @Override
318     public void enterType_stmt(YangParser.Type_stmtContext ctx) {
319         final String typeName = stringFromNode(ctx);
320         final int line = ctx.getStart().getLine();
321         final QName typeQName = parseQName(typeName);
322
323         TypeDefinition<?> type = null;
324         Type_body_stmtsContext typeBody = null;
325         for (int i = 0; i < ctx.getChildCount(); i++) {
326             if (ctx.getChild(i) instanceof Type_body_stmtsContext) {
327                 typeBody = (Type_body_stmtsContext) ctx.getChild(i);
328                 break;
329             }
330         }
331
332         // if this is base yang type...
333         if (YangTypesConverter.isBaseYangType(typeName)) {
334             if (typeBody == null) {
335                 // check for types which must have body
336                 checkMissingBody(typeName, moduleName, line);
337                 // if there are no constraints, just grab default base yang type
338                 type = YangTypesConverter.javaTypeForBaseYangType(actualPath,
339                         namespace, revision, typeName);
340                 moduleBuilder.setType(type, actualPath);
341             } else {
342                 if ("union".equals(typeName)) {
343                     List<String> typePath = new ArrayList<String>(actualPath);
344                     typePath.add(typeName);
345                     SchemaPath p = createActualSchemaPath(typePath, namespace,
346                             revision, yangModelPrefix);
347                     UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(
348                             actualPath, namespace, revision, line);
349                     moduleBuilder.enterNode(unionBuilder);
350                     unionBuilder.setPath(p);
351                 } else if ("identityref".equals(typeName)) {
352                     SchemaPath path = createActualSchemaPath(actualPath,
353                             namespace, revision, yangModelPrefix);
354                     moduleBuilder.addIdentityrefType(
355                             getIdentityrefBase(typeBody), actualPath, path,
356                             line);
357                 } else {
358                     type = parseTypeBody(typeName, typeBody, actualPath,
359                             namespace, revision, yangModelPrefix,
360                             moduleBuilder.getActualNode());
361                     moduleBuilder.setType(type, actualPath);
362                 }
363             }
364         } else {
365             type = parseUnknownTypeBody(typeQName, typeBody, actualPath,
366                     namespace, revision, yangModelPrefix,
367                     moduleBuilder.getActualNode(), moduleBuilder);
368             // mark parent node of this type statement as dirty
369             moduleBuilder.addDirtyNode(actualPath);
370             moduleBuilder.setType(type, actualPath);
371         }
372
373         updatePath(typeName);
374     }
375
376     private QName parseQName(String typeName) {
377         QName typeQName;
378         if (typeName.contains(":")) {
379             String[] splittedName = typeName.split(":");
380             String prefix = splittedName[0];
381             String name = splittedName[1];
382             if (prefix.equals(yangModelPrefix)) {
383                 typeQName = new QName(namespace, revision, prefix, name);
384             } else {
385                 typeQName = new QName(null, null, prefix, name);
386             }
387         } else {
388             typeQName = new QName(namespace, revision, yangModelPrefix,
389                     typeName);
390         }
391         return typeQName;
392     }
393
394     @Override
395     public void exitType_stmt(YangParser.Type_stmtContext ctx) {
396         final String actContainer = actualPath.pop();
397         logger.debug("exiting " + actContainer);
398
399         final String typeName = stringFromNode(ctx);
400         if ("union".equals(typeName)) {
401             moduleBuilder.exitNode();
402         }
403     }
404
405     @Override
406     public void enterGrouping_stmt(YangParser.Grouping_stmtContext ctx) {
407         final String groupName = stringFromNode(ctx);
408         QName groupQName = new QName(namespace, revision, yangModelPrefix,
409                 groupName);
410         GroupingBuilder builder = moduleBuilder.addGrouping(groupQName,
411                 actualPath, ctx.getStart().getLine());
412         moduleBuilder.enterNode(builder);
413         updatePath(groupName);
414         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
415                 yangModelPrefix));
416         parseSchemaNodeArgs(ctx, builder);
417     }
418
419     @Override
420     public void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx) {
421         String actContainer = actualPath.pop();
422         logger.debug("exiting " + actContainer);
423         moduleBuilder.exitNode();
424     }
425
426     @Override
427     public void enterContainer_stmt(Container_stmtContext ctx) {
428         final String containerName = stringFromNode(ctx);
429         QName containerQName = new QName(namespace, revision, yangModelPrefix,
430                 containerName);
431         ContainerSchemaNodeBuilder builder = moduleBuilder.addContainerNode(
432                 containerQName, actualPath, ctx.getStart().getLine());
433         moduleBuilder.enterNode(builder);
434         updatePath(containerName);
435
436         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
437                 yangModelPrefix));
438         parseSchemaNodeArgs(ctx, builder);
439         parseConstraints(ctx, builder.getConstraints());
440
441         for (int i = 0; i < ctx.getChildCount(); ++i) {
442             final ParseTree childNode = ctx.getChild(i);
443             if (childNode instanceof Presence_stmtContext) {
444                 builder.setPresence(true);
445                 break;
446             }
447         }
448     }
449
450     @Override
451     public void exitContainer_stmt(Container_stmtContext ctx) {
452         final String actContainer = actualPath.pop();
453         logger.debug("exiting " + actContainer);
454         moduleBuilder.exitNode();
455     }
456
457     @Override
458     public void enterLeaf_stmt(Leaf_stmtContext ctx) {
459         final String leafName = stringFromNode(ctx);
460         QName leafQName = new QName(namespace, revision, yangModelPrefix,
461                 leafName);
462         LeafSchemaNodeBuilder builder = moduleBuilder.addLeafNode(leafQName,
463                 actualPath, ctx.getStart().getLine());
464         moduleBuilder.enterNode(builder);
465         updatePath(leafName);
466
467         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
468                 yangModelPrefix));
469         parseSchemaNodeArgs(ctx, builder);
470         parseConstraints(ctx, builder.getConstraints());
471
472         String defaultStr = null;
473         String unitsStr = null;
474         for (int i = 0; i < ctx.getChildCount(); i++) {
475             ParseTree child = ctx.getChild(i);
476             if (child instanceof Default_stmtContext) {
477                 defaultStr = stringFromNode(child);
478             } else if (child instanceof Units_stmtContext) {
479                 unitsStr = stringFromNode(child);
480             }
481         }
482         builder.setDefaultStr(defaultStr);
483         builder.setUnits(unitsStr);
484     }
485
486     @Override
487     public void exitLeaf_stmt(YangParser.Leaf_stmtContext ctx) {
488         final String actLeaf = actualPath.pop();
489         logger.debug("exiting " + actLeaf);
490         moduleBuilder.exitNode();
491     }
492
493     @Override
494     public void enterUses_stmt(YangParser.Uses_stmtContext ctx) {
495         final String groupingPathStr = stringFromNode(ctx);
496         UsesNodeBuilder builder = moduleBuilder.addUsesNode(groupingPathStr,
497                 actualPath, ctx.getStart().getLine());
498
499         moduleBuilder.enterNode(builder);
500         updatePath(groupingPathStr);
501         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
502                 yangModelPrefix));
503     }
504
505     @Override
506     public void exitUses_stmt(YangParser.Uses_stmtContext ctx) {
507         final String actContainer = actualPath.pop();
508         logger.debug("exiting " + actContainer);
509         moduleBuilder.exitNode();
510     }
511
512     @Override
513     public void enterRefine_stmt(YangParser.Refine_stmtContext ctx) {
514         String refineString = stringFromNode(ctx);
515         RefineHolder refine = parseRefine(ctx);
516         moduleBuilder.addRefine(refine, actualPath);
517         moduleBuilder.enterNode(refine);
518         updatePath(refineString);
519     }
520
521     @Override
522     public void exitRefine_stmt(YangParser.Refine_stmtContext ctx) {
523         final String actContainer = actualPath.pop();
524         logger.debug("exiting " + actContainer);
525         moduleBuilder.exitNode();
526     }
527
528     @Override
529     public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) {
530         final String leafListName = stringFromNode(ctx);
531         QName leafListQName = new QName(namespace, revision, yangModelPrefix,
532                 leafListName);
533         LeafListSchemaNodeBuilder builder = moduleBuilder.addLeafListNode(
534                 leafListQName, actualPath, ctx.getStart().getLine());
535         moduleBuilder.enterNode(builder);
536         updatePath(leafListName);
537
538         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
539                 yangModelPrefix));
540         parseSchemaNodeArgs(ctx, builder);
541         parseConstraints(ctx, builder.getConstraints());
542
543         for (int i = 0; i < ctx.getChildCount(); ++i) {
544             final ParseTree childNode = ctx.getChild(i);
545             if (childNode instanceof Ordered_by_stmtContext) {
546                 final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;
547                 final boolean userOrdered = parseUserOrdered(orderedBy);
548                 builder.setUserOrdered(userOrdered);
549                 break;
550             }
551         }
552     }
553
554     @Override
555     public void exitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) {
556         final String actContainer = actualPath.pop();
557         logger.debug("exiting " + actContainer);
558         moduleBuilder.exitNode();
559     }
560
561     @Override
562     public void enterList_stmt(List_stmtContext ctx) {
563         final String containerName = stringFromNode(ctx);
564         QName containerQName = new QName(namespace, revision, yangModelPrefix,
565                 containerName);
566         ListSchemaNodeBuilder builder = moduleBuilder.addListNode(
567                 containerQName, actualPath, ctx.getStart().getLine());
568         moduleBuilder.enterNode(builder);
569         updatePath(containerName);
570
571         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
572                 yangModelPrefix));
573         parseSchemaNodeArgs(ctx, builder);
574         parseConstraints(ctx, builder.getConstraints());
575
576         String keyDefinition = "";
577         for (int i = 0; i < ctx.getChildCount(); ++i) {
578             ParseTree childNode = ctx.getChild(i);
579             if (childNode instanceof Ordered_by_stmtContext) {
580                 final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;
581                 final boolean userOrdered = parseUserOrdered(orderedBy);
582                 builder.setUserOrdered(userOrdered);
583             } else if (childNode instanceof Key_stmtContext) {
584                 keyDefinition = stringFromNode(childNode);
585                 List<QName> key = createListKey(keyDefinition, namespace,
586                         revision, yangModelPrefix);
587                 builder.setKeyDefinition(key);
588             }
589         }
590     }
591
592     @Override
593     public void exitList_stmt(List_stmtContext ctx) {
594         final String actContainer = actualPath.pop();
595         logger.debug("exiting " + actContainer);
596         moduleBuilder.exitNode();
597     }
598
599     @Override
600     public void enterAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) {
601         final String anyXmlName = stringFromNode(ctx);
602         QName anyXmlQName = new QName(namespace, revision, yangModelPrefix,
603                 anyXmlName);
604         AnyXmlBuilder builder = moduleBuilder.addAnyXml(anyXmlQName,
605                 actualPath, ctx.getStart().getLine());
606         moduleBuilder.enterNode(builder);
607         updatePath(anyXmlName);
608
609         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
610                 yangModelPrefix));
611         parseSchemaNodeArgs(ctx, builder);
612         parseConstraints(ctx, builder.getConstraints());
613     }
614
615     @Override
616     public void exitAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) {
617         final String actContainer = actualPath.pop();
618         logger.debug("exiting " + actContainer);
619         moduleBuilder.exitNode();
620     }
621
622     @Override
623     public void enterChoice_stmt(YangParser.Choice_stmtContext ctx) {
624         final String choiceName = stringFromNode(ctx);
625         QName choiceQName = new QName(namespace, revision, yangModelPrefix,
626                 choiceName);
627         ChoiceBuilder builder = moduleBuilder.addChoice(choiceQName,
628                 actualPath, ctx.getStart().getLine());
629         moduleBuilder.enterNode(builder);
630
631         updatePath(choiceName);
632         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
633                 yangModelPrefix));
634         parseSchemaNodeArgs(ctx, builder);
635         parseConstraints(ctx, builder.getConstraints());
636
637         // set 'default' case
638         for (int i = 0; i < ctx.getChildCount(); i++) {
639             ParseTree child = ctx.getChild(i);
640             if (child instanceof Default_stmtContext) {
641                 String defaultCase = stringFromNode(child);
642                 builder.setDefaultCase(defaultCase);
643                 break;
644             }
645         }
646     }
647
648     @Override
649     public void exitChoice_stmt(YangParser.Choice_stmtContext ctx) {
650         final String actContainer = actualPath.pop();
651         logger.debug("exiting " + actContainer);
652         moduleBuilder.exitNode();
653     }
654
655     @Override
656     public void enterCase_stmt(YangParser.Case_stmtContext ctx) {
657         final String caseName = stringFromNode(ctx);
658         QName choiceQName = new QName(namespace, revision, yangModelPrefix,
659                 caseName);
660         ChoiceCaseBuilder builder = moduleBuilder.addCase(choiceQName,
661                 actualPath, ctx.getStart().getLine());
662         moduleBuilder.enterNode(builder);
663
664         updatePath(caseName);
665         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
666                 yangModelPrefix));
667         parseSchemaNodeArgs(ctx, builder);
668         parseConstraints(ctx, builder.getConstraints());
669     }
670
671     @Override
672     public void exitCase_stmt(YangParser.Case_stmtContext ctx) {
673         final String actContainer = actualPath.pop();
674         logger.debug("exiting " + actContainer);
675         moduleBuilder.exitNode();
676     }
677
678     @Override
679     public void enterNotification_stmt(YangParser.Notification_stmtContext ctx) {
680         final String notificationName = stringFromNode(ctx);
681         QName notificationQName = new QName(namespace, revision,
682                 yangModelPrefix, notificationName);
683         NotificationBuilder builder = moduleBuilder.addNotification(
684                 notificationQName, actualPath, ctx.getStart().getLine());
685         moduleBuilder.enterNode(builder);
686         updatePath(notificationName);
687
688         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
689                 yangModelPrefix));
690         parseSchemaNodeArgs(ctx, builder);
691     }
692
693     @Override
694     public void exitNotification_stmt(YangParser.Notification_stmtContext ctx) {
695         final String actContainer = actualPath.pop();
696         logger.debug("exiting " + actContainer);
697         moduleBuilder.exitNode();
698     }
699
700     // Unknown types
701     @Override
702     public void enterIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {
703         final String nodeParameter = stringFromNode(ctx);
704         QName nodeType = null;
705
706         final String nodeTypeStr = ctx.getChild(0).getText();
707         final String[] splittedElement = nodeTypeStr.split(":");
708         if (splittedElement.length == 1) {
709             nodeType = new QName(null, null, yangModelPrefix,
710                     splittedElement[0]);
711         } else {
712             nodeType = new QName(null, null, splittedElement[0],
713                     splittedElement[1]);
714         }
715
716         QName qname;
717         if (nodeParameter != null) {
718             String[] splittedName = nodeParameter.split(":");
719             if (splittedName.length == 2) {
720                 qname = new QName(null, null, splittedName[0], splittedName[1]);
721             } else {
722                 qname = new QName(namespace, revision, yangModelPrefix,
723                         splittedName[0]);
724             }
725         } else {
726             qname = new QName(namespace, revision, yangModelPrefix,
727                     nodeParameter);
728         }
729
730         UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(
731                 qname, actualPath, ctx.getStart().getLine());
732         builder.setNodeType(nodeType);
733         builder.setNodeParameter(nodeParameter);
734         updatePath(nodeParameter);
735         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
736                 yangModelPrefix));
737         parseSchemaNodeArgs(ctx, builder);
738         moduleBuilder.enterNode(builder);
739     }
740
741     @Override
742     public void exitIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {
743         final String actContainer = actualPath.pop();
744         logger.debug("exiting " + actContainer);
745         moduleBuilder.exitNode();
746     }
747
748     @Override
749     public void enterRpc_stmt(YangParser.Rpc_stmtContext ctx) {
750         final String rpcName = stringFromNode(ctx);
751         QName rpcQName = new QName(namespace, revision, yangModelPrefix,
752                 rpcName);
753         RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(rpcQName,
754                 actualPath, ctx.getStart().getLine());
755         moduleBuilder.enterNode(rpcBuilder);
756         updatePath(rpcName);
757
758         rpcBuilder.setPath(createActualSchemaPath(actualPath, namespace,
759                 revision, yangModelPrefix));
760         parseSchemaNodeArgs(ctx, rpcBuilder);
761     }
762
763     @Override
764     public void exitRpc_stmt(YangParser.Rpc_stmtContext ctx) {
765         final String actContainer = actualPath.pop();
766         logger.debug("exiting " + actContainer);
767         moduleBuilder.exitNode();
768     }
769
770     @Override
771     public void enterInput_stmt(YangParser.Input_stmtContext ctx) {
772         final String input = "input";
773         QName rpcQName = new QName(namespace, revision, yangModelPrefix, input);
774         ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcInput(
775                 rpcQName, ctx.getStart().getLine());
776         moduleBuilder.enterNode(builder);
777         updatePath(input);
778
779         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
780                 yangModelPrefix));
781         parseSchemaNodeArgs(ctx, builder);
782         parseConstraints(ctx, builder.getConstraints());
783     }
784
785     @Override
786     public void exitInput_stmt(YangParser.Input_stmtContext ctx) {
787         final String actContainer = actualPath.pop();
788         logger.debug("exiting " + actContainer);
789         moduleBuilder.exitNode();
790     }
791
792     @Override
793     public void enterOutput_stmt(YangParser.Output_stmtContext ctx) {
794         final String output = "output";
795         QName rpcQName = new QName(namespace, revision, yangModelPrefix, output);
796         ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcOutput(
797                 rpcQName, ctx.getStart().getLine());
798         moduleBuilder.enterNode(builder);
799         updatePath(output);
800
801         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
802                 yangModelPrefix));
803         parseSchemaNodeArgs(ctx, builder);
804         parseConstraints(ctx, builder.getConstraints());
805     }
806
807     @Override
808     public void exitOutput_stmt(YangParser.Output_stmtContext ctx) {
809         final String actContainer = actualPath.pop();
810         logger.debug("exiting " + actContainer);
811         moduleBuilder.exitNode();
812     }
813
814     @Override
815     public void enterFeature_stmt(YangParser.Feature_stmtContext ctx) {
816         final String featureName = stringFromNode(ctx);
817         QName featureQName = new QName(namespace, revision, yangModelPrefix,
818                 featureName);
819         FeatureBuilder featureBuilder = moduleBuilder.addFeature(featureQName,
820                 actualPath, ctx.getStart().getLine());
821         moduleBuilder.enterNode(featureBuilder);
822         updatePath(featureName);
823
824         featureBuilder.setPath(createActualSchemaPath(actualPath, namespace,
825                 revision, yangModelPrefix));
826         parseSchemaNodeArgs(ctx, featureBuilder);
827     }
828
829     @Override
830     public void exitFeature_stmt(YangParser.Feature_stmtContext ctx) {
831         final String actContainer = actualPath.pop();
832         logger.debug("exiting " + actContainer);
833         moduleBuilder.exitNode();
834     }
835
836     @Override
837     public void enterDeviation_stmt(YangParser.Deviation_stmtContext ctx) {
838         final String targetPath = stringFromNode(ctx);
839         String reference = null;
840         String deviate = null;
841         DeviationBuilder builder = moduleBuilder.addDeviation(targetPath,
842                 actualPath, ctx.getStart().getLine());
843         moduleBuilder.enterNode(builder);
844         updatePath(targetPath);
845
846         for (int i = 0; i < ctx.getChildCount(); i++) {
847             ParseTree child = ctx.getChild(i);
848             if (child instanceof Reference_stmtContext) {
849                 reference = stringFromNode(child);
850             } else if (child instanceof Deviate_not_supported_stmtContext) {
851                 deviate = stringFromNode(child);
852             } else if (child instanceof Deviate_add_stmtContext) {
853                 deviate = stringFromNode(child);
854             } else if (child instanceof Deviate_replace_stmtContext) {
855                 deviate = stringFromNode(child);
856             } else if (child instanceof Deviate_delete_stmtContext) {
857                 deviate = stringFromNode(child);
858             }
859         }
860         builder.setReference(reference);
861         builder.setDeviate(deviate);
862     }
863
864     @Override
865     public void exitDeviation_stmt(YangParser.Deviation_stmtContext ctx) {
866         final String actContainer = actualPath.pop();
867         logger.debug("exiting " + actContainer);
868         moduleBuilder.exitNode();
869     }
870
871     @Override
872     public void enterConfig_stmt(YangParser.Config_stmtContext ctx) {
873         boolean configuration = parseConfig(ctx);
874         moduleBuilder.addConfiguration(configuration, actualPath, ctx
875                 .getStart().getLine());
876     }
877
878     @Override
879     public void enterIdentity_stmt(YangParser.Identity_stmtContext ctx) {
880         final String identityName = stringFromNode(ctx);
881         final QName identityQName = new QName(namespace, revision,
882                 yangModelPrefix, identityName);
883         IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(
884                 identityQName, actualPath, ctx.getStart().getLine());
885         moduleBuilder.enterNode(builder);
886         updatePath(identityName);
887
888         builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
889                 yangModelPrefix));
890         parseSchemaNodeArgs(ctx, builder);
891
892         for (int i = 0; i < ctx.getChildCount(); i++) {
893             ParseTree child = ctx.getChild(i);
894             if (child instanceof Base_stmtContext) {
895                 String baseIdentityName = stringFromNode(child);
896                 builder.setBaseIdentityName(baseIdentityName);
897             }
898         }
899     }
900
901     @Override
902     public void exitIdentity_stmt(YangParser.Identity_stmtContext ctx) {
903         final String actContainer = actualPath.pop();
904         logger.debug("exiting " + actContainer);
905         moduleBuilder.exitNode();
906     }
907
908     public ModuleBuilder getModuleBuilder() {
909         return moduleBuilder;
910     }
911
912     private void updatePath(String containerName) {
913         actualPath.push(containerName);
914     }
915
916 }