Bug 6244: Add context to exceptions thrown by yang statement parser
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / ModuleStatementSupport.java
1 /*
2  * Copyright (c) 2015 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.parser.stmt.rfc6020;
9
10 import static org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator.MAX;
11 import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
12
13 import com.google.common.base.Optional;
14 import java.net.URI;
15 import java.util.Date;
16 import java.util.NavigableMap;
17 import java.util.TreeMap;
18 import org.opendaylight.yangtools.concepts.SemVer;
19 import org.opendaylight.yangtools.yang.common.QNameModule;
20 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
21 import org.opendaylight.yangtools.yang.model.api.Module;
22 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
23 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
24 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.NamespaceStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
28 import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleIdentifierImpl;
29 import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
30 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
31 import org.opendaylight.yangtools.yang.parser.spi.PreLinkageModuleNamespace;
32 import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.SemanticVersionModuleNamespace;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.SemanticVersionNamespace;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
38 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
39 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
40 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleIdentifier;
41 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
42 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
43 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
44 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToNamespace;
45 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNamespaceForBelongsTo;
46 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleQNameToModuleName;
47 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
48 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
49 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.ModuleEffectiveStatementImpl;
50
51 public class ModuleStatementSupport extends
52         AbstractStatementSupport<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> {
53     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(Rfc6020Mapping
54             .MODULE)
55             .add(Rfc6020Mapping.ANYXML, 0, MAX)
56             .add(Rfc6020Mapping.AUGMENT, 0, MAX)
57             .add(Rfc6020Mapping.CHOICE, 0, MAX)
58             .add(Rfc6020Mapping.CONTACT, 0, 1)
59             .add(Rfc6020Mapping.CONTAINER, 0, MAX)
60             .add(Rfc6020Mapping.DESCRIPTION, 0, 1)
61             .add(Rfc6020Mapping.DEVIATION, 0, MAX)
62             .add(Rfc6020Mapping.EXTENSION, 0, MAX)
63             .add(Rfc6020Mapping.FEATURE, 0, MAX)
64             .add(Rfc6020Mapping.GROUPING, 0, MAX)
65             .add(Rfc6020Mapping.IDENTITY, 0, MAX)
66             .add(Rfc6020Mapping.IMPORT, 0, MAX)
67             .add(Rfc6020Mapping.INCLUDE, 0, MAX)
68             .add(Rfc6020Mapping.LEAF, 0, MAX)
69             .add(Rfc6020Mapping.LEAF_LIST, 0, MAX)
70             .add(Rfc6020Mapping.LIST, 0, MAX)
71             .add(Rfc6020Mapping.NAMESPACE, 1, 1)
72             .add(Rfc6020Mapping.NOTIFICATION, 0, MAX)
73             .add(Rfc6020Mapping.ORGANIZATION, 0, 1)
74             .add(Rfc6020Mapping.PREFIX, 1, 1)
75             .add(Rfc6020Mapping.REFERENCE, 0, 1)
76             .add(Rfc6020Mapping.REVISION, 0, MAX)
77             .add(Rfc6020Mapping.RPC, 0, MAX)
78             .add(Rfc6020Mapping.TYPEDEF, 0, MAX)
79             .add(Rfc6020Mapping.USES, 0, MAX)
80             .add(Rfc6020Mapping.YANG_VERSION, 0, 1)
81             .add(SupportedExtensionsMapping.SEMANTIC_VERSION, 0, 1)
82             .build();
83
84     public ModuleStatementSupport() {
85         super(Rfc6020Mapping.MODULE);
86     }
87
88     @Override
89     public String parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
90         return value;
91     }
92
93     @Override
94     public ModuleStatement createDeclared(final StmtContext<String, ModuleStatement, ?> ctx) {
95         return new ModuleStatementImpl(ctx);
96     }
97
98     @Override
99     public EffectiveStatement<String, ModuleStatement> createEffective(
100             final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
101         return new ModuleEffectiveStatementImpl(ctx);
102     }
103
104     @Override
105     public void onPreLinkageDeclared(Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
106         final String moduleName = stmt.getStatementArgument();
107
108         final URI moduleNs = firstAttributeOf(stmt.declaredSubstatements(),
109                 NamespaceStatement.class);
110         SourceException.throwIfNull(moduleNs, stmt.getStatementSourceReference(),
111             "Namespace of the module [%s] is missing", stmt.getStatementArgument());
112         stmt.addToNs(ModuleNameToNamespace.class, moduleName, moduleNs);
113
114         final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
115         SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
116             "Prefix of the module [%s] is missing", stmt.getStatementArgument());
117         stmt.addToNs(ImpPrefixToNamespace.class, modulePrefix, moduleNs);
118
119         stmt.addContext(PreLinkageModuleNamespace.class, moduleName, stmt);
120
121         Optional<Date> revisionDate = Optional.fromNullable(Utils.getLatestRevision(stmt.declaredSubstatements
122                 ()));
123         if (!revisionDate.isPresent()) {
124             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
125         }
126
127         QNameModule qNameModule = QNameModule.create(moduleNs, revisionDate.orNull()).intern();
128
129         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule);
130     };
131
132     @Override
133     public void onLinkageDeclared(final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
134
135         Optional<URI> moduleNs = Optional.fromNullable(firstAttributeOf(stmt.declaredSubstatements(),
136                 NamespaceStatement.class));
137         SourceException.throwIf(!moduleNs.isPresent(), stmt.getStatementSourceReference(),
138             "Namespace of the module [%s] is missing", stmt.getStatementArgument());
139
140         Optional<Date> revisionDate = Optional.fromNullable(Utils.getLatestRevision(stmt.declaredSubstatements()));
141         if (!revisionDate.isPresent()) {
142             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
143         }
144
145         QNameModule qNameModule = QNameModule.create(moduleNs.get(), revisionDate.orNull()).intern();
146         ModuleIdentifier moduleIdentifier = new ModuleIdentifierImpl(stmt.getStatementArgument(),
147                 Optional.absent(), revisionDate);
148
149         stmt.addContext(ModuleNamespace.class, moduleIdentifier, stmt);
150         stmt.addContext(ModuleNamespaceForBelongsTo.class, moduleIdentifier.getName(), stmt);
151         stmt.addContext(NamespaceToModule.class, qNameModule, stmt);
152
153         final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
154         SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
155             "Prefix of the module [%s] is missing", stmt.getStatementArgument());
156
157         stmt.addToNs(PrefixToModule.class, modulePrefix, qNameModule);
158         stmt.addToNs(ModuleNameToModuleQName.class, stmt.getStatementArgument(), qNameModule);
159         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule); // tu
160         stmt.addToNs(ModuleCtxToModuleIdentifier.class, stmt, moduleIdentifier);
161         stmt.addToNs(ModuleQNameToModuleName.class, qNameModule, stmt.getStatementArgument());
162         stmt.addToNs(ModuleIdentifierToModuleQName.class, moduleIdentifier, qNameModule);
163         stmt.addToNs(ImpPrefixToModuleIdentifier.class, modulePrefix, moduleIdentifier);
164
165         if (stmt.isEnabledSemanticVersioning()) {
166             addToSemVerModuleNamespace(stmt);
167         }
168     }
169
170     private void addToSemVerModuleNamespace(
171             final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
172         final String moduleName = stmt.getStatementArgument();
173         NavigableMap<SemVer, StmtContext<?, ?, ?>> modulesMap = stmt.getFromNamespace(
174                 SemanticVersionModuleNamespace.class, moduleName);
175         if (modulesMap == null) {
176             modulesMap = new TreeMap<SemVer, StmtContext<?, ?, ?>>();
177         }
178         SemVer moduleSemVer = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
179         if(moduleSemVer == null) {
180             moduleSemVer = Module.DEFAULT_SEMANTIC_VERSION;
181         }
182         modulesMap.put(moduleSemVer, stmt);
183         stmt.addToNs(SemanticVersionModuleNamespace.class, moduleName, modulesMap);
184     }
185
186     @Override
187     public void onFullDefinitionDeclared(final Mutable<String, ModuleStatement,
188             EffectiveStatement<String, ModuleStatement>> stmt) {
189         super.onFullDefinitionDeclared(stmt);
190         SUBSTATEMENT_VALIDATOR.validate(stmt);
191     }
192 }