Refactor CmdlineOperations

This commit is contained in:
Reinhard Pointner 2017-03-23 16:53:20 +08:00
parent 2f7ee58707
commit ec44c7c38d
2 changed files with 43 additions and 77 deletions

View File

@ -69,10 +69,8 @@ import net.filebot.vfs.SimpleFileInfo;
import net.filebot.web.AudioTrack; import net.filebot.web.AudioTrack;
import net.filebot.web.Datasource; import net.filebot.web.Datasource;
import net.filebot.web.Episode; import net.filebot.web.Episode;
import net.filebot.web.EpisodeFormat;
import net.filebot.web.EpisodeListProvider; import net.filebot.web.EpisodeListProvider;
import net.filebot.web.Movie; import net.filebot.web.Movie;
import net.filebot.web.MovieFormat;
import net.filebot.web.MovieIdentificationService; import net.filebot.web.MovieIdentificationService;
import net.filebot.web.MoviePart; import net.filebot.web.MoviePart;
import net.filebot.web.MusicIdentificationService; import net.filebot.web.MusicIdentificationService;
@ -142,7 +140,7 @@ public class CmdlineOperations implements CmdlineInterface {
} }
@Override @Override
public List<File> rename(EpisodeListProvider db, String query, ExpressionFileFormat format, ExpressionFilter filter, SortOrder order, Locale locale, boolean strict, List<File> files, RenameAction action, ConflictAction conflict, File output) throws Exception { public List<File> rename(EpisodeListProvider db, String query, ExpressionFileFormat format, ExpressionFilter filter, SortOrder order, Locale locale, boolean strict, List<File> files, RenameAction action, ConflictAction conflict, File outputDir) throws Exception {
// match files and episodes in linear order // match files and episodes in linear order
List<Episode> episodes = fetchEpisodeList(db, query, filter, order, locale, strict); List<Episode> episodes = fetchEpisodeList(db, query, filter, order, locale, strict);
@ -151,19 +149,8 @@ public class CmdlineOperations implements CmdlineInterface {
matches.add(new Match<File, Episode>(files.get(i), episodes.get(i))); matches.add(new Match<File, Episode>(files.get(i), episodes.get(i)));
} }
// map old files to new paths by applying formatting and validating filenames
Map<File, File> renameMap = new LinkedHashMap<File, File>();
for (Match<File, ?> match : matches) {
File file = match.getValue();
Object episode = match.getCandidate();
String newName = format != null ? format.format(new MediaBindingBean(episode, file, getContext(matches))) : validateFileName(EpisodeFormat.SeasonEpisode.format(episode));
renameMap.put(file, getDestinationFile(file, newName, output));
}
// rename episodes // rename episodes
return renameAll(renameMap, action, conflict, matches); return renameAll(formatMatches(matches, format, outputDir), action, conflict, matches);
} }
@Override @Override
@ -254,19 +241,8 @@ public class CmdlineOperations implements CmdlineInterface {
// add matches from other files that are linked via filenames // add matches from other files that are linked via filenames
matches.addAll(derivateMatches); matches.addAll(derivateMatches);
// map old files to new paths by applying formatting and validating filenames
Map<File, File> renameMap = new LinkedHashMap<File, File>();
for (Match<File, ?> match : matches) {
File file = match.getValue();
Object episode = match.getCandidate();
String newName = (format != null) ? format.format(new MediaBindingBean(episode, file, getContext(matches))) : validateFileName(EpisodeFormat.SeasonEpisode.format(episode));
renameMap.put(file, getDestinationFile(file, newName, outputDir));
}
// rename episodes // rename episodes
return renameAll(renameMap, renameAction, conflictAction, matches); return renameAll(formatMatches(matches, format, outputDir), renameAction, conflictAction, matches);
} }
private List<Match<File, Object>> matchEpisodes(Collection<File> files, Collection<Episode> episodes, boolean strict) throws Exception { private List<Match<File, Object>> matchEpisodes(Collection<File> files, Collection<Episode> episodes, boolean strict) throws Exception {
@ -503,19 +479,8 @@ public class CmdlineOperations implements CmdlineInterface {
}); });
}); });
// map old files to new paths by applying formatting and validating filenames
Map<File, File> renameMap = new LinkedHashMap<File, File>();
for (Match<File, ?> match : matches) {
File file = match.getValue();
Object movie = match.getCandidate();
String newName = (format != null) ? format.format(new MediaBindingBean(movie, file, getContext(matches))) : validateFileName(MovieFormat.NameYear.format(movie));
renameMap.put(file, getDestinationFile(file, newName, outputDir));
}
// rename movies // rename movies
return renameAll(renameMap, renameAction, conflictAction, matches); return renameAll(formatMatches(matches, format, outputDir), renameAction, conflictAction, matches);
} }
public List<File> renameMusic(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFileFormat format, MusicIdentificationService... services) throws Exception { public List<File> renameMusic(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFileFormat format, MusicIdentificationService... services) throws Exception {
@ -536,40 +501,29 @@ public class CmdlineOperations implements CmdlineInterface {
}); });
} }
// map old files to new paths by applying formatting and validating filenames
Map<File, File> renameMap = new LinkedHashMap<File, File>();
for (Match<File, ?> it : matches) {
File file = it.getValue();
Object music = it.getCandidate();
String path = format != null ? format.format(new MediaBindingBean(music, file, getContext(matches))) : validateFileName(music.toString());
renameMap.put(file, getDestinationFile(file, path, outputDir));
}
// error logging // error logging
remaining.forEach(f -> log.warning(format("Failed to process music file: %s", f))); remaining.forEach(f -> log.warning(format("Failed to process music file: %s", f)));
// rename movies // rename movies
return renameAll(renameMap, renameAction, conflictAction, null); return renameAll(formatMatches(matches, format, outputDir), renameAction, conflictAction, null);
} }
public List<File> renameFiles(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFileFormat format, XattrMetaInfoProvider service, ExpressionFilter filter, boolean strict) throws Exception { public List<File> renameFiles(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFileFormat format, XattrMetaInfoProvider service, ExpressionFilter filter, boolean strict) throws Exception {
log.config(format("Rename files using [%s]", service.getName())); log.config(format("Rename files using [%s]", service.getName()));
Map<File, File> renameMap = new LinkedHashMap<File, File>();
// match to xattr metadata object or the file itself // match to xattr metadata object or the file itself
Map<File, Object> matches = service.match(files, strict); Map<File, Object> matches = service.match(files, strict);
Map<File, File> renameMap = new LinkedHashMap<File, File>(); service.match(files, strict).forEach((k, v) -> {
MediaBindingBean bindingBean = new MediaBindingBean(v, k, matches);
for (Entry<File, Object> it : matches.entrySet()) {
MediaBindingBean bindingBean = new MediaBindingBean(it.getValue(), it.getKey(), matches);
if (filter == null || filter.matches(bindingBean)) { if (filter == null || filter.matches(bindingBean)) {
String newName = format != null ? format.format(bindingBean) : bindingBean.getInfoObject() instanceof File ? bindingBean.getInfoObject().toString() : validateFileName(bindingBean.getInfoObject().toString()); String destinationPath = format != null ? format.format(bindingBean) : v instanceof File ? v.toString() : validateFileName(v.toString());
renameMap.put(it.getKey(), getDestinationFile(it.getKey(), newName, outputDir)); renameMap.put(k, getDestinationFile(k, destinationPath, outputDir));
} }
} });
return renameAll(renameMap, renameAction, conflictAction, null); return renameAll(renameMap, renameAction, conflictAction, null);
} }
@ -601,7 +555,22 @@ public class CmdlineOperations implements CmdlineInterface {
return newFile; return newFile;
} }
public List<File> renameAll(Map<File, File> renameMap, RenameAction renameAction, ConflictAction conflictAction, List<Match<File, ?>> matches) throws Exception { private Map<File, File> formatMatches(List<Match<File, ?>> matches, ExpressionFormat format, File outputDir) throws Exception {
// map old files to new paths by applying formatting and validating filenames
Map<File, File> renameMap = new LinkedHashMap<File, File>();
for (Match<File, ?> match : matches) {
File file = match.getValue();
Object object = match.getCandidate();
String destinationPath = format != null ? format.format(new MediaBindingBean(object, file, getContext(matches))) : validateFileName(object.toString());
renameMap.put(file, getDestinationFile(file, destinationPath, outputDir));
}
return renameMap;
}
protected List<File> renameAll(Map<File, File> renameMap, RenameAction renameAction, ConflictAction conflictAction, List<Match<File, ?>> matches) throws Exception {
if (renameMap.isEmpty()) { if (renameMap.isEmpty()) {
throw new CmdlineException("Failed to identify or process any files"); throw new CmdlineException("Failed to identify or process any files");
} }
@ -854,21 +823,20 @@ public class CmdlineOperations implements CmdlineInterface {
return destination; return destination;
} }
private <T> List<T> applyExpressionFilter(List<T> input, ExpressionFilter filter) throws Exception { protected <T> List<T> applyExpressionFilter(List<T> input, ExpressionFilter filter) {
if (filter == null) { if (filter == null) {
return input; return input;
} }
log.fine(format("Apply filter [%s] on [%d] items", filter.getExpression(), input.size())); log.fine(format("Apply filter [%s] on [%d] items", filter.getExpression(), input.size()));
Map<File, T> context = new EntryList<File, T>(null, input);
List<T> output = new ArrayList<T>(input.size()); return input.stream().filter(it -> {
for (T it : input) { if (filter.matches(new MediaBindingBean(it, null, new EntryList<File, T>(null, input)))) {
if (filter.matches(new MediaBindingBean(it, null, context))) {
log.finest(format("Include [%s]", it)); log.finest(format("Include [%s]", it));
output.add(it); return true;
} }
} return false;
return output; }).collect(toList());
} }
protected <T extends SearchResult> T selectSearchResult(String query, Collection<T> options) throws Exception { protected <T extends SearchResult> T selectSearchResult(String query, Collection<T> options) throws Exception {
@ -1043,20 +1011,18 @@ public class CmdlineOperations implements CmdlineInterface {
@Override @Override
public Stream<String> fetchEpisodeList(EpisodeListProvider db, String query, ExpressionFormat format, ExpressionFilter filter, SortOrder order, Locale locale, boolean strict) throws Exception { public Stream<String> fetchEpisodeList(EpisodeListProvider db, String query, ExpressionFormat format, ExpressionFilter filter, SortOrder order, Locale locale, boolean strict) throws Exception {
// default episode format
if (format == null) {
return fetchEpisodeList(db, query, new ExpressionFormat("{episode}"), filter, order, locale, strict);
}
// collect all episode objects first // collect all episode objects first
List<Episode> episodes = fetchEpisodeList(db, query, filter, order, locale, strict); List<Episode> episodes = fetchEpisodeList(db, query, filter, order, locale, strict);
// lazy format // instant format
Map<File, Episode> context = new EntryList<File, Episode>(null, episodes); if (format == null) {
return episodes.stream().map(Episode::toString);
}
// lazy format
return episodes.stream().map(episode -> { return episodes.stream().map(episode -> {
try { try {
return format.format(new MediaBindingBean(episode, null, context)); return format.format(new MediaBindingBean(episode, null, new EntryList<File, Episode>(null, episodes)));
} catch (Exception e) { } catch (Exception e) {
debug.warning(e::getMessage); debug.warning(e::getMessage);
} }

View File

@ -32,11 +32,11 @@ public class ExpressionFilter {
return lastException; return lastException;
} }
public boolean matches(Object value) throws ScriptException { public boolean matches(Object value) {
return matches(new ExpressionBindings(value)); return matches(new ExpressionBindings(value));
} }
public boolean matches(Bindings bindings) throws ScriptException { public boolean matches(Bindings bindings) {
this.lastException = null; this.lastException = null;
// use privileged bindings so we are not restricted by the script sandbox // use privileged bindings so we are not restricted by the script sandbox