All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tmiyapub.parser.KeyValueLogParser Maven / Gradle / Ivy

package com.tmiyapub.parser;

import com.tmiyapub.parser.exception.IllegalCharacterException;

import java.util.HashMap;
import java.util.Map;

/**
 * a parser for log contains both key and value.
 */
public class KeyValueLogParser {
    private String source;
    private boolean doesWantComma = false;
    private boolean permitToOmitQuote = false;

    public KeyValueLogParser(String source) {
        this.source = source;
    }

    public KeyValueLogParser(String source, boolean doesWantComma) {
        this.source = source;
        this.doesWantComma = doesWantComma;
    }

    public KeyValueLogParser(String source, boolean doesWantComma, boolean permitToOmitQuote) {
        this.source = source;
        this.doesWantComma = doesWantComma;
        this.permitToOmitQuote = permitToOmitQuote;
    }

    public enum ParseMode {
        DEFAULT, WANT_EQ, WANT_QUOTE_OR_VALUE, WANT_VALUE, WANT_QUOTE, QUOTED, ESCAPED, WANT_COMMA, WANT_NEXT_NAME
    }

    /**
     * parse the source string and make a map
     *
     * @param index starting point on the string
     * @param map translated from source
     * @exception IllegalCharacterException to notify an illegal format
     */
    public void parse(int index, Map map) throws IllegalCharacterException {
        int i = index;
        ParseMode mode = ParseMode.DEFAULT;
        StringBuffer buffer = new StringBuffer();
        String name = null;
        Character quote = null;
        while (i < source.length()) {
            char c = source.charAt(i);
            switch (mode) {
                case DEFAULT:
                    if (c == ' ' || c == '\t') {
                        name = buffer.toString();
                        buffer = new StringBuffer();
                        mode = ParseMode.WANT_EQ;
                    } else if (c == '=') {
                        name = buffer.toString();
                        buffer = new StringBuffer();
                        if (permitToOmitQuote) {
                            mode = ParseMode.WANT_QUOTE_OR_VALUE;
                        } else {
                            mode = ParseMode.WANT_QUOTE;
                        }
                    } else if (c == '\"' || c == '\'') {
                        throw new IllegalCharacterException(i, c, mode, "unexpected quote character in key name.");
                    } else {
                        buffer.append(c);
                    }
                    break;
                case WANT_EQ:
                    if (c == '=') {
                        if (permitToOmitQuote) {
                            mode = ParseMode.WANT_QUOTE_OR_VALUE;
                        } else {
                            mode = ParseMode.WANT_QUOTE;
                        }
                    } else if (c == ' ' || c == '\t') {
                        // do nothing
                    } else {
                        throw new IllegalCharacterException(i, c, mode, "unexpected quote character after key name.");
                    }
                    break;
                case WANT_QUOTE_OR_VALUE:
                    if (c == '\'' || c == '\"') {
                        quote = c;
                        mode = ParseMode.QUOTED;
                    } else if (c == ' ' || c == '\t') {
                        // do nothing
                    } else {
                        buffer.append(c);
                        mode = ParseMode.WANT_VALUE;
                    }
                    break;
                case WANT_VALUE:
                    if (c == ' ' || c == '\t') {
                        if (name == null) {
                            throw new UnknownError("impossible");
                        }
                        map.put(name, buffer.toString());
                        if (doesWantComma) {
                            mode = ParseMode.WANT_COMMA;
                        } else {
                            mode = ParseMode.WANT_NEXT_NAME;
                        }
                        buffer = new StringBuffer();
                    } else {
                        buffer.append(c);
                    }
                    break;
                case WANT_QUOTE:
                    if (c == '\'' || c == '\"') {
                        quote = c;
                        mode = ParseMode.QUOTED;
                    } else if (c == ' ' || c == '\t') {
                        // do nothing
                    } else {
                        throw new IllegalCharacterException(i, c, mode, "unexpected quote character after equal.");
                    }
                    break;
                case QUOTED:
                    if (quote == null) {
                        throw new UnknownError("impossible");
                    } else if (quote.equals(c)) {
                        if (name == null) {
                            throw new UnknownError("impossible");
                        }
                        map.put(name, buffer.toString());
                        if (doesWantComma) {
                            mode = ParseMode.WANT_COMMA;
                        } else {
                            mode = ParseMode.WANT_NEXT_NAME;
                        }
                        buffer = new StringBuffer();
                    } else if (c == '\\') {
                        mode = ParseMode.ESCAPED;
                    } else {
                        buffer.append(c);
                    }
                    break;
                case ESCAPED:
                    if (c == 't') {
                        buffer.append('\t');
                    } else if (c == 'b') {
                        buffer.append('\b');
                    } else if (c == 'n') {
                        buffer.append('\n');
                    } else if (c == 'r') {
                        buffer.append('\r');
                    } else if (c == 'f') {
                        buffer.append('\f');
                    } else if (c == '\'') {
                        buffer.append('\'');
                    } else if (c == '\"') {
                        buffer.append('\"');
                    } else if (c == '\'') {
                        buffer.append('\'');
                    } else if (c == 'x') {
                        String xx = source.substring(i + 1, i + 3);
                        buffer.append((char)Integer.parseInt(xx, 16));
                        i += 2;
                    } else {
                        throw new IllegalCharacterException(i, c, mode, "unknown escape sequence.");
                    }
                    mode = ParseMode.QUOTED;
                    break;
                case WANT_COMMA:
                    if (c == ' ' || c == '\t') {
                        // do nothing
                    } else if (c == ',') {
                        mode = ParseMode.WANT_NEXT_NAME;
                    } else {
                        throw new IllegalCharacterException(i, c, mode, "only comma wanted.");
                    }
                    break;
                case WANT_NEXT_NAME:
                    if (c == ' ' || c == '\t') {
                        // do nothing
                    } else {
                        mode = ParseMode.DEFAULT;
                        i--; // redo this character in DEFAULT mode.
                    }
                    break;
                default:
                    throw new UnknownError("impossible");
            }
            i++;
        }
        if (mode != ParseMode.WANT_NEXT_NAME && mode != ParseMode.WANT_COMMA) {
            throw new IllegalCharacterException(i, null, mode, "Unexpected end of source.");
        }
    }


    /**
     * parse the source string and make a map
     *
     * @return map translated from source
     * @exception IllegalCharacterException to notify an illegal format
     */
    public Map parse() throws IllegalCharacterException {
        Map map = new HashMap<>();
        this.parse(0, map);
        return map;
    }

}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy