org.zgif.model.tools.GenerationPostProcessor.java Source code

Java tutorial

Introduction

Here is the source code for org.zgif.model.tools.GenerationPostProcessor.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Martin Fluegge (Berlin, Germany) 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
 *  
 * Contributors:
 *    Martin Fluegge - initial API and implementation and/or initial documentation
 *  
 *******************************************************************************/
package org.zgif.model.tools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

/**
 * @author Martin Fluegge
 * 
 */
public class GenerationPostProcessor {

    //@formatter:off
    private List<String> deleteFiles = Arrays.asList("ObjectFactory.java");
    private List<String> typeNames = Arrays.asList("Amount", "Area");

    private List<String> removeLines = Arrays.asList("    @XmlElement(name = \"extension_map\")",
            "    protected ExtensionMap extensionMap;");
    //@formatter:on

    private static final String BASE_PACKAGE = "org.zgif.model";
    private static final String NODE_PACKAGE = "org.zgif.model.node";
    private static final String GROUP_PACKAGE = "org.zgif.model.node.group";
    private static final String ENTITY_PACKAGE = "org.zgif.model.node.entity";
    private static final String TYPE_PACKAGE = "org.zgif.model.datatype";
    private static final String ENUM_PACKAGE = "org.zgif.model.datatype.enumeration";

    private static final Logger ROOT_LOGGER = Logger.getRootLogger();
    private static final Log LOG = LogFactory.getLog(GenerationPostProcessor.class);

    private File baseDir;
    private Map<String, String> classPackageMap = new HashMap<String, String>();

    public static void main(String[] args) throws Throwable {
        if (!ROOT_LOGGER.getAllAppenders().hasMoreElements()) {
            PatternLayout layout = new PatternLayout("%d{ISO8601} %-5p [%t] %c: %m%n");
            ConsoleAppender consoleAppender = new ConsoleAppender(layout);
            ROOT_LOGGER.addAppender(consoleAppender);
            ROOT_LOGGER.setLevel(Level.ALL);
        }

        new GenerationPostProcessor().run();
    }

