2 * Copyright (c) 2017 Pantheon Technologies, s.r.o. 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.yang2sources.plugin;
10 import static com.google.common.base.Preconditions.checkState;
11 import static com.google.common.base.Verify.verifyNotNull;
12 import static java.util.Objects.requireNonNull;
14 import com.google.common.base.MoreObjects;
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.collect.Maps;
17 import com.google.common.io.CharStreams;
18 import java.io.IOException;
19 import java.io.Reader;
20 import java.util.Collection;
21 import java.util.HashMap;
22 import java.util.HashSet;
25 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
26 import org.opendaylight.yangtools.yang.model.api.Module;
27 import org.opendaylight.yangtools.yang.model.api.Submodule;
28 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
29 import org.opendaylight.yangtools.yang.model.spi.source.YangTextSource;
30 import org.opendaylight.yangtools.yang.parser.api.YangParser;
31 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * An incremental state reactor. Allows resolution of a SchemaContext based on a set of sources.
38 // FIXME: reneame to ExecutionModuleReactor or similar
39 final class ProcessorModuleReactor {
40 private static final Logger LOG = LoggerFactory.getLogger(ProcessorModuleReactor.class);
42 private final Map<SourceIdentifier, YangTextSource> modelsInProject;
43 private final Collection<ScannedDependency> dependencies;
45 private YangParser parser;
47 ProcessorModuleReactor(final YangParser parser, final Collection<YangTextSource> modelsInProject,
48 final Collection<ScannedDependency> dependencies) {
49 this.parser = requireNonNull(parser);
50 this.modelsInProject = Maps.uniqueIndex(modelsInProject, YangTextSource::sourceId);
51 this.dependencies = ImmutableList.copyOf(dependencies);
54 ContextHolder toContext() throws IOException, YangParserException {
55 checkState(parser != null, "Context has already been assembled");
57 for (var source : toUniqueSources(dependencies)) {
58 // This source is coming from a dependency:
59 // - its identifier should be accurate, as it should have been processed into a file with accurate name
60 // - it is not required to be parsed, hence we add it just as a library source
61 parser.addLibSource(source);
64 final EffectiveModelContext schemaContext = verifyNotNull(parser.buildEffectiveModel());
67 final Set<Module> modules = new HashSet<>();
68 for (Module module : schemaContext.getModules()) {
69 final SourceIdentifier modId = Util.moduleToIdentifier(module);
70 LOG.debug("Looking for source {}", modId);
71 if (modelsInProject.containsKey(modId)) {
72 LOG.debug("Module {} belongs to current project", module);
75 for (Submodule sub : module.getSubmodules()) {
76 final SourceIdentifier subId = Util.moduleToIdentifier(sub);
77 if (!modelsInProject.containsKey(subId)) {
78 LOG.warn("Submodule {} not found in input files", sub);
84 return new ContextHolder(schemaContext, modules, modelsInProject.keySet());
87 Collection<YangTextSource> getModelsInProject() {
88 return modelsInProject.values();
91 private static Collection<YangTextSource> toUniqueSources(final Collection<ScannedDependency> dependencies)
93 final Map<String, YangTextSource> byContent = new HashMap<>();
95 for (ScannedDependency dependency : dependencies) {
96 for (YangTextSource s : dependency.sources()) {
97 try (Reader reader = s.openStream()) {
98 final String contents = CharStreams.toString(reader);
99 byContent.putIfAbsent(contents, s);
103 return byContent.values();
107 public String toString() {
108 return MoreObjects.toStringHelper(this).add("sources", modelsInProject.keySet()).toString();