de.aeb.sqlscriptformater.SqlScriptFormater.java Source code

Java tutorial

Introduction

Here is the source code for de.aeb.sqlscriptformater.SqlScriptFormater.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package de.aeb.sqlscriptformater;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;

/**
 * (!) depends on correct sql syntax in file
 *
 * @author Eugen
 *
 */
public class SqlScriptFormater {

    private static final Logger log = Logger.getLogger(SqlScriptFormater.class.getName());

    private static final String USAGE = getUsageString();

    private static final String HEADER = getHeaderString();

    private static final String PREFIX = "generated_";

    private static String getUsageString() {
        return "-------------------------------------------------------------------------------\n"
                + "Usage: java -jar sqlsf.jar OPERATION OPSTRING FILE/PATH [OPTIONALS]\n"
                + "\t\tOPERATION:\t-r/-remove | -a/-add | -e/-exists\n" + "\t\tOPSTRING:\tex. \"_lut\"\n"
                + "\t\tFILE/PATH:\tex.\"create.sql\" or \"C:\\scripts\\create.sql\"\n"
                + "\t\t[OPTIONALS]:\t-h (add HEADER) | -f (replace Generated Files)\n"
                + "-------------------------------------------------------------------------------\n";
    }

    private static String getHeaderString() {
        return "--##############################################\n"
                + "--### File is generated by SQLScriptFormater ###\n"
                + "--##############################################\n \n";
    }

    // OP-Parmeters --- START
    private File _opFile;
    private OperationsEnum _op;
    private String _opStr;

    public File getOpFile() {
        return _opFile;
    }

    public void setOpFile(File _opFile) {
        this._opFile = _opFile;
        checkParameters();
    }

    public OperationsEnum getOp() {
        return _op;
    }

    public void setOp(OperationsEnum _op) {
        this._op = _op;
        checkParameters();
    }

    public String getOpStr() {
        return _opStr;
    }

    public void setOpStr(String _opStr) {
        this._opStr = _opStr;
        checkParameters();
    }

    // OP-Parmeters --- END
    //
    // Internals -- START
    private final ArrayList<String> _errors = new ArrayList<>();
    private boolean _success = false;
    private boolean _parametersSet = false;
    private boolean _buildWithHeader = false;
    private boolean _replace = false;

    private boolean isParametersSet() {
        return _parametersSet;
    }

    public boolean isSuccess() {
        return _success;
    }

    public ArrayList<String> getErrors() {
        return _errors;
    }

    /**
     * Set before run() to skip Header in file.
     */
    public void buildWithoutHeader() {
        _buildWithHeader = false;
    }

    /**
     * Set to replace generated Files.
     */
    public void replaceFiles() {
        _replace = true;
    }

    // Internals -- END
    //------------------------
    // Constructors
    //------------------------
    /**
     * Default Constructor; use set-Methods to set parameters
     */
    public SqlScriptFormater() {
    }

    /**
     * Constructor for parametric use.
     *
     * @param args String array containing the parameters in the right order.
     * @param verbose turns logging on or off.
     */
    public SqlScriptFormater(String[] args, boolean verbose) {
        // for debugging
        if (verbose) {
            log.setLevel(Level.ALL);
        } else {
            log.setLevel(Level.OFF);
        }
        _parametersSet = extractArgs(args);
    }

    //------------------------
    // Methods
    //------------------------
    public static void printUsage() {
        System.out.println(USAGE);
    }

    public void printErrors() {
        if (_errors.size() > 0) {
            for (String _error : _errors) {
                System.out.println(_error);
            }
        } else {
            System.out.println("No Errors to print out!");
        }
    }

    public void printStatus() {
        if (_success) {
            System.out.println("Last Operation: success");
        } else {
            System.out.println("Last Operation: unsuccessful");
        }
    }

