11package com .github .oeuvres .alix .web ;
22
33import static com .github .oeuvres .alix .web .Pars .END ;
4+ import static com .github .oeuvres .alix .web .Pars .F ;
5+ import static com .github .oeuvres .alix .web .Pars .Q ;
6+ import static com .github .oeuvres .alix .web .Pars .SLOP ;
7+ import static com .github .oeuvres .alix .web .Pars .SLOP_DEFAULT ;
8+ import static com .github .oeuvres .alix .web .Pars .SLOP_RANGE ;
49import static com .github .oeuvres .alix .web .Pars .START ;
510import static com .github .oeuvres .alix .web .Pars .YEAR ;
611
712import java .io .IOException ;
13+ import java .util .logging .Logger ;
814
915import org .apache .lucene .document .IntPoint ;
16+ import org .apache .lucene .queries .spans .SpanQuery ;
1017import org .apache .lucene .search .Query ;
1118
1219import com .google .gson .stream .JsonWriter ;
1623
1724import com .github .oeuvres .alix .lucene .FlucYear ;
1825import com .github .oeuvres .alix .lucene .LuceneIndex ;
26+ import com .github .oeuvres .alix .lucene .spans .SpanQueryParser ;
1927import com .github .oeuvres .alix .web .util .HttpPars ;
2028
2129/**
4351 */
4452public abstract class Op
4553{
46- /** Operation name, used for URL routing (e.g. "kwic", "cooc"). */
47- public abstract String name ();
54+ protected static final Logger LOG = Logger .getLogger (Op .class .getName ());
55+
56+
57+ /**
58+ * Try to claim an unmatched path segment as a resource.
59+ * Returns {@code false} if this op cannot handle the segment;
60+ * the router retains 404 responsibility.
61+ */
62+ public boolean offer (LuceneIndex index , String segment , String format ,
63+ HttpServletRequest req , HttpServletResponse resp ) throws IOException {
64+ return true ;
65+ }
4866
4967 /**
5068 * Dispatch to the appropriate format method.
@@ -71,7 +89,7 @@ else switch (format) {
7189 case "jsonl" -> jsonl (index , req , resp );
7290 case "csv" -> csv (index , req , resp );
7391 default -> AlixServlet .jsonError (resp , 406 ,
74- name () + ": unsupported format: " + format );
92+ getClass (). getSimpleName () + ": unsupported format: " + format );
7593 }
7694 }
7795
@@ -81,35 +99,35 @@ else switch (format) {
8199 protected void page (LuceneIndex index ,
82100 HttpServletRequest req , HttpServletResponse resp ) throws IOException
83101 {
84- AlixServlet .jsonError (resp , 406 , name () + ": default html not implemented" );
102+ AlixServlet .jsonError (resp , 406 , getClass (). getSimpleName () + ": default html not implemented" );
85103 }
86104
87105 /** Structured JSON. */
88106 protected void json (LuceneIndex index ,
89107 HttpServletRequest req , HttpServletResponse resp ) throws IOException
90108 {
91- AlixServlet .jsonError (resp , 406 , name () + ": json not implemented" );
109+ AlixServlet .jsonError (resp , 406 , getClass (). getSimpleName () + ": json not implemented" );
92110 }
93111
94112 /** HTML fragment for streaming insertion. */
95113 protected void html (LuceneIndex index ,
96114 HttpServletRequest req , HttpServletResponse resp ) throws IOException
97115 {
98- AlixServlet .jsonError (resp , 406 , name () + ": html fragment not implemented" );
116+ AlixServlet .jsonError (resp , 406 , getClass (). getSimpleName () + ": html fragment not implemented" );
99117 }
100118
101119 /** JSON Lines — one object per line. */
102120 protected void jsonl (LuceneIndex index ,
103121 HttpServletRequest req , HttpServletResponse resp ) throws IOException
104122 {
105- AlixServlet .jsonError (resp , 406 , name () + ": jsonl not implemented" );
123+ AlixServlet .jsonError (resp , 406 , getClass (). getSimpleName () + ": jsonl not implemented" );
106124 }
107125
108126 /** CSV tabular export. */
109127 protected void csv (LuceneIndex index ,
110128 HttpServletRequest req , HttpServletResponse resp ) throws IOException
111129 {
112- AlixServlet .jsonError (resp , 406 , name () + ": csv not implemented" );
130+ AlixServlet .jsonError (resp , 406 , getClass (). getSimpleName () + ": csv not implemented" );
113131 }
114132
115133 // ---- response utilities ----
@@ -164,4 +182,21 @@ Query yearQuery(LuceneIndex index, HttpPars pars) throws IOException {
164182 if (start == end ) return IntPoint .newExactQuery (YEAR , start );
165183 return IntPoint .newRangeQuery (YEAR , start , end );
166184 }
185+
186+ /**
187+ * Build a SpanQuery from parameters
188+ * @param index
189+ * @param pars
190+ * @return
191+ * @throws IOException
192+ */
193+ SpanQuery spanQuery (LuceneIndex index , HttpPars pars ) throws IOException {
194+ final String q = pars .getString (Q , null );
195+ if (q == null ) return null ;
196+ final String content = pars .getString (F , index .content ());
197+ final int slop = pars .getInt (SLOP , SLOP_RANGE , SLOP_DEFAULT , SLOP );
198+ SpanQuery spanQuery = new SpanQueryParser (content , slop ).parse (q );
199+ return spanQuery ;
200+ }
201+
167202}
0 commit comments