Package com.alexkasko.springjdbc.typedqueries.mavenplugin

Source Code of com.alexkasko.springjdbc.typedqueries.mavenplugin.GenerateBeanQueriesMojo

package com.alexkasko.springjdbc.typedqueries.mavenplugin;

import com.alexkasko.springjdbc.typedqueries.codegen.CodeGenerator;
import com.alexkasko.springjdbc.typedqueries.common.PlainSqlQueriesParser;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.output.CountingOutputStream;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.springframework.util.ClassUtils;

import java.io.*;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;

import static org.apache.commons.io.FileUtils.openInputStream;
import static org.apache.commons.io.FileUtils.openOutputStream;
import static org.apache.commons.io.IOUtils.closeQuietly;

/**
* Maven-plugin, takes file with SQL queries and generates java methods for executing each query.
* For queries, that take input parameters, also generates an interface containing typed parameters getters.
*
* @author alexkasko
* Date: 12/22/12
*
* @goal codegen
* @phase generate-sources
*/
public class GenerateBeanQueriesMojo extends AbstractMojo {
    /**
     * Queries file
     *
     * @parameter expression="${typedqueries.queriesFile}"
     * @required
     */

    private File queriesFile;
    /**
     * Queries file
     *
     * @parameter expression="${typedqueries.queriesFile}"
     *            default-value="UTF-8"
     */
    private String queriesFileEncoding;
    /**
     * Generated class name, uses query file name bt default
     *
     * @parameter expression="${typedqueries.fullClassName}"
     */
    private String fullClassName;
    /**
     * Whether to check SQL file date and skip code generation
     *
     * @parameter expression="${typedqueries.checkSqlFileDate}"
     *            default-value="true"
     */
     private boolean checkSqlFileDate;
    /**
     * Whether to make generated class and its methods public or
     * package-private, true by default
     *
     * @parameter expression="${typedqueries.isPublic}" default-value="true"
     */
    private boolean isPublic;
    /**
     * Whether to use iterable jdbc template extensions from this
     * project (https://github.com/alexkasko/springjdbc-iterable),
     * false by default
     *
     * @parameter expression="${typedqueries.useIterableJdbcTemplate}"
     */
    private boolean useIterableJdbcTemplate;
    /**
     * Whether to generate additional update methods, those check that
     * only single row was changed on update, false by default
     *
     * @parameter expression="${typedqueries.useCheckSingleRowUpdates}"
     */
    private boolean useCheckSingleRowUpdates;
    /**
     * Whether to generate additional insert (DML) methods (with parameters), those
     * takes {@link java.util.Iterator} of parameters and execute inserts
     * for the contents of the specified iterator in batch mode, false by default
     *
     * @parameter expression="${typedqueries.useBatchInserts}"
     */
    private boolean useBatchInserts;
    /**
     * Whether to recognize query templates on method generation, false by default
     *
     * @parameter expression="${typedqueries.useTemplateStringSubstitution}"
     */
    private boolean useTemplateStringSubstitution;
    /**
     * Whether to convert underscored parameter named to camel ones, true by default
     *
     * @parameter expression="${typedqueries.useUnderscoredToCamel}" default-value="true"
     */
    private boolean useUnderscoredToCamel;

