001 package ps6; 002 003 import ps4.StreetSegment; 004 005 import java.io.*; 006 import java.util.*; 007 008 /** 009 * A StreetSegReader reads StreetSegments from a set of Tiger Databases. 010 * 011 * <p> Tiger Databases are produced and maintained by the <a 012 * href="http://tiger.census.gov/">U.S. Census Bureau</a>. 013 * 014 * <p> Tiger Databases are distributed in zip-compressed files. To 015 * allow for the loading of an arbitrary number of these databases, 016 * one creates each StreetSegReader with a source directory argument, 017 * which will then be searched for Tiger Database files when 018 * <code>streetSegments()</code> is called. The subdirectories of the 019 * argument directory are not searched recursively for Tiger files as 020 * well; only the immediate contents of this.sourceDirectory will be 021 * considered as potential Tiger files. 022 * 023 * <p> StreetSegReader is only specified to operate correctly with 024 * directories that contain no <tt>.zip</tt> files besides the Tiger 025 * Databases. Files with other extensions (such as <tt>.pdf</tt>) 026 * will not affect the operation of StreetSegReader, but no other 027 * <tt>.zip</tt> files should be kept in the source directory for a 028 * StreetSegReader. 029 * 030 * @specfield sourceDirectory : String // name of directory where Tiger files are located 031 * @specfield streetSegs : Collection // contents of the database; each element is a StreetSegment 032 * 033 */ 034 public class StreetSegReader 035 { 036 037 private File sourceDirectory; 038 039 /** 040 * @effects Constructs a StreetSegReader where sourceDirectory 041 * contains the Tiger Database files. 042 * 043 * @throws InvalidSourceException if sourceDirectory is not valid 044 * database (most directories, even empty ones, count as valid). 045 **/ 046 public StreetSegReader(String sourceDirectory) 047 throws InvalidSourceException 048 { 049 try { 050 051 File source = null; 052 if (sourceDirectory != null) { 053 source = new File(sourceDirectory); 054 } 055 reader = new StreetSegReader(source); 056 057 } catch (StreetSegReader.InvalidSourceException e) { 058 throw new InvalidSourceException("" + e.getMessage()); 059 } 060 } 061 062 private StreetSegReader (File sourceDirFile) 063 throws InvalidSourceException{ 064 065 if (sourceDirFile == null) { 066 throw new InvalidSourceException("DIRECTORY for StreetSegReader constructor cannot be null"); 067 } 068 069 if (!sourceDirFile.isDirectory()) { 070 throw new InvalidSourceException(sourceDirFile + " is not a valid DIRECTORY for StreetSegReader"); 071 } 072 073 // java.io.File is immutable 074 this.sourceDirectory = sourceDirFile; 075 } 076 077 // our adaptee 078 private StreetSegReader reader = null;; 079 080 081 private static final FilenameFilter zipFileFilter = new ZipFilter(); 082 083 /** Filter class for only getting .zip files */ 084 private static class ZipFilter 085 implements FilenameFilter { 086 public boolean accept(File d, String name) { 087 return (name.toLowerCase().endsWith("zip")); 088 } 089 } 090 091 092 /** 093 * Returns an Iterator over this.streetSegs. 094 * 095 * @returns an iterator that produces the contents of 096 * this.streetSegs. Each element produced by the Iterator is a 097 * StreetSegment. 098 **/ 099 public Iterator<StreetSegment> iterator() { 100 return reader.streetSegmentsInternal(); 101 } 102 103 104 protected StreetSegIterator streetSegmentsInternal() { 105 File[] filesToRead = sourceDirectory.listFiles(zipFileFilter); 106 StreetSegmentFilter killfilter = KillfileReader.fromDir(sourceDirectory); 107 return new StreetSegIterator(Arrays.asList(filesToRead).iterator(), killfilter); 108 } 109 110 /** 111 * Returns an Iterator over this.streetSegs. 112 * 113 * @modifies: System.err 114 * 115 * @effects: If (debug) then prints messages to System.err on 116 * progress of database reading. Else no change to System.err 117 * 118 * @returns an iterator that produces the contents of 119 * this.streetSegs. Each element produced by the Iterator is a 120 * StreetSegment. 121 **/ 122 public Iterator<StreetSegment> streetSegments() { 123 StreetSegIterator iter = reader.streetSegmentsInternal(); 124 return iter; 125 } 126 127 // Inner classes 128 129 /** 130 * Exception indicating that the requested source for a 131 * tiger database is invalid 132 **/ 133 public static class InvalidSourceException 134 extends Exception{ 135 public static final long serialVersionUID = 4534; 136 public InvalidSourceException(String msg) { super(msg); } 137 } 138 139 }