Skip to content

Commit bc469b4

Browse files
committed
HttpPars refact
1 parent 59f0fe0 commit bc469b4

3 files changed

Lines changed: 46 additions & 121 deletions

File tree

web/src/main/java/com/github/oeuvres/alix/web/HttpPars.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -274,18 +274,18 @@ public Enum<?> getEnum(final String name, final Enum<?> fallback, final String c
274274
}
275275

276276
/**
277-
* Resolve a request parameter as a float.
277+
* Resolve a request parameter as a double.
278278
*
279279
* @param name parameter name.
280280
* @param fallback value returned when absent or unparseable.
281-
* @return resolved float.
281+
* @return resolved double.
282282
*/
283-
public float getFloat(final String name, final float fallback)
283+
public double getDouble(final String name, final double fallback)
284284
{
285285
String value = request.getParameter(name);
286286
if (hasValue(value)) {
287287
try {
288-
return Float.parseFloat(value);
288+
return Double.parseDouble(value);
289289
} catch (NumberFormatException e) {
290290
// fall through
291291
}
@@ -294,21 +294,21 @@ public float getFloat(final String name, final float fallback)
294294
}
295295

296296
/**
297-
* Resolve a request parameter as a float with cookie persistence.
297+
* Resolve a request parameter as a double with cookie persistence.
298298
* Priority: request parameter → cookie → fallback.
299299
* An empty (non-null) parameter resets the cookie.
300300
*
301301
* @param name parameter name.
302-
* @param fallback value returned when neither parameter nor cookie yield a valid float.
302+
* @param fallback value returned when neither parameter nor cookie yield a valid double.
303303
* @param cookie cookie name for persistence.
304-
* @return resolved float.
304+
* @return resolved double.
305305
*/
306-
public float getFloat(final String name, final float fallback, final String cookie)
306+
public double getDouble(final String name, final double fallback, final String cookie)
307307
{
308308
String value = request.getParameter(name);
309309
if (hasValue(value)) {
310310
try {
311-
float ret = Float.parseFloat(value);
311+
double ret = Double.parseDouble(value);
312312
cookie(cookie, "" + ret);
313313
return ret;
314314
} catch (NumberFormatException e) {
@@ -323,7 +323,7 @@ public float getFloat(final String name, final float fallback, final String cook
323323
if (value == null)
324324
return fallback;
325325
try {
326-
return Float.parseFloat(value);
326+
return Double.parseDouble(value);
327327
} catch (NumberFormatException e) {
328328
cookie(cookie, null);
329329
return fallback;

web/src/main/java/com/github/oeuvres/alix/web/Op.java

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@
2424
* format methods you need.</li>
2525
* <li>Register it in {@code AlixServlet.registerOps()}.</li>
2626
* </ol>
27+
*
28+
* <h2>Parameter resolution</h2>
29+
* <p>
30+
* Subclasses should use {@link HttpPars} for typed parameter access
31+
* with fallback and optional cookie persistence, rather than reading
32+
* raw request parameters directly.
33+
* </p>
2734
*/
2835
public abstract class Op
2936
{
@@ -96,37 +103,7 @@ protected void csv(LuceneIndex index,
96103
AlixServlet.sendError(resp, 406, name() + ": csv not implemented");
97104
}
98105

99-
// ---- shared utilities ----
100-
101-
/** Read the "q" parameter, or null if absent/blank. */
102-
protected static String qParam(final HttpServletRequest req)
103-
{
104-
final String q = req.getParameter("q");
105-
return (q != null && !q.isBlank()) ? q.trim() : null;
106-
}
107-
108-
/** Read an integer parameter, or {@code def} if absent/unparseable. */
109-
protected static int intParam(
110-
final HttpServletRequest req, final String name, final int def)
111-
{
112-
final String s = req.getParameter(name);
113-
if (s == null) return def;
114-
try { return Integer.parseInt(s.trim()); }
115-
catch (NumberFormatException e) { return def; }
116-
}
117-
118-
/** Pagination: 0-based start offset. */
119-
protected static int start(final HttpServletRequest req)
120-
{
121-
return Math.max(0, intParam(req, "start", 0));
122-
}
123-
124-
/** Pagination: result limit, clamped to [1, max]. */
125-
protected static int limit(
126-
final HttpServletRequest req, final int def, final int max)
127-
{
128-
return Math.max(1, Math.min(intParam(req, "limit", def), max));
129-
}
106+
// ---- response utilities ----
130107

131108
/** Open a Gson {@link JsonWriter} on the response. */
132109
protected static JsonWriter jsonWriter(final HttpServletResponse resp)
Lines changed: 28 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.github.oeuvres.alix.web.op;
1+
package com.github.oeuvres.alix.web;
22

33
import java.io.IOException;
44
import java.util.List;
@@ -8,11 +8,11 @@
88
import jakarta.servlet.http.HttpServletRequest;
99
import jakarta.servlet.http.HttpServletResponse;
1010

11+
import com.github.oeuvres.alix.lucene.FlucText;
1112
import com.github.oeuvres.alix.lucene.LuceneIndex;
1213
import com.github.oeuvres.alix.lucene.terms.TermRow;
1314
import com.github.oeuvres.alix.lucene.terms.TermScorer;
1415
import com.github.oeuvres.alix.lucene.terms.ThemeTerms;
15-
import com.github.oeuvres.alix.web.AlixServlet;
1616

1717
/**
1818
* {@code /{index}/terms} — ranked term lists.
@@ -37,12 +37,12 @@
3737
*/
3838
public final class OpTerms extends Op
3939
{
40+
/** Clamping range for the {@code top} parameter. */
41+
private static final int[] TOP_RANGE = { 1, 500 };
42+
4043
/** Default number of returned terms. */
4144
private static final int DEFAULT_TOP = 50;
4245

43-
/** Hard ceiling on returned terms. */
44-
private static final int MAX_TOP = 500;
45-
4646
/** Default BM25 IDF exponent. */
4747
private static final double DEFAULT_IDF_EXP = 1.3d;
4848

@@ -56,10 +56,11 @@ protected void json(
5656
final HttpServletResponse resp
5757
) throws IOException
5858
{
59-
// ---- parameter parsing ----
60-
final String field = fieldParam(index, req);
61-
final int topK = topParam(req);
62-
final String q = qParam(req);
59+
final HttpPars pars = new HttpPars(req);
60+
61+
final String field = pars.getString("field", index.content());
62+
final int topK = pars.getInt("top", TOP_RANGE, DEFAULT_TOP);
63+
final String q = pars.getString("q", null);
6364

6465
// ---- dispatch to producer ----
6566
final List<TermRow> rows;
@@ -72,88 +73,35 @@ protected void json(
7273
}
7374
else {
7475
// Theme terms mode
75-
final ThemeTerms themeTerms = index.themeTerms(field);
76+
final FlucText fluc = index.fieldText(field);
77+
if (fluc == null) {
78+
AlixServlet.sendError(resp, 404,
79+
"terms: field '" + field + "' not found or not a text field");
80+
return;
81+
}
82+
final ThemeTerms themeTerms = fluc.themeTerms();
7683
if (themeTerms == null) {
7784
AlixServlet.sendError(resp, 503,
7885
"terms: lexicon or field statistics not available for field '"
7986
+ field + "'");
8087
return;
8188
}
82-
final double idfExp = doubleParam(req, "idfExp", DEFAULT_IDF_EXP);
89+
final double idfExp = pars.getDouble("idfExp", DEFAULT_IDF_EXP);
8390
final TermScorer scorer = new TermScorer.BM25(idfExp);
8491
rows = themeTerms.topTerms(scorer, topK);
8592
}
8693

8794
// ---- serialize ----
88-
writeTermRows(resp, rows);
89-
}
90-
91-
// ================================================================
92-
// Serialization
93-
// ================================================================
94-
95-
/**
96-
* Write a list of term rows as a JSON array.
97-
*/
98-
private static void writeTermRows(
99-
final HttpServletResponse resp,
100-
final List<TermRow> rows
101-
) throws IOException
102-
{
103-
final JsonWriter jw = jsonWriter(resp);
104-
jw.beginArray();
105-
for (TermRow row : rows) {
106-
jw.beginObject();
107-
jw.name("term").value(row.term());
108-
jw.name("count").value(row.count());
109-
jw.name("score").value(row.score());
110-
jw.endObject();
111-
}
112-
jw.endArray();
113-
jw.flush();
114-
}
115-
116-
// ================================================================
117-
// Parameter helpers
118-
// ================================================================
119-
120-
/**
121-
* Resolve the target field: explicit {@code field} param, or index default.
122-
*/
123-
private static String fieldParam(
124-
final LuceneIndex index,
125-
final HttpServletRequest req
126-
) {
127-
final String param = req.getParameter("field");
128-
if (param != null && !param.isBlank()) {
129-
return param.trim();
130-
}
131-
return index.content();
132-
}
133-
134-
/**
135-
* Read the {@code top} parameter, clamped to {@code [1, MAX_TOP]}.
136-
*/
137-
private static int topParam(final HttpServletRequest req)
138-
{
139-
return Math.max(1, Math.min(intParam(req, "top", DEFAULT_TOP), MAX_TOP));
140-
}
141-
142-
/**
143-
* Read a double parameter, or {@code def} if absent/unparseable.
144-
*/
145-
private static double doubleParam(
146-
final HttpServletRequest req,
147-
final String name,
148-
final double def
149-
) {
150-
final String s = req.getParameter(name);
151-
if (s == null) return def;
152-
try {
153-
return Double.parseDouble(s.trim());
154-
}
155-
catch (NumberFormatException e) {
156-
return def;
95+
try (JsonWriter jw = jsonWriter(resp)) {
96+
jw.beginArray();
97+
for (TermRow row : rows) {
98+
jw.beginObject();
99+
jw.name("term").value(row.term());
100+
jw.name("count").value(row.count());
101+
jw.name("score").value(row.score());
102+
jw.endObject();
103+
}
104+
jw.endArray();
157105
}
158106
}
159107
}

0 commit comments

Comments
 (0)