Bug 6878: Add support for parsing yang-specific XPath functions
[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         final ModuleIdentifier moduleIdentifier = ModuleIdentifierImpl.create(stmt.getStatementArgument(),
146                 Optional.empty(), revisionDate);
147
148         stmt.addContext(ModuleNamespace.class, moduleIdentifier, stmt);
149         stmt.addContext(ModuleNamespaceForBelongsTo.class, moduleIdentifier.getName(), stmt);
150         stmt.addContext(NamespaceToModule.class, qNameModule, stmt);
151
152         final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
153         SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
154             "Prefix of the module [%s] is missing", stmt.getStatementArgument());
155
156         stmt.addToNs(PrefixToModule.class, modulePrefix, qNameModule);
157         stmt.addToNs(ModuleNameToModuleQName.class, stmt.getStatementArgument(), qNameModule);
158         stmt.addToNs(ModuleCtxToModuleQName.class, stmt, qNameModule); // tu
159         stmt.addToNs(ModuleCtxToModuleIdentifier.class, stmt, moduleIdentifier);
160         stmt.addToNs(ModuleQNameToModuleName.class, qNameModule, stmt.getStatementArgument());
161         stmt.addToNs(ModuleIdentifierToModuleQName.class, moduleIdentifier, qNameModule);
162         stmt.addToNs(ImpPrefixToModuleIdentifier.class, modulePrefix, moduleIdentifier);
163
164         if (stmt.isEnabledSemanticVersioning()) {
165             addToSemVerModuleNamespace(stmt);
166         }
167     }
168
169     private static void addToSemVerModuleNamespace(
170             final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
171         final String moduleName = stmt.getStatementArgument();
172         NavigableMap<SemVer, StmtContext<?, ?, ?>> modulesMap = stmt.getFromNamespace(
173                 SemanticVersionModuleNamespace.class, moduleName);
174         if (modulesMap == null) {
175             modulesMap = new TreeMap<>();
176         }
177         SemVer moduleSemVer = stmt.getFromNamespace(SemanticVersionNamespace.class, stmt);
178         if(moduleSemVer == null) {
179             moduleSemVer = Module.DEFAULT_SEMANTIC_VERSION;
180         }
181         modulesMap.put(moduleSemVer, stmt);
182         stmt.addToNs(SemanticVersionModuleNamespace.class, moduleName, modulesMap);
183     }
184
185     @Override
186     protected SubstatementValidator getSubstatementValidator() {
187         return SUBSTATEMENT_VALIDATOR;
188     }
189 }