1 package org.paneris.bibliomania; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.sql.Timestamp; 6 import java.util.Enumeration; 7 import java.util.Hashtable; 8 import java.util.Vector; 9 10 import org.melati.poem.AccessToken; 11 import org.melati.poem.PoemTask; 12 import org.melati.poem.PoemThread; 13 import org.melati.poem.UnexpectedExceptionPoemException; 14 import org.melati.poem.util.ArrayEnumeration; 15 import org.melati.poem.util.Order; 16 import org.melati.poem.util.SortUtils; 17 import org.melati.poem.transaction.ToTidyList; 18 import org.melati.util.UnexpectedExceptionException; 19 import org.paneris.bibliomania.generated.StockingsSearchBase; 20 import org.paneris.bibliomania.metasearch.Metasearch; 21 import org.webmacro.WebMacroException; 22 23 public class StockingsSearch extends StockingsSearchBase { 24 25 public BibliomaniaDatabase getBibliomaniaDatabase () { 26 return (BibliomaniaDatabase)getDatabase(); 27 } 28 29 public StockingsSearch() {} 30 31 private long timeout; 32 private SearchThread searchThread; 33 34 private static class DisplayOrder implements Order { 35 36 private static int iom(Integer i) { 37 return i == null ? Integer.MAX_VALUE : i.intValue(); 38 } 39 40 public boolean lessOrEqual(Object a, Object b) { 41 BookStocking sa = (BookStocking)a; 42 BookStocking sb = (BookStocking)b; 43 44 int fca = iom(sa.getFormatcode_unsafe()); 45 int fcb = iom(sb.getFormatcode_unsafe()); 46 47 if (fca < fcb) return true; 48 else if (fca > fcb) return false; 49 50 int pna = iom(sa.getPricenumber_unsafe()); 51 int pnb = iom(sb.getPricenumber_unsafe()); 52 53 return pna <= pnb; 54 } 55 56 public static final Order it = new DisplayOrder(); 57 } 58 59 public class CollatingResults { 60 61 private Object[] sorted; 62 63 public CollatingResults(Vector baseResults) { 64 sorted = SortUtils.sorted(DisplayOrder.it, baseResults); 65 } 66 67 public Enumeration startingAtRow(int row) { 68 return new Buy.CollatedHitsEnumeration( 69 new ArrayEnumeration(sorted), 70 getBibliomaniaDatabase().bookshops().length, row); 71 } 72 } 73 74 private class SearchThread extends Thread { 75 76 Metasearch search; 77 ToTidyList toTidy = new ToTidyList(); 78 79 public SearchThread() { 80 final BibliomaniaDatabase database = getBibliomaniaDatabase(); 81 database.notifyBookshopSearchStart(); 82 search = new Metasearch(database.bookshops(), 83 getTitleterm_unsafe(), 84 getAuthorterm_unsafe(), 85 toTidy); 86 start(); 87 } 88 89 public void run() { 90 final BibliomaniaDatabase database = getBibliomaniaDatabase(); 91 92 try { 93 synchronized (search) { 94 try { 95 search.wait(timeout); 96 } 97 catch (InterruptedException e) { 98 search.close(); 99 return; 100 } 101 } 102 103 if (search.running()) 104 search.close(); 105 106 toTidy.close(); 107 108 database.inSession( 109 AccessToken.root, 110 new PoemTask() { 111 public void run() { 112 try { 113 File cache = cachedResultsFile(); 114 115 File dir = cache.getParentFile(); 116 if (!dir.exists()) 117 dir.mkdirs(); 118 119 Hashtable extras = new Hashtable(); 120 extras.put("results", 121 new CollatingResults(search.currentResults())); 122 123 getBibliomaniaDatabase().interpolateTemplateToFile( 124 "metasearch/CachedResults.wm", cache, null, extras); 125 } 126 catch (WebMacroException e) { 127 throw new UnexpectedExceptionException(e); 128 } 129 catch (IOException e) { 130 throw new UnexpectedExceptionException(e); 131 } 132 finally { 133 setLastperformed(new Timestamp(System.currentTimeMillis())); 134 PoemThread.commit(); 135 } 136 } 137 }); 138 } 139 catch (Exception e) { 140 System.err.println("Exception in StockingsSearch for `" + 141 getAuthorterm_unsafe() + "'/`" + 142 getTitleterm_unsafe() + "'"); 143 e.printStackTrace(); 144 } 145 finally { 146 database.notifyBookshopSearchStop(); 147 synchronized (StockingsSearch.this) { 148 searchThread = null; 149 } 150 } 151 } 152 } 153 154 private Metasearch search() { 155 SearchThread running = searchThread; 156 157 if (running == null) { 158 synchronized (this) { 159 if (searchThread == null) { 160 timeout = 161 getBibliomaniaDatabase().getBibBookBookshopSearchTimeoutMillis(); 162 searchThread = new SearchThread(); 163 } 164 running = searchThread; 165 } 166 } 167 168 return running.search; 169 } 170 171 public void runNewSearch() { 172 search(); 173 } 174 175 public Enumeration newSearchResults() { 176 return search().currentAndFutureResults(); 177 } 178 179 private String cachedResultsFileLocation() { 180 StringBuffer it = new StringBuffer(); 181 it.append(getBibliomaniaDatabase().getBookStockingsCacheDir()); 182 183 String t = troid().toString(); 184 185 if (t.length() % 2 == 1) 186 t = '0' + t; 187 188 for (int i = 0; i < t.length(); i += 2) { 189 it.append('/'); 190 it.append(t.substring(i, i + 2)); 191 } 192 193 it.append(".html"); 194 195 return it.toString(); 196 } 197 198 private File cachedResultsFile() { 199 return new File(cachedResultsFileLocation()); 200 } 201 202 public boolean upToDate() { 203 Timestamp last = getLastperformed(); 204 return last != null && 205 System.currentTimeMillis() - last.getTime() < 206 getBibliomaniaDatabase().getBookStockingsCheckIntervalMillis(); 207 } 208 209 public String cachedResultsPath() { 210 if (!upToDate()) 211 return null; 212 else { 213 File it = cachedResultsFile(); 214 return it.exists() ? it.toString() : null; 215 } 216 } 217 218 public void delete_unsafe() { 219 super.delete_unsafe(); 220 cachedResultsFile().delete(); 221 } 222 223 public static void main(final String[] args) { 224 final BibliomaniaDatabase bib = new BibliomaniaDatabase(false, true); 225 bib.connect("bibliomania","org.melati.poem.dbms.Postgresql", 226 "jdbc:postgresql:bibliomania", "postgres", "*",8); 227 228 bib.setLogSQL(true); 229 230 bib.inSession( 231 AccessToken.root, 232 new PoemTask() { 233 public void run() { 234 try { 235 StockingsSearch s = 236 bib.getStockingsSearchTable().searchFor(args[0], args[1]); 237 String res = s.cachedResultsPath(); 238 if (res != null) 239 System.out.println("-> " + res); 240 else { 241 System.err.println("searching ..........."); 242 for (Enumeration r = s.newSearchResults(); 243 r.hasMoreElements();) { 244 BookStocking st = (BookStocking)r.nextElement(); 245 System.out.println(st.getPublisher_unsafe() + " " + 246 st.getShop_unsafe() + " " + 247 st.getPrice_unsafe()); 248 } 249 System.err.println("......... done searching"); 250 } 251 } 252 catch (Exception e) { 253 throw new UnexpectedExceptionPoemException(e); 254 } 255 } 256 }); 257 } 258 }