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