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 }