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.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
28 public final class StatementSupportBundle implements Immutable, NamespaceBehaviour.Registry {
30 private static final StatementSupportBundle EMPTY = new StatementSupportBundle(null, null, ImmutableMap.of(),
31 ImmutableMap.of(), ImmutableTable.of());
33 private final StatementSupportBundle parent;
34 private final ImmutableMap<QName, StatementSupport<?, ?, ?>> commonDefinitions;
35 private final ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificDefinitions;
36 private final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaceDefinitions;
37 private final Set<YangVersion> supportedVersions;
39 private StatementSupportBundle(final StatementSupportBundle parent,
40 final Set<YangVersion> supportedVersions,
41 final ImmutableMap<QName, StatementSupport<?, ?, ?>> commonStatements,
42 final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces,
43 final ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificStatements) {
45 this.supportedVersions = supportedVersions;
46 this.commonDefinitions = commonStatements;
47 this.namespaceDefinitions = namespaces;
48 this.versionSpecificDefinitions = versionSpecificStatements;
52 * Returns statement definitions common for all versions.
54 * @return map of common statement definitions
56 public ImmutableMap<QName, StatementSupport<?, ?, ?>> getCommonDefinitions() {
57 return commonDefinitions;
61 * Returns statement definitions specific for requested version. Result of this method does nit include common
62 * statement definitions.
66 * @return map of statement definitions specific for requested version, it
67 * doesn't include common statement definitions.
69 public ImmutableMap<QName, StatementSupport<?, ?, ?>> getDefinitionsSpecificForVersion(final YangVersion version) {
70 return versionSpecificDefinitions.row(version);
74 * Returns all version specific statement definitions. Result of this method does not include common statement
77 * @return table of all version specific statement definitions, it doesn't
78 * include common statement definitions.
80 public ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> getAllVersionSpecificDefinitions() {
81 return versionSpecificDefinitions;
84 public ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> getNamespaceDefinitions() {
85 return namespaceDefinitions;
88 public static Builder builder(final Set<YangVersion> supportedVersions) {
89 return new Builder(supportedVersions, EMPTY);
92 public static Builder derivedFrom(final StatementSupportBundle parent) {
93 return new Builder(parent.getSupportedVersions(), parent);
96 public Set<YangVersion> getSupportedVersions() {
97 return supportedVersions;
101 public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(
102 final Class<N> namespace) throws NamespaceNotAvailableException {
103 final NamespaceBehaviour<?, ?, ?> potential = namespaceDefinitions.get(namespace);
104 if (potential != null) {
105 checkState(namespace.equals(potential.getIdentifier()));
107 // Safe cast, previous checkState checks equivalence of key from which type argument are derived
108 return (NamespaceBehaviour<K, V, N>) potential;
110 if (parent != null) {
111 return parent.getNamespaceBehaviour(namespace);
116 public <K, V, N extends IdentifierNamespace<K, V>> boolean hasNamespaceBehaviour(final Class<N> namespace) {
117 if (namespaceDefinitions.containsKey(namespace)) {
120 if (parent != null) {
121 return parent.hasNamespaceBehaviour(namespace);
126 public StatementSupport<?, ?, ?> getStatementDefinition(final YangVersion version, final QName stmtName) {
127 StatementSupport<?, ?, ?> result = getVersionSpecificStatementDefinition(version, stmtName);
128 if (result == null) {
129 result = getCommonStatementDefinition(stmtName);
135 private StatementSupport<?, ?, ?> getCommonStatementDefinition(final QName stmtName) {
136 final StatementSupport<?, ?, ?> potential = commonDefinitions.get(stmtName);
137 if (potential != null) {
140 if (parent != null) {
141 return parent.getCommonStatementDefinition(stmtName);
146 private StatementSupport<?, ?, ?> getVersionSpecificStatementDefinition(final YangVersion version,
147 final QName stmtName) {
148 final StatementSupport<?, ?, ?> potential = versionSpecificDefinitions.get(version, stmtName);
149 if (potential != null) {
153 if (parent != null) {
154 return parent.getVersionSpecificStatementDefinition(version, stmtName);
159 public static class Builder implements org.opendaylight.yangtools.concepts.Builder<StatementSupportBundle> {
160 private final Map<QName, StatementSupport<?, ?, ?>> commonStatements = new HashMap<>();
161 private final Table<YangVersion, QName, StatementSupport<?, ?, ?>> versionSpecificStatements = HashBasedTable
163 private final Map<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces = new HashMap<>();
165 private final Set<YangVersion> supportedVersions;
166 private StatementSupportBundle parent;
168 Builder(final Set<YangVersion> supportedVersions, final StatementSupportBundle parent) {
169 this.parent = requireNonNull(parent);
170 this.supportedVersions = ImmutableSet.copyOf(supportedVersions);
173 public Builder addSupport(final StatementSupport<?, ?, ?> definition) {
174 final QName identifier = definition.getStatementName();
175 checkState(!commonStatements.containsKey(identifier),
176 "Statement %s already defined in common statement bundle.", identifier);
177 checkState(parent.getCommonStatementDefinition(identifier) == null,
178 "Statement %s already defined.", identifier);
179 commonStatements.put(identifier, definition);
183 public <K, V, N extends IdentifierNamespace<K, V>> Builder addSupport(
184 final NamespaceBehaviour<K, V, N> namespaceSupport) {
185 final Class<N> identifier = namespaceSupport.getIdentifier();
186 checkState(!namespaces.containsKey(identifier));
187 checkState(!parent.hasNamespaceBehaviour(identifier));
188 namespaces.put(identifier, namespaceSupport);
192 public Builder addVersionSpecificSupport(final YangVersion version,
193 final StatementSupport<?, ?, ?> definition) {
194 checkArgument(supportedVersions.contains(requireNonNull(version)));
196 final QName identifier = definition.getStatementName();
197 checkState(!commonStatements.containsKey(identifier),
198 "Statement %s already defined in common statement bundle.", identifier);
199 checkState(!versionSpecificStatements.contains(version, identifier),
200 "Statement %s already defined for version %s.", identifier, version);
201 checkState(parent.getCommonStatementDefinition(identifier) == null,
202 "Statement %s already defined in parent's common statement bundle.", identifier);
203 checkState(parent.getVersionSpecificStatementDefinition(version, identifier) == null,
204 "Statement %s already defined for version %s in parent's statement bundle.", identifier, version);
205 versionSpecificStatements.put(version, identifier, definition);
209 public Set<YangVersion> getSupportedVersions() {
210 return supportedVersions;
213 public Builder setParent(final StatementSupportBundle parent) {
214 this.parent = parent;
219 public StatementSupportBundle build() {
220 Preconditions.checkState(parent != null, "Parent must not be null");
221 return new StatementSupportBundle(parent, supportedVersions, ImmutableMap.copyOf(commonStatements),
222 ImmutableMap.copyOf(namespaces), ImmutableTable.copyOf(versionSpecificStatements));