2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
10 import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
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.ModuleIdentifier;
21 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
22 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
23 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.NamespaceStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
26 import org.opendaylight.yangtools.yang.model.util.ModuleIdentifierImpl;
27 import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
28 import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
29 import org.opendaylight.yangtools.yang.parser.spi.PreLinkageModuleNamespace;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.SemanticVersionModuleNamespace;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.SemanticVersionNamespace;
33 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
34 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
37 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
38 import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
39 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleIdentifier;
40 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
41 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
42 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
43 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToNamespace;
44 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNamespaceForBelongsTo;
45 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleQNameToModuleName;
46 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
47 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
48 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.ModuleEffectiveStatementImpl;
50 public class ModuleStatementSupport extends
51 AbstractStatementSupport<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> {
52 private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping
54 .addAny(YangStmtMapping.ANYXML)
55 .addAny(YangStmtMapping.AUGMENT)
56 .addAny(YangStmtMapping.CHOICE)
57 .addOptional(YangStmtMapping.CONTACT)
58 .addAny(YangStmtMapping.CONTAINER)
59 .addOptional(YangStmtMapping.DESCRIPTION)
60 .addAny(YangStmtMapping.DEVIATION)
61 .addAny(YangStmtMapping.EXTENSION)
62 .addAny(YangStmtMapping.FEATURE)
63 .addAny(YangStmtMapping.GROUPING)
64 .addAny(YangStmtMapping.IDENTITY)
65 .addAny(YangStmtMapping.IMPORT)
66 .addAny(YangStmtMapping.INCLUDE)
67 .addAny(YangStmtMapping.LEAF)
68 .addAny(YangStmtMapping.LEAF_LIST)
69 .addAny(YangStmtMapping.LIST)
70 .addMandatory(YangStmtMapping.NAMESPACE)
71 .addAny(YangStmtMapping.NOTIFICATION)
72 .addOptional(YangStmtMapping.ORGANIZATION)
73 .addMandatory(YangStmtMapping.PREFIX)
74 .addOptional(YangStmtMapping.REFERENCE)
75 .addAny(YangStmtMapping.REVISION)
76 .addAny(YangStmtMapping.RPC)
77 .addAny(YangStmtMapping.TYPEDEF)
78 .addAny(YangStmtMapping.USES)
79 .addOptional(YangStmtMapping.YANG_VERSION)
80 .addOptional(SupportedExtensionsMapping.OPENCONFIG_VERSION)
83 public ModuleStatementSupport() {
84 super(YangStmtMapping.MODULE);
88 public String parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
93 public ModuleStatement createDeclared(final StmtContext<String, ModuleStatement, ?> ctx) {
94 return new ModuleStatementImpl(ctx);
98 public EffectiveStatement<String, ModuleStatement> createEffective(
99 final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
100 return new ModuleEffectiveStatementImpl(ctx);
104 public void onPreLinkageDeclared(final Mutable<String, ModuleStatement,
105 EffectiveStatement<String, ModuleStatement>> stmt) {
106 final String moduleName = stmt.getStatementArgument();
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);
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);
118 stmt.addContext(PreLinkageModuleNamespace.class, moduleName, stmt);
120 Optional<Date> revisionDate = Optional.ofNullable(StmtContextUtils.getLatestRevision(
121 stmt.declaredSubstatements()));
122 if (!revisionDate.isPresent()) {
123 revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
126 final QNameModule qNameModule = QNameModule.create(moduleNs, revisionDate.orElse(null)).intern();
128 stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule);
129 stmt.setRootIdentifier(ModuleIdentifierImpl.create(stmt.getStatementArgument(),
130 Optional.empty(), revisionDate));
134 public void onLinkageDeclared(final Mutable<String, ModuleStatement,
135 EffectiveStatement<String, ModuleStatement>> stmt) {
137 final Optional<URI> moduleNs = Optional.ofNullable(firstAttributeOf(stmt.declaredSubstatements(),
138 NamespaceStatement.class));
139 SourceException.throwIf(!moduleNs.isPresent(), stmt.getStatementSourceReference(),
140 "Namespace of the module [%s] is missing", stmt.getStatementArgument());
142 Optional<Date> revisionDate = Optional.ofNullable(StmtContextUtils.getLatestRevision(
143 stmt.declaredSubstatements()));
144 if (!revisionDate.isPresent()) {
145 revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
148 final QNameModule qNameModule = QNameModule.create(moduleNs.get(), revisionDate.orElse(null)).intern();
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());
156 final ModuleIdentifier moduleIdentifier = ModuleIdentifierImpl.create(stmt.getStatementArgument(),
157 Optional.empty(), revisionDate);
159 stmt.addContext(ModuleNamespace.class, moduleIdentifier, stmt);
160 stmt.addContext(ModuleNamespaceForBelongsTo.class, moduleIdentifier.getName(), stmt);
161 stmt.addContext(NamespaceToModule.class, qNameModule, stmt);
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());
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);
175 if (stmt.isEnabledSemanticVersioning()) {
176 addToSemVerModuleNamespace(stmt);
180 private static int compareNullableSemVer(final SemVer ver1, final SemVer ver2) {
182 return ver2 == null ? 0 : -1;
185 return ver2 == null ? 1 : ver1.compareTo(ver2);
188 private static void addToSemVerModuleNamespace(
189 final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
190 final String moduleName = stmt.getStatementArgument();
191 NavigableMap<SemVer, StmtContext<?, ?, ?>> modulesMap = stmt.getFromNamespace(
192 SemanticVersionModuleNamespace.class, moduleName);
193 if (modulesMap == null) {
194 modulesMap = new TreeMap<>(ModuleStatementSupport::compareNullableSemVer);
196 final SemVer moduleSemVer = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
197 modulesMap.put(moduleSemVer, stmt);
198 stmt.addToNs(SemanticVersionModuleNamespace.class, moduleName, modulesMap);
202 protected SubstatementValidator getSubstatementValidator() {
203 return SUBSTATEMENT_VALIDATOR;