View Javadoc

1   package net.sourceforge.jgeocoder.tiger;
2   import static net.sourceforge.jgeocoder.AddressComponent.CITY;
3   import static net.sourceforge.jgeocoder.AddressComponent.COUNTY;
4   import static net.sourceforge.jgeocoder.AddressComponent.LAT;
5   import static net.sourceforge.jgeocoder.AddressComponent.LON;
6   import static net.sourceforge.jgeocoder.AddressComponent.STATE;
7   import static net.sourceforge.jgeocoder.AddressComponent.ZIP;
8   
9   import java.io.File;
10  import java.util.Map;
11  
12  import net.sourceforge.jgeocoder.AddressComponent;
13  
14  import org.apache.commons.lang.StringUtils;
15  import org.apache.commons.lang.builder.EqualsBuilder;
16  import org.apache.commons.lang.builder.HashCodeBuilder;
17  import org.apache.commons.lang.builder.ToStringBuilder;
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  
21  import com.sleepycat.je.DatabaseException;
22  import com.sleepycat.je.Environment;
23  import com.sleepycat.je.EnvironmentConfig;
24  import com.sleepycat.persist.EntityStore;
25  import com.sleepycat.persist.PrimaryIndex;
26  import com.sleepycat.persist.SecondaryIndex;
27  import com.sleepycat.persist.StoreConfig;
28  import com.sleepycat.persist.model.Entity;
29  import com.sleepycat.persist.model.KeyField;
30  import com.sleepycat.persist.model.Persistent;
31  import com.sleepycat.persist.model.PrimaryKey;
32  import com.sleepycat.persist.model.Relationship;
33  import com.sleepycat.persist.model.SecondaryKey;
34  
35  @Entity
36  class CityWithSpaces{
37    @PrimaryKey
38    private String _noSpace;
39    private String _withSpace;
40    public String getNoSpace() {
41      return _noSpace;
42    }
43    public String getWithSpace() {
44      return _withSpace;
45    }
46    public void setNoSpace(String noSpace) {
47      _noSpace = noSpace;
48    }
49    public void setWithSpace(String withSpace) {
50      _withSpace = withSpace;
51    }
52    @Override
53    public String toString() {
54      return ToStringBuilder.reflectionToString(this);
55    }
56    @Override
57    public int hashCode() {
58      return HashCodeBuilder.reflectionHashCode(this);
59    }
60    @Override
61    public boolean equals(Object obj) {
62      return EqualsBuilder.reflectionEquals(this, obj);
63    }
64  }
65  
66  @Entity
67  class CityStateGeo{
68    @PrimaryKey
69    private Location _location;
70    private float _lat;
71    private float _lon;
72    public Location getLocation() {
73      return _location;
74    }
75    public void setLocation(Location location) {
76      _location = location;
77    }
78    public float getLat() {
79      return _lat;
80    }
81    public void setLat(float lat) {
82      _lat = lat;
83    }
84    public float getLon() {
85      return _lon;
86    }
87    public void setLon(float lon) {
88      _lon = lon;
89    }
90    @Override
91    public String toString() {
92      return ToStringBuilder.reflectionToString(this);
93    }
94    @Override
95    public int hashCode() {
96      return HashCodeBuilder.reflectionHashCode(this);
97    }
98    @Override
99    public boolean equals(Object obj) {
100     return EqualsBuilder.reflectionEquals(this, obj);
101   }
102 }
103 
104 @Entity
105 class County{
106     @PrimaryKey
107     private Location _location;
108     private String[] _zips;
109     private float _lat;
110     private float _lon;
111     public Location getLocation() {
112         return _location;
113     }
114     public void setLocation(Location _location) {
115         this._location = _location;
116     }
117     public String[] getZips() {
118         return _zips;
119     }
120     public void setZips(String[] _zips) {
121         this._zips = _zips;
122     }
123     public float getLat() {
124         return _lat;
125     }
126     public void setLat(float _lat) {
127         this._lat = _lat;
128     }
129     public float getLon() {
130         return _lon;
131     }
132     public void setLon(float _lon) {
133         this._lon = _lon;
134     }
135     @Override
136     public String toString() {
137       return ToStringBuilder.reflectionToString(this);
138     }
139     @Override
140     public int hashCode() {
141       return HashCodeBuilder.reflectionHashCode(this);
142     }
143     @Override
144     public boolean equals(Object obj) {
145       return EqualsBuilder.reflectionEquals(this, obj);
146     }
147 }
148 
149 @Entity
150 class ZipCode{
151   @PrimaryKey
152   private String _zip;
153   @SecondaryKey(relate=Relationship.MANY_TO_ONE)
154   private Location _location;
155   @SecondaryKey(relate=Relationship.MANY_TO_ONE)
156   private String _county;
157   private float _lat;
158   private float _lon;
159   private String _zipClass;
160   public String getZip() {
161     return _zip;
162   }
163   public void setZip(String zip) {
164     _zip = zip;
165   }
166   public Location getLocation() {
167     return _location;
168   }
169   public void setLocation(Location location) {
170     _location = location;
171   }
172   public String getCounty() {
173     return _county;
174   }
175   public void setCounty(String county) {
176     _county = county;
177   }
178   public float getLat() {
179     return _lat;
180   }
181   public void setLat(float lat) {
182     _lat = lat;
183   }
184   public float getLon() {
185     return _lon;
186   }
187   public void setLon(float lon) {
188     _lon = lon;
189   }
190   public String getZipClass() {
191     return _zipClass;
192   }
193   public void setZipClass(String zipClass) {
194     _zipClass = zipClass;
195   }
196   @Override
197   public String toString() {
198     return ToStringBuilder.reflectionToString(this);
199   }
200   @Override
201   public int hashCode() {
202     return HashCodeBuilder.reflectionHashCode(this);
203   }
204   @Override
205   public boolean equals(Object obj) {
206     return EqualsBuilder.reflectionEquals(this, obj);
207   }
208   
209 }
210 @Persistent
211 class Location{ 
212   @KeyField(1)
213   private String _city;
214   @KeyField(2)
215   private String _state;
216 
217   public String getCity() {
218     return _city;
219   }
220   public void setCity(String city) {
221     _city = city;
222   }
223   public String getState() {
224     return _state;
225   }
226   public void setState(String state) {
227     _state = state;
228   }
229   @Override
230   public String toString() {
231     return ToStringBuilder.reflectionToString(this);
232   }
233   @Override
234   public int hashCode() {
235     return HashCodeBuilder.reflectionHashCode(this);
236   }
237   @Override
238   public boolean equals(Object obj) {
239     return EqualsBuilder.reflectionEquals(this, obj);
240   }
241 }
242 /***
243  * TODO javadocs me
244  * @author jliang
245  *
246  */
247 class ZipCodeDAO{
248   private static final Log LOGGER = LogFactory.getLog(ZipCodeDAO.class);
249   private PrimaryIndex<String, ZipCode> _zipCodeByZip;
250   private SecondaryIndex<Location, String, ZipCode> _zipCodeByLocation;
251   private PrimaryIndex<Location, CityStateGeo> _cityStateGeoByLocation;
252   private PrimaryIndex<String, CityWithSpaces> _cityWithSpaceByNoSpace;
253   private PrimaryIndex<Location, County> _countyByLocation;
254   public ZipCodeDAO(EntityStore store) throws DatabaseException{
255     _zipCodeByZip = store.getPrimaryIndex(String.class, ZipCode.class);
256     _zipCodeByLocation = store.getSecondaryIndex(_zipCodeByZip, Location.class, "_location");
257     _cityStateGeoByLocation = store.getPrimaryIndex(Location.class, CityStateGeo.class);
258     _cityWithSpaceByNoSpace = store.getPrimaryIndex(String.class, CityWithSpaces.class);
259     _countyByLocation = store.getPrimaryIndex(Location.class, County.class);
260   }
261   
262   public PrimaryIndex<Location, County> getCountyByLocation() {
263     return _countyByLocation;
264   }
265 
266   public PrimaryIndex<String, CityWithSpaces> getCityWithSpaceByNoSpace() {
267     return _cityWithSpaceByNoSpace;
268   }
269   
270   public PrimaryIndex<Location, CityStateGeo> getCityStateGeoByLocation() {
271     return _cityStateGeoByLocation;
272   }
273   public SecondaryIndex<Location, String, ZipCode> getZipCodeByLocation() {
274     return _zipCodeByLocation;
275   }
276   public PrimaryIndex<String, ZipCode> getZipCodeByZip() {
277     return _zipCodeByZip;
278   }
279   
280   public boolean fillInCSByZip(Map<AddressComponent, String> m, String zip) throws DatabaseException{
281     return fillInCSByZip(m, _zipCodeByZip.get(zip));
282   }
283   
284   private boolean fillInCSByZip(Map<AddressComponent, String> m, ZipCode zipcode) throws DatabaseException{
285       if(zipcode == null){
286           return false;
287       }
288     String city = zipcode.getLocation().getCity();
289     CityWithSpaces cws = getCityWithSpaceByNoSpace().get(city);
290     if(cws != null){
291       m.put(CITY, cws.getWithSpace());
292     }else{
293       m.put(CITY, city);
294     }
295     m.put(COUNTY, zipcode.getCounty());
296     m.put(STATE, zipcode.getLocation().getState());
297     return true;
298   }
299   
300   private County getCounty(Location loc){
301      try {
302           return _countyByLocation.get(loc);
303      } catch (DatabaseException e) {
304           if(LOGGER.isDebugEnabled()){
305               LOGGER.debug("Unable to get county by city state", e);
306           }
307           return null;
308      }
309   }
310   
311   public County getCounty(String city, String state){
312       if(StringUtils.isBlank(city)||StringUtils.isBlank(state)){
313           return null;
314       }
315       city = city.replaceAll("//s+|//bCOUNTY$|//bPARISH$|//bBOROUGH$", "");
316       Location loc = new Location();
317       loc.setCity(city); loc.setState(state);
318       return getCounty(loc);
319   }
320   
321   public boolean geocodeByCityState(Map<AddressComponent, String> m){
322     String city = m.get(AddressComponent.CITY), state = m.get(AddressComponent.STATE);
323     if(StringUtils.isBlank(city)||StringUtils.isBlank(state)){
324       return false;
325     }
326     boolean onlyCounty = city.endsWith("COUNTY");
327     city = city.replaceAll("//s+|//bCOUNTY$|//bPARISH$|//bBOROUGH$", "");
328     try {
329       Location loc = new Location();
330       loc.setCity(city); loc.setState(state);
331       CityStateGeo geo = onlyCounty? null : _cityStateGeoByLocation.get(loc);
332       County county = getCounty(loc);
333       if(geo!= null || county != null){
334           if(onlyCounty && county != null){
335               m.put(LAT, String.valueOf(county.getLat()));
336               m.put(LON, String.valueOf(county.getLon()));
337               return true;
338           }else if(geo != null){
339               m.put(LAT, String.valueOf(geo.getLat()));
340               m.put(LON, String.valueOf(geo.getLon()));
341               return true;   
342           }else if(county != null){
343               m.put(LAT, String.valueOf(county.getLat()));
344               m.put(LON, String.valueOf(county.getLon()));
345               return true;
346           }
347       }
348     } catch (DatabaseException e) {
349       if(LOGGER.isDebugEnabled()){
350         LOGGER.debug("Unable to geocode with city state", e);
351       }
352       return false;
353     }
354     return false;
355   }
356   
357   public boolean geocodeByZip(Map<AddressComponent, String> m){
358     String zip = m.get(ZIP);
359     if(StringUtils.isBlank(zip)){
360       return false;
361     }
362     try {
363       ZipCode zipcode = _zipCodeByZip.get(zip);
364       if(zipcode != null){
365         if(m.get(LAT) == null){
366           m.put(LAT, String.valueOf(zipcode.getLat()));
367         }
368         if(m.get(LON) == null){
369           m.put(LON, String.valueOf(zipcode.getLon()));
370         }
371         return true;
372       }
373     } catch (Exception e) {
374       if(LOGGER.isDebugEnabled()){
375         LOGGER.debug("Unable to geocode with zip", e);
376       }
377       return false;
378     }
379     return false;
380   }
381 }
382 
383 class ZipCodesDb{
384   private Environment _env = null;
385   private EntityStore _store = null;
386   public Environment getEnv() {
387     return _env;
388   }
389   public EntityStore getStore() {
390     return _store;
391   }
392   
393   public void init(JGeocoderConfig jgconfig, File envHome, boolean readOnly, boolean transactional) throws DatabaseException{
394     
395     EnvironmentConfig config = new EnvironmentConfig();
396     config.setAllowCreate(!readOnly);
397     config.setReadOnly(readOnly);
398     config.setTransactional(transactional);
399     if(jgconfig != null){
400       if(jgconfig.getBerkeleyDbCachePercent() >= 0 ){
401         config.setCacheSize(jgconfig.getBerkeleyDbCacheSize());
402       }
403       if(jgconfig.getBerkeleyDbCachePercent() >= 0){
404         config.setCachePercent(jgconfig.getBerkeleyDbCachePercent());
405       }
406     }
407     _env = new Environment(envHome, config);
408     StoreConfig config2 = new StoreConfig();
409     config2.setAllowCreate(!readOnly);
410     config2.setReadOnly(readOnly);
411     config2.setTransactional(transactional);
412     _store = new EntityStore(_env, "ZipCodeEntityStore", config2);
413   }
414   
415   public void init(File envHome, boolean readOnly, boolean transactional) throws DatabaseException{
416     init(null, envHome, readOnly, transactional);
417   }
418   
419   public void shutdown() throws DatabaseException{
420     if(_store != null){
421       _store.close();
422     }
423     if(_env != null){
424       _env.close();
425     }
426   }
427   
428 }