io.github.carlomicieli.footballdb.starter.pages.TableBuilder.java Source code

Java tutorial

Introduction

Here is the source code for io.github.carlomicieli.footballdb.starter.pages.TableBuilder.java

Source

/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.github.carlomicieli.footballdb.starter.pages;

import org.apache.commons.lang3.tuple.Pair;
import org.jsoup.nodes.Element;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static io.github.carlomicieli.footballdb.starter.pages.Page.childrenWithTag;

/**
 * This class is used to build tables.
 *
 * @author Carlo Micieli
 */
public class TableBuilder {

    protected List<String> columnHeaders = new ArrayList<>();
    protected List<List<String>> values = new ArrayList<>();
    protected Pair<Integer, Integer> size;

    protected TableBuilder() {
        size = Pair.of(0, 0);
    }

    public Table toTable() {
        return new Table(this);
    }

    public TableBuilder headers(String... cells) {
        this.columnHeaders = merge(this.columnHeaders, Arrays.asList(cells));
        return this;
    }

    public TableBuilder headers(Stream<Cell> cells) {
        headers(cells.flatMap(Cell::values).toArray(String[]::new));
        return this;
    }

    public TableBuilder row(String... cells) {
        List<String> colValues = Arrays.asList(cells);
        checkTableSize(colValues);

        values.add(colValues);
        size = Pair.of(size.getLeft() + 1, colValues.size());
        return this;
    }

    public TableBuilder row(Stream<Cell> cells) {
        row(cells.flatMap(Cell::values).toArray(String[]::new));
        return this;
    }

    private static List<String> merge(List<String> first, List<String> second) {
        if (first == null || first.size() == 0)
            return second;
        return IntStream.range(0, first.size()).mapToObj(id -> first.get(id) + "." + second.get(id))
                .collect(Collectors.toList());
    }

    private void checkTableSize(List<String> colValues) {
        int numOfRows = size.getLeft();
        int numOfColumns = size.getRight();
        if (numOfRows != 0 && numOfColumns != colValues.size()) {
            throw new IllegalArgumentException("Invalid number of columns");
        }
    }

    public static Optional<Table> fromElement(Element tableElement) {
        return Optional.ofNullable(tableElement).filter(e -> e.tagName().equals("table")).map(e -> {
            TableBuilder tb = new TableBuilder();
            childrenWithTag(e, "tr").forEach(r -> addToTable(tb, r));
            return tb.toTable();
        });
    }

    private static void addToTable(TableBuilder tb, Element r) {
        Stream<Cell> values = childrenWithTag(r, "td").map(Cell::ofElement);
        if (isHeaderRow(r)) {
            tb.headers(values);
        } else {
            tb.row(values);
        }
    }

    private static boolean isHeaderRow(Element r) {
        return r.parent().tagName().equals("thead");
    }

    private static int colSpan(Element e) {
        String cs = e.attr("colspan");
        if (cs == null || cs.equals(""))
            return 1;
        return Integer.parseInt(cs);
    }

    static class Cell {
        private final int span;
        private final String text;

        private Cell(String text, int span) {
            this.span = span;
            this.text = text;
        }

        Stream<String> values() {
            return Collections.nCopies(span, text).stream();
        }

        static Cell ofElement(Element e) {
            return new Cell(e.text(), colSpan(e));
        }

        static Cell cell(String text) {
            return new Cell(text, 1);
        }

        static Cell multiple(String text, int span) {
            return new Cell(text, span);
        }

        static Stream<Cell> cells(Cell... cells) {
            return Stream.of(cells);
        }
    }
}