    /**
     * Whether to generate interfaces for columns, false by default
     *
     * @parameter expression="${typedqueries.generateInterfacesForColumns}"
     */
    private boolean generateInterfacesForColumns;
    /**
     * Regular expression to use for identifying 'select' queries by name,
     * default: '^select[a-zA-Z][a-zA-Z0-9_$]*$'
     *
     * @parameter expression="${typedqueries.selectRegex}"
     */
    private String selectRegex;
    /**
     * Regular expression to use for identifying 'insert', 'update' and 'delete' queries by name,
     * default: '^(?:insert|update|delete|create|drop)[a-zA-Z][a-zA-Z0-9_$]*$'
     *
     * @parameter expression="${typedqueries.updateRegex}"
     */
    private String updateRegex;
    /**
     * Regular expression to recognize query templates by name,
     * default: '^[a-zA-Z0-9_$]*Template$'
     *
     * @parameter expression="${typedqueries.templateRegex}"
     */
    private String templateRegex;
    /**
     * Regular expression constraint for template substitution values,
     * default: '^[a-zA-Z0-9_$]*$'
     *
     * @parameter expression="${typedqueries.templateValueConstraintRegex}"
     */
    private String templateValueConstraintRegex;
    /**
     * Mapping of query parameter names postfixes to data types in JSON map format, e.g.
     * '{"_long": "long", "_byte_a": "byte[]", "_date": "java.util.Date"}', see default in 'CodeGenerator' javadoc
     *
     * @parameter expression="${typedqueries.typeIdMapJson}"
     */
    private String typeIdMapJson;
    /**
     * FreeMarker template file for generating class
     *
     * @parameter expression="${typedqueries.freemarkerTemplate}"
     */
    private File templateFile;
    /**
     * FreeMarker template file encoding, 'UTF-8' by default
     *
     * @parameter expression="${typedqueries.freemarkerTemplateEncoding}"
     *            default-value="UTF-8"
     */
    private String templateFileEncoding;
    /**
     * @parameter expression="${project.basedir}"
     * @required
     * @readonly
     */
    private File baseDirectory;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        Writer outWriter = null;
        try {
            if(!(queriesFile.exists() && queriesFile.isFile())) throw new FileNotFoundException(queriesFile.getAbsolutePath());
            String fcn = null != fullClassName ? fullClassName : FilenameUtils.removeExtension(queriesFile.getName());
            File outFile = new File(baseDirectory, "src/main/java/" + fcn.replace(".", "/") + ".java");
            if (checkSqlFileDate && outFile.exists() && outFile.isFile() && outFile.length() > 0 &&
                    outFile.lastModified() >= queriesFile.lastModified()) {
                getLog().info("Typed queries file: [" + outFile.getAbsolutePath() + "] is up to date, skipping code generation");
                return;
            }
            Map<String, String> queries = readFile(queriesFile);
            CodeGenerator.Builder builder = CodeGenerator.builder();
            if(!isPublic) builder.setPublic(false);
            if(useIterableJdbcTemplate) builder.setUseIterableJdbcTemplate(true);
            if(useCheckSingleRowUpdates) builder.setUseCheckSingleRowUpdates(true);
            if(useBatchInserts) builder.setUseBatchInserts(true);
            if(useTemplateStringSubstitution) builder.setUseTemplateStringSubstitution(true);
            if(!useUnderscoredToCamel) builder.setUseUnderscoredToCamel(false);
            if(generateInterfacesForColumns) builder.setGenerateInterfacesForColumns(true);
            if(null != selectRegex) builder.setSelectRegex(selectRegex);
            if(null != updateRegex) builder.setUpdateRegex(updateRegex);
            if(null != templateRegex) builder.setTemplateRegex(templateRegex);
            if(null != templateValueConstraintRegex) builder.setTemplateValueConstraintRegex(templateValueConstraintRegex);
            if(null != typeIdMapJson) builder.setTypeIdMap(parseTypeIdMap(typeIdMapJson));
            if(null != templateFile) builder.setFreemarkerTemplate(FileUtils.readFileToString(templateFile, templateFileEncoding));
            CodeGenerator cg = builder.build();
            CountingOutputStream counter = new CountingOutputStream(openOutputStream(outFile));
            outWriter = new OutputStreamWriter(counter, "UTF-8");
            getLog().info("Generating queries wrapper for file: [" + queriesFile.getAbsolutePath() + "] " +
                    "into java file: [" + outFile.getAbsolutePath() + "]");
            cg.generate(queries, fcn, queriesFile.getName(), outWriter);
            getLog().info("Writing compete, bytes written: [" + counter.getCount() + "]");
        } catch(IOException e) {
            throw new MojoFailureException("IO error", e);
        } catch (ClassNotFoundException e) {
            throw new MojoFailureException("Type id map error", e);
        } finally {
            closeQuietly(outWriter);
        }
    }

    @SuppressWarnings("unchecked") // properties API
    private Map<String, String> readFile(File file) throws IOException {
        if (!file.exists() && file.isFile()) throw new FileNotFoundException(
                "Cannot read queries file: [" + file.getAbsolutePath() + "]");
        InputStream is = null;
        try {
            String fname = file.getName().toLowerCase();
            final Map<String, String> res;
            is = openInputStream(file);
            if (fname.endsWith("sql")) {
                res = new PlainSqlQueriesParser().parse(is, queriesFileEncoding);
            } else if (fname.endsWith("json")) {
                Reader re = new InputStreamReader(is, queriesFileEncoding);
                Type mapType = new TypeToken<LinkedHashMap<String, String>>(){}.getType();
                res = new Gson().fromJson(re, mapType);
            } else if (fname.endsWith("properties")) {
                Properties props = new Properties();
                props.load(new InputStreamReader(is, queriesFileEncoding));
                res = (Map) props;
            } else if (fname.endsWith("xml")) {
                Properties props = new Properties();
                props.loadFromXML(is);
                res = (Map) props;
            } else throw new IOException("Cannot parse queries file: [" + file.getAbsolutePath() +"], " +
                    "only '*.sql', '*.json', '*.properties' and '*.xml' files are supported");
            return res;
        } finally {
            closeQuietly(is);
        }
    }

    private Map<String, Class<?>> parseTypeIdMap(String json) throws ClassNotFoundException {
        Type mapType = new TypeToken<LinkedHashMap<String, String>>(){}.getType();
        Map<String, String> strings = new Gson().fromJson(json, mapType);
        Map<String, Class<?>> res = new LinkedHashMap<String, Class<?>>();
        for(Map.Entry<String, String> en : strings.entrySet()) {
            Class<?> clazz = ClassUtils.forName(en.getValue(), GenerateBeanQueriesMojo.class.getClassLoader());
            res.put(en.getKey(), clazz);
        }
        return res;
    }
}
TOP

Related Classes of com.alexkasko.springjdbc.typedqueries.mavenplugin.GenerateBeanQueriesMojo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.