jshm.dataupdaters.RbSongUpdater.java Source code

Java tutorial

Introduction

Here is the source code for jshm.dataupdaters.RbSongUpdater.java

Source

/*
 * -----LICENSE START-----
 * JSHManager - A Java-based tool for managing one's ScoreHero account.
 * Copyright (C) 2008 Tim Mullin
 * 
 * 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 2 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, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 * -----LICENSE END-----
*/
package jshm.dataupdaters;

import static jshm.hibernate.HibernateUtil.openSession;

import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
//import org.hibernate.criterion.Example;
import org.netbeans.spi.wizard.ResultProgressHandle;

import jshm.*;
import jshm.rb.*;
import jshm.sh.scraper.RbSongScraper;
import jshm.xml.RbSongDataFetcher;
import jshm.xml.RbSongInfoFetcher;

public class RbSongUpdater {
    static final Logger LOG = Logger.getLogger(RbSongUpdater.class.getName());

    public static void updateViaXml(final GameTitle game) throws Exception {
        updateViaXml(null, game);
    }

    public static void updateViaXml(final ResultProgressHandle progress, final GameTitle game) throws Exception {
        if (!(game instanceof RbGameTitle))
            throw new IllegalArgumentException("game must be an RbGameTitle");

        Session session = null;
        Transaction tx = null;

        try {
            session = openSession();
            tx = session.beginTransaction();

            // first get the songs themselves

            if (null != progress)
                progress.setBusy("Downloading song data for " + game);

            RbSongDataFetcher fetcher = new RbSongDataFetcher();
            fetcher.fetch((RbGameTitle) game);

            LOG.finer("xml updated at " + fetcher.updated);

            Map<RbGame, Tiers> tiers = fetcher.tierMap;
            LOG.finer("xml had " + tiers.size() + " tiers for " + game);

            if (null != progress)
                progress.setBusy("Updating tiers");

            for (RbGame key : tiers.keySet()) {
                Tiers.setTiers(key, tiers.get(key));
                key.mapTiers(tiers.get(key));
            }

            Tiers.write();

            List<RbSong> songs = fetcher.songs;

            LOG.finer("xml had " + songs.size() + " songs for " + game);

            if (songs.isEmpty()) {
                throw new Exception("xml had 0 songs for " + game + ", it's probably out of date");
            }

            int i = 0, total = songs.size();
            for (RbSong song : songs) {
                if (null != progress)
                    progress.setProgress(String.format("Processing song %s of %s", i + 1, total), i, total);

                // only care about the sh id and gameTitle
                RbSong result = (RbSong) session
                        .createQuery("FROM RbSong WHERE scoreHeroId=:shid AND gameTitle=:gameTtl")
                        .setInteger("shid", song.getScoreHeroId()).setString("gameTtl", song.getGameTitle().title)
                        .uniqueResult();

                if (null == result) {
                    // new insert
                    LOG.info("Inserting song: " + song);
                    session.save(song);
                } else {
                    LOG.finest("found song: " + result);
                    // update existing
                    if (result.update(song, true)) {
                        LOG.info("Updating song to: " + result);
                        session.update(result);
                    } else {
                        LOG.finest("No changes to song: " + result);
                    }
                }

                if (i % 64 == 0) {
                    session.flush();
                    session.clear();
                }

                i++;
            }

            // now get song orders
            List<SongOrder> orders = fetcher.orders;

            LOG.finer("xml had " + orders.size() + " song orderings for " + game);

            // faster to delete them all and insert instead of checking
            // each one separately
            LOG.info("Deleting old song orders");
            int deletedOrderCount = session.createQuery("delete SongOrder where gameTitle=:gameTitle")
                    .setString("gameTitle", game.toString()).executeUpdate();

            LOG.finer("deleted " + deletedOrderCount + " old song orders");

            i = 0;
            total = orders.size();
            for (SongOrder order : orders) {
                // we need to get an instance of the RbSong that's in the db,
                // not the detached one we used before from the xml
                order.setSong(RbSong.getByScoreHeroId(session, order.getSong().getScoreHeroId()));

                // new insert
                LOG.info("Inserting song order: " + order);
                session.save(order);

                if (i % 64 == 0) {
                    session.flush();
                    session.clear();

                    if (null != progress)
                        progress.setProgress("Processing song order lists...", i, total);
                }

                i++;
            }

            tx.commit();
        } catch (HibernateException e) {
            if (null != tx && tx.isActive())
                tx.rollback();
            LOG.throwing("RbSongUpdater", "updateViaXml", e);
            throw e;
        } finally {
            if (null != session && session.isOpen())
                session.close();
        }
    }

    public static void updateViaScraping(final GameTitle game) throws Exception {
        updateViaScraping(null, game);
    }

