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 }