BUG-5222: Optimize use of declared substatements
[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     }
128
129     @Override
130     public void onLinkageDeclared(final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
131
132         final Optional<URI> moduleNs = Optional.ofNullable(firstAttributeOf(stmt.declaredSubstatements(),
133                 NamespaceStatement.class));
134         SourceException.throwIf(!moduleNs.isPresent(), stmt.getStatementSourceReference(),
135             "Namespace of the module [%s] is missing", stmt.getStatementArgument());
136
137         Optional<Date> revisionDate = Optional.ofNullable(Utils.getLatestRevision(stmt.declaredSubstatements()));
138         if (!revisionDate.isPresent()) {
139             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
140         }
141
142         final QNameModule qNameModule = QNameModule.create(moduleNs.get(), revisionDate.orElse(null)).intern();
143         final ModuleIdentifier moduleIdentifier = ModuleIdentifierImpl.create(stmt.getStatementArgument(),
144                 Optional.empty(), revisionDate);
145
146         stmt.addContext(ModuleNamespace.class, moduleIdentifier, stmt);
147         stmt.addContext(ModuleNamespaceForBelongsTo.class, moduleIdentifier.getName(), stmt);
148         stmt.addContext(NamespaceToModule.class, qNameModule, stmt);
149
150         final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
151         SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
152             "Prefix of the module [%s] is missing", stmt.getStatementArgument());
153
154         stmt.addToNs(PrefixToModule.class, modulePrefix, qNameModule);
155         stmt.addToNs(ModuleNameToModuleQName.class, stmt.getStatementArgument(), qNameModule);
156         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule); // tu
157         stmt.addToNs(ModuleCtxToModuleIdentifier.class, stmt, moduleIdentifier);
158         stmt.addToNs(ModuleQNameToModuleName.class, qNameModule, stmt.getStatementArgument());
159         stmt.addToNs(ModuleIdentifierToModuleQName.class, moduleIdentifier, qNameModule);
160         stmt.addToNs(ImpPrefixToModuleIdentifier.class, modulePrefix, moduleIdentifier);
161
162         if (stmt.isEnabledSemanticVersioning()) {
163             addToSemVerModuleNamespace(stmt);
164         }
165     }
166
167     private static void addToSemVerModuleNamespace(
168             final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
169         final String moduleName = stmt.getStatementArgument();
170         NavigableMap<SemVer, StmtContext<?, ?, ?>> modulesMap = stmt.getFromNamespace(
171                 SemanticVersionModuleNamespace.class, moduleName);
172         if (modulesMap == null) {
173             modulesMap = new TreeMap<>();
174         }
175         SemVer moduleSemVer = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
176         if(moduleSemVer == null) {
177             moduleSemVer = Module.DEFAULT_SEMANTIC_VERSION;
178         }
179         modulesMap.put(moduleSemVer, stmt);
180         stmt.addToNs(SemanticVersionModuleNamespace.class, moduleName, modulesMap);
181     }
182
183     @Override
184     protected SubstatementValidator getSubstatementValidator() {
185         return SUBSTATEMENT_VALIDATOR;
186     }
187 }