    public static void updateViaScraping(final ResultProgressHandle progress, final GameTitle game)
            throws Exception {
        if (!(game instanceof RbGameTitle))
            throw new IllegalArgumentException("game must be an RbGameTitle");

        Session session = null;
        Transaction tx = null;

        try {
            session = openSession();
            tx = session.beginTransaction();

            // first get the songs themselves, need to do for each platform
            for (Game g : Game.getByTitle(game)) {
                if (null != progress)
                    progress.setBusy("Downloading song list for " + g);

                List<RbSong> songs = RbSongScraper.scrape((RbGame) g);

                LOG.finer("scraped " + songs.size() + " songs for " + g);

                assert null != RbSongScraper.lastScrapedTiers;
                LOG.finer("remapping " + RbSongScraper.lastScrapedTiers.size() + " tiers for " + g);
                Tiers tiers = new Tiers(RbSongScraper.lastScrapedTiers);
                Tiers.setTiers(g, tiers);
                ((RbGame) g).mapTiers(tiers);

                int i = 0, total = songs.size();
                for (RbSong song : songs) {
                    if (null != progress)
                        progress.setProgress(String.format("Processing song %s of %s", i + 1, total), i, total);

                    // only care about the sh id and gameTitle
                    RbSong result = (RbSong) session
                            .createQuery("FROM RbSong WHERE scoreHeroId=:shid AND gameTitle=:gameTtl")
                            .setInteger("shid", song.getScoreHeroId())
                            .setString("gameTtl", song.getGameTitle().title).uniqueResult();

                    if (null == result) {
                        // new insert
                        LOG.info("Inserting song: " + song);
                        session.save(song);
                    } else {
                        LOG.finest("found song: " + result);
                        // update existing
                        if (result.update(song, false)) {
                            LOG.info("Updating song to: " + result);
                            session.update(result);
                        } else {
                            LOG.finest("No changes to song: " + result);
                        }
                    }

                    if (i % 64 == 0) {
                        session.flush();
                        session.clear();
                    }

                    i++;
                }
            }

            // need to save tiers at some point
            Tiers.write();

            // faster to delete them all and insert instead of checking
            // each one separately
            LOG.info("Deleting old song orders");
            int deletedOrderCount = session.createQuery("delete SongOrder where gameTitle=:gameTitle")
                    .setString("gameTitle", game.toString()).executeUpdate();

            LOG.finer("deleted " + deletedOrderCount + " old song orders");

            // for now we kind of have to do each platform/group combo.... 20+ requests ugh
            // at least it seems to be working
            for (Game g : Game.getByTitle(game)) {
                if (null != progress)
                    progress.setBusy("Downloading song order lists for " + g);

                List<SongOrder> orders = RbSongScraper.scrapeOrders(progress, (RbGame) g);

                LOG.finer("scraped " + orders.size() + " song orderings for " + g);

                int i = 0, total = orders.size();
                for (SongOrder order : orders) {
                    LOG.info("Inserting song order: " + order);
                    session.save(order);

                    if (i % 64 == 0) {
                        session.flush();
                        session.clear();

                        if (null != progress)
                            progress.setProgress("Processing song order lists...", i, total);
                    }

                    i++;
                }
            }

            tx.commit();
        } catch (HibernateException e) {
            if (null != tx && tx.isActive())
                tx.rollback();
            LOG.throwing("RbSongUpdater", "updateViaScraping", e);
            throw e;
        } finally {
            if (null != session && session.isOpen())
                session.close();
        }
    }

    public static void updateSongInfo() throws Exception {
        updateSongInfo(null);
    }

    @SuppressWarnings("unchecked")
    public static void updateSongInfo(final ResultProgressHandle progress) throws Exception {
        if (null != progress)
            progress.setBusy("Downloading song meta data...");
        RbSongInfoFetcher fetcher = new RbSongInfoFetcher();
        fetcher.fetch();
        Session session = null;
        Transaction tx = null;

        try {
            session = openSession();
            tx = session.beginTransaction();

            int i = 0, total = fetcher.songMap.size();

            for (String key : fetcher.songMap.keySet()) {
                if (null != progress)
                    progress.setProgress(String.format("Processing song %s of %s", i + 1, total), i, total);

                String upperTtl = key.toUpperCase();
                String ttlReplacement = upperTtl.replace("AND", "%").replace(" '", "%").replace('&', '%')
                        .replace('/', '%').replace('\'', '%').replace('!', '%').replace('?', '%')
                        .replace('\u00E8', '%') // e`
                        .replace('\u00DC', '%') // U umlat
                ;

                // extra steps taken to try to cope with song title inconsistencies
                List<RbSong> result = (List<RbSong>) session
                        .createQuery("FROM RbSong WHERE UPPER(title) LIKE :ttl AND gameTitle != :tbrbGt")
                        .setString("ttl", ttlReplacement).setString("tbrbGt", RbGameTitle.TBRB.title) // just ignore tbrb for now
                        .list();

                if (!upperTtl.equals(ttlReplacement)) {
                    LOG.fine("Looking for {" + ttlReplacement + "}, given {" + upperTtl + "}, found "
                            + result.size());
                }

                for (RbSong s : result) {
                    if (s.update(fetcher.songMap.get(key))) {
                        LOG.info("Updating song to: " + s);
                        session.update(s);
                    } else {
                        LOG.finer("No changes to song: " + s);
                    }
                }

                if (i % 64 == 0) {
                    session.flush();
                    session.clear();
                }

                i++;
            }

            tx.commit();
        } catch (HibernateException e) {
            if (null != tx && tx.isActive())
                tx.rollback();
            LOG.throwing("RbSongUpdater", "updateSongInfo", e);
            throw e;
        } finally {
            if (null != session && session.isOpen())
                session.close();
        }

        for (GameTitle g : GameTitle.getBySeries(GameSeries.ROCKBAND)) {
            g.initDynamicTiers();
        }
    }
}