1/* 2 * ReadOnceStrategy.java 3 * Copyright (C) 2006 Amin Ahmad 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19package org.ahmadsoft.postal; 20 21import java.io.File; 22import java.io.RandomAccessFile; 23import java.util.ArrayList; 24import java.util.Collections; 25import java.util.HashMap; 26import java.util.List; 27import java.util.Map; 28 29/** 30 * A retrieval strategy that looks up from disk the first time 31 * and subsequently reads from cache. The Read-Once strategy 32 * is quite acceptable for day to day usage, its main problem 33 * being that memory usage limits cannot be enforced. 34 * 35 * @author Amin Ahmad 36 */ 37public class ReadOnceStrategy implements PostalRetrievalStrategy { 38 39 private RandomAccessFile dataFile; 40 private RandomAccessFile indexFile; 41 42 private static Map cache = Collections.synchronizedMap(new HashMap()); 43 44 /** 45 * @inheritDoc 46 */ 47 public void initialize(File _indexFile, File _dataFile) throws Exception { 48 dataFile = new RandomAccessFile(_dataFile, "r"); 49 indexFile = new RandomAccessFile(_indexFile, "r"); 50 } 51 52 private synchronized List diskLookup(int postalCode) { 53 List result = new ArrayList(); 54 55 try { 56 indexFile.seek((postalCode-1) * 8); 57 indexFile.readInt(); 58 int loc = indexFile.readInt(); 59 60 dataFile.seek(loc); 61 short type=0; 62 while (0 != (type=dataFile.readShort())) { 63 String state = dataFile.readUTF(); 64 String city = dataFile.readUTF(); 65 66 result.add(new PostalCodeEntry(postalCode,city,state,type)); 67 } 68 } catch (Exception e) { 69 throw new RuntimeException(e); 70 } 71 72 return result; 73 } 74 75 /** 76 * @inheritDoc 77 */ 78 public List getCandidates(int postalCode) { 79 if (postalCode < 1 || postalCode > 99999) { 80 return new ArrayList(); 81 } 82 83 List candidates = null; 84 if (!cache.containsKey(new Integer(postalCode))) { 85 candidates = Collections.unmodifiableList(diskLookup(postalCode)); 86 cache.put(new Integer(postalCode), candidates); 87 } else { 88 candidates = (List) cache.get(new Integer(postalCode)); 89 } 90 91 return candidates; 92 } 93 94 /** 95 * @inheritDoc 96 */ 97 public void dispose() throws Exception { 98 dataFile.close(); 99 indexFile.close(); 100 cache = null; 101 } 102 103} 104