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

com.x5.template.InlineTable Maven / Gradle / Ivy

There is a newer version: 3.6.2
Show newest version
package com.x5.template;

import java.util.Map;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.x5.util.TableData;

public class InlineTable
{
    // comma or close-bracket
    private static final Pattern DELIM = Pattern.compile("[,\\]]");

    /**
     * for testing...
     */
    public static void main(String[] args)
    {
        String test = "[[code,name,price],[abc,Apples,$2.50],[xyz,Whiz-Bang \\[you\\, and everyone\\, will love it!\\],$13.99]]";
        System.out.println("Reading in table...");
        TableData table = InlineTable.parseTable(test);
        System.out.println("...finished.  Checking data structures:");

        String[] labels = table.getColumnLabels();

        Map record;

        while (table.hasNext()) {
            record = table.nextRecord();
            for (int i=0; i0) System.out.print(", ");
                String label = labels[i];
                System.out.print(label + "=" + record.get(label));
            }
            System.out.println();
        }
    }

    public static TableData parseTable(String data)
    {
        return _parseTable(data);
    }

    /*
     * example [[code,name,price],[abc,Apples,$2.50],[xyz,Whiz-Bang \[you\, and everyone\, will love it!\],$13.99]]
     */
    private static SimpleTable _parseTable(String data)
    {
        // first elt of array is labels
        // remainder is record data
        ArrayList row = new ArrayList();
        int marker = 0;
        int dataLen = data.length();
        // scan for bracket marking start of data
        marker = data.indexOf("[");

        if (marker < 0) {
            //System.err.println("could not locate start of data");
            return null;
        }

        String[] labels = null;
        ArrayList records = null;

        // parse a row
        while (marker > -1 && marker < dataLen) {
            // scan for bracket marking start of row
            marker = data.indexOf("[",marker+1);
            if (marker < 0) {
                //System.err.println("no more rows");
                break;
            }

            // parse a single field
            while (marker > 0 && marker < dataLen && data.charAt(marker) != ']') {
                marker++;
                // scan for unescaped comma OR unescaped close-bracket
                int delimPos = nextUnescapedDelim(DELIM, data, marker);
                if (delimPos > 0) {
                    String field = data.substring(marker,delimPos);
                    // apply escapes
                    field = field.replace("\\[","[");
                    field = field.replace("\\]","]");
                    field = field.replace("\\,",",");
                    row.add(field);
                    //System.err.println("parsed one field");
                } else {
                    //System.err.println("missing field/row delimiter!");
                }
                marker = delimPos;
            }

            if (row.size() > 0) {
                // record row
                String[] parsedRow = new String[row.size()];
                parsedRow = row.toArray(parsedRow);
                if (labels == null) {
                    labels = parsedRow;
                } else {
                    if (records == null) records = new ArrayList();
                    records.add(parsedRow);
                }
                row.clear();
            }
            // scan to start of next row
            if (marker > 0) marker = data.indexOf(",",marker+1);
        }

        return labels == null ? null : new SimpleTable(labels, records);
    }

    private static int nextUnescapedDelim(Pattern delim, String input, int searchFrom)
    {
        Matcher m = delim.matcher(input);
        boolean hasDelim = m.find(searchFrom);

        if (!hasDelim) return -1;
        int delimPos = m.start();

        boolean isProvenDelimeter = false;
        while (!isProvenDelimeter) {
            // count number of backslashes that precede this forward slash
            int bsCount = 0;
            while (delimPos-(1+bsCount) >= searchFrom && input.charAt(delimPos - (1+bsCount)) == '\\') {
                bsCount++;
            }
            // if odd number of backslashes precede this delimiter char, it's escaped
            // if even number precede, it's not escaped, it's the true delimiter
            // (because it's preceded by either no backslash or an escaped backslash)
            if (bsCount % 2 == 0) {
                isProvenDelimeter = true;
            } else {
                // keep looking for real delimiter
                if (m.find()) {
                    delimPos = m.start();
                } else {
                    // if the input is not legal (missing delimiters??), bail out
                    return -1;
                }
            }
        }
        return delimPos;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy