com.sixdegreeshq.sitenav.GeneratorMojo.java Source code

Java tutorial

Introduction

Here is the source code for com.sixdegreeshq.sitenav.GeneratorMojo.java

Source

/*
 * Copyright 2016 alessandro negrin <alessandro@sixdegreeshq.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.sixdegreeshq.sitenav;

import com.sixdegreeshq.sitenav.model.Page;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import lombok.Getter;
import lombok.Setter;
import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.xml.sax.InputSource;

/**
 *
 * @author alessandro
 */
@Mojo(name = "generator", defaultPhase = LifecyclePhase.PROCESS_RESOURCES)
public class GeneratorMojo extends AbstractMojo {

    /**
     * site map xml resource location in classpath
     *
     */
    @Getter
    @Setter
    @Parameter(defaultValue = "sitenav.xml")
    private String inputResourceLocation = "sitenav.xml";

    /**
     * package for autogenerated classes
     *
     */
    @Getter
    @Setter
    @Parameter(defaultValue = "R")
    private String outputPackage = "R";

    /**
     * folder for generated sources
     *
     */
    @Getter
    @Setter
    @Parameter(defaultValue = "target/generated-sources/java")
    private File outputFolder = new File("target/generated-sources/java");

    /**
     * if running tests
     *
     */
    @Getter
    @Setter
    @Parameter(defaultValue = "false")
    private boolean testing;

    /**
     * java code to resolve locale
     *
     */
    @Getter
    @Setter
    @Parameter(defaultValue = "java.util.Locale.getDefault()")
    private String localeResolutionCode = "java.util.Locale.getDefault()";

