diff --git a/pom.xml b/pom.xml
index 2212657f..ee23a17f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,6 +18,7 @@
org.springframework.boot.loader.JarLauncher
17
19
+ 3.1.14
src/main/java/drrename/PrimaryStageInitializer.java
@@ -127,6 +128,11 @@
+
+ com.github.ulisesbocchio
+ jasypt-maven-plugin
+ 3.0.3
+
@@ -189,6 +195,20 @@
jackson-dataformat-xml
2.13.4
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+ 3.1.1
+
+
+ com.github.ulisesbocchio
+ jasypt-spring-boot-starter
+ 3.0.4
+
diff --git a/src/main/java/drrename/DrRenameApplication.java b/src/main/java/drrename/DrRenameApplication.java
index edbfa6ad..bd0e5b88 100644
--- a/src/main/java/drrename/DrRenameApplication.java
+++ b/src/main/java/drrename/DrRenameApplication.java
@@ -8,7 +8,6 @@
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
-@Slf4j
public class DrRenameApplication extends Application {
private ConfigurableApplicationContext applicationContext;
diff --git a/src/main/java/drrename/FileTypeByMimeProvider.java b/src/main/java/drrename/FileTypeByMimeProvider.java
deleted file mode 100644
index 2638d530..00000000
--- a/src/main/java/drrename/FileTypeByMimeProvider.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package drrename;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.tika.Tika;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-@Slf4j
-public class FileTypeByMimeProvider implements FileTypeProvider {
-
- public static String UNKNOWN = "n/a";
-
- public static String DIRECTORY = "directory";
-
- @Override
- public String getFileType(Path path) {
- final File file = path.toFile();
- if(Files.isDirectory(path)){
- return DIRECTORY;
- }
- try {
- Tika tika = new Tika();
- @SuppressWarnings("")
- var result = tika.detect(file);
- return result;
- } catch (Exception e) {
- log.error(e.getLocalizedMessage(), e);
- return UNKNOWN;
- }
- }
-}
diff --git a/src/main/java/drrename/GeneralExceptionHandler.java b/src/main/java/drrename/GeneralExceptionHandler.java
index fb810fd7..85a38522 100644
--- a/src/main/java/drrename/GeneralExceptionHandler.java
+++ b/src/main/java/drrename/GeneralExceptionHandler.java
@@ -6,9 +6,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
-import java.util.Arrays;
import java.util.ResourceBundle;
-import java.util.stream.Collectors;
@Slf4j
@Component
@@ -22,21 +20,21 @@ private class Handler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
log.error("Uncaught exception on thread {}", t, e);
+ Platform.runLater(() -> showAlertDialog(e));
+ }
+
+ private void showAlertDialog(Throwable e) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle(String.format(resourceBundle.getString(ALERT_TITLE)));
- alert.setHeaderText(e.toString());
-
- TextArea area = new TextArea(Arrays.stream(e.getStackTrace())
- .map(StackTraceElement::toString)
- .collect(Collectors.joining("\n")));
-
+ alert.setHeaderText(e.getLocalizedMessage());
+ TextArea area = new TextArea(RenameUtil.stackTraceToString(e));
alert.getDialogPane().setContent(area);
area.setWrapText(true);
area.setEditable(false);
alert.setResizable(true);
-
-
- Platform.runLater(alert::showAndWait);
+ alert.getDialogPane().setPrefHeight(300);
+ alert.getDialogPane().setPrefWidth(400);
+ alert.showAndWait();
}
}
diff --git a/src/main/java/drrename/Launcher.java b/src/main/java/drrename/Launcher.java
index d6fa6cbe..9cbe8bdb 100644
--- a/src/main/java/drrename/Launcher.java
+++ b/src/main/java/drrename/Launcher.java
@@ -1,5 +1,6 @@
package drrename;
+import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import drrename.ui.ResourceBundleAwareLazyFxControllerAndViewResolver;
import javafx.scene.Node;
import lombok.extern.slf4j.Slf4j;
@@ -9,6 +10,7 @@
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
@@ -16,6 +18,8 @@
import java.util.ResourceBundle;
@Slf4j
+@EnableFeignClients
+@EnableEncryptableProperties
@SpringBootApplication
public class Launcher {
diff --git a/src/main/java/drrename/MovieDbChecker.java b/src/main/java/drrename/MovieDbChecker.java
new file mode 100644
index 00000000..112d78eb
--- /dev/null
+++ b/src/main/java/drrename/MovieDbChecker.java
@@ -0,0 +1,110 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename;
+
+import drrename.config.TheMovieDbConfig;
+import drrename.kodi.nfo.MovieDbCheckType;
+import drrename.model.themoviedb.SearchResultDto;
+import drrename.model.themoviedb.TranslationDto;
+import drrename.model.themoviedb.TranslationsDto;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Scope;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.time.LocalDate;
+import java.util.*;
+
+@Getter
+@Setter
+@Slf4j
+@Component
+@Scope("prototype")
+public class MovieDbChecker {
+
+ private final MovieDbClient client;
+
+ private final TheMovieDbConfig config;
+
+ private final ResourceBundle resourceBundle;
+
+ private Set onlineTitles;
+
+ private String theMovieDbId;
+
+ public MovieDbChecker(MovieDbClient client, TheMovieDbConfig config, ResourceBundle resourceBundle) {
+ this.client = client;
+ this.config = config;
+ this.resourceBundle = resourceBundle;
+ }
+
+ protected void reset(){
+ this.onlineTitles = new LinkedHashSet<>();
+ this.theMovieDbId = null;
+ }
+
+ public MovieDbCheckType check(String searchString, Integer year) throws IOException {
+ reset();
+ var searchResult = client.searchMovie(config.getApiKey(), null, config.isIncludeAdult(), searchString, year);
+ ResponseEntity translatinos;
+ if(searchResult.getBody() != null && !searchResult.getBody().getResults().isEmpty()){
+ SearchResultDto firstResult = searchResult.getBody().getResults().get(0);
+ getOnlineTitles().add(buildNameString(firstResult.getTitle(), firstResult.getReleaseDate()));
+ getOnlineTitles().add(buildNameString(firstResult.getOriginalTitle(), firstResult.getReleaseDate()));
+ if(searchString.equals(firstResult.getTitle())){
+ theMovieDbId = firstResult.getPosterPath();
+ return MovieDbCheckType.ORIGINAL_TITEL;
+ }
+ if(searchString.equals(firstResult.getOriginalTitle())){
+ theMovieDbId = firstResult.getPosterPath();
+ return MovieDbCheckType.ORIGINAL_TITEL;
+ }
+ translatinos = client.getTranslations(firstResult.getId(), config.getApiKey());
+ if(translatinos.getBody() != null){
+ for(TranslationDto translationDto : translatinos.getBody().getTranslations()){
+ String iso1 = translationDto.getIso3166();
+ String iso2 = translationDto.getIso639();
+ String title = translationDto.getData().getTitle();
+ if(resourceBundle.getLocale().getLanguage().equals(iso1) || resourceBundle.getLocale().getLanguage().equals(iso2)){
+ getOnlineTitles().add(buildNameString(translationDto.getData().getTitle(), firstResult.getReleaseDate()));
+ }
+ if(searchString.equals(title)){
+ theMovieDbId = firstResult.getPosterPath();
+ return MovieDbCheckType.LOCALIZED_TITLE;
+ }
+ }
+ } else {
+ log.warn("Translations body is null");
+ }
+ }
+ return MovieDbCheckType.NOT_FOUND;
+ }
+
+ private String buildNameString(String title, LocalDate date) {
+ if(date == null){
+ return title;
+ }
+ return title + " (" + date.getYear() + ")";
+ }
+}
diff --git a/src/main/java/drrename/MovieDbClient.java b/src/main/java/drrename/MovieDbClient.java
new file mode 100644
index 00000000..400cb39f
--- /dev/null
+++ b/src/main/java/drrename/MovieDbClient.java
@@ -0,0 +1,39 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename;
+
+import drrename.model.themoviedb.SearchResultsDto;
+import drrename.model.themoviedb.TranslationsDto;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(value = "moviedb", url = "${app.kodi.themoviedb.baseurl}", configuration = MovieDbClientConfig.class)
+public interface MovieDbClient {
+
+ @RequestMapping(method = RequestMethod.GET, value = "/search/movie", produces = "application/json")
+ ResponseEntity searchMovie(@RequestParam(name = "api_key") String apiKey, @RequestParam(name = "langauge", required = false) String language, @RequestParam(name = "include_adult", required = false) Boolean includeAdult, @RequestParam(name = "query") String query, @RequestParam(name = "year") Number year);
+
+ @RequestMapping(method = RequestMethod.GET, value = "/movie/{id}/translations", produces = "application/json")
+ ResponseEntity getTranslations(@PathVariable(name = "id") Number id, @RequestParam(name = "api_key") String apiKey);
+}
diff --git a/src/main/java/drrename/MovieDbClientConfig.java b/src/main/java/drrename/MovieDbClientConfig.java
new file mode 100644
index 00000000..34884de5
--- /dev/null
+++ b/src/main/java/drrename/MovieDbClientConfig.java
@@ -0,0 +1,34 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.context.annotation.Bean;
+
+public class MovieDbClientConfig {
+
+ @Bean
+ ObjectMapper objectMapper(){
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ return mapper;
+ }
+}
diff --git a/src/main/java/drrename/MovieDbImagesClient.java b/src/main/java/drrename/MovieDbImagesClient.java
new file mode 100644
index 00000000..ea4d4826
--- /dev/null
+++ b/src/main/java/drrename/MovieDbImagesClient.java
@@ -0,0 +1,36 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename;
+
+import drrename.model.themoviedb.SearchResultsDto;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(value = "moviedb-images", url = "${app.kodi.themoviedb.images.baseurl}", configuration = MovieDbClientConfig.class)
+public interface MovieDbImagesClient {
+
+ @RequestMapping(method = RequestMethod.GET, value = "/w500/{poster_path}", produces = MediaType.IMAGE_JPEG_VALUE)
+ ResponseEntity searchMovie(@RequestParam(name = "api_key") String apiKey, @RequestParam(name = "langauge", required = false) String language, @RequestParam(name = "include_adult", required = false) Boolean includeAdult, @PathVariable(name = "poster_path") String posterPath);
+}
diff --git a/src/main/java/drrename/RenameUtil.java b/src/main/java/drrename/RenameUtil.java
index 2614e8c9..9c3ea4ae 100644
--- a/src/main/java/drrename/RenameUtil.java
+++ b/src/main/java/drrename/RenameUtil.java
@@ -1,27 +1,20 @@
package drrename;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.dataformat.xml.XmlMapper;
-import drrename.model.nfo.NfoFileXmlModel;
-import lombok.extern.slf4j.Slf4j;
-
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.stream.Collectors;
-@Slf4j
public class RenameUtil {
- public static Path getImagePathFromNfo(Path nfoFile) throws IOException {
- XmlMapper mapper = new XmlMapper();
- mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
- try {
- NfoFileXmlModel xmlFileContent = mapper.readValue(nfoFile.toFile(), NfoFileXmlModel.class);
- if(xmlFileContent.getArt() != null && xmlFileContent.getArt().getPoster() != null)
- return nfoFile.getParent().resolve(xmlFileContent.getArt().getPoster());
- } catch (JsonParseException e) {
- log.debug("Failed to deserialize image path from {})", nfoFile);
- }
- return null;
+ public static Path rename(final Path file, String newFileName) throws IOException {
+ return Files.move(file, file.resolveSibling(newFileName));
+ }
+
+ public static String stackTraceToString(Throwable e) {
+ return Arrays.stream(e.getStackTrace())
+ .map(StackTraceElement::toString)
+ .collect(Collectors.joining("\n"));
}
}
diff --git a/src/main/java/drrename/Strings.java b/src/main/java/drrename/Strings.java
new file mode 100644
index 00000000..3017a87a
--- /dev/null
+++ b/src/main/java/drrename/Strings.java
@@ -0,0 +1,51 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename;
+
+/**
+ * String helper functions.
+ *
+ * @author Gili Tzabari
+ */
+public final class Strings
+{
+ /**
+ * @param str a String
+ * @param prefix a prefix
+ * @return true if {@code start} starts with {@code prefix}, disregarding case sensitivity
+ */
+ public static boolean startsWithIgnoreCase(String str, String prefix)
+ {
+ return str.regionMatches(true, 0, prefix, 0, prefix.length());
+ }
+
+ public static boolean endsWithIgnoreCase(String str, String suffix)
+ {
+ int suffixLength = suffix.length();
+ return str.regionMatches(true, str.length() - suffixLength, suffix, 0, suffixLength);
+ }
+
+ /**
+ * Prevent construction.
+ */
+ private Strings()
+ {
+ }
+}
diff --git a/src/main/java/drrename/config/TheMovieDbConfig.java b/src/main/java/drrename/config/TheMovieDbConfig.java
new file mode 100644
index 00000000..d550ded6
--- /dev/null
+++ b/src/main/java/drrename/config/TheMovieDbConfig.java
@@ -0,0 +1,37 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "app.kodi.themoviedb")
+public class TheMovieDbConfig {
+
+ String apiKey;
+
+ String baseUrl;
+
+ boolean includeAdult;
+
+}
diff --git a/src/main/java/drrename/event/FilePreviewEvent.java b/src/main/java/drrename/event/FilePreviewEvent.java
index e6e39d7c..b0e4eb8e 100644
--- a/src/main/java/drrename/event/FilePreviewEvent.java
+++ b/src/main/java/drrename/event/FilePreviewEvent.java
@@ -19,10 +19,8 @@
package drrename.event;
-import drrename.model.RenamingEntry;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import drrename.model.RenamingControl;
-public record FilePreviewEvent(RenamingEntry renamingEntry) {
+public record FilePreviewEvent(RenamingControl renamingControl) {
}
diff --git a/src/main/java/drrename/event/FileRenamedEvent.java b/src/main/java/drrename/event/FileRenamedEvent.java
index 28b677ed..690d3d1e 100644
--- a/src/main/java/drrename/event/FileRenamedEvent.java
+++ b/src/main/java/drrename/event/FileRenamedEvent.java
@@ -19,7 +19,7 @@
package drrename.event;
-import drrename.model.RenamingEntry;
+import drrename.model.RenamingControl;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -33,9 +33,9 @@ public class FileRenamedEvent {
private final UUID uuid;
- private final List renamedEntries;
+ private final List renamedEntries;
- public FileRenamedEvent(UUID uuid, RenamingEntry renamedEntries) {
+ public FileRenamedEvent(UUID uuid, RenamingControl renamedEntries) {
this(uuid, Collections.singletonList(renamedEntries));
}
}
diff --git a/src/main/java/drrename/event/NewRenamingEntryEvent.java b/src/main/java/drrename/event/NewRenamingEntryEvent.java
index c1d5ca8a..5997bea9 100644
--- a/src/main/java/drrename/event/NewRenamingEntryEvent.java
+++ b/src/main/java/drrename/event/NewRenamingEntryEvent.java
@@ -19,7 +19,7 @@
package drrename.event;
-import drrename.model.RenamingEntry;
+import drrename.model.RenamingControl;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@@ -34,9 +34,9 @@ public class NewRenamingEntryEvent {
private final UUID uuid;
- private final List renamingEntries;
+ private final List renamingEntries;
- public NewRenamingEntryEvent(UUID uuid, RenamingEntry renamingEntries) {
+ public NewRenamingEntryEvent(UUID uuid, RenamingControl renamingEntries) {
this(uuid, Collections.singletonList(renamingEntries));
}
}
diff --git a/src/main/java/drrename/event/StageReadyEvent.java b/src/main/java/drrename/event/StageReadyEvent.java
index 2cb49025..f4586736 100644
--- a/src/main/java/drrename/event/StageReadyEvent.java
+++ b/src/main/java/drrename/event/StageReadyEvent.java
@@ -20,8 +20,6 @@
package drrename.event;
import javafx.stage.Stage;
-import lombok.Data;
-import lombok.RequiredArgsConstructor;
public record StageReadyEvent(Stage stage) {
diff --git a/src/main/java/drrename/event/StartingFileTypeEvent.java b/src/main/java/drrename/event/StartingFileTypeEvent.java
index 334b79af..113cc9b1 100644
--- a/src/main/java/drrename/event/StartingFileTypeEvent.java
+++ b/src/main/java/drrename/event/StartingFileTypeEvent.java
@@ -1,6 +1,5 @@
package drrename.event;
-import java.util.Objects;
import java.util.UUID;
public class StartingFileTypeEvent extends SynchronousUuidEvent {
diff --git a/src/main/java/drrename/event/StartingListFilesEvent.java b/src/main/java/drrename/event/StartingListFilesEvent.java
index bee4ea1a..8ddb4bd7 100644
--- a/src/main/java/drrename/event/StartingListFilesEvent.java
+++ b/src/main/java/drrename/event/StartingListFilesEvent.java
@@ -19,8 +19,6 @@
package drrename.event;
-import lombok.Data;
-
import java.util.UUID;
public class StartingListFilesEvent extends SynchronousUuidEvent {
diff --git a/src/main/java/drrename/event/SynchronousUuidEvent.java b/src/main/java/drrename/event/SynchronousUuidEvent.java
index d405c69e..cd00150f 100644
--- a/src/main/java/drrename/event/SynchronousUuidEvent.java
+++ b/src/main/java/drrename/event/SynchronousUuidEvent.java
@@ -22,7 +22,6 @@
import lombok.Data;
import lombok.RequiredArgsConstructor;
-import java.util.Objects;
import java.util.UUID;
@RequiredArgsConstructor
diff --git a/src/main/java/drrename/filecreator/DummyFileCreatorController.java b/src/main/java/drrename/filecreator/DummyFileCreatorController.java
index 3ce709af..517255b9 100644
--- a/src/main/java/drrename/filecreator/DummyFileCreatorController.java
+++ b/src/main/java/drrename/filecreator/DummyFileCreatorController.java
@@ -19,10 +19,10 @@
package drrename.filecreator;
-import drrename.ui.mainview.GoCancelButtonsComponentController;
-import drrename.ui.mainview.StartDirectoryComponentController;
import drrename.event.DummyFileCreatorButtonCancelEvent;
import drrename.event.DummyFileCreatorButtonGoEvent;
+import drrename.ui.mainview.GoCancelButtonsComponentController;
+import drrename.ui.mainview.StartDirectoryComponentController;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
@@ -36,13 +36,10 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.rgielen.fxweaver.core.FxmlView;
-import org.springframework.context.ApplicationEvent;
-import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.net.URL;
-import java.nio.file.Path;
import java.util.ResourceBundle;
@RequiredArgsConstructor
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/NfoCheckResultTreeItemContent.java b/src/main/java/drrename/kodi/FixFailedException.java
similarity index 59%
rename from src/main/java/drrename/kodi/treeitem/content/check/NfoCheckResultTreeItemContent.java
rename to src/main/java/drrename/kodi/FixFailedException.java
index 0c3c7699..b7ef0637 100644
--- a/src/main/java/drrename/kodi/treeitem/content/check/NfoCheckResultTreeItemContent.java
+++ b/src/main/java/drrename/kodi/FixFailedException.java
@@ -17,21 +17,26 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content.check;
+package drrename.kodi;
-public class NfoCheckResultTreeItemContent extends CheckResultTreeItemContent {
+public class FixFailedException extends Exception {
- private boolean missingNfoIsAWarning;
+ public FixFailedException() {
+ }
+
+ public FixFailedException(String message) {
+ super(message);
+ }
- public NfoCheckResultTreeItemContent(T checkResult) {
- super(checkResult);
+ public FixFailedException(String message, Throwable cause) {
+ super(message, cause);
}
- public boolean isMissingNfoIsAWarning() {
- return missingNfoIsAWarning;
+ public FixFailedException(Throwable cause) {
+ super(cause);
}
- public void setMissingNfoIsAWarning(boolean missingNfoIsAWarning) {
- this.missingNfoIsAWarning = missingNfoIsAWarning;
+ public FixFailedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
}
}
diff --git a/src/main/java/drrename/kodi/treeitem/KodiTreeRootItem.java b/src/main/java/drrename/kodi/KodiRootTreeItem.java
similarity index 67%
rename from src/main/java/drrename/kodi/treeitem/KodiTreeRootItem.java
rename to src/main/java/drrename/kodi/KodiRootTreeItem.java
index d05839ff..2b6e44be 100644
--- a/src/main/java/drrename/kodi/treeitem/KodiTreeRootItem.java
+++ b/src/main/java/drrename/kodi/KodiRootTreeItem.java
@@ -17,16 +17,20 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem;
+package drrename.kodi;
-import drrename.kodi.treeitem.content.KodiTreeItemContent;
-import drrename.kodi.treeitem.content.KodiRootTreeItemContent;
-import drrename.ui.FilterableTreeItem;
+import javafx.scene.control.TreeView;
-public class KodiTreeRootItem extends FilterableTreeItem {
+import java.util.concurrent.Executor;
- public KodiTreeRootItem() {
- super(new KodiRootTreeItemContent());
- getValue().setTreeItem(this);
+/**
+ * The root value of the Kodi {@link TreeView}.
+ *
+ * @see KodiRootTreeItemValue
+ */
+public class KodiRootTreeItem extends KodiTreeItem {
+
+ public KodiRootTreeItem(Executor executor) {
+ super(new KodiRootTreeItemValue(executor));
}
}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/CheckResultTreeItemContent.java b/src/main/java/drrename/kodi/KodiRootTreeItemValue.java
similarity index 54%
rename from src/main/java/drrename/kodi/treeitem/content/check/CheckResultTreeItemContent.java
rename to src/main/java/drrename/kodi/KodiRootTreeItemValue.java
index 5cb70179..5707e3e4 100644
--- a/src/main/java/drrename/kodi/treeitem/content/check/CheckResultTreeItemContent.java
+++ b/src/main/java/drrename/kodi/KodiRootTreeItemValue.java
@@ -17,36 +17,40 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content.check;
+package drrename.kodi;
-import drrename.kodi.treeitem.content.KodiTreeItemContent;
-import lombok.RequiredArgsConstructor;
+import java.util.concurrent.Executor;
-import java.util.Objects;
-
-@RequiredArgsConstructor
-public class CheckResultTreeItemContent extends KodiTreeItemContent {
+/**
+ * {@link KodiRootTreeItem}'s value.
+ *
+ * @see KodiRootTreeItem
+ */
+public class KodiRootTreeItemValue extends KodiTreeItemValue {
- private final T checkResult;
+ public KodiRootTreeItemValue(Executor executor) {
+ super(null, false, executor);
+ setMessage("Analysis");
+ setGraphic(null);
+ }
- public T getCheckResult() {
- return checkResult;
+ @Override
+ protected String updateMessage(Boolean newValue) {
+ return null;
}
@Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof CheckResultTreeItemContent> that)) return false;
- return checkResult.equals(that.checkResult);
+ protected String updateIdentifier() {
+ return null;
}
@Override
- public int hashCode() {
- return Objects.hash(checkResult);
+ public void fix() throws FixFailedException {
+ throw new IllegalStateException("Cannot fix");
}
@Override
- public String toString() {
- return checkResult.toString();
+ protected void updateStatus() {
+ // nothing to update
}
}
diff --git a/src/main/java/drrename/kodi/KodiToolsController.java b/src/main/java/drrename/kodi/KodiToolsController.java
index 726bf714..723eac69 100644
--- a/src/main/java/drrename/kodi/KodiToolsController.java
+++ b/src/main/java/drrename/kodi/KodiToolsController.java
@@ -1,11 +1,7 @@
package drrename.kodi;
-import drrename.RenameUtil;
-import drrename.kodi.treeitem.content.check.NfoCheckResultTreeItemContent;
-import drrename.kodi.treeitem.KodiTreeRootItem;
-import drrename.kodi.treeitem.MovieTreeItemFactory;
-import drrename.kodi.treeitem.content.KodiTreeItemContent;
-import drrename.kodi.treeitem.content.MovieTreeItemContent;
+import drrename.kodi.nfo.NfoFileTreeItemValue;
+import drrename.model.RenamingPath;
import drrename.ui.FXUtil;
import drrename.ui.mainview.GoCancelButtonsComponentController;
import drrename.ui.mainview.StartDirectoryComponentController;
@@ -51,7 +47,7 @@ public class KodiToolsController implements Initializable {
public ProgressBar progressBar;
- public TreeView treeView;
+ public TreeView treeView;
public Button buttonExpandAll;
@@ -75,10 +71,12 @@ public class KodiToolsController implements Initializable {
private final Executor executor;
- private KodiTreeRootItem treeRoot;
+ private KodiRootTreeItem treeRoot;
private final MovieTreeItemFactory movieTreeItemFactory;
+ private WarningsConfig warningsConfig;
+
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
mainStage = new Stage();
@@ -91,11 +89,11 @@ public void initialize(URL url, ResourceBundle resourceBundle) {
goCancelButtonsComponentController.setButtonGoActionEventFactory(KodiToolsButtonGoEvent::new);
progressBar.visibleProperty().bind(service.runningProperty());
- treeRoot = new KodiTreeRootItem();
+ treeRoot = new KodiRootTreeItem(executor);
treeView.setRoot(treeRoot);
buttonExpandAll.setDisable(true);
buttonCollapseAll.setDisable(true);
- treeRoot.getChildren().addListener((ListChangeListener super TreeItem>) e -> {
+ treeRoot.getChildren().addListener((ListChangeListener super TreeItem>) e -> {
buttonExpandAll.setDisable(e.getList().isEmpty());
buttonCollapseAll.setDisable(e.getList().isEmpty());
});
@@ -106,34 +104,7 @@ public void initialize(URL url, ResourceBundle resourceBundle) {
onButtonGoEvent(null);
}
});
- treeView.setCellFactory(tv -> new TreeCell<>() {
-
- @Override
- protected void updateItem(KodiTreeItemContent item, boolean empty) {
- super.updateItem(item, empty);
- if (item == null) {
- setText(null);
- setStyle(null);
- } else {
- setText(item.toString());
- List styles = new ArrayList<>();
- if (item.hasWarning()) {
- if (item instanceof MovieTreeItemContent) {
- styles.add("-fx-font-size: 13;");
- }
- styles.add("-fx-font-weight: bold;");
- styles.add("-fx-background-color: wheat;");
- var joinedStylesString = String.join(" ", styles);
- setStyle(joinedStylesString);
- } else {
- if (item instanceof MovieTreeItemContent) {
- styles.add("-fx-font-size: 14;");
- } else
- setStyle(null);
- }
- }
- }
- });
+ treeView.setCellFactory(this::treeViewCellFactoryCallback);
treeView.getSelectionModel().getSelectedIndices().addListener((ListChangeListener) c -> {
imageStage.close();
@@ -143,19 +114,26 @@ protected void updateItem(KodiTreeItemContent item, boolean empty) {
}
var hans = treeView.getTreeItem(c.getAddedSubList().get(0)).getValue();
log.debug("Selection changed: {} ({})", hans, hans.getClass());
- if (hans instanceof NfoCheckResultTreeItemContent> peter) {
+ if (hans instanceof NfoFileTreeItemValue peter) {
log.debug("Handling {}", peter);
- Path nfoFile = peter.getCheckResult().getNfoFile();
- executor.execute(() -> showImage(nfoFile));
+ Path nfoFile = peter.getNfoFile();
+ executor.execute(() -> showImage(nfoFile));
}
}
});
+
+ warningsConfig = new WarningsConfig();
+ warningsConfig.missingNfoFileIsWarningProperty().bind(checkBoxMissingNfoFileIsAWarning.selectedProperty());
+ }
+
+ private TreeCell treeViewCellFactoryCallback(TreeView kodiTreeItemContentTreeView) {
+ return new KodiTreeCell(treeView);
}
private void showImage(Path nfoFile) {
if (nfoFile != null && Files.exists(nfoFile) && Files.isReadable(nfoFile)) {
try {
- Path imagePath = RenameUtil.getImagePathFromNfo(nfoFile);
+ Path imagePath = KodiUtil.getImagePathFromNfo(nfoFile);
if (imagePath != null && Files.exists(imagePath) && Files.isReadable(imagePath)) {
log.debug("Taking a look at {}", imagePath);
Image image = new Image(imagePath.toFile().toURI().toString(), false);
@@ -190,13 +168,13 @@ private void updateTreeRootPredicate() {
Platform.runLater(() -> treeRoot.setPredicate(buildHideEmptyPredicate()));
}
- private Predicate buildHideEmptyPredicate() {
+ private Predicate buildHideEmptyPredicate() {
return item -> {
- if(item instanceof NfoCheckResultTreeItemContent> anotherItem)
- anotherItem.setMissingNfoIsAWarning(checkBoxMissingNfoFileIsAWarning.isSelected());
- if (checkBoxHideEmpty.isSelected())
- return item.hasWarning();
- return true;
+ var nfoFileIsWarning = checkBoxMissingNfoFileIsAWarning.isSelected();
+ if(item instanceof NfoFileTreeItemValue item2){
+ item2.setMissingNfoFileIsWarning(nfoFileIsWarning);
+ }
+ return item.isWarning() || !checkBoxHideEmpty.isSelected();
};
}
@@ -239,11 +217,11 @@ private void handleResult(WorkerStateEvent workerStateEvent) {
}
}
- private List> buildAndFillLevel1Items(List movieFolders) {
- List> result = new ArrayList<>();
+ private List> buildAndFillLevel1Items(List movieFolders) {
+ List> result = new ArrayList<>();
- for(Path moviePath : movieFolders){
- var item = movieTreeItemFactory.buildNew(moviePath);
+ for (Path moviePath : movieFolders) {
+ var item = movieTreeItemFactory.buildNew(new RenamingPath(moviePath), warningsConfig);
result.add(item);
}
diff --git a/src/main/java/drrename/kodi/KodiTreeCell.java b/src/main/java/drrename/kodi/KodiTreeCell.java
new file mode 100644
index 00000000..9672b257
--- /dev/null
+++ b/src/main/java/drrename/kodi/KodiTreeCell.java
@@ -0,0 +1,54 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import javafx.beans.binding.Bindings;
+import javafx.scene.Node;
+import javafx.scene.control.Control;
+import javafx.scene.control.TreeCell;
+
+public class KodiTreeCell extends TreeCell {
+
+ public KodiTreeCell(Control treeView) {
+ prefWidthProperty().bind(treeView.widthProperty().subtract(20.0));
+ }
+
+ @Override
+ protected void updateItem(KodiTreeItemValue item, boolean empty) {
+
+ super.updateItem(item, empty);
+ if (item == null) {
+ textProperty().unbind();
+ styleProperty().unbind();
+ graphicProperty().unbind();
+ setText(null);
+ setStyle(null);
+ setGraphic(null);
+ } else {
+ graphicProperty().bind(item.graphicProperty());
+ textProperty().bind(Bindings.createStringBinding(() -> calculateMessageString(item), item.messageProperty()));
+ styleProperty().bind(item.styleProperty());
+ }
+ }
+
+ private String calculateMessageString(KodiTreeItemValue item) {
+ return (item.getIdentifer() != null ? item.getIdentifer() + ": " : "") + item.getMessage();
+ }
+}
diff --git a/src/main/java/drrename/kodi/treeitem/KodiTreeItem.java b/src/main/java/drrename/kodi/KodiTreeItem.java
similarity index 70%
rename from src/main/java/drrename/kodi/treeitem/KodiTreeItem.java
rename to src/main/java/drrename/kodi/KodiTreeItem.java
index dfe0b415..f93434f3 100644
--- a/src/main/java/drrename/kodi/treeitem/KodiTreeItem.java
+++ b/src/main/java/drrename/kodi/KodiTreeItem.java
@@ -17,24 +17,27 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem;
+package drrename.kodi;
-import drrename.kodi.treeitem.content.KodiTreeItemContent;
import drrename.ui.FilterableTreeItem;
+import javafx.beans.Observable;
import javafx.scene.control.TreeItem;
+import lombok.extern.slf4j.Slf4j;
-public class KodiTreeItem extends FilterableTreeItem {
+@Slf4j
+public class KodiTreeItem extends FilterableTreeItem {
- public KodiTreeItem(KodiTreeItemContent value) {
+ public KodiTreeItem(KodiTreeItemValue value) {
super(value);
- getValue().setTreeItem(this);
+ value.setTreeItem(this);
+ graphicProperty().bind(value.graphicProperty());
}
- public void add(KodiTreeItem childItem) {
- getSourceChildren().add(childItem);
+ protected Observable[] getExtractorCallback(TreeItem item) {
+ return new Observable[]{item.getValue().getRenamingPath().movieNameProperty(), item.getValue().warningProperty()};
}
- public boolean contains(KodiTreeItem childItem) {
- return getSourceChildren().stream().map(TreeItem::getValue).anyMatch(v -> v.equals(childItem.getValue()));
+ public void add(KodiTreeItem childItem) {
+ getSourceChildren().add(childItem);
}
}
diff --git a/src/main/java/drrename/kodi/KodiTreeItemValue.java b/src/main/java/drrename/kodi/KodiTreeItemValue.java
new file mode 100644
index 00000000..5a040898
--- /dev/null
+++ b/src/main/java/drrename/kodi/KodiTreeItemValue.java
@@ -0,0 +1,289 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.model.RenamingPath;
+import javafx.application.Platform;
+import javafx.beans.property.*;
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.control.TreeItem;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+
+/**
+ * Base class for all {@link KodiTreeItem} values.
+ *
+ * @see KodiTreeItem
+ */
+@Slf4j
+public abstract class KodiTreeItemValue {
+
+ private static final String warning_font = "-fx-font-weight: bold;";
+
+ private static final String warning_color = "-fx-background-color: wheat;";
+
+ private final ListProperty styles;
+
+ private final StringProperty style;
+
+ private final StringProperty buttonText;
+
+ private final BooleanProperty canFix;
+
+ private final ObjectProperty warning;
+
+ private final StringProperty message;
+
+ private final StringProperty identifer;
+
+ private final ObjectProperty graphic;
+
+ private final boolean fixable;
+
+ private final WarningsConfig warningsConfig;
+
+ private final RenamingPath renamingPath;
+
+ private final ObjectProperty treeItem;
+
+ private final Executor executor;
+
+ public KodiTreeItemValue(RenamingPath moviePath, boolean fixable, Executor executor) {
+ this.renamingPath = moviePath;
+ this.fixable = fixable;
+ this.executor = executor;
+ this.buttonText = new SimpleStringProperty();
+ this.canFix = new SimpleBooleanProperty();
+ this.styles = new SimpleListProperty<>(FXCollections.observableArrayList());
+ this.style = new SimpleStringProperty();
+ this.warning = new SimpleObjectProperty<>();
+ this.message = new SimpleStringProperty();
+ this.graphic = new SimpleObjectProperty<>();
+ this.treeItem = new SimpleObjectProperty<>();
+ this.warningsConfig = new WarningsConfig();
+ this.identifer = new SimpleStringProperty();
+ init();
+ }
+
+ private void init() {
+ getStyles().addListener((ListChangeListener) c -> {
+ while (c.next()) {
+ setStyle(String.join(" ", c.getList()));
+ }
+ });
+ canFixProperty().addListener((observable, oldValue, newValue) -> updateButtonText());
+ warningProperty().addListener((observable, oldValue, newValue) -> {
+ updateStyles(newValue);
+ updateButtonText();
+ setMessage(updateMessage(newValue));
+ });
+ setGraphic(buildGraphic());
+ setIdentifer(updateIdentifier());
+ }
+
+ protected abstract String updateMessage(Boolean newValue);
+
+
+ public abstract void fix() throws FixFailedException;
+
+ protected abstract String updateIdentifier();
+
+ protected void performFix() {
+
+ executor.execute(() -> {
+ try {
+ fix();
+ Platform.runLater(() -> updateStatus());
+ } catch (FixFailedException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ protected abstract void updateStatus();
+
+ protected void updateButtonText() {
+ updateButtonText(isCanFix(), isWarning());
+ }
+
+ protected void updateButtonText(boolean canFix, boolean isWarning) {
+ if (canFix) {
+ buttonText.set("Fix");
+ } else if (isWarning) {
+ buttonText.set("Fix manually");
+ } else {
+ buttonText.set("OK");
+ }
+ }
+
+ protected void updateStyles(Boolean warning) {
+ if (warning) {
+ styles.add(warning_font);
+ styles.add(warning_color);
+ } else {
+ styles.remove(warning_font);
+ styles.remove(warning_color);
+ }
+ }
+
+ protected Node buildGraphic() {
+ Button button = new Button();
+ button.textProperty().bind(buttonText);
+ button.disableProperty().bind(canFixProperty().not());
+ button.setOnAction(actionEvent -> {
+ performFix();
+ });
+ return button;
+ }
+
+ public boolean contains(KodiTreeItem childItem) {
+ return getTreeItem() != null && new ArrayList<>(getTreeItem().getSourceChildren()).stream().map(TreeItem::getValue).anyMatch(v -> v.equals(childItem.getValue()));
+ }
+
+ // Getter / Setter //
+
+
+ public KodiTreeItem getTreeItem() {
+ return treeItem.get();
+ }
+
+ public ObjectProperty treeItemProperty() {
+ return treeItem;
+ }
+
+ public void setTreeItem(KodiTreeItem treeItem) {
+ this.treeItem.set(treeItem);
+ }
+
+ public String getMessage() {
+ return message.get();
+ }
+
+ public StringProperty messageProperty() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message.set(message);
+ }
+
+ public boolean isWarning() {
+ return warning.get();
+ }
+
+ public ObjectProperty warningProperty() {
+ return warning;
+ }
+
+ public void setWarning(boolean warning) {
+ this.warning.set(warning);
+ }
+
+ public boolean isCanFix() {
+ return canFix.get();
+ }
+
+ public BooleanProperty canFixProperty() {
+ return canFix;
+ }
+
+ public void setCanFix(boolean canFix) {
+ this.canFix.set(canFix);
+ }
+
+ public boolean isFixable() {
+ return fixable;
+ }
+
+ public String getStyle() {
+ return style.get();
+ }
+
+ public StringProperty styleProperty() {
+ return style;
+ }
+
+ public void setStyle(String style) {
+ this.style.set(style);
+ }
+
+ protected ObservableList getStyles() {
+ return styles.get();
+ }
+
+ protected ListProperty stylesProperty() {
+ return styles;
+ }
+
+ protected void setStyles(ObservableList styles) {
+ this.styles.set(styles);
+ }
+
+ public RenamingPath getRenamingPath() {
+ return renamingPath;
+ }
+
+
+ public String getButtonText() {
+ return buttonText.get();
+ }
+
+ public StringProperty buttonTextProperty() {
+ return buttonText;
+ }
+
+ public void setButtonText(String buttonText) {
+ this.buttonText.set(buttonText);
+ }
+
+ public Node getGraphic() {
+ return graphic.get();
+ }
+
+ public ObjectProperty graphicProperty() {
+ return graphic;
+ }
+
+ public void setGraphic(Node graphic) {
+ this.graphic.set(graphic);
+ }
+
+ public WarningsConfig getWarningsConfig() {
+ return warningsConfig;
+ }
+
+ public String getIdentifer() {
+ return identifer.get();
+ }
+
+ public StringProperty identiferProperty() {
+ return identifer;
+ }
+
+ public void setIdentifer(String identifer) {
+ this.identifer.set(identifer);
+ }
+}
diff --git a/src/main/java/drrename/kodi/KodiUtil.java b/src/main/java/drrename/kodi/KodiUtil.java
new file mode 100644
index 00000000..6be4e8ca
--- /dev/null
+++ b/src/main/java/drrename/kodi/KodiUtil.java
@@ -0,0 +1,62 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import drrename.model.nfo.NfoFileXmlModel;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+@Slf4j
+public class KodiUtil {
+
+ public static String getMovieNameFromDirectoryName(String directoryName){
+ if(directoryName.contains("(")) {
+ return directoryName.substring(0, directoryName.indexOf("(")).trim();
+ }
+ return directoryName;
+ }
+
+ public static Integer getMovieYearFromDirectoryName(String directoryName) {
+ if(directoryName.contains("(")) {
+ return Integer.parseInt(directoryName.substring(directoryName.indexOf("(")+1, directoryName.indexOf(")")).trim());
+ }
+ return null;
+ }
+
+ public static Path getImagePathFromNfo(Path nfoFile) throws IOException {
+ XmlMapper mapper = new XmlMapper();
+ mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ try {
+ NfoFileXmlModel xmlFileContent = mapper.readValue(nfoFile.toFile(), NfoFileXmlModel.class);
+ if(xmlFileContent.getArt() != null && xmlFileContent.getArt().getPoster() != null)
+ return nfoFile.getParent().resolve(xmlFileContent.getArt().getPoster());
+ } catch (JsonParseException e) {
+ log.debug("Failed to deserialize image path from {})", nfoFile);
+ }
+ return null;
+ }
+
+
+}
diff --git a/src/main/java/drrename/kodi/MovieDbClientFactory.java b/src/main/java/drrename/kodi/MovieDbClientFactory.java
new file mode 100644
index 00000000..33b7f7a3
--- /dev/null
+++ b/src/main/java/drrename/kodi/MovieDbClientFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.MovieDbChecker;
+import drrename.MovieDbClient;
+import drrename.MovieDbImagesClient;
+import drrename.config.TheMovieDbConfig;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import java.util.ResourceBundle;
+
+@Component
+public class MovieDbClientFactory {
+
+ private final MovieDbClient client;
+
+ private final MovieDbImagesClient imagesClient;
+
+ private final TheMovieDbConfig config;
+
+ private final ResourceBundle resourceBundle;
+
+ public MovieDbClientFactory(MovieDbClient client, MovieDbImagesClient imagesClient, TheMovieDbConfig config, ResourceBundle resourceBundle) {
+ this.client = client;
+ this.imagesClient = imagesClient;
+ this.config = config;
+ this.resourceBundle = resourceBundle;
+ }
+
+ @Bean
+ @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+ public MovieDbChecker getNewMovieDbChecker() {
+ return new MovieDbChecker(client, config, resourceBundle);
+ }
+
+ public MovieDbImagesClient getImagesClient() {
+ return imagesClient;
+ }
+
+ public TheMovieDbConfig getConfig() {
+ return config;
+ }
+}
diff --git a/src/main/java/drrename/kodi/MovieFileNameChecker.java b/src/main/java/drrename/kodi/MovieFileNameChecker.java
new file mode 100644
index 00000000..7704993c
--- /dev/null
+++ b/src/main/java/drrename/kodi/MovieFileNameChecker.java
@@ -0,0 +1,77 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.mime.FileTypeByMimeProvider;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+@Getter
+@Setter
+@Slf4j
+public class MovieFileNameChecker {
+
+ private List mediaFiles;
+
+ public MovieFileNameType checkDir(Path directory) {
+ String movieName = directory.getFileName().toString();
+ try {
+ setMediaFiles(findAllMediaFiles(directory));
+ for(Path mediaFile : mediaFiles){
+ String baseName = FilenameUtils.getBaseName(mediaFile.getFileName().toString());
+ if(baseName.startsWith(movieName)){
+ return MovieFileNameType.MATCHES_DIR_NAME;
+ }
+ }
+ if(!mediaFiles.isEmpty()){
+ return MovieFileNameType.INVALID_MEDIA_FILE_NAME;
+ }
+ } catch (IOException e) {
+ log.error(e.getLocalizedMessage(), e);
+ return MovieFileNameType.EXCEPTION;
+
+ }
+ return MovieFileNameType.NO_MEDIA_FILES_FOUND;
+ }
+
+ private List findAllMediaFiles(Path directory) throws IOException {
+ List result = new ArrayList<>();
+ try (DirectoryStream ds = Files.newDirectoryStream(directory)) {
+ for (Path child : ds) {
+ if(Files.isRegularFile(child)){
+ var mediaType = new FileTypeByMimeProvider().getFileType(child);
+ if(mediaType.startsWith("video")){
+ result.add(child.getFileName());
+ }
+ }
+ }
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/drrename/kodi/MovieFileNameTreeItemValue.java b/src/main/java/drrename/kodi/MovieFileNameTreeItemValue.java
new file mode 100644
index 00000000..d29c23b4
--- /dev/null
+++ b/src/main/java/drrename/kodi/MovieFileNameTreeItemValue.java
@@ -0,0 +1,90 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.model.RenamingPath;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+
+import java.util.concurrent.Executor;
+
+public class MovieFileNameTreeItemValue extends KodiTreeItemValue {
+
+ private final ObjectProperty type;
+
+ private final MovieFileNameChecker checker;
+
+ public MovieFileNameTreeItemValue(RenamingPath path, Executor executor) {
+ super(path, true, executor);
+ this.type = new SimpleObjectProperty<>();
+ checker = new MovieFileNameChecker();
+ updateStatus();
+
+ }
+
+ @Override
+ protected String updateMessage(Boolean newValue) {
+ if (getType() == null) {
+ return "unknown";
+ }
+ if (newValue) {
+ return getType().toString() + (checker.getMediaFiles().isEmpty() ? "" : getWarningAdditionalInfo());
+ }
+ return (getType().toString());
+ }
+
+ private String getWarningAdditionalInfo() {
+ return ": " + checker.getMediaFiles();
+ }
+
+ @Override
+ public void fix() throws FixFailedException {
+ throw new IllegalStateException("Cannot fix");
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return "Movie File Name";
+ }
+
+ @Override
+ protected void updateStatus() {
+ setType(checker.checkDir(getRenamingPath().getOldPath()));
+ setWarning(calculateWarning());
+ }
+
+ private boolean calculateWarning() {
+ return getType().isWarning();
+ }
+
+ // Getter / Setter //
+
+ public MovieFileNameType getType() {
+ return type.get();
+ }
+
+ public ObjectProperty typeProperty() {
+ return type;
+ }
+
+ public void setType(MovieFileNameType type) {
+ this.type.set(type);
+ }
+}
diff --git a/src/main/java/drrename/kodi/MovieFileNameType.java b/src/main/java/drrename/kodi/MovieFileNameType.java
new file mode 100644
index 00000000..fd86300b
--- /dev/null
+++ b/src/main/java/drrename/kodi/MovieFileNameType.java
@@ -0,0 +1,54 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+public enum MovieFileNameType {
+ MATCHES_DIR_NAME("Media file name matches directory name"), EXCEPTION("Failed to get media names"){
+ @Override
+ boolean isWarning() {
+ return true;
+ }
+ }, NO_MEDIA_FILES_FOUND("No media files found"){
+ @Override
+ boolean isWarning() {
+ return true;
+ }
+ }, INVALID_MEDIA_FILE_NAME("Invalid media file name"){
+ @Override
+ boolean isWarning() {
+ return true;
+ }
+ };
+
+ private final String name;
+
+ MovieFileNameType(String name){
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ boolean isWarning(){
+ return false;
+ }
+}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/NfoCheckResult.java b/src/main/java/drrename/kodi/MovieTreeItem.java
similarity index 77%
rename from src/main/java/drrename/kodi/treeitem/content/check/NfoCheckResult.java
rename to src/main/java/drrename/kodi/MovieTreeItem.java
index e75b33cf..9856000f 100644
--- a/src/main/java/drrename/kodi/treeitem/content/check/NfoCheckResult.java
+++ b/src/main/java/drrename/kodi/MovieTreeItem.java
@@ -17,15 +17,13 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content.check;
+package drrename.kodi;
-import java.nio.file.Path;
+public class MovieTreeItem extends KodiTreeItem {
-public abstract class NfoCheckResult extends CheckResult {
-
- public NfoCheckResult(String result) {
- super(result);
+ public MovieTreeItem(MovieTreeItemValue content) {
+ super(content);
}
- public abstract Path getNfoFile();
+
}
diff --git a/src/main/java/drrename/kodi/treeitem/MovieTreeItemFactory.java b/src/main/java/drrename/kodi/MovieTreeItemFactory.java
similarity index 64%
rename from src/main/java/drrename/kodi/treeitem/MovieTreeItemFactory.java
rename to src/main/java/drrename/kodi/MovieTreeItemFactory.java
index bfd08e93..9669824e 100644
--- a/src/main/java/drrename/kodi/treeitem/MovieTreeItemFactory.java
+++ b/src/main/java/drrename/kodi/MovieTreeItemFactory.java
@@ -17,14 +17,15 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem;
+package drrename.kodi;
-import drrename.kodi.treeitem.content.check.CheckServiceProvider;
+import drrename.kodi.checkservice.CheckServiceProvider;
+import drrename.model.RenamingPath;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
-import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.concurrent.Executor;
@Slf4j
@@ -36,12 +37,13 @@ public class MovieTreeItemFactory {
private final CheckServiceProvider checkServiceProvider;
- public MovieTreeItem buildNew(Path moviePath){
- return triggerNfoFileNameCheck(new MovieTreeItem(moviePath));
+ public MovieTreeItem buildNew(RenamingPath moviePath, WarningsConfig warningsConfig) {
+ return triggerChecks(new MovieTreeItem(new MovieTreeItemValue(moviePath, executor)), warningsConfig);
}
- private MovieTreeItem triggerNfoFileNameCheck(MovieTreeItem movieTreeItem) {
- executor.execute(() -> checkServiceProvider.getCheckServices().forEach(e -> e.addChildItem(movieTreeItem)));
+ private MovieTreeItem triggerChecks(MovieTreeItem movieTreeItem, WarningsConfig warningsConfig) {
+ var listCopy = new ArrayList<>(checkServiceProvider.getCheckServices());
+ executor.execute(() -> listCopy.forEach(e -> e.addChildItem(movieTreeItem, warningsConfig, executor)));
return movieTreeItem;
}
}
diff --git a/src/main/java/drrename/kodi/MovieTreeItemValue.java b/src/main/java/drrename/kodi/MovieTreeItemValue.java
new file mode 100644
index 00000000..f2d2ca60
--- /dev/null
+++ b/src/main/java/drrename/kodi/MovieTreeItemValue.java
@@ -0,0 +1,73 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.model.RenamingPath;
+import javafx.beans.binding.Bindings;
+import javafx.scene.control.TreeItem;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.concurrent.Executor;
+
+@Slf4j
+public class MovieTreeItemValue extends KodiTreeItemValue {
+
+ public MovieTreeItemValue(RenamingPath moviePath, Executor executor) {
+ super(moviePath, false, executor);
+ moviePath.movieNameProperty().addListener((observableValue, s, t1) -> setMessage(t1));
+ treeItemProperty().addListener((observable, oldValue, newValue) -> {
+ if (newValue != null) {
+ initWarning(newValue);
+ } else {
+ warningProperty().unbind();
+ }
+ });
+ setMessage(moviePath.getMovieName());
+ setGraphic(null);
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return null;
+ }
+
+ @Override
+ protected void updateStatus() {
+ // message is updated via binding to movie name property
+ }
+
+ @Override
+ protected String updateMessage(Boolean newValue) {
+ return getRenamingPath().getMovieName();
+ }
+
+ @Override
+ public void fix() throws FixFailedException {
+ throw new IllegalStateException("Cannot fix");
+ }
+
+ protected void initWarning(KodiTreeItem treeItem) {
+ warningProperty().bind(Bindings.createBooleanBinding(() -> calculateWarning(treeItem), treeItem.getSourceChildren()));
+ }
+
+ protected boolean calculateWarning(KodiTreeItem treeItem) {
+ return treeItem.getSourceChildren().stream().map(TreeItem::getValue).anyMatch(KodiTreeItemValue::isWarning);
+ }
+}
diff --git a/src/main/java/drrename/kodi/MultipleSpacesService.java b/src/main/java/drrename/kodi/MultipleSpacesService.java
new file mode 100644
index 00000000..8a7a3edf
--- /dev/null
+++ b/src/main/java/drrename/kodi/MultipleSpacesService.java
@@ -0,0 +1,33 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.kodi.checkservice.CheckService;
+import drrename.model.RenamingPath;
+
+import java.util.concurrent.Executor;
+
+public class MultipleSpacesService extends CheckService {
+
+ @Override
+ public MultipleSpacesTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ return new MultipleSpacesTreeItemValue(path, executor);
+ }
+}
diff --git a/src/main/java/drrename/kodi/MultipleSpacesTreeItemValue.java b/src/main/java/drrename/kodi/MultipleSpacesTreeItemValue.java
new file mode 100644
index 00000000..0d23a2ca
--- /dev/null
+++ b/src/main/java/drrename/kodi/MultipleSpacesTreeItemValue.java
@@ -0,0 +1,68 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.model.RenamingPath;
+import drrename.strategy.RegexReplaceRenamingStrategy;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.concurrent.Executor;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@Slf4j
+public class MultipleSpacesTreeItemValue extends KodiTreeItemValue {
+
+ public MultipleSpacesTreeItemValue(RenamingPath path, Executor executor) {
+ super(path, true, executor);
+ updateStatus();
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return "Movie Name Multiple Spaces";
+ }
+
+ @Override
+ protected String updateMessage(Boolean newValue) {
+ return isWarning() ? "Multiple spaces in path" : "No multiple spaces in path";
+ }
+
+ protected boolean calculateWarning() {
+ return test(getRenamingPath().getMovieName());
+ }
+
+ public boolean test(String fileName) {
+ Pattern p = Pattern.compile("\\s{2,}");
+ Matcher m = p.matcher(fileName);
+ return m.find();
+ }
+
+ protected void updateStatus() {
+ setWarning(calculateWarning());
+ setCanFix(isWarning());
+ }
+
+ public void fix() {
+ getRenamingPath().rename(new RegexReplaceRenamingStrategy(null).setReplacementStringFrom("\\s+").setReplacementStringTo(" "));
+ }
+
+
+}
diff --git a/src/main/java/drrename/kodi/ProblematicMovieNameService.java b/src/main/java/drrename/kodi/ProblematicMovieNameService.java
new file mode 100644
index 00000000..634e056b
--- /dev/null
+++ b/src/main/java/drrename/kodi/ProblematicMovieNameService.java
@@ -0,0 +1,32 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.kodi.checkservice.CheckService;
+import drrename.model.RenamingPath;
+
+import java.util.concurrent.Executor;
+
+public class ProblematicMovieNameService extends CheckService {
+ @Override
+ public ProblematicMovieNameTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ return new ProblematicMovieNameTreeItemValue(path, executor);
+ }
+}
diff --git a/src/main/java/drrename/kodi/ProblematicMovieNameTreeItemValue.java b/src/main/java/drrename/kodi/ProblematicMovieNameTreeItemValue.java
new file mode 100644
index 00000000..54fa8f62
--- /dev/null
+++ b/src/main/java/drrename/kodi/ProblematicMovieNameTreeItemValue.java
@@ -0,0 +1,57 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.model.RenamingPath;
+
+import java.util.concurrent.Executor;
+
+public class ProblematicMovieNameTreeItemValue extends KodiTreeItemValue {
+
+ public ProblematicMovieNameTreeItemValue(RenamingPath moviePath, Executor executor) {
+ super(moviePath, false, executor);
+ updateStatus();
+ }
+
+ @Override
+ protected String updateMessage(Boolean newValue) {
+ return isWarning() ? "Folder name problematic" : "Folder name unproblematic";
+ }
+
+ @Override
+ public void fix() throws FixFailedException {
+throw new IllegalStateException("Cannot fix");
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return "Problematic Name";
+ }
+
+ @Override
+ protected void updateStatus() {
+ setWarning(calculateWarning());
+ setCanFix(isWarning());
+ }
+
+ private boolean calculateWarning() {
+ return getRenamingPath().getMovieName().startsWith(".");
+ }
+}
diff --git a/src/main/java/drrename/kodi/SubdirsTreeItemValue.java b/src/main/java/drrename/kodi/SubdirsTreeItemValue.java
new file mode 100644
index 00000000..79341410
--- /dev/null
+++ b/src/main/java/drrename/kodi/SubdirsTreeItemValue.java
@@ -0,0 +1,145 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi;
+
+import drrename.model.RenamingPath;
+import javafx.beans.property.ListProperty;
+import javafx.beans.property.SimpleListProperty;
+import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
+import javafx.collections.ObservableList;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+@Slf4j
+public class SubdirsTreeItemValue extends KodiTreeItemValue {
+
+ private final ListProperty subdirs;
+
+ public SubdirsTreeItemValue(RenamingPath moviePath, Executor executor) {
+ super(moviePath, false, executor);
+ subdirs = new SimpleListProperty<>();
+ init();
+ updateStatus();
+ }
+
+ private void init(){
+ subdirs.addListener((ListChangeListener) c -> {
+ while(c.next()){
+ setWarning(calculateWarning(c.getList()));
+ setCanFix(isWarning());
+ }
+ });
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return "Subdirs";
+ }
+
+ @Override
+ protected void updateStatus() {
+ try {
+ setSubdirs(FXCollections.observableArrayList(getSubdirs(getRenamingPath().getOldPath())));
+ } catch (IOException e) {
+ log.error(e.getLocalizedMessage(), e);
+ }
+ }
+
+ protected List getSubdirs(Path path) throws IOException {
+ List subdirs = new ArrayList<>();
+ try (DirectoryStream ds = Files.newDirectoryStream(path)) {
+ for (Path child : ds) {
+ if (Files.isDirectory(child)) {
+ subdirs.add(child);
+ }
+ }
+ }
+ return subdirs;
+ }
+
+ protected List getChildFilesAndFolders(Path path) throws IOException {
+ List subdirs = new ArrayList<>();
+ try (DirectoryStream ds = Files.newDirectoryStream(path)) {
+ for (Path child : ds) {
+ subdirs.add(child);
+ }
+ }
+ return subdirs;
+ }
+
+ protected String countChildFilesAndFolders(Path path) {
+ try {
+ return Integer.toString(getChildFilesAndFolders(path).size());
+ } catch (IOException e) {
+ return e.getLocalizedMessage();
+ }
+ }
+
+ private boolean calculateWarning(Collection extends Path> subdirs){
+ return !subdirs.isEmpty();
+ }
+
+ @Override
+ protected String updateMessage(Boolean newValue) {
+ return newValue ? "Has subdirs: " + getSubdirs().stream().map(p -> p.getFileName() + "[" + countChildFilesAndFolders(p) + "]").toList() : "No subdirs";
+ }
+
+ @Override
+ public void fix() throws FixFailedException {
+ for(Path p : getSubdirs()){
+ try (var dirStream = Files.walk(p)) {
+ dirStream
+ .map(Path::toFile)
+ .sorted(Comparator.reverseOrder())
+ .forEach(File::delete);
+ } catch (IOException e) {
+ throw new FixFailedException(e);
+ }
+ }
+ }
+
+
+
+ // Getter / Setter //
+
+
+ public ObservableList getSubdirs() {
+ return subdirs.get();
+ }
+
+ public ListProperty subdirsProperty() {
+ return subdirs;
+ }
+
+ public void setSubdirs(ObservableList subdirs) {
+ this.subdirs.set(subdirs);
+ }
+}
diff --git a/src/main/java/drrename/kodi/treeitem/content/KodiTreeItemContent.java b/src/main/java/drrename/kodi/WarningsConfig.java
similarity index 56%
rename from src/main/java/drrename/kodi/treeitem/content/KodiTreeItemContent.java
rename to src/main/java/drrename/kodi/WarningsConfig.java
index 54725a8c..f56dc6cd 100644
--- a/src/main/java/drrename/kodi/treeitem/content/KodiTreeItemContent.java
+++ b/src/main/java/drrename/kodi/WarningsConfig.java
@@ -17,28 +17,30 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content;
+package drrename.kodi;
-import javafx.scene.control.TreeItem;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+public class WarningsConfig {
-public abstract class KodiTreeItemContent {
+ private final BooleanProperty missingNfoFileIsWarning;
- private TreeItem treeItem;
-
- public boolean hasWarning() {
- return treeItem != null && treeItem.getChildren().stream().map(TreeItem::getValue).anyMatch(KodiTreeItemContent::hasWarning);
+ public WarningsConfig(){
+ this.missingNfoFileIsWarning = new SimpleBooleanProperty();
}
// Getter / Setter //
- @SuppressWarnings("unused")
- public TreeItem getTreeItem() {
- return treeItem;
+ public boolean isMissingNfoFileIsWarning() {
+ return missingNfoFileIsWarning.get();
+ }
+
+ public BooleanProperty missingNfoFileIsWarningProperty() {
+ return missingNfoFileIsWarning;
}
- public KodiTreeItemContent setTreeItem(TreeItem treeItem) {
- this.treeItem = treeItem;
- return this;
+ public void setMissingNfoFileIsWarning(boolean missingNfoFileIsWarning) {
+ this.missingNfoFileIsWarning.set(missingNfoFileIsWarning);
}
}
diff --git a/src/main/java/drrename/kodi/checkservice/CheckService.java b/src/main/java/drrename/kodi/checkservice/CheckService.java
new file mode 100644
index 00000000..1a998647
--- /dev/null
+++ b/src/main/java/drrename/kodi/checkservice/CheckService.java
@@ -0,0 +1,48 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.checkservice;
+
+import drrename.kodi.KodiTreeItem;
+import drrename.kodi.KodiTreeItemValue;
+import drrename.kodi.MovieTreeItem;
+import drrename.kodi.WarningsConfig;
+import drrename.model.RenamingPath;
+import javafx.application.Platform;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.concurrent.Executor;
+
+@Slf4j
+public abstract class CheckService {
+
+ public void addChildItem(MovieTreeItem treeItem, WarningsConfig warningsConfig, Executor executor) {
+
+ R checkResult = checkPath(treeItem.getValue().getRenamingPath(), warningsConfig, executor);
+ var childItem = buildChildItem(checkResult);
+ Platform.runLater(() -> treeItem.add(childItem));
+
+ }
+
+ public abstract R checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor);
+
+ public KodiTreeItem buildChildItem(R checkResult) {
+ return new KodiTreeItem(checkResult);
+ }
+}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/CheckServiceProvider.java b/src/main/java/drrename/kodi/checkservice/CheckServiceProvider.java
similarity index 63%
rename from src/main/java/drrename/kodi/treeitem/content/check/CheckServiceProvider.java
rename to src/main/java/drrename/kodi/checkservice/CheckServiceProvider.java
index bd9d3383..3f7135d4 100644
--- a/src/main/java/drrename/kodi/treeitem/content/check/CheckServiceProvider.java
+++ b/src/main/java/drrename/kodi/checkservice/CheckServiceProvider.java
@@ -17,25 +17,35 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content.check;
+package drrename.kodi.checkservice;
-import drrename.kodi.treeitem.content.NfoFileContentCheckService;
+import drrename.kodi.MultipleSpacesService;
+import drrename.kodi.ProblematicMovieNameService;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
-
+/**
+ * Holds all {@link CheckService} instances that should run.
+ */
@Service
public class CheckServiceProvider {
private final List> checkServices;
- public CheckServiceProvider(){
+ public CheckServiceProvider(NfoFileContentUrlCheckService nfoFileContentUrlCheckService){
+
this.checkServices = Arrays.asList(
+ nfoFileContentUrlCheckService,
+ new MovieFileNameCheckService(),
new NfoFileNameCheckService(),
- new NfoFileContentCheckService(),
- new SubdirsCheckService()
+ new NfoFileContentYearCheckService(),
+ new NfoFileContentTitleCheckService(),
+ new NfoFileContentCoverCheckService(),
+ new SubdirsCheckService(),
+ new MultipleSpacesService(),
+ new ProblematicMovieNameService()
);
}
diff --git a/src/main/java/drrename/kodi/checkservice/MovieFileNameCheckService.java b/src/main/java/drrename/kodi/checkservice/MovieFileNameCheckService.java
new file mode 100644
index 00000000..df6bd274
--- /dev/null
+++ b/src/main/java/drrename/kodi/checkservice/MovieFileNameCheckService.java
@@ -0,0 +1,34 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.checkservice;
+
+import drrename.kodi.MovieFileNameTreeItemValue;
+import drrename.kodi.WarningsConfig;
+import drrename.kodi.checkservice.CheckService;
+import drrename.model.RenamingPath;
+
+import java.util.concurrent.Executor;
+
+public class MovieFileNameCheckService extends CheckService {
+ @Override
+ public MovieFileNameTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ return new MovieFileNameTreeItemValue(path, executor);
+ }
+}
diff --git a/src/main/java/drrename/kodi/checkservice/NfoFileContentCoverCheckService.java b/src/main/java/drrename/kodi/checkservice/NfoFileContentCoverCheckService.java
new file mode 100644
index 00000000..7f5de49b
--- /dev/null
+++ b/src/main/java/drrename/kodi/checkservice/NfoFileContentCoverCheckService.java
@@ -0,0 +1,36 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.checkservice;
+
+import drrename.kodi.WarningsConfig;
+import drrename.kodi.nfo.NfoFileContentCoverTreeItemValue;
+import drrename.model.RenamingPath;
+
+import java.util.concurrent.Executor;
+
+public class NfoFileContentCoverCheckService extends CheckService {
+
+ public NfoFileContentCoverTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ return new NfoFileContentCoverTreeItemValue(path, executor);
+
+ }
+
+
+}
diff --git a/src/main/java/drrename/kodi/checkservice/NfoFileContentTitleCheckService.java b/src/main/java/drrename/kodi/checkservice/NfoFileContentTitleCheckService.java
new file mode 100644
index 00000000..8b96ab61
--- /dev/null
+++ b/src/main/java/drrename/kodi/checkservice/NfoFileContentTitleCheckService.java
@@ -0,0 +1,36 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.checkservice;
+
+import drrename.kodi.WarningsConfig;
+import drrename.kodi.nfo.NfoFileContentTitleTreeItemValue;
+import drrename.model.RenamingPath;
+
+import java.util.concurrent.Executor;
+
+public class NfoFileContentTitleCheckService extends CheckService {
+
+ public NfoFileContentTitleTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ return new NfoFileContentTitleTreeItemValue(path, executor);
+
+ }
+
+
+}
diff --git a/src/main/java/drrename/kodi/checkservice/NfoFileContentUrlCheckService.java b/src/main/java/drrename/kodi/checkservice/NfoFileContentUrlCheckService.java
new file mode 100644
index 00000000..5700de9a
--- /dev/null
+++ b/src/main/java/drrename/kodi/checkservice/NfoFileContentUrlCheckService.java
@@ -0,0 +1,44 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.checkservice;
+
+import drrename.kodi.MovieDbClientFactory;
+import drrename.kodi.WarningsConfig;
+import drrename.kodi.nfo.NfoFileContentUrlTreeItemValue;
+import drrename.model.RenamingPath;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.Executor;
+
+@Component
+public class NfoFileContentUrlCheckService extends CheckService {
+
+ private final MovieDbClientFactory factory;
+
+ public NfoFileContentUrlCheckService(MovieDbClientFactory factory) {
+
+ this.factory = factory;
+ }
+
+ @Override
+ public NfoFileContentUrlTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ return new NfoFileContentUrlTreeItemValue(path, executor, factory);
+ }
+}
diff --git a/src/main/java/drrename/kodi/checkservice/NfoFileContentYearCheckService.java b/src/main/java/drrename/kodi/checkservice/NfoFileContentYearCheckService.java
new file mode 100644
index 00000000..ebee2628
--- /dev/null
+++ b/src/main/java/drrename/kodi/checkservice/NfoFileContentYearCheckService.java
@@ -0,0 +1,36 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.checkservice;
+
+import drrename.kodi.WarningsConfig;
+import drrename.kodi.nfo.NfoFileContentYearTreeItemValue;
+import drrename.model.RenamingPath;
+
+import java.util.concurrent.Executor;
+
+public class NfoFileContentYearCheckService extends CheckService {
+
+ public NfoFileContentYearTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ return new NfoFileContentYearTreeItemValue(path, executor);
+
+ }
+
+
+}
diff --git a/src/main/java/drrename/kodi/checkservice/NfoFileNameCheckService.java b/src/main/java/drrename/kodi/checkservice/NfoFileNameCheckService.java
new file mode 100644
index 00000000..41d7fdf8
--- /dev/null
+++ b/src/main/java/drrename/kodi/checkservice/NfoFileNameCheckService.java
@@ -0,0 +1,38 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.checkservice;
+
+import drrename.kodi.WarningsConfig;
+import drrename.kodi.nfo.NfoFileNameTreeItemValue;
+import drrename.model.RenamingPath;
+
+import java.nio.file.Files;
+import java.util.concurrent.Executor;
+
+public class NfoFileNameCheckService extends CheckService {
+
+ @Override
+ public NfoFileNameTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ if (!Files.isDirectory(path.getOldPath())) {
+ throw new IllegalArgumentException(path.getMovieName() + " is not a directory");
+ }
+ return new NfoFileNameTreeItemValue(path, warningsConfig, executor);
+ }
+}
diff --git a/src/main/java/drrename/kodi/treeitem/content/NfoFileContentTreeItemContent.java b/src/main/java/drrename/kodi/checkservice/SubdirsCheckService.java
similarity index 62%
rename from src/main/java/drrename/kodi/treeitem/content/NfoFileContentTreeItemContent.java
rename to src/main/java/drrename/kodi/checkservice/SubdirsCheckService.java
index 9e9f0dda..6694eedb 100644
--- a/src/main/java/drrename/kodi/treeitem/content/NfoFileContentTreeItemContent.java
+++ b/src/main/java/drrename/kodi/checkservice/SubdirsCheckService.java
@@ -17,19 +17,19 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content;
+package drrename.kodi.checkservice;
-import drrename.kodi.treeitem.content.check.NfoFileContentCheckResult;
-import drrename.kodi.treeitem.content.check.NfoCheckResultTreeItemContent;
+import drrename.kodi.SubdirsTreeItemValue;
+import drrename.kodi.WarningsConfig;
+import drrename.kodi.checkservice.CheckService;
+import drrename.model.RenamingPath;
-public class NfoFileContentTreeItemContent extends NfoCheckResultTreeItemContent {
+import java.util.concurrent.Executor;
- public NfoFileContentTreeItemContent(NfoFileContentCheckResult value) {
- super(value);
- }
+public class SubdirsCheckService extends CheckService {
@Override
- public boolean hasWarning() {
- return getCheckResult().isWarning();
+ public SubdirsTreeItemValue checkPath(RenamingPath path, WarningsConfig warningsConfig, Executor executor) {
+ return new SubdirsTreeItemValue(path, executor);
}
}
diff --git a/src/main/java/drrename/kodi/treeitem/content/MovieTreeItemContent.java b/src/main/java/drrename/kodi/nfo/MovieDbCheckType.java
similarity index 67%
rename from src/main/java/drrename/kodi/treeitem/content/MovieTreeItemContent.java
rename to src/main/java/drrename/kodi/nfo/MovieDbCheckType.java
index 6e979f56..81047c1a 100644
--- a/src/main/java/drrename/kodi/treeitem/content/MovieTreeItemContent.java
+++ b/src/main/java/drrename/kodi/nfo/MovieDbCheckType.java
@@ -17,24 +17,30 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content;
+package drrename.kodi.nfo;
-import java.nio.file.Path;
+public enum MovieDbCheckType {
-public class MovieTreeItemContent extends KodiTreeItemContent {
+ NOT_FOUND("Not found"){
+ @Override
+ public boolean isWarning() {
+ return true;
+ }
+ },
+ ORIGINAL_TITEL("Original title"), LOCALIZED_TITLE("Localized title");
- private final Path moviePath;
+ private final String name;
- public MovieTreeItemContent(Path moviePath) {
- this.moviePath = moviePath;
+ MovieDbCheckType(String name){
+ this.name = name;
}
@Override
public String toString() {
- return moviePath.getFileName().toString();
+ return name;
}
- public Path getMoviePath() {
- return moviePath;
+ public boolean isWarning() {
+ return false;
}
}
diff --git a/src/main/java/drrename/kodi/treeitem/content/KodiRootTreeItemContent.java b/src/main/java/drrename/kodi/nfo/NfoChecker.java
similarity index 72%
rename from src/main/java/drrename/kodi/treeitem/content/KodiRootTreeItemContent.java
rename to src/main/java/drrename/kodi/nfo/NfoChecker.java
index 26908073..760a2f70 100644
--- a/src/main/java/drrename/kodi/treeitem/content/KodiRootTreeItemContent.java
+++ b/src/main/java/drrename/kodi/nfo/NfoChecker.java
@@ -17,21 +17,22 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content;
+package drrename.kodi.nfo;
-public class KodiRootTreeItemContent extends KodiTreeItemContent {
+import lombok.Getter;
+import lombok.Setter;
- public KodiRootTreeItemContent() {
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
- }
+@Getter
+@Setter
+public class NfoChecker {
- @Override
- public boolean hasWarning() {
- return false;
- }
+ private List nfoFiles;
- @Override
- public String toString() {
- return "Analysis Result";
+ public NfoChecker(){
+ nfoFiles = new ArrayList<>();
}
}
diff --git a/src/main/java/drrename/kodi/nfo/NfoContentChecker.java b/src/main/java/drrename/kodi/nfo/NfoContentChecker.java
new file mode 100644
index 00000000..24396fb3
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoContentChecker.java
@@ -0,0 +1,58 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.model.nfo.NfoRoot;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+@Slf4j
+public abstract class NfoContentChecker extends NfoChecker {
+
+ public NfoFileContentType checkNfoFile(Path nfoFile){
+ if(Files.notExists(nfoFile)){
+ return NfoFileContentType.NO_FILE;
+ }
+ if(!Files.isReadable(nfoFile)){
+ return NfoFileContentType.EXCEPTION;
+ }
+ if(!Files.isRegularFile(nfoFile)){
+ return NfoFileContentType.NOT_A_FILE;
+ }
+ try {
+ NfoRoot xmlModel = new NfoFileParser().parse(nfoFile);
+ if(xmlModel == null || (xmlModel.getMovie() == null && xmlModel.getUrl() == null)){
+ return NfoFileContentType.INVALID_FILE;
+ }
+ if(xmlModel.getMovie() == null && xmlModel.getUrl() != null){
+ return NfoFileContentType.URL_ONLY_FILE;
+ }
+ return doCheckNfoFile(nfoFile.getParent(), xmlModel);
+ } catch (IOException e) {
+ log.debug(e.getLocalizedMessage());
+ return NfoFileContentType.EXCEPTION;
+ }
+ }
+
+ protected abstract NfoFileContentType doCheckNfoFile(Path moviePath, NfoRoot xmlModel) throws IOException;
+}
diff --git a/src/main/java/drrename/kodi/nfo/NfoContentCoverChecker.java b/src/main/java/drrename/kodi/nfo/NfoContentCoverChecker.java
new file mode 100644
index 00000000..74b9d38a
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoContentCoverChecker.java
@@ -0,0 +1,48 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.mime.FileTypeByMimeProvider;
+import drrename.model.nfo.NfoRoot;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class NfoContentCoverChecker extends NfoContentChecker {
+ @Override
+ protected NfoFileContentType doCheckNfoFile(Path moviePath, NfoRoot xmlModel) throws IOException {
+ if(xmlModel.getMovie().getArt() == null || xmlModel.getMovie().getArt().getPoster() == null){
+ return NfoFileContentType.MISSING_POSTER;
+ }
+ if(verifyCoverFront(moviePath, xmlModel)){
+ return NfoFileContentType.VALID_POSTER;
+ }
+ return NfoFileContentType.INVALID_POSTER;
+ }
+
+ static boolean verifyCoverFront(Path moviePath, NfoRoot xmlFileContent) {
+ if (xmlFileContent == null || xmlFileContent.getMovie() == null || xmlFileContent.getMovie().getArt() == null || xmlFileContent.getMovie().getArt().getPoster() == null) {
+ return false;
+ }
+ Path coverFront = moviePath.resolve(xmlFileContent.getMovie().getArt().getPoster());
+ return Files.isRegularFile(coverFront) && Files.isReadable(coverFront) && new FileTypeByMimeProvider().getFileType(coverFront).startsWith("image");
+ }
+}
diff --git a/src/main/java/drrename/kodi/nfo/NfoContentTitleChecker.java b/src/main/java/drrename/kodi/nfo/NfoContentTitleChecker.java
new file mode 100644
index 00000000..c507f34a
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoContentTitleChecker.java
@@ -0,0 +1,48 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.Strings;
+import drrename.model.nfo.NfoRoot;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+public class NfoContentTitleChecker extends NfoContentChecker {
+ @Override
+ protected NfoFileContentType doCheckNfoFile(Path moviePath, NfoRoot xmlModel) throws IOException {
+ if(xmlModel.getMovie().getTitle() == null){
+ return NfoFileContentType.MISSING_TITLE;
+ }
+ if(verifyTitle(moviePath, xmlModel)){
+ return NfoFileContentType.VALID_TITLE;
+ }
+ return NfoFileContentType.INVALID_TITLE;
+ }
+
+ static boolean verifyTitle(Path moviePath, NfoRoot xmlFileContent) {
+ return xmlFileContent != null && xmlFileContent.getMovie() != null && xmlFileContent.getMovie().getTitle() != null && Strings.startsWithIgnoreCase(moviePath.getFileName().toString(),getSimplifiedName(xmlFileContent.getMovie().getTitle()));
+ }
+
+ private static String getSimplifiedName(String title) {
+ // NFO title may be more specific, e.g. might contain punctuation
+ return title.replaceAll(",", "");
+ }
+}
diff --git a/src/main/java/drrename/kodi/nfo/NfoContentYearChecker.java b/src/main/java/drrename/kodi/nfo/NfoContentYearChecker.java
new file mode 100644
index 00000000..8cd0b1a9
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoContentYearChecker.java
@@ -0,0 +1,49 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.model.nfo.NfoRoot;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+public class NfoContentYearChecker extends NfoContentChecker {
+
+ @Override
+ protected NfoFileContentType doCheckNfoFile(Path moviePath, NfoRoot xmlModel) throws IOException {
+ if(xmlModel.getMovie().getYear() == null){
+ return NfoFileContentType.MISSING_YEAR;
+ }
+ if(verifyYear(moviePath, xmlModel)){
+ return NfoFileContentType.VALID_YEAR;
+ }
+ return NfoFileContentType.INVALID_YEAR;
+ }
+
+ private boolean verifyYear(Path moviePath, NfoRoot xmlFileContent) {
+ return xmlFileContent != null &&
+ xmlFileContent.getMovie() != null &&
+ xmlFileContent.getMovie().getYear() != null &&
+ moviePath.getFileName().toString().endsWith("(" + xmlFileContent.getMovie().getYear() + ")");
+ }
+
+
+
+}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/SubdirsCheckService.java b/src/main/java/drrename/kodi/nfo/NfoFileCollector.java
similarity index 57%
rename from src/main/java/drrename/kodi/treeitem/content/check/SubdirsCheckService.java
rename to src/main/java/drrename/kodi/nfo/NfoFileCollector.java
index 90482ccd..1c64de81 100644
--- a/src/main/java/drrename/kodi/treeitem/content/check/SubdirsCheckService.java
+++ b/src/main/java/drrename/kodi/nfo/NfoFileCollector.java
@@ -17,11 +17,10 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content.check;
+package drrename.kodi.nfo;
-import drrename.kodi.treeitem.KodiTreeItem;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
+import org.apache.commons.io.FilenameUtils;
import java.io.IOException;
import java.nio.file.DirectoryStream;
@@ -31,30 +30,22 @@
import java.util.List;
@Slf4j
-@Service
-public class SubdirsCheckService extends CheckService {
+public class NfoFileCollector {
- @Override
- public CheckResult checkPath(Path path) throws IOException {
- if (getSubdirs(path).isEmpty())
- return new CheckResult("No sub-directories");
- return new CheckResult("Sub-directories found");
- }
-
- @Override
- public KodiTreeItem buildChildItem(CheckResult checkResult) {
- return new KodiTreeItem(new CheckResultTreeItemContent(checkResult));
- }
-
- static List getSubdirs(Path path) throws IOException {
- List subdirs = new ArrayList<>();
- try (DirectoryStream ds = Files.newDirectoryStream(path)) {
+ public List collectNfoFiles(Path directory) throws IOException {
+ List result = new ArrayList<>();
+ try (DirectoryStream ds = Files.newDirectoryStream(directory)) {
for (Path child : ds) {
- if (Files.isDirectory(child)) {
- subdirs.add(child.getFileName());
+ String extension = FilenameUtils.getExtension(child.getFileName().toString());
+ if(Files.isHidden(child)){
+ log.debug("Ignoring hidden NFO file {}", child);
+ continue;
+ }
+ if (Files.isRegularFile(child) && NfoFiles.DEFAULT_EXTENSION.equalsIgnoreCase(extension)) {
+ result.add(child);
}
}
}
- return subdirs;
+ return result;
}
}
diff --git a/src/main/java/drrename/kodi/nfo/NfoFileContentCoverTreeItemValue.java b/src/main/java/drrename/kodi/nfo/NfoFileContentCoverTreeItemValue.java
new file mode 100644
index 00000000..4f74ea56
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoFileContentCoverTreeItemValue.java
@@ -0,0 +1,47 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.model.RenamingPath;
+import lombok.extern.slf4j.Slf4j;
+
+import java.nio.file.Path;
+import java.util.concurrent.Executor;
+
+@Slf4j
+public class NfoFileContentCoverTreeItemValue extends NfoFileContentTreeItemValue {
+
+ public NfoFileContentCoverTreeItemValue(RenamingPath path, Executor executor) {
+ super(path, false, executor);
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return "NFO Poster";
+ }
+
+ @Override
+ protected NfoFileContentType parseNfoFile(Path child) {
+ var checker = new NfoContentCoverChecker();
+ var result = checker.checkNfoFile(child);
+ setNfoFiles(checker.getNfoFiles());
+ return result;
+ }
+}
diff --git a/src/main/java/drrename/kodi/nfo/NfoFileContentTitleTreeItemValue.java b/src/main/java/drrename/kodi/nfo/NfoFileContentTitleTreeItemValue.java
new file mode 100644
index 00000000..53816a30
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoFileContentTitleTreeItemValue.java
@@ -0,0 +1,45 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.model.RenamingPath;
+
+import java.nio.file.Path;
+import java.util.concurrent.Executor;
+
+public class NfoFileContentTitleTreeItemValue extends NfoFileContentTreeItemValue {
+
+ public NfoFileContentTitleTreeItemValue(RenamingPath moviePath, Executor executor) {
+ super(moviePath, false, executor);
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return "NFO Title";
+ }
+
+ @Override
+ protected NfoFileContentType parseNfoFile(Path child) {
+ var checker = new NfoContentTitleChecker();
+ var result = checker.checkNfoFile(child);
+ setNfoFiles(checker.getNfoFiles());
+ return result;
+ }
+}
diff --git a/src/main/java/drrename/kodi/nfo/NfoFileContentTreeItemValue.java b/src/main/java/drrename/kodi/nfo/NfoFileContentTreeItemValue.java
new file mode 100644
index 00000000..f87ac73e
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoFileContentTreeItemValue.java
@@ -0,0 +1,95 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.model.RenamingPath;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.concurrent.Executor;
+
+@Slf4j
+public abstract class NfoFileContentTreeItemValue extends NfoFileTreeItemValue {
+
+ private final ObjectProperty parseResult;
+
+ public NfoFileContentTreeItemValue(RenamingPath moviePath, boolean fixable, Executor executor) {
+ super(moviePath, fixable, executor);
+ this.parseResult = new SimpleObjectProperty<>();
+ parseResult.addListener((observable, oldValue, newValue) -> setWarning(newValue.isWarning(isMissingNfoFileIsWarning())));
+ missingNfoFileIsWarningProperty().addListener((observable, oldValue, newValue) -> setWarning(getParseResult().isWarning(isMissingNfoFileIsWarning())));
+ updateStatus();
+ }
+
+ protected NfoFileContentType parseNfoFile() {
+
+ try {
+ var nfoFiles = new NfoFileCollector().collectNfoFiles(getRenamingPath().getOldPath());
+ if (nfoFiles.isEmpty()) {
+ return NfoFileContentType.NO_FILE;
+ }
+ // take a look only at the first file
+ var result = parseNfoFile(nfoFiles.get(0));
+ setNfoFiles(nfoFiles);
+ return result;
+ } catch (IOException e) {
+ log.debug("Failed to parse NFO file. Reason: {}", e.getLocalizedMessage());
+ return NfoFileContentType.EXCEPTION;
+ }
+ }
+
+
+ protected abstract NfoFileContentType parseNfoFile(Path child);
+
+
+ @Override
+ protected void updateStatus() {
+ parseResult.set(parseNfoFile());
+ }
+
+ @Override
+ protected String updateMessage(Boolean warning) {
+ return getParseResult().toString();
+ }
+
+ @Override
+ public void fix() {
+ throw new IllegalStateException("Cannot fix");
+ }
+
+ // Getter / Setter //
+
+ public NfoFileContentType getParseResult() {
+ return parseResult.get();
+ }
+
+ public ObjectProperty parseResultProperty() {
+ return parseResult;
+ }
+
+ public void setParseResult(NfoFileContentType parseResult) {
+ this.parseResult.set(parseResult);
+ }
+
+
+}
diff --git a/src/main/java/drrename/kodi/nfo/NfoFileContentType.java b/src/main/java/drrename/kodi/nfo/NfoFileContentType.java
new file mode 100644
index 00000000..ff136770
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoFileContentType.java
@@ -0,0 +1,91 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+public enum NfoFileContentType {
+ NO_FILE("No file"){
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return missingNfoFileIsWarning;
+ }
+ },
+ INVALID_FILE("Invalid file"){
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ }
+ , INVALID_YEAR("Invalid year"){
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ }, VALID_YEAR("Valid year"),
+ EXCEPTION("Could not parse file"){
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ }, URL_ONLY_FILE("URL-only"),
+ MISSING_YEAR("No year"){
+ @Override
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ }, VALID_TITLE("Valid title"),
+ INVALID_TITLE("Title does not match folder name"){
+ @Override
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ }, VALID_POSTER("Valid Poster"),
+ INVALID_POSTER("Invalid Poster"){
+ @Override
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ }, NOT_A_FILE("Not a file"){
+ @Override
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ }, MISSING_TITLE("Missing title"){
+ @Override
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ }, MISSING_POSTER("Missing poster"){
+ @Override
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return true;
+ }
+ };
+
+ private final String name;
+
+ NfoFileContentType(String name){
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ public boolean isWarning(boolean missingNfoFileIsWarning) {
+ return false;
+ }
+}
diff --git a/src/main/java/drrename/kodi/nfo/NfoFileContentUrlTreeItemValue.java b/src/main/java/drrename/kodi/nfo/NfoFileContentUrlTreeItemValue.java
new file mode 100644
index 00000000..8b4d20a7
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoFileContentUrlTreeItemValue.java
@@ -0,0 +1,182 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.MovieDbChecker;
+import drrename.MovieDbImagesClient;
+import drrename.RenameUtil;
+import drrename.config.TheMovieDbConfig;
+import drrename.kodi.FixFailedException;
+import drrename.kodi.KodiTreeItemValue;
+import drrename.kodi.KodiUtil;
+import drrename.kodi.MovieDbClientFactory;
+import drrename.model.RenamingPath;
+import javafx.application.Platform;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import javafx.scene.Node;
+import javafx.scene.control.Button;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.file.*;
+import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
+
+@Slf4j
+public class NfoFileContentUrlTreeItemValue extends KodiTreeItemValue {
+
+ @AllArgsConstructor
+ static
+ class FixConfig {
+ Button button;
+ String newName;
+ }
+
+ private final ObjectProperty type;
+
+ private final MovieDbChecker checker;
+
+ private final MovieDbImagesClient imagesClient;
+
+ private final TheMovieDbConfig config;
+
+ private FixConfig fixConfig;
+
+ public NfoFileContentUrlTreeItemValue(RenamingPath moviePath, Executor executor, MovieDbClientFactory factory) {
+ super(moviePath, false, executor);
+ this.type = new SimpleObjectProperty<>();
+ this.checker = factory.getNewMovieDbChecker();
+ this.imagesClient = factory.getImagesClient();
+ this.config = factory.getConfig();
+ updateStatus();
+ }
+
+ @Override
+ protected String updateMessage(Boolean newValue) {
+ return newValue ? "Movie name could not be found online" + getAdditionalMessageString() : "Movie name found online" + ": " + getType();
+ }
+
+ private String getAdditionalMessageString() {
+ return checker.getOnlineTitles().isEmpty() ? "" : ". Best matches: " + checker.getOnlineTitles().stream().map(Object::toString).collect(Collectors.joining(", "));
+ }
+
+ @Override
+ public void fix() throws FixFailedException {
+ try {
+ var renameResult = RenameUtil.rename(getRenamingPath().getOldPath(), fixConfig.newName);
+ Platform.runLater(() -> getRenamingPath().commitRename(renameResult));
+ } catch (IOException e) {
+ throw new FixFailedException(e);
+ }
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return "Movie name lookup";
+ }
+
+
+ @Override
+ protected void updateStatus() {
+ MovieDbCheckType newType = null;
+ try {
+ newType = checker.check(KodiUtil.getMovieNameFromDirectoryName(getRenamingPath().getMovieName()), KodiUtil.getMovieYearFromDirectoryName(getRenamingPath().getMovieName()));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ setType(newType);
+ setWarning(getType().isWarning());
+ updateMessage(isWarning());
+ setCanFix(!checker.getOnlineTitles().isEmpty() && isWarning());
+ if (!checker.getOnlineTitles().isEmpty() && isWarning()) {
+ Platform.runLater(() -> setGraphic(buildGraphic2()));
+ } else {
+ Platform.runLater(() -> setGraphic(super.buildGraphic()));
+ }
+ if (checker.getTheMovieDbId() != null) {
+ var image = imagesClient.searchMovie(config.getApiKey(), null, true, checker.getTheMovieDbId());
+ try {
+ if (image.getBody() != null) {
+ Path tempFile = Files.createTempFile("tmp", ".jpg");
+ Path outputFile = getRenamingPath().getOldPath().resolve(Paths.get("folder.jpg"));
+ try (FileOutputStream outputStream = new FileOutputStream(tempFile.toFile())) {
+ outputStream.write(image.getBody());
+ log.debug("Wrote image to {}", tempFile);
+ }
+ if (Files.exists(outputFile)) {
+ FileChannel imageFileChannel = FileChannel.open(outputFile);
+ long imageFileSize = imageFileChannel.size();
+ imageFileChannel.close();
+ FileChannel imageFileChannel2 = FileChannel.open(tempFile);
+ long imageFileSize2 = imageFileChannel2.size();
+ imageFileChannel2.close();
+ if(imageFileSize2 > imageFileSize){
+ log.debug("Downloaded file is larger in size, replacing ours with download");
+ Files.move(tempFile, outputFile, StandardCopyOption.REPLACE_EXISTING);
+ } else {
+ log.debug("Our image is larger in size, keeping it");
+ }
+ } else {
+ log.debug("{} does not exist, using download", outputFile);
+ Files.move(tempFile, outputFile);
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private Node buildGraphic2() {
+ VBox box = new VBox(4);
+ for (String name : checker.getOnlineTitles()) {
+ Button button = new Button("Fix to \"" + name + "\"");
+ VBox.setVgrow(button, Priority.ALWAYS);
+ button.setMaxWidth(500);
+ button.setOnAction(event -> button.setOnAction(actionEvent -> {
+ fixConfig = new FixConfig(button, name);
+ performFix();
+ }));
+ box.getChildren().add(button);
+ }
+ return box;
+ }
+
+ // FX Getter / Setter //
+
+
+ public MovieDbCheckType getType() {
+ return type.get();
+ }
+
+ public ObjectProperty typeProperty() {
+ return type;
+ }
+
+ public void setType(MovieDbCheckType type) {
+ this.type.set(type);
+ }
+}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/NfoFileContentCheckResult.java b/src/main/java/drrename/kodi/nfo/NfoFileContentYearTreeItemValue.java
similarity index 55%
rename from src/main/java/drrename/kodi/treeitem/content/check/NfoFileContentCheckResult.java
rename to src/main/java/drrename/kodi/nfo/NfoFileContentYearTreeItemValue.java
index 587f0d48..72f7bd70 100644
--- a/src/main/java/drrename/kodi/treeitem/content/check/NfoFileContentCheckResult.java
+++ b/src/main/java/drrename/kodi/nfo/NfoFileContentYearTreeItemValue.java
@@ -17,35 +17,32 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content.check;
+package drrename.kodi.nfo;
-import java.nio.file.Path;
-
-public class NfoFileContentCheckResult extends NfoCheckResult {
+import drrename.model.RenamingPath;
+import lombok.extern.slf4j.Slf4j;
- private final Path nfoFile;
+import java.nio.file.Path;
+import java.util.concurrent.Executor;
- private final boolean warning;
+@Slf4j
+public class NfoFileContentYearTreeItemValue extends NfoFileContentTreeItemValue {
- public NfoFileContentCheckResult(String result, Path nfoFile, boolean hasWarning) {
- super(result);
- this.nfoFile = nfoFile;
- this.warning = hasWarning;
+ public NfoFileContentYearTreeItemValue(RenamingPath path, Executor executor) {
+ super(path, false, executor);
}
@Override
- public String toString() {
-// if(isWarning()){
-// return super.toString() + (nfoFile != null ? " " + nfoFile.getFileName().toString() : "");
-// }
- return super.toString();
+ protected String updateIdentifier() {
+ return "NFO Year";
}
- public boolean isWarning() {
- return warning;
- }
- public Path getNfoFile() {
- return nfoFile;
+ @Override
+ protected NfoFileContentType parseNfoFile(Path child) {
+ var checker = new NfoContentYearChecker();
+ var result = checker.checkNfoFile(child);
+ setNfoFiles(checker.getNfoFiles());
+ return result;
}
}
diff --git a/src/main/java/drrename/kodi/nfo/NfoFileNameChecker.java b/src/main/java/drrename/kodi/nfo/NfoFileNameChecker.java
new file mode 100644
index 00000000..98e3a296
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoFileNameChecker.java
@@ -0,0 +1,65 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+@Slf4j
+public class NfoFileNameChecker extends NfoChecker {
+
+ public NfoFileNameType checkDir(Path directory) {
+ String movieName = directory.getFileName().toString();
+ try {
+ setNfoFiles(new NfoFileCollector().collectNfoFiles(directory));
+ if (getNfoFiles().isEmpty()) {
+ return NfoFileNameType.NO_FILE;
+ }
+ if (getNfoFiles().size() > 1) {
+ return NfoFileNameType.MULTIPLE_FILES;
+ } else {
+ return checkFile(movieName, getNfoFiles().get(0));
+ }
+ } catch (IOException e) {
+ log.error(e.getLocalizedMessage(), e);
+ return NfoFileNameType.ERROR;
+ }
+ }
+
+ protected NfoFileNameType checkFile(String movieName, Path nfoFile) {
+ if (!Files.isRegularFile(nfoFile)) {
+ throw new IllegalArgumentException(nfoFile.getFileName().toString() + " is not a file");
+ }
+ String nfoFileName = nfoFile.getFileName().toString();
+ if (NfoFiles.DEFAULT_NAME.equalsIgnoreCase(nfoFileName)) {
+ return NfoFileNameType.DEFAULT_NAME;
+ } else if (FilenameUtils.getBaseName(nfoFileName).equalsIgnoreCase(movieName)) {
+ return NfoFileNameType.MOVIE_NAME;
+ } else {
+ return NfoFileNameType.INVALID_NAME;
+ }
+ }
+
+
+}
diff --git a/src/main/java/drrename/kodi/nfo/NfoFileNameTreeItemValue.java b/src/main/java/drrename/kodi/nfo/NfoFileNameTreeItemValue.java
new file mode 100644
index 00000000..08bf1ef0
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoFileNameTreeItemValue.java
@@ -0,0 +1,120 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.kodi.FixFailedException;
+import drrename.kodi.WarningsConfig;
+import drrename.model.RenamingPath;
+import javafx.beans.property.ObjectProperty;
+import javafx.beans.property.SimpleObjectProperty;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
+
+@Slf4j
+public class NfoFileNameTreeItemValue extends NfoFileTreeItemValue {
+
+ private final ObjectProperty type;
+
+ private final WarningsConfig warningsConfig;
+
+
+ public NfoFileNameTreeItemValue(RenamingPath moviePath, WarningsConfig warningsConfig, Executor executor) {
+ super(moviePath, true, executor);
+ this.warningsConfig = warningsConfig;
+ this.type = new SimpleObjectProperty<>();
+ updateStatus();
+ missingNfoFileIsWarningProperty().addListener((observable, oldValue, newValue) -> setWarning(calculateWarning()));
+ }
+
+ @Override
+ protected void updateStatus() {
+ var checker = new NfoFileNameChecker();
+ var type = checker.checkDir(getRenamingPath().getOldPath());
+ setNfoFiles(checker.getNfoFiles());
+ setType(type);
+ setWarning(calculateWarning());
+ setCanFix(isWarning() && getNfoFiles().size() == 1);
+ }
+
+ @Override
+ protected String updateIdentifier() {
+ return "NFO File Name";
+ }
+
+ protected String updateMessage(Boolean newValue) {
+ if (getType() == null) {
+ return "unknown";
+ }
+ if (newValue) {
+ return (getType().toString() + getWarningAdditionalInfo());
+ }
+ return (getType().toString());
+ }
+
+ @Override
+ public void fix() throws FixFailedException {
+ Path nfoFile = getNfoFile();
+ try {
+ Path newPath = Files.move(nfoFile, nfoFile.resolveSibling(NfoFiles.DEFAULT_NAME));
+ if(!newPath.getFileName().toString().equals(NfoFiles.DEFAULT_NAME)){
+ throw new FixFailedException("Rename failed");
+ }
+ } catch (IOException e) {
+ throw new FixFailedException(e);
+ }
+ }
+
+ private String getWarningAdditionalInfo() {
+ return getNfoFiles().isEmpty() ? "" : ": " + getNfoFiles().stream().map(f -> f.getFileName().toString()).collect(Collectors.joining(", "));
+ }
+
+ protected boolean calculateWarning() {
+ if (NfoFileNameType.NO_FILE.equals(getType()) && !isMissingNfoFileIsWarning()) {
+ return false;
+ }
+ return !NfoFileNameType.MOVIE_NAME.equals(getType()) && !NfoFileNameType.DEFAULT_NAME.equals(getType());
+ }
+
+ // Getter / Setter //
+
+
+ public NfoFileNameType getType() {
+ return type.get();
+ }
+
+ public ObjectProperty typeProperty() {
+ return type;
+ }
+
+ public void setType(NfoFileNameType type) {
+ this.type.set(type);
+ }
+
+ public WarningsConfig getWarningsConfig() {
+ return warningsConfig;
+ }
+
+
+}
diff --git a/src/main/java/drrename/kodi/treeitem/content/NfoFileNameType.java b/src/main/java/drrename/kodi/nfo/NfoFileNameType.java
similarity index 81%
rename from src/main/java/drrename/kodi/treeitem/content/NfoFileNameType.java
rename to src/main/java/drrename/kodi/nfo/NfoFileNameType.java
index 2a2979b3..519f8b43 100644
--- a/src/main/java/drrename/kodi/treeitem/content/NfoFileNameType.java
+++ b/src/main/java/drrename/kodi/nfo/NfoFileNameType.java
@@ -17,10 +17,10 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content;
+package drrename.kodi.nfo;
public enum NfoFileNameType {
- NO_FILE("No NFO file"), MOVIE_NAME("NFO file name matching movie name"), DEFAULT_NAME("Default NFO file name"), MULTIPLE_FILES("Multiple NFO files"), INVALID_NAME("Invalid NFO file name");
+ NO_FILE("No file"), MOVIE_NAME("File name matching movie name"), DEFAULT_NAME("Default file name"), MULTIPLE_FILES("Multiple files"), INVALID_NAME("Invalid file name"), ERROR("Error");
private final String name;
diff --git a/src/main/java/drrename/model/nfo/NfoFileParser.java b/src/main/java/drrename/kodi/nfo/NfoFileParser.java
similarity index 71%
rename from src/main/java/drrename/model/nfo/NfoFileParser.java
rename to src/main/java/drrename/kodi/nfo/NfoFileParser.java
index 23668eed..18c026d4 100644
--- a/src/main/java/drrename/model/nfo/NfoFileParser.java
+++ b/src/main/java/drrename/kodi/nfo/NfoFileParser.java
@@ -17,19 +17,24 @@
* along with this program. If not, see .
*/
-package drrename.model.nfo;
+package drrename.kodi.nfo;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import drrename.model.nfo.NfoRoot;
+import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.stream.Stream;
+@Slf4j
public class NfoFileParser {
private final XmlMapper xmlMapper;
@@ -50,9 +55,25 @@ public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p,
}
public NfoRoot parse(Path filePath) throws IOException {
-
+ long lineCount;
+ try (Stream stream = Files.lines(filePath)) {
+ lineCount = stream.filter(s -> !s.isBlank()).count();
+ }catch (Exception e){
+ log.debug("Cannot count lines, reason: {}", e.getLocalizedMessage());
+ throw new IOException(e);
+ }
+ if(lineCount == 1){
+ NfoRoot root = new NfoRoot();
+ root.setUrl(Files.readString(filePath));
+ return root;
+ }
String content = "" + String.join("", Files.readAllLines(filePath)) + "";
- return xmlMapper.readValue(content, NfoRoot.class);
+ try {
+ return xmlMapper.readValue(content, NfoRoot.class);
+ } catch (MismatchedInputException e) {
+ log.debug(e.getLocalizedMessage());
+ return null;
+ }
}
}
diff --git a/src/main/java/drrename/kodi/nfo/NfoFileTreeItemValue.java b/src/main/java/drrename/kodi/nfo/NfoFileTreeItemValue.java
new file mode 100644
index 00000000..08442044
--- /dev/null
+++ b/src/main/java/drrename/kodi/nfo/NfoFileTreeItemValue.java
@@ -0,0 +1,74 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.kodi.nfo;
+
+import drrename.kodi.KodiTreeItemValue;
+import drrename.model.RenamingPath;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Base class for all NFO file related {@code KodiTreeItemValue}s.
+ *
+ * @see drrename.kodi.KodiRootTreeItem
+ */
+@Setter
+@Getter
+public abstract class NfoFileTreeItemValue extends KodiTreeItemValue {
+
+ private List nfoFiles;
+
+ private BooleanProperty missingNfoFileIsWarning;
+
+ public NfoFileTreeItemValue(RenamingPath moviePath, boolean fixable, Executor executor) {
+ super(moviePath, fixable, executor);
+ this.nfoFiles = new ArrayList<>();
+ this.missingNfoFileIsWarning = new SimpleBooleanProperty();
+ }
+
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+
+ public Path getNfoFile() {
+ return nfoFiles.isEmpty() ? null : nfoFiles.get(0);
+ }
+
+ public boolean isMissingNfoFileIsWarning() {
+ return missingNfoFileIsWarning.get();
+ }
+
+ public BooleanProperty missingNfoFileIsWarningProperty() {
+ return missingNfoFileIsWarning;
+ }
+
+ public void setMissingNfoFileIsWarning(boolean missingNfoFileIsWarning) {
+ this.missingNfoFileIsWarning.set(missingNfoFileIsWarning);
+ }
+}
+
diff --git a/src/main/java/drrename/kodi/treeitem/NfoFileNameTreeItem.java b/src/main/java/drrename/kodi/nfo/NfoFiles.java
similarity index 76%
rename from src/main/java/drrename/kodi/treeitem/NfoFileNameTreeItem.java
rename to src/main/java/drrename/kodi/nfo/NfoFiles.java
index 58416b65..9374ac90 100644
--- a/src/main/java/drrename/kodi/treeitem/NfoFileNameTreeItem.java
+++ b/src/main/java/drrename/kodi/nfo/NfoFiles.java
@@ -17,13 +17,12 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem;
+package drrename.kodi.nfo;
-import drrename.kodi.treeitem.content.NfoFileNameTreeItemContent;
+public class NfoFiles {
-public class NfoFileNameTreeItem extends KodiTreeItem {
+ public static final String DEFAULT_EXTENSION = "nfo";
+
+ public static final String DEFAULT_NAME = "movie" + "." + DEFAULT_EXTENSION;
- public NfoFileNameTreeItem(NfoFileNameTreeItemContent value) {
- super(value);
- }
}
diff --git a/src/main/java/drrename/kodi/treeitem/content/NfoFileContentCheckService.java b/src/main/java/drrename/kodi/treeitem/content/NfoFileContentCheckService.java
deleted file mode 100644
index b7e275f8..00000000
--- a/src/main/java/drrename/kodi/treeitem/content/NfoFileContentCheckService.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Dr.Rename - A Minimalistic Batch Renamer
- *
- * Copyright (C) 2022
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package drrename.kodi.treeitem.content;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.dataformat.xml.XmlMapper;
-import drrename.kodi.treeitem.KodiTreeItem;
-import drrename.kodi.treeitem.content.check.CheckService;
-import drrename.kodi.treeitem.content.check.NfoFileContentCheckResult;
-import drrename.model.nfo.NfoFileXmlModel;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-
-import java.io.IOException;
-import java.nio.charset.MalformedInputException;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-@RequiredArgsConstructor
-@Slf4j
-public class NfoFileContentCheckService extends CheckService {
-
- @Override
- public KodiTreeItem buildChildItem(NfoFileContentCheckResult checkResult) {
- return new KodiTreeItem(new NfoFileContentTreeItemContent(checkResult));
- }
-
- public NfoFileContentCheckResult checkPath(Path path) throws IOException {
- XmlMapper mapper = new XmlMapper();
- mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
-
- try (DirectoryStream ds = Files.newDirectoryStream(path)) {
- for (Path child : ds) {
- String extension = FilenameUtils.getExtension(child.getFileName().toString());
- if (Files.isRegularFile(child) && "nfo".equalsIgnoreCase(extension)) {
- // we look only at the first file found
- try {
- NfoFileXmlModel xmlFileContent = mapper.readValue(child.toFile(), NfoFileXmlModel.class);
- if (!verifyTitle(path, xmlFileContent)) {
- return new NfoFileContentCheckResult("NFO title mismatch", child, true);
- }
- if (!verifyYear(path, xmlFileContent)) {
- return new NfoFileContentCheckResult("NFO year mismatch", child, true);
- }
- if (!verifyCoverFront(path, xmlFileContent)) {
- return new NfoFileContentCheckResult("NFO front-cover not readable", child, true);
- }
- return new NfoFileContentCheckResult("XML NFO", child, false);
- } catch (JsonParseException e) {
- log.debug("{} for {}", e.getLocalizedMessage(), child);
- try {
- String content = Files.readString(child);
- if (content == null) {
- return new NfoFileContentCheckResult("Empty NFO", child, true);
- }
- if (content.contains("imdb")) {
- return new NfoFileContentCheckResult("Single line NFO (imdb)", child, false);
- } else {
- return new NfoFileContentCheckResult("Unknown NFO content", child, true);
- }
- } catch (MalformedInputException ee) {
- log.debug("{} for {}", ee.getLocalizedMessage(), child);
- log.debug("{} for path {}", ee.getLocalizedMessage(), path);
- return new NfoFileContentCheckResult("Invalid NFO content", child, true);
- }
- }
- }
- }
- return new NfoFileContentCheckResult("No NFO file", null, true);
- }
- }
-
-
- private boolean verifyYear(Path moviePath, NfoFileXmlModel xmlFileContent) {
- return xmlFileContent.getYear() != null && moviePath.getFileName().toString().endsWith("(" + xmlFileContent.getYear() + ")");
- }
-
- private boolean verifyTitle(Path moviePath, NfoFileXmlModel xmlFileContent) {
- return xmlFileContent.getTitle() != null && moviePath.getFileName().toString().startsWith(xmlFileContent.getTitle());
- }
-
- private boolean verifyCoverFront(Path moviePath, NfoFileXmlModel xmlFileContent) {
- if (xmlFileContent.getArt() == null || xmlFileContent.getArt().getPoster() == null) {
- return false;
- }
- Path coverFront = moviePath.resolve(xmlFileContent.getArt().getPoster());
- return Files.isRegularFile(coverFront) && Files.isReadable(coverFront);
- }
-}
diff --git a/src/main/java/drrename/kodi/treeitem/content/NfoFileNameTreeItemContent.java b/src/main/java/drrename/kodi/treeitem/content/NfoFileNameTreeItemContent.java
deleted file mode 100644
index 4c456b77..00000000
--- a/src/main/java/drrename/kodi/treeitem/content/NfoFileNameTreeItemContent.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Dr.Rename - A Minimalistic Batch Renamer
- *
- * Copyright (C) 2022
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package drrename.kodi.treeitem.content;
-
-import drrename.kodi.treeitem.content.check.NfoFileNameCheckResult;
-import drrename.kodi.treeitem.content.check.NfoCheckResultTreeItemContent;
-
-import java.util.stream.Collectors;
-
-public class NfoFileNameTreeItemContent extends NfoCheckResultTreeItemContent {
-
- public NfoFileNameTreeItemContent(NfoFileNameCheckResult checkResult) {
- super(checkResult);
- }
-
- @Override
- public boolean hasWarning() {
- if(NfoFileNameType.NO_FILE.equals(getCheckResult().getType()) && !isMissingNfoIsAWarning()){
- return false;
- }
- return !NfoFileNameType.MOVIE_NAME.equals(getCheckResult().getType()) && !NfoFileNameType.DEFAULT_NAME.equals(getCheckResult().getType());
- }
-
- @Override
- public String toString() {
- if(hasWarning()){
- return super.toString() + " " + getCheckResult().getNfoFiles().stream().map(e -> e.getFileName().toString()).collect(Collectors.joining(", "));
- }
- return super.toString();
- }
-}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/CheckResult.java b/src/main/java/drrename/kodi/treeitem/content/check/CheckResult.java
deleted file mode 100644
index 99d80ca7..00000000
--- a/src/main/java/drrename/kodi/treeitem/content/check/CheckResult.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Dr.Rename - A Minimalistic Batch Renamer
- *
- * Copyright (C) 2022
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package drrename.kodi.treeitem.content.check;
-
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-
-import java.util.Objects;
-
-public class CheckResult {
-
- protected final StringProperty result;
-
- public CheckResult(String result) {
- this.result = new SimpleStringProperty(result);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof CheckResult that)) return false;
- return Objects.equals(getResult(), that.getResult());
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(result);
- }
-
- @Override
- public String toString() {
- return getResult();
- }
-
- // Getter / Setter //
-
- public String getResult() {
- return result.get();
- }
-
- public StringProperty resultProperty() {
- return result;
- }
-
- public void setResult(String result) {
- this.result.set(result);
- }
-
-
-}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/NfoFileNameCheckResult.java b/src/main/java/drrename/kodi/treeitem/content/check/NfoFileNameCheckResult.java
deleted file mode 100644
index 9a8cd6a5..00000000
--- a/src/main/java/drrename/kodi/treeitem/content/check/NfoFileNameCheckResult.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Dr.Rename - A Minimalistic Batch Renamer
- *
- * Copyright (C) 2022
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package drrename.kodi.treeitem.content.check;
-
-import drrename.kodi.treeitem.content.NfoFileNameType;
-import javafx.beans.property.ListProperty;
-import javafx.beans.property.SimpleListProperty;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-
-import java.nio.file.Path;
-import java.util.Collection;
-
-public class NfoFileNameCheckResult extends NfoCheckResult {
-
- private final ListProperty nfoFiles;
- private final NfoFileNameType type;
-
- public NfoFileNameCheckResult(NfoFileNameType result, Collection nfoFiles) {
- super(result.toString());
- this.type = result;
- this.nfoFiles = new SimpleListProperty<>(FXCollections.observableArrayList(nfoFiles));
- }
-
- @Override
- public Path getNfoFile() {
- return getNfoFiles().isEmpty() ? null : getNfoFiles().get(0);
- }
-
- // Getter / Setter //
-
- public NfoFileNameType getType() {
- return type;
- }
-
- public ObservableList getNfoFiles() {
- return nfoFiles.get();
- }
-
- public ListProperty nfoFilesProperty() {
- return nfoFiles;
- }
-
- public void setNfoFiles(ObservableList nfoFiles) {
- this.nfoFiles.set(nfoFiles);
- }
-
-
-}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/NfoFileNameCheckService.java b/src/main/java/drrename/kodi/treeitem/content/check/NfoFileNameCheckService.java
deleted file mode 100644
index 0ed1ca0a..00000000
--- a/src/main/java/drrename/kodi/treeitem/content/check/NfoFileNameCheckService.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Dr.Rename - A Minimalistic Batch Renamer
- *
- * Copyright (C) 2022
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package drrename.kodi.treeitem.content.check;
-
-import drrename.kodi.treeitem.NfoFileNameTreeItem;
-import drrename.kodi.treeitem.content.NfoFileNameType;
-import drrename.kodi.treeitem.content.NfoFileNameTreeItemContent;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-
-import java.io.IOException;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-
-@Slf4j
-public class NfoFileNameCheckService extends CheckService {
-
- @Override
- public NfoFileNameTreeItem buildChildItem(NfoFileNameCheckResult checkResult) {
- return new NfoFileNameTreeItem(new NfoFileNameTreeItemContent(checkResult));
- }
-
- @Override
- public NfoFileNameCheckResult checkPath(Path path) throws IOException {
- if(!Files.isDirectory(path)){
- throw new IllegalArgumentException(path.getFileName().toString() + " is not a directory");
- }
- String movieName = path.getFileName().toString();
- List childString = new ArrayList<>();
- NfoFileNameType type = NfoFileNameType.NO_FILE;
- try (DirectoryStream ds = Files.newDirectoryStream(path)) {
- for (Path child : ds) {
- String extension = FilenameUtils.getExtension(child.getFileName().toString());
- if (Files.isRegularFile(child) && "nfo".equalsIgnoreCase(extension)) {
- childString.add(child);
- if(childString.size() > 1){
- type = NfoFileNameType.MULTIPLE_FILES;
- } else {
- type = checkFile(movieName, child);
- }
- }
- }
- }
- return new NfoFileNameCheckResult(type, childString);
- }
-
- static NfoFileNameType checkFile(String movieName, Path child) {
- if(!Files.isRegularFile(child)){
- throw new IllegalArgumentException(child.getFileName().toString() + " is not a directory");
- }
- String childName = child.getFileName().toString();
- if ("movie.nfo".equalsIgnoreCase(childName)) {
- return NfoFileNameType.DEFAULT_NAME;
- } else if (FilenameUtils.getBaseName(childName).equalsIgnoreCase(movieName)) {
- return NfoFileNameType.MOVIE_NAME;
- } else {
- return NfoFileNameType.INVALID_NAME;
- }
- }
-
-
-}
diff --git a/src/main/java/drrename/kodi/treeitem/content/check/CheckService.java b/src/main/java/drrename/mime/FileTypeByMimeProvider.java
similarity index 57%
rename from src/main/java/drrename/kodi/treeitem/content/check/CheckService.java
rename to src/main/java/drrename/mime/FileTypeByMimeProvider.java
index 10cff9cd..e39fe0f4 100644
--- a/src/main/java/drrename/kodi/treeitem/content/check/CheckService.java
+++ b/src/main/java/drrename/mime/FileTypeByMimeProvider.java
@@ -17,31 +17,37 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem.content.check;
+package drrename.mime;
-import drrename.kodi.treeitem.KodiTreeItem;
-import drrename.kodi.treeitem.MovieTreeItem;
-import javafx.application.Platform;
+import drrename.FileTypeProvider;
import lombok.extern.slf4j.Slf4j;
+import org.apache.tika.Tika;
-import java.io.IOException;
+import java.io.File;
+import java.nio.file.Files;
import java.nio.file.Path;
@Slf4j
-public abstract class CheckService {
+public class FileTypeByMimeProvider implements FileTypeProvider {
- public void addChildItem(MovieTreeItem treeItem) {
+ public static String UNKNOWN = "n/a";
+
+ public static String DIRECTORY = "directory";
+
+ @Override
+ public String getFileType(Path path) {
+ final File file = path.toFile();
+ if(Files.isDirectory(path)){
+ return DIRECTORY;
+ }
try {
- R checkResult = checkPath(treeItem.getMoviePath());
- var childItem = buildChildItem(checkResult);
- if(!treeItem.contains(childItem))
- Platform.runLater(() -> treeItem.add(childItem));
- }catch (IOException e){
+ Tika tika = new Tika();
+ @SuppressWarnings("")
+ var result = tika.detect(file);
+ return result;
+ } catch (Exception e) {
log.error(e.getLocalizedMessage(), e);
+ return UNKNOWN;
}
}
-
- public abstract R checkPath(Path path) throws IOException;
-
- public abstract KodiTreeItem buildChildItem(R checkResult);
}
diff --git a/src/main/java/drrename/model/RenamingControl.java b/src/main/java/drrename/model/RenamingControl.java
new file mode 100644
index 00000000..91cbd14e
--- /dev/null
+++ b/src/main/java/drrename/model/RenamingControl.java
@@ -0,0 +1,120 @@
+package drrename.model;
+
+import drrename.ui.Styles;
+import javafx.beans.binding.Bindings;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+import javafx.beans.value.ObservableValue;
+import javafx.geometry.Insets;
+import javafx.scene.control.Control;
+import javafx.scene.control.Label;
+import lombok.extern.slf4j.Slf4j;
+
+import java.nio.file.Path;
+import java.util.concurrent.Callable;
+
+@Slf4j
+public class RenamingControl extends RenamingPath {
+
+ private final StringProperty fileType;
+
+ private final Control leftControl;
+
+ private final Control rightControl;
+
+ public RenamingControl(final Path path) {
+ super(path);
+
+ this.fileType = new SimpleStringProperty();
+ newPath.addListener((v, o, n) -> willChange.set(!getOldPath().getFileName().toString().equals(n)));
+ oldPath.addListener((observable, oldValue, newValue) -> willChange.set(!getOldPath().getFileName().toString().equals(getNewPath())));
+ leftControl = buildLeft();
+ rightControl = buildRight();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "{" + getOldPath().toString() + "}";
+ }
+
+ protected Control buildLeft() {
+
+ final Label tLeft = new Label();
+ tLeft.setPadding(new Insets(2, 2, 2, 2));
+ tLeft.textProperty().bind(buildTextBindingLeft());
+ tLeft.styleProperty().bind(buildStyleBindingLeft());
+
+ return tLeft;
+ }
+
+ protected ObservableValue buildStyleBindingLeft() {
+ return Bindings.createObjectBinding(this::calcStyleLeft);
+ }
+
+ protected ObservableValue buildTextBindingLeft() {
+ return Bindings.createObjectBinding(this::calculateOldPath, oldPathProperty());
+ }
+
+ protected String calculateOldPath() {
+ return getOldPath().getFileName().toString();
+ }
+
+ protected String calcStyleLeft() {
+ final StringBuilder sb = new StringBuilder();
+ if (getOldPath().toFile().isDirectory()) {
+ sb.append(Styles.directoryStyle());
+ }
+ if (sb.toString().length() > 0)
+ return sb.toString();
+ return Styles.defaultStyle();
+ }
+
+ protected Control buildRight() {
+
+ final Label tRight = new Label();
+ tRight.setPadding(new Insets(2, 2, 2, 2));
+ tRight.setMaxWidth(Double.POSITIVE_INFINITY);
+ tRight.textProperty().bind(Bindings.createStringBinding(buildTextRight(), exceptionProperty(), newPathProperty()));
+ tRight.styleProperty().bind(
+ Bindings.createObjectBinding(this::calcStyleRight, willChangeProperty(), exceptionProperty(), newPathProperty()));
+ return tRight;
+ }
+
+ protected Callable buildTextRight() {
+ return () -> {
+ if (getException() != null)
+ return getException().toString();
+ return getNewPath() == null ? null : getNewPath();
+ };
+ }
+
+ protected String calcStyleRight() {
+ if (isWillChange()) {
+ return Styles.changingStyle();
+ }
+ return Styles.defaultStyle();
+ }
+
+ // Getter / Setter //
+
+
+ public StringProperty fileTypeProperty() {
+ return fileType;
+ }
+
+ public String getFileType() {
+ return fileType.get();
+ }
+
+ public void setFileType(String fileType) {
+ fileTypeProperty().set(fileType);
+ }
+
+ public Control getLeftControl() {
+ return leftControl;
+ }
+
+ public Control getRightControl() {
+ return rightControl;
+ }
+}
diff --git a/src/main/java/drrename/model/RenamingEntry.java b/src/main/java/drrename/model/RenamingEntry.java
deleted file mode 100644
index eda840e6..00000000
--- a/src/main/java/drrename/model/RenamingEntry.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package drrename.model;
-
-import drrename.strategy.RenamingStrategy;
-import drrename.ui.Styles;
-import javafx.application.Platform;
-import javafx.beans.binding.Bindings;
-import javafx.beans.property.*;
-import javafx.beans.value.ObservableValue;
-import javafx.geometry.Insets;
-import javafx.scene.control.Control;
-import javafx.scene.control.Label;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.FileNotFoundException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Objects;
-import java.util.concurrent.Callable;
-
-@Slf4j
-public class RenamingEntry {
-
- private final ObjectProperty oldPath;
- private final StringProperty newPath;
- private final ObjectProperty exception;
- private final BooleanProperty willChange;
- private final BooleanProperty filtered;
- private final StringProperty fileType;
-
- private final Control leftControl;
-
- private final Control rightControl;
-
- public RenamingEntry(final Path path) {
-
- this.oldPath = new SimpleObjectProperty<>(Objects.requireNonNull(path));
- this.newPath = new SimpleStringProperty();
- exception = new SimpleObjectProperty<>();
- this.willChange = new SimpleBooleanProperty();
- this.fileType = new SimpleStringProperty();
- this.filtered = new SimpleBooleanProperty();
- newPath.addListener((v, o, n) -> willChange.set(!getOldPath().getFileName().toString().equals(n)));
- oldPath.addListener((observable, oldValue, newValue) -> willChange.set(!getOldPath().getFileName().toString().equals(getNewPath())));
- leftControl = buildLeft();
- rightControl = buildRight();
- }
-
- public String preview(final RenamingStrategy strategy) {
-
- if (Files.exists(getOldPath())) {
- final String s = strategy.getNameNew(getOldPath());
- Platform.runLater(() -> newPath.set(s));
- return s;
- }
- var exception = new FileNotFoundException(getOldPath().getFileName().toString());
- Platform.runLater(() -> exceptionProperty().set(exception));
- return null;
- }
-
- public Path rename(final RenamingStrategy strategy) {
- if (isFiltered()) {
- log.warn("Rename called on filtered entry, skipping {}", this);
- return getOldPath();
- }
- try {
- Path newPath = strategy.rename(getOldPath(), null);
- Platform.runLater(() -> commitRename(newPath));
- return newPath;
- } catch (final Exception e) {
- log.debug(e.getLocalizedMessage(), e);
- Platform.runLater(() -> this.exception.set(e));
- return getOldPath();
- }
- }
-
- public void commitRename(Path newPath) {
- setOldPath(newPath);
- exceptionProperty().set(null);
- // for now set to false to see an immediate effect, preview service should be triggered and should update this any time soon again.
- setWillChange(false);
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "{" + getOldPath().toString() + "}";
- }
-
- protected Control buildLeft() {
-
- final Label tLeft = new Label();
- tLeft.setPadding(new Insets(2, 2, 2, 2));
- tLeft.textProperty().bind(buildTextBindingLeft());
- tLeft.styleProperty().bind(buildStyleBindingLeft());
-
- return tLeft;
- }
-
- protected ObservableValue buildStyleBindingLeft() {
- return Bindings.createObjectBinding(this::calcStyleLeft);
- }
-
- protected ObservableValue buildTextBindingLeft() {
- return Bindings.createObjectBinding(this::calculateOldPath, oldPathProperty());
- }
-
- protected String calculateOldPath() {
- return getOldPath().getFileName().toString();
- }
-
- protected String calcStyleLeft() {
- final StringBuilder sb = new StringBuilder();
- if (getOldPath().toFile().isDirectory()) {
- sb.append(Styles.directoryStyle());
- }
- if (sb.toString().length() > 0)
- return sb.toString();
- return Styles.defaultStyle();
- }
-
- protected Control buildRight() {
-
- final Label tRight = new Label();
- tRight.setPadding(new Insets(2, 2, 2, 2));
- tRight.setMaxWidth(Double.POSITIVE_INFINITY);
- tRight.textProperty().bind(Bindings.createStringBinding(buildTextRight(), exceptionProperty(), newPathProperty()));
- tRight.styleProperty().bind(
- Bindings.createObjectBinding(this::calcStyleRight, willChangeProperty(), exceptionProperty(), newPathProperty()));
- return tRight;
- }
-
- protected Callable buildTextRight() {
- return () -> {
- if (getException() != null)
- return getException().toString();
- return getNewPath() == null ? null : getNewPath();
- };
- }
-
- protected String calcStyleRight() {
- if (willChange()) {
- return Styles.changingStyle();
- }
- return Styles.defaultStyle();
- }
-
- // Getter / Setter //
-
-
- public BooleanProperty filteredProperty() {
- return filtered;
- }
-
- public boolean isFiltered() {
- return filtered.get();
- }
-
- public void setFiltered(boolean filtered) {
- this.filtered.set(filtered);
- }
-
- public StringProperty fileTypeProperty() {
- return fileType;
- }
-
- public String getFileType() {
- return fileType.get();
- }
-
- public void setFileType(String fileType) {
- fileTypeProperty().set(fileType);
- }
-
- public void setNewPath(String newPath) {
- this.newPath.set(newPath);
- }
-
- public String getNewPath() {
- return newPath.get();
- }
-
- public Throwable getException() {
- return exception.get();
- }
-
- public ObjectProperty exceptionProperty() {
- return exception;
- }
-
- public StringProperty newPathProperty() {
- return newPath;
- }
-
- public BooleanProperty willChangeProperty() {
- return this.willChange;
- }
-
- public boolean willChange() {
- return this.willChangeProperty().get();
- }
-
- public void setWillChange(final boolean willChange) {
- this.willChangeProperty().set(willChange);
- }
-
- public ObjectProperty oldPathProperty() {
- return this.oldPath;
- }
-
- public Path getOldPath() {
- return this.oldPathProperty().get();
- }
-
- public void setOldPath(final Path oldPath) {
- this.oldPathProperty().set(oldPath);
- }
-
- public Control getLeftControl() {
- return leftControl;
- }
-
- public Control getRightControl() {
- return rightControl;
- }
-}
diff --git a/src/main/java/drrename/model/RenamingPath.java b/src/main/java/drrename/model/RenamingPath.java
new file mode 100644
index 00000000..e8a9dde0
--- /dev/null
+++ b/src/main/java/drrename/model/RenamingPath.java
@@ -0,0 +1,175 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.model;
+
+import drrename.strategy.RenamingStrategy;
+import javafx.application.Platform;
+import javafx.beans.property.*;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.FileNotFoundException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+
+@Slf4j
+public class RenamingPath {
+ protected final ObjectProperty oldPath;
+
+ protected final StringProperty newPath;
+
+ protected final ObjectProperty exception;
+
+ protected final BooleanProperty willChange;
+
+ protected final BooleanProperty filtered;
+
+ protected final StringProperty movieName;
+ private final ChangeListener super Path> listener;
+
+ public RenamingPath(final Path path) {
+ listener = new ChangeListener() {
+ @Override
+ public void changed(ObservableValue extends Path> observableValue, Path path, Path t1) {
+ movieName.set(t1.getFileName().toString());
+ }
+ };
+ this.oldPath = new SimpleObjectProperty<>();
+ this.newPath = new SimpleStringProperty();
+ this.movieName = new SimpleStringProperty();
+ this.exception = new SimpleObjectProperty<>();
+ this.willChange = new SimpleBooleanProperty();
+ this.filtered = new SimpleBooleanProperty();
+ oldPath.addListener(listener);
+ oldPath.set(Objects.requireNonNull(path));
+ }
+
+ public String preview(final RenamingStrategy strategy) {
+
+ if (Files.exists(getOldPath())) {
+ final String s = strategy.getNameNew(getOldPath());
+ Platform.runLater(() -> newPath.set(s));
+ return s;
+ }
+ var exception = new FileNotFoundException(getOldPath().getFileName().toString());
+ Platform.runLater(() -> exceptionProperty().set(exception));
+ return null;
+ }
+
+ public Path rename(final RenamingStrategy strategy) {
+ if (isFiltered()) {
+ log.warn("Rename called on filtered entry, skipping {}", this);
+ return getOldPath();
+ }
+ try {
+ Path newPath = strategy.rename(getOldPath(), null);
+ Platform.runLater(() -> commitRename(newPath));
+ return newPath;
+ } catch (final Exception e) {
+ log.debug(e.getLocalizedMessage(), e);
+ Platform.runLater(() -> this.exception.set(e));
+ return getOldPath();
+ }
+ }
+
+ public void commitRename(Path newPath) {
+ setOldPath(newPath);
+ exceptionProperty().set(null);
+ // for now set to false to see an immediate effect, preview service should be triggered and should update this any time soon again.
+ setWillChange(false);
+ }
+
+ // Getter / Setter //
+
+
+ public String getMovieName() {
+ return movieName.get();
+ }
+
+ public StringProperty movieNameProperty() {
+ return movieName;
+ }
+
+ public void setMovieName(String movieName) {
+ this.movieName.set(movieName);
+ }
+
+ public Path getOldPath() {
+ return oldPath.get();
+ }
+
+ public void setOldPath(Path oldPath) {
+ this.oldPath.set(oldPath);
+ }
+
+ public String getNewPath() {
+ return newPath.get();
+ }
+
+ public void setNewPath(String newPath) {
+ this.newPath.set(newPath);
+ }
+
+ public Throwable getException() {
+ return exception.get();
+ }
+
+ public void setException(Throwable exception) {
+ this.exception.set(exception);
+ }
+
+ public boolean isWillChange() {
+ return willChange.get();
+ }
+
+ public void setWillChange(boolean willChange) {
+ this.willChange.set(willChange);
+ }
+
+ public boolean isFiltered() {
+ return filtered.get();
+ }
+
+ public void setFiltered(boolean filtered) {
+ this.filtered.set(filtered);
+ }
+
+ public BooleanProperty filteredProperty() {
+ return filtered;
+ }
+
+ public ObjectProperty exceptionProperty() {
+ return exception;
+ }
+
+ public StringProperty newPathProperty() {
+ return newPath;
+ }
+
+ public BooleanProperty willChangeProperty() {
+ return this.willChange;
+ }
+
+ public ObjectProperty oldPathProperty() {
+ return this.oldPath;
+ }
+}
diff --git a/src/main/java/drrename/kodi/treeitem/MovieTreeItem.java b/src/main/java/drrename/model/themoviedb/SearchResultDto.java
similarity index 63%
rename from src/main/java/drrename/kodi/treeitem/MovieTreeItem.java
rename to src/main/java/drrename/model/themoviedb/SearchResultDto.java
index 2ff6503e..27de1a36 100644
--- a/src/main/java/drrename/kodi/treeitem/MovieTreeItem.java
+++ b/src/main/java/drrename/model/themoviedb/SearchResultDto.java
@@ -17,23 +17,30 @@
* along with this program. If not, see .
*/
-package drrename.kodi.treeitem;
+package drrename.model.themoviedb;
-import drrename.kodi.treeitem.content.MovieTreeItemContent;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
-import java.nio.file.Path;
+import java.time.LocalDate;
-public class MovieTreeItem extends KodiTreeItem {
+@Data
+public class SearchResultDto {
- public MovieTreeItem(MovieTreeItemContent content) {
- super(content);
- }
+ @JsonProperty("original_title")
+ String originalTitle;
- public MovieTreeItem(Path moviePath) {
- this(new MovieTreeItemContent(moviePath));
- }
+ @JsonProperty("title")
+ String title;
- public Path getMoviePath(){
- return ((MovieTreeItemContent)getValue()).getMoviePath();
- }
+ @JsonProperty("overview")
+ String overview;
+
+ Number id;
+
+ @JsonProperty("release_date")
+ LocalDate releaseDate;
+
+ @JsonProperty("poster_path")
+ String posterPath;
}
diff --git a/src/main/java/drrename/model/themoviedb/SearchResultsDto.java b/src/main/java/drrename/model/themoviedb/SearchResultsDto.java
new file mode 100644
index 00000000..2ad7c33a
--- /dev/null
+++ b/src/main/java/drrename/model/themoviedb/SearchResultsDto.java
@@ -0,0 +1,30 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.model.themoviedb;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SearchResultsDto {
+
+ List results;
+}
diff --git a/src/main/java/drrename/model/themoviedb/TranslationData.java b/src/main/java/drrename/model/themoviedb/TranslationData.java
new file mode 100644
index 00000000..46a216d3
--- /dev/null
+++ b/src/main/java/drrename/model/themoviedb/TranslationData.java
@@ -0,0 +1,28 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.model.themoviedb;
+
+import lombok.Data;
+
+@Data
+public class TranslationData {
+
+ String title;
+}
diff --git a/src/main/java/drrename/model/themoviedb/TranslationDto.java b/src/main/java/drrename/model/themoviedb/TranslationDto.java
new file mode 100644
index 00000000..b892bf57
--- /dev/null
+++ b/src/main/java/drrename/model/themoviedb/TranslationDto.java
@@ -0,0 +1,35 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.model.themoviedb;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class TranslationDto {
+
+ @JsonProperty("iso_3166_1")
+ String iso3166;
+
+ @JsonProperty("iso_639_1")
+ String iso639;
+
+ TranslationData data;
+}
diff --git a/src/main/java/drrename/model/themoviedb/TranslationsDto.java b/src/main/java/drrename/model/themoviedb/TranslationsDto.java
new file mode 100644
index 00000000..9bcf6a7c
--- /dev/null
+++ b/src/main/java/drrename/model/themoviedb/TranslationsDto.java
@@ -0,0 +1,31 @@
+/*
+ * Dr.Rename - A Minimalistic Batch Renamer
+ *
+ * Copyright (C) 2022
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package drrename.model.themoviedb;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class TranslationsDto {
+
+ List translations;
+
+}
diff --git a/src/main/java/drrename/service/EntriesService.java b/src/main/java/drrename/service/EntriesService.java
index 54885385..e16855f4 100644
--- a/src/main/java/drrename/service/EntriesService.java
+++ b/src/main/java/drrename/service/EntriesService.java
@@ -3,7 +3,7 @@
import drrename.config.AppConfig;
import drrename.event.FileRenamedEvent;
import drrename.event.NewRenamingEntryEvent;
-import drrename.model.RenamingEntry;
+import drrename.model.RenamingControl;
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.property.*;
@@ -44,25 +44,25 @@ public class EntriesService {
private final AppConfig appConfig;
- private final ListProperty entries;
+ private final ListProperty entries;
- private final ListProperty entriesFiltered;
+ private final ListProperty entriesFiltered;
- private final FilteredList entriesWillRename;
+ private final FilteredList entriesWillRename;
- private final FilteredList loadedImageEntries;
+ private final FilteredList loadedImageEntries;
- private final FilteredList loadedVideosEntries;
+ private final FilteredList loadedVideosEntries;
- private final FilteredList willRenameImageEntries;
+ private final FilteredList willRenameImageEntries;
- private final FilteredList willRenameVideosEntries;
+ private final FilteredList willRenameVideosEntries;
- private final ListProperty entriesRenamed;
+ private final ListProperty entriesRenamed;
- private final FilteredList renamedImageEntries;
+ private final FilteredList renamedImageEntries;
- private final FilteredList renamedVideosEntries;
+ private final FilteredList renamedVideosEntries;
private final StringProperty statusLoaded = new SimpleStringProperty();
@@ -82,13 +82,13 @@ public class EntriesService {
private final BooleanProperty showOnlyChainging = new SimpleBooleanProperty();
- private final Predicate entriesFilteredDefaultPredicate = e -> true;
+ private final Predicate entriesFilteredDefaultPredicate = e -> true;
- private final static Predicate isImage = e -> e.getFileType() != null && e.getFileType().contains("image");
+ private final static Predicate isImage = e -> e.getFileType() != null && e.getFileType().contains("image");
- private final static Predicate isVideo = e -> e.getFileType() != null && e.getFileType().contains("video");
+ private final static Predicate isVideo = e -> e.getFileType() != null && e.getFileType().contains("video");
- private final static Predicate noHidden = e -> {
+ private final static Predicate noHidden = e -> {
try {
return !Files.isHidden(e.getOldPath());
} catch (IOException ex) {
@@ -98,9 +98,9 @@ public class EntriesService {
}
};
- private final static Predicate noDirectories = e -> !Files.isDirectory(e.getOldPath());
+ private final static Predicate noDirectories = e -> !Files.isDirectory(e.getOldPath());
- private final static Predicate onlyChanging = RenamingEntry::willChange;
+ private final static Predicate onlyChanging = RenamingControl::isWillChange;
public EntriesService(ResourceBundle resourceBundle, AppConfig appConfig, Executor executor) {
this.resourceBundle = resourceBundle;
@@ -108,7 +108,7 @@ public EntriesService(ResourceBundle resourceBundle, AppConfig appConfig, Execut
entries = new SimpleListProperty<>(FXCollections.observableArrayList(item -> new Observable[]{item.newPathProperty(), item.exceptionProperty(), item.fileTypeProperty(), item.filteredProperty(), item.willChangeProperty()}));
entriesFiltered = new SimpleListProperty<>(new FilteredList<>(entries, entriesFilteredDefaultPredicate));
entriesRenamed = new SimpleListProperty<>(FXCollections.observableArrayList());
- entriesWillRename = new FilteredList<>(entries, RenamingEntry::willChange);
+ entriesWillRename = new FilteredList<>(entries, RenamingControl::isWillChange);
loadedImageEntries = new FilteredList<>(entries, isImage);
loadedVideosEntries = new FilteredList<>(entries, isVideo);
willRenameImageEntries = new FilteredList<>(entriesWillRename, isImage);
@@ -130,29 +130,29 @@ private void initListeners() {
entries.sizeProperty().addListener((observable, oldValue, newValue) -> statusLoaded.setValue(String.format(resourceBundle.getString(LOADED), newValue)));
- entriesWillRename.addListener((ListChangeListener) c -> statusWillRename.setValue(String.format(resourceBundle.getString(WILL_RENAME), c.getList().size())));
+ entriesWillRename.addListener((ListChangeListener) c -> statusWillRename.setValue(String.format(resourceBundle.getString(WILL_RENAME), c.getList().size())));
entriesRenamed.sizeProperty().addListener((observable, oldValue, newValue) -> statusRenamed.setValue(String.format(resourceBundle.getString(RENAMED), newValue)));
- loadedImageEntries.addListener((ListChangeListener) c -> updateLoadedFileTypesLabel());
+ loadedImageEntries.addListener((ListChangeListener) c -> updateLoadedFileTypesLabel());
- loadedVideosEntries.addListener((ListChangeListener) c -> updateLoadedFileTypesLabel());
+ loadedVideosEntries.addListener((ListChangeListener) c -> updateLoadedFileTypesLabel());
- willRenameImageEntries.addListener((ListChangeListener) c -> updateWillRenameFileTypesLabel());
+ willRenameImageEntries.addListener((ListChangeListener) c -> updateWillRenameFileTypesLabel());
- willRenameVideosEntries.addListener((ListChangeListener) c -> updateWillRenameFileTypesLabel());
+ willRenameVideosEntries.addListener((ListChangeListener) c -> updateWillRenameFileTypesLabel());
- renamedImageEntries.addListener((ListChangeListener) c -> updateRenamedFileTypesLabel());
+ renamedImageEntries.addListener((ListChangeListener) c -> updateRenamedFileTypesLabel());
- renamedVideosEntries.addListener((ListChangeListener) c -> updateRenamedFileTypesLabel());
+ renamedVideosEntries.addListener((ListChangeListener) c -> updateRenamedFileTypesLabel());
- filterHiddenFiles.addListener((observable, oldValue, newValue) -> ((FilteredList)entriesFiltered.get()).setPredicate(getCombinedPredicate()));
- filterDirectories.addListener((observable, oldValue, newValue) -> ((FilteredList)entriesFiltered.get()).setPredicate(getCombinedPredicate()));
- showOnlyChainging.addListener((observable, oldValue, newValue) -> ((FilteredList)entriesFiltered.get()).setPredicate(getCombinedPredicate()));
+ filterHiddenFiles.addListener((observable, oldValue, newValue) -> ((FilteredList)entriesFiltered.get()).setPredicate(getCombinedPredicate()));
+ filterDirectories.addListener((observable, oldValue, newValue) -> ((FilteredList)entriesFiltered.get()).setPredicate(getCombinedPredicate()));
+ showOnlyChainging.addListener((observable, oldValue, newValue) -> ((FilteredList)entriesFiltered.get()).setPredicate(getCombinedPredicate()));
}
- private Predicate super RenamingEntry> getCombinedPredicate() {
- Predicate resultPredicate = null;
+ private Predicate super RenamingControl> getCombinedPredicate() {
+ Predicate resultPredicate = null;
if(isFilterHiddenFiles()){
resultPredicate = noHidden;
}
@@ -191,7 +191,7 @@ public void onFileRenamedEvent(FileRenamedEvent event) {
// Getter / Setter
- public ObservableList getEntries() {
+ public ObservableList getEntries() {
return entries.get();
}
@@ -255,8 +255,8 @@ public void setFilterHiddenFiles(boolean filterHiddenFiles) {
this.filterHiddenFiles.set(filterHiddenFiles);
}
- public FilteredList getEntriesFiltered() {
- return (FilteredList) entriesFiltered.get();
+ public FilteredList getEntriesFiltered() {
+ return (FilteredList) entriesFiltered.get();
}
public boolean isFilterDirectories() {
@@ -283,7 +283,7 @@ public void setShowOnlyChainging(boolean showOnlyChainging) {
this.showOnlyChainging.set(showOnlyChainging);
}
- public List getEntriesRenamed() {
+ public List getEntriesRenamed() {
return entriesRenamed;
}
}
diff --git a/src/main/java/drrename/strategy/MediaMetadataRenamingStrategy.java b/src/main/java/drrename/strategy/MediaMetadataRenamingStrategy.java
index a247db4f..717358ef 100644
--- a/src/main/java/drrename/strategy/MediaMetadataRenamingStrategy.java
+++ b/src/main/java/drrename/strategy/MediaMetadataRenamingStrategy.java
@@ -1,5 +1,12 @@
package drrename.strategy;
+import com.drew.imaging.ImageMetadataReader;
+import com.drew.metadata.Directory;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
+
import java.nio.file.Path;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
@@ -8,14 +15,6 @@
import java.util.List;
import java.util.ResourceBundle;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-
-import com.drew.imaging.ImageMetadataReader;
-import com.drew.metadata.Directory;
-import com.drew.metadata.Metadata;
-import com.drew.metadata.Tag;
-
@Slf4j
public class MediaMetadataRenamingStrategy extends RenamingStrategyProto {
diff --git a/src/main/java/drrename/strategy/RegexReplaceRenamingStrategy.java b/src/main/java/drrename/strategy/RegexReplaceRenamingStrategy.java
index 53e85413..d6cdad07 100644
--- a/src/main/java/drrename/strategy/RegexReplaceRenamingStrategy.java
+++ b/src/main/java/drrename/strategy/RegexReplaceRenamingStrategy.java
@@ -1,11 +1,11 @@
package drrename.strategy;
+import lombok.extern.slf4j.Slf4j;
+
import java.nio.file.Path;
import java.util.ResourceBundle;
import java.util.regex.PatternSyntaxException;
-import lombok.extern.slf4j.Slf4j;
-
@Slf4j
public class RegexReplaceRenamingStrategy extends RenamingStrategyProto {
diff --git a/src/main/java/drrename/strategy/RenamingStrategy.java b/src/main/java/drrename/strategy/RenamingStrategy.java
index d4164a15..d9cf8e33 100644
--- a/src/main/java/drrename/strategy/RenamingStrategy.java
+++ b/src/main/java/drrename/strategy/RenamingStrategy.java
@@ -35,7 +35,7 @@ public interface RenamingStrategy {
Path rename(Path file, BasicFileAttributes attrs) throws IOException, InterruptedException;
- void setReplacementStringFrom(String replacement);
+ RenamingStrategyProto setReplacementStringFrom(String replacement);
- void setReplacementStringTo(String replacement);
+ RenamingStrategyProto setReplacementStringTo(String replacement);
}
diff --git a/src/main/java/drrename/strategy/RenamingStrategyProto.java b/src/main/java/drrename/strategy/RenamingStrategyProto.java
index 376895a9..f69c8c1d 100644
--- a/src/main/java/drrename/strategy/RenamingStrategyProto.java
+++ b/src/main/java/drrename/strategy/RenamingStrategyProto.java
@@ -1,5 +1,10 @@
package drrename.strategy;
+import drrename.RenameUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
@@ -9,10 +14,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
-
@Slf4j
public abstract class RenamingStrategyProto implements RenamingStrategy {
@@ -65,7 +66,7 @@ protected Path doRename(final Path file, String nameNew) throws IOException {
return file;
}
log.debug("Renaming" + IOUtils.LINE_SEPARATOR + "old:\t" + nameOld + IOUtils.LINE_SEPARATOR + "new:\t" + nameNew);
- return Files.move(file, file.resolveSibling(nameNew));
+ return RenameUtil.rename(file, nameNew);
} catch (final FileAlreadyExistsException e) {
log.debug(e.getLocalizedMessage());
return doRename(file, getFileAlreadyExistsFileName(nameNew, fileNameCounter));
@@ -106,13 +107,15 @@ public Path rename(final Path file, final BasicFileAttributes attrs) throws IOEx
}
@Override
- public void setReplacementStringFrom(final String replacementStringFrom) {
+ public RenamingStrategyProto setReplacementStringFrom(final String replacementStringFrom) {
this.replacementStringFrom = replacementStringFrom;
+ return this;
}
@Override
- public void setReplacementStringTo(final String replacementStringTo) {
+ public RenamingStrategyProto setReplacementStringTo(final String replacementStringTo) {
this.replacementStringTo = replacementStringTo;
+ return this;
}
@Override
diff --git a/src/main/java/drrename/ui/FilterableTreeItem.java b/src/main/java/drrename/ui/FilterableTreeItem.java
index c89ce071..343ca887 100644
--- a/src/main/java/drrename/ui/FilterableTreeItem.java
+++ b/src/main/java/drrename/ui/FilterableTreeItem.java
@@ -27,11 +27,10 @@
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
+import javafx.scene.Node;
import javafx.scene.control.TreeItem;
import javafx.util.Callback;
-import java.util.Collection;
-import java.util.LinkedHashSet;
import java.util.function.Predicate;
public class FilterableTreeItem extends TreeItem {
@@ -39,34 +38,49 @@ public class FilterableTreeItem extends TreeItem {
// Do not convert this to a local variable. Thinks will break.
protected final FilteredList> filteredChildren;
- protected final ObjectProperty> predicate = new SimpleObjectProperty<>();
+ protected final ObjectProperty> predicate;
+
+ public FilterableTreeItem() {
+ predicate = new SimpleObjectProperty<>();
+ sourceChildren = FXCollections.observableArrayList(this::getExtractorCallback);
+ filteredChildren = new FilteredList<>(sourceChildren);
+ init();
+ }
public FilterableTreeItem(T value) {
super(value);
+ predicate = new SimpleObjectProperty<>();
+ sourceChildren = FXCollections.observableArrayList(this::getExtractorCallback);
+ filteredChildren = new FilteredList<>(sourceChildren);
+ init();
- sourceChildren = FXCollections.observableArrayList(item -> getExtractorCallback());
+ }
+
+ public FilterableTreeItem(T value, Node graphic) {
+ super(value, graphic);
+ sourceChildren = FXCollections.observableArrayList(this::getExtractorCallback);
filteredChildren = new FilteredList<>(sourceChildren);
+ predicate = new SimpleObjectProperty<>();
+ init();
+ }
+ private void init() {
filteredChildren.predicateProperty().bind(Bindings.createObjectBinding(this::buildFilterableListPredicate, predicate));
-
filteredChildren.addListener((ListChangeListener>) c -> {
while (c.next()) {
- Collection> removeFinal = new LinkedHashSet<>(c.getRemoved());
- c.getAddedSubList().forEach(removeFinal::remove);
- Collection> addFinal = new LinkedHashSet<>(c.getAddedSubList());
- c.getRemoved().forEach(addFinal::remove);
- getChildren().removeAll(removeFinal);
- getChildren().addAll(addFinal);
+ getChildren().removeAll(c.getRemoved());
+ getChildren().addAll(c.getAddedSubList());
}
});
}
/**
- * Override to add callbacks to the {@link #sourceChildren} collection.
- * See {@link FXCollections#observableArrayList(Callback)}
+ * Override to add callbacks to the {@link #sourceChildren} collection. See
+ * {@link FXCollections#observableArrayList(Callback)}
+ *
* @return callbacks that are passed to the observable source list
*/
- protected Observable[] getExtractorCallback() {
+ protected Observable[] getExtractorCallback(TreeItem item) {
return new Observable[]{};
}
diff --git a/src/main/java/drrename/ui/MainController.java b/src/main/java/drrename/ui/MainController.java
index cfaf7b34..c768de47 100644
--- a/src/main/java/drrename/ui/MainController.java
+++ b/src/main/java/drrename/ui/MainController.java
@@ -1,16 +1,16 @@
package drrename.ui;
-import drrename.FileTypeByMimeProvider;
import drrename.FileTypeProvider;
import drrename.RenamingStrategies;
-import drrename.strategy.RenamingStrategy;
import drrename.config.AppConfig;
import drrename.event.MainViewButtonCancelEvent;
import drrename.event.MainViewButtonGoEvent;
import drrename.filecreator.DummyFileCreatorController;
import drrename.kodi.KodiToolsController;
-import drrename.model.RenamingEntry;
+import drrename.mime.FileTypeByMimeProvider;
+import drrename.model.RenamingControl;
import drrename.service.EntriesService;
+import drrename.strategy.RenamingStrategy;
import drrename.ui.mainview.GoCancelButtonsComponentController;
import drrename.ui.mainview.ReplacementStringComponentController;
import drrename.ui.mainview.StartDirectoryComponentController;
@@ -207,12 +207,12 @@ public void initialize(URL url, ResourceBundle resourceBundle) {
if (config.isDebug())
applyRandomColors();
- entriesService.getEntriesFiltered().addListener((ListChangeListener) c -> {
+ entriesService.getEntriesFiltered().addListener((ListChangeListener) c -> {
while (c.next()) {
executor.execute(() -> {
- Collection removeFinal = new LinkedHashSet<>(c.getRemoved());
+ Collection removeFinal = new LinkedHashSet<>(c.getRemoved());
c.getAddedSubList().forEach(removeFinal::remove);
- Collection addFinal = new LinkedHashSet<>(c.getAddedSubList());
+ Collection addFinal = new LinkedHashSet<>(c.getAddedSubList());
c.getRemoved().forEach(addFinal::remove);
Platform.runLater(() -> {
removeFromContent(removeFinal);
@@ -386,32 +386,32 @@ public static String getRandomColorString() {
return String.format("#%06x", new Random().nextInt(256 * 256 * 256));
}
- private void addToContent(final Collection extends RenamingEntry> renamingBeans) {
+ private void addToContent(final Collection extends RenamingControl> renamingBeans) {
renamingBeans.forEach(this::addToContent);
}
- private void removeFromContent(final Collection extends RenamingEntry> renamingBeans) {
+ private void removeFromContent(final Collection extends RenamingControl> renamingBeans) {
if (leftContent.getItems().isEmpty() && rightContent.getItems().isEmpty()) {
return;
}
renamingBeans.forEach(this::removeFromContent);
}
- private void addToContent(final RenamingEntry renamingEntry) {
- leftContent.getItems().add(renamingEntry.getLeftControl());
- rightContent.getItems().add(renamingEntry.getRightControl());
+ private void addToContent(final RenamingControl renamingControl) {
+ leftContent.getItems().add(renamingControl.getLeftControl());
+ rightContent.getItems().add(renamingControl.getRightControl());
}
- private void removeFromContent(final RenamingEntry renamingEntry) {
+ private void removeFromContent(final RenamingControl renamingControl) {
if (leftContent.getItems().isEmpty() && rightContent.getItems().isEmpty()) {
return;
}
- if (!leftContent.getItems().remove(renamingEntry.getLeftControl())) {
- log.warn("Failed to remove {} from left content", renamingEntry.getLeftControl());
+ if (!leftContent.getItems().remove(renamingControl.getLeftControl())) {
+ log.warn("Failed to remove {} from left content", renamingControl.getLeftControl());
}
- if (!rightContent.getItems().remove(renamingEntry.getRightControl())) {
- log.warn("Failed to remove {} from right content", renamingEntry.getRightControl());
+ if (!rightContent.getItems().remove(renamingControl.getRightControl())) {
+ log.warn("Failed to remove {} from right content", renamingControl.getRightControl());
}
}
@@ -468,7 +468,7 @@ private void updateFileTypeInfo() {
startService(fileTypeService);
}
- private void initFileTypeService(Collection renamingEntries) {
+ private void initFileTypeService(Collection renamingEntries) {
fileTypeService.cancel();
fileTypeService.reset();
fileTypeService.setRenamingEntries(renamingEntries);
diff --git a/src/main/java/drrename/ui/PrimaryStageInitializer.java b/src/main/java/drrename/ui/PrimaryStageInitializer.java
index d7f477c7..0bffbdf5 100644
--- a/src/main/java/drrename/ui/PrimaryStageInitializer.java
+++ b/src/main/java/drrename/ui/PrimaryStageInitializer.java
@@ -1,14 +1,13 @@
package drrename.ui;
-import drrename.ui.config.UiConfig;
import drrename.event.StageReadyEvent;
+import drrename.ui.config.UiConfig;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.rgielen.fxweaver.core.FxWeaver;
-import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
diff --git a/src/main/java/drrename/ui/mainview/controller/FileListComponentController.java b/src/main/java/drrename/ui/mainview/controller/FileListComponentController.java
index 26678e1e..0b1350ba 100644
--- a/src/main/java/drrename/ui/mainview/controller/FileListComponentController.java
+++ b/src/main/java/drrename/ui/mainview/controller/FileListComponentController.java
@@ -6,8 +6,6 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.rgielen.fxweaver.core.FxmlView;
-import org.springframework.context.ApplicationEvent;
-import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import java.net.URL;
diff --git a/src/main/java/drrename/ui/service/FileTypeService.java b/src/main/java/drrename/ui/service/FileTypeService.java
index 8cc23c3c..40163cb5 100644
--- a/src/main/java/drrename/ui/service/FileTypeService.java
+++ b/src/main/java/drrename/ui/service/FileTypeService.java
@@ -3,7 +3,6 @@
import drrename.FileTypeProvider;
import javafx.concurrent.Task;
import lombok.RequiredArgsConstructor;
-import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
diff --git a/src/main/java/drrename/ui/service/FileTypeTask.java b/src/main/java/drrename/ui/service/FileTypeTask.java
index 4c7164e7..1807b84f 100644
--- a/src/main/java/drrename/ui/service/FileTypeTask.java
+++ b/src/main/java/drrename/ui/service/FileTypeTask.java
@@ -1,13 +1,11 @@
package drrename.ui.service;
import drrename.FileTypeProvider;
-import drrename.event.StartingFileTypeEvent;
-import drrename.model.RenamingEntry;
+import drrename.model.RenamingControl;
import javafx.application.Platform;
import javafx.concurrent.Task;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.ApplicationEventPublisher;
import java.util.List;
@@ -15,12 +13,12 @@
@RequiredArgsConstructor
public class FileTypeTask extends Task {
- private final List beans;
+ private final List beans;
private final FileTypeProvider fileTypeProvider;
- public static void setFileType(FileTypeProvider fileTypeProvider, RenamingEntry renamingEntry) {
- final String fileType = fileTypeProvider.getFileType(renamingEntry.getOldPath());
- Platform.runLater(() -> renamingEntry.setFileType(fileType));
+ public static void setFileType(FileTypeProvider fileTypeProvider, RenamingControl renamingControl) {
+ final String fileType = fileTypeProvider.getFileType(renamingControl.getOldPath());
+ Platform.runLater(() -> renamingControl.setFileType(fileType));
}
@Override
@@ -28,7 +26,7 @@ protected Void call() throws Exception {
if (beans == null) return null;
long cnt = 0;
- for (final RenamingEntry p : beans) {
+ for (final RenamingControl p : beans) {
if (Thread.currentThread().isInterrupted())
throw new InterruptedException("Cancelled");
setFileType(fileTypeProvider, p);
diff --git a/src/main/java/drrename/ui/service/FilesService.java b/src/main/java/drrename/ui/service/FilesService.java
index 41548563..969dd4a1 100644
--- a/src/main/java/drrename/ui/service/FilesService.java
+++ b/src/main/java/drrename/ui/service/FilesService.java
@@ -1,27 +1,27 @@
package drrename.ui.service;
+import drrename.model.RenamingControl;
+import javafx.concurrent.Service;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import drrename.model.RenamingEntry;
-import javafx.concurrent.Service;
-
public abstract class FilesService extends Service {
- private List renamingEntries;
+ private List renamingEntries;
public FilesService() {
this.renamingEntries = new ArrayList<>();
}
- public List getRenamingEntries() {
+ public List getRenamingEntries() {
return renamingEntries;
}
- public void setRenamingEntries(final Collection extends RenamingEntry> renamingEntries) {
+ public void setRenamingEntries(final Collection extends RenamingControl> renamingEntries) {
this.renamingEntries = new ArrayList<>(renamingEntries);
}
diff --git a/src/main/java/drrename/ui/service/ListDirectoryTask.java b/src/main/java/drrename/ui/service/ListDirectoryTask.java
index eee8a7d0..c3402bcb 100644
--- a/src/main/java/drrename/ui/service/ListDirectoryTask.java
+++ b/src/main/java/drrename/ui/service/ListDirectoryTask.java
@@ -1,7 +1,10 @@
package drrename.ui.service;
-import drrename.event.*;
-import drrename.model.RenamingEntry;
+import drrename.event.ListFilesFinishedEvent;
+import drrename.event.NewRenamingEntryEvent;
+import drrename.event.StartingListFilesEvent;
+import drrename.event.SynchronousUuidEvent;
+import drrename.model.RenamingControl;
import javafx.concurrent.Task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
@@ -10,10 +13,12 @@
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
@Slf4j
-public class ListDirectoryTask extends Task> {
+public class ListDirectoryTask extends Task> {
private final Path dir;
@@ -27,24 +32,24 @@ public ListDirectoryTask(final Path dir, ApplicationEventPublisher eventPublishe
}
@Override
- protected List call() throws IOException {
+ protected List call() throws IOException {
return getEntries(dir);
}
- List getEntries(final Path dir) throws IOException {
- List result = new ArrayList<>();
+ List getEntries(final Path dir) throws IOException {
+ List result = new ArrayList<>();
SynchronousUuidEvent event = new StartingListFilesEvent();
log.debug("Publishing event {}", event);
eventPublisher.publishEvent(event);
- List smallList = new ArrayList<>();
+ List smallList = new ArrayList<>();
try (DirectoryStream stream = Files.newDirectoryStream(dir)) {
for (Path path : stream) {
if (Thread.interrupted()) {
break;
}
- RenamingEntry newEntry = new RenamingEntry(path);
+ RenamingControl newEntry = new RenamingControl(path);
result.add(newEntry);
smallList.add(newEntry);
if(smallList.size() > 3) {
diff --git a/src/main/java/drrename/ui/service/ListFilesTask.java b/src/main/java/drrename/ui/service/ListFilesTask.java
index 4d4b228d..3dc53d5e 100644
--- a/src/main/java/drrename/ui/service/ListFilesTask.java
+++ b/src/main/java/drrename/ui/service/ListFilesTask.java
@@ -1,8 +1,8 @@
package drrename.ui.service;
-import drrename.event.StartingListFilesEvent;
-import drrename.model.RenamingEntry;
import drrename.event.NewRenamingEntryEvent;
+import drrename.event.StartingListFilesEvent;
+import drrename.model.RenamingControl;
import javafx.concurrent.Task;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -15,7 +15,7 @@
@RequiredArgsConstructor
@Slf4j
-public class ListFilesTask extends Task> {
+public class ListFilesTask extends Task> {
private final Collection files;
@@ -23,13 +23,13 @@ public class ListFilesTask extends Task> {
@Override
- protected List call() {
+ protected List call() {
return getEntries(files);
}
- List getEntries(final Collection files) {
- List result = new ArrayList<>();
+ List getEntries(final Collection files) {
+ List result = new ArrayList<>();
var event = new StartingListFilesEvent();
log.debug("Publishing event {}", event);
eventPublisher.publishEvent(event);
@@ -37,7 +37,7 @@ List getEntries(final Collection files) {
if (Thread.interrupted()) {
break;
}
- var newEntry = new RenamingEntry(f);
+ var newEntry = new RenamingControl(f);
result.add(newEntry);
eventPublisher.publishEvent(new NewRenamingEntryEvent(event.getUuid(), newEntry));
updateProgress(result.size(), files.size());
diff --git a/src/main/java/drrename/ui/service/LoadPathsService.java b/src/main/java/drrename/ui/service/LoadPathsService.java
index 10d78827..24f04d74 100644
--- a/src/main/java/drrename/ui/service/LoadPathsService.java
+++ b/src/main/java/drrename/ui/service/LoadPathsService.java
@@ -1,6 +1,6 @@
package drrename.ui.service;
-import drrename.model.RenamingEntry;
+import drrename.model.RenamingControl;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import lombok.RequiredArgsConstructor;
@@ -13,14 +13,14 @@
@RequiredArgsConstructor
@org.springframework.stereotype.Service
-public class LoadPathsService extends Service> {
+public class LoadPathsService extends Service> {
private Collection files;
private final ApplicationEventPublisher eventPublisher;
@Override
- protected Task> createTask(){
+ protected Task> createTask(){
// If 'files' is one entry only, and it's a directory, use ListDirectoryTask, otherwise use ListFilesTask.
if(files != null && files.size() == 1 && Files.isDirectory(files.iterator().next())){
return new ListDirectoryTask(files.iterator().next(), eventPublisher);
diff --git a/src/main/java/drrename/ui/service/PreviewService.java b/src/main/java/drrename/ui/service/PreviewService.java
index 315000e3..f515e08d 100644
--- a/src/main/java/drrename/ui/service/PreviewService.java
+++ b/src/main/java/drrename/ui/service/PreviewService.java
@@ -1,6 +1,6 @@
package drrename.ui.service;
-import drrename.model.RenamingEntry;
+import drrename.model.RenamingControl;
import javafx.concurrent.Task;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@@ -9,7 +9,7 @@
import java.util.concurrent.Executor;
@Service
-public class PreviewService extends StrategyService> {
+public class PreviewService extends StrategyService> {
private final ApplicationEventPublisher applicationEventPublisher;
@@ -19,7 +19,7 @@ public PreviewService(final Executor taskExecutor, ApplicationEventPublisher app
}
@Override
- protected Task> createTask() {
+ protected Task> createTask() {
return new PreviewTask(getRenamingEntries(), getRenamingStrategy(), applicationEventPublisher);
}
diff --git a/src/main/java/drrename/ui/service/PreviewTask.java b/src/main/java/drrename/ui/service/PreviewTask.java
index ddeb5503..c3fbabad 100644
--- a/src/main/java/drrename/ui/service/PreviewTask.java
+++ b/src/main/java/drrename/ui/service/PreviewTask.java
@@ -1,9 +1,9 @@
package drrename.ui.service;
-import drrename.strategy.RenamingStrategy;
import drrename.event.FilePreviewEvent;
import drrename.event.StartingPreviewEvent;
-import drrename.model.RenamingEntry;
+import drrename.model.RenamingControl;
+import drrename.strategy.RenamingStrategy;
import javafx.concurrent.Task;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -14,22 +14,22 @@
@Slf4j
@RequiredArgsConstructor
-public class PreviewTask extends Task> {
+public class PreviewTask extends Task> {
- private final List beans;
+ private final List beans;
private final RenamingStrategy renamingStrategy;
private final ApplicationEventPublisher applicationEventPublisher;
@Override
- protected List call() throws Exception {
+ protected List call() throws Exception {
- List