2fbdad58e6fd3ee36e41cd8e754b1a4d7b34ccbf
[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.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;
49
50 public class ModuleStatementSupport extends
51         AbstractStatementSupport<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> {
52     private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(YangStmtMapping
53             .MODULE)
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.SEMANTIC_VERSION)
81             .build();
82
83     public ModuleStatementSupport() {
84         super(YangStmtMapping.MODULE);
85     }
86
87     @Override
88     public String parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
89         return value;
90     }
91
92     @Override
93     public ModuleStatement createDeclared(final StmtContext<String, ModuleStatement, ?> ctx) {
94         return new ModuleStatementImpl(ctx);
95     }
96
97     @Override
98     public EffectiveStatement<String, ModuleStatement> createEffective(
99             final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
100         return new ModuleEffectiveStatementImpl(ctx);
101     }
102
103     @Override
104     public void onPreLinkageDeclared(final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
105         final String moduleName = stmt.getStatementArgument();
106
107         final URI moduleNs = firstAttributeOf(stmt.declaredSubstatements(), NamespaceStatement.class);
108         SourceException.throwIfNull(moduleNs, stmt.getStatementSourceReference(),
109             "Namespace of the module [%s] is missing", stmt.getStatementArgument());
110         stmt.addToNs(ModuleNameToNamespace.class, moduleName, moduleNs);
111
112         final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
113         SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
114             "Prefix of the module [%s] is missing", stmt.getStatementArgument());
115         stmt.addToNs(ImpPrefixToNamespace.class, modulePrefix, moduleNs);
116
117         stmt.addContext(PreLinkageModuleNamespace.class, moduleName, stmt);
118
119         Optional<Date> revisionDate = Optional.ofNullable(Utils.getLatestRevision(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(),
128                 Optional.empty(), revisionDate));
129     }
130
131     @Override
132     public void onLinkageDeclared(final Mutable<String, ModuleStatement, 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(Utils.getLatestRevision(stmt.declaredSubstatements()));
140         if (!revisionDate.isPresent()) {
141             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
142         }
143
144         final QNameModule qNameModule = QNameModule.create(moduleNs.get(), revisionDate.orElse(null)).intern();
145
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                 Optional.empty(), 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(ModuleIdentifierToModuleQName.class, moduleIdentifier, qNameModule);
170         stmt.addToNs(ImpPrefixToModuleIdentifier.class, modulePrefix, moduleIdentifier);
171
172         if (stmt.isEnabledSemanticVersioning()) {
173             addToSemVerModuleNamespace(stmt);
174         }
175     }
176
177     private static void addToSemVerModuleNamespace(
178             final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
179         final String moduleName = stmt.getStatementArgument();
180         NavigableMap<SemVer, StmtContext<?, ?, ?>> modulesMap = stmt.getFromNamespace(
181                 SemanticVersionModuleNamespace.class, moduleName);
182         if (modulesMap == null) {
183             modulesMap = new TreeMap<>();
184         }
185         SemVer moduleSemVer = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
186         if(moduleSemVer == null) {
187             moduleSemVer = Module.DEFAULT_SEMANTIC_VERSION;
188         }
189         modulesMap.put(moduleSemVer, stmt);
190         stmt.addToNs(SemanticVersionModuleNamespace.class, moduleName, modulesMap);
191     }
192
193     @Override
194     protected SubstatementValidator getSubstatementValidator() {
195         return SUBSTATEMENT_VALIDATOR;
196     }
197 }