Mercurial > hg > digilib-old
comparison servlet/src/digilib/io/DocuDirectory.java @ 569:1f666c2b4578
Merge with PDF branch
8beefd1142b28ca9b2433205e7eea82a517bb215
author | robcast |
---|---|
date | Tue, 21 Dec 2010 09:52:16 +0100 |
parents | 686086d6e6d6 |
children | 6e8488acb499 790cbfb58b52 |
comparison
equal
deleted
inserted
replaced
535:9936604d466e | 569:1f666c2b4578 |
---|---|
23 | 23 |
24 import java.io.File; | 24 import java.io.File; |
25 import java.io.IOException; | 25 import java.io.IOException; |
26 import java.util.ArrayList; | 26 import java.util.ArrayList; |
27 import java.util.Collections; | 27 import java.util.Collections; |
28 import java.util.Iterator; | |
29 import java.util.List; | 28 import java.util.List; |
30 import java.util.Map; | 29 import java.util.Map; |
31 | 30 |
32 import org.xml.sax.SAXException; | 31 import org.xml.sax.SAXException; |
32 | |
33 import digilib.io.FileOps.FileClass; | |
33 | 34 |
34 /** | 35 /** |
35 * @author casties | 36 * @author casties |
36 */ | 37 */ |
37 public class DocuDirectory extends Directory { | 38 public class DocuDirectory extends Directory { |
38 | 39 |
39 /** list of files (DocuDirent) */ | 40 /** list of files (DocuDirent) */ |
40 private ArrayList[] list = null; | 41 private List<List<DocuDirent>> list = null; |
41 | 42 |
42 /** directory object is valid (exists on disk) */ | 43 /** directory object is valid (exists on disk) */ |
43 private boolean isValid = false; | 44 private boolean isValid = false; |
44 | 45 |
45 /** reference of the parent DocuDirCache */ | 46 /** reference of the parent DocuDirCache */ |
47 | 48 |
48 /** directory name (digilib canonical form) */ | 49 /** directory name (digilib canonical form) */ |
49 private String dirName = null; | 50 private String dirName = null; |
50 | 51 |
51 /** directory metadata */ | 52 /** directory metadata */ |
52 private Map dirMeta = null; | 53 private MetadataMap dirMeta = null; |
53 | 54 |
54 /** state of metadata is valid */ | 55 /** state of metadata is valid */ |
55 private boolean metaChecked = false; | 56 private boolean metaChecked = false; |
56 | 57 |
57 /** unresolved file metadata */ | 58 /** unresolved file metadata */ |
58 private Map unresolvedFileMeta = null; | 59 private Map<String, MetadataMap> unresolvedFileMeta = null; |
59 | 60 |
60 /** time of last access of this object (not the filesystem) */ | 61 /** time of last access of this object (not the filesystem) */ |
61 private long objectATime = 0; | 62 private long objectATime = 0; |
62 | 63 |
63 /** time directory was last modified on the file system */ | 64 /** time directory was last modified on the file system */ |
87 * Sets and checks the dir object. | 88 * Sets and checks the dir object. |
88 * | 89 * |
89 */ | 90 */ |
90 protected void initDir() { | 91 protected void initDir() { |
91 String baseDirName = cache.getBaseDirNames()[0]; | 92 String baseDirName = cache.getBaseDirNames()[0]; |
92 // clear directory first | 93 // clear directory list |
93 list = new ArrayList[FileOps.NUM_CLASSES]; | 94 FileClass[] fcs = FileClass.values(); |
95 list = new ArrayList<List<DocuDirent>>(fcs.length); | |
96 // create empty list for all classes | |
97 for (@SuppressWarnings("unused") FileClass fc: fcs) { | |
98 list.add(null); | |
99 } | |
94 isValid = false; | 100 isValid = false; |
95 dirMTime = 0; | 101 dirMTime = 0; |
96 // the first directory has to exist | 102 // the first directory has to exist |
97 dir = new File(baseDirName, dirName); | 103 dir = new File(baseDirName, dirName); |
98 } | 104 } |
100 /** | 106 /** |
101 * number of DocuFiles in this directory. | 107 * number of DocuFiles in this directory. |
102 * | 108 * |
103 */ | 109 */ |
104 public int size() { | 110 public int size() { |
105 return ((list != null) && (list[0] != null)) ? list[0].size() : 0; | 111 return ((list != null) && (list.get(0) != null)) ? list.get(0).size() : 0; |
106 } | 112 } |
107 | 113 |
108 /** | 114 /** |
109 * number of files of this class in this directory. | 115 * number of files of this class in this directory. |
110 * | 116 * |
111 * @param fc | 117 * @param fc |
112 * fileClass | 118 * fileClass |
113 */ | 119 */ |
114 public int size(int fc) { | 120 public int size(FileClass fc) { |
115 return ((list != null) && (list[fc] != null)) ? list[fc].size() : 0; | 121 return ((list != null) && (list.get(fc.ordinal()) != null)) ? list.get(fc.ordinal()).size() : 0; |
116 } | 122 } |
117 | 123 |
118 /** | 124 /** |
119 * Returns the ImageFile at the index. | 125 * Returns the ImageFileSet at the index. |
120 * | 126 * |
121 * @param index | 127 * @param index |
122 * @return | 128 * @return |
123 */ | 129 */ |
124 public ImageFileset get(int index) { | 130 public ImageFileset get(int index) { |
125 if ((list == null) || (list[0] == null) || (index >= list[0].size())) { | 131 if ((list == null) || (list.get(0) == null) || (index >= list.get(0).size())) { |
126 return null; | 132 return null; |
127 } | 133 } |
128 return (ImageFileset) list[0].get(index); | 134 return (ImageFileset) list.get(0).get(index); |
129 } | 135 } |
130 | 136 |
131 /** | 137 /** |
132 * Returns the file of the class at the index. | 138 * Returns the file of the class at the index. |
133 * | 139 * |
134 * @param index | 140 * @param index |
135 * @param fc | 141 * @param fc |
136 * fileClass | 142 * fileClass |
137 * @return | 143 * @return |
138 */ | 144 */ |
139 public DocuDirent get(int index, int fc) { | 145 public DocuDirent get(int index, FileClass fc) { |
140 if ((list == null) || (list[fc] == null) || (index >= list[fc].size())) { | 146 if ((list == null) || (list.get(fc.ordinal()) == null) || (index >= list.get(fc.ordinal()).size())) { |
141 return null; | 147 return null; |
142 } | 148 } |
143 return (DocuDirent) list[fc].get(index); | 149 return (DocuDirent) list.get(fc.ordinal()).get(index); |
144 } | 150 } |
145 | 151 |
146 /** | 152 /** |
147 * Checks if the directory exists on the filesystem. | 153 * Checks if the directory exists on the filesystem. |
148 * | 154 * |
178 /* | 184 /* |
179 * using ReadableFileFilter is safer (we won't get directories with file | 185 * using ReadableFileFilter is safer (we won't get directories with file |
180 * extensions) but slower. | 186 * extensions) but slower. |
181 */ | 187 */ |
182 File[] allFiles = null; | 188 File[] allFiles = null; |
183 if (cache.safeDirIndex) { | 189 // allFiles = dir.listFiles(new FileOps.ReadableFileFilter()); |
184 allFiles = dir.listFiles(new FileOps.ReadableFileFilter()); | 190 allFiles = dir.listFiles(); |
185 } else { | |
186 allFiles = dir.listFiles(); | |
187 } | |
188 //logger.debug(" done"); | 191 //logger.debug(" done"); |
189 if (allFiles == null) { | 192 if (allFiles == null) { |
190 // not a directory | 193 // not a directory |
191 return false; | 194 return false; |
192 } | 195 } |
208 //logger.debug(" done"); | 211 //logger.debug(" done"); |
209 } | 212 } |
210 } | 213 } |
211 | 214 |
212 // go through all file classes | 215 // go through all file classes |
213 for (int classIdx = 0; classIdx < FileOps.NUM_CLASSES; classIdx++) { | 216 //for (int classIdx = 0; classIdx < FileOps.NUM_CLASSES; classIdx++) { |
214 int fileClass = cache.getFileClasses()[classIdx]; | 217 for (FileClass fileClass: cache.getFileClasses()) { |
215 //logger.debug("filtering directory "+dir.getPath()+" for class | 218 //fileClass = cache.getFileClasses()[classIdx]; |
216 // "+fc); | |
217 File[] fileList = FileOps.listFiles(allFiles, FileOps | 219 File[] fileList = FileOps.listFiles(allFiles, FileOps |
218 .filterForClass(fileClass)); | 220 .filterForClass(fileClass)); |
219 //logger.debug(" done"); | 221 //logger.debug(" done"); |
220 // number of files in the directory | 222 // number of files in the directory |
221 int numFiles = fileList.length; | 223 int numFiles = fileList.length; |
222 if (numFiles > 0) { | 224 if (numFiles > 0) { |
223 // create new list | 225 // create new list |
224 list[fileClass] = new ArrayList(numFiles); | 226 list.set(fileClass.ordinal(), new ArrayList<DocuDirent>(numFiles)); |
225 // sort the file names alphabetically and iterate the list | 227 // sort the file names alphabetically and iterate the list |
226 // Arrays.sort(fileList); // not needed <hertzhaft> | 228 // Arrays.sort(fileList); // not needed <hertzhaft> |
227 Map hints = FileOps.newHints(FileOps.HINT_BASEDIRS, dirs); | 229 Map<Integer, Object> hints = FileOps.newHints(FileOps.HINT_BASEDIRS, dirs); |
228 hints.put(FileOps.HINT_FILEEXT, scalext); | 230 hints.put(FileOps.HINT_FILEEXT, scalext); |
229 for (int i = 0; i < numFiles; i++) { | 231 for (int i = 0; i < numFiles; i++) { |
230 DocuDirent f = FileOps.fileForClass(fileClass, fileList[i], | 232 DocuDirent f = FileOps.fileForClass(fileClass, fileList[i], |
231 hints); | 233 hints); |
232 // add the file to our list | 234 // add the file to our list |
233 // logger.debug(f.getName()); | 235 // logger.debug(f.getName()); |
234 | 236 |
235 list[fileClass].add(f); | 237 list.get(fileClass.ordinal()).add(f); |
236 f.setParent(this); | 238 f.setParent(this); |
237 } | 239 } |
238 // we sort the ArrayList, not the Array, for binarySearch to work | 240 // we sort the inner ArrayList (the list of files not the list of file types) |
239 Collections.sort(list[fileClass]); | 241 // for binarySearch to work (DocuDirent's natural sort order is by filename) |
242 Collections.sort(list.get(fileClass.ordinal())); | |
240 } | 243 } |
241 } | 244 } |
242 // clear the scaled directories | 245 // clear the scaled directories |
243 for (int j = 1; j < nb; j++) { | 246 for (int j = 1; j < nb; j++) { |
244 if (dirs[j] != null) { | 247 if (dirs[j] != null) { |
280 File mf = new File(dir, "index.meta"); | 283 File mf = new File(dir, "index.meta"); |
281 if (mf.canRead()) { | 284 if (mf.canRead()) { |
282 XMLMetaLoader ml = new XMLMetaLoader(); | 285 XMLMetaLoader ml = new XMLMetaLoader(); |
283 try { | 286 try { |
284 // read directory meta file | 287 // read directory meta file |
285 Map fileMeta = ml.loadURL(mf.getAbsolutePath()); | 288 Map<String, MetadataMap> fileMeta = ml.loadURL(mf.getAbsolutePath()); |
286 if (fileMeta == null) { | 289 if (fileMeta == null) { |
287 return; | 290 return; |
288 } | 291 } |
289 // meta for the directory itself is in the "" bin | 292 // meta for the directory itself is in the "" bin |
290 dirMeta = (Map) fileMeta.remove(""); | 293 dirMeta = fileMeta.remove(""); |
291 // read meta for files in this directory | 294 // read meta for files in this directory |
292 readFileMeta(fileMeta, null); | 295 readFileMeta(fileMeta, null); |
293 // is there meta for other files left? | 296 // is there meta for other files left? |
294 if (fileMeta.size() > 0) { | 297 if (fileMeta.size() > 0) { |
295 unresolvedFileMeta = fileMeta; | 298 unresolvedFileMeta = fileMeta; |
332 * @param fileMeta | 335 * @param fileMeta |
333 * @param relPath | 336 * @param relPath |
334 * @param fc | 337 * @param fc |
335 * fileClass | 338 * fileClass |
336 */ | 339 */ |
337 protected void readFileMeta(Map fileMeta, String relPath) { | 340 protected void readFileMeta(Map<String,MetadataMap> fileMeta, String relPath) { |
338 if (list == null) { | 341 if (list == null) { |
339 // there are no files | 342 // there are no files |
340 return; | 343 return; |
341 } | 344 } |
342 String path = (relPath != null) ? (relPath + "/") : ""; | 345 String path = (relPath != null) ? (relPath + "/") : ""; |
343 // go through all file classes | 346 // go through all file classes |
344 for (int nc = 0; nc < list.length; nc++) { | 347 for (FileClass fc: FileClass.values()) { |
345 int fc = cache.getFileClasses()[nc]; | 348 if (list.get(fc.ordinal()) == null) { |
346 if (list[fc] == null) { | |
347 continue; | 349 continue; |
348 } | 350 } |
349 // iterate through the list of files in this directory | 351 // iterate through the list of files in this directory |
350 for (Iterator i = list[fc].iterator(); i.hasNext();) { | 352 for (DocuDirent f: list.get(fc.ordinal())) { |
351 DocuDirent f = (DocuDirent) i.next(); | |
352 // prepend path to the filename | 353 // prepend path to the filename |
353 String fn = path + f.getName(); | 354 String fn = path + f.getName(); |
354 // look up meta for this file and remove from dir | 355 // look up meta for this file and remove from dir |
355 Map meta = (Map) fileMeta.remove(fn); | 356 MetadataMap meta = fileMeta.remove(fn); |
356 if (meta != null) { | 357 if (meta != null) { |
357 // store meta in file | 358 // store meta in file |
358 f.setFileMeta(meta); | 359 f.setFileMeta(meta); |
359 } | 360 } |
360 } | 361 } |
361 } | 362 } |
362 } | 363 } |
363 | 364 |
364 protected void notifyChildMeta(Map childmeta) { | 365 protected void notifyChildMeta(MetadataMap childmeta) { |
365 List children = cache.getChildren(this.dirName, true); | 366 List<DocuDirectory> children = cache.getChildren(this.dirName, true); |
366 if (children.size() > 0) { | 367 if (children.size() > 0) { |
367 for (Iterator i = children.iterator(); i.hasNext();) { | 368 /*for (DocuDirectory d: children) { |
368 // TODO: finish this! | 369 // TODO: finish this! |
369 //((DocuDirectory) i.next()).readFileMeta() | 370 //((DocuDirectory) i.next()).readFileMeta() |
370 } | 371 }*/ |
371 } | 372 } |
372 } | 373 } |
373 | 374 |
374 /** | 375 /** |
375 * Update access time. | 376 * Update access time. |
393 * @param fc | 394 * @param fc |
394 * file class | 395 * file class |
395 * @return int index of file <code>fn</code> | 396 * @return int index of file <code>fn</code> |
396 */ | 397 */ |
397 public int indexOf(String fn) { | 398 public int indexOf(String fn) { |
398 int fc = FileOps.classForFilename(fn); | 399 FileClass fc = FileOps.classForFilename(fn); |
399 return indexOf(fn, fc); | 400 return indexOf(fn, fc); |
400 } | 401 } |
401 | 402 |
402 /** | 403 /** |
403 * Searches for the file with the name <code>fn</code> and class fc. | 404 * Searches for the file with the name <code>fn</code> and class fc. |
407 * | 408 * |
408 * @param fn | 409 * @param fn |
409 * filename | 410 * filename |
410 * @return int index of file <code>fn</code> | 411 * @return int index of file <code>fn</code> |
411 */ | 412 */ |
412 public int indexOf(String fn, int fc) { | 413 public int indexOf(String fn, FileClass fc) { |
413 if (!isRead()) { | 414 if (!isRead()) { |
414 // read directory now | 415 // read directory now |
415 if (!readDir()) { | 416 if (!readDir()) { |
416 return -1; | 417 return -1; |
417 } | 418 } |
418 } | 419 } |
419 List fileList = list[fc]; | 420 List<DocuDirent> fileList = list.get(fc.ordinal()); |
420 // empty directory? | 421 // empty directory? |
421 if (fileList == null) { | 422 if (fileList == null) { |
422 return -1; | 423 return -1; |
423 } | 424 } |
424 | 425 |
425 // search for exact match | 426 // search for exact match (DocuDirent does compareTo<String>) |
426 // OBS: fileList needs to be sorted first (see )! <hertzhaft> | 427 // OBS: fileList needs to be sorted first (see )! <hertzhaft> |
427 int idx = Collections.binarySearch(fileList, fn); | 428 int idx = Collections.binarySearch(fileList, fn); |
428 if (idx >= 0) { | 429 if (idx >= 0) { |
429 return idx; | 430 return idx; |
430 } else { | 431 } else { |
431 logger.debug(fn + " not found by binarysearch"); | 432 logger.debug(fn + " not found by binarysearch"); |
432 // try closest matches without extension | 433 // try closest matches without extension |
433 idx = -idx - 1; | 434 idx = -idx - 1; |
434 if ((idx < fileList.size()) | 435 if ((idx < fileList.size()) |
435 && isBaseInList(fileList, idx, fn)) { | 436 && isBasenameInList(fileList, idx, fn)) { |
436 // idx matches | 437 // idx matches |
437 return idx; | 438 return idx; |
438 } else if ((idx > 0) | 439 } else if ((idx > 0) |
439 && isBaseInList(fileList, idx-1, fn)) { | 440 && isBasenameInList(fileList, idx-1, fn)) { |
440 // idx-1 matches | 441 // idx-1 matches |
441 return idx - 1; | 442 return idx - 1; |
442 } else if ((idx + 1 < fileList.size()) | 443 } else if ((idx + 1 < fileList.size()) |
443 && isBaseInList(fileList, idx+1, fn)) { | 444 && isBasenameInList(fileList, idx+1, fn)) { |
444 // idx+1 matches | 445 // idx+1 matches |
445 return idx + 1; | 446 return idx + 1; |
446 } | 447 } |
447 | 448 |
448 } | 449 } |
449 return -1; | 450 return -1; |
450 } | 451 } |
451 | 452 |
452 private boolean isBaseInList(List fl, int idx, String fn) { | 453 private boolean isBasenameInList(List<DocuDirent> fl, int idx, String fn) { |
453 String dfn = FileOps.basename(((DocuDirent) fl.get(idx)) | 454 String dfn = FileOps.basename((fl.get(idx)) |
454 .getName()); | 455 .getName()); |
455 return (dfn.equals(fn)||dfn.equals(FileOps.basename(fn))); | 456 return (dfn.equals(fn)||dfn.equals(FileOps.basename(fn))); |
456 } | 457 } |
457 | 458 |
458 | 459 |
465 * @param fn | 466 * @param fn |
466 * filename | 467 * filename |
467 * @return DocuDirent | 468 * @return DocuDirent |
468 */ | 469 */ |
469 public DocuDirent find(String fn) { | 470 public DocuDirent find(String fn) { |
470 int fc = FileOps.classForFilename(fn); | 471 FileClass fc = FileOps.classForFilename(fn); |
471 int i = indexOf(fn, fc); | 472 int i = indexOf(fn, fc); |
472 if (i >= 0) { | 473 if (i >= 0) { |
473 return (DocuDirent) list[0].get(i); | 474 return (DocuDirent) list.get(0).get(i); |
474 } | 475 } |
475 return null; | 476 return null; |
476 } | 477 } |
477 | 478 |
478 /** | 479 /** |
484 * | 485 * |
485 * @param fn | 486 * @param fn |
486 * filename | 487 * filename |
487 * @return DocuDirent | 488 * @return DocuDirent |
488 */ | 489 */ |
489 public DocuDirent find(String fn, int fc) { | 490 public DocuDirent find(String fn, FileClass fc) { |
490 int i = indexOf(fn, fc); | 491 int i = indexOf(fn, fc); |
491 if (i >= 0) { | 492 if (i >= 0) { |
492 return (DocuDirent) list[fc].get(i); | 493 return (DocuDirent) list.get(fc.ordinal()).get(i); |
493 } | 494 } |
494 return null; | 495 return null; |
495 } | 496 } |
496 | 497 |
497 /** | 498 /** |
529 } | 530 } |
530 | 531 |
531 /** | 532 /** |
532 * @return Hashtable | 533 * @return Hashtable |
533 */ | 534 */ |
534 public Map getDirMeta() { | 535 public MetadataMap getDirMeta() { |
535 return dirMeta; | 536 return dirMeta; |
536 } | 537 } |
537 | 538 |
538 /** | 539 /** |
539 * Checks metadata | 540 * Checks metadata |
558 * Sets the dirMeta. | 559 * Sets the dirMeta. |
559 * | 560 * |
560 * @param dirMeta | 561 * @param dirMeta |
561 * The dirMeta to set | 562 * The dirMeta to set |
562 */ | 563 */ |
563 public void setDirMeta(Map dirMeta) { | 564 public void setDirMeta(MetadataMap dirMeta) { |
564 this.dirMeta = dirMeta; | 565 this.dirMeta = dirMeta; |
565 } | 566 } |
566 | 567 |
567 public boolean hasUnresolvedFileMeta() { | 568 public boolean hasUnresolvedFileMeta() { |
568 return (this.unresolvedFileMeta != null); | 569 return (this.unresolvedFileMeta != null); |