BUG-7052: Move qnameFromArgument to StmtContextUtils
[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.meta.StmtContextUtils.firstAttributeOf;
11
12 import java.net.URI;
13 import java.util.Date;
14 import java.util.NavigableMap;
15 import java.util.Optional;
16 import java.util.TreeMap;
17 import org.opendaylight.yangtools.concepts.SemVer;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
20 import org.opendaylight.yangtools.yang.model.api.Module;
21 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
22 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.NamespaceStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
27 import org.opendaylight.yangtools.yang.model.util.ModuleIdentifierImpl;
28 import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
29 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
30 import org.opendaylight.yangtools.yang.parser.spi.PreLinkageModuleNamespace;
31 import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.SemanticVersionModuleNamespace;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.SemanticVersionNamespace;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
37 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
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(YangStmtMapping
54             .MODULE)
55             .addAny(YangStmtMapping.ANYXML)
56             .addAny(YangStmtMapping.AUGMENT)
57             .addAny(YangStmtMapping.CHOICE)
58             .addOptional(YangStmtMapping.CONTACT)
59             .addAny(YangStmtMapping.CONTAINER)
60             .addOptional(YangStmtMapping.DESCRIPTION)
61             .addAny(YangStmtMapping.DEVIATION)
62             .addAny(YangStmtMapping.EXTENSION)
63             .addAny(YangStmtMapping.FEATURE)
64             .addAny(YangStmtMapping.GROUPING)
65             .addAny(YangStmtMapping.IDENTITY)
66             .addAny(YangStmtMapping.IMPORT)
67             .addAny(YangStmtMapping.INCLUDE)
68             .addAny(YangStmtMapping.LEAF)
69             .addAny(YangStmtMapping.LEAF_LIST)
70             .addAny(YangStmtMapping.LIST)
71             .addMandatory(YangStmtMapping.NAMESPACE)
72             .addAny(YangStmtMapping.NOTIFICATION)
73             .addOptional(YangStmtMapping.ORGANIZATION)
74             .addMandatory(YangStmtMapping.PREFIX)
75             .addOptional(YangStmtMapping.REFERENCE)
76             .addAny(YangStmtMapping.REVISION)
77             .addAny(YangStmtMapping.RPC)
78             .addAny(YangStmtMapping.TYPEDEF)
79             .addAny(YangStmtMapping.USES)
80             .addOptional(YangStmtMapping.YANG_VERSION)
81             .addOptional(SupportedExtensionsMapping.OPENCONFIG_VERSION)
82             .build();
83
84     public ModuleStatementSupport() {
85         super(YangStmtMapping.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(final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
106         final String moduleName = stmt.getStatementArgument();
107
108         final URI moduleNs = firstAttributeOf(stmt.declaredSubstatements(), NamespaceStatement.class);
109         SourceException.throwIfNull(moduleNs, stmt.getStatementSourceReference(),
110             "Namespace of the module [%s] is missing", stmt.getStatementArgument());
111         stmt.addToNs(ModuleNameToNamespace.class, moduleName, moduleNs);
112
113         final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
114         SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
115             "Prefix of the module [%s] is missing", stmt.getStatementArgument());
116         stmt.addToNs(ImpPrefixToNamespace.class, modulePrefix, moduleNs);
117
118         stmt.addContext(PreLinkageModuleNamespace.class, moduleName, stmt);
119
120         Optional<Date> revisionDate = Optional.ofNullable(StmtContextUtils.getLatestRevision(
121             stmt.declaredSubstatements()));
122         if (!revisionDate.isPresent()) {
123             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
124         }
125
126         final QNameModule qNameModule = QNameModule.create(moduleNs, revisionDate.orElse(null)).intern();
127
128         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule);
129         stmt.setRootIdentifier(ModuleIdentifierImpl.create(stmt.getStatementArgument(),
130                 Optional.empty(), revisionDate));
131     }
132
133     @Override
134     public void onLinkageDeclared(final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
135
136         final Optional<URI> moduleNs = Optional.ofNullable(firstAttributeOf(stmt.declaredSubstatements(),
137                 NamespaceStatement.class));
138         SourceException.throwIf(!moduleNs.isPresent(), stmt.getStatementSourceReference(),
139             "Namespace of the module [%s] is missing", stmt.getStatementArgument());
140
141         Optional<Date> revisionDate = Optional.ofNullable(StmtContextUtils.getLatestRevision(
142             stmt.declaredSubstatements()));
143         if (!revisionDate.isPresent()) {
144             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
145         }
146
147         final QNameModule qNameModule = QNameModule.create(moduleNs.get(), revisionDate.orElse(null)).intern();
148
149         final StmtContext<?, ModuleStatement, EffectiveStatement<String, ModuleStatement>> possibleDuplicateModule =
150                 stmt.getFromNamespace(NamespaceToModule.class, qNameModule);
151         if (possibleDuplicateModule != null && possibleDuplicateModule != stmt) {
152             throw new SourceException(stmt.getStatementSourceReference(), "Module namespace collision: %s. At %s",
153                     qNameModule.getNamespace(), possibleDuplicateModule.getStatementSourceReference());
154         }
155
156         final ModuleIdentifier moduleIdentifier = ModuleIdentifierImpl.create(stmt.getStatementArgument(),
157                 Optional.empty(), revisionDate);
158
159         stmt.addContext(ModuleNamespace.class, moduleIdentifier, stmt);
160         stmt.addContext(ModuleNamespaceForBelongsTo.class, moduleIdentifier.getName(), stmt);
161         stmt.addContext(NamespaceToModule.class, qNameModule, stmt);
162
163         final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
164         SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
165             "Prefix of the module [%s] is missing", stmt.getStatementArgument());
166
167         stmt.addToNs(PrefixToModule.class, modulePrefix, qNameModule);
168         stmt.addToNs(ModuleNameToModuleQName.class, stmt.getStatementArgument(), qNameModule);
169         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule); // tu
170         stmt.addToNs(ModuleCtxToModuleIdentifier.class, stmt, moduleIdentifier);
171         stmt.addToNs(ModuleQNameToModuleName.class, qNameModule, stmt.getStatementArgument());
172         stmt.addToNs(ModuleIdentifierToModuleQName.class, moduleIdentifier, qNameModule);
173         stmt.addToNs(ImpPrefixToModuleIdentifier.class, modulePrefix, moduleIdentifier);
174
175         if (stmt.isEnabledSemanticVersioning()) {
176             addToSemVerModuleNamespace(stmt);
177         }
178     }
179
180     private static void addToSemVerModuleNamespace(
181             final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
182         final String moduleName = stmt.getStatementArgument();
183         NavigableMap<SemVer, StmtContext<?, ?, ?>> modulesMap = stmt.getFromNamespace(
184                 SemanticVersionModuleNamespace.class, moduleName);
185         if (modulesMap == null) {
186             modulesMap = new TreeMap<>();
187         }
188         SemVer moduleSemVer = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
189         if(moduleSemVer == null) {
190             moduleSemVer = Module.DEFAULT_SEMANTIC_VERSION;
191         }
192         modulesMap.put(moduleSemVer, stmt);
193         stmt.addToNs(SemanticVersionModuleNamespace.class, moduleName, modulesMap);
194     }
195
196     @Override
197     protected SubstatementValidator getSubstatementValidator() {
198         return SUBSTATEMENT_VALIDATOR;
199     }
200 }