    @Deprecated
    public boolean old_printFile() {
        boolean bOk = true;
        try {
            BufferedReader in = new BufferedReader(new FileReader(_opFile));
            String line = null;
            int i = 1;
            System.out.println("Selected File " + _opFile.getName() + ":");
            while ((line = in.readLine()) != null) {
                String formatedStr = "Line " + (i++) + ": " + line;
                System.out.println(formatedStr);
            }
        } catch (FileNotFoundException ex) {
            _errors.add("File not found: " + ex.getMessage());
            return false;
        } catch (IOException ex) {
            _errors.add("IOExeption: " + ex.getMessage());
            return false;
        }
        return bOk;
    }

    public boolean printFile() {
        boolean bOk = true;

        // load lines from file
        List<String> lines = readLinesFromFile(_opFile, "UTF-8");

        if (lines != null) {
            int start = 0;
            int end = lines.size() - 1;
            //loop through the lines
            for (int index = start; index <= end; index++) {
                // actual line
                String line = lines.get(index);
                // Printout formated
                int lineNumber = index + 1;
                System.out.println("Line " + lineNumber + " :" + line);
            }
        } else {
            //lines == null
            bOk = false;
        }
        return bOk;
    }

    private void checkParameters() {
        _parametersSet = (_opFile != null && _op != null && _opStr != null);
    }

    // Methods for Parameter Extraction --- START
    /**
     * Extracts the Arguments from String[] and sets the parameters accordingly.
     *
     * @param args String[]. Valid are 3,4 or 5 Arguments.
     * @return Returns true if extraction was succsessful, else false.
     */
    public boolean extractArgs(String[] args) {
        boolean bOk = true;

        // Check args length min 3 required
        if (args.length == 3) {

            bOk = extract3Args(args);

        } else if (args.length == 4) {

            bOk = extract4Args(args);

        } else if (args.length == 5) {

            bOk = extract5Args(args);

        } else {
            _errors.add("Arguments are not Vaild!");
            bOk = false;
        }
        return bOk;
    }

    private OperationsEnum checkAndGetOpArg(String arg) {
        String op = arg.trim();
        log.info("op String after trim:" + op);
        OperationsEnum rOp = OperationsEnum.UNSUPPORTED;

        if (op != "" && op != " ") {
            if (op.startsWith("-")) {
                op = op.substring(1);
                log.info("op shorted String:" + op);
                String firstLetter = "";
                if (op.length() > 1) {
                    firstLetter = op.substring(0, 1);
                    log.info("op String first Letter:" + firstLetter);
                } else {
                    firstLetter = op;
                }

                switch (firstLetter) {
                // op = remove
                case "r": {
                    if (op.contains("remove") || op.startsWith("r")) {
                        rOp = OperationsEnum.REMOVE;
                    }
                    break;
                }
                // op = add
                case "a": {
                    if (op.contains("add") || op.startsWith("a")) {
                        rOp = OperationsEnum.ADD;
                    }
                    break;
                }
                // op = exits
                case "e": {
                    if (op.contains("exists") || op.startsWith("e")) {
                        rOp = OperationsEnum.EXISTS;
                    }
                    break;
                }
                // nothing from above = false
                default:
                    rOp = OperationsEnum.UNSUPPORTED;
                }
            } else {
                // not an operation argument
                _errors.add("First Argument is not an Operation, \"-\" missing.");
            }

        } else {
            // not a valid argument
            _errors.add("First Argument is empty.");
        }
        return rOp;
    }

    private boolean extract3Args(String[] args) {
        boolean bOk = true;
        // null checks
        if (args[0] != null && args[1] != null && args[2] != null) {

            // Check first argument
            OperationsEnum op = checkAndGetOpArg(args[0]);
            if (op == OperationsEnum.UNSUPPORTED) {
                //Return if OperationsEnum is Unsupported, no need to check the other arguments
                _errors.add("Unsupported Operation in first argument!");
                return bOk = false;
            } else {
                _op = op;
            }
            log.info("first arg extracted. bOk=" + bOk);

            // Check second arg
            if (checkOpStrArg(args[1])) {
                _opStr = args[1];
            } else {
                //Return if check failed, no need to check the other arguments
                _errors.add("Checks failed in second argument!");
                return bOk = false;
            }
            log.info("second arg extracted. bOk=" + bOk);

            // Check third arg
            File file = checkAndGetFileArg(args[2]);
            if (file != null) {
                _opFile = file;
            } else {
                _errors.add("Checks failed in third argument!");
                bOk = false;
            }
            log.info("third arg extracted. bOk=" + bOk);

        } else {
            _errors.add("Some Arguments are not Valid or null!");
            bOk = false;
        }

        return bOk;
    }