    public void run() throws Throwable {
        LOG.info("Starting post processing");

        File scriptPath = new File(getClass().getResource("").toURI());
        baseDir = traversalFile(scriptPath, "..", "..", "..", "..", "..", "..", "src", "main", "generated-sources");
        LOG.debug("baseDir=" + baseDir);

        File modelBaseDir = traversalFile(baseDir, BASE_PACKAGE.split("[.]"));
        for (File subDir : modelBaseDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.isDirectory();
            }
        })) {
            LOG.info("delete dir: " + subDir);
            boolean isDeleted = deleteFile(subDir);
            if (!isDeleted) {
                LOG.error("cannot delete dir: " + subDir.getCanonicalPath());
                throw new Exception("cannot delete dir: " + subDir.getCanonicalPath());
            }
        }

        Boolean arePackagesToClean = false;
        for (File sourceFile : modelBaseDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.isFile() && f.getName().endsWith(".java");
            }
        })) {
            arePackagesToClean = true;

            String fileName = sourceFile.getName();

            if (deleteFiles.contains(fileName)) {
                sourceFile.delete();
            } else {
                String packageName = null;

                if (packageName == null) {
                    for (String typeName : typeNames) {
                        if (fileName.equals(typeName + ".java")) {
                            packageName = TYPE_PACKAGE;
                        }
                    }
                }

                if (packageName == null) {
                    if (fileName.equals("AbstractGroupNode.java")
                            || fileContains(sourceFile, ".*extends AbstractGroupNode.*", ".*protected.*;")) {
                        packageName = GROUP_PACKAGE;
                    }
                }

                if (packageName == null) {
                    if (fileName.equals("AbstractEntityNode.java")
                            || fileContains(sourceFile, ".*extends AbstractEntityNode.*", ".*protected.*;")) {
                        packageName = ENTITY_PACKAGE;
                    }
                }

                if (packageName == null) {
                    if (fileName.equals("AbstractNode.java")
                            || fileContains(sourceFile, ".*extends AbstractNode.*", ".*protected.*;")) {
                        packageName = NODE_PACKAGE;
                    }
                }

                if (packageName == null) {
                    if (fileContains(sourceFile, "public enum .*", ".*protected.*;")) {
                        packageName = ENUM_PACKAGE;
                    }
                }

                // TODO: bad workaround until other bugs with generating are
                // completed
                if (packageName == null) {
                    if (fileName.startsWith("Hash") || fileName.startsWith("Term") || fileName.endsWith("s.java")) {
                        packageName = ENTITY_PACKAGE;
                    }
                }

                if (packageName != null) {
                    moveFile(sourceFile, packageName);
                }
            }
        }

        if (arePackagesToClean) {
            cleanupPackage(NODE_PACKAGE);
            cleanupPackage(ENTITY_PACKAGE);
            cleanupPackage(GROUP_PACKAGE);
            cleanupPackage(TYPE_PACKAGE);
            cleanupPackage(ENUM_PACKAGE);
            cleanupPackage(BASE_PACKAGE);
        } else {
            LOG.warn("no java files found in baseDir");
            throw new Exception("no java files found in baseDir");
        }
    }

    public void moveFile(File sourceFile, String packageName) throws Throwable {
        String fileName = sourceFile.getName();
        LOG.info("move file '" + fileName + "' to package: " + packageName);

        File newDir = traversalFile(baseDir.getCanonicalFile(), packageName.split("[.]"));
        File newSourceFile = new File(newDir, fileName);

        newDir.mkdirs();
        Boolean renamed = sourceFile.renameTo(newSourceFile);

        if (renamed) {
            classPackageMap.put(fileName.substring(0, fileName.length() - 5), packageName);
        }
    }

    public void cleanupPackage(String packageName) throws Throwable {
        LOG.info("cleanup package: " + packageName);

        File packageDir = traversalFile(baseDir.getCanonicalFile(), packageName.split("[.]"));
        LOG.debug("packageDir=" + packageDir);
        if (packageDir.exists()) {
            for (File sourceFile : packageDir.listFiles()) {
                if (sourceFile.isFile() && sourceFile.getName().endsWith(".java")) {
                    rewriteFile(sourceFile, packageName);
                }
            }
        }
    }

    public void rewriteFile(File sourceFile, String packageName) throws Throwable {
        final String fileName = sourceFile.getName();
        final String currentModelClassName = fileName.substring(0, fileName.length() - 5);

        Set<String> usedModelClasses = new HashSet<String>();

        final String linePublicClass = "public class " + currentModelClassName + " {";
        String classExtension = null;
        if (packageName.equals(NODE_PACKAGE)) {
            classExtension = "AbstractNode";
            usedModelClasses.add("AbstractNode");
        } else if (packageName.equals(ENTITY_PACKAGE)) {
            classExtension = "AbstractEntityNode";
            usedModelClasses.add("AbstractEntityNode");
        } else if (packageName.equals(GROUP_PACKAGE)) {
            classExtension = "AbstractGroupNode";
            usedModelClasses.add("AbstractGroupNode");
        }

        // backup File
        File tmpFile = new File(sourceFile.getParent(), fileName + ".bak");
        sourceFile.renameTo(tmpFile);

        // read file
        BufferedReader reader = new BufferedReader(new FileReader(tmpFile));

        StringBuilder body = new StringBuilder((int) tmpFile.length());
        String lineBefore = "";
        Set<String> flags = new HashSet<String>();
        for (String line = reader.readLine(); line != null; line = reader.readLine()) {
            if (lineBefore.equals("    /**") && line.contains("extensionMap")) {
                flags.add("xetter_extensionMap");
                body.append("*/");
                body.append(System.lineSeparator());
            }
            if (lineBefore.equals("    /**") && line.contains("validFrom")) {
                flags.add("xetter_validFrom");
                body.append("*/");
                body.append(System.lineSeparator());
            }
            if (lineBefore.equals("    /**") && line.contains("validTo")) {
                flags.add("xetter_validTo");
                body.append("*/");
                body.append(System.lineSeparator());
            }

            if (!removeLines.contains(line) && !flags.contains("xetter_extensionMap")
                    && !flags.contains("xetter_validFrom") && !flags.contains("xetter_validTo")) {
                for (String modelClass : classPackageMap.keySet()) {
                    if (!modelClass.equals(currentModelClassName) && (line.contains(" " + modelClass + " ")
                            || line.contains(modelClass + ".class") || line.contains("extends " + modelClass))) {
                        usedModelClasses.add(modelClass);
                    }
                }

                if (classExtension != null && !flags.contains("PublicClassPassed")
                        && line.equals(linePublicClass)) {
                    line = line.substring(0, line.length() - 1) + "extends " + classExtension + " {";
                    flags.add("PublicClassPassed");
                }

                if (!line.startsWith("package")) {
                    body.append(line);
                    body.append(System.lineSeparator());
                }
            }

            if (flags.contains("xetter_extensionMap") && line.equals("    }")) {
                flags.remove("xetter_extensionMap");
            }
            if (flags.contains("xetter_validFrom") && line.equals("    }")) {
                flags.remove("xetter_validFrom");
            }
            if (flags.contains("xetter_validTo") && line.equals("    }")) {
                flags.remove("xetter_validTo");
            }

            lineBefore = line;
        }
        reader.close();

        // append package and imports
        BufferedWriter writer = new BufferedWriter(new FileWriter(sourceFile));
        writer.append("package " + packageName + ";" + System.lineSeparator() + System.lineSeparator());
        for (String usedModel : usedModelClasses) {
            writer.append(
                    "import " + classPackageMap.get(usedModel) + "." + usedModel + ";" + System.lineSeparator());
        }

        // write body
        writer.append(body.toString());
        writer.close();

        // delete original file
        tmpFile.delete();
    }

    // public static Boolean fileContains(File file, String regex) throws
    // FileNotFoundException {
    // fileContains(file, regex, null);
    // }
    public static Boolean fileContains(File file, String regex, String stopRegex) throws FileNotFoundException {
        final BufferedReader reader = new BufferedReader(new FileReader(file));
        Boolean found = false;

        try {
            for (String line = reader.readLine(); line != null; line = reader.readLine()) {
                if (Pattern.matches(regex, line)) {
                    found = true;
                    break;
                }
                if (stopRegex != null && Pattern.matches(stopRegex, line)) {
                    break;
                }
            }
        } catch (IOException e) {
            LOG.warn("unable to read " + file.getAbsolutePath(), e);
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
            }
        }

        return found;
    }

    public static File traversalFile(File base, String... nodes) {
        File curFile = base;
        for (String curNode : nodes) {
            if (curNode.equals("..")) {
                curFile = curFile.getParentFile();
            } else if (curNode.equals(".")) {
                // nothing to do
            } else {
                curFile = new File(curFile, curNode);
            }

        }
        return curFile;
    }

    public static boolean deleteFile(File file) {
        if (file.exists()) {
            if (file.isDirectory()) {
                if (file.list().length == 0) {
                    return file.delete();
                } else {
                    String files[] = file.list();
                    for (String subFile : files) {
                        boolean isDeleted = deleteFile(new File(file, subFile));
                        if (!isDeleted) {
                            return false;
                        }
                    }

                    if (file.list().length == 0) {
                        return file.delete();
                    }
                }
            } else {
                return file.delete();
            }
        }

        return false;
    }
}