2017-04-06 12:00:36 +02:00
/ * *
* cemu_UI
*
2019-05-17 00:22:51 +02:00
* Copyright 2017 - 2019 < @Seil0 >
2017-04-06 12:00:36 +02:00
*
2017-10-15 13:37:45 +02:00
* 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 .
2017-04-06 12:00:36 +02:00
*
2017-10-15 13:37:45 +02:00
* 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 .
2017-04-06 12:00:36 +02:00
* /
2019-05-17 00:22:51 +02:00
2017-11-13 16:44:39 +01:00
package com.cemu_UI.controller ;
2017-03-23 13:44:21 +01:00
import java.awt.Graphics2D ;
import java.awt.image.BufferedImage ;
import java.io.File ;
import java.io.IOException ;
import java.net.URL ;
import java.sql.Connection ;
import java.sql.DriverManager ;
2019-05-18 01:25:54 +02:00
import java.sql.PreparedStatement ;
2017-03-23 13:44:21 +01:00
import java.sql.ResultSet ;
import java.sql.SQLException ;
import java.sql.Statement ;
2017-03-25 15:18:45 +01:00
import java.util.ArrayList ;
2017-03-23 13:44:21 +01:00
import java.util.List ;
import javax.imageio.ImageIO ;
import javax.xml.parsers.DocumentBuilder ;
import javax.xml.parsers.DocumentBuilderFactory ;
import javax.xml.parsers.ParserConfigurationException ;
import org.apache.commons.io.FileUtils ;
2017-09-12 15:04:21 +02:00
import org.apache.logging.log4j.LogManager ;
import org.apache.logging.log4j.Logger ;
2017-03-23 13:44:21 +01:00
import org.w3c.dom.Document ;
import org.xml.sax.SAXException ;
2019-05-18 01:25:54 +02:00
import com.cemu_UI.datatypes.UIROMDataType ;
import javafx.collections.FXCollections ;
import javafx.collections.ObservableList ;
2017-11-13 16:44:39 +01:00
2017-12-12 11:19:33 +01:00
public class DBController {
2019-01-22 19:21:38 +01:00
2019-05-18 01:25:54 +02:00
private static DBController instance = null ;
2017-03-25 15:18:45 +01:00
private ArrayList < String > entries = new ArrayList < > ( ) ;
2019-05-18 01:25:54 +02:00
private String DB_PATH_LocalGames ;
private String DB_PATH_ReverenceGames ;
private Connection connectionLocal = null ;
private Connection connectionReverence = null ;
2017-12-12 11:19:33 +01:00
private static final Logger LOGGER = LogManager . getLogger ( DBController . class . getName ( ) ) ;
2017-03-23 13:44:21 +01:00
2019-05-18 01:25:54 +02:00
public DBController ( ) {
}
public static DBController getInstance ( ) {
if ( instance = = null ) {
instance = new DBController ( ) ;
}
return instance ;
}
2017-12-12 11:19:33 +01:00
/ * *
2019-05-18 01:25:54 +02:00
* initialize the { @link DBController } with the database connection check if
* there is a need to create a new database refresh the database
2017-12-12 11:19:33 +01:00
* /
2018-02-04 15:19:36 +01:00
public void init ( ) {
2019-05-18 01:25:54 +02:00
initDatabaseConnection ( ) ;
2017-03-23 13:44:21 +01:00
createRomDatabase ( ) ;
}
2017-11-27 10:57:16 +01:00
/ * *
2019-05-18 01:25:54 +02:00
* create a new connection to the HomeFlix . db database
* AutoCommit is set to false to prevent some issues , so manual commit is active !
2017-11-27 10:57:16 +01:00
*
* TODO this should be called LocalGames
* /
2019-05-18 01:25:54 +02:00
private void initDatabaseConnection ( ) {
DB_PATH_LocalGames = XMLController . getDirCemuUI ( ) + " /localRoms.db " ;
DB_PATH_ReverenceGames = XMLController . getRference_gamesFile ( ) . getAbsolutePath ( ) ;
2017-03-23 13:44:21 +01:00
try {
// create a database connection
2019-05-18 01:25:54 +02:00
connectionLocal = DriverManager . getConnection ( " jdbc:sqlite: " + DB_PATH_LocalGames ) ;
connectionLocal . setAutoCommit ( false ) ;
connectionReverence = DriverManager . getConnection ( " jdbc:sqlite: " + DB_PATH_ReverenceGames ) ;
connectionReverence . setAutoCommit ( false ) ;
2017-03-23 13:44:21 +01:00
} catch ( SQLException e ) {
2019-05-18 01:25:54 +02:00
// if the error message is "out of memory", it probably means no database file is found
LOGGER . error ( " error while loading the Local- or ReverenceGames database " , e ) ;
2017-03-23 13:44:21 +01:00
}
2019-05-18 01:25:54 +02:00
LOGGER . info ( " Local- and ReverenceGames database loaded successfull " ) ;
2017-03-23 13:44:21 +01:00
}
2017-11-27 10:57:16 +01:00
/ * *
* creating the local_roms table in localRoms . db
* if the table has no entries , call loadRomDirectory
*
2019-05-18 01:25:54 +02:00
* TODO the local_roms table should be called LocalGames
2017-11-27 10:57:16 +01:00
* /
void createRomDatabase ( ) {
2017-03-23 13:44:21 +01:00
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-03-23 13:44:21 +01:00
stmt . executeUpdate ( " create table if not exists local_roms (title, coverPath, romPath, titleID, productCode, region, lastPlayed, timePlayed) " ) ;
2019-05-18 01:25:54 +02:00
connectionLocal . commit ( ) ;
2017-03-23 13:44:21 +01:00
stmt . close ( ) ;
2017-09-12 15:04:21 +02:00
} catch ( SQLException e ) {
2019-05-18 01:25:54 +02:00
LOGGER . error ( " error while creating local-games database " , e ) ;
2017-03-23 13:44:21 +01:00
}
2019-05-18 01:25:54 +02:00
}
/ * *
* refresh database to contain all ( new added ) games
* /
public void refreshDataBase ( ) {
LOGGER . info ( " <========== starting refreshing database ==========> " ) ;
entries . clear ( ) ;
2017-11-27 10:57:16 +01:00
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-11-27 10:57:16 +01:00
ResultSet rs = stmt . executeQuery ( " SELECT * FROM local_roms " ) ;
while ( rs . next ( ) ) {
2017-03-25 15:18:45 +01:00
entries . add ( rs . getString ( 2 ) ) ;
}
stmt . close ( ) ;
rs . close ( ) ;
2017-11-27 10:57:16 +01:00
} catch ( SQLException e ) {
2017-09-12 15:04:21 +02:00
LOGGER . error ( " error while loading ROMs from ROM database, local_roms table " , e ) ;
2017-03-25 15:18:45 +01:00
}
2019-05-18 01:25:54 +02:00
2017-11-27 10:57:16 +01:00
if ( entries . size ( ) = = 0 ) {
2018-01-31 17:01:47 +01:00
loadAllGames ( ) ;
2017-03-25 15:18:45 +01:00
}
2019-05-18 01:25:54 +02:00
LOGGER . info ( " <========== finished refreshing database ==========> " ) ;
2017-03-23 13:44:21 +01:00
}
2018-01-31 17:01:47 +01:00
// add a game to the database
2017-11-27 10:57:16 +01:00
public void addGame ( String title , String coverPath , String romPath , String titleID , String productCode , String region , String lastPlayed , String timePlayed ) throws SQLException {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-10-31 14:11:17 +01:00
stmt . executeUpdate ( " insert into local_roms values (' " + title + " ',' " + coverPath + " ',' " + romPath + " ',' " + titleID + " ', "
+ " ' " + productCode + " ',' " + region + " ',' " + lastPlayed + " ',' " + timePlayed + " ') " ) ;
2019-05-18 01:25:54 +02:00
connectionLocal . commit ( ) ;
2017-03-23 13:44:21 +01:00
stmt . close ( ) ;
2017-09-12 15:04:21 +02:00
LOGGER . info ( " added \" " + title + " \" to ROM database " ) ;
2017-03-23 13:44:21 +01:00
}
2018-01-31 17:01:47 +01:00
// remove a game from the database
2017-11-27 10:57:16 +01:00
public void removeGame ( String titleID ) throws SQLException {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-03-23 13:44:21 +01:00
stmt . executeUpdate ( " delete from local_roms where titleID = ' " + titleID + " ' " ) ;
2019-05-18 01:25:54 +02:00
connectionLocal . commit ( ) ;
2017-03-23 13:44:21 +01:00
stmt . close ( ) ;
2017-09-12 15:04:21 +02:00
LOGGER . info ( " removed \" " + titleID + " \" from ROM database " ) ;
2017-03-23 13:44:21 +01:00
}
2019-05-18 01:25:54 +02:00
/ * *
* load all games from the database to a ObservableList , order entries by title
* @return a ObservableList that contains all local games from the database
* /
public ObservableList < UIROMDataType > loadAllGames ( ) {
ObservableList < UIROMDataType > games = FXCollections . observableArrayList ( ) ;
LOGGER . info ( " loading all local games from the database ... " ) ;
try {
Statement stmt = connectionLocal . createStatement ( ) ;
2017-03-23 13:44:21 +01:00
ResultSet rs = stmt . executeQuery ( " SELECT * FROM local_roms " ) ;
while ( rs . next ( ) ) {
2019-05-18 01:25:54 +02:00
games . add ( new UIROMDataType ( rs . getString ( " romPath " ) , rs . getString ( " titleID " ) , rs . getString ( " title " ) ,
rs . getString ( " coverPath " ) ) ) ;
2017-03-23 13:44:21 +01:00
}
stmt . close ( ) ;
rs . close ( ) ;
2019-05-18 01:25:54 +02:00
} catch ( Exception e ) {
LOGGER . error ( " error while loading all local games from the database " , e ) ;
2017-03-23 13:44:21 +01:00
}
2019-05-18 01:25:54 +02:00
return games ;
2017-03-23 13:44:21 +01:00
}
2019-05-18 01:25:54 +02:00
/ * *
* load one game from the database
* @param titleID the titleID of the game you wish to get
* @return the game you asked for
* /
public UIROMDataType loadSingleGame ( String titleID ) {
UIROMDataType game = null ;
LOGGER . info ( " loading a single game (ID: {}) from the database ... " , titleID ) ;
2017-03-23 13:44:21 +01:00
try {
2019-05-18 01:25:54 +02:00
PreparedStatement ps = connectionLocal . prepareStatement ( " SELECT * FROM local_roms where titleID = ? " ) ;
ps . setString ( 1 , titleID ) ;
ResultSet rs = ps . executeQuery ( ) ;
2017-03-23 13:44:21 +01:00
while ( rs . next ( ) ) {
2019-05-18 01:25:54 +02:00
game = new UIROMDataType ( rs . getString ( " romPath " ) , rs . getString ( " titleID " ) , rs . getString ( " title " ) ,
rs . getString ( " coverPath " ) ) ;
2017-03-23 13:44:21 +01:00
}
rs . close ( ) ;
2019-05-18 01:25:54 +02:00
ps . close ( ) ;
2017-03-23 13:44:21 +01:00
} catch ( Exception e ) {
2017-11-27 10:57:16 +01:00
LOGGER . error ( " error while loading a single game into the mainWindowController " , e ) ;
2017-03-23 13:44:21 +01:00
}
2019-05-18 01:25:54 +02:00
return game ;
2017-03-23 13:44:21 +01:00
}
2017-11-27 10:57:16 +01:00
/ * *
* get all . rpx files from a given directory and add them to the games database if they don ' t exist there
* @param directory where to search for the . rpx files
* /
2017-11-13 16:44:39 +01:00
public void loadRomDirectory ( String directory ) {
2017-03-23 13:44:21 +01:00
File dir = new File ( directory ) ;
2017-04-08 02:25:23 +02:00
File appFile ;
2017-03-23 13:44:21 +01:00
String [ ] extensions = new String [ ] { " rpx " , " jsp " } ;
2019-01-22 19:21:38 +01:00
File pictureCache = XMLController . getPictureCache ( ) ;
2018-02-17 17:49:12 +01:00
String coverPath ;
2017-03-23 13:44:21 +01:00
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionReverence . createStatement ( ) ;
2017-03-23 13:44:21 +01:00
List < File > files = ( List < File > ) FileUtils . listFiles ( dir , extensions , true ) ;
2018-01-31 17:01:47 +01:00
LOGGER . info ( " <============================== start loading ROM Directory ==============================> " ) ;
2017-10-31 14:11:17 +01:00
LOGGER . info ( " Getting all .rpx files in " + dir . getCanonicalPath ( ) + " including those in subdirectories " ) ;
2017-11-27 10:57:16 +01:00
// for all files in dir get the app.xml
2017-03-23 13:44:21 +01:00
for ( File file : files ) {
2017-12-12 19:19:01 +01:00
appFile = new File ( file . getParent ( ) + " /app.xml " ) ;
2017-03-23 13:44:21 +01:00
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory . newInstance ( ) ;
DocumentBuilder documentBuilder = documentBuilderFactory . newDocumentBuilder ( ) ;
Document document = documentBuilder . parse ( appFile ) ;
2017-12-12 19:19:01 +01:00
String title_ID = document . getElementsByTagName ( " title_id " ) . item ( 0 ) . getTextContent ( ) ; // get titile_ID from app.xml
2017-03-23 13:44:21 +01:00
title_ID = title_ID . substring ( 0 , 8 ) + " - " + title_ID . substring ( 8 , title_ID . length ( ) ) ;
2017-12-12 19:19:01 +01:00
LOGGER . info ( " Name: " + file . getName ( ) + " ; Title ID: " + title_ID ) ;
ResultSet rs = stmt . executeQuery ( " SELECT * FROM games WHERE TitleID = ' " + title_ID + " '; " ) ;
2017-11-27 10:57:16 +01:00
// for all elements in the games table check if it's already present, else add it
2017-03-23 13:44:21 +01:00
while ( rs . next ( ) ) {
2018-02-18 13:57:30 +01:00
if ( checkAddEntry ( rs . getString ( 2 ) ) ) {
2017-09-12 15:04:21 +02:00
LOGGER . info ( rs . getString ( 2 ) + " : game already in database " ) ;
2017-12-12 19:19:01 +01:00
} else {
2017-09-12 15:04:21 +02:00
LOGGER . info ( " adding cover to cache ... " ) ;
2017-12-12 19:19:01 +01:00
BufferedImage originalImage = ImageIO . read ( new URL ( rs . getString ( 6 ) ) ) ; // change path to where file is located
int type = originalImage . getType ( ) = = 0 ? BufferedImage . TYPE_INT_ARGB : originalImage . getType ( ) ;
BufferedImage resizeImagePNG = resizeImage ( originalImage , type , 400 , 600 ) ;
ImageIO . write ( resizeImagePNG , " png " , new File ( pictureCache + " / " + rs . getString ( 3 ) + " .png " ) ) ;
coverPath = pictureCache + " / " + rs . getString ( 3 ) + " .png " ;
2017-09-12 15:04:21 +02:00
LOGGER . info ( rs . getString ( 2 ) + " : adding ROM " ) ;
2017-12-12 19:19:01 +01:00
addGame ( rs . getString ( 2 ) , coverPath , file . getCanonicalPath ( ) , rs . getString ( 1 ) , rs . getString ( 3 ) ,
rs . getString ( 5 ) , " " , " 0 " ) ;
2017-03-23 13:44:21 +01:00
}
}
}
2018-01-31 17:01:47 +01:00
LOGGER . info ( " <============================= finished loading ROM Directory ============================> " ) ;
2017-03-23 13:44:21 +01:00
} catch ( IOException | SQLException | ParserConfigurationException | SAXException e ) {
2017-09-12 15:04:21 +02:00
LOGGER . error ( " error while loading ROMs from directory " , e ) ;
2017-03-23 13:44:21 +01:00
}
}
2018-02-18 13:57:30 +01:00
/ * *
* check if there is a game with the given name already in the database
* @param title game title
* @return true if the game exists , false if not
* @throws SQLException
* /
private boolean checkAddEntry ( String title ) throws SQLException {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-03-23 13:44:21 +01:00
boolean check = false ;
ResultSet rs = stmt . executeQuery ( " SELECT * FROM local_roms WHERE title = ' " + title + " '; " ) ;
while ( rs . next ( ) ) {
check = true ;
}
return check ;
}
2018-01-31 17:01:47 +01:00
@SuppressWarnings ( " unused " )
2017-03-23 13:44:21 +01:00
private void checkRemoveEntry ( ) {
2017-09-12 15:04:21 +02:00
/ * *
* TODO needs to be implemented !
* don ' t show ROM on the UI , but keep all parameter in case it ' s showing up again ask if old data should be used
* /
//LOGGER.info("check if entry removed not done yet!");
2017-03-23 13:44:21 +01:00
}
2017-10-31 14:11:17 +01:00
/ * *
* getting info for a game with titleID
* @param titleID Title - ID of the Game
* @return title , coverPath , romPath , titleID ( in this order )
* /
2017-11-13 16:44:39 +01:00
public String [ ] getGameInfo ( String titleID ) {
2017-10-31 14:11:17 +01:00
String [ ] gameInfo = new String [ 4 ] ;
LOGGER . info ( " getting game info for titleID: " + titleID + " ... " ) ;
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-10-31 14:11:17 +01:00
ResultSet rs = stmt . executeQuery ( " SELECT * FROM local_roms where titleID = ' " + titleID + " ' " ) ;
while ( rs . next ( ) ) {
gameInfo [ 0 ] = rs . getString ( 1 ) ; // title
gameInfo [ 1 ] = rs . getString ( 2 ) ; // coverPath
gameInfo [ 2 ] = rs . getString ( 3 ) ; // romPath
gameInfo [ 3 ] = rs . getString ( 4 ) ; // titleID
}
stmt . close ( ) ;
rs . close ( ) ;
} catch ( Exception e ) {
LOGGER . error ( " error while getting game info " , e ) ;
}
return gameInfo ;
}
2017-11-15 21:21:52 +01:00
public void setGameInfo ( String title , String coverPath , String romPath , String titleID ) {
2017-10-31 14:11:17 +01:00
LOGGER . info ( " setting game info for titleID: " + titleID + " ... " ) ;
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-10-31 14:11:17 +01:00
stmt . executeUpdate ( " UPDATE local_roms SET title = ' " + title + " ', coverPath = ' " + coverPath + " ', "
+ " romPath = ' " + romPath + " ' WHERE titleID = ' " + titleID + " '; " ) ;
2019-05-18 01:25:54 +02:00
connectionLocal . commit ( ) ;
2017-10-31 14:11:17 +01:00
stmt . close ( ) ;
} catch ( Exception e ) {
LOGGER . error ( " error while setting game info " , e ) ;
}
}
2017-11-13 16:44:39 +01:00
public void setLastPlayed ( String titleID ) {
2017-03-23 13:44:21 +01:00
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-03-23 13:44:21 +01:00
stmt . executeUpdate ( " UPDATE local_roms SET lastPlayed=date('now') WHERE titleID = ' " + titleID + " '; " ) ;
2019-05-18 01:25:54 +02:00
connectionLocal . commit ( ) ;
2017-03-23 13:44:21 +01:00
stmt . close ( ) ;
} catch ( SQLException e ) {
2017-09-12 15:04:21 +02:00
LOGGER . error ( " failed to set the last played " , e ) ;
2017-03-23 13:44:21 +01:00
}
}
2017-11-13 16:44:39 +01:00
public String getLastPlayed ( String titleID ) {
2017-03-23 13:44:21 +01:00
String lastPlayed = null ;
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-03-23 13:44:21 +01:00
ResultSet rs = stmt . executeQuery ( " SELECT lastPlayed FROM local_roms WHERE titleID = ' " + titleID + " '; " ) ;
lastPlayed = rs . getString ( 1 ) ;
stmt . close ( ) ;
rs . close ( ) ;
} catch ( SQLException e ) {
2017-09-12 15:04:21 +02:00
LOGGER . error ( " failed to get the last played " , e ) ;
2017-03-23 13:44:21 +01:00
}
return lastPlayed ;
}
2017-11-13 16:44:39 +01:00
public void setTotalPlaytime ( String timePlayed , String titleID ) {
2017-03-23 13:44:21 +01:00
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-03-25 15:18:45 +01:00
stmt . executeUpdate ( " UPDATE local_roms SET timePlayed=' " + timePlayed + " ' WHERE titleID = ' " + titleID + " '; " ) ;
2019-05-18 01:25:54 +02:00
connectionLocal . commit ( ) ;
2017-03-23 13:44:21 +01:00
stmt . close ( ) ;
} catch ( SQLException e ) {
2017-09-12 15:04:21 +02:00
LOGGER . error ( " failed to set total play time " , e ) ;
2017-03-23 13:44:21 +01:00
e . printStackTrace ( ) ;
}
}
2017-11-13 16:44:39 +01:00
public String getTotalPlaytime ( String titleID ) {
2017-03-23 13:44:21 +01:00
String timePlayed = null ;
try {
2019-05-18 01:25:54 +02:00
Statement stmt = connectionLocal . createStatement ( ) ;
2017-03-23 13:44:21 +01:00
ResultSet rs = stmt . executeQuery ( " SELECT timePlayed FROM local_roms WHERE titleID = ' " + titleID + " '; " ) ;
2017-03-25 15:18:45 +01:00
timePlayed = rs . getString ( 1 ) ;
2017-03-23 13:44:21 +01:00
stmt . close ( ) ;
rs . close ( ) ;
} catch ( SQLException e ) {
2017-09-12 15:04:21 +02:00
LOGGER . error ( " failed to get total play time " , e ) ;
2017-03-23 13:44:21 +01:00
}
return timePlayed ;
}
2017-03-25 15:18:45 +01:00
2019-05-18 01:25:54 +02:00
private static BufferedImage resizeImage ( BufferedImage originalImage , int type , int IMG_WIDTH , int IMG_HEIGHT ) {
BufferedImage resizedImage = new BufferedImage ( IMG_WIDTH , IMG_HEIGHT , type ) ;
Graphics2D g = resizedImage . createGraphics ( ) ;
g . drawImage ( originalImage , 0 , 0 , IMG_WIDTH , IMG_HEIGHT , null ) ;
g . dispose ( ) ;
return resizedImage ;
}
2017-10-31 14:11:17 +01:00
2017-03-23 13:44:21 +01:00
}