20716d9732d5fb7a84b77ba3d1dbcbd497cc9d42
[yangtools.git] / parser / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / CrossSourceStatementReactor.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.reactor;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.SetMultimap;
15 import java.util.Arrays;
16 import java.util.Collection;
17 import java.util.EnumMap;
18 import java.util.Map;
19 import java.util.Set;
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.common.QNameModule;
23 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
25 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
26 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
27 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
28
29 public final class CrossSourceStatementReactor {
30     private final ImmutableMap<ModelProcessingPhase, StatementSupportBundle> supportedTerminology;
31     private final ImmutableMap<ValidationBundleType, Collection<?>> supportedValidation;
32
33     CrossSourceStatementReactor(final Map<ModelProcessingPhase, StatementSupportBundle> supportedTerminology,
34             final Map<ValidationBundleType, Collection<?>> supportedValidation) {
35         this.supportedTerminology = ImmutableMap.copyOf(supportedTerminology);
36         this.supportedValidation = ImmutableMap.copyOf(supportedValidation);
37     }
38
39     /**
40      * Create a new {@link Builder}.
41      *
42      * @return A new builder.
43      */
44     public static @NonNull Builder builder() {
45         return new Builder();
46     }
47
48     /**
49      * Start a new reactor build using the default statement parser mode with all features and deviations enabled.
50      *
51      * @return A new {@link BuildAction}.
52      */
53     public @NonNull BuildAction newBuild() {
54         return new BuildAction(supportedTerminology, supportedValidation);
55     }
56
57     public static class Builder implements org.opendaylight.yangtools.concepts.Builder<CrossSourceStatementReactor> {
58         private final Map<ValidationBundleType, Collection<?>> validationBundles =
59                 new EnumMap<>(ValidationBundleType.class);
60         private final Map<ModelProcessingPhase, StatementSupportBundle> bundles =
61                 new EnumMap<>(ModelProcessingPhase.class);
62
63         public @NonNull Builder setBundle(final ModelProcessingPhase phase, final StatementSupportBundle bundle) {
64             bundles.put(phase, bundle);
65             return this;
66         }
67
68         public @NonNull Builder setValidationBundle(final ValidationBundleType type,
69                 final Collection<?> validationBundle) {
70             validationBundles.put(type, validationBundle);
71             return this;
72         }
73
74         @Override
75         public CrossSourceStatementReactor build() {
76             return new CrossSourceStatementReactor(bundles, validationBundles);
77         }
78     }
79
80     public static class BuildAction {
81         private final BuildGlobalContext context;
82         private boolean supportedFeaturesSet = false;
83         private boolean modulesDeviatedByModulesSet = false;
84
85         BuildAction(final ImmutableMap<ModelProcessingPhase, StatementSupportBundle> supportedTerminology,
86                 final ImmutableMap<ValidationBundleType, Collection<?>> supportedValidation) {
87             this.context = new BuildGlobalContext(supportedTerminology, supportedValidation);
88         }
89
90         /**
91          * Add main source. All main sources are present in resulting SchemaContext.
92          *
93          * @param source which should be added into main sources
94          * @return This build action, for fluent use.
95          * @throws NullPointerException if @{code source} is null
96          */
97         public @NonNull BuildAction addSource(final StatementStreamSource source) {
98             context.addSource(source);
99             return this;
100         }
101
102         /**
103          * Add main sources. All main sources are present in resulting SchemaContext.
104          *
105          * @param sources which should be added into main sources
106          * @return This build action, for fluent use.
107          * @throws NullPointerException if @{code sources} is null or contains a null element
108          */
109         public @NonNull BuildAction addSources(final StatementStreamSource... sources) {
110             addSources(Arrays.asList(sources));
111             return this;
112         }
113
114         /**
115          * Add main sources. All main sources are present in resulting SchemaContext.
116          *
117          * @param sources which should be added into main sources
118          * @return This build action, for fluent use.
119          * @throws NullPointerException if @{code sources} is null or contains a null element
120          */
121         public @NonNull BuildAction addSources(final @NonNull Collection<? extends StatementStreamSource> sources) {
122             for (final StatementStreamSource source : sources) {
123                 context.addSource(requireNonNull(source));
124             }
125             return this;
126         }
127
128         /**
129          * Add a library source. Only library sources required by main sources are present in resulting SchemaContext.
130          * Any other library sources are ignored and this also applies to error reporting.
131          *
132          * <p>
133          * Library sources are not supported in semantic version mode currently.
134          *
135          * @param libSource source which should be added into library sources
136          * @return This build action, for fluent use.
137          * @throws NullPointerException if @{code libSource} is null
138          */
139         public @NonNull BuildAction addLibSource(final StatementStreamSource libSource) {
140             context.addLibSource(libSource);
141             return this;
142         }
143
144         /**
145          * Add library sources. Only library sources required by main sources are present in resulting SchemaContext.
146          * Any other library sources are ignored and this also applies to error reporting.
147          *
148          * <p>
149          * Library sources are not supported in semantic version mode currently.
150          *
151          * @param libSources sources which should be added into library sources
152          * @return This build action, for fluent use.
153          * @throws NullPointerException if @{code libSources} is null or contains a null element
154          */
155         public @NonNull BuildAction addLibSources(final StatementStreamSource... libSources) {
156             addLibSources(Arrays.asList(libSources));
157             return this;
158         }
159
160         /**
161          * Add library sources. Only library sources required by main sources are present in resulting SchemaContext.
162          * Any other library sources are ignored and this also applies to error reporting.
163          *
164          * <p>
165          * Library sources are not supported in semantic version mode currently.
166          *
167          * @param libSources sources which should be added into library sources
168          * @return This build action, for fluent use.
169          * @throws NullPointerException if @{code libSources} is null or contains a null element
170          */
171         public @NonNull BuildAction addLibSources(final Collection<StatementStreamSource> libSources) {
172             for (final StatementStreamSource libSource : libSources) {
173                 context.addLibSource(libSource);
174             }
175             return this;
176         }
177
178         /**
179          * Set supported features based on which all if-feature statements in the
180          * parsed YANG modules will be resolved.
181          *
182          * @param supportedFeatures
183          *            Set of supported features in the final SchemaContext.
184          *            If the set is empty, no features encountered will be supported.
185          * @return This build action, for fluent use.
186          */
187         public @NonNull BuildAction setSupportedFeatures(final @NonNull Set<QName> supportedFeatures) {
188             checkState(!supportedFeaturesSet, "Supported features should be set only once.");
189             context.setSupportedFeatures(requireNonNull(supportedFeatures));
190             supportedFeaturesSet = true;
191             return this;
192         }
193
194         /**
195          * Set YANG modules which can be deviated by specified modules during the parsing process.
196          * Map key (QNameModule) denotes a module which can be deviated by the modules in the Map value.
197          *
198          * @param modulesDeviatedByModules
199          *            Map of YANG modules (Map key) which can be deviated by specified modules (Map value) in the final
200          *            SchemaContext. If the map is empty, no deviations encountered will be supported.
201          * @return This build action, for fluent use.
202          */
203         public @NonNull BuildAction setModulesWithSupportedDeviations(
204                 final @NonNull SetMultimap<QNameModule, QNameModule> modulesDeviatedByModules) {
205             checkState(!modulesDeviatedByModulesSet, "Modules with supported deviations should be set only once.");
206             context.setModulesDeviatedByModules(requireNonNull(modulesDeviatedByModules));
207             modulesDeviatedByModulesSet = true;
208             return this;
209         }
210
211         /**
212          * Build the effective model context.
213          */
214         public ReactorDeclaredModel build() throws ReactorException {
215             return context.build();
216         }
217
218         public EffectiveSchemaContext buildEffective() throws ReactorException {
219             return context.buildEffective();
220         }
221     }
222 }