com.quattroresearch.helm.HlConfigEntry.java Source code

Java tutorial

Introduction

Here is the source code for com.quattroresearch.helm.HlConfigEntry.java

Source

/*******************************************************************************
 * Copyright C 2016, QUATTRO RESEARCH GMBH
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
 * Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 ******************************************************************************/
package com.quattroresearch.helm;

import java.io.*;
import java.util.regex.*;
import org.apache.commons.cli.*;
import org.helm.notation2.parser.*;
import org.helm.notation2.parser.notation.HELM2Notation;
import org.helm.notation2.parser.exceptionparser.ExceptionState;
import org.jdom2.JDOMException;

class HlConfigEntry {
    String category;
    String keyword;
    String value;
    String preHtmlSeq;
    String postHtmlSeq;

    HlConfigEntry() {
    }

    HlConfigEntry(String category, String keyword, String value) {
        this.category = category;
        this.keyword = keyword;
        this.value = value;
    }
}

public class HELMHighlighter {
    final static String DEFAULT_COLOR = "#000000"; // Black
    final static String DEFAULT_FONTSIZE = "12";

    static HlConfigEntry defaultFontsizeEntry;
    static HlConfigEntry defaultColorEntry;
    static HlConfigEntry defaultSectionSeparator;
    static HlConfigEntry[] hlConfigEntries = null;

    public static void main(String[] args) throws Exception {
        CommandLineParser cmdline_parser = new DefaultParser();
        Options options = new Options();
        String usage = "Usage: -i <input_file> -o <output_file> -c <highlight_config_file>";
        String errorLine;

        if (args.length < 6) {
            log(usage);
            return;
        }

        options.addOption("c", true, "config file containing highlighting options");
        options.addOption("i", true, "input file containing HELM string");
        options.addOption("o", true, "output file containing highlighted HELM string");

        try { // parse the command line arguments
            CommandLine cmd_line = cmdline_parser.parse(options, args);
            String cfilename = cmd_line.getOptionValue("c");
            log("Cfg filename=" + cfilename);
            String ofilename = cmd_line.getOptionValue("o");
            log("Output filename=" + ofilename);
            String ifilename = cmd_line.getOptionValue("i");
            log("Input filename=" + ifilename);
            if (cfilename == null || ofilename == null || ifilename == null || cfilename.equals("")
                    || ifilename.equals("") || ofilename.equals("")) {
                log(usage);
                return;
            }
            if (!(errorLine = setupHlConfigEntries(cfilename)).equals("")) { // in case of error, a non-empty string will be returned
                log("Bad entry in " + cfilename + ": '" + errorLine
                        + "': missing category, keyword or value, exiting..."); // error
                return;
            }
            handleInputOutputFiles(ifilename, ofilename);
        } catch (IOException e) {
            System.out.println(e);
        }
    }

