net.landora.anidb.mylist.ListReader.java Source code

Java tutorial

Introduction

Here is the source code for net.landora.anidb.mylist.ListReader.java

Source

/**
 * Copyright (C) 2012-2014 Blake Dickie
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package net.landora.anidb.mylist;

import net.landora.model.anidb.Anime;
import net.landora.model.anidb.AnimeCategory;
import net.landora.model.anidb.AnimeCategoryWeight;
import net.landora.model.anidb.AnimeEpisode;
import net.landora.model.anidb.AnimeFile;
import net.landora.model.anidb.AnimeGroup;
import net.landora.model.anidb.AnimeListItem;
import net.landora.model.anidb.AnimeName;
import net.landora.model.anidb.repo.AnimeCategoryRepository;
import net.landora.model.anidb.repo.AnimeFileRepository;
import net.landora.model.anidb.repo.AnimeGroupRepository;
import net.landora.model.anidb.repo.AnimeRepository;
import org.apache.commons.io.IOUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xeustechnologies.jtar.TarEntry;
import org.xeustechnologies.jtar.TarInputStream;
import java.io.InputStream;
import java.net.URL;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

/**
 *
 * @author bdickie
 */
@Component
public class ListReader {

    @Autowired
    private AnimeRepository animeRepository;

    @Autowired
    private AnimeCategoryRepository animeCategoryRepository;

    @Autowired
    private AnimeGroupRepository animeGroupRepository;

    @Autowired
    private AnimeFileRepository animeFileRepository;

    public ListReader() {
    }

    private Map<String, String> values;

    public boolean download(URL input) throws Throwable {
        return download(input.openStream());
    }

    public boolean download(InputStream input) throws Throwable {
        TarInputStream is = null;
        try {
            is = new TarInputStream(new GZIPInputStream(input));

            TarEntry entry;
            while ((entry = is.getNextEntry()) != null) {
                if (!entry.getName().equalsIgnoreCase("mylist.xml")) {
                    continue;
                }

                XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(is);
                reader.nextTag();
                reader.require(XMLStreamReader.START_ELEMENT, null, "my_anime_list");
                values = new HashMap<>();
                StringBuilder value = new StringBuilder();

                while (reader.nextTag() != XMLStreamReader.END_ELEMENT) {
                    reader.require(XMLStreamReader.START_ELEMENT, null, null);
                    String tableName = reader.getLocalName();

                    values.clear();

                    while (reader.nextTag() != XMLStreamReader.END_ELEMENT) {
                        String valueName = reader.getLocalName();

                        value.setLength(0);
                        while (reader.next() != XMLStreamReader.END_ELEMENT) {
                            switch (reader.getEventType()) {
                            case XMLStreamReader.CDATA:
                            case XMLStreamReader.CHARACTERS:
                            case XMLStreamReader.SPACE:
                                value.append(reader.getText());
                            }
                        }
                        reader.require(XMLStreamReader.END_ELEMENT, null, valueName);
                        values.put(valueName, value.toString());

                    }
                    reader.require(XMLStreamReader.END_ELEMENT, null, tableName);

                    handleTable(tableName);

                }
                reader.require(XMLStreamReader.END_ELEMENT, null, "my_anime_list");

                saveLast();
            }
            return true;
        } finally {
            if (is != null) {
                IOUtils.closeQuietly(is);
            } else if (input != null) {
                IOUtils.closeQuietly(input);
            }
        }
    }

    private void saveLast() {
        saveLastAnime();
        saveLastEpisode();
        saveLastFile();
    }

    private DateTime exportDate;

    private void handleTable(String tableName) throws ParseException {
        System.out.println(tableName);
        if (tableName.equals("anime")) {
            handleAnime();
        } else if (tableName.equals("title")) {
            handleTitle();
        } else if (tableName.equals("anime_category")) {
            handleAnimeCategory();
        } else if (tableName.equals("episode")) {
            handleEpisode();
        } else if (tableName.equals("file")) {
            handleFile();
        } else if (tableName.equals("user_info")) {
            exportDate = getDateTime("ExportDate");
        }
    }

    private String getString(String name) {
        String value = values.get(name);
        if (value == null) {
            return null;
        }
        return value.replaceAll(Pattern.quote("<br />"), "\n");
    }

    private Integer getInt(String name) {
        String value = getString(name);
        if (value == null || value.length() == 0 || value.equals("-")) {
            return null;
        }
        return Integer.parseInt(value);
    }

