RowReport.java

/*
 * CSVeed (https://github.com/42BV/CSVeed)
 *
 * Copyright 2013-2023 CSVeed.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of The Apache Software License,
 * Version 2.0 which accompanies this distribution, and is available at
 * https://www.apache.org/licenses/LICENSE-2.0.txt
 */
package org.csveed.report;

import java.util.ArrayList;
import java.util.List;

/**
 * The Class RowReport.
 */
public class RowReport {

    /** The row. */
    private String row;

    /** The start. */
    private int start;

    /** The end. */
    private int end;

    /**
     * Instantiates a new row report.
     *
     * @param row
     *            the row
     * @param start
     *            the start
     * @param end
     *            the end
     */
    public RowReport(String row, int start, int end) {
        this.row = row;
        this.start = start;
        this.end = start == end && start < row.length() ? start + 1 : end;
    }

    /**
     * Gets the row.
     *
     * @return the row
     */
    public String getRow() {
        return row;
    }

    /**
     * Gets the start.
     *
     * @return the start
     */
    public int getStart() {
        return start;
    }

    /**
     * Gets the end.
     *
     * @return the end
     */
    public int getEnd() {
        return end;
    }

    /**
     * Tokenize.
     *
     * @return the list
     */
    public List<RowPart> tokenize() {
        List<RowPart> lines = new ArrayList<>();
        if (start > 0) {
            lines.add(new RowPart(row.substring(0, start), false));
        }
        if (end - start > 0) {
            lines.add(new RowPart(row.substring(start, end), true));
        }
        if (end < row.length()) {
            lines.add(new RowPart(row.substring(end), false));
        }
        return lines;
    }

    /**
     * Gets the printable lines.
     *
     * @return the printable lines
     */
    public List<String> getPrintableLines() {
        List<String> lines = new ArrayList<>();

        List<RowPart> parts = tokenize();

        lines.add(createContentLine(parts));
        lines.add(createFocusLine(parts));

        return lines;
    }

    /**
     * Creates the content line.
     *
     * @param parts
     *            the parts
     *
     * @return the string
     */
    private String createContentLine(List<RowPart> parts) {
        StringBuilder line = new StringBuilder();
        for (RowPart token : parts) {
            line.append(token.getToken());
        }
        return line.toString();
    }

    /**
     * Creates the focus line.
     *
     * @param parts
     *            the parts
     *
     * @return the string
     */
    private String createFocusLine(List<RowPart> parts) {
        StringBuilder line = new StringBuilder();
        boolean placedMarkers = false;
        for (RowPart token : parts) {
            if (token.isHighlight()) {
                line.append(printUnderscoredPart(token));
                placedMarkers = true;
            } else {
                line.append(printEmptyPart(token));
            }
        }
        if (!placedMarkers) { // Essentially only at the end-of-line
            line.append('^');
        }
        return line.toString();
    }

    /**
     * Prints the empty part.
     *
     * @param token
     *            the token
     *
     * @return the string
     */
    private String printEmptyPart(RowPart token) {
        StringBuilder linePart = new StringBuilder();
        for (int i = 0; i < token.getToken().length(); i++) {
            linePart.append(' ');
        }
        return linePart.toString();
    }

    /**
     * Prints the underscored part.
     *
     * @param token
     *            the token
     *
     * @return the string
     */
    private String printUnderscoredPart(RowPart token) {
        StringBuilder linePart = new StringBuilder();
        for (int i = 0; i < token.getToken().length(); i++) {
            if (i == 0 || i == token.getToken().length() - 1) {
                linePart.append('^');
            } else {
                linePart.append('-');
            }
        }
        return linePart.toString();
    }

}