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