    private Long getLong(String name) {
        String value = getString(name);
        if (value == null || value.length() == 0 || value.equals("-")) {
            return null;
        }
        return Long.parseLong(value);
    }

    private Float getFloat(String name) {
        String value = getString(name);
        if (value == null || value.length() == 0 || value.equals("-")) {
            return null;
        }
        return Float.parseFloat(value);
    }

    private Boolean getBoolean(String name) {
        String value = getString(name);
        if (value == null || value.length() == 0 || value.equals("-")) {
            return null;
        }
        return getString(name).equals("1");
    }

    private final DateTimeFormatter dateTimeFormat;
    private final DateTimeFormatter dateFormat;

    {
        dateTimeFormat = DateTimeFormat.forPattern("dd.MM.yyyy HH:mm").withZoneUTC();

        dateFormat = DateTimeFormat.forPattern("dd.MM.yyyy").withZoneUTC();
    }

    public DateTime getDateTime(String name) throws ParseException {
        String value = getString(name);
        if (value == null || value.equals("0") || value.length() == 0 || value.equals("-") || value.equals("?")) {
            return null;
        }

        DateTime date;

        try {
            date = dateTimeFormat.parseDateTime(value);
        } catch (IllegalArgumentException e) {
            date = dateFormat.parseDateTime(value);
        }

        return date;
    }

    public LocalDate getLocalDate(String name) throws ParseException {
        String value = getString(name);
        if (value == null || value.equals("0") || value.length() == 0 || value.equals("-") || value.equals("?")) {
            return null;
        }

        LocalDate date;

        try {
            date = dateTimeFormat.parseLocalDate(value);
        } catch (IllegalArgumentException e) {
            date = dateFormat.parseLocalDate(value);
        }

        return date;
    }

    private Anime anime;

    private void handleAnime() throws ParseException {
        saveLast();

        int animeId = getInt("AnimeID");
        anime = animeRepository.findByAnimeId(animeId);
        if (anime == null) {
            anime = new Anime();
            anime.setAnimeId(animeId);
        }

        anime.getNames().clear();
        anime.getCategories().clear();
        anime.setLastLoaded(exportDate);

        anime.setNameEnglish(getString("NameEnglish"));
        if (anime.getNameEnglish().length() == 0) {
            anime.setNameEnglish(null);
        }
        anime.setNameMain(getString("Name"));
        anime.setDescription(getString("AnimeDescription"));
        anime.setStartDate(getLocalDate("StartDate"));
        anime.setEndDate(getLocalDate("EndDate"));
        anime.setEpisodeCount(getInt("Eps"));
        anime.setType(getString("TypeName"));
        anime.setRatingPermanent(getFloat("Rating"));
        anime.setRatingPermanentVotes(anime.getRatingPermanent() == null ? null : getInt("Votes"));
        anime.setRatingTemporary(getFloat("TempRating"));
        anime.setRatingTemporaryVotes(anime.getRatingTemporary() == null ? null : getInt("TempVotes"));
        anime.setHentai(getBoolean("Hentai"));

    }

    private void handleTitle() throws ParseException {
        if (anime == null) {
            return;
        }

        AnimeName name = new AnimeName();
        String language = getString("LanguageName");
        String converted = LANGUAGE_CONVERT.get(language);

        name.setLanguage(converted == null ? language : converted);
        name.setType(getString("TitleTypeName"));
        name.setName(getString("Name"));

        anime.getNames().add(name);

    }

    private void handleAnimeCategory() throws ParseException {
        if (anime == null) {
            return;
        }

        int categoryId = getInt("CategoryID");
        AnimeCategory category = animeCategoryRepository.findByCategoryId(categoryId);
        if (category == null) {
            category = new AnimeCategory();
            category.setCategoryId(categoryId);
            category.setName(getString("CategoryName"));
            category.setHentai(getBoolean("CategoryHentai"));
            category = animeCategoryRepository.save(category);
        }

        AnimeCategoryWeight categoryWeight = new AnimeCategoryWeight();
        categoryWeight.setCategory(category);
        categoryWeight.setWeight(getInt("CategoryWeight") / 100);

        anime.getCategories().add(categoryWeight);

    }

    private void saveLastAnime() {
        if (anime == null) {
            return;
        }
        animeRepository.save(anime);
        anime = null;
    }

    private final static Map<String, String> LANGUAGE_CONVERT;

