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.stmt.reactor;
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.ImmutableMap;
12 import com.google.common.io.ByteSource;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.util.Arrays;
16 import java.util.Collection;
17 import java.util.EnumMap;
18 import java.util.List;
20 import java.util.Optional;
22 import javax.annotation.Nonnull;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.QNameModule;
25 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
26 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
27 import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
28 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
29 import org.opendaylight.yangtools.yang.parser.rfc6020.repo.YangStatementStreamSource;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
33 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
34 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
35 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
36 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 public final class CrossSourceStatementReactor {
41 private static final Logger LOG = LoggerFactory.getLogger(CrossSourceStatementReactor.class);
43 private final Map<ModelProcessingPhase, StatementSupportBundle> supportedTerminology;
44 private final Map<ValidationBundleType, Collection<?>> supportedValidation;
46 CrossSourceStatementReactor(final Map<ModelProcessingPhase, StatementSupportBundle> supportedTerminology,
47 final Map<ValidationBundleType, Collection<?>> supportedValidation) {
48 this.supportedTerminology = ImmutableMap.copyOf(supportedTerminology);
49 this.supportedValidation = ImmutableMap.copyOf(supportedValidation);
53 * Create a new {@link Builder}.
55 * @return A new builder.
57 public static Builder builder() {
62 * Start a new reactor build using the default statement parser mode with all features and deviations enabled.
64 * @return A new {@link BuildAction}.
66 public BuildAction newBuild() {
67 return newBuild(StatementParserMode.DEFAULT_MODE);
71 * Start a new reactor build using the default statement parser mode and enabling only the specified features
74 * @param supportedFeatures The set of supported features in the final SchemaContext
75 * @return A new {@link BuildAction}.
77 * @deprecated Use {@link #newBuild()} and then call setSupportedFeatures() on the created BuildAction instead.
80 public BuildAction newBuild(final Set<QName> supportedFeatures) {
81 final BuildAction buildAction = newBuild();
82 if (supportedFeatures != null) {
83 buildAction.setSupportedFeatures(supportedFeatures);
90 * Start a new reactor build using the default statement parser mode and enabling only the specified features
93 * @param supportedFeatures The set of supported features in the final SchemaContext, if present.
94 * @return A new {@link BuildAction}.
96 * @deprecated Use {@link #newBuild()} and then call setSupportedFeatures() on the created BuildAction instead.
99 public BuildAction newBuild(final Optional<Set<QName>> supportedFeatures) {
100 final BuildAction buildAction = newBuild();
101 if (supportedFeatures.isPresent()) {
102 buildAction.setSupportedFeatures(supportedFeatures.get());
109 * Start a new reactor build using the specified statement parser mode and enabling all features and deviations.
111 * @param statementParserMode Parser mode to use
112 * @return A new {@link BuildAction}.
113 * @throws NullPointerException if statementParserMode is null
115 public BuildAction newBuild(final StatementParserMode statementParserMode) {
116 return new BuildAction(statementParserMode);
120 * Start a new reactor build using the specified statement parser mode and enabling only the specified features
121 * and all deviations.
123 * @param statementParserMode Parser mode to use
124 * @param supportedFeatures The set of supported features in the final SchemaContext
125 * @return A new {@link BuildAction}.
126 * @throws NullPointerException if statementParserMode is null
128 * @deprecated Use {@link #newBuild(StatementParserMode)} and then call setSupportedFeatures()
129 * on the created BuildAction instead.
132 public BuildAction newBuild(final StatementParserMode statementParserMode,
133 final Set<QName> supportedFeatures) {
134 final BuildAction buildAction = new BuildAction(statementParserMode);
135 if (supportedFeatures != null) {
136 buildAction.setSupportedFeatures(supportedFeatures);
143 * Start a new reactor build using the specified statement parser mode and enabling only the specified features
144 * and all deviations.
146 * @param statementParserMode Parser mode to use
147 * @param supportedFeatures The set of supported features in the final SchemaContext, or absent if all features
148 * encountered should be supported.
149 * @return A new {@link BuildAction}.
150 * @throws NullPointerException if statementParserMode is null
152 * @deprecated Use {@link #newBuild(StatementParserMode)} and then call setSupportedFeatures()
153 * on the created BuildAction instead.
156 public BuildAction newBuild(final StatementParserMode statementParserMode,
157 final Optional<Set<QName>> supportedFeatures) {
158 final BuildAction buildAction = new BuildAction(statementParserMode);
159 if (supportedFeatures.isPresent()) {
160 buildAction.setSupportedFeatures(supportedFeatures.get());
166 private static <T> T warnOnNull(final T obj) {
168 LOG.info("Set of supported features has not been provided, so all features are supported by default.");
173 public static class Builder implements org.opendaylight.yangtools.concepts.Builder<CrossSourceStatementReactor> {
174 private final Map<ValidationBundleType, Collection<?>> validationBundles =
175 new EnumMap<>(ValidationBundleType.class);
176 private final Map<ModelProcessingPhase, StatementSupportBundle> bundles =
177 new EnumMap<>(ModelProcessingPhase.class);
179 public Builder setBundle(final ModelProcessingPhase phase, final StatementSupportBundle bundle) {
180 bundles.put(phase, bundle);
184 public Builder setValidationBundle(final ValidationBundleType type, final Collection<?> validationBundle) {
185 validationBundles.put(type, validationBundle);
190 public CrossSourceStatementReactor build() {
191 return new CrossSourceStatementReactor(bundles, validationBundles);
195 public class BuildAction {
196 private final BuildGlobalContext context;
197 private boolean supportedFeaturesSet = false;
198 private boolean modulesDeviatedByModulesSet = false;
200 BuildAction(@Nonnull final StatementParserMode statementParserMode) {
201 this.context = new BuildGlobalContext(supportedTerminology,supportedValidation,
202 Preconditions.checkNotNull(statementParserMode));
206 * Add main source. All main sources are present in resulting
210 * which should be added into main sources
212 public void addSource(final StatementStreamSource source) {
213 context.addSource(source);
217 * Add main sources. All main sources are present in resulting
221 * which should be added into main sources
223 public void addSources(final StatementStreamSource... sources) {
224 addSources(Arrays.asList(sources));
227 public void addSources(final Collection<? extends StatementStreamSource> sources) {
228 for (final StatementStreamSource source : sources) {
229 context.addSource(source);
234 * Add library sources. Only library sources required by main sources
235 * are present in resulting SchemaContext. Any other library sources are
236 * ignored and this also applies to error reporting.
238 * Library sources are not supported in openconfig version mode currently.
241 * yang sources which should be added into library sources
243 public void addLibSources(final StatementStreamSource... libSources) {
244 for (final StatementStreamSource libSource : libSources) {
245 context.addLibSource(libSource);
250 * Set supported features based on which all if-feature statements in the
251 * parsed YANG modules will be resolved.
253 * @param supportedFeatures
254 * Set of supported features in the final SchemaContext.
255 * If the set is empty, no features encountered will be supported.
257 public void setSupportedFeatures(@Nonnull final Set<QName> supportedFeatures) {
258 Preconditions.checkState(!supportedFeaturesSet, "Supported features should be set only once.");
259 context.setSupportedFeatures(Preconditions.checkNotNull(supportedFeatures));
260 supportedFeaturesSet = true;
264 * Set YANG modules which can be deviated by specified modules during the parsing process.
265 * Map key (QNameModule) denotes a module which can be deviated by the modules in the Map value.
267 * @param modulesDeviatedByModules
268 * Map of YANG modules (Map key) which can be deviated by specified modules (Map value) in the final
269 * SchemaContext. If the map is empty, no deviations encountered will be supported.
271 public void setModulesWithSupportedDeviations(
272 @Nonnull final Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules) {
273 Preconditions.checkState(!modulesDeviatedByModulesSet,
274 "Modules with supported deviations should be set only once.");
275 context.setModulesDeviatedByModules(Preconditions.checkNotNull(modulesDeviatedByModules));
276 modulesDeviatedByModulesSet = true;
280 * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException
281 * @throws ReactorException
283 public EffectiveModelContext build() throws ReactorException {
284 return context.build();
287 public EffectiveSchemaContext buildEffective() throws ReactorException {
288 return context.buildEffective();
292 * @deprecated Use {@link #addSources(Collection)} and {@link #buildEffective()} instead.
295 public SchemaContext buildEffective(final Collection<ByteSource> yangByteSources) throws ReactorException,
297 for (final ByteSource source : yangByteSources) {
298 if (source instanceof YangTextSchemaSource) {
300 addSource(YangStatementStreamSource.create((YangTextSchemaSource) source));
301 } catch (YangSyntaxErrorException e) {
302 throw new IOException("Source " + source + " failed to parse", e);
305 addSource(new YangStatementSourceImpl(source.openStream()));
309 return buildEffective();
313 * @deprecated Use {@link #addSources(Collection)} and {@link #buildEffective()} instead.
316 public SchemaContext buildEffective(final List<InputStream> yangInputStreams) throws ReactorException {
317 for (final InputStream yangInputStream : yangInputStreams) {
318 addSource(new YangStatementSourceImpl(yangInputStream));
321 return buildEffective();