    public static String setupHlConfigEntries(String cfilename) throws IOException {
        int lineCount = 0;
        int hlConfigEntriesIndex = 0;
        String currentLine = "";
        String[] splitResult;

        // Count the non-commentary config lines in order to determine the dimension of the hlConfigEntries[] array:
        BufferedReader br = new BufferedReader(new FileReader(cfilename));
        while ((currentLine = br.readLine()) != null) { // count non-commentary cfg lines
            if (currentLine.equals("") || currentLine.charAt(0) == '#' || currentLine.contains("NO_HIGHLIGHTING")
                    || currentLine.contains("DEFAULT")) {
                // log("IGNORED: " + currentLine);
                continue; // do not count lines that are empty, start with '#', contain "NO_HIGHLIGHTING" or "DEFAULT"
            }
            lineCount++;
        }
        br.close();

        // Create the special entries defaultFontsizeEntry, defaultColorEntry, defaultSectionSeparator with program-internal default values:
        defaultColorEntry = new HlConfigEntry("DEFAULT_COLOR", "COLOR", DEFAULT_COLOR);
        translateCfgToHtmlSeq(defaultColorEntry);
        defaultFontsizeEntry = new HlConfigEntry("DEFAULT_FONTSIZE", "FONTSIZE", DEFAULT_FONTSIZE);
        translateCfgToHtmlSeq(defaultFontsizeEntry);
        defaultSectionSeparator = new HlConfigEntry("DEFAULT_SECTION_SEPARATOR", "FONTSIZE", DEFAULT_FONTSIZE);
        // no default internal highlighting of '$': empty HTML sequences
        defaultSectionSeparator.preHtmlSeq = defaultSectionSeparator.postHtmlSeq = "";

        // Knowing the count of the effective cfg lines, create the "hlConfigEntries" array now. Note that the entries
        // DEFAULT_FONTSIZE, DEFAULT_COLOR, DEFAULT_SECTION_SEPARATOR have separate instances in the class "HelmHighlighter"
        // (namely defaultFontsizeEntry, defaultColorEntry, defaultSectionSeparator), therefore they will have no entries
        // in the hlConfigEntries[] array (they have already been omitted while previously computing "lineCount").
        hlConfigEntries = new HlConfigEntry[lineCount];
        for (int i = 0; i < hlConfigEntries.length; i++) {
            hlConfigEntries[i] = new HlConfigEntry();
        }

        // Read again the config file, ignoring all lines that are empty, start with '#' or contain "NO_HIGHLIGHTING":
        br = new BufferedReader(new FileReader(cfilename)); // re-initialize the readers to start again from the beginning
        while ((currentLine = br.readLine()) != null) {
            if (currentLine.equals("") || currentLine.charAt(0) == '#' || currentLine.contains("NO_HIGHLIGHTING")) {
                continue; // ignore lines that are empty, start with '#' or ' ', or contain "NO_HIGHLIGHTING"
            }
            splitResult = currentLine.split("[ \t]+"); // '+' to suppress subsequent delimiters    
            if (splitResult.length < 3) { // error: at least one element is missing from the triple "<category> <keyword> <value>":
                br.close();
                return (currentLine); // Return the bad config line entry
            }
            switch (splitResult[0]) {
            case "DEFAULT_FONTSIZE": // Fill defaultFontsizeEntry:
                defaultFontsizeEntry.category = splitResult[0];
                defaultFontsizeEntry.keyword = splitResult[1];
                defaultFontsizeEntry.value = splitResult[2];
                translateCfgToHtmlSeq(defaultFontsizeEntry);
                break;
            case "DEFAULT_COLOR": // Fill defaultColorEntry:
                defaultColorEntry.category = splitResult[0];
                defaultColorEntry.keyword = splitResult[1];
                defaultColorEntry.value = splitResult[2];
                translateCfgToHtmlSeq(defaultColorEntry);
                break;
            case "DEFAULT_SECTION_SEPARATOR": // Fill defaultSectionSeparator:
                defaultSectionSeparator.category = splitResult[0];
                defaultSectionSeparator.keyword = splitResult[1];
                defaultSectionSeparator.value = splitResult[2];
                if (!defaultSectionSeparator.keyword.equals("FONTSIZE")
                        || !defaultSectionSeparator.value.equals(DEFAULT_FONTSIZE)) {
                    // translate only if something has changed (i.e., the default is no longer valid):
                    translateCfgToHtmlSeq(defaultSectionSeparator);
                }
                break;
            default: // All other config entries:
                hlConfigEntries[hlConfigEntriesIndex].category = splitResult[0];
                hlConfigEntries[hlConfigEntriesIndex].keyword = splitResult[1];
                hlConfigEntries[hlConfigEntriesIndex].value = splitResult[2];
                translateCfgToHtmlSeq(hlConfigEntries[hlConfigEntriesIndex]);
                hlConfigEntriesIndex++;
                break;
            }
        }
        // log("SIZEOF hlConfigEntries: " + hlConfigEntries.length);
        br.close();
        return (""); // there was no bad config entry, return the empty string
    }

