Bug 4506: Honor if-feature during SchemaContext assembly
[yangtools.git] / yang / yang-parser-impl / 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 com.google.common.base.Preconditions;
11 import com.google.common.collect.ImmutableMap;
12 import com.google.common.io.ByteSource;
13 import java.io.File;
14 import java.io.FileNotFoundException;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.EnumMap;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.function.Predicate;
25 import org.opendaylight.yangtools.yang.common.QName;
26 import org.opendaylight.yangtools.yang.model.api.Module;
27 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
31 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
32 import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
33 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
34 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
35 import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
36
37 public class CrossSourceStatementReactor {
38
39     private final Map<ModelProcessingPhase,StatementSupportBundle> supportedTerminology;
40     private final Map<ValidationBundleType,Collection<?>> supportedValidation;
41
42     CrossSourceStatementReactor(final Map<ModelProcessingPhase, StatementSupportBundle> supportedTerminology) {
43         this.supportedTerminology = ImmutableMap.copyOf(supportedTerminology);
44         this.supportedValidation = ImmutableMap.of();
45     }
46
47     CrossSourceStatementReactor(final Map<ModelProcessingPhase, StatementSupportBundle> supportedTerminology, final Map<ValidationBundleType,Collection<?>> supportedValidation) {
48         this.supportedTerminology = ImmutableMap.copyOf(supportedTerminology);
49         this.supportedValidation = ImmutableMap.copyOf(supportedValidation);
50     }
51
52     public static Builder builder() {
53         return new Builder();
54     }
55
56     public final BuildAction newBuild() {
57         return newBuild(t -> true);
58     }
59
60     public final BuildAction newBuild(final Predicate<QName> isFeatureSupported) {
61         return new BuildAction(isFeatureSupported);
62     }
63
64     public static class Builder implements org.opendaylight.yangtools.concepts.Builder<CrossSourceStatementReactor>{
65
66         final Map<ModelProcessingPhase,StatementSupportBundle> bundles = new EnumMap<>(ModelProcessingPhase.class);
67         final Map<ValidationBundleType,Collection<?>> validationBundles = new EnumMap<>(ValidationBundleType.class);
68
69         public Builder setBundle(final ModelProcessingPhase phase,final StatementSupportBundle bundle) {
70             bundles.put(phase, bundle);
71             return this;
72         }
73
74
75         public Builder setValidationBundle(final ValidationBundleType type, final Collection<?> validationBundle) {
76             validationBundles.put(type,validationBundle);
77             return this;
78         }
79
80         @Override
81         public CrossSourceStatementReactor build() {
82             return new CrossSourceStatementReactor(bundles, validationBundles);
83         }
84     }
85
86     public class BuildAction {
87         private final BuildGlobalContext context;
88
89         public BuildAction() {
90             this(t -> true);
91         }
92
93         public BuildAction(Predicate<QName> isFeatureSupported) {
94             Preconditions.checkNotNull(isFeatureSupported);
95             this.context = new BuildGlobalContext(supportedTerminology, supportedValidation, isFeatureSupported);
96         }
97
98         public void addSource(final StatementStreamSource source) {
99             context.addSource(source);
100         }
101
102         public void addSources(final StatementStreamSource... sources) {
103             for (StatementStreamSource source : sources) {
104                 context.addSource(source);
105             }
106         }
107
108         /**
109          * @throws org.opendaylight.yangtools.yang.parser.spi.source.SourceException
110          * @throws ReactorException
111          */
112         public EffectiveModelContext build() throws ReactorException {
113             return context.build();
114         }
115
116         public EffectiveSchemaContext buildEffective() throws ReactorException {
117             return context.buildEffective();
118         }
119
120         public SchemaContext buildEffective(final Collection<ByteSource> yangByteSources) throws
121                 ReactorException, IOException {
122             for (ByteSource yangByteSource : yangByteSources) {
123                 addSource(new YangStatementSourceImpl(yangByteSource.openStream()));
124             }
125
126             return buildEffective();
127         }
128
129         public SchemaContext buildEffective(final List<InputStream> yangInputStreams) throws
130                 ReactorException {
131             for (InputStream yangInputStream : yangInputStreams) {
132                 addSource(new YangStatementSourceImpl(yangInputStream));
133             }
134
135             return buildEffective();
136         }
137
138         /**
139          * @deprecated This method was never used and relies on deprecated module methods.
140          */
141         @Deprecated
142         public Map<File, Module> buildEffectiveMappedToSource(final List<File> yangFiles) throws
143                 ReactorException, FileNotFoundException {
144             if (yangFiles == null || yangFiles.isEmpty()) {
145                 return Collections.emptyMap();
146             }
147
148             Map<String, File> pathToFile = new HashMap<>();
149             Map<File, Module> sourceFileToModule = new HashMap<>();
150
151             for (File yangFile : yangFiles) {
152                 addSource(new YangStatementSourceImpl(new NamedFileInputStream(yangFile, yangFile.getPath())));
153                 pathToFile.put(yangFile.getPath(), yangFile);
154             }
155
156             EffectiveSchemaContext schema = buildEffective();
157             Set<Module> modules = schema.getModules();
158             for (Module module : modules) {
159                 sourceFileToModule.put(pathToFile.get(module.getModuleSourcePath()), module);
160             }
161
162             return sourceFileToModule;
163         }
164     }
165 }