    private Log log = getLog();

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        try {

            MavenProject project = MavenProject.class.cast(getPluginContext().get("project"));

            project.addCompileSourceRoot(outputFolder.getAbsolutePath());

            if (testing) {
                project.addTestCompileSourceRoot(outputFolder.getAbsolutePath());
            } else {
                project.addCompileSourceRoot(outputFolder.getAbsolutePath());
            }

            ClassLoader cl = getProjectClassLoader(project);

            SitenavHandler sitenavHandler = new SitenavHandler();

            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            parser.parse(new InputSource(cl.getResourceAsStream(inputResourceLocation)), sitenavHandler);

            File packageDir = new File(outputFolder, outputPackage.replace('.', '/'));
            packageDir.mkdirs();

            if (sitenavHandler.getRoot().getChildren() != null) {
                String pageSB = readResource("/com/sixdegreeshq/sitenav/tpl/Page.tpl");

                String pageContent = pageSB.toString().replace("${packageName}", outputPackage);
                FileOutputStream pageFOS = new FileOutputStream(new File(packageDir, "Page.java"));
                pageFOS.write(pageContent.getBytes());
                pageFOS.close();

                for (Page topLevelNode : sitenavHandler.getRoot().getChildren()) {
                    String className = topLevelNode.alias;
                    File javaFile = new File(packageDir, className + ".java");
                    PrintWriter pw = new PrintWriter(javaFile, "UTF-8");

                    String nodeSB = readResource("/com/sixdegreeshq/sitenav/tpl/Node.tpl");
                    ;
                    String nodeContent = nodeSB.toString().replace("${localeDeclaration}", localeResolutionCode)
                            .replace("${className}", className)
                            .replace("${packageDeclaration}", "package " + outputPackage + ";")
                            .replace("${alias}", className)
                            .replace("${langs}", toString(topLevelNode.getPaths(), true))
                            .replace("${paths}", toString(topLevelNode.getPaths(), false))
                            .replace("${pathsDeclarations}", getDeclarations(topLevelNode.getPaths()))
                            .replace("${classModifier}", "");

                    nodeContent = nodeContent.replace("${childrenDeclaration}", navigate(topLevelNode));
                    nodeContent = nodeContent.replace("${children}", children(topLevelNode));

                    FileOutputStream nodeFOS = new FileOutputStream(new File(packageDir, className + ".java"));
                    nodeFOS.write(nodeContent.getBytes());
                    nodeFOS.close();
                }
            }

        } catch (Throwable t) {
            t.printStackTrace();
            throw new MojoExecutionException(t.getMessage(), t);
        }

    }

    private String readResource(String resource) throws IOException {
        Reader pageReader = new InputStreamReader(getClass().getResourceAsStream(resource));
        StringBuffer pageSB = new StringBuffer(1024);
        char[] buffer = new char[4096];
        int read = -1;
        while ((read = pageReader.read(buffer)) != -1) {
            pageSB.append(buffer, 0, read);
        }
        pageReader.close();
        return pageSB.toString();
    }

    private String navigate(Page page) throws IOException {

        StringBuffer code = new StringBuffer(1024);

        if (page.getChildren() != null) {
            for (Page child : page.getChildren()) {

                String nodeSB = readResource("/com/sixdegreeshq/sitenav/tpl/Node.tpl");

                String nodeContent = nodeSB.toString().replace("${localeDeclaration}", localeResolutionCode)
                        .replace("${className}", child.alias).replace("${packageDeclaration}", "")
                        .replace("${alias}", child.alias).replace("${langs}", toString(child.getPaths(), true))
                        .replace("${paths}", toString(child.getPaths(), false))
                        .replace("${pathsDeclarations}", getDeclarations(child.getPaths()))
                        .replace("${classModifier}", "static");

                nodeContent = nodeContent.replace("${childrenDeclaration}", navigate(child));
                nodeContent = nodeContent.replace("${children}", children(child));

                code.append('\n').append(nodeContent).append('\n');
            }
        }

        return code.toString();

    }

    private String capitalize(final String line) {
        return Character.toUpperCase(line.charAt(0)) + line.substring(1);
    }

    private CharSequence toString(List<Page.Path> paths, boolean lang) {
        StringBuffer sb = new StringBuffer();
        boolean first = true;
        for (Page.Path path : paths) {
            if (!first) {
                sb.append(',');
            }
            first = false;
            sb.append('"').append(lang ? path.lang : path.value).append('"');
        }

        return sb.toString();
    }

    /**
     * got from
     * https://github.com/querydsl/querydsl/blob/master/querydsl-maven-plugin/src/main/java/com/querydsl/maven/AbstractExporterMojo.java
     *
     */
    @SuppressWarnings("unchecked")
    private ClassLoader getProjectClassLoader(MavenProject project)
            throws DependencyResolutionRequiredException, MalformedURLException {
        List<String> classpathElements;
        if (testing) {
            classpathElements = project.getTestClasspathElements();
            for (Resource testResource : project.getTestResources()) {
                classpathElements.add(testResource.getDirectory());
            }

        } else {
            classpathElements = project.getCompileClasspathElements();
        }

        for (Resource testResource : project.getResources()) {
            classpathElements.add(testResource.getDirectory());
        }

        List<URL> urls = new ArrayList<URL>(classpathElements.size());
        for (String element : classpathElements) {
            File file = new File(element);
            if (file.exists()) {
                urls.add(file.toURI().toURL());
            }
        }
        return new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader());
    }

    private CharSequence getDeclarations(List<Page.Path> paths) {
        StringBuffer sb = new StringBuffer();
        if (paths != null) {
            for (Page.Path path : paths) {
                sb.append("/** ").append(path.value).append(" */").append('\n');
                sb.append("public static final String path");
                if (!"*".equals(path.lang)) {
                    sb.append('_').append(path.lang);
                }
                sb.append("=\"").append(path.value).append("\";").append('\n');
                sb.append("/** ").append(path.value).append(" */").append('\n');
                sb.append("public static final String p");
                if (!"*".equals(path.lang)) {
                    sb.append('_').append(path.lang);
                }
                sb.append("=\"").append(path.value).append("\";").append('\n');
            }
        }

        return sb;
    }

    private CharSequence children(Page page) {
        if (!page.getChildren().isEmpty()) {
            StringBuffer sb = new StringBuffer();
            boolean first = true;
            for (Page child : page.getChildren()) {
                if (!first) {
                    sb.append(',');
                }
                sb.append(page.alias + "." + child.alias + ".class");
                first = false;
            }
            return sb.toString();
        }

        return "";
    }
}