Java tutorial
/* * 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); } } }