All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tentackle.maven.wizard.AbstractWizardMojo Maven / Gradle / Ivy

There is a newer version: 21.16.1.0
Show newest version
/*
 * Tentackle - http://www.tentackle.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */


package org.tentackle.maven.wizard;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.model.fileset.FileSet;

import org.tentackle.model.EntityAliases;
import org.tentackle.model.Model;
import org.tentackle.model.ModelDefaults;
import org.tentackle.model.ModelException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * Base wizard mojo.
 *
 * @author harald
 */
public abstract class AbstractWizardMojo extends AbstractMojo {

  /**
   * The Maven Project.
   */
  @Parameter(defaultValue = "${project}", readonly = true, required = true)
  private MavenProject mavenProject;

  /**
   * Directory holding the model files to be processed.
* Ignored if fileset explicitly given. */ @Parameter(defaultValue = "${project.build.directory}/wurbel/model", property = "tentackle.modelDir") protected File modelDir; /** * Directory holding the status info.
* Used to store the next free classId per profile in case multiple PDOs are * generated without an intermediate mvn clean package/install or wurbel run.
* Must be a subdir of the target directory to be removed via mvn clean. */ @Parameter(defaultValue = "${project.build.directory}/wizard") private File statusDir; /** * The model defaults. */ @Parameter(property = "tentackle.modelDefaults") protected String modelDefaults; /** * The entity aliases. */ @Parameter(property = "tentackle.entityAliases") protected String entityAliases; /** * The list of file sets containing the model.
* If set, the modelDir is ignored. */ @Parameter protected List filesets; /** * The profiles. */ @Parameter(required = true) private List profiles; /** * The directory holding the templates. */ @Parameter(defaultValue = "${project.basedir}/templates") private File templateDir; /** * Gets the profiles. * * @param the profile type * @param clazz the concrete profile class * @return the list of profiles * @throws MojoExecutionException if profile names are not unique */ @SuppressWarnings("unchecked") public List getProfiles(Class clazz) throws MojoExecutionException { List list = new ArrayList<>(); for (Profile profile : profiles) { if (clazz.isAssignableFrom(profile.getClass())) { if (list.contains(profile)) { throw new MojoExecutionException("profile " + profile + " configured more than once"); } list.add((T) profile); } } return list; } /** * Gets the template directory. * * @return the directory holding the wizard templates */ public File getTemplateDir() { return templateDir; } /** * Gets the status directory. * * @return the status dir */ public File getStatusDir() { return statusDir; } @Override public void execute() throws MojoExecutionException, MojoFailureException { validate(); loadModel(); } /** * Gets the model defaults. * * @return the defaults, null if none * @throws MojoExecutionException if parsing the model defaults failed */ protected ModelDefaults getModelDefaults() throws MojoExecutionException { if (modelDefaults == null) { return null; } try { return new ModelDefaults(modelDefaults); } catch (ModelException mex) { throw new MojoExecutionException(mex.getMessage(), mex); } } /** * Gets the entity aliases. * * @return the aliases, null if none * @throws MojoExecutionException if parsing the aliases failed */ protected EntityAliases getEntityAliases() throws MojoExecutionException { if (entityAliases == null) { return null; } try { return new EntityAliases(entityAliases); } catch (ModelException mex) { throw new MojoExecutionException(mex.getMessage(), mex); } } /** * Loads the model. *

* Notice: the model is only needed by the {@link PdoMojo}, but we configure it for the whole plugin. * * @throws MojoFailureException if the model is inconsistent * @throws MojoExecutionException if loading failed due to some other error */ protected void loadModel() throws MojoFailureException, MojoExecutionException { int errors = 0; if (filesets != null && !filesets.isEmpty()) { // explicit filesets given instead of model dir for (FileSet fileSet : filesets) { errors += processFileSet(fileSet); } } else { // all from model dir String[] files = modelDir.isDirectory() ? modelDir.list() : null; if (files != null && files.length > 0) { final FileSet fs = new FileSet(); fs.setDirectory(modelDir.getPath()); errors += processFileSet(fs); } else { getLog().warn((modelDir.exists() ? "empty modelDir " : "no modelDir ") + modelDir.getAbsolutePath()); } } if (errors > 0) { throw new MojoFailureException(errors + " model errors"); } try { getLog().info(Model.getInstance().getAllEntitites().size() + " entities loaded"); } catch (ModelException e) { throw new MojoExecutionException("cannot determine entities", e); } } /** * Processes a fileset to load the model. * * @param fileSet the fileset containing the model * @return the number of errors * @throws MojoExecutionException if model defaults or entity aliases could not be determined */ protected int processFileSet(FileSet fileSet) throws MojoExecutionException { int errors = 0; if (fileSet.getDirectory() == null) { // directory missing: use modelDir as default fileSet.setDirectory(modelDir.getAbsolutePath()); } File dir = new File(fileSet.getDirectory()); String modelDirName = dir.getPath(); try { Model.getInstance().loadModel(modelDirName, getModelDefaults(), getEntityAliases()); } catch (ModelException mex) { getLog().error("parsing model failed in directory " + modelDirName + ":\n" + mex.getMessage()); errors++; } return errors; } /** * Validates the configuration. * * @throws MojoExecutionException if project not set or misconfigured */ protected void validate() throws MojoExecutionException { if (mavenProject == null) { throw new MojoExecutionException("missing project"); } if (mavenProject.getBasedir() == null) { throw new MojoExecutionException("missing project.baseDir"); } if (templateDir.exists()) { if (!templateDir.isDirectory()) { throw new MojoExecutionException(templateDir.getPath() + " is not a directory"); } } else { templateDir.mkdirs(); getLog().info("template directory created: " + templateDir.getPath()); installTemplates(); } } /** * Copies the templates to the template directory.
* Overwrites any existing templates. * * @throws MojoExecutionException if failed */ protected void installTemplates() throws MojoExecutionException { installTemplate(Constants.CATEGORY_PDO, "DomainImplementation.ftl"); installTemplate(Constants.CATEGORY_PDO, "DomainInterface.ftl"); installTemplate(Constants.CATEGORY_PDO, "PdoInterface.ftl"); installTemplate(Constants.CATEGORY_PDO, "PersistenceImplementation.ftl"); installTemplate(Constants.CATEGORY_PDO, "PersistenceInterface.ftl"); installTemplate(Constants.CATEGORY_OPERATION, "DomainImplementation.ftl"); installTemplate(Constants.CATEGORY_OPERATION, "DomainInterface.ftl"); installTemplate(Constants.CATEGORY_OPERATION, "OperationInterface.ftl"); installTemplate(Constants.CATEGORY_OPERATION, "PersistenceImplementation.ftl"); installTemplate(Constants.CATEGORY_OPERATION, "PersistenceInterface.ftl"); } private void installTemplate(String category, String template) throws MojoExecutionException { File dir = new File(templateDir, category); dir.mkdirs(); File file = new File(dir, template); String path = "/templates/" + category + "/" + template; String text = loadResourceFileIntoString(path); try (PrintStream ps = new PrintStream(new FileOutputStream(file))) { ps.print(text); getLog().info("installed " + category + "-template " + template); } catch (IOException e) { throw new MojoExecutionException("cannot install template " + path, e); } } private String loadResourceFileIntoString(String path) throws MojoExecutionException { InputStream inputStream = getClass().getResourceAsStream(path); if (inputStream == null) { throw new MojoExecutionException("no such resource: " + path); } BufferedReader buffer = new BufferedReader(new InputStreamReader(inputStream)); return buffer.lines().collect(Collectors.joining(System.getProperty("line.separator"))); } /** * Creates a map of package names to package infos. * * @return the packages * @throws MojoExecutionException if split package detected */ protected Map createPackageMap() throws MojoExecutionException { Map map = new HashMap<>(); StringBuilder buf = new StringBuilder(); for (MavenProject project : mavenProject.getCollectedProjects()) { for (String path : project.getCompileSourceRoots()) { for (PackageInfo info : getPackages(project, path)) { boolean infoContaingFiles = info.isContainingJavaFiles(); PackageInfo splitPkg = map.get(info.getName()); if (splitPkg != null) { if (splitPkg.isContainingJavaFiles()) { if (infoContaingFiles) { buf.append("\nsplit package detected: " + info.getName() + " in " + project.getName() + " and " + splitPkg.getProject().getName()); } // other package is empty: keep existing with java files continue; } else if (!infoContaingFiles) { // more than one empty package found: add it to the suspects until we know whether a non-empty exists List dups = splitPkg.getEmptyDuplicates(); if (dups == null) { dups = new ArrayList<>(); splitPkg.setEmptyDuplicates(dups); } dups.add(info); continue; } // else: split is empty and info contains java files -> replace empty } // add new or replace empty package map.put(info.getName(), info); } } } if (buf.length() > 0) { // at least one split package found // this isnt okay whether used in profiles or not buf.deleteCharAt(0); // remove leading newline throw new MojoExecutionException(buf.toString()); } return map; } private List getPackages(MavenProject project, String compileSourceRoot) { List packages = new ArrayList<>(); checkDir(project, new File(compileSourceRoot), packages, ""); return packages; } private void checkDir(MavenProject project, File dir, List packages, String packageName) { if (dir.isDirectory()) { boolean containsJavaFiles = false; boolean empty = true; for (File file : dir.listFiles()) { if (!file.isHidden()) { empty = false; if (file.isDirectory()) { checkDir(project, file, packages, packageName.isEmpty() ? file.getName() : packageName + "." + file.getName()); } else if (file.getName().endsWith(".java")) { containsJavaFiles = true; } } } if ((empty || containsJavaFiles) && !packageName.isEmpty()) { packages.add(new PackageInfo(packageName, project, dir)); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy