1
0
mirror of https://github.com/mitb-archive/filebot synced 2024-12-22 15:58:52 -05:00

* intuitive access for all map bindings in episode expression format (e.g. video.width or video['width'])

* added AssociativeScriptObject
* enable table sorting in MediaInfoComponent
This commit is contained in:
Reinhard Pointner 2009-04-06 20:34:33 +00:00
parent 912bf0464f
commit e6b785df63
6 changed files with 220 additions and 41 deletions

View File

@ -0,0 +1,169 @@
package net.sourceforge.filebot.format;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
import sun.org.mozilla.javascript.internal.Scriptable;
class AssociativeScriptObject implements Scriptable {
/**
* Map allowing look-up of values by a fault-tolerant key as specified by the defining key.
*
* @see {@link #definingKey(String)}
*/
protected final TreeMap<String, Object> properties = new TreeMap<String, Object>(new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return definingKey(s1).compareTo(definingKey(s2));
}
});
/**
* The Java constructor
*/
public AssociativeScriptObject(Map<String, ?> properties) {
this.properties.putAll(properties);
}
protected String definingKey(String s) {
// letters and digits are defining, everything else will be ignored
return s.replaceAll("[^\\p{Alnum}]", "").toLowerCase();
}
/**
* Defines properties available by name.
*
* @param name the name of the property
* @param start the object where lookup began
*/
public boolean has(String name, Scriptable start) {
return properties.containsKey(name);
}
/**
* Get the property with the given name.
*
* @param name the property name
* @param start the object where the lookup began
*/
public Object get(String name, Scriptable start) {
Object value = properties.get(name);
if (value == null)
throw new BindingException(name, "undefined");
return value;
}
/**
* Defines properties available by index.
*
* @param index the index of the property
* @param start the object where lookup began
*/
public boolean has(int index, Scriptable start) {
// get property by index not supported
return false;
}
/**
* Get property by index.
*
* @param index the index of the property
* @param start the object where the lookup began
*/
public Object get(int index, Scriptable start) {
// get property by index not supported
throw new BindingException(String.valueOf(index), "undefined");
}
/**
* Get property names.
*/
public Object[] getIds() {
return properties.keySet().toArray();
}
/**
* Returns the name of this JavaScript class.
*/
public String getClassName() {
return getClass().getSimpleName();
}
/**
* Returns the string value of this object.
*/
@SuppressWarnings("unchecked")
@Override
public Object getDefaultValue(Class typeHint) {
return this.toString();
}
@Override
public String toString() {
return getClassName() + properties.entrySet().toString();
}
public void put(String name, Scriptable start, Object value) {
// ignore, object is immutable
}
public void put(int index, Scriptable start, Object value) {
// ignore, object is immutable
}
public void delete(String id) {
// ignore, object is immutable
}
public void delete(int index) {
// ignore, object is immutable
}
public Scriptable getPrototype() {
return null;
}
public void setPrototype(Scriptable prototype) {
// ignore, don't care about prototype
}
public Scriptable getParentScope() {
return null;
}
public void setParentScope(Scriptable parent) {
// ignore, don't care about scope
}
public boolean hasInstance(Scriptable value) {
return false;
}
}

View File

@ -9,6 +9,11 @@ public class BindingException extends RuntimeException {
} }
public BindingException(String binding, String innerMessage) {
this(binding, innerMessage, null);
}
public BindingException(String binding, String innerMessage, Throwable cause) { public BindingException(String binding, String innerMessage, Throwable cause) {
this(String.format("BindingError: \"%s\": %s", binding, innerMessage), cause); this(String.format("BindingError: \"%s\": %s", binding, innerMessage), cause);
} }

View File

