1 package org.paneris.bibliomania;
2
3 import java.util.Enumeration;
4
5 import javax.servlet.http.HttpServletRequest;
6
7 import org.melati.Melati;
8 import org.melati.servlet.Form;
9 import org.melati.poem.AccessToken;
10 import org.melati.poem.Persistent;
11 import org.melati.poem.PoemTask;
12 import org.melati.poem.PoemThread;
13 import org.melati.poem.UnexpectedExceptionPoemException;
14 import org.melati.template.ServletTemplateContext;
15 import org.paneris.bibliomania.fti.ContextSearchResults;
16 import org.paneris.bibliomania.fti.HitText;
17 import org.paneris.bibliomania.fti.IndexOther;
18 import org.paneris.bibliomania.fti.Library;
19 import org.paneris.bibliomania.fti.Score;
20 import org.paneris.bibliomania.fti.ScoredHitTextsEnumeration;
21 import org.paneris.bibliomania.fti.SearchResults;
22 import org.webmacro.WebMacroException;
23 import org.webmacro.servlet.HandlerException;
24 import org.webmacro.servlet.WebContext;
25
26 import com.sleepycat.db.DatabaseException;
27
28 public class Search extends BibliomaniaServlet {
29
30 private static final long serialVersionUID = 1L;
31
32 protected String bibliomaniaHandle(Melati melati, WebContext context) throws WebMacroException {
33 ServletTemplateContext tc = melati.getServletTemplateContext();
34 String queryText = Form.getFieldNulled(tc, "queryText");
35 String queryHeadwords = Form.getFieldNulled(tc, "queryHeadwords");
36
37 if (queryText == null && queryHeadwords == null)
38 return bibliomaniaTemplate("search/Search.wm");
39
40 context.put("queryText", queryText == null ? "" : queryText);
41 context.put("queryHeadwords", queryHeadwords == null ? "" : queryHeadwords);
42
43 int start = 0;
44 String startString = context.getForm("start");
45 if (startString != null) {
46 try {
47 start = Math.max(0, Integer.parseInt(startString));
48 } catch (NumberFormatException e) {
49 throw new HandlerException("`start' param must be a number");
50 }
51 }
52
53 BibliomaniaDatabase bib = (BibliomaniaDatabase)PoemThread.database();
54
55 if (!bib.openBerkelyDBs()) {
56 context.put("message", "Full text search has been temporarily switched off, sorry.");
57 } else {
58
59 boolean infoSearch = "true".equals(context.getForm("info"));
60
61 IndexOther fti = infoSearch ? bib.infoFTI() : bib.fti();
62 Library lib = infoSearch ? bib.infoLibrary() : bib.getChapterTable();
63 context.put("info", infoSearch ? Boolean.TRUE : null);
64
65 SearchResults raw;
66 try {
67 raw = fti.querySearchResults(queryText, queryHeadwords);
68 PoemThread.toTidy().add(raw);
69 } catch (DatabaseException e) {
70 throw new HandlerException(
71 "Problem with Full Text index:" + e.toString());
72 }
73
74 ContextSearchResults results;
75 results = new ContextSearchResults(lib, raw, fti);
76 PoemThread.toTidy().add(results);
77
78 String hitsPerTextString = context.getForm("hitsPerText");
79 int hitsPerText;
80 if (hitsPerTextString != null && !hitsPerTextString.trim().equals(""))
81 try {
82 hitsPerText = Math.max(0, Integer.parseInt(hitsPerTextString));
83 if (hitsPerText == 0)
84 hitsPerText =
85 ((BibliomaniaDatabase)melati.getDatabase())
86 .getDefaultSearchHitsPerText();
87 } catch (NumberFormatException e) {
88 throw new HandlerException("`hitsPerText' param must be a number");
89 } else
90 hitsPerText =
91 ((BibliomaniaDatabase)melati.getDatabase())
92 .getDefaultSearchHitsPerText();
93
94 long startTextID = 0;
95 long limitTextID = Long.MAX_VALUE;
96
97 boolean restrict = "true".equals(context.getForm("restrict"));
98
99 if (restrict) {
100 Persistent object = melati.getObject();
101 if (object != null && object instanceof Unit) {
102 startTextID = ((Unit)object).ftiTextID_start();
103 limitTextID = ((Unit)object).ftiTextID_limit();
104 }
105 }
106 context.put("restrict", restrict ? "true" : "false");
107
108 Score.Hit[] order;
109 try {
110 order = Score.scoredHits(raw, startTextID, limitTextID, 50
111 );
112 } catch (DatabaseException e) {
113 throw new HandlerException(
114 "Problem with Full Text index:" + e.toString());
115 }
116
117 ScoredHitTextsEnumeration hits =
118 new ScoredHitTextsEnumeration(
119 results,
120 order,
121 start,
122 bib.getSearchHitsPerPage(),
123 hitsPerText);
124 context.put("hitTexts", hits);
125 context.put("count", order.length);
126
127 context.put("hitsPerText", new Integer(hitsPerText));
128
129 context.put("start", new Integer(hits.getPageStart()));
130 context.put("end", new Integer(hits.getPageEnd()));
131
132 HttpServletRequest req = context.getRequest();
133
134 Integer prevStart = hits.getPrevPageStart();
135 if (prevStart != null)
136 context.put(
137 "prevPageURI",
138 req.getRequestURI()
139 + "?"
140 + Form.sameQueryWith(
141 req.getQueryString(),
142 "start",
143 prevStart.toString()));
144
145 Integer nextStart = hits.getNextPageStart();
146 if (nextStart != null)
147 context.put(
148 "nextPageURI",
149 req.getRequestURI()
150 + "?"
151 + Form.sameQueryWith(
152 req.getQueryString(),
153 "start",
154 nextStart.toString()));
155 }
156 return bibliomaniaTemplate("search/Results.wm");
157 }
158
159 public static void main(final String[] args) throws Exception {
160 IndexOther.debug = true;
161
162 final BibliomaniaDatabase bib = new BibliomaniaDatabase(false);
163 bib.connect("bibliomania",
164 "org.melati.poem.dbms.Postgresql",
165 "jdbc:postgresql:bibliomania",
166 "postgres",
167 "*",
168 8);
169
170 bib.inSession(AccessToken.root, new PoemTask() {
171 public void run() {
172 try {
173 SearchResults raw = bib.fti().querySearchResults(args[0]);
174
175 int hitsPerText = 10;
176
177 long startTextID;
178 if (args.length < 3)
179 startTextID = 0L;
180 else if (args[1].equals("tid"))
181 startTextID = Long.parseLong(args[2]);
182 else
183 startTextID =
184 ((Unit)bib
185 .getTable(args[1])
186 .getObject(Integer.parseInt(args[2])))
187 .ftiTextID_start();
188
189 long limitTextID;
190 if (args.length < 5)
191 limitTextID = Long.MAX_VALUE;
192 else if (args[3].equals("tid"))
193 limitTextID = Long.parseLong(args[4]);
194 else
195 limitTextID =
196 ((Unit)bib
197 .getTable(args[3])
198 .getObject(Integer.parseInt(args[4])))
199 .ftiTextID_start();
200
201 System.err.println("[ " + startTextID + ", " + limitTextID + ")");
202
203 Score.Hit[] order =
204 Score.scoredHits(raw, startTextID, limitTextID, 50);
205
206 ContextSearchResults results =
207 new ContextSearchResults(bib.getChapterTable(), raw, bib.fti());
208
209 Enumeration hits =
210 new ScoredHitTextsEnumeration(
211 results,
212 order,
213 0,
214 bib.getSearchHitsPerPage(),
215 hitsPerText);
216
217 while (hits.hasMoreElements())
218 ((HitText)hits.nextElement()).dump();
219 } catch (Exception e) {
220 throw new UnexpectedExceptionPoemException(e);
221 }
222 }
223 });
224 }
225 }