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