From: Robert Varga Date: Tue, 5 Sep 2017 14:31:14 +0000 (+0200) Subject: BUG-7568: Use YangTextSchemaSource to emit schema files X-Git-Tag: v2.0.0~245 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=ae14ac018999945d45c1f7568b32bb725808a254;p=yangtools.git BUG-7568: Use YangTextSchemaSource to emit schema files To properly address the issue of META-INF/yang files not having their revisions we need to encapsulate minimal project initialization state, which gives us properly-resolved revisions. We then refactor the execution flow to first inspect files to determine whan needs to happen and then execute. Change-Id: Icdf8069c72b24ad4cb196ebd79de194023eba9e4 Signed-off-by: Robert Varga --- diff --git a/yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java b/yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java index b6f1b55d3b..c27c926132 100644 --- a/yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java +++ b/yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java @@ -44,13 +44,13 @@ public class YangToSourcesPluginTestIT { @Test public void testAdditionalConfiguration() throws Exception { - final Verifier vrf = setUp("test-parent/AdditionalConfig/", false); + Verifier vrf = setUp("test-parent/AdditionalConfig/", false); vrf.verifyTextInLog("[DEBUG] yang-to-sources: Additional configuration picked up for : " + "org.opendaylight.yangtools.yang2sources.spi.CodeGeneratorTestImpl: " + "{nm1=abcd=a.b.c.d, nm2=abcd2=a.b.c.d.2}"); vrf.verifyTextInLog("[DEBUG] yang-to-sources: Additional configuration picked up for : " + "org.opendaylight.yangtools.yang2sources.spi.CodeGeneratorTestImpl: {c1=config}"); - vrf.verifyTextInLog(File.separator + "files marked as resources: META-INF/yang"); + vrf.verifyTextInLog("[DEBUG] yang-to-sources: YANG files marked as resources:"); vrf.verifyTextInLog(Joiner.on(File.separator).join(Arrays.asList("target", "generated-sources", "spi")) + " marked as resources for generator: org.opendaylight.yangtools.yang2sources.spi." + "CodeGeneratorTestImpl"); @@ -145,19 +145,19 @@ public class YangToSourcesPluginTestIT { v1.executeGoal("package"); String buildDir = getMavenBuildDirectory(v1); - v1.assertFilePresent(buildDir + "/classes/META-INF/yang/testfile1.yang"); - v1.assertFilePresent(buildDir + "/classes/META-INF/yang/testfile2.yang"); - v1.assertFilePresent(buildDir + "/classes/META-INF/yang/testfile3.yang"); + v1.assertFilePresent(buildDir + "/classes/META-INF/yang/types1@2013-02-27.yang"); + v1.assertFilePresent(buildDir + "/classes/META-INF/yang/types2@2013-02-27.yang"); + v1.assertFilePresent(buildDir + "/classes/META-INF/yang/types3@2013-02-27.yang"); Verifier v2 = setUp("test-parent/GenerateTest2/", false); v2.executeGoal("clean"); v2.executeGoal("package"); buildDir = getMavenBuildDirectory(v2); - v2.assertFilePresent(buildDir + "/classes/META-INF/yang/private.yang"); - v2.assertFileNotPresent(buildDir + "/classes/META-INF/yang/testfile1.yang"); - v2.assertFileNotPresent(buildDir + "/classes/META-INF/yang/testfile2.yang"); - v2.assertFileNotPresent(buildDir + "/classes/META-INF/yang/testfile3.yang"); + v2.assertFilePresent(buildDir + "/classes/META-INF/yang/private@2013-02-27.yang"); + v2.assertFileNotPresent(buildDir + "/classes/META-INF/yang/types1@2013-02-27.yang"); + v2.assertFileNotPresent(buildDir + "/classes/META-INF/yang/types2@2013-02-27.yang"); + v2.assertFileNotPresent(buildDir + "/classes/META-INF/yang/types3@2013-02-27.yang"); } private static String getMavenBuildDirectory(final Verifier verifier) throws IOException { diff --git a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/ContextHolder.java b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/ContextHolder.java new file mode 100644 index 0000000000..0565ecfef2 --- /dev/null +++ b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/ContextHolder.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang2sources.plugin; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import java.util.Optional; +import java.util.Set; +import org.opendaylight.yangtools.concepts.Immutable; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; + +final class ContextHolder implements Immutable { + private final SchemaContext context; + private final Set modules; + private final Set sources; + + ContextHolder(final SchemaContext context, final Set modules, final Set sources) { + this.context = Preconditions.checkNotNull(context); + this.modules = ImmutableSet.copyOf(modules); + this.sources = ImmutableSet.copyOf(sources); + } + + SchemaContext getContext() { + return context; + } + + Set getYangModules() { + return modules; + } + + Optional moduleToResourcePath(final Module mod) { + final SourceIdentifier id = Util.moduleToIdentifier(mod); + return sources.contains(id) + ? Optional.of("/" + YangToSourcesProcessor.META_INF_YANG_STRING_JAR + "/" + id.toYangFilename()) + : Optional.empty(); + } +} \ No newline at end of file diff --git a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/ProcessorModuleReactor.java b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/ProcessorModuleReactor.java new file mode 100644 index 0000000000..f801fb0744 --- /dev/null +++ b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/ProcessorModuleReactor.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang2sources.plugin; + +import com.google.common.base.MoreObjects; +import com.google.common.base.Preconditions; +import com.google.common.base.Verify; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableSet; +import java.io.IOException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import javax.annotation.concurrent.NotThreadSafe; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException; +import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException; +import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; +import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaContextResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * An incremental state reactor. Allows resolution of a SchemaContext based on a set of sources. + * + * @author Robert Varga + */ +@NotThreadSafe +final class ProcessorModuleReactor { + private static final Logger LOG = LoggerFactory.getLogger(ProcessorModuleReactor.class); + + private final YangTextSchemaContextResolver resolver; + private final Set sourcesInProject; + + ProcessorModuleReactor(final YangTextSchemaContextResolver resolver) { + this.resolver = Preconditions.checkNotNull(resolver); + sourcesInProject = ImmutableSet.copyOf(resolver.getAvailableSources()); + } + + void registerSource(final YangTextSchemaSource source) throws SchemaSourceException, IOException, + YangSyntaxErrorException { + resolver.registerSource(source); + } + + ContextHolder toContext() throws SchemaResolutionException { + final SchemaContext schemaContext = Verify.verifyNotNull(resolver.trySchemaContext()); + + final Set modules = new HashSet<>(); + for (Module module : schemaContext.getModules()) { + final SourceIdentifier modId = Util.moduleToIdentifier(module); + LOG.debug("Looking for source {}", modId); + if (sourcesInProject.contains(modId)) { + LOG.debug("Module {} belongs to current project", module); + modules.add(module); + + for (Module sub : module.getSubmodules()) { + final SourceIdentifier subId = Util.moduleToIdentifier(sub); + if (sourcesInProject.contains(subId)) { + LOG.warn("Submodule {} not found in input files", sub); + } + } + } + } + + return new ContextHolder(schemaContext, modules, sourcesInProject); + } + + Collection getModelsInProject() { + return Collections2.transform(sourcesInProject, id -> resolver.getSourceTexts(id).iterator().next()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("sources", sourcesInProject).add("resolver", resolver).toString(); + } +} diff --git a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java index 2941edd4cb..d897f109bd 100644 --- a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java +++ b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java @@ -12,9 +12,6 @@ import static org.opendaylight.yangtools.yang2sources.plugin.YangToSourcesProces import static org.opendaylight.yangtools.yang2sources.plugin.YangToSourcesProcessor.META_INF_YANG_STRING; import static org.opendaylight.yangtools.yang2sources.plugin.YangToSourcesProcessor.META_INF_YANG_STRING_JAR; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import com.google.common.io.ByteSource; import com.google.common.io.ByteStreams; import java.io.File; @@ -23,11 +20,11 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -41,8 +38,11 @@ import org.apache.maven.model.Plugin; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.apache.maven.repository.RepositorySystem; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -290,32 +290,16 @@ final class Util { return yangsFilesFromDependencies; } - static final class ContextHolder { - private final SchemaContext context; - private final Set yangModules; - private final Map yangFiles; - - ContextHolder(final SchemaContext context, final Set yangModules, final Map yangFiles) { - this.context = Preconditions.checkNotNull(context); - this.yangModules = ImmutableSet.copyOf(yangModules); - this.yangFiles = ImmutableMap.copyOf(yangFiles); - } - - SchemaContext getContext() { - return context; - } - - Set getYangModules() { - return yangModules; + static SourceIdentifier moduleToIdentifier(final Module module) { + final QNameModule mod = module.getQNameModule(); + final Date rev = mod.getRevision(); + final com.google.common.base.Optional optRev; + if (SimpleDateFormatUtil.DEFAULT_DATE_REV.equals(rev)) { + optRev = com.google.common.base.Optional.absent(); + } else { + optRev = com.google.common.base.Optional.of(mod.getFormattedRevision()); } - Optional moduleToResourcePath(final Module mod) { - final String fileName = yangFiles.get(mod); - if (fileName == null) { - return Optional.empty(); - } - - return Optional.of("/" + YangToSourcesProcessor.META_INF_YANG_STRING_JAR + "/" + fileName); - } + return RevisionSourceIdentifier.create(module.getName(), optRev); } } diff --git a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangProvider.java b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangProvider.java index 29d72b513a..b9c2ac9959 100644 --- a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangProvider.java +++ b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangProvider.java @@ -7,48 +7,54 @@ */ package org.opendaylight.yangtools.yang2sources.plugin; +import com.google.common.io.Files; import java.io.File; import java.io.IOException; import java.util.Collection; import org.apache.maven.model.Resource; -import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; +import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -class YangProvider { - private static final Logger LOG = LoggerFactory.getLogger(YangProvider.class); +abstract class YangProvider { + private static final class Default extends YangProvider { + private static final Logger LOG = LoggerFactory.getLogger(YangProvider.class); - void addYangsToMetaInf(final MavenProject project, final File yangFilesRootDir, - final Collection excludedFiles) throws MojoFailureException { + @Override + void addYangsToMetaInf(final MavenProject project, final Collection modelsInProject) + throws IOException { - // copy project's src/main/yang/*.yang to target/generated-sources/yang/META-INF/yang/*.yang - File generatedYangDir = new GeneratedDirectories(project).getYangDir(); - addYangsToMetaInf(project, yangFilesRootDir, excludedFiles, generatedYangDir); - } + final File generatedYangDir = new GeneratedDirectories(project).getYangDir(); + LOG.debug("Generated dir {}", generatedYangDir); - private static void addYangsToMetaInf(final MavenProject project, final File yangFilesRootDir, - final Collection excludedFiles, final File generatedYangDir) throws MojoFailureException { + // copy project's src/main/yang/*.yang to ${project.builddir}/generated-sources/yang/META-INF/yang/ + // This honors setups like a Eclipse-profile derived one + final File withMetaInf = new File(generatedYangDir, YangToSourcesProcessor.META_INF_YANG_STRING); + withMetaInf.mkdirs(); - File withMetaInf = new File(generatedYangDir, YangToSourcesProcessor.META_INF_YANG_STRING); - withMetaInf.mkdirs(); + for (YangTextSchemaSource source : modelsInProject) { + final String fileName = source.getIdentifier().toYangFilename(); + final File file = new File(withMetaInf, fileName); - try { - Collection files = Util.listFiles(yangFilesRootDir, excludedFiles); - for (File file : files) { - org.apache.commons.io.FileUtils.copyFile(file, new File(withMetaInf, file.getName())); + source.copyTo(Files.asByteSink(file)); + LOG.debug("Created file {} for {}", file, source.getIdentifier()); } - } catch (IOException e) { - LOG.warn("Failed to generate files into root {}", yangFilesRootDir, e); - throw new MojoFailureException("Unable to list yang files into resource folder", e); + + setResource(generatedYangDir, project); + LOG.debug("{} YANG files marked as resources: {}", YangToSourcesProcessor.LOG_PREFIX, generatedYangDir); } + } - setResource(generatedYangDir, project); + private static final YangProvider DEFAULT = new Default(); - LOG.debug("{} Yang files from: {} marked as resources: {}", YangToSourcesProcessor.LOG_PREFIX, yangFilesRootDir, - YangToSourcesProcessor.META_INF_YANG_STRING_JAR); + static YangProvider getInstance() { + return DEFAULT; } + abstract void addYangsToMetaInf(MavenProject project, Collection modelsInProject) + throws IOException; + static void setResource(final File targetYangDir, final MavenProject project) { Resource res = new Resource(); res.setDirectory(targetYangDir.getPath()); diff --git a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessor.java b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessor.java index 97c810d751..a708c412b9 100644 --- a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessor.java +++ b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessor.java @@ -8,12 +8,9 @@ package org.opendaylight.yangtools.yang2sources.plugin; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.ImmutableSet; import com.google.common.io.CharStreams; import java.io.File; @@ -22,27 +19,20 @@ import java.io.Reader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; -import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.FileUtils; -import org.opendaylight.yangtools.yang.common.QNameModule; -import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier; -import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException; +import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException; import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaContextResolver; -import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaSourceRegistration; import org.opendaylight.yangtools.yang2sources.plugin.ConfigArg.CodeGeneratorArg; -import org.opendaylight.yangtools.yang2sources.plugin.Util.ContextHolder; import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator; import org.opendaylight.yangtools.yang2sources.spi.BuildContextAware; import org.opendaylight.yangtools.yang2sources.spi.MavenProjectAware; @@ -70,14 +60,6 @@ class YangToSourcesProcessor { private final BuildContext buildContext; private final YangProvider yangProvider; - @VisibleForTesting - YangToSourcesProcessor(final File yangFilesRootDir, final Collection excludedFiles, - final List codeGenerators, final MavenProject project, final boolean inspectDependencies, - final YangProvider yangProvider) { - this(new DefaultBuildContext(), yangFilesRootDir, excludedFiles, codeGenerators, project, - inspectDependencies, yangProvider); - } - private YangToSourcesProcessor(final BuildContext buildContext, final File yangFilesRootDir, final Collection excludedFiles, final List codeGenerators, final MavenProject project, final boolean inspectDependencies, final YangProvider yangProvider) { @@ -87,45 +69,67 @@ class YangToSourcesProcessor { this.codeGenerators = ImmutableList.copyOf(codeGenerators); this.project = Preconditions.checkNotNull(project); this.inspectDependencies = inspectDependencies; - this.yangProvider = yangProvider; + this.yangProvider = Preconditions.checkNotNull(yangProvider); + } + + @VisibleForTesting + YangToSourcesProcessor(final File yangFilesRootDir, final Collection excludedFiles, + final List codeGenerators, final MavenProject project, final boolean inspectDependencies, + final YangProvider yangProvider) { + this(new DefaultBuildContext(), yangFilesRootDir, excludedFiles, codeGenerators, project, + inspectDependencies, yangProvider); } YangToSourcesProcessor(final BuildContext buildContext, final File yangFilesRootDir, final Collection excludedFiles, final List codeGenerators, final MavenProject project, final boolean inspectDependencies) { - this(yangFilesRootDir, excludedFiles, codeGenerators, project, inspectDependencies, new YangProvider()); + this(yangFilesRootDir, excludedFiles, codeGenerators, project, inspectDependencies, YangProvider.getInstance()); } public void execute() throws MojoExecutionException, MojoFailureException { - ContextHolder context = processYang(); - if (context != null) { - generateSources(context); - yangProvider.addYangsToMetaInf(project, yangFilesRootDir, excludedFiles); - } + conditionalExecute(false); } void conditionalExecute(final boolean skip) throws MojoExecutionException, MojoFailureException { - if (skip) { - LOG.info("Skipping YANG code generation because property yang.skip is true"); - - // But manually add resources - // add META_INF/yang - yangProvider.addYangsToMetaInf(project, yangFilesRootDir, excludedFiles); + final Optional optReactor = createReactor(); + if (!optReactor.isPresent()) { + return; + } - // add META_INF/services - File generatedServicesDir = new GeneratedDirectories(project).getYangServicesDir(); - YangProvider.setResource(generatedServicesDir, project); - LOG.debug("{} Yang services files from: {} marked as resources: {}", LOG_PREFIX, generatedServicesDir, - META_INF_YANG_SERVICES_STRING_JAR); + final ProcessorModuleReactor reactor = optReactor.get(); + if (!skip) { + final ContextHolder holder; + try { + holder = createContextHolder(reactor); + } catch (SchemaSourceException | YangSyntaxErrorException e) { + throw new MojoFailureException("Failed to process reactor " + reactor, e); + } catch (IOException e) { + throw new MojoExecutionException("Failed to read reactor " + reactor, e); + } + generateSources(holder); } else { - execute(); + LOG.info("Skipping YANG code generation because property yang.skip is true"); + } + + // add META_INF/yang + final Collection models = reactor.getModelsInProject(); + try { + yangProvider.addYangsToMetaInf(project, models); + } catch (IOException e) { + throw new MojoExecutionException("Failed write model files for " + models, e); } + + // add META_INF/services + File generatedServicesDir = new GeneratedDirectories(project).getYangServicesDir(); + YangProvider.setResource(generatedServicesDir, project); + LOG.debug("{} Yang services files from: {} marked as resources: {}", LOG_PREFIX, generatedServicesDir, + META_INF_YANG_SERVICES_STRING_JAR); } @SuppressWarnings("checkstyle:illegalCatch") - private ContextHolder processYang() throws MojoExecutionException { + private Optional createReactor() throws MojoExecutionException { LOG.info("{} Inspecting {}", LOG_PREFIX, yangFilesRootDir); try { /* @@ -142,7 +146,7 @@ class YangToSourcesProcessor { if (allFiles.isEmpty()) { LOG.info("{} No input files found", LOG_PREFIX); - return null; + return Optional.empty(); } /* @@ -160,61 +164,20 @@ class YangToSourcesProcessor { if (noChange) { LOG.info("{} None of {} input files changed", LOG_PREFIX, allFiles.size()); - return null; + return Optional.empty(); } - final Builder b = ImmutableMap.builder(); final YangTextSchemaContextResolver resolver = YangTextSchemaContextResolver.create("maven-plugin"); for (final File f : yangFilesInProject) { - final YangTextSchemaSourceRegistration reg = resolver.registerSource(YangTextSchemaSource.forFile(f)); - // Registration has an accurate identifier - b.put(reg.getInstance().getIdentifier(), f.getName()); - } - - final Map sourcesInProject = b.build(); - - /** - * Set contains all modules generated from input sources. Number of - * modules may differ from number of sources due to submodules - * (parsed submodule's data are added to its parent module). Set - * cannot contains null values. - */ - if (inspectDependencies) { - final List sourcesInDependencies = Util.findYangFilesInDependenciesAsStream( - project); - for (YangTextSchemaSource s : toUniqueSources(sourcesInDependencies)) { - resolver.registerSource(s); - } - } - - final SchemaContext schemaContext = resolver.trySchemaContext(); - final Set projectYangModules = new HashSet<>(); - final Map projectYangFiles = new HashMap<>(); - for (Module module : schemaContext.getModules()) { - final SourceIdentifier modId = moduleToIdentifier(module); - LOG.debug("Looking for source {}", modId); - final String file = sourcesInProject.get(modId); - if (file != null) { - LOG.debug("Module {} belongs to current project", module); - projectYangModules.add(module); - projectYangFiles.put(module, file); - - for (Module sub : module.getSubmodules()) { - final SourceIdentifier subId = moduleToIdentifier(sub); - final String subFile = sourcesInProject.get(subId); - if (subFile != null) { - LOG.debug("Submodule {} belongs to current project", sub); - projectYangFiles.put(sub, subFile); - } else { - LOG.warn("Submodule {} not found in input files", sub); - } - } - } + resolver.registerSource(YangTextSchemaSource.forFile(f)); } LOG.debug("Processed project files: {}", yangFilesInProject); LOG.info("{} Project model files parsed: {}", LOG_PREFIX, yangFilesInProject.size()); - return new ContextHolder(schemaContext, projectYangModules, projectYangFiles); + + final ProcessorModuleReactor reactor = new ProcessorModuleReactor(resolver); + LOG.debug("Initialized reactor {}", reactor, yangFilesInProject); + return Optional.of(reactor); } catch (Exception e) { // MojoExecutionException is thrown since execution cannot continue LOG.error("{} Unable to parse {} files from {}", LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir, e); @@ -224,17 +187,23 @@ class YangToSourcesProcessor { } } - private static SourceIdentifier moduleToIdentifier(final Module module) { - final QNameModule mod = module.getQNameModule(); - final Date rev = mod.getRevision(); - final Optional optRev; - if (!SimpleDateFormatUtil.DEFAULT_DATE_REV.equals(rev)) { - optRev = Optional.of(mod.getFormattedRevision()); - } else { - optRev = Optional.absent(); + private ContextHolder createContextHolder(final ProcessorModuleReactor reactor) throws MojoFailureException, + IOException, SchemaSourceException, YangSyntaxErrorException { + /** + * Set contains all modules generated from input sources. Number of + * modules may differ from number of sources due to submodules + * (parsed submodule's data are added to its parent module). Set + * cannot contains null values. + */ + if (inspectDependencies) { + final List sourcesInDependencies = Util.findYangFilesInDependenciesAsStream( + project); + for (YangTextSchemaSource s : toUniqueSources(sourcesInDependencies)) { + reactor.registerSource(s); + } } - return RevisionSourceIdentifier.create(module.getName(), optRev); + return reactor.toContext(); } private static Collection toUniqueSources(final Collection sources) diff --git a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java index 17f5074f49..53fb962ce7 100644 --- a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java +++ b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java @@ -56,11 +56,10 @@ public class GenerateSourcesTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - this.yang = new File(getClass().getResource("/yang/mock.yang").toURI()).getParent(); - this.outDir = new File("/outputDir"); + yang = new File(getClass().getResource("/yang/mock.yang").toURI()).getParent(); + outDir = new File("/outputDir"); final YangProvider mock = mock(YangProvider.class); - doNothing().when(mock).addYangsToMetaInf(any(MavenProject.class), any(File.class), - any(Collection.class)); + doNothing().when(mock).addYangsToMetaInf(any(MavenProject.class), any(Collection.class)); final YangToSourcesProcessor processor = new YangToSourcesProcessor(new File(this.yang), ImmutableList.of(), ImmutableList.of(new CodeGeneratorArg(GeneratorMock.class.getName(), "outputDir")), this.project, false, @@ -76,16 +75,15 @@ public class GenerateSourcesTest { @Test public void test() throws Exception { - this.mojo.execute(); - assertEquals(this.outDir, GeneratorMock.outputDir); - assertEquals(this.project, GeneratorMock.project); + mojo.execute(); + assertEquals(outDir, GeneratorMock.outputDir); + assertEquals(project, GeneratorMock.project); assertTrue(GeneratorMock.additionalCfg.isEmpty()); assertThat(GeneratorMock.resourceBaseDir.toString(), containsString("target" + File.separator + "generated-sources" + File.separator + "spi")); } public static class GeneratorMock implements BasicCodeGenerator, MavenProjectAware { - private static int called = 0; private static File outputDir; private static Map additionalCfg; diff --git a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/UtilTest.java b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/UtilTest.java index 5380b8b488..a6df5bdb25 100644 --- a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/UtilTest.java +++ b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/UtilTest.java @@ -15,6 +15,7 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import com.google.common.collect.ImmutableSet; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -26,10 +27,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarEntry; @@ -50,7 +49,6 @@ import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; -import org.opendaylight.yangtools.yang2sources.plugin.Util.ContextHolder; @RunWith(MockitoJUnitRunner.class) public class UtilTest { @@ -139,10 +137,10 @@ public class UtilTest { final File testYang1 = new File(getClass().getResource("/test.yang").toURI()); final File testYang2 = new File(getClass().getResource("/test2.yang").toURI()); final SchemaContext context = YangParserTestUtils.parseYangSources(testYang1, testYang2); - final Map yangModules = new HashMap<>(); - final Util.ContextHolder cxH = new ContextHolder(context, yangModules.keySet(), yangModules); + final Set yangModules = new HashSet<>(); + final ContextHolder cxH = new ContextHolder(context, yangModules, ImmutableSet.of()); assertEquals(context, cxH.getContext()); - assertEquals(yangModules.keySet(), cxH.getYangModules()); + assertEquals(yangModules, cxH.getYangModules()); } private URL makeMetaInf() throws Exception { diff --git a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojoTest.java b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojoTest.java index df7cce503d..041b24198b 100644 --- a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojoTest.java +++ b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojoTest.java @@ -75,6 +75,6 @@ public class YangToSourcesMojoTest { Mockito.when(mvnProject.getBuild()).thenReturn(build); final boolean dependencies = true; this.proc = new YangToSourcesProcessor(file, ImmutableList.of(excludedYang), codeGenerators, - mvnProject, dependencies, new YangProvider()); + mvnProject, dependencies, YangProvider.getInstance()); } } diff --git a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessorTest.java b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessorTest.java index 93c6497284..a3ca3f0c05 100644 --- a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessorTest.java +++ b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesProcessorTest.java @@ -54,7 +54,7 @@ public class YangToSourcesProcessorTest { Mockito.when(mvnProject.getBuild()).thenReturn(build); final boolean dependencies = true; final YangToSourcesProcessor proc = new YangToSourcesProcessor(file, ImmutableList.of(excludedYang), - codeGenerators, mvnProject, dependencies, new YangProvider()); + codeGenerators, mvnProject, dependencies, YangProvider.getInstance()); Assert.assertNotNull(proc); proc.execute(); } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java index cf5e75f8c0..1e1b3882e3 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java @@ -253,18 +253,6 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem return sc; } - @Beta - public SchemaContext trySchemaContext() throws SchemaResolutionException { - return trySchemaContext(StatementParserMode.DEFAULT_MODE); - } - - @Beta - public SchemaContext trySchemaContext(final StatementParserMode statementParserMode) - throws SchemaResolutionException { - final SchemaContextFactory factory = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); - return factory.createSchemaContext(ImmutableSet.copyOf(requiredSources), statementParserMode).checkedGet(); - } - @Override public synchronized CheckedFuture getSource( final SourceIdentifier sourceIdentifier) { @@ -288,6 +276,23 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem return ImmutableSet.copyOf(texts.keySet()); } + @Beta + public synchronized Collection getSourceTexts(final SourceIdentifier sourceIdentifier) { + return ImmutableSet.copyOf(texts.get(sourceIdentifier)); + } + + @Beta + public SchemaContext trySchemaContext() throws SchemaResolutionException { + return trySchemaContext(StatementParserMode.DEFAULT_MODE); + } + + @Beta + public SchemaContext trySchemaContext(final StatementParserMode statementParserMode) + throws SchemaResolutionException { + final SchemaContextFactory factory = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); + return factory.createSchemaContext(ImmutableSet.copyOf(requiredSources), statementParserMode).checkedGet(); + } + @Override public void close() { transReg.close();