Improved file name generation and handling of duplicate titles

fix: generated file names for covers, screens and game files is improved to consider more characters to avoid that two games point to the same files.
fix: When adding a new game where the file names becomes equal to an existing game in the db an additional index is added to the file name as a suffix.
fix: file names are re-calculated when a game is saved and renamed if not matching the new rules.
This commit is contained in:
lantzelot-swe 2021-12-13 19:01:55 +01:00
parent fea8772a6e
commit 1772fab2f3
6 changed files with 82 additions and 75 deletions

View File

@ -24,6 +24,7 @@ import se.lantz.model.data.GameView;
import se.lantz.model.data.ViewFilter;
import se.lantz.util.DbConstants;
import se.lantz.util.ExceptionHandler;
import se.lantz.util.FileManager;
import se.lantz.util.GameListDataComparator;
public class DbConnector
@ -755,12 +756,19 @@ public class DbConnector
return returnValue;
}
public int getGameDuplicateIndexToUse(String title)
public int getGameDuplicateIndexToUse(String title, String gameId)
{
//This is only called when the title changes for an existing game or when adding a new game
//Use generated name, that is what decides if a duplicate index needs to be used.
//Look at the coverFile column since all covers have the same name ending.
String fileName = FileManager.generateFileNameFromTitle(title, 0);
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("SELECT Duplicate FROM gameinfo WHERE title LIKE \"");
sqlBuilder.append(title);
sqlBuilder.append("\";");
sqlBuilder.append("SELECT rowId, Duplicate FROM gameinfo WHERE Coverfile GLOB \'");
sqlBuilder.append(fileName);
sqlBuilder.append("-cover*\' OR CoverFile GLOB \'");
sqlBuilder.append(fileName);
sqlBuilder.append("[0-9][0-9]-cover*\';");
String sql = sqlBuilder.toString();
logger.debug("Checking if game is in db already: {}", sql);
int returnIndex = 0;
@ -769,8 +777,13 @@ public class DbConnector
ResultSet rs = pstmt.executeQuery();
while (rs.next())
{
//Increase one to the available index since it's the one supposed to be used.
returnIndex = Math.max(returnIndex, rs.getInt(DbConstants.DUPLICATE_INDEX) + 1);
int rowId = rs.getInt("rowId");
//Ignore the current game if the query matches it
if (gameId.isEmpty() || rowId != Integer.parseInt(gameId))
{
//Increase one to the available index since it's the one supposed to be used.
returnIndex = Math.max(returnIndex, rs.getInt(DbConstants.DUPLICATE_INDEX) + 1);
}
}
}
catch (SQLException e)

View File

@ -468,7 +468,7 @@ public class ImportManager
int duplicateIndex = 0;
if (selectedOption == Options.ADD)
{
duplicateIndex = uiModel.getDbConnector().getGameDuplicateIndexToUse(title);
duplicateIndex = uiModel.getDbConnector().getGameDuplicateIndexToUse(title, "");
}
//Check any duplicates in added rows, always use this otherwise duplicates uses same names.
duplicateIndex = duplicateIndex + getDbRowDuplicate(title);

View File

