2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.spi.meta;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkState;
12 import static java.util.Objects.requireNonNull;
14 import com.google.common.base.Preconditions;
15 import com.google.common.collect.HashBasedTable;
16 import com.google.common.collect.ImmutableMap;
17 import com.google.common.collect.ImmutableSet;
18 import com.google.common.collect.ImmutableTable;
19 import com.google.common.collect.Table;
20 import java.util.HashMap;
23 import org.opendaylight.yangtools.concepts.Immutable;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.common.YangVersion;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
29 public final class StatementSupportBundle implements Immutable, NamespaceBehaviour.Registry {
31 private static final StatementSupportBundle EMPTY = new StatementSupportBundle(null, null, ImmutableMap.of(),
32 ImmutableMap.of(), ImmutableTable.of());
34 private final StatementSupportBundle parent;
35 private final ImmutableMap<QName, StatementSupport<?, ?, ?>> commonDefinitions;
36 private final ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificDefinitions;
37 private final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaceDefinitions;
38 private final ImmutableSet<YangVersion> supportedVersions;
40 private StatementSupportBundle(final StatementSupportBundle parent,
41 final ImmutableSet<YangVersion> supportedVersions,
42 final ImmutableMap<QName, StatementSupport<?, ?, ?>> commonStatements,
43 final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces,
44 final ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificStatements) {
46 this.supportedVersions = supportedVersions;
47 this.commonDefinitions = commonStatements;
48 this.namespaceDefinitions = namespaces;
49 this.versionSpecificDefinitions = versionSpecificStatements;
53 * Returns statement definitions common for all versions.
55 * @return map of common statement definitions
57 public ImmutableMap<QName, StatementSupport<?, ?, ?>> getCommonDefinitions() {
58 return commonDefinitions;
62 * Returns statement definitions specific for requested version. Result of this method does nit include common
63 * statement definitions.
67 * @return map of statement definitions specific for requested version, it
68 * doesn't include common statement definitions.
70 public ImmutableMap<QName, StatementSupport<?, ?, ?>> getDefinitionsSpecificForVersion(final YangVersion version) {
71 return versionSpecificDefinitions.row(version);
75 * Returns all version specific statement definitions. Result of this method does not include common statement
78 * @return table of all version specific statement definitions, it doesn't
79 * include common statement definitions.
81 public ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> getAllVersionSpecificDefinitions() {
82 return versionSpecificDefinitions;
85 public ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> getNamespaceDefinitions() {
86 return namespaceDefinitions;
89 public static Builder builder(final Set<YangVersion> supportedVersions) {
90 return new Builder(supportedVersions, EMPTY);
93 public static Builder derivedFrom(final StatementSupportBundle parent) {
94 return new Builder(parent.getSupportedVersions(), parent);
97 public Set<YangVersion> getSupportedVersions() {
98 return supportedVersions;
102 @SuppressWarnings("unchecked")
103 public <K, V, N extends ParserNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(
104 final Class<N> namespace) {
105 final NamespaceBehaviour<?, ?, ?> potential = namespaceDefinitions.get(namespace);
106 if (potential != null) {
107 checkState(namespace.equals(potential.getIdentifier()));
109 // Safe cast, previous checkState checks equivalence of key from which type argument are derived
110 return (NamespaceBehaviour<K, V, N>) potential;
112 if (parent != null) {
113 return parent.getNamespaceBehaviour(namespace);
118 public <K, V, N extends ParserNamespace<K, V>> boolean hasNamespaceBehaviour(final Class<N> namespace) {
119 if (namespaceDefinitions.containsKey(namespace)) {
122 if (parent != null) {
123 return parent.hasNamespaceBehaviour(namespace);
128 public StatementSupport<?, ?, ?> getStatementDefinition(final YangVersion version, final QName stmtName) {
129 StatementSupport<?, ?, ?> result = getVersionSpecificStatementDefinition(version, stmtName);
130 if (result == null) {
131 result = getCommonStatementDefinition(stmtName);
137 private StatementSupport<?, ?, ?> getCommonStatementDefinition(final QName stmtName) {
138 final StatementSupport<?, ?, ?> potential = commonDefinitions.get(stmtName);
139 if (potential != null) {
142 if (parent != null) {
143 return parent.getCommonStatementDefinition(stmtName);
148 private StatementSupport<?, ?, ?> getVersionSpecificStatementDefinition(final YangVersion version,
149 final QName stmtName) {
150 final StatementSupport<?, ?, ?> potential = versionSpecificDefinitions.get(version, stmtName);
151 if (potential != null) {
155 if (parent != null) {
156 return parent.getVersionSpecificStatementDefinition(version, stmtName);
161 public static class Builder implements org.opendaylight.yangtools.concepts.Builder<StatementSupportBundle> {
162 private static final Logger LOG = LoggerFactory.getLogger(Builder.class);
164 private final Map<QName, StatementSupport<?, ?, ?>> commonStatements = new HashMap<>();
165 private final Table<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificStatements = HashBasedTable
167 private final Map<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces = new HashMap<>();
169 private final ImmutableSet<YangVersion> supportedVersions;
170 private StatementSupportBundle parent;
172 Builder(final Set<YangVersion> supportedVersions, final StatementSupportBundle parent) {
173 this.parent = requireNonNull(parent);
174 this.supportedVersions = ImmutableSet.copyOf(supportedVersions);
177 public Builder addSupport(final StatementSupport<?, ?, ?> support) {
178 final QName identifier = support.getStatementName();
179 checkNoParentDefinition(identifier);
181 checkState(!commonStatements.containsKey(identifier),
182 "Statement %s already defined in common statement bundle.", identifier);
183 commonStatements.put(identifier, support);
187 public <K, V, N extends ParserNamespace<K, V>> Builder addSupport(
188 final NamespaceBehaviour<K, V, N> namespaceSupport) {
189 final Class<N> identifier = namespaceSupport.getIdentifier();
190 checkState(!namespaces.containsKey(identifier));
191 checkState(!parent.hasNamespaceBehaviour(identifier));
192 namespaces.put(identifier, namespaceSupport);
196 public Builder addVersionSpecificSupport(final YangVersion version,
197 final StatementSupport<?, ?, ?> definition) {
198 checkArgument(supportedVersions.contains(requireNonNull(version)));
200 final QName identifier = definition.getStatementName();
201 checkState(!commonStatements.containsKey(identifier),
202 "Statement %s already defined in common statement bundle.", identifier);
203 checkState(!versionSpecificStatements.contains(version, identifier),
204 "Statement %s already defined for version %s.", identifier, version);
205 checkNoParentDefinition(identifier);
206 checkState(parent.getVersionSpecificStatementDefinition(version, identifier) == null,
207 "Statement %s already defined for version %s in parent's statement bundle.", identifier, version);
208 versionSpecificStatements.put(version, identifier, definition);
212 public Set<YangVersion> getSupportedVersions() {
213 return supportedVersions;
216 public Builder setParent(final StatementSupportBundle parent) {
217 this.parent = parent;
221 public Builder overrideSupport(final StatementSupport<?, ?, ?> support) {
222 final QName identifier = support.getStatementName();
223 checkNoParentDefinition(identifier);
225 final StatementSupport<?, ?, ?> previousSupport = commonStatements.replace(identifier, support);
226 checkState(previousSupport != null, "Statement %s was not previously defined", identifier);
227 LOG.debug("Changed statement {} support from {} to {}", identifier, previousSupport, support);
232 public StatementSupportBundle build() {
233 Preconditions.checkState(parent != null, "Parent must not be null");
234 return new StatementSupportBundle(parent, supportedVersions, ImmutableMap.copyOf(commonStatements),
235 ImmutableMap.copyOf(namespaces), ImmutableTable.copyOf(versionSpecificStatements));
238 private void checkNoParentDefinition(final QName identifier) {
239 checkState(parent.getCommonStatementDefinition(identifier) == null,
240 "Statement %s is defined in parent's common statement bundle", identifier);