Add submodule lookup namespace
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / module / ModuleEffectiveStatementImpl.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.rfc7950.stmt.module;
9
10 import static com.google.common.base.Verify.verifyNotNull;
11
12 import com.google.common.collect.ImmutableMap;
13 import com.google.common.collect.ImmutableMap.Builder;
14 import com.google.common.collect.Maps;
15 import java.util.Map;
16 import java.util.Map.Entry;
17 import java.util.Objects;
18 import java.util.Optional;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.yangtools.yang.common.QNameModule;
21 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
22 import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
23 import org.opendaylight.yangtools.yang.model.api.stmt.ImportEffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.PrefixEffectiveStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleEffectiveStatement;
28 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveModule;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
30 import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
31 import org.opendaylight.yangtools.yang.parser.spi.source.IncludedSubmoduleNameToModuleCtx;
32 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
33
34 final class ModuleEffectiveStatementImpl extends AbstractEffectiveModule<ModuleStatement>
35         implements ModuleEffectiveStatement {
36     private final Map<String, SubmoduleEffectiveStatement> nameToSubmodule;
37     private final Map<String, ModuleEffectiveStatement> prefixToModule;
38     private final Map<QNameModule, String> namespaceToPrefix;
39     private final @NonNull QNameModule qnameModule;
40
41     ModuleEffectiveStatementImpl(
42             final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
43         super(ctx);
44         qnameModule = verifyNotNull(ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx));
45
46         final String localPrefix = findFirstEffectiveSubstatementArgument(PrefixEffectiveStatement.class).get();
47         final Builder<String, ModuleEffectiveStatement> prefixToModuleBuilder = ImmutableMap.builder();
48         prefixToModuleBuilder.put(localPrefix, this);
49
50         streamEffectiveSubstatements(ImportEffectiveStatement.class)
51                 .map(imp -> imp.findFirstEffectiveSubstatementArgument(PrefixEffectiveStatement.class).get())
52                 .forEach(prefix -> {
53                     final StmtContext<?, ?, ?> importedCtx =
54                             verifyNotNull(ctx.getFromNamespace(ImportPrefixToModuleCtx.class, prefix),
55                                 "Failed to resolve prefix %s", prefix);
56                     prefixToModuleBuilder.put(prefix, (ModuleEffectiveStatement) importedCtx.buildEffective());
57                 });
58         prefixToModule = prefixToModuleBuilder.build();
59
60         final Map<QNameModule, String> tmp = Maps.newLinkedHashMapWithExpectedSize(prefixToModule.size() + 1);
61         tmp.put(qnameModule, localPrefix);
62         for (Entry<String, ModuleEffectiveStatement> e : prefixToModule.entrySet()) {
63             tmp.putIfAbsent(e.getValue().localQNameModule(), e.getKey());
64         }
65         namespaceToPrefix = ImmutableMap.copyOf(tmp);
66
67         final Map<String, StmtContext<?, ?, ?>> submodules =
68                 ctx.getAllFromCurrentStmtCtxNamespace(IncludedSubmoduleNameToModuleCtx.class);
69         nameToSubmodule = submodules == null ? ImmutableMap.of() :
70             ImmutableMap.copyOf(Maps.transformValues(submodules,
71                 submodule -> (SubmoduleEffectiveStatement) submodule.buildEffective()));
72     }
73
74     @Override
75     public @NonNull QNameModule localQNameModule() {
76         return qnameModule;
77     }
78
79     @Override
80     public @NonNull QNameModule getQNameModule() {
81         return qnameModule;
82     }
83
84     @Override
85     @SuppressWarnings("unchecked")
86     public <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends Map<K, V>> getNamespaceContents(
87             final @NonNull Class<N> namespace) {
88         if (PrefixToEffectiveModuleNamespace.class.equals(namespace)) {
89             return Optional.of((Map<K, V>) prefixToModule);
90         }
91         if (QNameModuleToPrefixNamespace.class.equals(namespace)) {
92             return Optional.of((Map<K, V>) namespaceToPrefix);
93         }
94         if (NameToEffectiveSubmoduleNamespace.class.equals(namespace)) {
95             return Optional.of((Map<K, V>) nameToSubmodule);
96         }
97         return super.getNamespaceContents(namespace);
98     }
99
100     @Override
101     public int hashCode() {
102         final int prime = 31;
103         int result = 1;
104         result = prime * result + Objects.hashCode(getName());
105         result = prime * result + Objects.hashCode(getYangVersion());
106         result = prime * result + Objects.hashCode(qnameModule);
107         return result;
108     }
109
110     @Override
111     public boolean equals(final Object obj) {
112         if (this == obj) {
113             return true;
114         }
115         if (!(obj instanceof ModuleEffectiveStatementImpl)) {
116             return false;
117         }
118         ModuleEffectiveStatementImpl other = (ModuleEffectiveStatementImpl) obj;
119         if (!Objects.equals(getName(), other.getName())) {
120             return false;
121         }
122         if (!qnameModule.equals(other.qnameModule)) {
123             return false;
124         }
125         if (!Objects.equals(getYangVersion(), other.getYangVersion())) {
126             return false;
127         }
128         return true;
129     }
130 }