Cleanup use of Guava library
[yangtools.git] / yang / yang-parser-spi / src / main / java / org / opendaylight / yangtools / yang / parser / spi / meta / StatementSupportBundle.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.spi.meta;
9
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;
13
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;
21 import java.util.Map;
22 import java.util.Set;
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;
27
28 public final class StatementSupportBundle implements Immutable, NamespaceBehaviour.Registry {
29
30     private static final StatementSupportBundle EMPTY = new StatementSupportBundle(null, null, ImmutableMap.of(),
31             ImmutableMap.of(), ImmutableTable.of());
32
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;
38
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) {
44         this.parent = parent;
45         this.supportedVersions = supportedVersions;
46         this.commonDefinitions = commonStatements;
47         this.namespaceDefinitions = namespaces;
48         this.versionSpecificDefinitions = versionSpecificStatements;
49     }
50
51     /**
52      * Returns statement definitions common for all versions.
53      *
54      * @return map of common statement definitions
55      */
56     public ImmutableMap<QName, StatementSupport<?, ?, ?>> getCommonDefinitions() {
57         return commonDefinitions;
58     }
59
60     /**
61      * Returns statement definitions specific for requested version. Result of this method does nit include common
62      * statement definitions.
63      *
64      * @param version
65      *            requested version
66      * @return map of statement definitions specific for requested version, it
67      *         doesn't include common statement definitions.
68      */
69     public ImmutableMap<QName, StatementSupport<?, ?, ?>> getDefinitionsSpecificForVersion(final YangVersion version) {
70         return versionSpecificDefinitions.row(version);
71     }
72
73     /**
74      * Returns all version specific statement definitions. Result of this method does not include common statement
75      * definitions.
76      *
77      * @return table of all version specific statement definitions, it doesn't
78      *         include common statement definitions.
79      */
80     public ImmutableTable<YangVersion, QName, StatementSupport<?, ?, ?>> getAllVersionSpecificDefinitions() {
81         return versionSpecificDefinitions;
82     }
83
84     public ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> getNamespaceDefinitions() {
85         return namespaceDefinitions;
86     }
87
88     public static Builder builder(final Set<YangVersion> supportedVersions) {
89         return new Builder(supportedVersions, EMPTY);
90     }
91
92     public static Builder derivedFrom(final StatementSupportBundle parent) {
93         return new Builder(parent.getSupportedVersions(), parent);
94     }
95
96     public Set<YangVersion> getSupportedVersions() {
97         return supportedVersions;
98     }
99
100     @Override
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()));
106
107             // Safe cast, previous checkState checks equivalence of key from which type argument are derived
108             return (NamespaceBehaviour<K, V, N>) potential;
109         }
110         if (parent != null) {
111             return parent.getNamespaceBehaviour(namespace);
112         }
113         return null;
114     }
115
116     public <K, V, N extends IdentifierNamespace<K, V>> boolean hasNamespaceBehaviour(final Class<N> namespace) {
117         if (namespaceDefinitions.containsKey(namespace)) {
118             return true;
119         }
120         if (parent != null) {
121             return parent.hasNamespaceBehaviour(namespace);
122         }
123         return false;
124     }
125
126     public StatementSupport<?, ?, ?> getStatementDefinition(final YangVersion version, final QName stmtName) {
127         StatementSupport<?, ?, ?> result = getVersionSpecificStatementDefinition(version, stmtName);
128         if (result == null) {
129             result = getCommonStatementDefinition(stmtName);
130         }
131
132         return result;
133     }
134
135     private StatementSupport<?, ?, ?> getCommonStatementDefinition(final QName stmtName) {
136         final StatementSupport<?, ?, ?> potential = commonDefinitions.get(stmtName);
137         if (potential != null) {
138             return potential;
139         }
140         if (parent != null) {
141             return parent.getCommonStatementDefinition(stmtName);
142         }
143         return null;
144     }
145
146     private StatementSupport<?, ?, ?> getVersionSpecificStatementDefinition(final YangVersion version,
147             final QName stmtName) {
148         final StatementSupport<?, ?, ?> potential = versionSpecificDefinitions.get(version, stmtName);
149         if (potential != null) {
150             return potential;
151         }
152
153         if (parent != null) {
154             return parent.getVersionSpecificStatementDefinition(version, stmtName);
155         }
156         return null;
157     }
158
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
162                 .create();
163         private final Map<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces = new HashMap<>();
164
165         private final Set<YangVersion> supportedVersions;
166         private StatementSupportBundle parent;
167
168         Builder(final Set<YangVersion> supportedVersions, final StatementSupportBundle parent) {
169             this.parent = requireNonNull(parent);
170             this.supportedVersions = ImmutableSet.copyOf(supportedVersions);
171         }
172
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);
180             return this;
181         }
182
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);
189             return this;
190         }
191
192         public Builder addVersionSpecificSupport(final YangVersion version,
193                 final StatementSupport<?, ?, ?> definition) {
194             checkArgument(supportedVersions.contains(requireNonNull(version)));
195
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);
206             return this;
207         }
208
209         public Set<YangVersion> getSupportedVersions() {
210             return supportedVersions;
211         }
212
213         public Builder setParent(final StatementSupportBundle parent) {
214             this.parent = parent;
215             return this;
216         }
217
218         @Override
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));
223         }
224     }
225 }