001/*******************************************************************************
002 * Copyright (c) 2017 Red Hat Inc
003 * All rights reserved. This program and the accompanying materials
004 * are made available under the terms of the Eclipse Public License v1.0
005 * which accompanies this distribution, and is available at
006 * http://www.eclipse.org/legal/epl-v10.html
007 *
008 * Contributors:
009 *     Jens Reimann - initial API and implementation
010 *******************************************************************************/
011package de.dentrassi.varlink.maven;
012
013import static java.nio.file.Files.walkFileTree;
014
015import java.io.File;
016import java.io.IOException;
017import java.nio.charset.Charset;
018import java.nio.file.FileVisitResult;
019import java.nio.file.Path;
020import java.nio.file.SimpleFileVisitor;
021import java.nio.file.attribute.BasicFileAttributes;
022import java.util.HashMap;
023import java.util.List;
024import java.util.Map;
025
026import org.apache.maven.plugin.AbstractMojo;
027import org.apache.maven.plugin.MojoExecutionException;
028import org.apache.maven.plugin.MojoFailureException;
029import org.apache.maven.plugins.annotations.Component;
030import org.apache.maven.plugins.annotations.LifecyclePhase;
031import org.apache.maven.plugins.annotations.Mojo;
032import org.apache.maven.plugins.annotations.Parameter;
033import org.apache.maven.project.MavenProject;
034import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
035import org.sonatype.plexus.build.incremental.BuildContext;
036
037import de.dentrassi.varlink.generator.Generator;
038import de.dentrassi.varlink.generator.JdtGenerator;
039
040/**
041 * Generate Java bindings for a Varlink file
042 */
043@Mojo(defaultPhase = LifecyclePhase.GENERATE_SOURCES, name = "generate", requiresProject = true)
044public class GenerateMojo extends AbstractMojo {
045
046    /**
047     * Allows to skip the generation
048     */
049    @Parameter(property = "varlink.skip", required = false, defaultValue = "false")
050    private boolean skip;
051
052    public void setSkip(final boolean skip) {
053        this.skip = skip;
054    }
055
056    public boolean isSkip() {
057        return this.skip;
058    }
059
060    /**
061     * The character set to use for the generated resources
062     */
063    @Parameter(property = "varlink.generator.charset", required = true, defaultValue = "${project.build.sourceEncoding}")
064    private String characterSet;
065
066    public void setCharacterSet(final String characterSet) {
067        this.characterSet = characterSet;
068    }
069
070    public String getCharacterSet() {
071        return this.characterSet;
072    }
073
074    /**
075     * The path to generate the sources to
076     */
077    @Parameter(required = true, property = "varlink.targetPath", defaultValue = "${project.build.directory}/generated-sources/varlink")
078    private File targetPath;
079
080    public void setTargetPath(final File targetPath) {
081        this.targetPath = targetPath;
082    }
083
084    public File getTargetPath() {
085        return this.targetPath;
086    }
087
088    /**
089     * The path to load the sources from
090     */
091    @Parameter(required = true, property = "varlink.sourcePath", defaultValue = "${basedir}/src/main/varlink")
092    private File sourcePath;
093
094    public void setSourcePath(final File sourcePath) {
095        this.sourcePath = sourcePath;
096    }
097
098    public File getSourcePath() {
099        return this.sourcePath;
100    }
101
102    @Parameter(property = "project", readonly = true, required = true)
103    protected MavenProject project;
104
105    public void setProject(final MavenProject project) {
106        this.project = project;
107    }
108
109    @Component
110    private BuildContext buildContext;
111
112    public void setBuildContext(final BuildContext buildContext) {
113        this.buildContext = buildContext;
114    }
115
116    @Override
117    public void execute() throws MojoExecutionException, MojoFailureException {
118
119        try {
120
121            // load interfaces
122
123            final Loader loader = new Loader();
124
125            final Map<String, List<Diagnostic>> errors = new HashMap<>();
126
127            walkFileTree(
128                    this.sourcePath.toPath(),
129                    new SimpleFileVisitor<Path>() {
130                        @Override
131                        public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
132                                throws IOException {
133
134                            final List<Diagnostic> localErrors = loader.loadFrom(file);
135                            if (!localErrors.isEmpty()) {
136                                errors.put(file.toString(), localErrors);
137                            }
138
139                            return FileVisitResult.CONTINUE;
140                        }
141                    });
142
143            // process errors
144
145            if (!errors.isEmpty()) {
146                for (final Map.Entry<String, List<Diagnostic>> entry : errors.entrySet()) {
147                    for (final Diagnostic diag : entry.getValue()) {
148                        String location = diag.getLocation();
149                        if (location == null) {
150                            location = entry.getKey();
151                        }
152                        getLog().error(String.format("%s:%s:%s: %s", location, diag.getLine(),
153                                diag.getColumn(), diag.getMessage()));
154                    }
155                }
156                throw new MojoFailureException("Failed to validate models. See log for more information.");
157            }
158
159            // setup generator
160
161            final Generator.Options options = new Generator.Options();
162
163            if (this.characterSet != null) {
164                options.setCharacterSet(Charset.forName(this.characterSet));
165            }
166            if (this.targetPath != null) {
167                options.setTargetPath(this.targetPath.toPath());
168            }
169
170            final Generator generator = new JdtGenerator(options);
171
172            // generate
173
174            generator.generateAll(loader);
175
176            // add sources
177
178            this.project.addCompileSourceRoot(this.targetPath.getAbsolutePath());
179            this.buildContext.refresh(this.targetPath.getAbsoluteFile());
180
181        } catch (final Exception e) {
182            throw new MojoExecutionException("Failed to generate", e);
183        }
184
185    }
186}