When a node is going down, remove edges in both directions associated with the node.
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / validator / YangModelBasicValidationListener.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.validator;
9
10 import java.net.URI;
11 import java.net.URISyntaxException;
12 import java.util.Set;
13
14 import org.antlr.v4.runtime.tree.ParseTree;
15 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
16 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Anyxml_stmtContext;
17 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
18 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Augment_stmtContext;
19 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;
20 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
21 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Case_stmtContext;
22 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Choice_stmtContext;
23 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext;
24 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Container_stmtContext;
25 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
26 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviate_add_stmtContext;
27 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Deviation_stmtContext;
28 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Extension_stmtContext;
29 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Feature_stmtContext;
30 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Grouping_stmtContext;
31 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Identity_stmtContext;
32 import org.opendaylight.controller.antlrv4.code.gen.YangParser.If_feature_stmtContext;
33 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Import_stmtContext;
34 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Include_stmtContext;
35 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Key_stmtContext;
36 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_list_stmtContext;
37 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leaf_stmtContext;
38 import org.opendaylight.controller.antlrv4.code.gen.YangParser.List_stmtContext;
39 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext;
40 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
41 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_header_stmtsContext;
42 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Module_stmtContext;
43 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Namespace_stmtContext;
44 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Notification_stmtContext;
45 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
46 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Prefix_stmtContext;
47 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_stmtContext;
48 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_date_stmtContext;
49 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Revision_stmtContext;
50 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Rpc_stmtContext;
51 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
52 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_header_stmtsContext;
53 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Submodule_stmtContext;
54 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_stmtContext;
55 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Typedef_stmtContext;
56 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Unique_stmtContext;
57 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Uses_stmtContext;
58 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_argContext;
59 import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener;
60 import org.opendaylight.controller.yang.parser.impl.YangParserListenerImpl;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64 import com.google.common.collect.Sets;
65
66 /**
67  * Validation listener that validates yang statements according to RFC-6020.
68  * This validator expects only one module or submodule per file and performs
69  * only basic validation where context from all yang models is not present.
70  */
71 final class YangModelBasicValidationListener extends YangParserBaseListener {
72
73     private static final Logger logger = LoggerFactory
74             .getLogger(YangModelBasicValidationListener.class);
75
76     private final Set<String> uniquePrefixes;
77     private final Set<String> uniqueImports;
78     private final Set<String> uniqueIncludes;
79
80     private String globalModuleId;
81
82     YangModelBasicValidationListener() {
83         super();
84         uniquePrefixes = Sets.newHashSet();
85         uniqueImports = Sets.newHashSet();
86         uniqueIncludes = Sets.newHashSet();
87     }
88
89     /**
90      * Constraints:
91      * <ol>
92      * <li>Identifier is in required format</li>
93      * <li>Header statements present(mandatory prefix and namespace statements
94      * are in header)</li>
95      * <li>Only one module or submodule per file</li>
96      * </ol>
97      */
98     @Override
99     public void enterModule_stmt(Module_stmtContext ctx) {
100
101         BasicValidations.checkIdentifier(ctx);
102
103         BasicValidations.checkPresentChildOfType(ctx,
104                 Module_header_stmtsContext.class, true);
105
106         String moduleName = ValidationUtil.getName(ctx);
107         BasicValidations.checkOnlyOneModulePresent(moduleName, globalModuleId);
108         globalModuleId = moduleName;
109     }
110
111     /**
112      * Constraints:
113      * <ol>
114      * <li>Identifier is in required format</li>
115      * <li>Header statements present(mandatory belongs-to statement is in
116      * header)</li>
117      * <li>Only one module or submodule per file</li>
118      * </ol>
119      */
120     @Override
121     public void enterSubmodule_stmt(Submodule_stmtContext ctx) {
122
123         BasicValidations.checkIdentifier(ctx);
124
125         BasicValidations.checkPresentChildOfType(ctx,
126                 Submodule_header_stmtsContext.class, true);
127
128         String submoduleName = ValidationUtil.getName(ctx);
129         BasicValidations.checkOnlyOneModulePresent(submoduleName,
130                 globalModuleId);
131         globalModuleId = submoduleName;
132
133     }
134
135     /**
136      * Constraints:
137      * <ol>
138      * <li>One Belongs-to statement present</li>
139      * </ol>
140      */
141     @Override
142     public void enterSubmodule_header_stmts(Submodule_header_stmtsContext ctx) {
143         BasicValidations.checkPresentChildOfType(ctx,
144                 Belongs_to_stmtContext.class, true);
145
146         // check Yang version present, if not log
147         try {
148             BasicValidations.checkPresentYangVersion(ctx,
149                     ValidationUtil.getRootParentName(ctx));
150         } catch (Exception e) {
151             logger.debug(e.getMessage());
152         }
153     }
154
155     /**
156      * Constraints:
157      * <ol>
158      * <li>One Namespace statement present</li>
159      * <li>One Prefix statement present</li>
160      * </ol>
161      */
162     @Override
163     public void enterModule_header_stmts(Module_header_stmtsContext ctx) {
164         String moduleName = ValidationUtil.getRootParentName(ctx);
165
166         BasicValidations.checkPresentChildOfType(ctx,
167                 Namespace_stmtContext.class, true);
168         BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
169                 true);
170
171         // check Yang version present, if not log
172         try {
173             BasicValidations.checkPresentYangVersion(ctx, moduleName);
174         } catch (Exception e) {
175             logger.debug(e.getMessage());
176         }
177     }
178
179     /**
180      * Constraints:
181      * <ol>
182      * <li>Date is in valid format</li>
183      * </ol>
184      */
185     @Override
186     public void enterRevision_stmt(Revision_stmtContext ctx) {
187         BasicValidations.checkDateFormat(ctx,
188                 YangParserListenerImpl.simpleDateFormat);
189
190     }
191
192     /**
193      * Constraints:
194      * <ol>
195      * <li>Identifier is in required format</li>
196      * <li>One Prefix statement child</li>
197      * </ol>
198      */
199     @Override
200     public void enterBelongs_to_stmt(Belongs_to_stmtContext ctx) {
201         BasicValidations.checkIdentifier(ctx);
202
203         BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
204                 true);
205     }
206
207     /**
208      * Constraints:
209      * <ol>
210      * <li>Namespace string can be parsed as URI</li>
211      * </ol>
212      */
213     @Override
214     public void enterNamespace_stmt(Namespace_stmtContext ctx) {
215         String namespaceName = ValidationUtil.getName(ctx);
216         String rootParentName = ValidationUtil.getRootParentName(ctx);
217
218         try {
219             new URI(namespaceName);
220         } catch (URISyntaxException e) {
221             ValidationUtil.ex(ValidationUtil.f(
222                     "(In module:%s) Namespace:%s cannot be parsed as URI",
223                     rootParentName, namespaceName));
224         }
225     }
226
227     /**
228      * Constraints:
229      * <ol>
230      * <li>Identifier is in required format</li>
231      * <li>Every import(identified by identifier) within a module/submodule is
232      * present only once</li>
233      * <li>One prefix statement child</li>
234      * </ol>
235      */
236     @Override
237     public void enterImport_stmt(Import_stmtContext ctx) {
238
239         BasicValidations.checkIdentifier(ctx);
240
241         BasicValidations.checkUniquenessInNamespace(ctx, uniqueImports);
242
243         BasicValidations.checkPresentChildOfType(ctx, Prefix_stmtContext.class,
244                 true);
245
246     }
247
248     /**
249      * Constraints:
250      * <ol>
251      * <li>Date is in valid format</li>
252      * </ol>
253      */
254     @Override
255     public void enterRevision_date_stmt(Revision_date_stmtContext ctx) {
256         BasicValidations.checkDateFormat(ctx,
257                 YangParserListenerImpl.simpleDateFormat);
258     }
259
260     /**
261      * Constraints:
262      * <ol>
263      * <li>Identifier is in required format</li>
264      * <li>Every include(identified by identifier) within a module/submodule is
265      * present only once</li>
266      * </ol>
267      */
268     @Override
269     public void enterInclude_stmt(Include_stmtContext ctx) {
270
271         BasicValidations.checkIdentifier(ctx);
272
273         BasicValidations.checkUniquenessInNamespace(ctx, uniqueIncludes);
274     }
275
276     /**
277      * Constraints:
278      * <ol>
279      * <li>Yang-version is specified as 1</li>
280      * </ol>
281      */
282     @Override
283     public void enterYang_version_stmt(YangParser.Yang_version_stmtContext ctx) {
284         String version = ValidationUtil.getName(ctx);
285         String rootParentName = ValidationUtil.getRootParentName(ctx);
286         if (!version.equals(BasicValidations.SUPPORTED_YANG_VERSION)) {
287             ValidationUtil
288                     .ex(ValidationUtil
289                             .f("(In (sub)module:%s) Unsupported yang version:%s, supported version:%s",
290                                     rootParentName, version,
291                                     BasicValidations.SUPPORTED_YANG_VERSION));
292         }
293     }
294
295     /**
296      * Constraints:
297      * <ol>
298      * <li>Identifier is in required format</li>
299      * <li>Every prefix(identified by identifier) within a module/submodule is
300      * presented only once</li>
301      * </ol>
302      */
303     @Override
304     public void enterPrefix_stmt(Prefix_stmtContext ctx) {
305
306         BasicValidations.checkIdentifier(ctx);
307
308         BasicValidations.checkUniquenessInNamespace(ctx, uniquePrefixes);
309     }
310
311     /**
312      * Constraints:
313      * <ol>
314      * <li>Identifier is in required format</li>
315      * <li>One type statement child</li>
316      * </ol>
317      */
318     @Override
319     public void enterTypedef_stmt(Typedef_stmtContext ctx) {
320
321         BasicValidations.checkIdentifier(ctx);
322
323         BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
324                 true);
325     }
326
327     /**
328      * Constraints:
329      * <ol>
330      * <li>(Prefix):Identifier is in required format</li>
331      * </ol>
332      */
333     @Override
334     public void enterType_stmt(Type_stmtContext ctx) {
335         BasicValidations.checkPrefixedIdentifier(ctx);
336     }
337
338     /**
339      * Constraints:
340      * <ol>
341      * <li>Identifier is in required format</li>
342      * </ol>
343      */
344     @Override
345     public void enterContainer_stmt(Container_stmtContext ctx) {
346         BasicValidations.checkIdentifier(ctx);
347     }
348
349     /**
350      * Constraints:
351      * <ol>
352      * <li>Identifier is in required format</li>
353      * <li>One type statement child</li>
354      * <li>Default statement must not be present if mandatory statement is</li>
355      * </ol>
356      */
357     @Override
358     public void enterLeaf_stmt(Leaf_stmtContext ctx) {
359         BasicValidations.checkIdentifier(ctx);
360
361         BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
362                 true);
363
364         BasicValidations.checkNotPresentBoth(ctx, Mandatory_stmtContext.class,
365                 Default_stmtContext.class);
366     }
367
368     /**
369      * Constraints:
370      * <ol>
371      * <li>Identifier is in required format</li>
372      * <li>One type statement child</li>
373      * </ol>
374      */
375     @Override
376     public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) {
377
378         BasicValidations.checkIdentifier(ctx);
379
380         BasicValidations.checkPresentChildOfType(ctx, Type_stmtContext.class,
381                 true);
382     }
383
384     private static final Set<String> permittedOrderByArgs = Sets.newHashSet(
385             "system", "user");
386
387     /**
388      * Constraints:
389      * <ol>
390      * <li>Value must be one of: system, user</li>
391      * </ol>
392      */
393     @Override
394     public void enterOrdered_by_arg(Ordered_by_argContext ctx) {
395         BasicValidations.checkOnlyPermittedValues(ctx, permittedOrderByArgs);
396     }
397
398     /**
399      * Constraints:
400      * <ol>
401      * <li>Identifier is in required format</li>
402      * </ol>
403      */
404     @Override
405     public void enterList_stmt(List_stmtContext ctx) {
406         BasicValidations.checkIdentifier(ctx);
407         // TODO check: "if config==true then key must be present" could be
408         // performed
409     }
410
411     /**
412      * Constraints:
413      * <ol>
414      * <li>No duplicate keys</li>
415      * </ol>
416      */
417     @Override
418     public void enterKey_stmt(Key_stmtContext ctx) {
419         BasicValidations.getAndCheckUniqueKeys(ctx);
420     }
421
422     /**
423      * Constraints:
424      * <ol>
425      * <liNo duplicate uniques</li>
426      * </ol>
427      */
428     @Override
429     public void enterUnique_stmt(Unique_stmtContext ctx) {
430         BasicValidations.getAndCheckUniqueKeys(ctx);
431     }
432
433     /**
434      * Constraints:
435      * <ol>
436      * <li>Identifier is in required format</li>
437      * <li>Default statement must not be present if mandatory statement is</li>
438      * </ol>
439      */
440     @Override
441     public void enterChoice_stmt(Choice_stmtContext ctx) {
442         BasicValidations.checkIdentifier(ctx);
443
444         BasicValidations.checkNotPresentBoth(ctx, Mandatory_stmtContext.class,
445                 Default_stmtContext.class);
446
447     }
448
449     /**
450      * Constraints:
451      * <ol>
452      * <li>Identifier is in required format</li>
453      * </ol>
454      */
455     @Override
456     public void enterCase_stmt(Case_stmtContext ctx) {
457         BasicValidations.checkIdentifier(ctx);
458     }
459
460     private static final Set<String> permittedBooleanArgs = Sets.newHashSet(
461             "true", "false");
462
463     /**
464      * Constraints:
465      * <ol>
466      * <li>Value must be one of: true, false</li>
467      * </ol>
468      */
469     @Override
470     public void enterMandatory_arg(Mandatory_argContext ctx) {
471         BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
472     }
473
474     /**
475      * Constraints:
476      * <ol>
477      * <li>Identifier is in required format</li>
478      * </ol>
479      */
480     @Override
481     public void enterAnyxml_stmt(Anyxml_stmtContext ctx) {
482         BasicValidations.checkIdentifier(ctx);
483     }
484
485     /**
486      * Constraints:
487      * <ol>
488      * <li>Identifier is in required format</li>
489      * </ol>
490      */
491     @Override
492     public void enterGrouping_stmt(Grouping_stmtContext ctx) {
493         BasicValidations.checkIdentifier(ctx);
494     }
495
496     /**
497      * Constraints:
498      * <ol>
499      * <li>(Prefix):Identifier is in required format</li>
500      * </ol>
501      */
502     @Override
503     public void enterUses_stmt(Uses_stmtContext ctx) {
504         BasicValidations.checkPrefixedIdentifier(ctx);
505     }
506
507     /**
508      * Constraints:
509      * <ol>
510      * <li>Identifier is in required format</li>
511      * </ol>
512      */
513     @Override
514     public void enterRefine_stmt(Refine_stmtContext ctx) {
515         BasicValidations.checkIdentifier(ctx);
516     }
517
518     /**
519      * Constraints:
520      * <ol>
521      * <li>Identifier is in required format</li>
522      * </ol>
523      */
524     @Override
525     public void enterRpc_stmt(Rpc_stmtContext ctx) {
526         BasicValidations.checkIdentifier(ctx);
527     }
528
529     /**
530      * Constraints:
531      * <ol>
532      * <li>Identifier is in required format</li>
533      * </ol>
534      */
535     @Override
536     public void enterNotification_stmt(Notification_stmtContext ctx) {
537         BasicValidations.checkIdentifier(ctx);
538     }
539
540     /**
541      * Constraints:
542      * <ol>
543      * <li>Schema Node Identifier is in required format</li>
544      * </ol>
545      */
546     @Override
547     public void enterAugment_stmt(Augment_stmtContext ctx) {
548         BasicValidations.checkSchemaNodeIdentifier(ctx);
549     }
550
551     /**
552      * Constraints:
553      * <ol>
554      * <li>Identifier is in required format</li>
555      * </ol>
556      */
557     @Override
558     public void enterIdentity_stmt(Identity_stmtContext ctx) {
559         BasicValidations.checkIdentifier(ctx);
560     }
561
562     /**
563      * Constraints:
564      * <ol>
565      * <li>(Prefix):Identifier is in required format</li>
566      * </ol>
567      */
568     @Override
569     public void enterBase_stmt(Base_stmtContext ctx) {
570         BasicValidations.checkPrefixedIdentifier(ctx);
571
572     }
573
574     /**
575      * Constraints:
576      * <ol>
577      * <li>Value must be one of: true, false</li>
578      * </ol>
579      */
580     @Override
581     public void enterYin_element_arg(Yin_element_argContext ctx) {
582         BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
583     }
584
585     /**
586      * Constraints:
587      * <ol>
588      * <li>Identifier is in required format</li>
589      * </ol>
590      */
591     @Override
592     public void enterExtension_stmt(Extension_stmtContext ctx) {
593         BasicValidations.checkIdentifier(ctx);
594     }
595
596     /**
597      * Constraints:
598      * <ol>
599      * <li>Identifier is in required format</li>
600      * </ol>
601      */
602     @Override
603     public void enterArgument_stmt(Argument_stmtContext ctx) {
604         BasicValidations.checkIdentifier(ctx);
605     }
606
607     /**
608      * Constraints:
609      * <ol>
610      * <li>Identifier is in required format</li>
611      * </ol>
612      */
613     @Override
614     public void enterFeature_stmt(Feature_stmtContext ctx) {
615         BasicValidations.checkIdentifier(ctx);
616
617     }
618
619     /**
620      * Constraints:
621      * <ol>
622      * <li>(Prefix):Identifier is in required format</li>
623      * </ol>
624      */
625     @Override
626     public void enterIf_feature_stmt(If_feature_stmtContext ctx) {
627         BasicValidations.checkPrefixedIdentifier(ctx);
628     }
629
630     /**
631      * Constraints:
632      * <ol>
633      * <li>Schema Node Identifier is in required format</li>
634      * <li>At least one deviate-* statement child</li>
635      * </ol>
636      */
637     @Override
638     public void enterDeviation_stmt(Deviation_stmtContext ctx) {
639         BasicValidations.checkSchemaNodeIdentifier(ctx);
640
641         Set<Class<? extends ParseTree>> types = Sets.newHashSet();
642         types.add(Deviate_add_stmtContext.class);
643         types.add(Deviate_add_stmtContext.class);
644         BasicValidations.checkPresentChildOfTypes(ctx, types, false);
645     }
646
647     /**
648      * Constraints:
649      * <ol>
650      * <li>Value must be one of: true, false</li>
651      * </ol>
652      */
653     @Override
654     public void enterConfig_arg(Config_argContext ctx) {
655         BasicValidations.checkOnlyPermittedValues(ctx, permittedBooleanArgs);
656     }
657
658     private static final Set<String> permittedStatusArgs = Sets.newHashSet(
659             "current", "deprecated", "obsolete");
660
661     /**
662      * Constraints:
663      * <ol>
664      * <li>Value must be one of: "current", "deprecated", "obsolete"</li>
665      * </ol>
666      */
667     @Override
668     public void enterStatus_arg(Status_argContext ctx) {
669         BasicValidations.checkOnlyPermittedValues(ctx, permittedStatusArgs);
670     }
671
672 }