io.github.carlomicieli.footballdb.starter.parsers.SeasonGamesParser.java Source code

Java tutorial

Introduction

Here is the source code for io.github.carlomicieli.footballdb.starter.parsers.SeasonGamesParser.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.parsers;

import io.github.carlomicieli.footballdb.starter.documents.DocumentDownloader;
import io.github.carlomicieli.footballdb.starter.documents.PathBuilder;
import io.github.carlomicieli.footballdb.starter.domain.games.Game;
import io.github.carlomicieli.footballdb.starter.domain.games.Season;
import io.github.carlomicieli.footballdb.starter.domain.games.TeamScore;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author Carlo Micieli
 */
@Component
public class SeasonGamesParser extends Parser<Season> {

    @Autowired
    public SeasonGamesParser(DocumentDownloader docs) {
        super(docs);
    }

    @Override
    protected PathBuilder pathBuilder() {
        return PathBuilder.proFootballReference();
    }

    @Override
    protected Season parseDocument(Document doc) {
        Stream<Element> rows = gamesTable(doc).flatMap(this::extractTableBody).map(e -> extractRows(e))
                .orElseThrow(() -> new NoSuchElementException("Games table not found"));

        String year = extractYear(doc);
        List<Game> games = rows.map(r -> mapToGame(year, r)).collect(Collectors.toList());
        return new Season(games);
    }

    private Optional<Element> gamesTable(Document doc) {
        return Optional.ofNullable(doc.getElementById("games"));
    }

    private Optional<Element> extractTableBody(Element table) {
        return table.children().stream().filter(e -> e.tagName().equals("tbody")).findFirst();
    }

    private Stream<Element> extractRows(Element tbody) {
        Predicate<Element> withoutCssClass = e -> e.className().equals("");
        Predicate<Element> gameRow = e -> !e.child(2).text().equals("Playoffs");

        return tbody.children().stream().filter(withoutCssClass).filter(gameRow);
    }

    private Game mapToGame(String year, Element e) {
        String at = e.child(5).text();
        Supplier<TeamScore> fst = () -> Game.newTeam(e.child(4).text(), e.child(7).text());
        Supplier<TeamScore> snd = () -> Game.newTeam(e.child(6).text(), e.child(8).text());

        return Game.builder().type(e.child(0).text()).date(year + " " + e.child(2).text())
                .home(select(at, fst, snd)).away(select(at, snd, fst)).build();
    }

    private TeamScore select(String at, Supplier<TeamScore> fst, Supplier<TeamScore> snd) {
        if (at.equals("@"))
            return snd.get();
        else
            return fst.get();
    }

    protected static String extractYear(Document doc) {
        return doc.title().substring(0, 4);
    }
}