    public static void translateCfgToHtmlSeq(HlConfigEntry configEntry) {
        String fontstyle;
        String colorHtmlCode;
        switch (configEntry.keyword) {
        case "FONTSTYLE":
            fontstyle = configEntry.value.toLowerCase();
            configEntry.preHtmlSeq = "<" + fontstyle + ">";
            configEntry.postHtmlSeq = "</" + fontstyle + ">";
            break;
        case "FONTSIZE":
            configEntry.preHtmlSeq = "<font style=\"font-size: " + configEntry.value + "pt\">";
            configEntry.postHtmlSeq = "</font>";
            break;
        case "COLOR":
            switch (configEntry.value) { // translate text into HTML color code sequence:
            case "RED":
                colorHtmlCode = "#ff0000";
                break; // RED
            case "GRE":
                colorHtmlCode = "#00b050";
                break; // GREEN
            case "BLU":
                colorHtmlCode = "#00b0f0";
                break; // BLUE
            case "YEL":
                colorHtmlCode = "#ffc000";
                break; // YELLOW
            case "GRY":
                colorHtmlCode = "#808080";
                break; // GRAY
            case "BLK":
                colorHtmlCode = "#000000";
                break; // BLACK
            default:
                colorHtmlCode = configEntry.value;
                break; // HTML color code sequence   
            }
            configEntry.preHtmlSeq = "<font color=\"" + colorHtmlCode + "\">";
            configEntry.postHtmlSeq = "</font>";
            break;
        }
        // logNoEOL("Config entry: category=" + configEntry.category + ", keyword=" + configEntry.keyword + ", value=" + configEntry.value);
        // log(", preHtmlSeq=" + configEntry.preHtmlSeq + ", postHtmlSeq=" + configEntry.postHtmlSeq);
    }

    public static void handleInputOutputFiles(String ifilename, String ofilename)
            throws IOException, JDOMException {
        BufferedReader br = new BufferedReader(new FileReader(ifilename));
        PrintWriter pw = new PrintWriter(ofilename);
        String helmString;

        // initialize the output HTML file:
        pw.println("<html>\n<head>\n<meta charset=\"UTF-8\">\n<font style=\"font-size: "
                + defaultFontsizeEntry.value + "pt\">\n</head>\n<body>");

        while ((helmString = br.readLine()) != null) { // read and process all HELM2-Strings from the input file
            processHelmString(helmString, pw);
        }
        br.close();

        pw.println("</body>\n</html>"); // write out the closing HTML sequence
        pw.flush();
        pw.close();
    }