    private boolean extract4Args(String[] args) {
        boolean bOk = true;
        if (args.length == 4) {
            if (args[3] != null) {

                String[] args3 = { args[0], args[1], args[2] };
                bOk = extract3Args(args3);
                String firstOptionalArg = args[3];
                setOptionalArg(firstOptionalArg);

            } else {
                bOk = false;
            }
        } else {
            bOk = false;
        }

        return bOk;
    }

    private boolean extract5Args(String[] args) {
        boolean bOk = true;
        if (args.length == 5) {
            if (args[4] != null) {

                String[] args4 = { args[0], args[1], args[2], args[3] };
                bOk = extract4Args(args4);
                String secondOptionalArg = args[4];
                setOptionalArg(secondOptionalArg);

            } else {
                bOk = false;
            }
        } else {
            bOk = false;
        }

        return bOk;
    }

    private boolean checkOpStrArg(String arg) {
        // Checks for second argument
        boolean bOk = true;
        String tArg = arg.trim();
        // empty or blank
        if (tArg == "" || tArg == " ") {
            _errors.add("Second Argument is empty or has blanks");
            bOk = false;
        }
        return bOk;
    }

    private File checkAndGetFileArg(String arg) {
        File sqlFile = new File(arg);
        try {
            if (sqlFile.isFile()) {
                if (sqlFile.exists()) {
                    if (sqlFile.canRead()) {
                        return sqlFile;
                    }
                }
            }
        } catch (Exception e) {
            _errors.add("File Error: " + e.getMessage());
            return null;
        }

        return null;
    }

    private void setOptionalArg(String OptionalArg) {
        if (OptionalArg.contains("-h") || OptionalArg.contains("-header")) {
            // set buildWtihHeader
            _buildWithHeader = true;
        } else if (OptionalArg.contains("-f") || OptionalArg.contains("-file")) {
            // set replace Generated Files
            _replace = true;
        }
    }

    // Methods for Parameter Extraction --- END
    @Deprecated
    private boolean old_runRemove() {
        boolean bOk = true;
        try {
            BufferedReader in = new BufferedReader(new FileReader(_opFile));
            String line = null;
            String outStr = "";
            if (_buildWithHeader) {
                outStr = HEADER + "";
            }
            int i = 1;
            while ((line = in.readLine()) != null) {
                String formatedStr = "Line " + (i++) + ": " + line;
                log.info(formatedStr);
                // remove line
                if (line.contains(_opStr)) {
                    // Skip that line

                } else {
                    // append to Output String and add newline feed
                    outStr += line + "\n";
                }
            }
            log.info(outStr);

            // save generated outStr to new File
            bOk = saveToNewFile(outStr);

            if (!bOk) {
                _errors.add("Failed to Save to File.");
            }

        } catch (FileNotFoundException ex) {
            _errors.add("File Not Found!" + ex.getMessage());
            return false;
        } catch (IOException ex) {
            _errors.add("IOExceptin: " + ex.getMessage());
            return false;
        }
        return bOk;
    }

    /**
     * Runs the Remove Operation. With some Case checks.
     *
     * @return true if succssesful, false if not
     */
    private boolean runRemove() {
        boolean bOk = true;

        // load lines from file
        List<String> lines = readLinesFromFile(_opFile, "UTF-8");

        // Format lines
        if (lines != null) {

            // apply Case Checks
            runRemoveCaseChecks(lines);

            // add header
            if (_buildWithHeader) {
                lines.addAll(0, Arrays.asList(HEADER.split("\n")));
            }

            // save lines to file
            bOk = saveToNewFile(lines);

            if (!bOk) {
                _errors.add("Failed to Save to File.");
            }

        } else {
            //lines == null
            bOk = false;
        }

        return bOk;
    }

