cd5f9fd7c04cca6eadc162306d2fcf831dee9c36
[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.Rfc6020Mapping;
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(Rfc6020Mapping
53             .MODULE)
54             .addAny(Rfc6020Mapping.ANYXML)
55             .addAny(Rfc6020Mapping.AUGMENT)
56             .addAny(Rfc6020Mapping.CHOICE)
57             .addOptional(Rfc6020Mapping.CONTACT)
58             .addAny(Rfc6020Mapping.CONTAINER)
59             .addOptional(Rfc6020Mapping.DESCRIPTION)
60             .addAny(Rfc6020Mapping.DEVIATION)
61             .addAny(Rfc6020Mapping.EXTENSION)
62             .addAny(Rfc6020Mapping.FEATURE)
63             .addAny(Rfc6020Mapping.GROUPING)
64             .addAny(Rfc6020Mapping.IDENTITY)
65             .addAny(Rfc6020Mapping.IMPORT)
66             .addAny(Rfc6020Mapping.INCLUDE)
67             .addAny(Rfc6020Mapping.LEAF)
68             .addAny(Rfc6020Mapping.LEAF_LIST)
69             .addAny(Rfc6020Mapping.LIST)
70             .addMandatory(Rfc6020Mapping.NAMESPACE)
71             .addAny(Rfc6020Mapping.NOTIFICATION)
72             .addOptional(Rfc6020Mapping.ORGANIZATION)
73             .addMandatory(Rfc6020Mapping.PREFIX)
74             .addOptional(Rfc6020Mapping.REFERENCE)
75             .addAny(Rfc6020Mapping.REVISION)
76             .addAny(Rfc6020Mapping.RPC)
77             .addAny(Rfc6020Mapping.TYPEDEF)
78             .addAny(Rfc6020Mapping.USES)
79             .addOptional(Rfc6020Mapping.YANG_VERSION)
80             .addOptional(SupportedExtensionsMapping.SEMANTIC_VERSION)
81             .build();
82
83     public ModuleStatementSupport() {
84         super(Rfc6020Mapping.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(),
108                 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);
112
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);
117
118         stmt.addContext(PreLinkageModuleNamespace.class, moduleName, stmt);
119
120         Optional<Date> revisionDate = Optional.ofNullable(Utils.getLatestRevision(stmt.declaredSubstatements()));
121         if (!revisionDate.isPresent()) {
122             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
123         }
124
125         QNameModule qNameModule = QNameModule.create(moduleNs, revisionDate.orElse(null)).intern();
126
127         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule);
128     };
129
130     @Override
131     public void onLinkageDeclared(final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
132
133         Optional<URI> moduleNs = Optional.ofNullable(firstAttributeOf(stmt.declaredSubstatements(),
134                 NamespaceStatement.class));
135         SourceException.throwIf(!moduleNs.isPresent(), stmt.getStatementSourceReference(),
136             "Namespace of the module [%s] is missing", stmt.getStatementArgument());
137
138         Optional<Date> revisionDate = Optional.ofNullable(Utils.getLatestRevision(stmt.declaredSubstatements()));
139         if (!revisionDate.isPresent()) {
140             revisionDate = Optional.of(SimpleDateFormatUtil.DEFAULT_DATE_REV);
141         }
142
143         QNameModule qNameModule = QNameModule.create(moduleNs.get(), revisionDate.orElse(null)).intern();
144         ModuleIdentifier moduleIdentifier = ModuleIdentifierImpl.create(stmt.getStatementArgument(),
145                 Optional.empty(), revisionDate);
146
147         stmt.addContext(ModuleNamespace.class, moduleIdentifier, stmt);
148         stmt.addContext(ModuleNamespaceForBelongsTo.class, moduleIdentifier.getName(), stmt);
149         stmt.addContext(NamespaceToModule.class, qNameModule, stmt);
150
151         final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
152         SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
153             "Prefix of the module [%s] is missing", stmt.getStatementArgument());
154
155         stmt.addToNs(PrefixToModule.class, modulePrefix, qNameModule);
156         stmt.addToNs(ModuleNameToModuleQName.class, stmt.getStatementArgument(), qNameModule);
157         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule); // tu
158         stmt.addToNs(ModuleCtxToModuleIdentifier.class, stmt, moduleIdentifier);
159         stmt.addToNs(ModuleQNameToModuleName.class, qNameModule, stmt.getStatementArgument());
160         stmt.addToNs(ModuleIdentifierToModuleQName.class, moduleIdentifier, qNameModule);
161         stmt.addToNs(ImpPrefixToModuleIdentifier.class, modulePrefix, moduleIdentifier);
162
163         if (stmt.isEnabledSemanticVersioning()) {
164             addToSemVerModuleNamespace(stmt);
165         }
166     }
167
168     private static void addToSemVerModuleNamespace(
169             final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
170         final String moduleName = stmt.getStatementArgument();
171         NavigableMap<SemVer, StmtContext<?, ?, ?>> modulesMap = stmt.getFromNamespace(
172                 SemanticVersionModuleNamespace.class, moduleName);
173         if (modulesMap == null) {
174             modulesMap = new TreeMap<>();
175         }
176         SemVer moduleSemVer = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
177         if(moduleSemVer == null) {
178             moduleSemVer = Module.DEFAULT_SEMANTIC_VERSION;
179         }
180         modulesMap.put(moduleSemVer, stmt);
181         stmt.addToNs(SemanticVersionModuleNamespace.class, moduleName, modulesMap);
182     }
183
184     @Override
185     public void onFullDefinitionDeclared(final Mutable<String, ModuleStatement,
186             EffectiveStatement<String, ModuleStatement>> stmt) {
187         super.onFullDefinitionDeclared(stmt);
188         SUBSTATEMENT_VALIDATOR.validate(stmt);
189     }
190 }