* allow drop of file names via verification files (e.g. sfv) in "New Names" list

* added before() and after() substring operations to ExpressionFormat.global.js
* refactoring
This commit is contained in:
Reinhard Pointner 2009-07-10 18:47:56 +00:00
parent 9c456b275a
commit b4578e9cdf
11 changed files with 143 additions and 65 deletions

View File

@ -60,11 +60,8 @@ public final class FileBotUtilities {
}
public static final ExtensionFileFilter TORRENT_FILES = MediaTypes.getDefault().filter("application/torrent");
public static final ExtensionFileFilter LIST_FILES = MediaTypes.getDefault().filter("application/list");
public static final ExtensionFileFilter VIDEO_FILES = MediaTypes.getDefault().filter("video");
public static final ExtensionFileFilter SUBTITLE_FILES = MediaTypes.getDefault().filter("subtitle");
public static final ExtensionFileFilter SFV_FILES = MediaTypes.getDefault().filter("verification/sfv");
public static final ExtensionFileFilter VIDEO_FILES = MediaTypes.getFilter("video");
public static final ExtensionFileFilter SUBTITLE_FILES = MediaTypes.getFilter("subtitle");
/**

View File

@ -34,34 +34,29 @@ public class MediaTypes {
}
private static MediaTypes instance;
private static final MediaTypes data = unmarshal();
public static synchronized MediaTypes getDefault() {
if (instance == null) {
try {
Unmarshaller unmarshaller = JAXBContext.newInstance(MediaTypes.class).createUnmarshaller();
// initialize singleton instance
instance = (MediaTypes) unmarshaller.unmarshal(MediaTypes.class.getResource("media.types"));
} catch (JAXBException e) {
throw new RuntimeException(e);
}
private static MediaTypes unmarshal() {
try {
Unmarshaller unmarshaller = JAXBContext.newInstance(MediaTypes.class).createUnmarshaller();
return (MediaTypes) unmarshaller.unmarshal(MediaTypes.class.getResource("media.types"));
} catch (JAXBException e) {
throw new RuntimeException(e);
}
return instance;
}
public ExtensionFileFilter filter(String name) {
return new ExtensionFileFilter(extensions(name));
public static ExtensionFileFilter getFilter(String name) {
return new ExtensionFileFilter(getExtensionList(name));
}
public List<String> extensions(String name) {
public static List<String> getExtensionList(String name) {
List<String> list = new ArrayList<String>();
for (Type type : types) {
for (Type type : data.types) {
if (type.name.startsWith(name)) {
addAll(list, type.extensions);
}

View File

@ -17,6 +17,7 @@ import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sourceforge.filebot.FileBotUtilities;
import net.sourceforge.filebot.MediaTypes;
import net.sourceforge.filebot.hash.SfvFormat;
import net.sourceforge.filebot.hash.VerificationFileScanner;
import net.sourceforge.filebot.mediainfo.MediaInfo;
@ -259,7 +260,7 @@ public class EpisodeFormatBindingBean {
private String getChecksumFromSfvFile(File file) throws IOException {
File folder = file.getParentFile();
for (File sfvFile : folder.listFiles(SFV_FILES)) {
for (File sfvFile : folder.listFiles(MediaTypes.getFilter("verification/sfv"))) {
VerificationFileScanner scanner = new VerificationFileScanner(sfvFile, new SfvFormat());
try {

View File

@ -34,6 +34,28 @@ String.prototype.space = function(replacement) {
}
/**
* Return substring before the given delimiter.
*/
String.prototype.before = function(delimiter) {
var endIndex = this.indexOf(delimiter);
// delimiter was found, return leading substring, else return original value
return endIndex >= 0 ? this.substring(0, endIndex) : this;
}
/**
* Return substring after the given delimiter.
*/
String.prototype.after = function(delimiter) {
var startIndex = this.indexOf(delimiter);
// delimiter was found, return trailing substring, else return original value
return startIndex >= 0 ? this.substring(startIndex + delimiter.length, this.length) : this;
}
/**
* Replace trailing parenthesis including any leading whitespace.
*

View File

@ -71,4 +71,16 @@ public enum HashType {
return name().toLowerCase();
}
public static HashType forName(String name) {
for (HashType value : HashType.values()) {
if (value.name().equalsIgnoreCase(name)) {
return value;
}
}
// value not found
return null;
}
}

View File

@ -45,8 +45,8 @@ public enum SubtitleFormat {
public abstract SubtitleReader newReader(Readable readable);
public ExtensionFileFilter filter() {
return MediaTypes.getDefault().filter("subtitle/" + this);
public ExtensionFileFilter getFilter() {
return MediaTypes.getFilter("subtitle/" + this);
}
}

View File

@ -202,7 +202,7 @@ public class EpisodeFormatDialog extends JDialog {
Settings.userRoot().put("dialog.sample.episode", episodeString);
firePreviewSampleChanged();
} catch (ParseException e) {
Logger.getLogger("ui").warning(String.format("Cannot parse %s", episodeString));
Logger.getLogger("ui").warning(String.format("Cannot parse '%s'", episodeString));
}
}
}
@ -319,7 +319,7 @@ public class EpisodeFormatDialog extends JDialog {
try {
return EpisodeFormat.getInstance().parseObject(sample);
} catch (Exception e) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage(), e);
Logger.getLogger(getClass().getName()).warning(e.getMessage());
}
}
@ -332,11 +332,7 @@ public class EpisodeFormatDialog extends JDialog {
String sample = Settings.userRoot().get("dialog.sample.file");
if (sample != null) {
try {
return new File(sample);
} catch (Exception e) {
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage(), e);
}
return new File(sample);
}
// default sample

View File

@ -2,7 +2,6 @@
package net.sourceforge.filebot.ui.panel.list;
import static net.sourceforge.filebot.FileBotUtilities.*;
import static net.sourceforge.tuned.FileUtilities.*;
import java.io.File;
@ -11,6 +10,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.sourceforge.filebot.MediaTypes;
import net.sourceforge.filebot.torrent.Torrent;
import net.sourceforge.filebot.ui.FileBotList;
import net.sourceforge.filebot.ui.transfer.FileTransferablePolicy;
@ -21,7 +21,7 @@ class FileListTransferablePolicy extends FileTransferablePolicy {
private FileBotList<? super String> list;
public FileListTransferablePolicy(FileBotList<? super String> list) {
this.list = list;
}
@ -46,7 +46,7 @@ class FileListTransferablePolicy extends FileTransferablePolicy {
if (containsOnly(files, FOLDERS)) {
loadFolders(files);
} else if (containsOnly(files, TORRENT_FILES)) {
} else if (containsOnly(files, MediaTypes.getFilter("application/torrent"))) {
loadTorrents(files);
} else {
loadFiles(files);

View File

@ -3,7 +3,6 @@ package net.sourceforge.filebot.ui.panel.rename;
import static java.awt.datatransfer.DataFlavor.*;
import static net.sourceforge.filebot.FileBotUtilities.*;
import static net.sourceforge.filebot.ui.transfer.FileTransferable.*;
import static net.sourceforge.tuned.FileUtilities.*;
@ -17,9 +16,10 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.filebot.MediaTypes;
import net.sourceforge.filebot.hash.HashType;
import net.sourceforge.filebot.hash.VerificationFileScanner;
import net.sourceforge.filebot.torrent.Torrent;
import net.sourceforge.filebot.ui.transfer.ArrayTransferable;
import net.sourceforge.filebot.ui.transfer.FileTransferablePolicy;
@ -94,12 +94,17 @@ class NamesListTransferablePolicy extends FileTransferablePolicy {
@Override
protected void load(List<File> files) throws FileNotFoundException {
protected void load(List<File> files) throws IOException {
List<Object> values = new ArrayList<Object>();
if (containsOnly(files, LIST_FILES)) {
if (containsOnly(files, MediaTypes.getFilter("application/list"))) {
// list files
loadListFiles(files, values);
} else if (containsOnly(files, TORRENT_FILES)) {
} else if (containsOnly(files, MediaTypes.getFilter("verification"))) {
// verification files
loadVerificationFiles(files, values);
} else if (containsOnly(files, MediaTypes.getFilter("application/torrent"))) {
// torrent files
loadTorrentFiles(files, values);
} else if (containsOnly(files, FOLDERS)) {
// load files from each folder
@ -107,6 +112,7 @@ class NamesListTransferablePolicy extends FileTransferablePolicy {
values.addAll(FastFile.foreach(folder.listFiles()));
}
} else {
// just add all given files
values.addAll(FastFile.foreach(files));
}
@ -132,24 +138,42 @@ class NamesListTransferablePolicy extends FileTransferablePolicy {
}
protected void loadTorrentFiles(List<File> files, List<Object> values) {
try {
for (File file : files) {
Torrent torrent = new Torrent(file);
for (Torrent.Entry entry : torrent.getFiles()) {
values.add(new AbstractFile(entry.getName(), entry.getLength()));
protected void loadVerificationFiles(List<File> files, List<Object> values) throws IOException {
for (File file : files) {
HashType format = HashType.forName(getExtension(file));
// check if format is valid
if (format == null)
continue;
// add all file names from verification file
VerificationFileScanner scanner = new VerificationFileScanner(file, format.getFormat());
try {
while (scanner.hasNext()) {
values.add(scanner.next().getKey().getName());
}
} finally {
scanner.close();
}
}
}
protected void loadTorrentFiles(List<File> files, List<Object> values) throws IOException {
for (File file : files) {
Torrent torrent = new Torrent(file);
for (Torrent.Entry entry : torrent.getFiles()) {
values.add(new AbstractFile(entry.getName(), entry.getLength()));
}
} catch (IOException e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, e.toString(), e);
}
}
@Override
public String getFileFilterDescription() {
return "text files and torrent files";
return "text files, verification files, torrent files";
}
}

View File

@ -8,8 +8,11 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
@ -28,7 +31,7 @@ final class SubtitleUtilities {
// gather all formats, put likely formats first
for (SubtitleFormat format : SubtitleFormat.values()) {
if (format.filter().accept(file.getName())) {
if (format.getFilter().accept(file.getName())) {
priorityList.addFirst(format);
} else {
priorityList.addLast(format);
@ -62,6 +65,20 @@ final class SubtitleUtilities {
}
public static String md5(ByteBuffer data) {
try {
MessageDigest hash = MessageDigest.getInstance("md-5");
hash.update(data);
// return hex string
return String.format("%032x", new BigInteger(1, hash.digest()));
} catch (NoSuchAlgorithmException e) {
// will not happen
throw new UnsupportedOperationException(e);
}
}
public static byte[] read(File source) throws IOException {
InputStream in = new FileInputStream(source);

View File

@ -6,8 +6,6 @@ import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class EpisodeFormat extends Format {
@ -48,23 +46,39 @@ public class EpisodeFormat extends Format {
@Override
public Episode parseObject(String source, ParsePosition pos) {
Pattern pattern = Pattern.compile("(.*) - (?:(\\w+?)x)?(\\w+)? - (.*)");
String[] section = source.substring(pos.getIndex()).split(" - ", 3);
Matcher matcher = pattern.matcher(source).region(pos.getIndex(), source.length());
if (!matcher.matches()) {
pos.setErrorIndex(matcher.regionStart());
// series name and episode identifier are required
if (section.length < 2) {
pos.setErrorIndex(0);
return null;
}
// episode number must not be null
if (matcher.group(3) == null) {
pos.setErrorIndex(matcher.start(3));
return null;
// normalize and check
for (int i = 0; i < section.length; i++) {
section[i] = section[i].trim();
if (section[i].isEmpty()) {
pos.setErrorIndex(0);
return null;
}
}
pos.setIndex(matcher.end());
return new Episode(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4));
String[] sxe = section[1].split("x", 2);
// series name
String name = section[0];
// season number and episode number
String season = (sxe.length == 2) ? sxe[0] : null;
String episode = (sxe.length == 2) ? sxe[1] : section[1];
// episode title
String title = (section.length == 3) ? section[2] : null;
// did parse input
pos.setIndex(source.length());
return new Episode(name, season, episode, title);
}