@ -8,7 +8,6 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.SortedMap;
import java.util.zip.CRC32; import java.util.zip.CRC32;
import net.sf.ehcache.Cache; import net.sf.ehcache.Cache;
@ -81,7 +80,7 @@ public class EpisodeFormatBindingBean {
@Define("hi") @Define("hi")
public String getHeightAndInterlacement() { public String getHeightAndInterlacement() {
String height = getMediaInfo(StreamKind.Video, 0, "Height"); String height = getMediaInfo(StreamKind.Video, 0, "Height");
String interlacement = getMediaInfo(StreamKind.Video, 0, "Interlacement/String"); String interlacement = getMediaInfo(StreamKind.Video, 0, "Interlacement");
if (height == null || interlacement == null) if (height == null || interlacement == null)
return null; return null;
@ -123,32 +122,32 @@ public class EpisodeFormatBindingBean {
@Define("general") @Define("general")
public SortedMap<String, String> getGeneralMediaInfo() { public Object getGeneralMediaInfo() {
return getMediaInfo().snapshot(StreamKind.General, 0); return new AssociativeScriptObject(getMediaInfo().snapshot(StreamKind.General, 0));
} }
@Define("video") @Define("video")
public SortedMap<String, String> getVideoInfo() { public Object getVideoInfo() {
return getMediaInfo().snapshot(StreamKind.Video, 0); return new AssociativeScriptObject(getMediaInfo().snapshot(StreamKind.Video, 0));
} }
@Define("audio") @Define("audio")
public SortedMap<String, String> getAudioInfo() { public Object getAudioInfo() {
return getMediaInfo().snapshot(StreamKind.Audio, 0); return new AssociativeScriptObject(getMediaInfo().snapshot(StreamKind.Audio, 0));
} }
@Define("text") @Define("text")
public SortedMap<String, String> getTextInfo() { public Object getTextInfo() {
return getMediaInfo().snapshot(StreamKind.Text, 0); return new AssociativeScriptObject(getMediaInfo().snapshot(StreamKind.Text, 0));
} }
@Define("image") @Define("image")
public SortedMap<String, String> getImageInfo() { public Object getImageInfo() {
return getMediaInfo().snapshot(StreamKind.Image, 0); return new AssociativeScriptObject(getMediaInfo().snapshot(StreamKind.Image, 0));
} }

View File

@ -6,10 +6,9 @@ import java.io.Closeable;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import com.sun.jna.Pointer; import com.sun.jna.Pointer;
import com.sun.jna.WString; import com.sun.jna.WString;
@ -80,14 +79,14 @@ public class MediaInfo implements Closeable {
} }
public Map<StreamKind, List<SortedMap<String, String>>> snapshot() { public Map<StreamKind, List<Map<String, String>>> snapshot() {
Map<StreamKind, List<SortedMap<String, String>>> mediaInfo = new EnumMap<StreamKind, List<SortedMap<String, String>>>(StreamKind.class); Map<StreamKind, List<Map<String, String>>> mediaInfo = new EnumMap<StreamKind, List<Map<String, String>>>(StreamKind.class);
for (StreamKind streamKind : StreamKind.values()) { for (StreamKind streamKind : StreamKind.values()) {
int streamCount = streamCount(streamKind); int streamCount = streamCount(streamKind);
if (streamCount > 0) { if (streamCount > 0) {
List<SortedMap<String, String>> streamInfoList = new ArrayList<SortedMap<String, String>>(streamCount); List<Map<String, String>> streamInfoList = new ArrayList<Map<String, String>>(streamCount);
for (int i = 0; i < streamCount; i++) { for (int i = 0; i < streamCount; i++) {
streamInfoList.add(snapshot(streamKind, i)); streamInfoList.add(snapshot(streamKind, i));
@ -101,8 +100,8 @@ public class MediaInfo implements Closeable {
} }
public SortedMap<String, String> snapshot(StreamKind streamKind, int streamNumber) { public Map<String, String> snapshot(StreamKind streamKind, int streamNumber) {
TreeMap<String, String> streamInfo = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER); Map<String, String> streamInfo = new LinkedHashMap<String, String>();
for (int i = 0, count = parameterCount(streamKind, streamNumber); i < count; i++) { for (int i = 0, count = parameterCount(streamKind, streamNumber); i < count; i++) {
String value = get(streamKind, streamNumber, i, InfoKind.Text); String value = get(streamKind, streamNumber, i, InfoKind.Text);

View File

@ -109,8 +109,8 @@ public class EpisodeFormatDialog extends JDialog {
header.add(progressIndicator, "pos 1al 0al, hidemode 3"); header.add(progressIndicator, "pos 1al 0al, hidemode 3");
header.add(title, "wrap unrel:push"); header.add(title, "wrap unrel:push");
header.add(preview, "gap indent, hidemode 3, wmax 90%"); header.add(preview, "gap indent, hidemode 3, wmax 90%");
header.add(errorMessage, "gap indent, hidemode 3, newline"); header.add(errorMessage, "gap indent, hidemode 3, wmax 90%, newline");
header.add(warningMessage, "gap indent, hidemode 3, newline"); header.add(warningMessage, "gap indent, hidemode 3, wmax 90%, newline");
JPanel content = new JPanel(new MigLayout("insets dialog, nogrid, fill")); JPanel content = new JPanel(new MigLayout("insets dialog, nogrid, fill"));
@ -353,7 +353,7 @@ public class EpisodeFormatDialog extends JDialog {
error = e; error = e;
} }
errorMessage.setText(error != null ? error.getCause().getMessage() : null); errorMessage.setText(error != null ? ExceptionUtilities.getRootCauseMessage(error) : null);
errorMessage.setVisible(error != null); errorMessage.setVisible(error != null);
warningMessage.setText(warning != null ? warning.getCause().getMessage() : null); warningMessage.setText(warning != null ? warning.getCause().getMessage() : null);

View File

@ -9,7 +9,6 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
@ -29,16 +28,24 @@ import net.sourceforge.tuned.ui.TunedUtilities;
public class MediaInfoComponent extends JTabbedPane { public class MediaInfoComponent extends JTabbedPane {
public MediaInfoComponent(Map<StreamKind, List<SortedMap<String, String>>> mediaInfo) { public MediaInfoComponent(Map<StreamKind, List<Map<String, String>>> mediaInfo) {
insert(mediaInfo); insert(mediaInfo);
} }
public void insert(Map<StreamKind, List<SortedMap<String, String>>> mediaInfo) { public void insert(Map<StreamKind, List<Map<String, String>>> mediaInfo) {
// create tabs for all streams // create tabs for all streams
for (Entry<StreamKind, List<SortedMap<String, String>>> entry : mediaInfo.entrySet()) { for (Entry<StreamKind, List<Map<String, String>>> entry : mediaInfo.entrySet()) {
for (SortedMap<String, String> parameters : entry.getValue()) { for (Map<String, String> parameters : entry.getValue()) {
addTab(entry.getKey().toString(), new JScrollPane(new JTable(new ParameterTableModel(parameters)))); JTable table = new JTable(new ParameterTableModel(parameters));
// allow sorting
table.setAutoCreateRowSorter(true);
// sort by parameter name
table.getRowSorter().toggleSortOrder(0);
addTab(entry.getKey().toString(), new JScrollPane(table));
} }
} }
} }
@ -75,11 +82,11 @@ public class MediaInfoComponent extends JTabbedPane {
protected static class ParameterTableModel extends AbstractTableModel { protected static class ParameterTableModel extends AbstractTableModel {
private final List<Entry<?, ?>> data; private final List<Entry<String, String>> data;
public ParameterTableModel(Map<?, ?> data) { public ParameterTableModel(Map<String, String> data) {
this.data = new ArrayList<Entry<?, ?>>(data.entrySet()); this.data = new ArrayList<Entry<String, String>>(data.entrySet());
} }