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