    static {
        LANGUAGE_CONVERT = new HashMap<>();

        LANGUAGE_CONVERT.put("english", "en");
        LANGUAGE_CONVERT.put("japanese", "ja");
        LANGUAGE_CONVERT.put("japanese (transcription)", "x-jat");
        LANGUAGE_CONVERT.put("spanish", "es");
        LANGUAGE_CONVERT.put("arabic", "ar");
        LANGUAGE_CONVERT.put("brazilian portuguese", "pt-BR");
        LANGUAGE_CONVERT.put("chinese (simplified)", "zh-Hans");

    }

    private AnimeEpisode episode;

    private void handleEpisode() throws ParseException {
        saveLast();

        int animeId = getInt("AnimeID");
        int episodeId = getInt("EpID");

        Anime a = animeRepository.findByAnimeId(animeId);
        for (AnimeEpisode e : a.getEpisodes()) {
            if (e.getEpisodeId() == episodeId) {
                episode = e;
                break;
            }
        }

        if (episode == null) {
            episode = new AnimeEpisode();
            episode.setEpisodeId(episodeId);
            episode.setAnime(a);
        }

        episode.setLength(getInt("EpLength"));
        episode.setRating(getFloat("EpRating"));
        episode.setRatingVotes(episode.getRating() == null ? null : getInt("EpVotes"));
        episode.setNameEnglish(getString("EpName"));
        episode.setNameKanji(getString("EpNameKanji"));
        episode.setNameRomaji(getString("EpNameRomaji"));
        episode.setAirDate(getLocalDate("EpAired"));
        episode.setEpisodeNumber(getString("EpNo"));

        a.getEpisodes().add(episode);
    }

    private void saveLastEpisode() {
        if (episode == null) {
            return;
        }

        animeRepository.save(episode.getAnime());
        episode = null;
    }

    private AnimeFile file;
    private AnimeListItem listItem;

    private void handleFile() throws ParseException {
        saveLast();

        int fileId = getInt("FID");

        file = animeFileRepository.findByFileId(fileId);
        if (file == null) {
            file = new AnimeFile();
            file.setFileId(fileId);
            Anime a = animeRepository.findByEpisodes_EpisodeId(getInt("EpID"));
            file.setEpisode(a.findEpisodeById(getInt("EpID")));
        }

        boolean generic = getBoolean("Generic");
        file.setGeneric(generic);

        if (!generic) {

            int groupId = getInt("GID");
            if (groupId > 0) {
                AnimeGroup group = animeGroupRepository.findByGroupId(groupId);
                if (group == null) {
                    group = new AnimeGroup();
                    group.setGroupId(groupId);
                    group.setLongName(getString("GName"));
                    group.setShortName(getString("GShortName"));
                    group = animeGroupRepository.save(group);
                }
                file.setGroup(group);
            }

            file.setEd2k(getString("ed2kHash"));
            file.setSize(getLong("Size"));

            int state = getInt("State");

            if ((state & 1) != 0) {
                file.setCrcValid(true);
            } else if ((state & 2) != 0) {
                file.setCrcValid(false);
            }

            file.setVersion(1);
            if ((state & 4) != 0) {
                file.setVersion(2);
            } else if ((state & 8) != 0) {
                file.setVersion(3);
            } else if ((state & 16) != 0) {
                file.setVersion(4);
            } else if ((state & 32) != 0) {
                file.setVersion(5);
            }

            if ((state & 64) != 0) {
                file.setCensored(false);
            } else if ((state & 128) != 0) {
                file.setCensored(false);
            }

            file.setVideoResolution(getString("ResName"));
            file.setFileType(getString("FileType"));
            file.setVideoCodec(getString("VCodecName"));
            file.setSource(getString("TypeName"));

        } else {
            file.setGroup(null);
            file.setCrcValid(null);
            file.setVersion(null);
            file.setCensored(null);
            file.setEd2k(null);
            file.setSize(null);
            file.setFileType("");
            file.setVideoResolution("");
            file.setVideoCodec("");
            file.setSource("");
        }

        listItem = file.getListItem();
        if (listItem == null) {
            listItem = new AnimeListItem();
            file.setListItem(listItem);
        }

        listItem.setStateId(getInt("MyState"));
        listItem.setFileStateId(getInt("MyFileState"));
        listItem.setViewDate(getDateTime("ViewDate"));
        listItem.setAddedDate(getDateTime("ListDate"));
        listItem.setStorage(getString("Storage"));
        listItem.setSource(getString("Source"));
        listItem.setOther(getString("Other"));
    }

    private void saveLastFile() {
        if (file == null) {
            return;
        }

        file = animeFileRepository.save(file);

        file = null;
        listItem = null;
    }

}