better sorting of directories

This commit is contained in:
Erik Forkalsrud 2009-05-03 17:38:35 -07:00
parent 7386a1a36e
commit 0a7867cf14
4 changed files with 233 additions and 191 deletions

View file

@ -44,8 +44,8 @@ public class ComparatorFactory {
public int compare(Entry e1, Entry e2) { public int compare(Entry e1, Entry e2) {
Date d1 = e1.getDate(); Date d1 = e1.getEarliest();
Date d2 = e2.getDate(); Date d2 = e2.getEarliest();
if (d1 != null && d2 != null) { if (d1 != null && d2 != null) {
return d1.compareTo(d2); return d1.compareTo(d2);
} else if (d1 != null) { } else if (d1 != null) {

View file

@ -19,6 +19,7 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@ -46,6 +47,7 @@ public class DirectoryEntry extends Entry {
List<Entry> children = new ArrayList<Entry>(); List<Entry> children = new ArrayList<Entry>();
boolean childrenLoaded = false; boolean childrenLoaded = false;
Comparator<Entry> sort = null; Comparator<Entry> sort = null;
Date earliest = null;
public DirectoryEntry(File file) { public DirectoryEntry(File file) {
super(file); super(file);
@ -137,7 +139,7 @@ public class DirectoryEntry extends Entry {
return props; return props;
} }
Properties generateCache() throws MetadataException, JpegProcessingException, IOException { Properties generateCache() throws MetadataException, JpegProcessingException, IOException, ParseException {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
Properties props = new Properties(); Properties props = new Properties();
@ -151,8 +153,9 @@ public class DirectoryEntry extends Entry {
void generateFileEntries(Properties props) void generateFileEntries(Properties props)
throws IOException, MetadataException, JpegProcessingException { throws IOException, MetadataException, JpegProcessingException, ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
File[] files = file.listFiles(); File[] files = file.listFiles();
for (File f : files) { for (File f : files) {
@ -174,7 +177,11 @@ public class DirectoryEntry extends Entry {
continue; continue;
} }
if (name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".JPG")) { if (name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".JPG")) {
generateThumbnailProperties(props, f); String base = "file." + f.getName() + ".";
Map<String, String> p = generateThumbnailProperties(f);
for (Map.Entry<String, String> e : p.entrySet()) {
props.setProperty(base + e.getKey(), e.getValue());
}
} }
} }
} }
@ -186,10 +193,10 @@ public class DirectoryEntry extends Entry {
props.setProperty("dir." + name, "present"); props.setProperty("dir." + name, "present");
} }
private void generateThumbnailProperties(Properties props, File f) private Map<String, String> generateThumbnailProperties(File f)
throws JpegProcessingException, MetadataException, IOException { throws JpegProcessingException, MetadataException, IOException {
HashMap<String, String> props = new HashMap<String, String>();
String name = f.getName(); String name = f.getName();
String base = "file." + name + ".";
boolean hasDate = false; boolean hasDate = false;
boolean hasOrientation = false; boolean hasOrientation = false;
boolean hasDim = false; boolean hasDim = false;
@ -202,52 +209,53 @@ public class DirectoryEntry extends Entry {
Directory exifDirectory = metadata.getDirectory(ExifDirectory.class); Directory exifDirectory = metadata.getDirectory(ExifDirectory.class);
if (exifDirectory.containsTag(ExifDirectory.TAG_ORIENTATION)) { if (exifDirectory.containsTag(ExifDirectory.TAG_ORIENTATION)) {
int orientation = exifDirectory.getInt(ExifDirectory.TAG_ORIENTATION); int orientation = exifDirectory.getInt(ExifDirectory.TAG_ORIENTATION);
props.setProperty(base + "orientation", nf.format(orientation)); props.put("orientation", nf.format(orientation));
hasOrientation = true; hasOrientation = true;
} }
if (exifDirectory.containsTag(ExifDirectory.TAG_EXIF_IMAGE_WIDTH) && if (exifDirectory.containsTag(ExifDirectory.TAG_EXIF_IMAGE_WIDTH) &&
exifDirectory.containsTag(ExifDirectory.TAG_EXIF_IMAGE_HEIGHT)) { exifDirectory.containsTag(ExifDirectory.TAG_EXIF_IMAGE_HEIGHT)) {
int width = exifDirectory.getInt(ExifDirectory.TAG_EXIF_IMAGE_WIDTH); int width = exifDirectory.getInt(ExifDirectory.TAG_EXIF_IMAGE_WIDTH);
int height = exifDirectory.getInt(ExifDirectory.TAG_EXIF_IMAGE_HEIGHT); int height = exifDirectory.getInt(ExifDirectory.TAG_EXIF_IMAGE_HEIGHT);
props.setProperty(base + "dimensions", new Dimension(width, height).toString()); props.put("dimensions", new Dimension(width, height).toString());
hasDim = true; hasDim = true;
} }
if (exifDirectory.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) { if (exifDirectory.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) {
Date captureDate = getExifDate(exifDirectory, ExifDirectory.TAG_DATETIME_ORIGINAL); Date captureDate = getExifDate(exifDirectory, ExifDirectory.TAG_DATETIME_ORIGINAL);
if (captureDate != null) { if (captureDate != null) {
props.setProperty(base + "captureDate", sdf.format(captureDate)); props.put("captureDate", sdf.format(captureDate));
hasDate = true; hasDate = true;
} }
} }
if (exifDirectory.containsTag(ExifDirectory.TAG_USER_COMMENT)) { if (exifDirectory.containsTag(ExifDirectory.TAG_USER_COMMENT)) {
String comment = exifDirectory.getString(ExifDirectory.TAG_USER_COMMENT); String comment = exifDirectory.getString(ExifDirectory.TAG_USER_COMMENT);
props.setProperty(base + "comment", comment); props.put("comment", comment);
} }
Directory jpegDirectory = metadata.getDirectory(JpegDirectory.class); Directory jpegDirectory = metadata.getDirectory(JpegDirectory.class);
if (jpegDirectory.containsTag(JpegDirectory.TAG_JPEG_IMAGE_WIDTH) && if (jpegDirectory.containsTag(JpegDirectory.TAG_JPEG_IMAGE_WIDTH) &&
jpegDirectory.containsTag(JpegDirectory.TAG_JPEG_IMAGE_HEIGHT)) { jpegDirectory.containsTag(JpegDirectory.TAG_JPEG_IMAGE_HEIGHT)) {
int width = jpegDirectory.getInt(JpegDirectory.TAG_JPEG_IMAGE_WIDTH); int width = jpegDirectory.getInt(JpegDirectory.TAG_JPEG_IMAGE_WIDTH);
int height = jpegDirectory.getInt(JpegDirectory.TAG_JPEG_IMAGE_HEIGHT); int height = jpegDirectory.getInt(JpegDirectory.TAG_JPEG_IMAGE_HEIGHT);
props.setProperty(base + "dimensions", new Dimension(width, height).toString()); props.put("dimensions", new Dimension(width, height).toString());
hasDim = true; hasDim = true;
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("problem reading file " + f.getPath(), e); throw new RuntimeException("problem reading file " + f.getPath(), e);
} }
props.setProperty(base + "etag", Integer.toHexString(name.hashCode() + Long.valueOf(f.lastModified()).hashCode())); props.put("etag", Integer.toHexString(name.hashCode() + Long.valueOf(f.lastModified()).hashCode()));
if (!hasDate) { if (!hasDate) {
props.setProperty(base + "captureDate", sdf.format(new Date(f.lastModified()))); props.put("captureDate", sdf.format(new Date(f.lastModified())));
} }
if (!hasOrientation) { if (!hasOrientation) {
props.setProperty(base + "orientation", "1"); props.put("orientation", "1");
} }
if (!hasDim) { if (!hasDim) {
Dimension dim = decodeImageForDimensions(f); Dimension dim = decodeImageForDimensions(f);
if (dim != null) { if (dim != null) {
props.setProperty(base + "dimensions", dim.toString()); props.put("dimensions", dim.toString());
hasDim = true; hasDim = true;
} }
} }
return props;
} }
private Date getExifDate(Directory exifDirectory, int tagName) throws MetadataException { private Date getExifDate(Directory exifDirectory, int tagName) throws MetadataException {
@ -305,9 +313,13 @@ public class DirectoryEntry extends Entry {
String caption = props.getProperty("caption"); String caption = props.getProperty("caption");
setCaption(caption); setCaption(caption);
sort = ComparatorFactory.getSort(props.getProperty("sort")); sort = ComparatorFactory.getSort(props.getProperty("sort"));
HashMap<String, Entry> entryMap = new HashMap<String, Entry>(); HashMap<String, Entry> entryMap = new HashMap<String, Entry>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss"); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
Iterator i = props.keySet().iterator();
Date oldest = new Date(file.lastModified());
Iterator<Object> i = props.keySet().iterator();
while (i.hasNext()) { while (i.hasNext()) {
String key = (String)i.next(); String key = (String)i.next();
if (key.startsWith("file.") && key.endsWith(".dimensions")) { if (key.startsWith("file.") && key.endsWith(".dimensions")) {
@ -317,7 +329,11 @@ public class DirectoryEntry extends Entry {
FileEntry entry = new FileEntry(this, f); FileEntry entry = new FileEntry(this, f);
Thumbnail thumbnail = new Thumbnail(f); Thumbnail thumbnail = new Thumbnail(f);
entry.setCaption(props.getProperty("file." + name + ".caption")); entry.setCaption(props.getProperty("file." + name + ".caption"));
entry.setDate(sdf.parse(props.getProperty("file." + name + ".captureDate"))); Date fileDate = sdf.parse(props.getProperty("file." + name + ".captureDate"));
if (fileDate.before(oldest)) {
oldest = fileDate;
}
entry.setDate(fileDate);
thumbnail.setSize(new Dimension(props.getProperty("file." + name + ".dimensions"))); thumbnail.setSize(new Dimension(props.getProperty("file." + name + ".dimensions")));
thumbnail.setOrientation(Integer.parseInt(props.getProperty("file." + name + ".orientation"))); thumbnail.setOrientation(Integer.parseInt(props.getProperty("file." + name + ".orientation")));
thumbnail.setEtag(props.getProperty("file." + name + ".etag")); thumbnail.setEtag(props.getProperty("file." + name + ".etag"));
@ -334,13 +350,26 @@ public class DirectoryEntry extends Entry {
String name = key.substring("dir.".length()); String name = key.substring("dir.".length());
boolean hidden = Boolean.parseBoolean(props.getProperty("dir." + name + ".hidden")); boolean hidden = Boolean.parseBoolean(props.getProperty("dir." + name + ".hidden"));
if (!hidden) { if (!hidden) {
children.add(new DirectoryEntry(this, new File(file, name))); DirectoryEntry dir = new DirectoryEntry(this, new File(file, name));
children.add(dir);
Date fileDate = dir.getEarliest();
if (fileDate != null && fileDate.before(oldest)) {
oldest = fileDate;
} }
} }
} }
}
this.earliest = oldest;
if (thumbnail == null && !children.isEmpty()) { if (thumbnail == null && !children.isEmpty()) {
setThumbnail(children.get(0).getThumbnail()); setThumbnail(children.get(0).getThumbnail());
} }
} }
@Override
public Date getEarliest() {
loadChildren();
return earliest;
}
} }

View file

@ -100,4 +100,8 @@ public abstract class Entry {
public File getPath() { public File getPath() {
return file; return file;
} }
public Date getEarliest() {
return getDate();
}
} }

View file

@ -2,6 +2,8 @@ package org.forkalsrud.album.web;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
@ -230,7 +232,6 @@ public class AlbumServlet
public class Mapper { public class Mapper {
public String map(File file) { public String map(File file) {
StringBuilder buf = new StringBuilder(); StringBuilder buf = new StringBuilder();
return appendFile(buf, file).toString(); return appendFile(buf, file).toString();
} }
@ -245,7 +246,15 @@ public class AlbumServlet
return appendFile(buf, file.getParentFile()).append('/').append(file.getName()); return appendFile(buf, file.getParentFile()).append('/').append(file.getName());
} }
} }
Calendar cal = Calendar.getInstance();
public String year(Date d) {
cal.setTime(d);
return String.valueOf(cal.get(Calendar.YEAR));
} }
} }
}
// eof // eof