    public static void processHelmString(String helmString, PrintWriter pw) throws IOException, JDOMException {
        String outputString = "";
        String simplePolymerSect, connectionsSect, groupingSect, extAnnotSect;
        String sectionName;
        String sectionSeparator;
        int simplePolymersEndIndex, connectionsEndIndex, groupingEndIndex, extAnnotEndIndex;
        int hlConfigEntriesIndex = 0;
        Pattern pattern;
        Matcher matcher;

        // The next piece of code obtains the substrings of the individual sections from the input with the help of the ParserHELM2 class.
        // As a side-effect, one can perform a syntax check of the input HELM-string by concatenating the resulting substrings and
        // matching the result to the input HELM-string: if they are equal, the input string should be syntactically correct.

        // Begin code depending on Helm2Parser (note also JDOMException and the org.helm.notation2.parser-relevant imports)
        ParserHELM2 helm_parser = new ParserHELM2();
        try {
            helm_parser.parse(helmString);
        } catch (ExceptionState e) { // Auto-generated catch block
            e.printStackTrace();
        }
        HELM2Notation notation = helm_parser.getHELM2Notation();
        simplePolymerSect = notation.polymerToHELM2();
        connectionsSect = notation.connectionToHELM2();
        groupingSect = notation.groupingToHELM2();
        extAnnotSect = notation.annotationToHELM2();
        outputString = simplePolymerSect + "$" + connectionsSect + "$" + groupingSect + "$" + extAnnotSect + "$"
                + "V2.0";
        log("outputStrg=" + outputString);
        log("helmString=" + helmString);
        if (!outputString.equals(helmString)) {
            System.out.println(
                    "Helm string syntax check failed, input helmstring and toHELM2 outputString differ, quit working");
            return;
        }

        log("simplePolymerSect=" + simplePolymerSect);
        log("connectionsSect=" + connectionsSect);
        log("groupingSect=" + groupingSect);
        log("extAnnotSect=" + extAnnotSect);

        // process all entries of the "hlConfigEntries" array:
        for (hlConfigEntriesIndex = 0; hlConfigEntriesIndex < hlConfigEntries.length; hlConfigEntriesIndex++) {
            pattern = Pattern.compile("^[^_]+");
            matcher = pattern.matcher(hlConfigEntries[hlConfigEntriesIndex].category);
            matcher.find();
            switch (sectionName = matcher.group()) {
            case "POLYMER":
                simplePolymerSect = regexEngine(simplePolymerSect, hlConfigEntries[hlConfigEntriesIndex]);
                break;
            case "CONNECTION":
                connectionsSect = regexEngine(connectionsSect, hlConfigEntries[hlConfigEntriesIndex]);
                break;
            case "GROUPING":
                groupingSect = regexEngine(groupingSect, hlConfigEntries[hlConfigEntriesIndex]);
                break;
            case "EXTANNOT":
                extAnnotSect = regexEngine(extAnnotSect, hlConfigEntries[hlConfigEntriesIndex]);
                break;
            }
        }
        // Compose the output HELM2 string from the four sections, '$' characters and the version string.
        sectionSeparator = defaultSectionSeparator.preHtmlSeq + "$" + defaultSectionSeparator.postHtmlSeq;
        outputString = simplePolymerSect + sectionSeparator + connectionsSect + sectionSeparator + groupingSect
                + sectionSeparator + extAnnotSect + sectionSeparator + "V2.0";
        pw.println(outputString);
    }

    public static String regexEngine(String sectionString, HlConfigEntry configEntry) {
        String outString = "";
        String hlTarget;
        Pattern pattern;
        Matcher matcher;

        pattern = Pattern.compile("^.*SECTION_(.*)");
        matcher = pattern.matcher(configEntry.category);
        matcher.find();
        hlTarget = matcher.group(1);
        // log("HLTARGET=" + hlTarget + ", SectionString: '" + sectionString + "'" + "configEntry.category=" + configEntry.category);

        switch (hlTarget) {
        case "PEPTIDE_ID":
            pattern = Pattern.compile("(PEPTIDE[0-9]+)");
            break;
        case "RNA_ID":
            pattern = Pattern.compile("(RNA[0-9]+)");
            break;
        case "CHEM_ID":
            pattern = Pattern.compile("(CHEM[0-9]+)");
            break;
        case "BLOB_ID":
            pattern = Pattern.compile("(BLOB[0-9]+)");
            break;
        case "GROUP_ID":
            pattern = Pattern.compile("(G[0-9]+)");
            break;
        case "BRANCH_MONOMER_ID":
            pattern = Pattern.compile("(\\([A-Z]\\))");
            break;
        case "MULTICHAR_MONOMER_ID":
            pattern = Pattern.compile("(\\[[A-Za-z]+\\])");
            break;
        case "MONOMER_SEPARATOR_DOT":
            pattern = Pattern.compile("(\\.)");
            break;
        case "SEPARATOR_PIPE":
            pattern = Pattern.compile("(\\|)");
            break;
        }

        matcher = pattern.matcher(sectionString);
        outString = matcher.replaceAll(configEntry.preHtmlSeq + "$1" + configEntry.postHtmlSeq);
        // log("OUTSTRING=" + outString);
        return (outString);
    }

    private static void log(String msg) {
        System.out.println(msg);
    }

    private static void logNoEOL(String msg) {
        System.out.print(msg);
    }

}