View Javadoc

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 }