@ -99,15 +99,13 @@ public class SavedStatesManager
}
//If the game has been renamed, make sure to rename the saves folder also
if (model.getInfoModel().isTitleChanged())
String oldFileName = model.getInfoModel().getOldGamesFile();
String newFileName = model.getInfoModel().getGamesFile();
File oldSaveFolder = new File(SAVES + oldFileName);
if (!oldFileName.equals(newFileName) && oldSaveFolder.exists())
{
String oldFileName = model.getInfoModel().getOldGamesFile();
File oldSaveFolder = new File(SAVES + oldFileName);
if (oldSaveFolder.exists())
{
//Rename old folder to new name
oldSaveFolder.renameTo(new File(SAVES + model.getInfoModel().getGamesFile()));
}
//Rename old folder to new name
oldSaveFolder.renameTo(new File(SAVES + model.getInfoModel().getGamesFile()));
}
String fileName = model.getInfoModel().getGamesFile();
@ -557,11 +555,11 @@ public class SavedStatesManager
{
return savedStatesMap.get(gameFileName) != null ? savedStatesMap.get(gameFileName) : 0;
}
public void checkEnablementOfPalNtscMenuItem(boolean check)
{
boolean palNtscItemEnabled = false;
if (check)
{
//Check if current game has a 0.vsf file and the current game file is a snapshot
@ -583,13 +581,13 @@ public class SavedStatesManager
}
palNtscFixMenuItem.setEnabled(palNtscItemEnabled);
}
public boolean swapGameFileAndSavedState()
{
String gamesFile = model.getInfoModel().getGamesFile();
Path gameFilePath = new File(FileManager.GAMES + gamesFile).toPath();
Path firstSavedStatePath = new File(SAVES + gamesFile).toPath().resolve(VSZ0);
Path tempFilePath = new File(FileManager.GAMES + "temp.gz").toPath();
try
{

View File

@ -367,39 +367,34 @@ public class InfoModel extends AbstractModel
}
}
public boolean updateFileNames()
public void updateFileNames()
{
if (isNewGame() || isTitleChanged() || screenNamesNeedsUpdate())
{
//Keep track of the old names, used when renaming files when saving
oldCoverFile = getCoverFile();
oldScreens1File = getScreens1File();
oldScreens2File = getScreens2File();
oldGamesFile = getGamesFile();
//Keep track of the old names, used when renaming files when saving
oldCoverFile = getCoverFile();
oldScreens1File = getScreens1File();
oldScreens2File = getScreens2File();
oldGamesFile = getGamesFile();
disableChangeNotification(true);
String fileName = FileManager.generateFileNameFromTitle(this.title, getDuplicateIndex());
if (!getCoverFile().isEmpty() || getCoverImage() != null)
{
setCoverFile(fileName + "-cover.png");
}
if (!getScreens1File().isEmpty() || getScreen1Image() != null)
{
setScreens1File(fileName + "-00.png");
}
if (!getScreens2File().isEmpty() || getScreen2Image() != null)
{
setScreens2File(fileName + "-01.png");
}
if (!getGamesFile().isEmpty())
{
String fileEnding = getGamesFile().substring(getGamesFile().indexOf("."));
setGamesFile(fileName + fileEnding);
}
disableChangeNotification(false);
return true;
disableChangeNotification(true);
String fileName = FileManager.generateFileNameFromTitle(this.title, getDuplicateIndex());
if (!getCoverFile().isEmpty() || getCoverImage() != null)
{
setCoverFile(fileName + "-cover.png");
}
return false;
if (!getScreens1File().isEmpty() || getScreen1Image() != null)
{
setScreens1File(fileName + "-00.png");
}
if (!getScreens2File().isEmpty() || getScreen2Image() != null)
{
setScreens2File(fileName + "-01.png");
}
if (!getGamesFile().isEmpty())
{
String fileEnding = getGamesFile().substring(getGamesFile().indexOf("."));
setGamesFile(fileName + fileEnding);
}
disableChangeNotification(false);
}
public void updateCoverAndScreensIfEmpty(boolean isC64)

View File

@ -8,7 +8,6 @@ import java.util.Collections;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.ListModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -72,12 +71,12 @@ public class MainViewModel extends AbstractModel
private GameListData selectedData;
Scraper scraper = new MobyGamesScraper();
public void setSavedStatesManager(SavedStatesManager savedStatesManager)
{
this.stateManager = savedStatesManager;
}
public SavedStatesManager getSavedStatesManager()
{
return this.stateManager;
@ -256,7 +255,7 @@ public class MainViewModel extends AbstractModel
}
//Read available saved states
stateManager.readSavedStates();
disableChangeNotification(false);
notifyChangeForAllModels();
//Do not reset unsaved for new entry
@ -322,7 +321,7 @@ public class MainViewModel extends AbstractModel
{
return systemModel;
}
public SavedStatesModel getSavedStatesModel()
{
return stateModel;
@ -492,7 +491,8 @@ public class MainViewModel extends AbstractModel
if (infoModel.isNewGame() || infoModel.isTitleChanged())
{
//Update duplicate index
infoModel.setDuplicateIndex(dbConnector.getGameDuplicateIndexToUse(infoModel.getTitle()));
infoModel.setDuplicateIndex(dbConnector.getGameDuplicateIndexToUse(infoModel.getTitle(),
this.selectedData.getGameId()));
}
if (!validateRequiredFields().isEmpty())
@ -589,7 +589,7 @@ public class MainViewModel extends AbstractModel
fileManager.saveFiles();
stateManager.saveSavedStates();
//Reset and images that where added previously
infoModel.resetImagesAndOldFileNames();
//Reset all models
@ -835,14 +835,14 @@ public class MainViewModel extends AbstractModel
{
fileManager.runViceWithoutGame();
}
public void runSnapshotInVice(SavedStatesModel.SAVESTATE saveState)
{
fileManager.runSnapshotInVice(saveState);
}
public void checkEnablementOfPalNtscMenuItem(boolean check)
{
stateManager.checkEnablementOfPalNtscMenuItem(check);
stateManager.checkEnablementOfPalNtscMenuItem(check);
}
}

View File

@ -113,12 +113,8 @@ public class FileManager
public void saveFiles()
{
//Check if title is different that in db, then rename existing files!
if (infoModel.isTitleChanged() || infoModel.isAnyScreenRenamed())
{
//Rename existing covers and screens and game file
renameFiles();
}
//Rename existing covers and screens and game file if needed
renameFiles();
//Fetch images that has been added
BufferedImage cover = infoModel.getCoverImage();
@ -352,14 +348,7 @@ public class FileManager
public static String generateFileNameFromTitle(String title, int duplicateIndex)
{
// All uppercase letters
// No spaces or special characters
//The maxi game tool seems to work like this: truncate to 23 characters and then remove all special characters.
if (title.length() > 23)
{
title = title.substring(0, 23);
logger.debug("FileName: truncating to : {}", title);
}
// Do the conversion
// No spaces or special characters, remove them first
List<Character> forbiddenCharsList =
" ,:'<27>-.!+*<>()/[]?|".chars().mapToObj(item -> (char) item).collect(Collectors.toList());
@ -367,11 +356,23 @@ public class FileManager
title.chars().mapToObj(item -> (char) item).filter(character -> !forbiddenCharsList.contains(character))
.map(Character::toUpperCase).collect(Collectors.toList());
String newNameString = newName.stream().map(String::valueOf).collect(Collectors.joining());
if (duplicateIndex > 0)
//The maxi game tool seems to truncate to a maximum length of 23 characters. Let's do the same here.
if (newNameString.length() > 23)
{
newNameString = newNameString.substring(0, 23);
logger.debug("FileName: truncating to : {}", title);
}
//Just add the duplicate index if there are several games with the same name
if (duplicateIndex > 0 && duplicateIndex < 10)
{
//Just add the duplicate index if there are several games with the same name
newNameString = newNameString + "0" + duplicateIndex;
}
else if (duplicateIndex > 9)
{
newNameString = newNameString + duplicateIndex;
}
logger.debug("Game title: \"{}\" ---- New fileName: \"{}\"", title, newNameString);
return newNameString;