diff --git a/src/main/java/uk/yermak/audiobookconverter/book/Chapter.java b/src/main/java/uk/yermak/audiobookconverter/book/Chapter.java index c5684081..00427862 100644 --- a/src/main/java/uk/yermak/audiobookconverter/book/Chapter.java +++ b/src/main/java/uk/yermak/audiobookconverter/book/Chapter.java @@ -4,6 +4,7 @@ import javafx.collections.ObservableList; import org.apache.commons.io.FilenameUtils; import uk.yermak.audiobookconverter.*; +import uk.yermak.audiobookconverter.fx.StringToContext; import java.time.Duration; import java.util.*; @@ -71,7 +72,7 @@ private void initRenderMap() { } if (context.contains("CUSTOM_TITLE")) { this.setCustomTitle(AppSetting.getProperty(AppSetting.CHAPTER_CUSTOM_TITLE, "")); - renderMap.put("CUSTOM_TITLE", chapter -> customTitle); + renderMap.put("CUSTOM_TITLE", StringToContext.getFunction(this.getCustomTitle())); } } diff --git a/src/main/java/uk/yermak/audiobookconverter/fx/ChapterEditor.java b/src/main/java/uk/yermak/audiobookconverter/fx/ChapterEditor.java index 82eb6b3a..10e4a21c 100644 --- a/src/main/java/uk/yermak/audiobookconverter/fx/ChapterEditor.java +++ b/src/main/java/uk/yermak/audiobookconverter/fx/ChapterEditor.java @@ -9,8 +9,8 @@ import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import uk.yermak.audiobookconverter.AppSetting; -import uk.yermak.audiobookconverter.book.Chapter; import uk.yermak.audiobookconverter.Utils; +import uk.yermak.audiobookconverter.book.Chapter; import java.util.HashMap; import java.util.List; @@ -158,10 +158,27 @@ void editChapter() { // } else if (context.containsKey("CUSTOM_TITLE")) { // customTitle.setText(AppSetting.getProperty(AppSetting.CHAPTER_CUSTOM_TITLE, "")); // } +// StringToContext stringToContext = new StringToContext(); + String formattingStringExplanation = "Special tokens\n" + + "%BOOK_NUMBER%\n" + + "%comment-0%\n" + + "%year%\n" + + "%genre%\n" + + "%album%\n" + + "%album_artist%\n" + + "%title%\n" + + "%BOOK_TITLE%\n" + + "%DURATION%\n" + + "%file_name%\n" + + "%CHAPTER_TEXT%\n" + + "%CHAPTER_NUMBER%\n"; + customTitle.setTooltip(new Tooltip(formattingStringExplanation)); + customTitle.textProperty().addListener((observable, oldValue, newValue) -> { // chapter.setCustomTitle(newValue); if (StringUtils.trimToNull(newValue) != null) { - context.put("CUSTOM_TITLE", c -> newValue); + StringToContext.updateContextUsingPrintf(context,newValue); +// context.put("CUSTOM_TITLE", c -> newValue); } else{ context.remove("CUSTOM_TITLE"); } @@ -194,13 +211,14 @@ void editChapter() { Optional result = dialog.showAndWait(); + if (result.isPresent() && result.get() == ButtonType.OK) { chapter.getRenderMap().clear(); chapter.getRenderMap().putAll(context); - chapter.setCustomTitle(StringUtils.trimToEmpty(customTitle.getText())); - if (StringUtils.isNotEmpty(customTitle.getText())) { - chapter.getRenderMap().put("CUSTOM_TITLE", Chapter::getCustomTitle); - } +// chapter.setCustomTitle(StringUtils.trimToEmpty(customTitle.getText())); +// if (StringUtils.isNotEmpty(customTitle.getText())) { +// chapter.getRenderMap().put("CUSTOM_TITLE", Chapter::getCustomTitle); +// } if (applyForAllChapters.isSelected() || saveAsDefault.isSelected()) { applyForAllChapters(context, customTitle); } @@ -209,7 +227,13 @@ void editChapter() { AppSetting.setProperty(AppSetting.CHAPTER_CONTEXT, defaultChapterContext); AppSetting.setProperty(AppSetting.CHAPTER_CUSTOM_TITLE, StringUtils.trimToNull(customTitle.getText())); } + + String t = AppSetting.getProperty(AppSetting.CHAPTER_CUSTOM_TITLE,"default"); + if(t.length()>1) + StringToContext.updateContextUsingPrintf(context, t); } + + } private void applyForAllChapters(Map> context, TextField customTitle) { @@ -217,10 +241,10 @@ private void applyForAllChapters(Map> context, for (Chapter c : chapters) { c.getRenderMap().clear(); c.getRenderMap().putAll(context); - if (StringUtils.isNotEmpty(customTitle.getText())) { - c.getRenderMap().put("CUSTOM_TITLE", Chapter::getCustomTitle); - } - c.setCustomTitle(customTitle.getText()); +// if (StringUtils.isNotEmpty(customTitle.getText())) { +// c.getRenderMap().put("CUSTOM_TITLE", Chapter::getCustomTitle); +// } +// c.setCustomTitle(customTitle.getText()); } } } diff --git a/src/main/java/uk/yermak/audiobookconverter/fx/StringToContext.java b/src/main/java/uk/yermak/audiobookconverter/fx/StringToContext.java new file mode 100644 index 00000000..365fb5e0 --- /dev/null +++ b/src/main/java/uk/yermak/audiobookconverter/fx/StringToContext.java @@ -0,0 +1,121 @@ +package uk.yermak.audiobookconverter.fx; + +import org.apache.commons.io.FilenameUtils; +import uk.yermak.audiobookconverter.book.Chapter; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + + +/** + * Util class which function is updating context in {@link ChapterEditor#editChapter()} method, + * so we can use printf like syntax for template naming chapter names. + * + * @author patsh + */ +public class StringToContext { + + /** + * Special tokens used in creating chapter naming template. + */ + public final static Set SPECIAL_TOKENS; + + /** + * Mapping between specials tokens at functions that map chapter object to some string. + */ + public final static Map> SPECIAL_TOKEN_TO_FUNCTION; + + static { + SPECIAL_TOKEN_TO_FUNCTION = new HashMap<>(); + SPECIAL_TOKEN_TO_FUNCTION.put("%BOOK_NUMBER%", + c -> String.valueOf(c.getPart().getBook().getBookInfo().bookNumber())); + SPECIAL_TOKEN_TO_FUNCTION.put("%comment-0%", + chapter -> chapter.getMedia().get(0).getBookInfo().comment()); + SPECIAL_TOKEN_TO_FUNCTION.put("%year%", + chapter -> chapter.getMedia().get(0).getBookInfo().year()); + SPECIAL_TOKEN_TO_FUNCTION.put("%genre%", + chapter -> chapter.getMedia().get(0).getBookInfo().genre()); + SPECIAL_TOKEN_TO_FUNCTION.put("%album%", + chapter -> chapter.getMedia().get(0).getBookInfo().series()); + SPECIAL_TOKEN_TO_FUNCTION.put("%album_artist%", + chapter -> chapter.getMedia().get(0).getBookInfo().narrator()); + SPECIAL_TOKEN_TO_FUNCTION.put("%artist%", + chapter -> chapter.getMedia().get(0).getBookInfo().writer()); + SPECIAL_TOKEN_TO_FUNCTION.put("%title%", + chapter -> chapter.getMedia().get(0).getBookInfo().title()); + SPECIAL_TOKEN_TO_FUNCTION.put("%BOOK_TITLE%", + c -> c.getPart().getBook().getBookInfo().title()); + SPECIAL_TOKEN_TO_FUNCTION.put("%DURATION%", + c -> Duration.ofMillis(c.getDuration())); + SPECIAL_TOKEN_TO_FUNCTION.put("%file_name%", + c -> FilenameUtils.getBaseName(c.getMedia().get(0).getFileName())); + SPECIAL_TOKEN_TO_FUNCTION.put("%CHAPTER_TEXT%", + c -> "Chapter"); + SPECIAL_TOKEN_TO_FUNCTION.put("%CHAPTER_NUMBER%", + c -> c.getNumber()); + + SPECIAL_TOKENS = SPECIAL_TOKEN_TO_FUNCTION.keySet(); + } + + + + public static Map> updateContextUsingPrintf(Map> context, String printf) { + Function exp = getFunction(printf); + + context.put("CUSTOM_TITLE", exp); + return context; + } + + /** + * Main method for generating function from string with special tokens. + *

+ * For example string - "%title% - chapter" will + * construct function that combines function mapped in {@link #SPECIAL_TOKEN_TO_FUNCTION} with string "- chapter". + * And put it in "CUSTOM_TITLE" value in context object. + * + * @param printf String for formatting chapter title. For example - "%title% - chapter" + * @return Function combining functions and strings + */ + + public static Function getFunction(String printf){ + String[] tokens = printf.split(" "); + ArrayList> functions = new ArrayList<>(); + ArrayList values = new ArrayList<>(); + values.add(""); + for (String token : tokens) { + if (SPECIAL_TOKENS.contains(token)) { + functions.add(SPECIAL_TOKEN_TO_FUNCTION.get(token)); + } else { + values.add(token); + } + } + + Function exp = chapter -> { + int n = Math.min(functions.size(), values.size()); + int i = 0; + StringBuilder sb = new StringBuilder(); + while (i < n) { + sb.append(values.get(i)); + sb.append(" "); + sb.append(functions.get(i).apply(chapter)); + sb.append(" "); + i++; + } + + while (i < functions.size()) { + sb.append(functions.get(i).apply(chapter)); + i++; + } + while (i < values.size()) { + sb.append(values.get(i)); + i++; + } + return sb.toString(); + }; + return exp; + } +}