    private boolean runAdd() {
        _errors.add("Add Operation not implemented");
        return false;
    }

    private boolean runExists() {
        _errors.add("Exists Operation not implemented");
        return false;
    }

    /**
     * Run an Operation on a file. For non parametic use.
     *
     * @param opFile File object (*.sql)
     * @param op Operation to run.
     * @param opStr String needed for that Operation.
     * @return true if succssesful, false if not
     */
    public boolean runOnFile(File opFile, OperationsEnum op, String opStr) {
        boolean bOk = true;
        if (opFile != null && op != null && opStr != null) {
            _opFile = opFile;
            _opStr = opStr;

            switch (op) {
            case ADD:
                bOk = runAdd();
                break;
            case REMOVE:
                bOk = runRemove();
                break;
            case EXISTS:
                bOk = runExists();
                break;
            case UNSUPPORTED:
                _errors.add("Unsupported Operation detected. Can not run!");
                bOk = false;
                break;
            default:
                bOk = false;
            }

        } else {
            _errors.add("Parameters invalid, some are probably null!");
            bOk = false;
        }

        // set succsess if operation was succsessful (bOk is true)
        if (bOk) {
            _success = true;
        }
        return bOk;
    }

    /**
     * Runs the Operation set in the parameters.
     *
     * @return true if succssesful, false if not
     */
    public boolean run() {
        if (isParametersSet()) {
            return runOnFile(_opFile, _op, _opStr);
        } else {
            _errors.add("No Parameters set!");
            return false;
        }
    }

    private boolean saveToNewFile(String outStr) {
        boolean bOk = true;
        // new prefixed File
        File newFile = new File(buildPrefixedFilepath());
        try {
            if (_replace) {
                if (newFile.exists()) {
                    newFile.delete();
                }
            }
            if (newFile.createNewFile()) {
                if (newFile.isFile()) {
                    bOk = writeStringToFile(newFile, outStr);
                } else {
                    bOk = false;
                }
            } else {
                _errors.add("A generated file already exists! Delete that and run again.");
                bOk = false;
            }
        } catch (IOException ex) {
            _errors.add("Failed to create new File: " + ex.getMessage());
            return false;
        }
        return bOk;
    }

    private boolean saveToNewFile(List<String> lines) {
        boolean bOk = true;
        // new prefixed File
        File newFile = new File(buildPrefixedFilepath());
        try {
            if (_replace) {
                if (newFile.exists()) {
                    newFile.delete();
                }
            }
            if (newFile.createNewFile()) {
                if (newFile.isFile()) {
                    bOk = writeListToFile(newFile, lines);
                } else {
                    bOk = false;
                }
            } else {
                _errors.add("A generated file already exists! Delete that and run again.");
                bOk = false;
            }
        } catch (IOException ex) {
            _errors.add("Failed to create new File: " + ex.getMessage());
            return false;
        }
        return bOk;
    }

    private String buildPrefixedFilepath() {
        String filepath = _opFile.getAbsolutePath();
        String oldname = _opFile.getName();
        //add prefix
        String newname = PREFIX + _opFile.getName();
        return filepath.replace(oldname, newname);

    }

    private List<String> readLinesFromFile(File file, String charset) {
        if (file != null) {
            List<String> lines = null;
            if (charset == null) {
                charset = "UTF-8";
            }
            try {
                lines = FileUtils.readLines(file, charset);
            } catch (IOException ex) {
                _errors.add("IOExceptin: " + ex.getMessage());
                return null;
            }
            return lines;
        } else {
            return null;
        }
    }

    private boolean writeStringToFile(File newFile, String outStr) {
        boolean bOk = true;
        if (newFile != null) {
            try {
                FileUtils.writeStringToFile(newFile, outStr, "UTF-8");
            } catch (IOException ex) {
                _errors.add("Failed to write to File: " + ex.getMessage());
                return false;
            }
        } else {
            bOk = false;
        }
        return bOk;
    }

