# HG changeset patch # User robcast # Date 1063729920 -7200 # Node ID e743b853efca51ab63c0f572d972da97b9c4072e # Parent e9a81ac446cb3079ee9f13a7a218dc555db68397 servlet version 1.16a4 - rather experimental - new Texter servlet for sending text - reads and caches text files in DocuDirCache - DocuFile renamed to ImageFile (-Set) - new TextFile diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/DocuImage.java --- a/servlet/src/digilib/image/DocuImage.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/DocuImage.java Tue Sep 16 18:32:00 2003 +0200 @@ -23,7 +23,7 @@ import java.awt.Rectangle; import java.io.OutputStream; -import digilib.io.DocuFile; +import digilib.io.ImageFile; import digilib.io.FileOpException; /** The basic class for the representation of a digilib image. @@ -46,7 +46,7 @@ * @param f Image File. * @throws FileOpException Exception thrown if any error occurs. */ - public void loadImage(DocuFile f) throws FileOpException; + public void loadImage(ImageFile f) throws FileOpException; /** This DocuImage support the loadSubImage operation. * @@ -61,7 +61,7 @@ * @param subsample * @throws FileOpException */ - public void loadSubimage(DocuFile f, Rectangle region, int subsample) + public void loadSubimage(ImageFile f, Rectangle region, int subsample) throws FileOpException; /** Writes the current image to a ServletResponse. diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/DocuImageImpl.java --- a/servlet/src/digilib/image/DocuImageImpl.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/DocuImageImpl.java Tue Sep 16 18:32:00 2003 +0200 @@ -23,7 +23,7 @@ import java.awt.Rectangle; import digilib.Utils; -import digilib.io.DocuFile; +import digilib.io.ImageFile; import digilib.io.FileOpException; /** Simple abstract implementation of the DocuImage interface. @@ -140,7 +140,7 @@ return false; } - public void loadSubimage(DocuFile f, Rectangle region, int subsample) + public void loadSubimage(ImageFile f, Rectangle region, int subsample) throws FileOpException { // empty implementation } diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/DocuInfo.java --- a/servlet/src/digilib/image/DocuInfo.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/DocuInfo.java Tue Sep 16 18:32:00 2003 +0200 @@ -22,7 +22,7 @@ import java.io.IOException; -import digilib.io.DocuFile; +import digilib.io.ImageFile; /** * @author casties @@ -30,15 +30,15 @@ */ public interface DocuInfo { - /** Checks the size and type of the DocuFile f. + /** Checks the size and type of the ImageFile f. * - * The image size and type of the DocuFile f is determined and stored in - * the DocuFile object. Returns true if successfull. + * The image size and type of the ImageFile f is determined and stored in + * the ImageFile object. Returns true if successfull. * - * @param f DocuFile to be checked. + * @param f ImageFile to be checked. * @return boolean true if check was successfull. * @throws FileOpException Exception thrown on error. */ - public boolean checkFile(DocuFile f) throws IOException; + public boolean checkFile(ImageFile f) throws IOException; } diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/ImageLoaderDocuImage.java --- a/servlet/src/digilib/image/ImageLoaderDocuImage.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/ImageLoaderDocuImage.java Tue Sep 16 18:32:00 2003 +0200 @@ -38,7 +38,7 @@ import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; -import digilib.io.DocuFile; +import digilib.io.ImageFile; import digilib.io.FileOpException; /** Implementation of DocuImage using the ImageLoader API of Java 1.4 and Java2D. */ @@ -99,9 +99,9 @@ } /* load image file */ - public void loadImage(DocuFile f) throws FileOpException { + public void loadImage(ImageFile f) throws FileOpException { util.dprintln(10, "loadImage!"); - System.gc(); + //System.gc(); try { img = ImageIO.read(f.getFile()); if (img == null) { @@ -116,13 +116,13 @@ /** Get an ImageReader for the image file. * */ - public void preloadImage(DocuFile f) throws IOException { + public void preloadImage(ImageFile f) throws IOException { if (reader != null) { // clean up old reader reader.dispose(); reader = null; } - System.gc(); + //System.gc(); RandomAccessFile rf = new RandomAccessFile(f.getFile(), "r"); ImageInputStream istream = ImageIO.createImageInputStream(rf); //Iterator readers = ImageIO.getImageReaders(istream); @@ -145,9 +145,9 @@ } /* Load an image file into the Object. */ - public void loadSubimage(DocuFile f, Rectangle region, int prescale) + public void loadSubimage(ImageFile f, Rectangle region, int prescale) throws FileOpException { - System.gc(); + //System.gc(); try { if ((reader == null) || (imgFile != f.getFile())) { preloadImage(f); diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/ImageLoaderDocuInfo.java --- a/servlet/src/digilib/image/ImageLoaderDocuInfo.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/ImageLoaderDocuInfo.java Tue Sep 16 18:32:00 2003 +0200 @@ -23,7 +23,7 @@ import java.io.IOException; -import digilib.io.DocuFile; +import digilib.io.ImageFile; import digilib.io.FileOps; /** @@ -34,8 +34,8 @@ private ImageLoaderDocuImage img = new ImageLoaderDocuImage(); - /* check image size and type and store in DocuFile f */ - public boolean checkFile(DocuFile f) throws IOException { + /* check image size and type and store in ImageFile f */ + public boolean checkFile(ImageFile f) throws IOException { ImageLoaderDocuImage img = new ImageLoaderDocuImage(); img.preloadImage(f); img.reader = img.reader; diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/ImageLoaderImageInfoDocuInfo.java --- a/servlet/src/digilib/image/ImageLoaderImageInfoDocuInfo.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/ImageLoaderImageInfoDocuInfo.java Tue Sep 16 18:32:00 2003 +0200 @@ -22,6 +22,7 @@ import ImageInfo; +import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Iterator; @@ -30,9 +31,9 @@ import javax.imageio.ImageReader; import javax.imageio.stream.ImageInputStream; -import digilib.io.DocuFile; import digilib.io.FileOpException; import digilib.io.FileOps; +import digilib.io.ImageFile; /** * @author casties @@ -40,9 +41,13 @@ */ public class ImageLoaderImageInfoDocuInfo implements DocuInfo { - /* check image size and type and store in DocuFile f */ - public boolean checkFile(DocuFile f) throws IOException { - RandomAccessFile raf = new RandomAccessFile(f.getFile(), "r"); + /* check image size and type and store in ImageFile f */ + public boolean checkFile(ImageFile imgf) throws IOException { + File f = imgf.getFile(); + if (f == null) { + throw new IOException("File not found!"); + } + RandomAccessFile raf = new RandomAccessFile(f, "r"); // set up ImageInfo object ImageInfo iif = new ImageInfo(); iif.setInput(raf); @@ -52,8 +57,8 @@ if (iif.check()) { ImageSize d = new ImageSize(iif.getWidth(), iif.getHeight()); - f.setSize(d); - f.setMimetype(iif.getMimeType()); + imgf.setSize(d); + imgf.setMimetype(iif.getMimeType()); raf.close(); } else { // else use ImageReader @@ -73,10 +78,10 @@ reader.setInput(istream); ImageSize d = new ImageSize(reader.getWidth(0), reader.getHeight(0)); - f.setSize(d); + imgf.setSize(d); String t = reader.getFormatName(); - t = FileOps.mimeForFile(f.getFile()); - f.setMimetype(t); + t = FileOps.mimeForFile(f); + imgf.setMimetype(t); // dispose the reader to free resources reader.dispose(); } diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/ImageSize.java --- a/servlet/src/digilib/image/ImageSize.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/ImageSize.java Tue Sep 16 18:32:00 2003 +0200 @@ -1,4 +1,4 @@ -/* DocuFile.java -- digilib image file class. +/* ImageFile.java -- digilib image file class. Digital Image Library servlet components diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/JAIDocuImage.java --- a/servlet/src/digilib/image/JAIDocuImage.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/JAIDocuImage.java Tue Sep 16 18:32:00 2003 +0200 @@ -35,7 +35,7 @@ import javax.media.jai.operator.TransposeType; import digilib.Utils; -import digilib.io.DocuFile; +import digilib.io.ImageFile; import digilib.io.FileOpException; /** A DocuImage implementation using Java Advanced Imaging Library. */ @@ -56,7 +56,7 @@ } /* Load an image file into the Object. */ - public void loadImage(DocuFile f) throws FileOpException { + public void loadImage(ImageFile f) throws FileOpException { System.gc(); img = JAI.create("fileload", f.getFile().getAbsolutePath()); if (img == null) { diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/JAIImageLoaderDocuImage.java --- a/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/JAIImageLoaderDocuImage.java Tue Sep 16 18:32:00 2003 +0200 @@ -34,7 +34,7 @@ import javax.imageio.stream.ImageInputStream; import javax.media.jai.JAI; -import digilib.io.DocuFile; +import digilib.io.ImageFile; import digilib.io.FileOpException; /** DocuImage implementation using the Java Advanced Imaging API and the ImageLoader @@ -81,7 +81,7 @@ } /* Load an image file into the Object. */ - public void loadImage(DocuFile f) throws FileOpException { + public void loadImage(ImageFile f) throws FileOpException { System.gc(); img = JAI.create("ImageRead", f.getFile().getAbsolutePath()); if (img == null) { @@ -91,7 +91,7 @@ } /* Get an ImageReader for the image file. */ - public void preloadImage(DocuFile f) throws IOException { + public void preloadImage(ImageFile f) throws IOException { System.gc(); RandomAccessFile rf = new RandomAccessFile(f.getFile(), "r"); ImageInputStream istream = ImageIO.createImageInputStream(rf); @@ -106,7 +106,7 @@ } /* Load an image file into the Object. */ - public void loadSubimage(DocuFile f, Rectangle region, int prescale) + public void loadSubimage(ImageFile f, Rectangle region, int prescale) throws FileOpException { System.gc(); try { diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/image/JIMIDocuImage.java --- a/servlet/src/digilib/image/JIMIDocuImage.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/image/JIMIDocuImage.java Tue Sep 16 18:32:00 2003 +0200 @@ -32,7 +32,7 @@ import com.sun.jimi.core.raster.JimiRasterImage; import digilib.Utils; -import digilib.io.DocuFile; +import digilib.io.ImageFile; import digilib.io.FileOpException; /** Implementation of DocuImage using the JIMI image Library. */ @@ -53,7 +53,7 @@ /** * load image file */ - public void loadImage(DocuFile f) throws FileOpException { + public void loadImage(ImageFile f) throws FileOpException { System.gc(); try { img = Jimi.getRasterImage(f.getFile().toURL()); diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/Directory.java --- a/servlet/src/digilib/io/Directory.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/io/Directory.java Tue Sep 16 18:32:00 2003 +0200 @@ -50,7 +50,8 @@ /** Constructor taking a File object and a parent. * - * @param d + * @param dir + * @param parent */ public Directory(File dir, Directory parent) { this.dir = dir; diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/DocuDirCache.java --- a/servlet/src/digilib/io/DocuDirCache.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/io/DocuDirCache.java Tue Sep 16 18:32:00 2003 +0200 @@ -23,23 +23,37 @@ import java.io.File; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; /** * @author casties */ public class DocuDirCache { - // HashMap of directories + /** HashMap of directories */ private HashMap map = null; - // names of base directories + /** names of base directories */ private String[] baseDirNames = null; - // number of files in the whole cache (approximate) + /** array of allowed file classes (image/text) */ + private int[] fileClasses = null; + /** number of files in the whole cache (approximate) */ private long numFiles = 0; - // number of cache hits + /** number of cache hits */ private long hits = 0; - // number of cache misses + /** number of cache misses */ private long misses = 0; + /** Constructor with array of base directory names and file classes. + * + * @param bd base directory names + */ + public DocuDirCache(String[] bd, int[] fileClasses) { + baseDirNames = bd; + map = new HashMap(); + this.fileClasses = fileClasses; + } /** Constructor with array of base directory names. * * @param bd base directory names @@ -47,6 +61,9 @@ public DocuDirCache(String[] bd) { baseDirNames = bd; map = new HashMap(); + // default file class is CLASS_IMAGE + fileClasses = new int[1]; + fileClasses[0] = FileOps.CLASS_IMAGE; } /** The number of directories in the cache. @@ -63,7 +80,7 @@ public void put(DocuDirectory newdir) { String s = newdir.getDirName(); if (map.containsKey(s)) { - System.out.println("Baah, duplicate key in DocuDirectory.put!"); + System.out.println("Baah, duplicate key in DocuDirCache.put!"); } else { map.put(s, newdir); numFiles += newdir.size(); @@ -87,12 +104,37 @@ } newDir.setParent(pd); } - // update dir in the end - newDir.readParentMeta(); } - /** Returns the DocuFileset with the pathname fn and the - * index in. + /** Get a list with all children of a directory. + * + * Returns a List of DocuDirectory's. + * Returns an empty List if the directory has no children. + * If recurse is false then only direct children are returned. + * + * @param dirname + * @param recurse find all children and their children. + * @return + */ + public List getChildren(String dirname, boolean recurse) { + List l = new LinkedList(); + for (Iterator i = map.keySet().iterator(); i.hasNext(); ) { + DocuDirectory dd = (DocuDirectory)i.next(); + if (recurse) { + if (dd.getDirName().startsWith(dirname)) { + l.add(dd); + } + } else { + if (dd.getParentDirName().equals(dirname)) { + l.add(dd); + } + } + } + return l; + } + + /** Returns the ImageFileset with the pathname fn and the + * index in and the class fc. * * If fn is a file then the corresponding Fileset is * returned and the index is ignored. @@ -101,7 +143,7 @@ * @param in file index * @return */ - public DocuFileset getFileset(String fn, int in) { + public DocuDirent getFile(String fn, int in, int fc) { DocuDirectory dd; // file number is 1-based, vector index is 0-based int n = in - 1; @@ -140,7 +182,7 @@ misses--; } // get the file's index - n = dd.indexOf(f.getName()); + n = dd.indexOf(f.getName(), fc); } else { // it's not even a file :-( return null; @@ -153,7 +195,7 @@ dd.refresh(); if (dd.isValid()) { try { - return dd.get(n); + return dd.get(n, fc); } catch (ArrayIndexOutOfBoundsException e) { } } @@ -253,4 +295,18 @@ return misses; } + /** + * @return + */ + public int[] getFileClasses() { + return fileClasses; + } + + /** + * @param fileClasses + */ + public void setFileClasses(int[] fileClasses) { + this.fileClasses = fileClasses; + } + } diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/DocuDirectory.java --- a/servlet/src/digilib/io/DocuDirectory.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/io/DocuDirectory.java Tue Sep 16 18:32:00 2003 +0200 @@ -27,6 +27,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import org.xml.sax.SAXException; @@ -35,9 +36,9 @@ */ public class DocuDirectory extends Directory { - // list of files (DocuFileSet) - private ArrayList list = null; - // directory object is valid (has been read) + // list of files (DocuDirent) + private ArrayList[] list = null; + // directory object is valid (exists on disk) private boolean isValid = false; // reference of the parent DocuDirCache private DocuDirCache cache = null; @@ -52,29 +53,37 @@ // time the file system directory was last modified private long dirMTime = 0; - /* - * constructors - */ - - /** Constructor with directory path and a parent DocuDirCache. + /** Constructor with digilib directory path and a parent DocuDirCache. * - * Reads the directory at the given path appended to the base directories - * from the cache. + * Directory names at the given path are appended to the base directories + * from the cache. The directory is checked on disk and isValid is set. + * If read is true the directory is read and filled. * * @see readDir * * @param path digilib directory path name * @param bd array of base directory names + * @param read the directory is read and filled */ public DocuDirectory(String path, DocuDirCache cache) { this.dirName = path; this.cache = cache; - readDir(); + initDir(); + checkDir(); } - /* - * other stuff + /** Sets and checks the dir object. + * */ + protected void initDir() { + String baseDirName = cache.getBaseDirNames()[0]; + // clear directory first + list = new ArrayList[FileOps.NUM_CLASSES]; + isValid = false; + dirMTime = 0; + // the first directory has to exist + dir = new File(baseDirName, dirName); + } /** The digilib name of the parent directory. * @@ -93,19 +102,54 @@ * */ public int size() { - return (list != null) ? list.size() : 0; + return ((list != null)&&(list[0] != null)) ? list[0].size() : 0; } - /** Returns the DocuFile at the index. + /** number of files of this class in this directory. + * + * @param fc fileClass + */ + public int size(int fc) { + return ((list != null)&&(list[fc] != null)) ? list[fc].size() : 0; + } + + /** Returns the ImageFile at the index. * * @param index * @return */ - public DocuFileset get(int index) { - if ((list == null) || (index >= list.size())) { + public ImageFileset get(int index) { + if ((list == null) || (list[0] != null) || (index >= list[0].size())) { return null; } - return (DocuFileset) list.get(index); + return (ImageFileset) list[0].get(index); + } + + /** Returns the file of the class at the index. + * + * @param index + * @param fc fileClass + * @return + */ + public DocuDirent get(int index, int fc) { + if ((list == null) || (list[fc] == null) || (index >= list[fc].size())) { + return null; + } + return (DocuDirent) list[fc].get(index); + } + + /** Checks if the directory exists on the filesystem. + * + * Sets isValid. + * + * @return + */ + public boolean checkDir() { + if (dir == null) { + initDir(); + } + isValid = dir.isDirectory(); + return isValid; } /** Read the filesystem directory and fill this object. @@ -115,91 +159,64 @@ * @return boolean the directory exists */ public boolean readDir() { + // list of base dirs from the parent cache String[] baseDirNames = cache.getBaseDirNames(); // first file extension to try for scaled directories - String fext = null; - // clear directory first - list = null; - isValid = false; + String scalext = null; // number of base dirs int nb = baseDirNames.length; // array of base dirs Directory[] dirs = new Directory[nb]; - // the first directory has to exist - dir = new File(baseDirNames[0], dirName); + // check directory first + checkDir(); + if (!isValid) { + return false; + } + // first entry is this directory + dirs[0] = this; + // fill array with the remaining directories + for (int j = 1; j < nb; j++) { + File d = new File(baseDirNames[j], dirName); + if (d.isDirectory()) { + dirs[j] = new Directory(d); + } + } - if (dir.isDirectory()) { - // fill array with the remaining directories - for (int j = 1; j < nb; j++) { - File d = new File(baseDirNames[j], dirName); - if (d.isDirectory()) { - dirs[j] = new Directory(d); - } - } - - File[] fl = dir.listFiles(new FileOps.ImageFileFilter()); + // go through all file classes + for (int nc = 0; nc < FileOps.NUM_CLASSES; nc++) { + int fc = cache.getFileClasses()[nc]; + File[] fl = dir.listFiles(FileOps.filterForClass(fc)); if (fl == null) { // not a directory return false; } - // number of image files in the directory + // number of files in the directory int nf = fl.length; if (nf > 0) { // create new list - list = new ArrayList(nf); - + list[fc] = new ArrayList(nf); // sort the file names alphabetically and iterate the list Arrays.sort(fl); for (int i = 0; i < nf; i++) { - String fn = fl[i].getName(); - String fnx = fn.substring(0, fn.lastIndexOf('.') + 1); - // add the first DocuFile to a new DocuFileset - DocuFileset fs = new DocuFileset(nb); - fs.add(new DocuFile(fn, fs, this)); - // iterate the remaining base directories - for (int j = 1; j < nb; j++) { - if (dirs[j] == null) { - continue; - } - File f; - if (fext != null) { - // use the last extension - f = new File(dirs[j].getDir(), fnx + fext); - } else { - // try the same filename as the original - f = new File(dirs[j].getDir(), fn); - } - // if the file exists, add to the DocuFileset - if (f.canRead()) { - fs.add(new DocuFile(f.getName(), fs, dirs[j])); - } else { - // try other file extensions - Iterator exts = FileOps.getImageExtensionIterator(); - while (exts.hasNext()) { - String s = (String) exts.next(); - f = new File(dirs[j].getDir(), fnx + s); - // if the file exists, add to the DocuFileset - if (f.canRead()) { - fs.add( - new DocuFile(f.getName(), fs, dirs[j])); - fext = s; - break; - } - } - } + DocuDirent f = null; + // what class of file do we have? + if (fc == FileOps.CLASS_IMAGE) { + // image file + f = new ImageFileset(dirs, fl[i], scalext); + } else if (fc == FileOps.CLASS_TEXT) { + // text file + f = new TextFile(fl[i]); } - // add the fileset to our list - list.add(fs); - fs.setParent(this); + // add the file to our list + list[fc].add(f); + f.setParent(this); } } - dirMTime = dir.lastModified(); - isValid = true; - // read metadata as well - readMeta(); } + dirMTime = dir.lastModified(); + // read metadata as well + readMeta(); return isValid; - } /** Check to see if the directory has been modified and reread if necessary. @@ -275,23 +292,41 @@ * * @param fileMeta * @param relPath + * @param fc fileClass */ - public void readFileMeta(HashMap fileMeta, String relPath) { + protected void readFileMeta(HashMap fileMeta, String relPath) { if (list == null) { // there are no files return; } String path = (relPath != null) ? (relPath + "/") : ""; - // iterate through the list of files in this directory - for (Iterator i = list.iterator(); i.hasNext();) { - DocuFileset df = (DocuFileset) i.next(); - // prepend path to the filename - String fn = path + df.getName(); - // look up meta for this file and remove from dir - HashMap meta = (HashMap) fileMeta.remove(fn); - if (meta != null) { - // store meta in file - df.setFileMeta(meta); + // go through all file classes + for (int nc = 0; nc < list.length; nc++) { + int fc = cache.getFileClasses()[nc]; + if (list[fc] == null) { + continue; + } + // iterate through the list of files in this directory + for (Iterator i = list[fc].iterator(); i.hasNext();) { + DocuDirent f = (DocuDirent) i.next(); + // prepend path to the filename + String fn = path + f.getName(); + // look up meta for this file and remove from dir + HashMap meta = (HashMap) fileMeta.remove(fn); + if (meta != null) { + // store meta in file + f.setFileMeta(meta); + } + } + } + } + + protected void notifyChildMeta(HashMap childmeta) { + List children = cache.getChildren(this.dirName, true); + if (children.size() > 0) { + for (Iterator i = children.iterator(); i.hasNext();) { + // TODO: finish this! + //((DocuDirectory) i.next()).readFileMeta() } } } @@ -312,13 +347,27 @@ * its index. Returns -1 if the file cannot be found. * * @param fn filename + * @param fc file class * @return int index of file fn */ public int indexOf(String fn) { + int fc = FileOps.classForFilename(fn); + return indexOf(fn, fc); + } + + /** Searches for the file with the name fn and class fc. + * + * Searches the directory for the file with the name fn and returns + * its index. Returns -1 if the file cannot be found. + * + * @param fn filename + * @return int index of file fn + */ + public int indexOf(String fn, int fc) { // linear search -> worst performance - int n = list.size(); + int n = list[fc].size(); for (int i = 0; i < n; i++) { - DocuFileset fs = (DocuFileset) list.get(i); + ImageFileset fs = (ImageFileset) list[fc].get(i); if (fs.getName().equals(fn)) { return i; } @@ -326,18 +375,35 @@ return -1; } - /** Finds the DocuFileset with the name fn. + /** Finds the ImageFileset with the name fn. * - * Searches the directory for the DocuFileset with the name fn and returns + * Searches the directory for the ImageFileset with the name fn and returns * it. Returns null if the file cannot be found. * * @param fn filename - * @return DocuFileset + * @return ImageFileset */ - public DocuFileset find(String fn) { - int i = indexOf(fn); + public ImageFileset find(String fn) { + int fc = FileOps.classForFilename(fn); + int i = indexOf(fn, fc); if (i >= 0) { - return (DocuFileset) list.get(i); + return (ImageFileset) list[0].get(i); + } + return null; + } + + /** Finds the ImageFileset with the name fn and class fc. + * + * Searches the directory for the ImageFileset with the name fn and returns + * it. Returns null if the file cannot be found. + * + * @param fn filename + * @return ImageFileset + */ + public ImageFileset find(String fn, int fc) { + int i = indexOf(fn, fc); + if (i >= 0) { + return (ImageFileset) list[fc].get(i); } return null; } @@ -349,13 +415,22 @@ return dirName; } - /** + /** The directory is valid (exists on disk). + * * @return boolean */ public boolean isValid() { return isValid; } + /** The directory has been read from disk. + * + * @return + */ + public boolean isRead() { + return (dirMTime != 0); + } + /** * @return long */ diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/DocuDirent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/DocuDirent.java Tue Sep 16 18:32:00 2003 +0200 @@ -0,0 +1,136 @@ +/* DocuDirent.java -- Abstract directory entry in a DocuDirectory + + Digital Image Library servlet components + + Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + Please read license.txt for the full details. A copy of the GPL + may be found at http://www.gnu.org/copyleft/lgpl.html + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * Created on 15.09.2003 by casties + * + */ +package digilib.io; + +import java.io.File; +import java.util.HashMap; + +/** Abstract directory entry in a DocuDirectory. + * + * @author casties + * + */ +public abstract class DocuDirent { + + /** the file class of this file */ + protected static int fileClass = FileOps.CLASS_NONE; + /** HashMap with metadata */ + protected HashMap fileMeta = null; + /** Is the Metadata valid */ + protected boolean metaChecked = false; + /** the parent directory */ + protected Directory parent = null; + + /** Checks metadata and does something with it. + * + */ + public abstract void checkMeta(); + + /** + * gets the (default) File + * @return + */ + public abstract File getFile(); + + /** Reads meta-data for this Fileset if there is any. + * + */ + public void readMeta() { + if ((fileMeta != null) || (getFile() != null)) { + // there is already metadata or there is no file + return; + } + // metadata is in the file {filename}.meta + String fn = getFile().getAbsolutePath(); + File mf = new File(fn + ".meta"); + if (mf.canRead()) { + XMLMetaLoader ml = new XMLMetaLoader(); + try { + // read meta file + HashMap meta = ml.loadURL(mf.getAbsolutePath()); + if (meta == null) { + return; + } + fileMeta = (HashMap) meta.get(getName()); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + /** The name of the (hires) image file. + * + * @return + */ + public String getName() { + File f = getFile(); + return (f != null) ? f.getName() : null; + } + + /** Returns the parent DocuDirectory. + * + * @return DocuDirectory + */ + public Directory getParent() { + return parent; + } + + /** + * Sets the parent. + * @param parent The parent to set + */ + public void setParent(Directory parent) { + this.parent = parent; + } + + /** Returns the meta-data for this fileset. + * + * @return HashMap + */ + public HashMap getFileMeta() { + return fileMeta; + } + + /** + * Sets the fileMeta. + * @param fileMeta The fileMeta to set + */ + public void setFileMeta(HashMap fileMeta) { + this.fileMeta = fileMeta; + } + + /** + * @return + */ + public boolean isMetaChecked() { + return metaChecked; + } + + /** + * @return + */ + public static int getFileClass() { + return fileClass; + } + +} diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/DocuFile.java --- a/servlet/src/digilib/io/DocuFile.java Tue Sep 16 18:26:31 2003 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/* DocuFile.java -- digilib image file class. - - Digital Image Library servlet components - - Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - Please read license.txt for the full details. A copy of the GPL - may be found at http://www.gnu.org/copyleft/lgpl.html - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - * Created on 25.02.2003 - */ - -package digilib.io; - -import java.io.File; - -import digilib.image.ImageSize; - -/** - * @author casties - */ -public class DocuFile { - - // file object - private String filename = null; - // parent DocuFileset - private DocuFileset parent = null; - // parent directory - private Directory dir = null; - // mime file type - private String mimetype = null; - // image size in pixels - private ImageSize pixelSize = null; - - public DocuFile(String fn, DocuFileset parent, Directory dir) { - this.filename = fn; - this.parent = parent; - this.dir = dir; - } - - public DocuFile(String fn) { - File f = new File(fn); - this.dir = new Directory(f.getParentFile()); - this.filename = f.getName(); - } - - /** Returns the file name (without path). - * - * @return - */ - public String getName() { - return filename; - } - - - /** - * @return File - */ - public File getFile() { - File f = new File(dir.getDir(), filename); - return f; - } - - /** - * @return ImageSize - */ - public ImageSize getSize() { - return pixelSize; - } - - /** - * @return String - */ - public String getMimetype() { - return mimetype; - } - - /** - * Sets the imageSize. - * @param imageSize The imageSize to set - */ - public void setSize(ImageSize imageSize) { - this.pixelSize = imageSize; - } - - /** - * Sets the mimetype. - * @param mimetype The mimetype to set - */ - public void setMimetype(String mimetype) { - this.mimetype = mimetype; - } - - /** - * @return DocuFileset - */ - public DocuFileset getParent() { - return parent; - } - - /** - * Sets the parent. - * @param parent The parent to set - */ - public void setParent(DocuFileset parent) { - this.parent = parent; - } - - /** - * @return boolean - */ - public boolean isChecked() { - return (pixelSize != null); - } - -} diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/DocuFileset.java --- a/servlet/src/digilib/io/DocuFileset.java Tue Sep 16 18:26:31 2003 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,347 +0,0 @@ -/* DocuFileset -- digilib image file info class. - - Digital Image Library servlet components - - Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2 of the License, or (at your - option) any later version. - - Please read license.txt for the full details. A copy of the GPL - may be found at http://www.gnu.org/copyleft/lgpl.html - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - */ -package digilib.io; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.ListIterator; - -import digilib.image.DocuInfo; -import digilib.image.ImageSize; - -/** - * @author casties - */ -public class DocuFileset { - - // list of files (DocuFile) - private ArrayList list = null; - // metadata - private HashMap fileMeta = null; - // metadata has been checked - private boolean metaChecked = false; - // resolution (DPI) - private double resX = 0; - private double resY = 0; - // parent directory - private DocuDirectory parent = null; - - /* - * constructors - */ - - public DocuFileset(int initialCapacity) { - list = new ArrayList(initialCapacity); - } - - /* - * other stuff - */ - - /** Adds a DocuFile to this Fileset. - * - * The files should be added in the order of higher to lower resolutions. - * The first file is considered the hires "original". - * - * @param f file to add - * @return true (always) - */ - public boolean add(DocuFile f) { - f.setParent(this); - return list.add(f); - } - - /** The number of image files in this Fileset. - * - * @return number of image files - */ - public int size() { - return (list != null) ? list.size() : 0; - } - - /** Get the DocuFile at the index. - * - * @param index - * @return - */ - public DocuFile get(int index) { - return (DocuFile) list.get(index); - } - - /** Get the next smaller DocuFile than the given size. - * - * Returns the DocuFile from the set that has a width and height - * smaller or equal the given size. - * Returns null if there isn't any smaller image. - * Needs DocuInfo instance to checkFile(). - * - * @param size - * @param info - * @return - */ - public DocuFile getNextSmaller(ImageSize size, DocuInfo info) { - for (Iterator i = getHiresIterator(); i.hasNext();) { - DocuFile f = (DocuFile) i.next(); - try { - if (!f.isChecked()) { - info.checkFile(f); - } - if (f.getSize().isTotallySmallerThan(size)) { - return f; - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return null; - } - - /** Get the next bigger DocuFile than the given size. - * - * Returns the DocuFile from the set that has a width or height - * bigger or equal the given size. - * Returns null if there isn't any bigger image. - * Needs DocuInfo instance to checkFile(). - * - * @param size - * @param info - * @return - */ - public DocuFile getNextBigger(ImageSize size, DocuInfo info) { - for (ListIterator i = getLoresIterator(); i.hasPrevious();) { - DocuFile f = (DocuFile) i.previous(); - try { - if (!f.isChecked()) { - info.checkFile(f); - } - if (f.getSize().isBiggerThan(size)) { - return f; - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - return null; - } - - /** Get an Iterator for this Fileset starting at the highest resolution - * images. - * - * @return - */ - public ListIterator getHiresIterator() { - return list.listIterator(); - } - - /** Get an Iterator for this Fileset starting at the lowest resolution - * images. - * - * The Iterator starts at the last element, so you have to use it backwards - * with hasPrevious() and previous(). - * - * @return - */ - public ListIterator getLoresIterator() { - return list.listIterator(list.size()); - } - - /** Reads meta-data for this Fileset if there is any. - * - */ - public void readMeta() { - if ((fileMeta != null) || list.isEmpty()) { - // there is already metadata or there's no file - return; - } - // metadata is in the file {filename}.meta - String fn = ((DocuFile) list.get(0)).getFile().getAbsolutePath(); - File mf = new File(fn + ".meta"); - if (mf.canRead()) { - XMLMetaLoader ml = new XMLMetaLoader(); - try { - // read meta file - HashMap meta = ml.loadURL(mf.getAbsolutePath()); - if (meta == null) { - return; - } - fileMeta = (HashMap) meta.get(getName()); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - /** Checks metadata and sets resolution in resX and resY. - * - */ - public void checkMeta() { - if (metaChecked) { - return; - } - if (fileMeta == null) { - // try to read metadata file - readMeta(); - if (fileMeta == null) { - // try directory metadata - if (parent.getDirMeta() != null) { - fileMeta = parent.getDirMeta(); - } else { - // no metadata available - metaChecked = true; - return; - } - } - } - metaChecked = true; - String s; - double dpi = 0; - double dpix = 0; - double dpiy = 0; - double sizex = 0; - double sizey = 0; - double pixx = 0; - double pixy = 0; - // DPI is valid for X and Y - if (fileMeta.containsKey("original-dpi")) { - try { - dpi = Double.parseDouble((String) fileMeta.get("original-dpi")); - } catch (NumberFormatException e) { - } - if (dpi != 0) { - resX = dpi; - resY = dpi; - return; - } - } - // DPI-X and DPI-Y - if (fileMeta.containsKey("original-dpi-x") - && fileMeta.containsKey("original-dpi-y")) { - try { - dpix = - Double.parseDouble((String) fileMeta.get("original-dpi-x")); - dpiy = - Double.parseDouble((String) fileMeta.get("original-dpi-y")); - } catch (NumberFormatException e) { - } - if ((dpix != 0) && (dpiy != 0)) { - resX = dpix; - resY = dpiy; - return; - } - } - // SIZE-X and SIZE-Y and PIXEL-X and PIXEL-Y - if (fileMeta.containsKey("original-size-x") - && fileMeta.containsKey("original-size-y") - && fileMeta.containsKey("original-pixel-x") - && fileMeta.containsKey("original-pixel-y")) { - try { - sizex = - Double.parseDouble( - (String) fileMeta.get("original-size-x")); - sizey = - Double.parseDouble( - (String) fileMeta.get("original-size-y")); - pixx = - Double.parseDouble( - (String) fileMeta.get("original-pixel-x")); - pixy = - Double.parseDouble( - (String) fileMeta.get("original-pixel-y")); - } catch (NumberFormatException e) { - } - if ((sizex != 0) && (sizey != 0) && (pixx != 0) && (pixy != 0)) { - resX = pixx / (sizex * 100 / 2.54); - resY = pixy / (sizey * 100 / 2.54); - return; - } - } - } - - /** The name of the (hires) image file. - * - * @return - */ - public String getName() { - if (!list.isEmpty()) { - return ((DocuFile) list.get(0)).getName(); - } - return null; - } - - /** Returns the parent DocuDirectory. - * - * @return DocuDirectory - */ - public DocuDirectory getParent() { - return parent; - } - - /** - * Sets the parent. - * @param parent The parent to set - */ - public void setParent(DocuDirectory parent) { - this.parent = parent; - } - - /** Returns the meta-data for this fileset. - * - * @return HashMap - */ - public HashMap getFileMeta() { - return fileMeta; - } - - /** - * Sets the fileMeta. - * @param fileMeta The fileMeta to set - */ - public void setFileMeta(HashMap fileMeta) { - this.fileMeta = fileMeta; - } - - /** - * @return - */ - public boolean isMetaChecked() { - return metaChecked; - } - - /** - * @return - */ - public double getResX() { - return resX; - } - - /** - * @return - */ - public double getResY() { - return resY; - } - -} diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/FileOps.java --- a/servlet/src/digilib/io/FileOps.java Tue Sep 16 18:26:31 2003 +0200 +++ b/servlet/src/digilib/io/FileOps.java Tue Sep 16 18:32:00 2003 +0200 @@ -20,14 +20,18 @@ package digilib.io; -import java.io.*; -import java.util.*; +import java.io.File; +import java.io.FileFilter; +import java.util.Arrays; +import java.util.Iterator; +import java.util.StringTokenizer; -import digilib.*; +import digilib.Utils; public class FileOps { private Utils util = null; + public static String[] fileTypes = { "jpg", @@ -43,11 +47,28 @@ "tif", "image/tiff", "tiff", - "image/tiff" }; + "image/tiff", + "txt", + "text/plain", + "html", + "text/html", + "htm", + "text/html", + "xml", + "text/xml" }; - public static String[] fileExtensions = + public static String[] imageExtensions = { "jpg", "jpeg", "jp2", "png", "gif", "tif", "tiff" }; + public static String[] textExtensions = + { "txt", "html", "htm", "xml"}; + + public static final int CLASS_NONE = -1; + public static final int CLASS_IMAGE = 0; + public static final int CLASS_TEXT = 1; + public static final int NUM_CLASSES = 2; + + public FileOps() { util = new Utils(); } @@ -73,18 +94,43 @@ return null; } - public static Iterator getImageExtensionIterator() { - return Arrays.asList(fileExtensions).iterator(); + /** + * get the file class for the filename (by extension) + * @param fn + * @return + */ + public static int classForFilename(String fn) { + int n = imageExtensions.length; + for (int i = 0; i < n; i ++) { + if (fn.toLowerCase().endsWith(imageExtensions[i])) { + return CLASS_IMAGE; + } + } + n = textExtensions.length; + for (int i = 0; i < n; i ++) { + if (fn.toLowerCase().endsWith(textExtensions[i])) { + return CLASS_TEXT; + } + } + return CLASS_NONE; + } + public static Iterator getImageExtensionIterator() { + return Arrays.asList(imageExtensions).iterator(); + } + + public static Iterator getTextExtensionIterator() { + return Arrays.asList(textExtensions).iterator(); + } + /** * convert a string with a list of pathnames into an array of strings * using the system's path separator string */ public static String[] pathToArray(String paths) { // split list into directories - StringTokenizer dirs = - new StringTokenizer(paths, File.pathSeparator); + StringTokenizer dirs = new StringTokenizer(paths, File.pathSeparator); int n = dirs.countTokens(); if (n < 1) { return null; @@ -104,114 +150,46 @@ } /** - * get a filehandle for a file or directory name - * returns File number n if fn is directory (starts with 1) - */ - public File getFile(String fn, int n) throws FileOpException { - util.dprintln(4, "getFile (" + fn + ", " + n + ")"); - - File f = new File(fn); - // if fn is a file name then return file - if (f.isFile()) { - return f; - } - // if fn is a directory name then open directory - if (f.isDirectory()) { - File[] fl = f.listFiles(new ImageFileFilter()); - Arrays.sort(fl); - if ((n > 0) && (n <= fl.length)) { - return fl[n - 1]; - } - } - throw new FileOpException("Unable to find file: " + fn); - } - - /** - * get the number of files in a directory - * (almost the same as getFile) - * returns 0 in case of problems - */ - public int getNumFiles(String fn) throws FileOpException { - util.dprintln(4, "getNumFiles (" + fn + ")"); - - File f = new File(fn); - // if fn is a file name then return 1 - if (f.isFile()) { - return 1; - } - // if fn is a directory name then return the number of files - if (f.isDirectory()) { - return f.listFiles(new ImageFileFilter()).length; - } - // then fn must be something strange... - return 0; - } - - /** - * get a filehandle for a file or directory name out of a list - * dirs is a list of base directories, fn is the appended file/dirname - * searches dirs until fn exists (backwards if fwd is false) - * returns File number n if fn is directory (starts with 1) - */ - public File getFileVariant(String[] dirs, String fn, int n, boolean fwd) - throws FileOpException { - util.dprintln( - 4, - "getVariantFile (" + dirs + ", " + fn + ", " + n + ")"); - - File f = null; - int nvar = dirs.length; - - for (int i = 0; i < nvar; i++) { - try { - f = getFile(dirs[(fwd) ? i : (nvar - i - 1)] + fn, n); - } catch (FileOpException e) { - f = null; - } - if (f != null) { - return f; - } - } - throw new FileOpException("Unable to find file: " + fn); - } - - /** - * get the number of files in a directory - * (almost the same as getFileVariant) - * returns 0 in case of problems - */ - public int getNumFilesVariant(String[] dirs, String fn, boolean fwd) - throws FileOpException { - util.dprintln(4, "getNumFilesVariant (" + dirs + ", " + fn + ")"); - - int nf = 0; - int nvar = dirs.length; - - for (int i = 0; i < nvar; i++) { - try { - nf = getNumFiles(dirs[(fwd) ? i : (nvar - i - 1)] + fn); - } catch (FileOpException e) { - nf = 0; - } - if (nf > 0) { - return nf; - } - } - return 0; - } - - /** * FileFilter for image types (helper class for getFile) */ static class ImageFileFilter implements FileFilter { public boolean accept(File f) { if (f.isFile()) { - return (mimeForFile(f) != null); + return ((mimeForFile(f) != null)&&(mimeForFile(f).startsWith("image"))); } else { return false; } } } + /** + * FileFilter for text types (helper class for getFile) + */ + static class TextFileFilter implements FileFilter { + + public boolean accept(File f) { + if (f.isFile()) { + return ((mimeForFile(f) != null)&&(mimeForFile(f).startsWith("text"))); + } else { + return false; + } + } + } + + /** Factory for FileFilters (image or text). + * + * @param fileClass + * @return + */ + public static FileFilter filterForClass(int fileClass) { + if (fileClass == CLASS_IMAGE) { + return new ImageFileFilter(); + } + if (fileClass == CLASS_TEXT) { + return new TextFileFilter(); + } + return null; + } + } diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/ImageFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/ImageFile.java Tue Sep 16 18:32:00 2003 +0200 @@ -0,0 +1,128 @@ +/* ImageFile.java -- digilib image file class. + + Digital Image Library servlet components + + Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + Please read license.txt for the full details. A copy of the GPL + may be found at http://www.gnu.org/copyleft/lgpl.html + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + * Created on 25.02.2003 + */ + +package digilib.io; + +import java.io.File; + +import digilib.image.ImageSize; + +/** + * @author casties + */ +public class ImageFile { + + // file name + private String filename = null; + // parent ImageFileset + private ImageFileset parent = null; + // parent directory + private Directory dir = null; + // mime file type + private String mimetype = null; + // image size in pixels + private ImageSize pixelSize = null; + + public ImageFile(String fn, ImageFileset parent, Directory dir) { + this.filename = fn; + this.parent = parent; + this.dir = dir; + } + + public ImageFile(String fn) { + File f = new File(fn); + this.dir = new Directory(f.getParentFile()); + this.filename = f.getName(); + } + + /** Returns the file name (without path). + * + * @return + */ + public String getName() { + return filename; + } + + + /** + * @return File + */ + public File getFile() { + if (dir == null) { + return null; + } + File f = new File(dir.getDir(), filename); + return f; + } + + /** + * @return ImageSize + */ + public ImageSize getSize() { + return pixelSize; + } + + /** + * @return String + */ + public String getMimetype() { + return mimetype; + } + + /** + * Sets the imageSize. + * @param imageSize The imageSize to set + */ + public void setSize(ImageSize imageSize) { + this.pixelSize = imageSize; + } + + /** + * Sets the mimetype. + * @param mimetype The mimetype to set + */ + public void setMimetype(String mimetype) { + this.mimetype = mimetype; + } + + /** + * @return ImageFileset + */ + public ImageFileset getParent() { + return parent; + } + + /** + * Sets the parent. + * @param parent The parent to set + */ + public void setParent(ImageFileset parent) { + this.parent = parent; + } + + /** + * @return boolean + */ + public boolean isChecked() { + return (pixelSize != null); + } + +} diff -r e9a81ac446cb -r e743b853efca servlet/src/digilib/io/ImageFileset.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servlet/src/digilib/io/ImageFileset.java Tue Sep 16 18:32:00 2003 +0200 @@ -0,0 +1,333 @@ +/* ImageFileset -- digilib image file info class. + + Digital Image Library servlet components + + Copyright (C) 2003 Robert Casties (robcast@mail.berlios.de) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + Please read license.txt for the full details. A copy of the GPL + may be found at http://www.gnu.org/copyleft/lgpl.html + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + */ +package digilib.io; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.ListIterator; + +import digilib.image.DocuInfo; +import digilib.image.ImageSize; + +/** + * @author casties + */ +public class ImageFileset extends DocuDirent { + + // this is an image file + protected static int fileClass = FileOps.CLASS_IMAGE; + + // list of files (ImageFile) + private ArrayList list = null; + // resolution (DPI) + private double resX = 0; + private double resY = 0; + + /** Creator for empty fileset with size for file list. + * + * @param initialCapacity + */ + public ImageFileset(int initialCapacity) { + list = new ArrayList(initialCapacity); + } + + /** Creator with a file and base directories. + * + * Reads the file and fills the + * fileset with corresponding files from the other base directories. + * First entry in dirs is the parent of this fileset. + * + * @see fill + * + * @param dirs array of base directories + * @param file first file to read + * @param scalext extension for scaled images + */ + public ImageFileset(Directory[] dirs, File file, String scalext) { + int nb = dirs.length; + list = new ArrayList(nb); + parent = dirs[0]; + fill(dirs, file, scalext); + } + + /** Adds a ImageFile to this Fileset. + * + * The files should be added in the order of higher to lower resolutions. + * The first file is considered the hires "original". + * + * @param f file to add + * @return true (always) + */ + public boolean add(ImageFile f) { + f.setParent(this); + return list.add(f); + } + + /** The number of image files in this Fileset. + * + * @return number of image files + */ + public int size() { + return (list != null) ? list.size() : 0; + } + + /** Gets the default File. + * + */ + public File getFile() { + return (list != null) ? ((ImageFile) list.get(0)).getFile() : null; + } + + /** Get the ImageFile at the index. + * + * @param index + * @return + */ + public ImageFile get(int index) { + return (ImageFile) list.get(index); + } + + /** Get the next smaller ImageFile than the given size. + * + * Returns the ImageFile from the set that has a width and height + * smaller or equal the given size. + * Returns null if there isn't any smaller image. + * Needs DocuInfo instance to checkFile(). + * + * @param size + * @param info + * @return + */ + public ImageFile getNextSmaller(ImageSize size, DocuInfo info) { + for (Iterator i = getHiresIterator(); i.hasNext();) { + ImageFile f = (ImageFile) i.next(); + try { + if (!f.isChecked()) { + info.checkFile(f); + } + if (f.getSize().isTotallySmallerThan(size)) { + return f; + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return null; + } + + /** Get the next bigger ImageFile than the given size. + * + * Returns the ImageFile from the set that has a width or height + * bigger or equal the given size. + * Returns null if there isn't any bigger image. + * Needs DocuInfo instance to checkFile(). + * + * @param size + * @param info + * @return + */ + public ImageFile getNextBigger(ImageSize size, DocuInfo info) { + for (ListIterator i = getLoresIterator(); i.hasPrevious();) { + ImageFile f = (ImageFile) i.previous(); + try { + if (!f.isChecked()) { + info.checkFile(f); + } + if (f.getSize().isBiggerThan(size)) { + return f; + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return null; + } + + /** Get an Iterator for this Fileset starting at the highest resolution + * images. + * + * @return + */ + public ListIterator getHiresIterator() { + return list.listIterator(); + } + + /** Get an Iterator for this Fileset starting at the lowest resolution + * images. + * + * The Iterator starts at the last element, so you have to use it backwards + * with hasPrevious() and previous(). + * + * @return + */ + public ListIterator getLoresIterator() { + return list.listIterator(list.size()); + } + + /** Fill the ImageFileset with files from different base directories. + * + * @param dirs list of base directories + * @param fl file (from first base dir) + * @param scalext first extension to try in other base dirs + */ + void fill(Directory[] dirs, File fl, String scalext) { + int nb = dirs.length; + String fn = fl.getName(); + String fnx = fn.substring(0, fn.lastIndexOf('.') + 1); + // add the first ImageFile to the ImageFileset + add(new ImageFile(fn, this, parent)); + // iterate the remaining base directories + for (int j = 1; j < nb; j++) { + if (dirs[j] == null) { + continue; + } + File f; + if (scalext != null) { + // use the last extension + f = new File(dirs[j].getDir(), fnx + scalext); + } else { + // try the same filename as the original + f = new File(dirs[j].getDir(), fn); + } + // if the file exists, add to the ImageFileset + if (f.canRead()) { + add(new ImageFile(f.getName(), this, dirs[j])); + } else { + // try other file extensions + Iterator exts = FileOps.getImageExtensionIterator(); + while (exts.hasNext()) { + String s = (String) exts.next(); + f = new File(dirs[j].getDir(), fnx + s); + // if the file exists, add to the ImageFileset + if (f.canRead()) { + add(new ImageFile(f.getName(), this, dirs[j])); + scalext = s; + break; + } + } + } + } + } + + /** Checks metadata and sets resolution in resX and resY. + * + */ + public void checkMeta() { + if (metaChecked) { + return; + } + if (fileMeta == null) { + // try to read metadata file + readMeta(); + if (fileMeta == null) { + // try directory metadata + if (((DocuDirectory) parent).getDirMeta() != null) { + fileMeta = ((DocuDirectory) parent).getDirMeta(); + } else { + // no metadata available + metaChecked = true; + return; + } + } + } + metaChecked = true; + String s; + double dpi = 0; + double dpix = 0; + double dpiy = 0; + double sizex = 0; + double sizey = 0; + double pixx = 0; + double pixy = 0; + // DPI is valid for X and Y + if (fileMeta.containsKey("original-dpi")) { + try { + dpi = Double.parseDouble((String) fileMeta.get("original-dpi")); + } catch (NumberFormatException e) { + } + if (dpi != 0) { + resX = dpi; + resY = dpi; + return; + } + } + // DPI-X and DPI-Y + if (fileMeta.containsKey("original-dpi-x") + && fileMeta.containsKey("original-dpi-y")) { + try { + dpix = + Double.parseDouble((String) fileMeta.get("original-dpi-x")); + dpiy = + Double.parseDouble((String) fileMeta.get("original-dpi-y")); + } catch (NumberFormatException e) { + } + if ((dpix != 0) && (dpiy != 0)) { + resX = dpix; + resY = dpiy; + return; + } + } + // SIZE-X and SIZE-Y and PIXEL-X and PIXEL-Y + if (fileMeta.containsKey("original-size-x") + && fileMeta.containsKey("original-size-y") + && fileMeta.containsKey("original-pixel-x") + && fileMeta.containsKey("original-pixel-y")) { + try { + sizex = + Double.parseDouble( + (String) fileMeta.get("original-size-x")); + sizey = + Double.parseDouble( + (String) fileMeta.get("original-size-y")); + pixx = + Double.parseDouble( + (String) fileMeta.get("original-pixel-x")); + pixy = + Double.parseDouble( + (String) fileMeta.get("original-pixel-y")); + } catch (NumberFormatException e) { + } + if ((sizex != 0) && (sizey != 0) && (pixx != 0) && (pixy != 0)) { + resX = pixx / (sizex * 100 / 2.54); + resY = pixy / (sizey * 100 / 2.54); + return; + } + } + } + + /** + * @return + */ + public double getResX() { + return resX; + } + + /** + * @return + */ + public double getResY() { + return resY; + } + +}