snark sorters for details page

no links yet
This commit is contained in:
zzz
2014-09-22 15:18:20 +00:00
parent 3fae6f06dd
commit 479b9691fd
2 changed files with 219 additions and 30 deletions

View File

@ -221,7 +221,8 @@ public class I2PSnarkServlet extends BasicServlet {
resp.sendError(404);
} else {
String base = addPaths(req.getRequestURI(), "/");
String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null);
String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null,
req.getParameter("sort"));
if (method.equals("POST")) {
// P-R-G
sendRedirect(req, resp, "");
@ -2493,23 +2494,6 @@ public class I2PSnarkServlet extends BasicServlet {
private static final String FOOTER = "</div></center></body></html>";
/**
* Sort alphabetically in current locale, ignore case,
* directories first
* @since 0.9.6
*/
private static class ListingComparator implements Comparator<File>, Serializable {
public int compare(File l, File r) {
boolean ld = l.isDirectory();
boolean rd = r.isDirectory();
if (ld && !rd)
return -1;
if (rd && !ld)
return 1;
return Collator.getInstance().compare(l.getName(), r.getName());
}
}
/**
* Modded heavily from the Jetty version in Resource.java,
@ -2538,10 +2522,11 @@ public class I2PSnarkServlet extends BasicServlet {
* @param base The encoded base URL
* @param parent True if the parent directory should be included
* @param postParams map of POST parameters or null if not a POST
* @param sortParam may be null
* @return String of HTML or null if postParams != null
* @since 0.7.14
*/
private String getListHTML(File xxxr, String base, boolean parent, Map<String, String[]> postParams)
private String getListHTML(File xxxr, String base, boolean parent, Map<String, String[]> postParams, String sortParam)
throws IOException
{
String decodedBase = decodePath(base);
@ -2845,7 +2830,6 @@ public class I2PSnarkServlet extends BasicServlet {
File[] ls = null;
if (r.isDirectory()) {
ls = r.listFiles();
Arrays.sort(ls, new ListingComparator());
} // if r is not a directory, we are only showing torrent info section
if (ls == null) {
@ -2854,6 +2838,21 @@ public class I2PSnarkServlet extends BasicServlet {
return buf.toString();
}
Storage storage = snark != null ? snark.getStorage() : null;
List<Sorters.FileAndIndex> fileList = new ArrayList<Sorters.FileAndIndex>(ls.length);
for (int i = 0; i < ls.length; i++) {
fileList.add(new Sorters.FileAndIndex(ls[i], storage));
}
if (fileList.size() > 1) {
int sort = 0;
if (sortParam != null) {
try {
sort = Integer.parseInt(sortParam);
} catch (NumberFormatException nfe) {}
}
Collections.sort(fileList, Sorters.getFileComparator(sort, this));
}
// second table - dir info
buf.append("<table class=\"snarkDirInfo\"><thead>\n");
buf.append("<tr>\n")
@ -2884,25 +2883,27 @@ public class I2PSnarkServlet extends BasicServlet {
//DateFormat dfmt=DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
// DateFormat.MEDIUM);
boolean showSaveButton = false;
for (int i=0 ; i< ls.length ; i++)
boolean rowEven = true;
for (Sorters.FileAndIndex fai : fileList)
{
//String encoded = encodePath(ls[i].getName());
// bugfix for I2P - Backport from Jetty 6 (zero file lengths and last-modified times)
// http://jira.codehaus.org/browse/JETTY-361?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel#issue-tabs
// See resource.diff attachment
//Resource item = addPath(encoded);
File item = ls[i];
File item = fai.file;
String rowClass = (i % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
String rowClass = (rowEven ? "snarkTorrentEven" : "snarkTorrentOdd");
rowEven = !rowEven;
buf.append("<TR class=\"").append(rowClass).append("\">");
// Get completeness and status string
boolean complete = false;
String status = "";
long length = item.length();
int fileIndex = -1;
int fileIndex = fai.index;
int priority = 0;
if (item.isDirectory()) {
if (fai.isDirectory) {
complete = true;
//status = toImg("tick") + ' ' + _("Directory");
} else {
@ -2911,10 +2912,8 @@ public class I2PSnarkServlet extends BasicServlet {
complete = true;
status = toImg("cancel") + ' ' + _("Torrent not found?");
} else {
Storage storage = snark.getStorage();
fileIndex = storage.indexOf(item);
long remaining = storage.remaining(fileIndex);
long remaining = fai.remaining;
if (remaining < 0) {
complete = true;
status = toImg("cancel") + ' ' + _("File not found in torrent?");
@ -2922,7 +2921,7 @@ public class I2PSnarkServlet extends BasicServlet {
complete = true;
status = toImg("tick") + ' ' + _("Complete");
} else {
priority = storage.getPriority(fileIndex);
priority = fai.priority;
if (priority < 0)
status = toImg("cancel");
else if (priority == 0)
@ -2937,7 +2936,7 @@ public class I2PSnarkServlet extends BasicServlet {
}
}
String path = addPaths(decodedBase, ls[i].getName());
String path = addPaths(decodedBase, item.getName());
if (item.isDirectory() && !path.endsWith("/"))
path=addPaths(path,"/");
path = encodePath(path);

View File

@ -1,5 +1,6 @@
package org.klomp.snark.web;
import java.io.File;
import java.io.Serializable;
import java.text.Collator;
import java.util.Collections;
@ -8,6 +9,7 @@ import java.util.Locale;
import org.klomp.snark.MetaInfo;
import org.klomp.snark.Snark;
import org.klomp.snark.Storage;
/**
* Comparators for various columns
@ -338,4 +340,192 @@ class Sorters {
return servlet.toIcon(meta.getName());
}
}
////////////// Comparators for details page below
/**
* Class to precompute and efficiently sort data
* on a torrent file entry.
*/
public static class FileAndIndex {
public final File file;
public final boolean isDirectory;
public final long length;
public final long remaining;
public final int priority;
public final int index;
/**
* @param storage may be null
*/
public FileAndIndex(File file, Storage storage) {
this.file = file;
index = storage != null ? storage.indexOf(file) : -1;
if (index >= 0) {
isDirectory = false;
remaining = storage.remaining(index);
priority = storage.getPriority(index);
} else {
isDirectory = file.isDirectory();
remaining = -1;
priority = 0;
}
length = isDirectory ? 0 : file.length();
}
}
/**
* Negative is reverse
*
*<ul>
*<li>0, 1: Name
*<li>5: Size
*<li>10: Remaining (needed)
*<li>12: File type
*<li>13: Priority
*</ul>
*
* @param servlet for file type callback only
*/
public static Comparator<FileAndIndex> getFileComparator(int type, I2PSnarkServlet servlet) {
boolean rev = type < 0;
Comparator<FileAndIndex> rv;
switch (type) {
case -1:
case 0:
case 1:
default:
rv = new FileNameComparator();
if (rev)
rv = Collections.reverseOrder(rv);
break;
case -5:
case 5:
rv = new FAISizeComparator(rev);
break;
case -10:
case 10:
rv = new FAIRemainingComparator(rev);
break;
case -12:
case 12:
rv = new FAITypeComparator(rev, servlet);
break;
case -13:
case 13:
rv = new FAIPriorityComparator(rev);
break;
}
return rv;
}
/**
* Sort alphabetically in current locale, ignore case,
* directories first
* @since 0.9.6 moved from I2PSnarkServlet in 0.9.16
*/
private static class FileNameComparator implements Comparator<FileAndIndex>, Serializable {
public int compare(FileAndIndex l, FileAndIndex r) {
return comp(l, r);
}
public static int comp(FileAndIndex l, FileAndIndex r) {
boolean ld = l.isDirectory;
boolean rd = r.isDirectory;
if (ld && !rd)
return -1;
if (rd && !ld)
return 1;
return Collator.getInstance().compare(l.file.getName(), r.file.getName());
}
}
/**
* Forward or reverse sort, but the fallback is always forward
*/
private static abstract class FAISort implements Comparator<FileAndIndex>, Serializable {
private final boolean _rev;
public FAISort(boolean rev) {
_rev = rev;
}
public int compare(FileAndIndex l, FileAndIndex r) {
int rv = compareIt(l, r);
if (rv != 0)
return _rev ? 0 - rv : rv;
return FileNameComparator.comp(l, r);
}
protected abstract int compareIt(FileAndIndex l, FileAndIndex r);
protected static int compLong(long l, long r) {
if (l < r)
return -1;
if (l > r)
return 1;
return 0;
}
}
private static class FAIRemainingComparator extends FAISort {
public FAIRemainingComparator(boolean rev) { super(rev); }
public int compareIt(FileAndIndex l, FileAndIndex r) {
return compLong(l.remaining, r.remaining);
}
}
private static class FAISizeComparator extends FAISort {
public FAISizeComparator(boolean rev) { super(rev); }
public int compareIt(FileAndIndex l, FileAndIndex r) {
return compLong(l.length, r.length);
}
}
private static class FAITypeComparator extends FAISort {
private final I2PSnarkServlet servlet;
public FAITypeComparator(boolean rev, I2PSnarkServlet servlet) {
super(rev);
this.servlet = servlet;
}
public int compareIt(FileAndIndex l, FileAndIndex r) {
String ls = toName(l);
String rs = toName(r);
return ls.compareTo(rs);
}
private String toName(FileAndIndex fai) {
if (fai.isDirectory)
return "0";
// arbitrary sort based on icon name
return servlet.toIcon(fai.file.getName());
}
}
private static class FAIPriorityComparator extends FAISort {
public FAIPriorityComparator(boolean rev) { super(rev); }
/** highest first */
public int compareIt(FileAndIndex l, FileAndIndex r) {
return r.priority - l.priority;
}
}
}