    private boolean writeListToFile(File newFile, List<String> lines) {
        boolean bOk = true;
        if (newFile != null) {
            try {
                FileUtils.writeLines(newFile, lines);
            } catch (IOException ex) {
                _errors.add("Failed to write to File: " + ex.getMessage());
                return false;
            }
        } else {
            bOk = false;
        }
        return bOk;
    }

    private void runRemoveCaseChecks(List<String> lines) {
        int start = 0;
        int end = lines.size() - 1;

        // Contains check for lower and upper Cases
        String opUpper = _opStr.toUpperCase();
        String opLower = _opStr.toLowerCase();

        //loop through the lines
        for (int index = start; index <= end; index++) {
            // actual line
            String line = lines.get(index);
            if (!line.isEmpty()) {
                if (line.contains(opUpper) || line.contains(opLower)) {
                    // line contains opStr and needs formating
                    // one liner? 
                    if (index > start) {
                        // not in first line? -> check comma 
                        String previousLine = lines.get(index - 1);
                        if (previousLine.contains(",")) {
                            if (previousLine.endsWith(",")) {
                                // index = last line? 
                                if (index == end) {
                                    // last line
                                    // case: .....,
                                    //       ...opStr... );
                                    // remove everything before LAST ")", line can contain multiple ")"
                                    int lastCloser = line.lastIndexOf(")");
                                    if (lastCloser < line.length()) {
                                        String newLine = line.substring(lastCloser, line.length());
                                        lines.set(index, newLine);
                                    }
                                    // remove , from previous line
                                    String newLine = previousLine.substring(0, previousLine.length() - 1);
                                    lines.set(index - 1, newLine);

                                } else if (index == end - 1) {
                                    // on second last line
                                    // case: .......,
                                    //       ...opStr..,
                                    //       );
                                    // remove , from previous line
                                    String newLine = previousLine.substring(0, previousLine.length() - 1);
                                    lines.set(index - 1, newLine);
                                    // now save to remove index line
                                    lines.remove(index);
                                    end = lines.size() - 1;
                                } else {
                                    // index != lastLine && != secondlastLine
                                    // case: .....,
                                    //       ...opStr..,
                                    //       ......
                                    // save to remove index line
                                    lines.remove(index);
                                    end = lines.size() - 1;
                                }

                            } else {
                                // previousLine does not end with ,
                                //  Case: ... , ...
                                //        ...opStr...
                                // -> syntax error?
                                // TODO add code 
                            }

                        } else if (previousLine.endsWith("(")) {
                            // previousLine has no comma, ends with (
                            // case : ... (
                            //        ...opStr..
                            // save to remove index line
                            lines.remove(index);
                            end = lines.size() - 1;
                        } else if (line.startsWith("(")) {
                            // Case :  .....
                            //        ( ...opStr ...
                            // remove "...opStr..." but leave "("
                            lines.set(index, line.substring(0, 1));
                        } else if (line.contains("(")) {
                            // Case : "... (  ...opStr ..." on same line
                            int firstOpener = line.indexOf("(");
                            if (firstOpener < line.length()) {
                                //remove everything behind "("
                                String newLine = line.substring(0, firstOpener + 1);
                                lines.set(index, newLine);
                            }
                        } else {

                        }

                    } else if (line.contains("(")) {
                        // first line (index = 0) -> one liner or opStr in first line
                        //-----------------------------------------------------------
                        if (line.startsWith("(")) {
                            // Case : "( ...opStr ..."
                            // remove "...opStr..." but leave "("
                            lines.set(index, line.substring(0, 1));
                        } else {
                            // Case : "... (  ...opStr ..." on same line
                            int firstOpener = line.indexOf("(");
                            if (firstOpener < line.length()) {
                                //remove everything behind "("
                                String newLine = line.substring(0, firstOpener + 1);
                                lines.set(index, newLine);
                            }
                        }
                    } else {
                        // one liner that contains ...opStr... and no opener
                        // this case cant be -> syntax error
                        // add empty line, just in case
                        lines.set(index, " ");
                    }
                } else {
                    // line does not contain opStr
                    // do nothing
                }
            } else {
                // line is empty
                // remove empty lines
                // lines.remove(index);
                // end = lines.size() - 1;
            }
        }
    }

}