mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
'v3.3.4.1'
This commit is contained in:
@@ -19,21 +19,22 @@ package gplx.xowa.specials; import gplx.*; import gplx.xowa.*;
|
||||
import gplx.xowa.users.history.*;
|
||||
import gplx.xowa.langs.*; import gplx.xowa.langs.specials.*;
|
||||
import gplx.xowa.specials.*;
|
||||
import gplx.xowa.specials.allPages.*; import gplx.xowa.specials.search.*; import gplx.xowa.specials.nearby.*; import gplx.xowa.specials.randoms.*; import gplx.xowa.specials.statistics.*; import gplx.xowa.xtns.translates.*; import gplx.xowa.specials.movePage.*;
|
||||
import gplx.xowa.specials.allPages.*; import gplx.xowa.specials.nearby.*; import gplx.xowa.specials.randoms.*; import gplx.xowa.specials.statistics.*; import gplx.xowa.xtns.translates.*; import gplx.xowa.specials.movePage.*;
|
||||
import gplx.xowa.specials.xowa.system_data.*; import gplx.xowa.specials.xowa.default_tab.*; import gplx.xowa.specials.xowa.popup_history.*; import gplx.xowa.specials.xowa.file_browsers.*; import gplx.xowa.specials.xowa.diags.*;
|
||||
import gplx.xowa.xtns.wdatas.specials.*;
|
||||
import gplx.xowa.addons.searchs.specials.*;
|
||||
import gplx.xowa.users.data.*; import gplx.xowa.users.bmks.*;
|
||||
public class Xows_mgr {
|
||||
private final Hash_adp_bry hash;
|
||||
public Xows_mgr(Xowe_wiki wiki, Xol_lang_itm lang) {
|
||||
hash = Hash_adp_bry.ci_u8(lang.Case_mgr());
|
||||
page_allpages = new Xows_page_allpages(wiki);
|
||||
page_search = new Xows_page__search(wiki);
|
||||
page_search = new Srch_special_page(wiki);
|
||||
page_random = new Xows_page_random(wiki);
|
||||
Evt_lang_changed(wiki.Lang());
|
||||
}
|
||||
public Xows_page_allpages Page_allpages() {return page_allpages;} private final Xows_page_allpages page_allpages;
|
||||
public Xows_page__search Page_search() {return page_search;} private final Xows_page__search page_search;
|
||||
public Srch_special_page Page_search() {return page_search;} private final Srch_special_page page_search;
|
||||
public Xows_page_random Page_random() {return page_random;} private final Xows_page_random page_random;
|
||||
public Xop_randomRootPage_page Page_randomRootPage() {return page_randomRootPage;} private final Xop_randomRootPage_page page_randomRootPage = new Xop_randomRootPage_page();
|
||||
public Xou_history_html Page_history() {return page_history;} private final Xou_history_html page_history = new Xou_history_html();
|
||||
|
||||
@@ -117,7 +117,7 @@ public class Xows_page_allpages implements gplx.core.brys.Bfr_arg, GfoInvkAble,
|
||||
rslt_prv = rslt_prv2;
|
||||
return true;
|
||||
} private Gfo_qarg_mgr arg_hash = new Gfo_qarg_mgr();
|
||||
private static final byte[] Bry_arg_from = Bry_.new_a7("from"), Bry_arg_ns = Bry_.new_a7("namespace"), Bry_arg_hideredirects = Bry_.new_a7("hideredirects");
|
||||
private static final byte[] Bry_arg_from = Bry_.new_a7("from"), Bry_arg_ns = Bry_.new_a7("namespace"), Bry_arg_hideredirects = Bry_.new_a7("hideredirects");
|
||||
public Xow_ns Init_ns() {return init_ns;} private Xow_ns init_ns;
|
||||
public void Build_html(Xoae_page page) {
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_m001();
|
||||
@@ -133,7 +133,7 @@ public class Xows_page_allpages implements gplx.core.brys.Bfr_arg, GfoInvkAble,
|
||||
int msg_id = fwd ? Xol_msg_itm_.Id_sp_allpages_fwd : Xol_msg_itm_.Id_sp_allpages_bwd;
|
||||
Xol_msg_itm msg_itm = wiki.Lang().Msg_mgr().Itm_by_id_or_null(msg_id);
|
||||
Bry_bfr tmp_bfr = wiki.Utl__bfr_mkr().Get_b512().Mkr_rls();
|
||||
byte[] lbl_text = msg_itm.Fmt(tmp_bfr, ttl.Full_txt());
|
||||
byte[] lbl_text = msg_itm.Fmt(tmp_bfr, ttl.Full_txt_w_ttl_case());
|
||||
byte[] args__rest = arg_hash.Concat(tmp_bfr, Bry_arg_ns, Bry_arg_hideredirects);
|
||||
byte[] arg_from = gplx.langs.htmls.encoders.Gfo_url_encoder_.Id.Encode(ttl.Page_txt_wo_qargs());
|
||||
return html_list_end.Bld_bry_many(bfr, arg_from, args__rest, lbl_text);
|
||||
@@ -165,7 +165,7 @@ public class Xows_page_allpages implements gplx.core.brys.Bfr_arg, GfoInvkAble,
|
||||
}
|
||||
public static final String Invk_html_all_ = "html_all_", Invk_html_list_grp_ = "html_list_grp_", Invk_html_list_itm_normal_ = "html_list_itm_normal_", Invk_html_list_itm_redirect_ = "html_list_itm_redirect_"
|
||||
, Invk_itms_per_page_ = "itms_per_page_", Invk_itms_per_grp_ = "itms_per_grp_", Invk_show_redirects_ = "show_redirects_";
|
||||
public static final String GRP_KEY = "xowa.special.allpages";
|
||||
public static final String GRP_KEY = "xowa.special.allpages";
|
||||
}
|
||||
class Xos_pagelist_html_itm_fmtr implements gplx.core.brys.Bfr_arg {
|
||||
public Xos_pagelist_html_itm_fmtr(Xows_page_allpages mgr, Xowe_wiki wiki) {
|
||||
@@ -190,10 +190,10 @@ class Xos_pagelist_html_itm_fmtr implements gplx.core.brys.Bfr_arg {
|
||||
if (ttl_itm == null) break; // ttl_itm can be null at bgn or end of title list; EX: list=A-Z; count=5; key=Z; itms=X,Y,Z,null,null
|
||||
Xoa_ttl ttl = Xows_page_allpages.ttl_(wiki, init_ns, ttl_itm);
|
||||
byte[] href = href_wtr.Build_to_bry(wiki, ttl);
|
||||
byte[] title = Xoh_html_wtr.Ttl_to_title(ttl.Full_txt());
|
||||
byte[] title = Xoh_html_wtr.Ttl_to_title(ttl.Full_txt_w_ttl_case());
|
||||
byte[] cls = Xoh_lnki_wtr.Lnki_cls_visited(history_mgr, wiki_key, ttl.Page_txt()); // NOTE: must be ttl.Page_txt() in order to match Xou_history_mgr.Add
|
||||
Bry_fmtr fmtr = ttl_itm.Redirected() ? itm_redirect : itm_normal;
|
||||
fmtr.Bld_bfr_many(bfr, itm_pct, href, title, ttl.Full_txt(), cls);
|
||||
fmtr.Bld_bfr_many(bfr, itm_pct, href, title, ttl.Full_txt_w_ttl_case(), cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,8 +124,8 @@ public class Xows_page_allpages_tst {
|
||||
class Xows_page_allpages_fxt {
|
||||
public Xows_page_allpages_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.app_();
|
||||
wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
app = Xoa_app_fxt.Make__app__edit();
|
||||
wiki = Xoa_app_fxt.Make__wiki__edit(app);
|
||||
allpages = wiki.Special_mgr().Page_allpages();
|
||||
GfoInvkAble_.InvkCmd_val(allpages, Xows_page_allpages.Invk_itms_per_page_, 5);
|
||||
}
|
||||
|
||||
@@ -71,8 +71,8 @@ public class Move_page implements Xows_page {
|
||||
fmtr_all.Bld_bfr_many(tmp_bfr
|
||||
, msg_mgr.Val_by_key_obj("move-page-legend")
|
||||
, Bry_.Add(Xoh_href_.Bry__wiki, src_ttl.Full_db())
|
||||
, gplx.langs.htmls.Gfh_utl.Escape_html_as_bry(src_ttl.Full_txt())
|
||||
, src_ttl.Full_txt()
|
||||
, gplx.langs.htmls.Gfh_utl.Escape_html_as_bry(src_ttl.Full_txt_w_ttl_case())
|
||||
, src_ttl.Full_txt_w_ttl_case()
|
||||
, msg_mgr.Val_by_key_obj("newtitle")
|
||||
, ns_list_fmtr
|
||||
, args.Trg_ttl()
|
||||
@@ -136,7 +136,7 @@ class Move_trg_ns_list_fmtr implements gplx.core.brys.Bfr_arg {
|
||||
fmtr.Bld_bfr_many(bfr, ns.Id(), bry_selected, ns.Name_combo());
|
||||
}
|
||||
}
|
||||
private static final byte[] Bry_selected = Bry_.new_a7(" selected=''");
|
||||
private static final byte[] Bry_selected = Bry_.new_a7(" selected=''");
|
||||
private Bry_fmtr fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <option value='~{ns_id}' ~{ns_selected}>~{ns_name}</option>"
|
||||
@@ -174,7 +174,7 @@ class Move_url_args {
|
||||
create_redirect = false;
|
||||
}
|
||||
private static final byte Key_submitted = 1, Key_src_ttl = 2, Key_trg_ns = 3, Key_trg_ttl = 4, Key_create_redirect = 5;
|
||||
private static final Hash_adp_bry arg_keys = Hash_adp_bry.ci_a7()
|
||||
private static final Hash_adp_bry arg_keys = Hash_adp_bry.ci_a7()
|
||||
.Add_str_byte("wpMove" , Key_submitted)
|
||||
.Add_str_byte("wpOldTitle" , Key_src_ttl)
|
||||
.Add_str_byte("wpNewTitleNs" , Key_trg_ns)
|
||||
|
||||
@@ -29,7 +29,7 @@ public class Rndm_core_tbl implements Rls_able {
|
||||
fld_interval = flds.Add_int("rndm_interval");
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public void Create_tbl() {conn.Ddl_create_tbl(Dbmeta_tbl_itm.New(tbl_name, flds, Dbmeta_idx_itm.new_unique_by_name(tbl_name, "core", fld_uid)));}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds, Dbmeta_idx_itm.new_unique_by_name(tbl_name, "core", fld_uid)));}
|
||||
public void Upsert(int uid, String where_sql, int total, int interval) {
|
||||
conn.Stmt_delete(tbl_name, fld_uid).Crt_int(fld_uid, uid).Exec_delete();
|
||||
conn.Stmt_insert(tbl_name, flds).Val_int(fld_uid, uid).Val_str(fld_where_sql, where_sql).Val_int(fld_total, total).Val_int(fld_interval, interval).Exec_insert();
|
||||
|
||||
@@ -30,7 +30,7 @@ public class Rndm_mgr implements Rls_able {
|
||||
}
|
||||
public void Rebuild(int uid, String where_sql, int interval) {
|
||||
int total_count = 0; List_adp rng_list = List_adp_.new_();
|
||||
Db_conn conn = page_tbl.Conn();
|
||||
Db_conn conn = page_tbl.conn;
|
||||
Db_stmt stmt = conn.Stmt_select_order(page_tbl.Tbl_name(), String_.Ary(page_tbl.Fld_page_id()), String_.Ary_empty, page_tbl.Fld_page_id());
|
||||
Db_rdr rdr = stmt.Exec_select__rls_auto();
|
||||
try {
|
||||
@@ -69,7 +69,7 @@ public class Rndm_mgr implements Rls_able {
|
||||
String sql = fmt_sql.Bld_many_to_str(bfr, page_tbl.Tbl_name(), page_tbl.Fld_page_id(), where_sql, page_id_bgn, offset);
|
||||
Db_rdr rdr = Db_rdr_.Empty;
|
||||
try {
|
||||
rdr = page_tbl.Conn().Exec_sql_as_rdr_v2(sql);
|
||||
rdr = page_tbl.conn.Exec_rdr(sql);
|
||||
return rdr.Move_next() ? rdr.Read_int(page_tbl.Fld_page_id()) : -1;
|
||||
}
|
||||
finally {rdr.Rls();}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class Rndm_range_tbl implements Rls_able {
|
||||
fld_rng_page_id = flds.Add_int("rng_page_id");
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public void Create_tbl() {conn.Ddl_create_tbl(Dbmeta_tbl_itm.New(tbl_name, flds, Dbmeta_idx_itm.new_unique_by_name(tbl_name, "core", fld_rng_uid, fld_rng_idx)));}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds, Dbmeta_idx_itm.new_unique_by_name(tbl_name, "core", fld_rng_uid, fld_rng_idx)));}
|
||||
public void Insert_bgn(int uid) {
|
||||
conn.Stmt_delete(tbl_name, fld_rng_uid).Crt_int(fld_rng_uid, uid).Exec_delete();
|
||||
stmt_insert = conn.Stmt_insert(tbl_name, flds);
|
||||
@@ -43,7 +43,7 @@ public class Rndm_range_tbl implements Rls_able {
|
||||
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_rng_uid, fld_rng_idx);
|
||||
Db_rdr rdr = stmt_select.Clear().Val_int(fld_rng_uid, core_uid).Val_int(fld_rng_idx, rng_idx).Exec_select__rls_manual();
|
||||
try {return rdr.Move_next() ? rdr.Read_int(fld_rng_page_id) : -1;}
|
||||
catch (Exception e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to get rndm_idx; url=~{0} core_uid=~{1} rng_idx=~{2} err=~{3}", conn.Conn_info().Xto_api(), core_uid, rng_idx, Err_.Message_gplx_log(e)); return -1;}
|
||||
catch (Exception e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "failed to get rndm_idx; url=~{0} core_uid=~{1} rng_idx=~{2} err=~{3}", conn.Conn_info().Db_api(), core_uid, rng_idx, Err_.Message_gplx_log(e)); return -1;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public void Rls() {
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.core.brys.fmtrs.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.wikis.nss.*; import gplx.xowa.langs.cases.*;
|
||||
import gplx.xowa.specials.search.crts.*;
|
||||
public class Srch_db_wkr {
|
||||
private Xol_case_mgr drd_case_mgr;
|
||||
public Srch_rslt_itm[] Search_by_drd(Cancelable cxl, Srch_rslt_lnr rslt_lnr, Xow_wiki wiki, byte[] search, int search_results_max) {
|
||||
Xows_ns_mgr ns_mgr = new Xows_ns_mgr(); ns_mgr.Add_main_if_empty();
|
||||
Srch_qry qry = new Srch_qry(search, 0, search_results_max, ns_mgr, Bool_.Y, new gplx.xowa.wikis.domains.Xow_domain_itm[] {wiki.Domain_itm()});
|
||||
Srch_rslt_hash cache = new Srch_rslt_hash(); cache.Init_by_db(cxl, search, wiki.Data__core_mgr().Db__search().Tbl__search_word());
|
||||
if (drd_case_mgr == null) drd_case_mgr = Xol_case_mgr_.U8();
|
||||
Search(cxl, rslt_lnr, cache, wiki, drd_case_mgr, qry);
|
||||
int len = cache.Count();
|
||||
Srch_rslt_itm[] rv = new Srch_rslt_itm[len];
|
||||
for (int i = 0; i < len; ++i)
|
||||
rv[i] = cache.Get_at(i);
|
||||
return rv;
|
||||
}
|
||||
@gplx.Internal protected void Search(Cancelable cxl, Srch_rslt_lnr rslt_lnr, Srch_rslt_hash cache, Xow_wiki wiki, Xol_case_mgr case_mgr, Srch_qry qry) {
|
||||
// get search_words
|
||||
Xowd_db_file search_db = wiki.Data__core_mgr().Db__search();
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search started (please wait)");
|
||||
Srch_crt_node ttl_matcher = cache.Ttl_matcher();
|
||||
if (ttl_matcher == null) {
|
||||
cache.Init_by_db(cxl, case_mgr.Case_build_lower(qry.search_raw), search_db.Tbl__search_word()); // lower-case search
|
||||
ttl_matcher = cache.Ttl_matcher();
|
||||
}
|
||||
// do some init
|
||||
int rslts_wanted = qry.itms_end - qry.itms_bgn;
|
||||
Xowd_db_file core_db = wiki.Data__core_mgr().Db__core();
|
||||
Xowd_page_tbl page_tbl = core_db.Tbl__page();
|
||||
Xowd_search_link_tbl link_tbl = search_db.Tbl__search_link();
|
||||
Srch_word_row[] word_ary = cache.Words(); int word_ary_len = word_ary.length;
|
||||
// read pages for each word from db
|
||||
Db_attach_rdr attach_rdr = new Db_attach_rdr(search_db.Conn(), "page_db", core_db.Url());
|
||||
attach_rdr.Attach();
|
||||
int total_found = 0;
|
||||
try {
|
||||
while (true) {
|
||||
boolean found_none = true;
|
||||
for (int i = 0; i < word_ary_len; ++i) { // loop each word to get rslts_wanted
|
||||
if (cxl.Canceled()) return;
|
||||
Srch_word_row word = word_ary[i];
|
||||
if (word.Rslts_done()) continue; // last db_search for word returned 0 results; don't search again;
|
||||
int offset = word.Rslts_offset();
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "searching; wiki=~{0} total=~{1} offset=~{2} index=~{3} word=~{4}", wiki.Domain_str(), word_ary_len, offset, i, word.text);
|
||||
String sql = search_fmt.Bld_many_to_str_auto_bfr(link_tbl.Tbl_name(), link_tbl.Fld_page_id(), link_tbl.Fld_word_id(), word.id, offset); // need to return enough results to fill qry.page_len as many results may be discarded below; DATE:2015-04-24
|
||||
int rslts_found = Search_pages(cxl, rslt_lnr, cache, wiki, case_mgr, qry, page_tbl, attach_rdr, sql, ttl_matcher, word, rslts_wanted);
|
||||
total_found += rslts_found;
|
||||
if (rslts_found == -1) return; // canceled
|
||||
else if (rslts_found > 0) found_none = false; // NOTE: do not reverse and do rslts_found == 0; want to check if any word returns results;
|
||||
}
|
||||
if (found_none) {cache.Done_y_(); break;}
|
||||
if (total_found >= rslts_wanted) break;
|
||||
}
|
||||
cache.Itms_end_(qry.itms_end);
|
||||
cache.Sort();
|
||||
}
|
||||
catch (Exception e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "error during search; wiki=~{0} total=~{1} err=~{2}", wiki.Domain_str(), word_ary_len, Err_.Message_gplx_log(e));}
|
||||
finally {attach_rdr.Detach();}
|
||||
}
|
||||
private int Search_pages(Cancelable cxl, Srch_rslt_lnr rslt_lnr, Srch_rslt_hash cache, Xow_wiki wiki, Xol_case_mgr case_mgr, Srch_qry qry
|
||||
, Xowd_page_tbl page_tbl, Db_attach_rdr attach_rdr, String sql, Srch_crt_node ttl_matcher, Srch_word_row word, int rslts_wanted) {
|
||||
int rslts_found = 0;
|
||||
Xow_ns_mgr ns_mgr = wiki.Ns_mgr();
|
||||
Db_rdr rdr = attach_rdr.Exec_as_rdr(sql);
|
||||
try {
|
||||
while (rdr.Move_next()) {
|
||||
if (cxl.Canceled()) return -1;
|
||||
word.Rslts_offset_add_1();
|
||||
int page_ns = rdr.Read_int(page_tbl.Fld_page_ns());
|
||||
if (!qry.ns_mgr.Has(page_ns)) continue; // ignore: ns doesn't match
|
||||
byte[] page_ttl = rdr.Read_bry_by_str(page_tbl.Fld_page_title());
|
||||
// Io_mgr.Instance.AppendFilStr("C:\\temp.txt", String_.new_u8(word.Text()) + "|" + Int_.To_str(page_ns) + "|" + String_.new_u8(page_ttl) + "\n");
|
||||
if (!ttl_matcher.Matches(case_mgr, page_ttl)) continue; // ignore: ttl doesn't match ttl_matcher
|
||||
Xow_ns ns = ns_mgr.Ids_get_or_null(page_ns);
|
||||
byte[] page_ttl_w_ns = ns.Gen_ttl(page_ttl);
|
||||
if (cache.Has(page_ttl_w_ns)) continue; // ignore: page already added by another word; EX: "A B"; word is "B", but "A B" already added by "A"
|
||||
Srch_rslt_itm row = new Srch_rslt_itm(wiki.Domain_bry(), wiki.Ttl_parse(page_ttl_w_ns), rdr.Read_int(page_tbl.Fld_page_id()), rdr.Read_int(page_tbl.Fld_page_len()));
|
||||
rslt_lnr.Notify_rslt_found(row);
|
||||
if (++rslts_found == rslts_wanted) break; // stop: found enough results; DATE:2015-04-24
|
||||
}
|
||||
} finally {rdr.Rls();}
|
||||
if (rslts_found == 0) word.Rslts_done_y_(); // read through entire rdr and nothing found; mark word done
|
||||
return rslts_found;
|
||||
}
|
||||
public Db_stmt New_qry(Db_conn conn, String page_db_alias, Xowd_page_tbl page, Xowd_search_link_tbl link, int offset) {
|
||||
Db_qry qry = Db_qry_.select_()
|
||||
.Cols_w_tbl_("p", page.Fld_page_id(), page.Fld_page_ns(), page.Fld_page_title(), page.Fld_page_len())
|
||||
.From_(page_db_alias, page.Tbl_name(), "p")
|
||||
.Join_(link.Tbl_name(), "l", Db_qry_.New_join__join(link.Fld_page_id(), page.Fld_page_id(), "p"))
|
||||
.Where_(Db_crt_.New_eq("l", link.Fld_word_id(), -1))
|
||||
.Order_("p", page.Fld_page_len(), Bool_.N)
|
||||
.Offset_(offset)
|
||||
;
|
||||
// qry_mgr.Add_ns(qry, page); // qry.Where_and_(page.Fld_page_ns(), -1)
|
||||
return conn.Stmt_new(qry);
|
||||
}
|
||||
private static final Bry_fmt search_fmt = Bry_fmt.New
|
||||
( String_.Concat_lines_nl_skip_last
|
||||
( "SELECT p.page_id"
|
||||
, ", p.page_namespace"
|
||||
, ", p.page_title"
|
||||
, ", p.page_len"
|
||||
, "FROM <attach_db>page p"
|
||||
, " JOIN ~{tbl_link} l ON p.page_id = l.~{col_link_page_id} "
|
||||
, "WHERE l.~{col_link_word_id} = ~{word_id}"
|
||||
, "ORDER BY p.page_len DESC"
|
||||
, "LIMIT -1" // NOTE:LIMIT needed when OFFSET is specified; -1 LIMIT means infinite; "If the LIMIT expression evaluates to a negative value, then there is no upper bound on the number of rows returned"; http://sqlite.org/lang_select.html
|
||||
, "OFFSET ~{offset};"
|
||||
), "tbl_link", "col_link_page_id", "col_link_word_id", "word_id", "offset");
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.domains.*;
|
||||
class Srch_qry {
|
||||
private final List_adp cmd_list = List_adp_.new_();
|
||||
public Srch_qry(byte[] search_raw, int page_idx, int page_len, Xows_ns_mgr ns_mgr, boolean async_db, Xow_domain_itm[] wiki_domains) {
|
||||
this.search_raw = search_raw; this.page_idx = page_idx; this.page_len = page_len; this.ns_mgr = ns_mgr; this.async_db = async_db; this.wiki_domains = wiki_domains;
|
||||
this.itms_bgn = page_idx * page_len;
|
||||
this.itms_end = itms_bgn + page_len;
|
||||
this.page_max = page_idx; // default page_max to page_idx; adjust later when all results are known
|
||||
this.key = Bry_.Add_w_dlm(Byte_ascii.Pipe, search_raw, ns_mgr.To_hash_key());
|
||||
this.special_link_base_href = Bry_.Add(Bry_.new_a7("Special:Search/"), search_raw, Bry_.new_a7("?fulltext=y"));
|
||||
}
|
||||
public final byte[] key;
|
||||
public final byte[] search_raw;
|
||||
public final int page_idx;
|
||||
public final int page_len;
|
||||
public final int itms_bgn;
|
||||
public final int itms_end;
|
||||
public final Xows_ns_mgr ns_mgr;
|
||||
public final Xow_domain_itm[] wiki_domains;
|
||||
public final byte[] special_link_base_href;
|
||||
public final boolean async_db;
|
||||
public int page_max;
|
||||
public int Cmds__len() {return cmd_list.Count();}
|
||||
public Xows_ui_cmd Cmds__get_at(int i) {return (Xows_ui_cmd)cmd_list.Get_at(i);}
|
||||
public void Cmds__add(Xows_ui_cmd cmd) {cmd_list.Add(cmd);}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.specials.search.crts.*;
|
||||
class Srch_rslt_hash { // per search request; EX: 'Earth* AND (History OR Future) AND -"middle earth"'
|
||||
private final Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
public Srch_crt_node Ttl_matcher() {return ttl_matcher;} private Srch_crt_node ttl_matcher;
|
||||
public Srch_word_row[] Words() {return words;} private Srch_word_row[] words; // words to search db; EX: earth, history, future but not "middle earth" (since not'ed)
|
||||
public boolean Done() {return done;} public void Done_y_() {done = true;} private boolean done; // marks if db search is done
|
||||
public int Count() {return hash.Count();}
|
||||
public int Itms_end() {return itms_end;} public void Itms_end_(int v) {itms_end = v;} private int itms_end;
|
||||
public void Init_by_db(Cancelable cxl, byte[] raw, gplx.xowa.wikis.data.tbls.Xowd_search_word_tbl word_tbl) {
|
||||
this.ttl_matcher = new Srch_crt_parser().Parse(raw);
|
||||
this.words = new Xows_db_matcher_bldr().Gather_words_for_db(cxl, ttl_matcher, word_tbl);
|
||||
}
|
||||
public boolean Has(byte[] key) {return hash.Has(key);}
|
||||
public Srch_rslt_itm Get_at(int i) {return (Srch_rslt_itm)hash.Get_at(i);}
|
||||
public void Add(Srch_rslt_itm itm) {hash.Add(itm.page_ttl.Full_db(), itm);}
|
||||
public void Get_between(Srch_rslt_list search_ui, int bgn, int end) {
|
||||
if (bgn >= hash.Count()) return; // requested start not in cache; exit
|
||||
for (int i = bgn; i < end; ++i) {
|
||||
if (i >= hash.Count()) break;
|
||||
search_ui.Add((Srch_rslt_itm)hash.Get_at(i));
|
||||
}
|
||||
}
|
||||
public void Sort() {hash.Sort_by(Srch_rslt_itm_sorter.Page_len_dsc);}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public class Srch_rslt_itm {
|
||||
public final byte[] key;
|
||||
public final byte[] wiki_bry;
|
||||
public final Xoa_ttl page_ttl;
|
||||
public final int page_id;
|
||||
public final int page_len;
|
||||
public Srch_rslt_itm(byte[] wiki_bry, Xoa_ttl page_ttl, int page_id, int page_len) {
|
||||
this.wiki_bry = wiki_bry;
|
||||
this.page_ttl = page_ttl;
|
||||
this.page_id = page_id;
|
||||
this.page_len = page_len;
|
||||
this.key = Bry_.Add(wiki_bry, Byte_ascii.Pipe_bry, page_ttl.Full_db());
|
||||
}
|
||||
}
|
||||
class Srch_rslt_itm_sorter implements gplx.core.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Srch_rslt_itm lhs = (Srch_rslt_itm)lhsObj;
|
||||
Srch_rslt_itm rhs = (Srch_rslt_itm)rhsObj;
|
||||
return -Int_.Compare(lhs.page_len, rhs.page_len);
|
||||
}
|
||||
public static final Srch_rslt_itm_sorter Page_len_dsc = new Srch_rslt_itm_sorter(); Srch_rslt_itm_sorter() {}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
class Srch_rslt_list {
|
||||
private final List_adp list = List_adp_.new_();
|
||||
public int Len() {return list.Count();}
|
||||
public void Add(Srch_rslt_itm rslt) {list.Add(rslt);}
|
||||
public Srch_rslt_itm Get_at(int i) {return (Srch_rslt_itm)list.Get_at(i);}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public interface Srch_rslt_lnr {
|
||||
void Notify_rslt_found(Srch_rslt_itm rslt);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public class Srch_word_row {
|
||||
public Srch_word_row(int id, byte[] text, int page_count) {this.id = id; this.text = text; this.page_count = page_count;}
|
||||
public final int id;
|
||||
public final byte[] text;
|
||||
public final int page_count;
|
||||
public int Rslts_offset() {return rslts_offset;} private int rslts_offset;
|
||||
public boolean Rslts_done() {return rslts_done;} private boolean rslts_done;
|
||||
public void Rslts_offset_add_1() {++rslts_offset;}
|
||||
public void Rslts_done_y_() {rslts_done = true;}
|
||||
}
|
||||
class Srch_word_row_sorter implements gplx.core.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Srch_word_row lhs = (Srch_word_row)lhsObj;
|
||||
Srch_word_row rhs = (Srch_word_row)rhsObj;
|
||||
return -Int_.Compare(lhs.page_count, rhs.page_count);
|
||||
}
|
||||
public static final Srch_word_row_sorter Page_count_dsc = new Srch_word_row_sorter(); Srch_word_row_sorter() {}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xog_search_suggest_cmd implements GfoInvkAble, Cancelable {
|
||||
private Xowe_wiki wiki; private byte[] search_bry; private Xosrh_page_mgr searcher; private int max_results, all_pages_extend, all_pages_min;
|
||||
public Xog_search_suggest_cmd(Xoae_app app, Xog_search_suggest_mgr mgr) {
|
||||
this.app = app; this.mgr = mgr;
|
||||
} private Xoae_app app; Xog_search_suggest_mgr mgr; Bry_bfr tmp_bfr = Bry_bfr.reset_(255); List_adp rslts_1 = List_adp_.new_(), rslts_2 = List_adp_.new_();
|
||||
public void Init(Xowe_wiki wiki, byte[] search_bry, int max_results, byte search_mode, int all_pages_extend, int all_pages_min) {
|
||||
this.wiki = wiki; this.search_bry = search_bry; this.max_results = max_results;
|
||||
this.search_mode = search_mode; this.all_pages_extend = all_pages_extend; this.all_pages_min = all_pages_min;
|
||||
searcher = new Xosrh_page_mgr();
|
||||
}
|
||||
private byte search_mode;
|
||||
public byte[] Search_bry() {return search_bry;}
|
||||
public boolean Canceled() {return canceled;}
|
||||
public void Cancel() {this.canceled = true;} private boolean canceled;
|
||||
public void Cancel_reset() {this.canceled = false;}
|
||||
public boolean Working() {return working;} public void Working_(boolean v) {working = v;} private boolean working;
|
||||
public List_adp Results() {return rslts_2;}
|
||||
public void Search() {
|
||||
try { // NOTE: must handle any errors in async mode
|
||||
canceled = false;
|
||||
working = true;
|
||||
boolean pass = false;
|
||||
switch (search_mode) {
|
||||
case Xog_search_suggest_mgr.Tid_search_mode_all_pages_v2: pass = Search_by_all_pages_v2(); break;
|
||||
case Xog_search_suggest_mgr.Tid_search_mode_all_pages_v1: pass = Search_by_all_pages_v1(); break;
|
||||
case Xog_search_suggest_mgr.Tid_search_mode_search: pass = Search_by_search(); break;
|
||||
}
|
||||
if (!pass) return;
|
||||
GfoInvkAble_.InvkCmd(app.Gui_mgr().Kit().New_cmd_sync(mgr), Xog_search_suggest_mgr.Invk_notify);
|
||||
working = false;
|
||||
}
|
||||
catch(Exception e) {
|
||||
app.Usr_dlg().Prog_many("", "", "error during search: err=~{0}", Err_.Message_gplx_full(e));
|
||||
}
|
||||
}
|
||||
private boolean Search_by_all_pages_v2() {
|
||||
rslts_2.Clear();
|
||||
Xoa_ttl search_ttl = Xoa_ttl.parse(wiki, search_bry); if (search_ttl == null) return false;
|
||||
byte[] search_ttl_bry = search_ttl.Page_db();
|
||||
wiki.Db_mgr().Load_mgr().Load_ttls_for_search_suggest(this, rslts_2, search_ttl.Ns(), search_ttl_bry, max_results, all_pages_min, all_pages_extend, true, false);
|
||||
return true;
|
||||
}
|
||||
private boolean Search_by_all_pages_v1() {
|
||||
rslts_2.Clear();
|
||||
Xowd_page_itm rslt_nxt = new Xowd_page_itm();
|
||||
Xowd_page_itm rslt_prv = new Xowd_page_itm();
|
||||
Xoa_ttl search_ttl = Xoa_ttl.parse(wiki, search_bry); if (search_ttl == null) return false;
|
||||
byte[] search_ttl_bry = search_ttl.Page_db();
|
||||
List_adp page_list = List_adp_.new_();
|
||||
wiki.Db_mgr().Load_mgr().Load_ttls_for_all_pages(this, page_list, rslt_nxt, rslt_prv, Int_obj_ref.zero_(), wiki.Ns_mgr().Ns_main(), search_ttl_bry, max_results, all_pages_min, all_pages_extend, true, false);
|
||||
Xowd_page_itm[] page_ary = (Xowd_page_itm[])page_list.To_ary_and_clear(Xowd_page_itm.class);
|
||||
int idx = 0, page_ary_len = page_ary.length;
|
||||
for (int i = 0; i < page_ary_len; i++) {
|
||||
Xowd_page_itm page = page_ary[i];
|
||||
if (page != null) {
|
||||
if (!Bry_.Has_at_bgn(page.Ttl_page_db(), search_ttl_bry)) continue; // look-ahead may return other titles that don't begin with search; ignore
|
||||
if (page.Text_len() > all_pages_min) {
|
||||
rslts_2.Add(page);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
if (idx == max_results) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private boolean Search_by_search() {
|
||||
Xosrh_rslt_grp rv = searcher.Itms_per_page_(max_results).Search(tmp_bfr, wiki, search_bry, 0, searcher, this);
|
||||
if (canceled) {working = false; return false;}
|
||||
rslts_1.Clear();
|
||||
int len = rv.Itms_len();
|
||||
for (int i = 0; i < len; i++)
|
||||
rslts_1.Add(rv.Itms_get_at(i));
|
||||
if (canceled) {working = false; return false;}
|
||||
rslts_1.Sort_by(Xowd_page_itm_sorter.EnyLenDsc);
|
||||
if (canceled) {working = false; return false;}
|
||||
if (len > max_results) len = max_results;
|
||||
rslts_2.Clear();
|
||||
for (int i = 0; i < len; i++)
|
||||
rslts_2.Add(rslts_1.Get_at(i));
|
||||
if (canceled) {working = false; return false;}
|
||||
rslts_2.Sort_by(Xowd_page_itm_sorter.IdAsc);
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(this, rslts_2, 0, len);
|
||||
rslts_2.Sort_by(Xowd_page_itm_sorter.TitleAsc);
|
||||
if (canceled) {working = false; return false;}
|
||||
return true;
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_search)) Search();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
} public static final String Invk_search = "search";
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.net.*; import gplx.core.threads.*; import gplx.core.envs.*;
|
||||
import gplx.gfui.*; import gplx.xowa.guis.*; import gplx.xowa.guis.views.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.core.js.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
public class Xog_search_suggest_mgr implements GfoInvkAble {
|
||||
public Xog_search_suggest_mgr(Xoa_gui_mgr gui_mgr) {
|
||||
this.app = gui_mgr.App();
|
||||
this.main_win = gui_mgr.Browser_win();
|
||||
cur_cmd = new Xog_search_suggest_cmd(app, this);
|
||||
} private Xoae_app app; private Xog_win_itm main_win; private Js_wtr wtr = new Js_wtr();
|
||||
private int results_max = 10; private boolean log_enabled = false;
|
||||
public boolean Enabled() {return enabled;} private boolean enabled = true;
|
||||
public byte Search_mode() {return search_mode;} public Xog_search_suggest_mgr Search_mode_(byte v) {search_mode = v; return this;} private byte search_mode = Tid_search_mode_all_pages_v2;
|
||||
public int All_pages_extend() {return all_pages_extend;} private int all_pages_extend = 1000; // look ahead by 1000
|
||||
public int All_pages_min() {return all_pages_min;} private int all_pages_min = 10000; // only look at pages > 10 kb
|
||||
public boolean Auto_wildcard() {return auto_wildcard;} private boolean auto_wildcard = false; // automatically add wild-card; EX: Earth -> *Earth*
|
||||
public Gfo_qarg_itm[] Args_default() {return args_default;} private Gfo_qarg_itm[] args_default = Gfo_qarg_itm.Ary_empty;
|
||||
public void Args_default_str_(String v) {
|
||||
this.args_default_str = v;
|
||||
byte[] bry = Bry_.new_a7("http://x.org/a?" + v);
|
||||
Gfo_url tmp_url = new Gfo_url();
|
||||
app.User().Wikii().Utl__url_parser().Url_parser().Parse(tmp_url, bry, 0, bry.length);
|
||||
args_default = tmp_url.Qargs();
|
||||
}
|
||||
private String args_default_str = "";// default args for search
|
||||
public static final int[] Ns_default_main = new int[] {Xow_ns_.Tid__main};
|
||||
public void Cancel() {
|
||||
cur_cmd.Cancel();
|
||||
long prv_time = Env_.TickCount();
|
||||
while (cur_cmd.Working()) {
|
||||
if (Env_.TickCount() - prv_time > 4000) {
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search cancel timeout: word=~{0}", String_.new_u8(search_bry));
|
||||
cur_cmd.Working_(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Search(Xowe_wiki wiki, byte[] search_bry, byte[] cbk_func) {
|
||||
this.wiki = wiki; this.search_bry = search_bry; this.cbk_func = cbk_func;
|
||||
Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_suggest, this, Invk_search_async).Start();
|
||||
} private Xowe_wiki wiki; private byte[] search_bry, cbk_func;
|
||||
private Object thread_lock = new Object();
|
||||
private void Search_async() {
|
||||
if (!enabled) return;
|
||||
if (search_bry.length == 0) return;
|
||||
this.Cancel();
|
||||
synchronized (thread_lock) {
|
||||
if (Bry_.Eq(search_bry , last_search_bry)) {
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search repeated?: word=~{0}", String_.new_u8(search_bry));
|
||||
return;
|
||||
}
|
||||
cur_cmd.Init(wiki, search_bry, results_max, search_mode, all_pages_extend, all_pages_min);
|
||||
this.last_search_bry = search_bry;
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search bgn: word=~{0}", String_.new_u8(search_bry));
|
||||
cur_cmd.Search();
|
||||
}
|
||||
} private Xog_search_suggest_cmd cur_cmd; byte[] last_search_bry;
|
||||
public void Notify() {// EX: receiveSuggestions('search_word', ['result_1', 'result_2']);
|
||||
// synchronized (thread_lock) NOTE: never use synchronized here; will synchronized search; DATE:2013-09-24
|
||||
byte[] search_bry = cur_cmd.Search_bry();
|
||||
if (!Bry_.Eq(search_bry, last_search_bry)) {
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search does not match?: expd=~{0} actl=~{1}", String_.new_u8(last_search_bry), String_.new_u8(search_bry));
|
||||
return; // do not notify if search terms do not match
|
||||
}
|
||||
List_adp found = cur_cmd.Results();
|
||||
wtr.Func_init(cbk_func);
|
||||
wtr.Prm_bry(search_bry);
|
||||
wtr.Prm_spr();
|
||||
wtr.Ary_init();
|
||||
int len = found.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xowd_page_itm p = (Xowd_page_itm)found.Get_at(i);
|
||||
Xow_ns ns = wiki.Ns_mgr().Ids_get_or_null(p.Ns_id());
|
||||
byte[] ttl = Xoa_ttl.Replace_unders(ns.Gen_ttl(p.Ttl_page_db()));
|
||||
wtr.Ary_bry(ttl);
|
||||
}
|
||||
wtr.Ary_term();
|
||||
wtr.Func_term();
|
||||
if (log_enabled) app.Usr_dlg().Log_many("", "", "search end: word=~{0}", String_.new_u8(search_bry));
|
||||
main_win.Active_html_box().Html_js_eval_script(wtr.To_str_and_clear());
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_search_async)) Search_async();
|
||||
else if (ctx.Match(k, Invk_notify)) Notify();
|
||||
else if (ctx.Match(k, Invk_enabled)) return Yn.To_str(enabled);
|
||||
else if (ctx.Match(k, Invk_enabled_)) enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_results_max)) return results_max;
|
||||
else if (ctx.Match(k, Invk_results_max_)) results_max = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_search_mode)) return Search_mode_str(search_mode);
|
||||
else if (ctx.Match(k, Invk_search_mode_)) search_mode = Search_mode_parse(m.ReadStr("v"));
|
||||
else if (ctx.Match(k, Invk_search_mode_list)) return Options_search_mode_list;
|
||||
else if (ctx.Match(k, Invk_all_pages_extend)) return all_pages_extend;
|
||||
else if (ctx.Match(k, Invk_all_pages_extend_)) all_pages_extend = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_all_pages_min)) return all_pages_min;
|
||||
else if (ctx.Match(k, Invk_all_pages_min_)) all_pages_min = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_auto_wildcard)) return Yn.To_str(auto_wildcard);
|
||||
else if (ctx.Match(k, Invk_auto_wildcard_)) auto_wildcard = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_log_enabled)) return Yn.To_str(log_enabled);
|
||||
else if (ctx.Match(k, Invk_log_enabled_)) log_enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_args_default)) return args_default_str;
|
||||
else if (ctx.Match(k, Invk_args_default_)) Args_default_str_(m.ReadStr("v"));
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final String Invk_search_async = "search_async", Invk_notify = "notify", Invk_enabled = "enabled", Invk_enabled_ = "enabled_", Invk_results_max = "results_max", Invk_results_max_ = "results_max_"
|
||||
, Invk_search_mode = "search_mode", Invk_search_mode_ = "search_mode_", Invk_search_mode_list = "search_mode_list"
|
||||
, Invk_all_pages_extend = "all_pages_extend", Invk_all_pages_extend_ = "all_pages_extend_"
|
||||
, Invk_all_pages_min = "all_pages_min", Invk_all_pages_min_ = "all_pages_min_"
|
||||
, Invk_auto_wildcard = "auto_wildcard", Invk_auto_wildcard_ = "auto_wildcard_"
|
||||
, Invk_log_enabled = "log_enabled", Invk_log_enabled_ = "log_enabled_"
|
||||
, Invk_args_default = "args_default", Invk_args_default_ = "args_default_"
|
||||
;
|
||||
private static final String Str_search_mode_search = "Search", Str_search_mode_all_pages_v1 = "AllPages", Str_search_mode_all_pages_v2 = "AllPages_(v2)";
|
||||
public static final byte Tid_search_mode_all_pages_v1 = 0, Tid_search_mode_search = 1, Tid_search_mode_all_pages_v2 = 2;
|
||||
private static KeyVal[] Options_search_mode_list = KeyVal_.Ary(KeyVal_.new_(Str_search_mode_search), KeyVal_.new_(Str_search_mode_all_pages_v1), KeyVal_.new_(Str_search_mode_all_pages_v2));
|
||||
private static byte Search_mode_parse(String v) {
|
||||
if (String_.Eq(v, Str_search_mode_search)) return Tid_search_mode_search;
|
||||
else if (String_.Eq(v, Str_search_mode_all_pages_v1)) return Tid_search_mode_all_pages_v1;
|
||||
else if (String_.Eq(v, Str_search_mode_all_pages_v2)) return Tid_search_mode_all_pages_v2;
|
||||
else throw Err_.new_unhandled(v);
|
||||
}
|
||||
private static String Search_mode_str(byte v) {
|
||||
switch (v) {
|
||||
case Tid_search_mode_search: return Str_search_mode_search;
|
||||
case Tid_search_mode_all_pages_v1: return Str_search_mode_all_pages_v1;
|
||||
case Tid_search_mode_all_pages_v2: return Str_search_mode_all_pages_v2;
|
||||
default: throw Err_.new_unhandled(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.wikis.tdbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_core_tst {
|
||||
// @Before public void Init() {fxt.Clear();} private Xos_search_mgr_fxt fxt = new Xos_search_mgr_fxt();
|
||||
@Test public void Basic() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Test_search_exact("b2", "B2_22", "B2_12", "B2__2");
|
||||
// fxt.Test_search_exact("a" , "A___0");
|
||||
// fxt.Test_search_exact("b1a"); // missing: mid
|
||||
// fxt.Test_search_exact("d"); // missing: end
|
||||
// fxt.Test_search_exact("$"); // missing: bgn
|
||||
// fxt.Test_search_match_bgn("b*", "B3_23", "B2_22", "B1_21", "B3_13", "B2_12", "B1_11", "B3__3", "B2__2", "B1__1");
|
||||
}
|
||||
// @Test public void Page_size() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Search_mgr().Page_mgr().Itms_per_page_(1);
|
||||
// fxt.Test_search("b*", 0, "B3_23");
|
||||
// fxt.Test_search("b*", 1, "B2_22");
|
||||
// fxt.Test_search("b*", 2, "B1_21");
|
||||
// fxt.Test_search("b*", 3, "B3_13");
|
||||
// }
|
||||
// @Test public void Url() {
|
||||
// Xoa_url url = Xoa_url_parser_old.Parse_url(fxt.App(), fxt.Wiki(), "Special:Search/Abc?fulltext=y&xowa_sort=len_desc");
|
||||
// fxt.Search_mgr().Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(Xosrh_rslt_itm_sorter.Tid_len_dsc, fxt.Search_mgr().Args_mgr().Sort_tid());
|
||||
// }
|
||||
// @Test public void Url_arg_title() {// http://en.wikipedia.org/wiki/Special:Search/Earth?fulltext=yes&title=Mars
|
||||
// fxt.Test_url_search_bry("Special:Search?fulltext=y&search=Abc" , "Abc"); // query arg
|
||||
//// fxt.Test_url_search_bry("Special:Search/Abc?fulltext=y" , "Abc"); // leaf
|
||||
// fxt.Test_url_search_bry("Special:Search/Abc?fulltext=y&search=Def" , "Def"); // leaf overrides query arg
|
||||
// }
|
||||
// @Test public void Url_ns() {
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc&ns0=1&ns1=1", "0|1");
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc&ns*=1", "*");
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc", "0");
|
||||
// }
|
||||
// @Test public void Html() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Test_html_by_url("B1", "", String_.Concat_lines_nl
|
||||
// ( "Result '''1''' of '''3''' for '''B1'''<br/>"
|
||||
// , "{|"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=0|<]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=1|>]]"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_sort=len_desc|length]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_sort=title_asc|title]]"
|
||||
// , "|-"
|
||||
// , "| 42 || [[B1 21]]"
|
||||
// , "|-"
|
||||
// , "| 22 || [[B1 11]]"
|
||||
// , "|-"
|
||||
// , "| 2 || [[B1 1]]"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=0|<]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=1|>]]"
|
||||
// , "|}"
|
||||
// ));
|
||||
// }
|
||||
//// @Test public void Page_next() {
|
||||
//// fxt.Init_basic();
|
||||
//// fxt.Search_mgr().Page_size_(1);
|
||||
//// fxt.Test_search(Xows_page__search.Match_tid_all, "B1", 0, "B1 1");
|
||||
//// fxt.Test_search(Xows_page__search.Match_tid_all, "B1", 1, "B1 11");
|
||||
//// }
|
||||
//// @Test public void Misc_url() {
|
||||
//// fxt.Init_basic();
|
||||
//// fxt.Search_mgr().Page_size_(1);
|
||||
//// fxt.Expd_address_page_("Special:Search/B1");
|
||||
//// fxt.Test_search(Xows_page__search.Match_tid_all, "B1", 0, "B1 1");
|
||||
//// }
|
||||
// @Test public void Sort_defaults_to_len_desc() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Search_mgr().Page_mgr().Itms_per_page_(3);
|
||||
// fxt.Test_search2(Xows_page__search.Match_tid_bgn, "b" , 0, Xosrh_rslt_itm_sorter.Tid_ttl_asc , "B1_11", "B1_21", "B1__1"); // sort by name; note that _ sorts after alphabet
|
||||
// fxt.Test_search2(Xows_page__search.Match_tid_bgn, "b" , 1, Xosrh_rslt_itm_sorter.Tid_none , "B2_12", "B2_22", "B2__2"); // sort by name still; next page should not reset
|
||||
// fxt.Test_search2(Xows_page__search.Match_tid_bgn, "b2" , 0, Xosrh_rslt_itm_sorter.Tid_none , "B2_22", "B2_12", "B2__2"); // sort by len desc; new search should reset
|
||||
// }
|
||||
}
|
||||
// class Xos_search_mgr_fxt {
|
||||
// Xoae_app app; Xowe_wiki wiki; Bry_bfr bfr = Bry_bfr.reset_(500); Xows_page__search search_mgr;
|
||||
// public Xoae_app App() {return app;}
|
||||
// public Xowe_wiki Wiki() {return wiki;}
|
||||
// public Xobl_regy_itm regy_itm_(int id, String bgn, String end, int count) {return new Xobl_regy_itm(id, Bry_.new_u8(bgn), Bry_.new_u8(end), count);}
|
||||
// public Xowd_page_itm data_ttl_(int id, String ttl) {return data_ttl_(id, 0, 0, false, 0, ttl);}
|
||||
// public Xowd_page_itm data_ttl_(int id, int fil, int row, boolean redirect, int len, String ttl) {return new Xowd_page_itm().Init(id, Bry_.new_u8(ttl), redirect, len, fil, row);}
|
||||
// public Xowd_page_itm data_id_(int id, String ttl) {return data_id_(id, Xow_ns_.Tid__main, ttl);}
|
||||
// public Xowd_page_itm data_id_(int id, int ns, String ttl) {return new Xowd_page_itm().Id_(id).Ns_id_(ns).Ttl_page_db_(Bry_.new_u8(ttl)).Text_db_id_(0).Text_len_(0);}
|
||||
// public Xobl_search_ttl data_sttl_(String word, params int[] ids) {return new Xobl_search_ttl(Bry_.new_u8(word), data_ttl_word_page_ary_(ids));}
|
||||
// public Xobl_search_ttl_page[] data_ttl_word_page_ary_(params int[] ids) {
|
||||
// int ids_len = ids.length;
|
||||
// Xobl_search_ttl_page[] rv = new Xobl_search_ttl_page[ids_len];
|
||||
// for (int i = 0; i < ids_len; i++) {
|
||||
// int id = ids[i];
|
||||
// rv[i] = new Xobl_search_ttl_page(id, id * 2);
|
||||
// }
|
||||
// return rv;
|
||||
// }
|
||||
// public void Init_regy_site(byte dir_info, params Xobl_regy_itm[] ary) {Init_regy(wiki.Tdb_fsys_mgr().Url_site_reg(dir_info), ary);}
|
||||
// public void Init_regy_ns (String ns_num, byte tid, params Xobl_regy_itm[] ary) {Init_regy(wiki.Tdb_fsys_mgr().Url_ns_reg(ns_num, tid), ary);}
|
||||
// public void Init_regy(Io_url url, Xobl_regy_itm[] ary) {
|
||||
// int ary_len = ary.length;
|
||||
// for (int i = 0; i < ary_len; i++) {
|
||||
// Xobl_regy_itm itm = ary[i];
|
||||
// itm.Srl_save(tmp_bfr);
|
||||
// }
|
||||
// Io_mgr.Instance.SaveFilBfr(url, tmp_bfr);
|
||||
// } private Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
|
||||
// public void Init_data(Io_url fil, params Xobl_data_itm[] ary) {
|
||||
// Xob_xdat_file xdat_file = new Xob_xdat_file();
|
||||
// int ary_len = ary.length;
|
||||
// for (int i = 0; i < ary_len; i++) {
|
||||
// Xobl_data_itm itm = ary[i];
|
||||
// itm.Srl_save(tmp_bfr);
|
||||
// xdat_file.Insert(bfr, tmp_bfr.To_bry_and_clear());
|
||||
// }
|
||||
// xdat_file.Save(fil);
|
||||
// }
|
||||
// public void Init_basic() {
|
||||
// this.Init_regy_ns(wiki.Ns_mgr().Ns_main().Num_str(), Xotdb_dir_info_.Tid_search_ttl, this.regy_itm_(0, "A", "C", 5));
|
||||
// this.Init_data(wiki.Tdb_fsys_mgr().Url_ns_fil(Xotdb_dir_info_.Tid_search_ttl, Xow_ns_.Tid__main, 0)
|
||||
// , this.data_sttl_("a" , 0)
|
||||
// , this.data_sttl_("b1" , 1, 11, 21)
|
||||
// , this.data_sttl_("b2" , 2, 12, 22)
|
||||
// , this.data_sttl_("b3" , 3, 13, 23)
|
||||
// , this.data_sttl_("c" , 4)
|
||||
// );
|
||||
// this.Init_regy_site(Xotdb_dir_info_.Tid_id, this.regy_itm_(0, "A", "C", 11));
|
||||
// this.Init_data(wiki.Tdb_fsys_mgr().Url_site_fil(Xotdb_dir_info_.Tid_id, 0)
|
||||
// , this.data_id_( 0, "A___0")
|
||||
// , this.data_id_( 1, "B1__1")
|
||||
// , this.data_id_( 2, "B2__2")
|
||||
// , this.data_id_( 3, "B3__3")
|
||||
// , this.data_id_( 4, "C___4")
|
||||
// , this.data_id_(11, "B1_11")
|
||||
// , this.data_id_(12, "B2_12")
|
||||
// , this.data_id_(13, "B3_13")
|
||||
// , this.data_id_(21, "B1_21")
|
||||
// , this.data_id_(22, "B2_22")
|
||||
// , this.data_id_(23, "B3_23")
|
||||
// );
|
||||
// search_mgr.Page_mgr().Ns_mgr().Add_all(); // WORKAROUND: xdat fmt does not store ns with search data; pages will be retrieved with ns_id = null; force ns_all (instead of allowing ns_main default);
|
||||
// }
|
||||
// public void Clear() {
|
||||
// Io_mgr.Instance.InitEngine_mem();
|
||||
// app = Xoa_app_fxt.app_();
|
||||
// wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
// search_mgr = wiki.Special_mgr().Page_search();
|
||||
// wiki.Appe().Gui_mgr().Search_suggest_mgr().Args_default_str_("ns*=1"); // WORKAROUND: xdat fmt does not store ns with search data; pages will be retrieved with ns_id = null; force ns_all (instead of allowing ns_main default);
|
||||
// }
|
||||
// public Xows_page__search Search_mgr() {return search_mgr;}
|
||||
// public void Test_url_search_bry(String url_str, String expd) {
|
||||
// Xoa_url url = Xoa_url_parser_old.Parse_url(app, wiki, url_str);
|
||||
// search_mgr.Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(expd, String_.new_u8(search_mgr.Args_mgr().Search_bry()));
|
||||
// }
|
||||
// public void Test_url__ns(String url_str, String expd) {
|
||||
// Xoa_url url = Xoa_url_parser_old.Parse_url(app, wiki, url_str);
|
||||
// search_mgr.Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(expd, String_.new_a7(search_mgr.Args_mgr().Ns_mgr().Xto_hash_key()));
|
||||
// }
|
||||
// public void Test_search_exact(String ttl_str, params String[] expd_ary) {Test_search(ttl_str, 0, expd_ary);}
|
||||
// public void Test_search_match_bgn(String ttl_str, params String[] expd_ary) {Test_search(ttl_str, 0, expd_ary);}
|
||||
// public void Test_search(String ttl_str, int page_idx, params String[] expd_ary) {
|
||||
// byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
// Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b128();
|
||||
// Xosrh_rslt_grp page = search_mgr.Page_mgr().Search(bfr, wiki, ttl_bry, page_idx, search_mgr.Page_mgr());
|
||||
// bfr.Mkr_rls();
|
||||
// Tfds.Eq_ary(expd_ary, Search_itms_to_int_ary(page));
|
||||
// }
|
||||
// public void Test_html_by_url(String ttl_str, String args_str, String expd_html) {
|
||||
// wiki.Init_needed_(false);
|
||||
// byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
// Xoa_ttl ttl = Xoa_ttl.parse(wiki, ttl_bry);
|
||||
// Xoae_page page = Xoae_page.New_test(wiki, ttl);
|
||||
// byte[] url_bry = Bry_.new_a7("http://en.wikipedia.org/wiki/Special:Search/" + ttl_str + args_str);
|
||||
// Xoa_url url = wiki.Appe().Url_parser().Parse(url_bry);
|
||||
// search_mgr.Special_gen(url, page, wiki, ttl);
|
||||
// Tfds.Eq_str_lines(expd_html, String_.new_u8(page.Root().Data_htm()));
|
||||
// }
|
||||
// public void Test_search2(byte match_tid, String ttl_str, int page_idx, byte sort_tid, params String[] expd_ary) {
|
||||
// Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b128();
|
||||
// Xoa_url_parser_old url_parser = new Xoa_url_parser_old();
|
||||
// byte[] url_raw = Bry_.new_a7("Special:Search/" + ttl_str + ((match_tid == Xows_page__search.Match_tid_all) ? "" : "*") + "?fulltext=y" + Xosrh_rslt_itm_sorter.Xto_url_arg(sort_tid) + "&xowa_page_size=1&xowa_page_index=" + page_idx);
|
||||
// Xoa_url url = url_parser.Parse(url_raw);
|
||||
// Xoa_ttl ttl = Xoa_ttl.parse(wiki, url_raw);
|
||||
// Xoae_page page = wiki.Ctx().Page();
|
||||
// search_mgr.Special_gen(url, page, wiki, ttl);
|
||||
// Xosrh_rslt_grp cur_grp = search_mgr.Cur_grp();
|
||||
// bfr.Mkr_rls();
|
||||
// Tfds.Eq_ary(expd_ary, Search_itms_to_int_ary(cur_grp));
|
||||
// }
|
||||
// String[] Search_itms_to_int_ary(Xosrh_rslt_grp page) {
|
||||
// int itms_len = page.Itms_len();
|
||||
// String[] rv = new String[itms_len];
|
||||
// for (int i = 0; i < itms_len; i++) {
|
||||
// Xowd_page_itm itm = page.Itms_get_at(i);
|
||||
// rv[i] = String_.new_u8(itm.Ttl_page_db());
|
||||
// }
|
||||
// return rv;
|
||||
// }
|
||||
// }
|
||||
// interface Xobl_data_itm {
|
||||
// void Srl_save(Bry_bfr bfr);
|
||||
// }
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_page_mgr implements Xosrh_page_mgr_searcher {
|
||||
public int Pages_len() {return pages_ary.length;}
|
||||
public int Itms_bgn() {return itms_bgn;} private int itms_bgn;
|
||||
public int Itms_end() {return itms_end;} private int itms_end;
|
||||
public int Itms_per_page() {return itms_per_page;} public Xosrh_page_mgr Itms_per_page_(int v) {itms_per_page = v; return this;} private int itms_per_page = 100;
|
||||
public byte Sort_tid() {return sort_tid;}
|
||||
public Xosrh_page_mgr Sort_tid_(byte v) {
|
||||
if (sort_tid == v) return this;
|
||||
sort_tid = v;
|
||||
sorter.Tid_(v);
|
||||
prv_search_bry = Bry_.Empty; // reset search
|
||||
return this;
|
||||
} byte sort_tid;
|
||||
private byte[] prv_search_bry = Bry_.Empty, prv_ns_bry = Bry_.Empty;
|
||||
public boolean Prv_search_is_same(byte[] cur_search_bry, byte[] cur_ns_bry) {
|
||||
return Bry_.Eq(cur_ns_bry, prv_ns_bry) && Bry_.Eq(cur_search_bry, prv_search_bry);
|
||||
}
|
||||
private Xosrh_rslt_grp[] pages_ary; List_adp cur_ids = List_adp_.new_();
|
||||
private Xosrh_rslt_itm_sorter sorter = new Xosrh_rslt_itm_sorter();
|
||||
private Xowe_wiki wiki;
|
||||
public Xows_ns_mgr Ns_mgr() {return ns_mgr;} public void Ns_mgr_(Xows_ns_mgr v) {ns_mgr = v;} private Xows_ns_mgr ns_mgr = new Xows_ns_mgr();
|
||||
public Xosrh_rslt_grp Search(Bry_bfr bfr, Xowe_wiki wiki, byte[] search, int page_idx, Xosrh_page_mgr_searcher searcher) {return Search(bfr, wiki, search, page_idx, searcher, Cancelable_.Never);}
|
||||
public Xosrh_rslt_grp Search(Bry_bfr bfr, Xowe_wiki wiki, byte[] search, int page_idx, Xosrh_page_mgr_searcher searcher, Cancelable cancelable) {
|
||||
this.wiki = wiki;
|
||||
Xosrh_rslt_grp rv = null;
|
||||
itms_bgn = page_idx * itms_per_page;
|
||||
itms_end = itms_bgn + itms_per_page;
|
||||
if (Prv_search_is_same(search, ns_mgr.To_hash_key())) { // search is same
|
||||
if (page_idx < pages_ary.length) { // page_idx is in bounds
|
||||
rv = pages_ary[page_idx];
|
||||
if (rv != null) return rv; // page_found; return it;
|
||||
}
|
||||
}
|
||||
else { // search is new; rebuild;
|
||||
List_adp ids = searcher.Parse_search_and_load_ids(cancelable, bfr, ns_mgr, search);
|
||||
Rebuild(cancelable, wiki, ids);
|
||||
prv_search_bry = search;
|
||||
prv_ns_bry = ns_mgr.To_hash_key();
|
||||
}
|
||||
int ids_len = cur_ids.Count();
|
||||
if (itms_end > ids_len) itms_end = ids_len;
|
||||
if (page_idx < 0 || page_idx >= pages_ary.length) return Grp_empty;
|
||||
if ( sort_tid != Xosrh_rslt_itm_sorter.Tid_ttl_asc
|
||||
&& cancelable == Cancelable_.Never // cancelable != Cancelable_.Never for search_suggest
|
||||
&& wiki.Db_mgr().Tid() == gplx.xowa.wikis.dbs.Xodb_mgr_txt.Tid_txt // txt only has search_title fields (page_id, word_id), so it needs to do another load to get page fields; note that sql has page fields already
|
||||
) {
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(cancelable, cur_ids, itms_bgn, itms_end);
|
||||
}
|
||||
rv = new Xosrh_rslt_grp(page_idx);
|
||||
for (int i = itms_bgn; i < itms_end; i++)
|
||||
rv.Itms_add((Xowd_page_itm)cur_ids.Get_at(i));
|
||||
pages_ary[page_idx] = rv;
|
||||
rv.Itms_total_(cur_ids.Count());
|
||||
return rv;
|
||||
}
|
||||
public List_adp Parse_search_and_load_ids(Cancelable cancelable, Bry_bfr bfr, Xows_ns_mgr ns_mgr, byte[] search) {
|
||||
search = wiki.Lang().Case_mgr().Case_build_lower(search, 0, search.length);
|
||||
Xosrh_qry_itm cur_root = Xosrh_parser.Instance.Parse(search);
|
||||
cur_root.Search(cancelable, bfr, search, wiki, itms_per_page, ns_mgr);
|
||||
return cur_root.Matches(search).Ids();
|
||||
}
|
||||
private void Rebuild(Cancelable cancelable, Xowe_wiki wiki, List_adp ids) {
|
||||
int ids_len = ids.Count();
|
||||
int pages_len = ((ids_len - 1) / itms_per_page) + 1; if (pages_len == 0) pages_len = 1;
|
||||
pages_ary = new Xosrh_rslt_grp[pages_len];
|
||||
cur_ids.Clear();
|
||||
for (int i = 0; i < ids_len; i++)
|
||||
cur_ids.Add(ids.Get_at(i));
|
||||
if (sort_tid == Xosrh_rslt_itm_sorter.Tid_ttl_asc) {
|
||||
cur_ids.Sort_by(sorter.Tid_(Xosrh_rslt_itm_sorter.Tid_id));
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(cancelable, cur_ids, 0, ids_len);
|
||||
cur_ids.Sort_by(sorter.Tid_(Xosrh_rslt_itm_sorter.Tid_ttl_asc));
|
||||
}
|
||||
else {
|
||||
cur_ids.Sort_by(sorter.Tid_(Xosrh_rslt_itm_sorter.Tid_len_dsc));
|
||||
}
|
||||
}
|
||||
private static final Xosrh_rslt_grp Grp_empty = new Xosrh_rslt_grp(-1);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
public interface Xosrh_page_mgr_searcher {
|
||||
List_adp Parse_search_and_load_ids(Cancelable cancelable, Bry_bfr bfr, Xows_ns_mgr ns_Mgr, byte[] search);
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.core.encoders.*; import gplx.xowa.wikis.tdbs.*; import gplx.xowa.wikis.tdbs.hives.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
public class Xosrh_page_mgr_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xosrh_page_mgr_fxt fxt = new Xosrh_page_mgr_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Init_itms_per_page_(3).Init_site_ids(10, 20);
|
||||
Xosrh_page_mgr_searcher ids_a = fxt.ids_(10, 17);
|
||||
fxt.Test_search("A", ids_a, 0, Int_.Ary(16, 15, 14));
|
||||
fxt.Test_search("A", ids_a, 1, Int_.Ary(13, 12, 11));
|
||||
fxt.Test_search("A", ids_a, 2, Int_.Ary(10));
|
||||
fxt.Test_search("A", ids_a, 0, Int_.Ary(16, 15, 14));
|
||||
Xosrh_page_mgr_searcher ids_b = fxt.ids_(17, 20);
|
||||
fxt.Init_sort_by_name_(true).Test_search("B", ids_b, 0, Int_.Ary(17, 18, 19));
|
||||
}
|
||||
}
|
||||
class Xosrh_page_mgr_fxt {
|
||||
public Xosrh_page_mgr_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.app_();
|
||||
wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
tmp_bfr = Bry_bfr.reset_(255);
|
||||
page_mgr = new Xosrh_page_mgr();
|
||||
hive_mgr = new Xowd_hive_mgr(wiki, Xotdb_dir_info_.Tid_id);
|
||||
}
|
||||
return this;
|
||||
} private Xoae_app app; Xowe_wiki wiki; Bry_bfr tmp_bfr; Xosrh_page_mgr page_mgr; Xowd_hive_mgr hive_mgr;
|
||||
public Xosrh_page_mgr_fxt Init_site_ids(int bgn, int end) {
|
||||
Xowd_page_itm tmp_itm = new Xowd_page_itm();
|
||||
for (int i = bgn; i < end; i++) {
|
||||
byte[] id_bry = new byte[5]; // NOTE: do not reuse; will break hive_mgr
|
||||
Base85_.Set_bry(i, id_bry, 0, 5);
|
||||
tmp_itm.Ns_id_(Xow_ns_.Tid__main).Init(i, Bry_.To_a7_bry(i, 0), false, 10, 0, i - bgn);
|
||||
Xotdb_page_itm_.Txt_id_save(tmp_bfr, tmp_itm);
|
||||
hive_mgr.Create(id_bry, tmp_bfr.To_bry_and_clear(), null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
// public Xowd_page_itm Set_all(int id, int fil_idx, int row_idx, boolean type_redirect, int itm_len, int ns_id, byte[] ttl) {
|
||||
public Xosrh_page_mgr_fxt Init_sort_by_name_(boolean v) {page_mgr.Sort_tid_(v ? Xosrh_rslt_itm_sorter.Tid_ttl_asc : Xosrh_rslt_itm_sorter.Tid_len_dsc); return this;}
|
||||
public Xosrh_page_mgr_fxt Init_itms_per_page_(int v) {page_mgr.Itms_per_page_(v); return this;}
|
||||
public Xosrh_page_mgr_searcher_mok ids_(int bgn, int end) {
|
||||
List_adp rv = List_adp_.new_();
|
||||
int len = end - bgn;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int itm_id = i + bgn;
|
||||
int itm_len = itm_id;
|
||||
Xowd_page_itm itm = Xowd_page_itm.new_srch(itm_id, itm_len);
|
||||
rv.Add(itm);
|
||||
}
|
||||
return new Xosrh_page_mgr_searcher_mok(rv);
|
||||
}
|
||||
public void Test_search(String search_str, Xosrh_page_mgr_searcher searcher, int page_idx, int[] expd) {
|
||||
byte[] search_bry = Bry_.new_a7(search_str);
|
||||
Xosrh_rslt_grp page = page_mgr.Search(tmp_bfr, wiki, search_bry, page_idx, searcher);
|
||||
Tfds.Eq_ary(expd, Xto_int_ary(page));
|
||||
}
|
||||
int[] Xto_int_ary(Xosrh_rslt_grp page) {
|
||||
int len = page.Itms_len();
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
rv[i] = ((Xowd_page_itm)page.Itms_get_at(i)).Id();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Xosrh_page_mgr_searcher_mok implements Xosrh_page_mgr_searcher {
|
||||
public Xosrh_page_mgr_searcher_mok(List_adp list) {this.list = list;} List_adp list;
|
||||
public List_adp Parse_search_and_load_ids(Cancelable cancelable, Bry_bfr bfr, Xows_ns_mgr ns_mgr, byte[] search) {return list;}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
class Xosrh_parser {
|
||||
public Xosrh_qry_itm Parse(byte[] src) {
|
||||
this.src = src;
|
||||
Xosrh_qry_tkn[] tkns = Xosrh_scanner.Instance.Scan(src);
|
||||
return Parse_itm_or(make_ctx.Init(tkns));
|
||||
} private Xosrh_parser_ctx make_ctx = new Xosrh_parser_ctx(); byte[] src;
|
||||
Xosrh_qry_itm Parse_itm_or(Xosrh_parser_ctx make_ctx) {
|
||||
Xosrh_qry_itm lhs = Parse_itm_and(make_ctx);
|
||||
while (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_or)) {
|
||||
make_ctx.Move_next();
|
||||
Xosrh_qry_itm rhs = Parse_itm_and(make_ctx);
|
||||
lhs = Xosrh_qry_itm.nde_(Xosrh_qry_itm.Tid_or, lhs, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
Xosrh_qry_itm Parse_itm_and(Xosrh_parser_ctx make_ctx) {
|
||||
Xosrh_qry_itm lhs = Parse_itm_not(make_ctx);
|
||||
while (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_and)) {
|
||||
make_ctx.Move_next();
|
||||
Xosrh_qry_itm rhs = Parse_itm_not(make_ctx);
|
||||
lhs = Xosrh_qry_itm.nde_(Xosrh_qry_itm.Tid_and, lhs, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
Xosrh_qry_itm Parse_itm_not(Xosrh_parser_ctx make_ctx) {
|
||||
Xosrh_qry_itm lhs = Parse_itm_leaf(make_ctx);
|
||||
while (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_not)) {
|
||||
make_ctx.Move_next();
|
||||
Xosrh_qry_itm rhs = Parse_itm_leaf(make_ctx);
|
||||
lhs = Xosrh_qry_itm.nde_(Xosrh_qry_itm.Tid_not, null, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
Xosrh_qry_itm Parse_itm_leaf(Xosrh_parser_ctx make_ctx) {
|
||||
if (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_paren_bgn)) {
|
||||
make_ctx.Move_next();
|
||||
Xosrh_qry_itm lhs = Parse_itm_or(make_ctx);
|
||||
if (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_paren_end)) make_ctx.Move_next(); // skip token
|
||||
return lhs;
|
||||
}
|
||||
else if (make_ctx.Cur_tid(Xosrh_qry_tkn.Tid_eos))
|
||||
return Xosrh_qry_itm.Null;
|
||||
else {
|
||||
Xosrh_qry_tkn word_tkn = make_ctx.Move_next();
|
||||
if (word_tkn.Tid() == Xosrh_qry_tkn.Tid_not) {
|
||||
word_tkn = make_ctx.Move_next();
|
||||
if (word_tkn == null) return Xosrh_qry_itm.Null; // occurs in "a -"
|
||||
Xosrh_qry_itm word_itm = Xosrh_qry_itm.word_(src, word_tkn);
|
||||
return Xosrh_qry_itm.nde_(Xosrh_qry_itm.Tid_not, null, word_itm);
|
||||
}
|
||||
else
|
||||
return Xosrh_qry_itm.word_(src, word_tkn);
|
||||
}
|
||||
}
|
||||
public static final Xosrh_parser Instance = new Xosrh_parser(); Xosrh_parser() {}
|
||||
}
|
||||
class Xosrh_parser_ctx {
|
||||
public Xosrh_parser_ctx Init(Xosrh_qry_tkn[] ary) {
|
||||
this.ary = ary;
|
||||
ary_len = ary.length;
|
||||
this.pos = 0;
|
||||
return this;
|
||||
} private Xosrh_qry_tkn[] ary; int pos = 0; int ary_len;
|
||||
public boolean Cur_tid(byte tid) {return pos < ary_len ? tid == ary[pos].Tid(): tid == Xosrh_qry_tkn.Tid_eos;}
|
||||
public Xosrh_qry_tkn Move_next() {
|
||||
Xosrh_qry_tkn rv = null;
|
||||
if (pos < ary_len) rv = ary[pos++];
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.wikis.tdbs.*; import gplx.xowa.wikis.tdbs.hives.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_parser_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xosearch_parser_fxt fxt = new Xosearch_parser_fxt();
|
||||
@Test public void Scan_word() {fxt.Test_scan("abc", "abc");}
|
||||
@Test public void Scan_word_many() {fxt.Test_scan("abc d ef", "abc", "AND", "d", "AND", "ef");}
|
||||
@Test public void Scan_word_symbol() {fxt.Test_scan("a, b", "a", "AND", "b");}
|
||||
@Test public void Scan_and_embedded() {fxt.Test_scan("candy", "candy");} // check that andy does not become "AND" + y
|
||||
@Test public void Scan_and_and() {fxt.Test_scan("a andand", "a", "AND", "andand");} // check that andand is word; note that AND is automatically inserted between consecutive words
|
||||
@Test public void Scan_and_parentheses() {fxt.Test_scan("a and(b)", "a", "and", "(", "b", ")");} // check that ( causes and to be treated as separate word
|
||||
@Test public void Scan_not() {fxt.Test_scan("-abc", "-", "abc");}
|
||||
@Test public void Scan_not_and() {fxt.Test_scan("a -bc", "a", "AND", "-", "bc");} // auto-add AND for -
|
||||
@Test public void Scan_space() {fxt.Test_scan(" a b ", "a", "AND", "b");} // spaces should not generate tkns
|
||||
@Test public void Scan_quote() {fxt.Test_scan("\"abc\"", "abc");}
|
||||
@Test public void Scan_complicated() {fxt.Test_scan("(a AND \"b\") OR -c", "(", "a","AND", "b", ")", "OR", "-", "c");}
|
||||
@Test public void Scan_not_embedded() {
|
||||
fxt.Test_scan ("a-b", "a-b"); // fail if "a", "NOT", "b"
|
||||
fxt.Test_scan_tids ("a-b", Xosrh_qry_tkn.Tid_word_quoted); // symbols in unquoted word should convert word to quotes; EX: a-b -> "a-b"
|
||||
}
|
||||
@Test public void Parse_basic() {fxt.Test_parse("abc", "abc");}
|
||||
@Test public void Parse_and() {fxt.Test_parse("abc AND def", "(abc AND def)");}
|
||||
@Test public void Parse_not() {fxt.Test_parse("-abc", "NOT abc");}
|
||||
@Test public void Parse_many() {fxt.Test_parse("A AND B OR C AND D", "((A AND B) OR (C AND D))");}
|
||||
@Test public void Match() {
|
||||
fxt.Init_match("A", 11, 12, 22);
|
||||
fxt.Init_match("B", 21, 22, 12);
|
||||
fxt.Test_match("A OR B" , 11, 12, 22, 21);
|
||||
fxt.Test_match("A AND B" , 22, 12);
|
||||
fxt.Test_match("A AND -B" , 11);
|
||||
}
|
||||
@Test public void Search() {
|
||||
Xosearch_searcher_fxt fxt = new Xosearch_searcher_fxt().Clear();
|
||||
fxt.Init_search("a1", 11, 12);
|
||||
fxt.Init_search("b1", 21, 22);
|
||||
fxt.Init_search("b2", 26, 27);
|
||||
fxt.Init_search("c1", 31, 12);
|
||||
fxt.Test_search("b1", 21, 22);
|
||||
fxt.Test_search("b*", 21, 22, 26, 27);
|
||||
}
|
||||
}
|
||||
class Xosearch_searcher_fxt {
|
||||
public Xosearch_searcher_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.app_();
|
||||
wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
mgr = new Xowd_hive_mgr(wiki, Xotdb_dir_info_.Tid_search_ttl);
|
||||
tmp_bfr = Bry_bfr.reset_(255);
|
||||
parser = Xosrh_parser.Instance;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
Xoae_app app; Xowe_wiki wiki; Xowd_hive_mgr mgr; Bry_bfr tmp_bfr;
|
||||
Xosrh_parser parser;
|
||||
public void Init_search(String ttl_str, int... ids) {
|
||||
byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
tmp_bfr.Add(ttl_bry);
|
||||
int len = ids.length;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int id = ids[i];
|
||||
tmp_bfr.Add_byte_pipe();
|
||||
tmp_bfr.Add_base85_len_5(id);
|
||||
tmp_bfr.Add_byte(Byte_ascii.Semic);
|
||||
tmp_bfr.Add_base85_len_5(0);
|
||||
}
|
||||
mgr.Create(wiki.Ns_mgr().Ns_main(), ttl_bry, tmp_bfr.To_bry_and_clear(), null);
|
||||
}
|
||||
public void Test_search(String ttl_str, int... expd) {
|
||||
byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
Xosrh_qry_itm qry_root = parser.Parse(ttl_bry);
|
||||
Xows_ns_mgr ns_mgr = new Xows_ns_mgr(); ns_mgr.Add_all(); // WORKAROUND: xdat fmt does not store ns with search data; pages will be retrieved with ns_id = null; force ns_all (instead of allowing ns_main default);
|
||||
qry_root.Search(Cancelable_.Never, tmp_bfr, ttl_bry, wiki, 100, ns_mgr);
|
||||
int[] actl = Xosearch_parser_fxt.Xto_ints(qry_root.Ids());
|
||||
Tfds.Eq_ary(expd, actl);
|
||||
}
|
||||
}
|
||||
class Xosearch_parser_fxt {
|
||||
public Xosearch_parser_fxt Clear() {
|
||||
if (parser == null) {
|
||||
parser = Xosrh_parser.Instance;
|
||||
matches = Ordered_hash_.New_bry();
|
||||
}
|
||||
matches.Clear();
|
||||
return this;
|
||||
} private Xosrh_parser parser; Ordered_hash matches;
|
||||
public void Init_match(String name, int... ids) {
|
||||
int len = ids.length;
|
||||
List_adp id_vals = List_adp_.new_();
|
||||
for (int i = 0; i < len; i++)
|
||||
id_vals.Add(Xowd_page_itm.new_srch(ids[i], 0));
|
||||
matches.Add(Bry_.new_a7(name), id_vals);
|
||||
}
|
||||
public void Test_match(String raw, int... expd) {
|
||||
byte[] src = Bry_.new_a7(raw);
|
||||
Xosrh_qry_itm qry_root = parser.Parse(src);
|
||||
Test_match_assign_ids(src, qry_root);
|
||||
Xosrh_qry_ids matches = qry_root.Matches(src);
|
||||
Tfds.Eq_ary(expd, Xto_ints(matches.Ids()));
|
||||
}
|
||||
public static int[] Xto_ints(List_adp list) {
|
||||
if (list == null) return Int_.Ary_empty;
|
||||
int len = list.Count();
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++)
|
||||
rv[i] = ((Xowd_page_itm)list.Get_at(i)).Id();
|
||||
return rv;
|
||||
}
|
||||
private void Test_match_assign_ids(byte[] src, Xosrh_qry_itm itm) {
|
||||
if (itm.Tid() == Xosrh_qry_itm.Tid_word) {
|
||||
byte[] word = itm.Word();
|
||||
List_adp ids = (List_adp)matches.Get_by(word);
|
||||
itm.Ids_(ids);
|
||||
}
|
||||
else {
|
||||
if (itm.Lhs() != null) Test_match_assign_ids(src, itm.Lhs());
|
||||
if (itm.Rhs() != null) Test_match_assign_ids(src, itm.Rhs());
|
||||
}
|
||||
}
|
||||
public void Test_scan(String raw, String... expd) {
|
||||
byte[] src = Bry_.new_a7(raw);
|
||||
Xosrh_qry_tkn[] actl_itms = Xosrh_scanner.Instance.Scan(src);
|
||||
Tfds.Eq_ary(expd, To_strings(src, actl_itms));
|
||||
}
|
||||
public void Test_scan_tids(String raw, byte... expd) {
|
||||
byte[] src = Bry_.new_a7(raw);
|
||||
Xosrh_qry_tkn[] actl_itms = Xosrh_scanner.Instance.Scan(src);
|
||||
Tfds.Eq_ary(expd, To_tids(actl_itms));
|
||||
}
|
||||
String[] To_strings(byte[] src, Xosrh_qry_tkn[] ary) {
|
||||
int len = ary.length;
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xosrh_qry_tkn tkn = ary[i];
|
||||
rv[i] = String_.new_a7(tkn.Val(src));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
byte[] To_tids(Xosrh_qry_tkn[] ary) {
|
||||
int len = ary.length;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xosrh_qry_tkn tkn = ary[i];
|
||||
rv[i] = tkn.Tid();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Test_parse(String raw, String expd) {
|
||||
byte[] src = Bry_.new_a7(raw);
|
||||
Xosrh_qry_itm qry_root = parser.Parse(src);
|
||||
Tfds.Eq(expd, qry_root.Xto_str(src));
|
||||
}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.dbs.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.bldrs.cmds.texts.*;
|
||||
class Xosrh_qry_itm {
|
||||
public Xosrh_qry_itm(byte tid, byte[] word, Xosrh_qry_itm lhs, Xosrh_qry_itm rhs) {
|
||||
this.tid = tid; this.word = word; this.lhs = lhs; this.rhs = rhs;
|
||||
}
|
||||
public byte Tid() {return tid;} private byte tid;
|
||||
public Xosrh_qry_itm Lhs() {return lhs;} private Xosrh_qry_itm lhs;
|
||||
public Xosrh_qry_itm Rhs() {return rhs;} private Xosrh_qry_itm rhs;
|
||||
public List_adp Ids() {return ids;} public void Ids_(List_adp v) {this.ids = v;} List_adp ids = List_adp_.Noop;
|
||||
public byte[] Word() {return word;} private byte[] word;
|
||||
public String Xto_str(byte[] src) {
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
Xto_str_bld(src, bfr);
|
||||
return bfr.To_str_and_clear();
|
||||
}
|
||||
public Xosrh_qry_ids Matches(byte[] src) {
|
||||
switch (tid) {
|
||||
case Xosrh_qry_itm.Tid_word:
|
||||
case Xosrh_qry_itm.Tid_word_quote:
|
||||
return new Xosrh_qry_ids(false, ids);
|
||||
case Xosrh_qry_itm.Tid_not: Xosrh_qry_ids rv = rhs.Matches(src); return rv.Not_(!rv.Not());
|
||||
case Xosrh_qry_itm.Tid_or:
|
||||
case Xosrh_qry_itm.Tid_and:
|
||||
List_adp merged = Evaluate(src, tid == Xosrh_qry_itm.Tid_and, lhs, rhs);
|
||||
return new Xosrh_qry_ids(false, merged);
|
||||
case Xosrh_qry_itm.Tid_null: return Xosrh_qry_ids.Null;
|
||||
default: throw Err_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
private static List_adp Search_word(Xowe_wiki wiki, Cancelable cancelable, Bry_bfr tmp_bfr, Xows_ns_mgr ns_mgr, byte[] search_word, int results_max) {
|
||||
List_adp found = List_adp_.new_();
|
||||
byte wiki_db_tid = wiki.Db_mgr().Tid();
|
||||
if (wiki_db_tid == Xodb_mgr_sql.Tid_sql
|
||||
&& wiki.Appe().Gui_mgr().Search_suggest_mgr().Auto_wildcard()) { // HACK: auto-asterisk words for sqlite; DATE:2013-09-05
|
||||
if (!Bry_.Has_at_end(search_word, new byte[] {Byte_ascii.Star}))
|
||||
search_word = Bry_.Add(search_word, Byte_ascii.Star);
|
||||
if (!Bry_.Has_at_bgn(search_word, new byte[] {Byte_ascii.Star}))
|
||||
search_word = Bry_.Add(Byte_ascii.Star, search_word);
|
||||
}
|
||||
wiki.Db_mgr().Load_mgr().Load_search(cancelable, found, search_word, results_max);
|
||||
List_adp rv = List_adp_.new_();
|
||||
int found_len = found.Count();
|
||||
for (int i = 0; i < found_len; i++) {
|
||||
Xowd_page_itm page = (Xowd_page_itm)found.Get_at(i);
|
||||
if ( ns_mgr.Has(page.Ns_id())
|
||||
|| wiki_db_tid == Xodb_mgr_txt.Tid_txt) // xdat does not store ns, so ns will always be null; no choice but to bring back all results; DATE:2013-11-14
|
||||
rv.Add(page);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Search(Cancelable cancelable, Bry_bfr tmp_bfr, byte[] src, Xowe_wiki wiki, int results_max, Xows_ns_mgr ns_mgr) {
|
||||
if (cancelable.Canceled()) return;
|
||||
switch (tid) {
|
||||
case Xosrh_qry_itm.Tid_null: return;
|
||||
case Xosrh_qry_itm.Tid_word:
|
||||
ids = Search_word(wiki, cancelable, tmp_bfr, ns_mgr, word, results_max);
|
||||
break;
|
||||
case Xosrh_qry_itm.Tid_word_quote:
|
||||
Ordered_hash tmp_search_list = Ordered_hash_.New();
|
||||
byte[][] words = gplx.xowa.bldrs.cmds.texts.Xob_search_base.Split_ttl_into_words(wiki.Lang(), tmp_search_list, tmp_bfr, word);
|
||||
int words_len = words.length;
|
||||
List_adp prv_list = null;
|
||||
for (int i = 0; i < words_len; i++) {
|
||||
if (cancelable.Canceled()) return;
|
||||
List_adp cur_list = Search_word(wiki, cancelable, tmp_bfr, ns_mgr, words[i], results_max);
|
||||
if (prv_list == null) // 1st list; just set to cur_list
|
||||
prv_list = cur_list;
|
||||
else { // nth list; AND to prv_list; "A B" should find all titles with "A AND B"
|
||||
prv_list = Evaluate(word, true, prv_list, false, cur_list, false);
|
||||
}
|
||||
}
|
||||
List_adp tmp_ids = prv_list;
|
||||
int ids_len = tmp_ids.Count();
|
||||
if (ids_len == 0) return;
|
||||
if (cancelable.Canceled()) return;
|
||||
wiki.Db_mgr().Load_mgr().Load_by_ids(cancelable, tmp_ids, 0, ids_len);
|
||||
if (cancelable.Canceled()) return;
|
||||
ids = List_adp_.new_();
|
||||
for (int i = 0; i < ids_len; i++) {
|
||||
Xowd_page_itm itm = (Xowd_page_itm)tmp_ids.Get_at(i);
|
||||
byte[] itm_ttl = itm.Ttl_page_db();
|
||||
itm_ttl = wiki.Lang().Case_mgr().Case_build_lower(itm_ttl, 0, itm_ttl.length); // lowercase ttl (since all search words are lower-cased)
|
||||
itm_ttl = Bry_.Replace(itm_ttl, Byte_ascii.Underline, Byte_ascii.Space); // replace _ with " " (assume user will use spaces in search term)
|
||||
if (Bry_find_.Find_fwd(itm_ttl, word) != Bry_find_.Not_found)
|
||||
ids.Add(itm);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (lhs != null) lhs.Search(cancelable, tmp_bfr, src, wiki, results_max, ns_mgr);
|
||||
if (rhs != null) rhs.Search(cancelable, tmp_bfr, src, wiki, results_max, ns_mgr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
static final byte Evaluate_tid_null = 0, Evaluate_tid_and = 1, Evaluate_tid_or = 2, Evaluate_tid_not_and = 3;
|
||||
List_adp Evaluate(byte[] src, boolean join_tid_is_and, Xosrh_qry_itm lhs, Xosrh_qry_itm rhs) {
|
||||
Xosrh_qry_ids lhs_grp = lhs.Matches(src), rhs_grp = rhs.Matches(src);
|
||||
boolean lhs_not = lhs_grp.Not(), rhs_not = rhs_grp.Not();
|
||||
List_adp lhs_list = lhs_grp.Ids(), rhs_list = rhs_grp.Ids();
|
||||
if (lhs_not && rhs_not) return Evaluate_not_found("NOT cannot be applied to both lists: lhs:~{0} rhs:~{1}", lhs.Xto_str(src), rhs.Xto_str(src));
|
||||
return Evaluate(src, join_tid_is_and, lhs_list, lhs_not, rhs_list, rhs_not);
|
||||
}
|
||||
/*
|
||||
AND,0 nots: hash a; iterate cur_b and add if in a
|
||||
OR ,0 nots; hash a; add a; iterate cur_b and add if not in a
|
||||
AND,1 nots; hash notted; iterate comp and add only if not in notted; (a,cur_b,c) AND NOT (cur_b)
|
||||
AND,2 nots; fail; NOT xq AND NOT qx will yield all titles
|
||||
OR ,2 nots; fail; NOT xq OR NOT qx will yield all titles
|
||||
OR ,1 nots; fail; (a, cur_b, c, d) OR NOT (xq) will yield all titles
|
||||
*/
|
||||
List_adp Evaluate(byte[] src, boolean join_tid_is_and, List_adp lhs_list, boolean lhs_not, List_adp rhs_list, boolean rhs_not) {
|
||||
List_adp list_to_hash = null, list_to_comp = null; int len = 0;
|
||||
byte tid = Evaluate_tid_null;
|
||||
List_adp rv = List_adp_.new_();
|
||||
if (lhs_not || rhs_not) {
|
||||
if (!join_tid_is_and)
|
||||
return Evaluate_not_found("NOT cannot be applied with OR: lhs:~{0} rhs:~{1}", lhs.Xto_str(src), rhs.Xto_str(src));
|
||||
if (lhs_not) {
|
||||
list_to_hash = lhs_list;
|
||||
list_to_comp = rhs_list;
|
||||
}
|
||||
else {
|
||||
list_to_hash = rhs_list;
|
||||
list_to_comp = lhs_list;
|
||||
}
|
||||
tid = Evaluate_tid_not_and;
|
||||
}
|
||||
else {
|
||||
tid = join_tid_is_and ? Evaluate_tid_and : Evaluate_tid_or;
|
||||
boolean rhs_is_smaller = rhs_list.Count() < lhs_list.Count();
|
||||
if (rhs_is_smaller) {
|
||||
list_to_hash = rhs_list;
|
||||
list_to_comp = lhs_list;
|
||||
}
|
||||
else {
|
||||
list_to_hash = lhs_list;
|
||||
list_to_comp = rhs_list;
|
||||
}
|
||||
}
|
||||
len = list_to_hash.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xowd_page_itm id = (Xowd_page_itm)list_to_hash.Get_at(i);
|
||||
try {
|
||||
if (!tmp_hash.Has(id.Id_val())) tmp_hash.Add(id.Id_val(), id);
|
||||
} catch (Exception e) {Err_.Noop(e); tmp_hash.Clear(); return List_adp_.Noop;} // handle error in case of threading issues; must clear tmp_hash else will accumulate;
|
||||
if (tid == Evaluate_tid_or)
|
||||
rv.Add(id);
|
||||
}
|
||||
len = list_to_comp.Count();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Xowd_page_itm id = (Xowd_page_itm)list_to_comp.Get_at(i);
|
||||
boolean exists = tmp_hash.Has(id.Id_val());
|
||||
switch (tid) {
|
||||
case Evaluate_tid_and: // iterate comp and add if in a; EX: (a,cur_b,c) AND (a,d); add a
|
||||
if (exists) rv.Add(id);
|
||||
break;
|
||||
case Evaluate_tid_or: // iterate comp and add if not in a; EX: (a,cur_b,c) OR (a,d); add d
|
||||
case Evaluate_tid_not_and: // iterate comp and add only if not in notted; (a,cur_b,c) AND NOT (cur_b); add a, c
|
||||
if (!exists)
|
||||
rv.Add(id);
|
||||
break;
|
||||
case Evaluate_tid_null: default:
|
||||
throw Err_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
tmp_hash.Clear();
|
||||
return rv;
|
||||
} static Ordered_hash tmp_hash = Ordered_hash_.New();
|
||||
List_adp Evaluate_not_found(String msg, Object... args) {
|
||||
return null;
|
||||
}
|
||||
public void Xto_str_bld(byte[] src, Bry_bfr bfr) {
|
||||
switch (tid) {
|
||||
case Xosrh_qry_itm.Tid_word: bfr.Add(word); break;
|
||||
case Xosrh_qry_itm.Tid_not: bfr.Add(Bry_not); rhs.Xto_str_bld(src, bfr); break;
|
||||
case Xosrh_qry_itm.Tid_or:
|
||||
case Xosrh_qry_itm.Tid_and:
|
||||
bfr.Add_byte(Byte_ascii.Paren_bgn);
|
||||
lhs.Xto_str_bld(src, bfr);
|
||||
bfr.Add(tid == Xosrh_qry_itm.Tid_or ? Bry_or : Bry_and);
|
||||
rhs.Xto_str_bld(src, bfr);
|
||||
bfr.Add_byte(Byte_ascii.Paren_end);
|
||||
break;
|
||||
case Xosrh_qry_itm.Tid_null: break;
|
||||
default: throw Err_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
public static final byte Tid_null = 0, Tid_root = 1, Tid_word = 2, Tid_word_quote = 3, Tid_not = 4, Tid_or = 5, Tid_and = 6;
|
||||
public static byte[] Bry_not = Bry_.new_a7("NOT "), Bry_and = Bry_.new_a7(" AND "), Bry_or = Bry_.new_a7(" OR ");
|
||||
public static final Xosrh_qry_itm Null = new Xosrh_qry_itm(Tid_null, null, null, null);
|
||||
public static Xosrh_qry_itm nde_(byte tid, Xosrh_qry_itm lhs, Xosrh_qry_itm rhs) {return new Xosrh_qry_itm(tid, null, lhs, rhs);}
|
||||
public static Xosrh_qry_itm word_(byte[] src, Xosrh_qry_tkn word_tkn) {
|
||||
byte tid = word_tkn.Tid() == Xosrh_qry_tkn.Tid_word ? Xosrh_qry_itm.Tid_word : Xosrh_qry_itm.Tid_word_quote;
|
||||
return new Xosrh_qry_itm(tid, word_tkn.Val(src), null, null);
|
||||
}
|
||||
}
|
||||
class Xosrh_qry_ids {
|
||||
public Xosrh_qry_ids(boolean not, List_adp ids) {this.not = not; this.ids = ids;}
|
||||
public boolean Not() {return not;} public Xosrh_qry_ids Not_(boolean v) {not = v; return this;} private boolean not;
|
||||
public List_adp Ids() {return ids;} public Xosrh_qry_ids Ids_(List_adp v) {ids = v; return this;} List_adp ids = List_adp_.Noop;
|
||||
public static final Xosrh_qry_ids Null = new Xosrh_qry_ids(false, List_adp_.Noop);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_rslt_grp {
|
||||
public Xosrh_rslt_grp(int idx) {this.idx = idx;} private Xowd_page_itm[] itms = Xowd_page_itm.Ary_empty;
|
||||
public int Idx() {return idx;} private int idx;
|
||||
public int Itms_len() {return itms_len;} private int itms_len; int itms_max;
|
||||
public int Itms_total() {return itms_total;} public Xosrh_rslt_grp Itms_total_(int v) {itms_total = v; return this;} private int itms_total;
|
||||
public Xowd_page_itm Itms_get_at(int i) {return itms[i];}
|
||||
public void Itms_add(Xowd_page_itm itm) {
|
||||
int new_itms_len = itms_len + 1;
|
||||
if (new_itms_len > itms_max) {
|
||||
itms_max = itms_max == 0 ? 2 : itms_max * 2;
|
||||
itms = (Xowd_page_itm[])Array_.Resize(itms, itms_max);
|
||||
}
|
||||
itms[itms_len] = itm;
|
||||
itms_len = new_itms_len;
|
||||
}
|
||||
public boolean Itms_full() {return itms_len >= itms_max;}
|
||||
public void Itms_clear() {
|
||||
for (int i = 0; i < itms_len; i++)
|
||||
itms[i] = null;
|
||||
itms = Xowd_page_itm.Ary_empty;
|
||||
itms_len = itms_max = 0;
|
||||
}
|
||||
public void Itms_sort(Xowd_page_itm_sorter sorter) {Array_.Sort(itms, sorter);}
|
||||
public static final Xosrh_rslt_grp[] Ary_empty = new Xosrh_rslt_grp[0];
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xosrh_rslt_itm_sorter implements gplx.core.lists.ComparerAble {
|
||||
public byte Tid() {return tid;} public Xosrh_rslt_itm_sorter Tid_(byte v) {tid = v; return this;} private byte tid = Tid_len_dsc;
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xowd_page_itm lhs = (Xowd_page_itm)lhsObj;
|
||||
Xowd_page_itm rhs = (Xowd_page_itm)rhsObj;
|
||||
if (lhs == null || rhs == null || tid == Tid_none) return CompareAble_.Same;
|
||||
// else if (lhs == null) return CompareAble_.Less;
|
||||
// else if (rhs == null) return CompareAble_.More;
|
||||
else {
|
||||
switch (tid) {
|
||||
case Tid_len_dsc: return Int_.Compare(lhs.Text_len(), rhs.Text_len()) * -1;
|
||||
case Tid_ttl_asc: return Bry_.Compare(lhs.Ttl_page_db(), rhs.Ttl_page_db());
|
||||
case Tid_id: return Int_.Compare(lhs.Id(), rhs.Id());
|
||||
default: throw Err_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
public static final byte Tid_none = 0, Tid_len_dsc = 1, Tid_ttl_asc = 2, Tid_id = 3;
|
||||
public static byte parse(String v) {
|
||||
if (String_.Eq(v, "none")) return Tid_none;
|
||||
else if (String_.Eq(v, "len_desc")) return Tid_len_dsc;
|
||||
else if (String_.Eq(v, "title_asc")) return Tid_ttl_asc;
|
||||
else throw Err_.new_unhandled(v);
|
||||
}
|
||||
public static String Xto_url_arg(byte v) {
|
||||
switch (v) {
|
||||
case Tid_none: return "";
|
||||
case Tid_len_dsc: return "&xowa_sort=len_desc";
|
||||
case Tid_ttl_asc: return "&xowa_sort=title_asc";
|
||||
default: throw Err_.new_unhandled(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.core.btries.*;
|
||||
class Xosrh_scanner {
|
||||
List_adp tkns = List_adp_.new_(); byte[] src; int src_len; int pos; int txt_bgn;
|
||||
public Xosrh_qry_tkn[] Scan(byte[] src) {
|
||||
this.src = src; this.src_len = src.length;
|
||||
tkns.Clear(); pos = 0; txt_bgn = -1;
|
||||
while (pos < src_len) {
|
||||
byte cur_b = src[pos];
|
||||
Object cur_obj = trie.Match_bgn_w_byte(cur_b, src, pos, src_len);
|
||||
if (cur_obj == null) { // text character
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
++pos;
|
||||
}
|
||||
else { // AND, OR, (, ), -, \s, "
|
||||
int pos_end = trie.Match_pos();
|
||||
byte cur_tid = ((Byte_obj_val)cur_obj).Val();
|
||||
if (Cur_join_is_word(cur_tid, pos_end)) continue;
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_word, txt_bgn, pos);
|
||||
txt_bgn = -1;
|
||||
}
|
||||
switch (cur_tid) {
|
||||
case Xosrh_qry_tkn.Tid_space: // discard spaces
|
||||
pos = Bry_find_.Find_fwd_while(src, pos, src_len, Byte_ascii.Space);
|
||||
break;
|
||||
case Xosrh_qry_tkn.Tid_quote: // find end quote and add as word
|
||||
int quote_bgn = pos + 1;
|
||||
int quote_end = Bry_find_.Find_fwd(src, Byte_ascii.Quote, quote_bgn, src_len);
|
||||
if (quote_end == Bry_find_.Not_found) throw Err_.new_wo_type("could not find end quote", "src", String_.new_u8(src));
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_word_quoted, quote_bgn, quote_end);
|
||||
pos = quote_end + 1; // +1 to place after quote
|
||||
break;
|
||||
case Xosrh_qry_tkn.Tid_not:
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_not, pos, pos_end);
|
||||
pos = pos_end;
|
||||
break;
|
||||
case Xosrh_qry_tkn.Tid_paren_bgn: case Xosrh_qry_tkn.Tid_paren_end:
|
||||
case Xosrh_qry_tkn.Tid_and: case Xosrh_qry_tkn.Tid_or:
|
||||
tkns.Add(new_tkn_(cur_tid, pos, pos_end));
|
||||
pos = pos_end;
|
||||
break;
|
||||
default: throw Err_.new_unhandled(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_word, txt_bgn, pos);
|
||||
txt_bgn = -1;
|
||||
}
|
||||
return (Xosrh_qry_tkn[])tkns.To_ary_and_clear(Xosrh_qry_tkn.class);
|
||||
}
|
||||
boolean Cur_join_is_word(byte cur_tid, int pos_end) { // extra logic to handle and / or occuring in unquoted strings; EX: random; for
|
||||
switch (cur_tid) {
|
||||
default: return false; // only look at AND, OR, -
|
||||
case Xosrh_qry_tkn.Tid_and: case Xosrh_qry_tkn.Tid_or: case Xosrh_qry_tkn.Tid_not:
|
||||
break;
|
||||
}
|
||||
boolean join_is_word = true;
|
||||
if (txt_bgn == -1) { // no pending word;
|
||||
if (cur_tid == Xosrh_qry_tkn.Tid_not) return false; // NOT is only operator if no pending tkn; EX: -abc -> NOT abc; a-b -> a-b
|
||||
byte nxt_b = pos_end < src_len ? src[pos_end] : Byte_ascii.Null;
|
||||
Object nxt_obj = trie.Match_bgn_w_byte(nxt_b, src, pos_end, src_len);
|
||||
if (nxt_obj == null) // next tkn is text; join must be word
|
||||
join_is_word = true;
|
||||
else { // next tkn is tkn
|
||||
byte nxt_tid = ((Byte_obj_val)nxt_obj).Val();
|
||||
switch (nxt_tid) {
|
||||
case Xosrh_qry_tkn.Tid_space: case Xosrh_qry_tkn.Tid_quote:
|
||||
case Xosrh_qry_tkn.Tid_paren_bgn: case Xosrh_qry_tkn.Tid_paren_end:
|
||||
join_is_word = false; // next tkn is sym; and/or is not word; EX: a AND ; a AND"b"; a AND(b)
|
||||
break;
|
||||
case Xosrh_qry_tkn.Tid_not: case Xosrh_qry_tkn.Tid_and: case Xosrh_qry_tkn.Tid_or:
|
||||
join_is_word = true; // next tkn is and or not; and/or is word; EX: andor; oror; or-abc;
|
||||
break;
|
||||
default: throw Err_.new_unhandled(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // pending word; cur join must be word; EX: "grand": "and" invoked and "gr" pending
|
||||
join_is_word = true;
|
||||
}
|
||||
if (join_is_word) {
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
pos = pos_end;
|
||||
return true;
|
||||
}
|
||||
if (txt_bgn != -1) {
|
||||
Tkns_add_word(Xosrh_qry_tkn.Tid_word, txt_bgn, pos); // create word
|
||||
txt_bgn = -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void Tkns_add_word(byte tid, int src_bgn, int src_end) {
|
||||
if (tkns.Count() > 0) { // at least 1 tkn
|
||||
Xosrh_qry_tkn last_tkn = (Xosrh_qry_tkn)tkns.Get_at_last();
|
||||
if (last_tkn.Tid() == Xosrh_qry_tkn.Tid_word) // previous tkn is not word; auto "AND" words; EX: A B -> A AND B
|
||||
tkns.Add(Xosrh_qry_tkn.new_bry_(Xosrh_qry_tkn.Tid_and, Bry_and));
|
||||
}
|
||||
if (tid == Xosrh_qry_tkn.Tid_word) { // if word has symbol, convert to quoted; EX: a-b should become "a-b"; otherwise searcher would search for a single word a-b
|
||||
byte[] cur_word = Bry_.Mid(src, src_bgn, src_end);
|
||||
byte[][] words = gplx.xowa.bldrs.cmds.texts.Xob_search_base.Split_ttl_into_words(null, tmp_list, tmp_bfr, cur_word);
|
||||
int words_len = words.length;
|
||||
if (words_len == 1 && !Bry_.Eq(words[0], cur_word) && Bry_find_.Find_fwd(cur_word, Byte_ascii.Star) == -1) {
|
||||
tkns.Add(Xosrh_qry_tkn.new_bry_(tid, words[0]));
|
||||
return;
|
||||
}
|
||||
if (words.length > 1)
|
||||
tid = Xosrh_qry_tkn.Tid_word_quoted;
|
||||
}
|
||||
tkns.Add(new_tkn_(tid, src_bgn, src_end));
|
||||
}
|
||||
Ordered_hash tmp_list = Ordered_hash_.New(); Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
Xosrh_qry_tkn new_tkn_(byte tid, int val_bgn, int val_end) {return Xosrh_qry_tkn.new_pos_(tid, val_bgn, val_end);}
|
||||
private static byte[] Bry_and = Bry_.new_a7("AND");
|
||||
private static final Btrie_slim_mgr trie = Btrie_slim_mgr.ci_a7()// NOTE:ci.ascii:OR / AND only
|
||||
.Add_str_byte(" ", Xosrh_qry_tkn.Tid_space)
|
||||
.Add_str_byte("\"", Xosrh_qry_tkn.Tid_quote)
|
||||
.Add_str_byte("-", Xosrh_qry_tkn.Tid_not)
|
||||
.Add_str_byte("(", Xosrh_qry_tkn.Tid_paren_bgn)
|
||||
.Add_str_byte(")", Xosrh_qry_tkn.Tid_paren_end)
|
||||
.Add_str_byte("or", Xosrh_qry_tkn.Tid_or)
|
||||
.Add_str_byte("and", Xosrh_qry_tkn.Tid_and);
|
||||
public static final Xosrh_scanner Instance = new Xosrh_scanner(); Xosrh_scanner() {}
|
||||
}
|
||||
class Xosrh_qry_tkn {
|
||||
Xosrh_qry_tkn(byte tid, int val_bgn, int val_end, byte[] val_bry) {this.tid = tid; this.val_bgn = val_bgn; this.val_end = val_end; this.val_bry = val_bry;}
|
||||
public byte Tid() {return tid;} private byte tid;
|
||||
int val_bgn = -1;
|
||||
int val_end = -1;
|
||||
byte[] val_bry;
|
||||
public byte[] Val(byte[] src) {return val_bry == null ? Bry_.Mid(src, val_bgn, val_end) : val_bry;}
|
||||
public static Xosrh_qry_tkn new_pos_(byte tid, int val_bgn, int val_end) {return new Xosrh_qry_tkn(tid, val_bgn, val_end, null);}
|
||||
public static Xosrh_qry_tkn new_bry_(byte tid, byte[] val_bry) {return new Xosrh_qry_tkn(tid, -1, -1, val_bry);}
|
||||
public static final byte Tid_root = 1, Tid_word = 2, Tid_word_quoted = 3, Tid_space = 4, Tid_quote = 5, Tid_not = 6, Tid_paren_bgn = 7, Tid_paren_end = 8, Tid_or = 9, Tid_and = 10, Tid_eos = 11;
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.langs.*;
|
||||
import gplx.xowa.wikis.domains.*; import gplx.xowa.wikis.domains.crts.*;
|
||||
class Xow_domain_sorter__manual implements gplx.core.lists.ComparerAble {
|
||||
private final Xow_domain_itm cur_domain;
|
||||
private final Xow_domain_crt_itm[] ary; private final int ary_len;
|
||||
public Xow_domain_sorter__manual(Xow_domain_itm cur_domain, Xow_domain_crt_itm[] ary) {
|
||||
this.cur_domain = cur_domain; this.ary = ary; this.ary_len = ary.length;
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain_itm lhs = (Xow_domain_itm)lhsObj;
|
||||
Xow_domain_itm rhs = (Xow_domain_itm)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs);
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs);
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(lhs.Domain_bry(), rhs.Domain_bry());
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(Xow_domain_itm domain) {
|
||||
int sort_idx = domain.Sort_idx(); if (sort_idx != -1) return sort_idx;
|
||||
sort_idx = Int_.Max_value;
|
||||
for (int i = 0; i < ary_len; ++i) {
|
||||
Xow_domain_crt_itm crt = ary[i];
|
||||
if (crt.Matches(cur_domain, domain)) {sort_idx = i; break;}
|
||||
}
|
||||
domain.Sort_idx_(sort_idx);
|
||||
return sort_idx;
|
||||
}
|
||||
public static void Sort(Xow_domain_sorter__manual sorter, Xow_domain_itm[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
ary[i].Sort_idx_(-1);
|
||||
Array_.Sort(ary, sorter);
|
||||
}
|
||||
}
|
||||
class Xow_domain_sorter__manual_tid implements gplx.core.lists.ComparerAble {
|
||||
private final Hash_adp sort_hash = Hash_adp_.new_(); private final Int_obj_ref sort_key = Int_obj_ref.neg1_();
|
||||
public Xow_domain_sorter__manual_tid(int[] id_ary) {
|
||||
int len = id_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int id_itm = id_ary[i];
|
||||
sort_hash.Add_if_dupe_use_nth(Int_obj_ref.new_(id_itm), Int_obj_ref.new_(i));
|
||||
}
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain_itm lhs = (Xow_domain_itm)lhsObj;
|
||||
Xow_domain_itm rhs = (Xow_domain_itm)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs.Domain_type_id());
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs.Domain_type_id());
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(Xow_domain_tid_.Get_type_as_bry(lhs.Domain_type_id()), Xow_domain_tid_.Get_type_as_bry(rhs.Domain_type_id()));
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(int tid) {
|
||||
Object o = sort_hash.Get_by(sort_key.Val_(tid));
|
||||
return o == null ? -1 : ((Int_obj_ref)o).Val();
|
||||
}
|
||||
public static Xow_domain_sorter__manual_tid new_(byte[]... id_brys) {
|
||||
int len = id_brys.length;
|
||||
int[] id_ints = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] id_bry = id_brys[i];
|
||||
int id_int = Xow_domain_tid_.Get_type_as_tid(id_bry);
|
||||
id_ints[i] = id_int;
|
||||
}
|
||||
return new Xow_domain_sorter__manual_tid(id_ints);
|
||||
}
|
||||
}
|
||||
class Xow_domain_sorter__manual_lang implements gplx.core.lists.ComparerAble {
|
||||
private final Hash_adp sort_hash = Hash_adp_.new_(); private final Int_obj_ref sort_key = Int_obj_ref.neg1_();
|
||||
public Xow_domain_sorter__manual_lang(int[] id_ary) {
|
||||
int len = id_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int id_int = id_ary[i];
|
||||
sort_hash.Add_if_dupe_use_nth(Int_obj_ref.new_(id_int), Int_obj_ref.new_(i));
|
||||
}
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain_itm lhs = (Xow_domain_itm)lhsObj;
|
||||
Xow_domain_itm rhs = (Xow_domain_itm)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs.Lang_actl_uid());
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs.Lang_actl_uid());
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(lhs.Lang_actl_key(), rhs.Lang_actl_key());
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(int tid) {
|
||||
Object o = sort_hash.Get_by(sort_key.Val_(tid));
|
||||
return o == null ? -1 : ((Int_obj_ref)o).Val();
|
||||
}
|
||||
public static Xow_domain_sorter__manual_lang new_(byte[]... id_brys) {
|
||||
int len = id_brys.length;
|
||||
int[] id_ints = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] id_bry = id_brys[i];
|
||||
int id_int = Xol_lang_stub_.Get_by_key_or_intl(id_bry).Id();
|
||||
id_ints[i] = id_int;
|
||||
}
|
||||
return new Xow_domain_sorter__manual_lang(id_ints);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.core.net.*;
|
||||
class Xows_arg_mgr {
|
||||
private final Xows_paging_parser paging_parser = new Xows_paging_parser();
|
||||
public Xows_ns_mgr Ns_mgr() {return ns_mgr;} private final Xows_ns_mgr ns_mgr = new Xows_ns_mgr();
|
||||
public byte[] Search_bry() {return search_bry;} private byte[] search_bry;
|
||||
public int Paging_idx() {return paging_idx;} private int paging_idx;
|
||||
public byte Sort_tid() {return sort_tid;} private byte sort_tid;
|
||||
public byte[] Cancel() {return cancel;} private byte[] cancel;
|
||||
public Xows_paging_itm[] Paging_itms() {return paging_itms;} private Xows_paging_itm[] paging_itms;
|
||||
public Xows_arg_mgr Search_bry_(byte[] v) {search_bry = v; return this;}
|
||||
public Xows_arg_mgr Clear() {
|
||||
ns_mgr.Clear();
|
||||
this.search_bry = null;
|
||||
this.paging_idx = 0;
|
||||
this.sort_tid = Xosrh_rslt_itm_sorter.Tid_none;
|
||||
this.cancel = null;
|
||||
return this;
|
||||
}
|
||||
public void Parse(Gfo_qarg_itm[] arg_ary) {
|
||||
if (arg_ary == null) return;
|
||||
int len = arg_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_qarg_itm arg = arg_ary[i];
|
||||
byte[] key = arg.Key_bry();
|
||||
Object tid = url_args.Get_by(key);
|
||||
if (tid != null) {
|
||||
switch (((Byte_obj_val)tid).Val()) {
|
||||
case Arg_search: this.search_bry = Bry_.Replace(arg.Val_bry(), Byte_ascii.Plus, Byte_ascii.Space); break;
|
||||
case Arg_page_idx: this.paging_idx = Bry_.To_int_or(arg.Val_bry(), 0); break;
|
||||
case Arg_sort: this.sort_tid = Xosrh_rslt_itm_sorter.parse(String_.new_a7(arg.Val_bry())); break;
|
||||
case Arg_cancel: this.cancel = arg.Val_bry(); break;
|
||||
case Arg_paging: this.paging_itms = paging_parser.Parse(arg.Val_bry()); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (Bry_.Has_at_bgn(key, Ns_bry)) // check for ns*; EX: &ns0=1&ns8=1; NOTE: lowercase only
|
||||
ns_mgr.Add_by_parse(key, arg.Val_bry());
|
||||
}
|
||||
}
|
||||
ns_mgr.Add_main_if_empty();
|
||||
}
|
||||
private static final byte Arg_search = 0, Arg_page_idx = 1, Arg_sort = 2, Arg_cancel = 3, Arg_paging = 4;
|
||||
private static byte[] Ns_bry = Bry_.new_a7("ns");
|
||||
public static final byte[]
|
||||
Arg_bry_page_index = Bry_.new_a7("xowa_page_index")
|
||||
, Arg_bry_cancel = Bry_.new_a7("cancel")
|
||||
;
|
||||
private static final Hash_adp_bry url_args = Hash_adp_bry.ci_a7()
|
||||
.Add_str_byte("xowa_paging", Arg_paging)
|
||||
.Add_bry_byte(Arg_bry_page_index, Arg_page_idx)
|
||||
.Add_str_byte("xowa_sort", Arg_sort)
|
||||
.Add_str_byte("search", Arg_search)
|
||||
.Add_bry_byte(Arg_bry_cancel, Arg_cancel)
|
||||
;
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.dbs.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.wikis.domains.*; import gplx.xowa.wikis.data.*;
|
||||
class Xows_core {
|
||||
private final Xoae_wiki_mgr wiki_mgr;
|
||||
private final Hash_adp_bry cache_hash = Hash_adp_bry.cs(); private final Hash_adp_bry cmd_hash = Hash_adp_bry.cs();
|
||||
private boolean ask_for_upgrade = true; private final Hash_adp_bry upgraded_wikis = Hash_adp_bry.cs();
|
||||
public Xows_core(Xoae_wiki_mgr wiki_mgr) {this.wiki_mgr = wiki_mgr;}
|
||||
private final Xows_html_wkr html_wkr = new Xows_html_wkr();
|
||||
public Srch_rslt_hash Get_cache_or_new(byte[] key) {
|
||||
Srch_rslt_hash cache = (Srch_rslt_hash)cache_hash.Get_by_bry(key);
|
||||
if (cache == null) {
|
||||
cache = new Srch_rslt_hash();
|
||||
cache_hash.Add_bry_obj(key, cache);
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
public void Search(Xow_wiki search_wiki, Xoae_page page, Srch_qry qry) {
|
||||
// generate 1 cmd per wiki
|
||||
Xow_domain_itm[] domain_ary = qry.wiki_domains; int domain_ary_len = domain_ary.length;
|
||||
for (int i = 0; i < domain_ary_len; ++i) {
|
||||
Xow_domain_itm domain = domain_ary[i];
|
||||
try {
|
||||
Xowe_wiki wiki = wiki_mgr.Get_by_or_make(domain.Domain_bry()); wiki.Init_assert();
|
||||
Assert_page_count(wiki);
|
||||
Xows_ui_cmd cmd = new Xows_ui_cmd(this, qry, wiki, page, page.Tab_data().Close_mgr(), page.Tab_data().Tab().Html_itm(), null, null); // null b/c args are only used by drd
|
||||
qry.Cmds__add(cmd);
|
||||
} catch (Exception e) {Xoa_app_.Usr_dlg().Warn_many("", "", "search:wiki failed; wiki=~{0} err=~{1}", domain.Domain_str(), Err_.Message_lang(e));} // handle bad wikis, like "en.wikipedia.org-old"; DATE:2015-04-24
|
||||
}
|
||||
qry.page_max = Int_.Max_value;
|
||||
// do search and generate html
|
||||
html_wkr.Init_by_wiki(search_wiki, search_wiki.Lang().Num_mgr(), qry);
|
||||
int cmds_len = qry.Cmds__len();
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
for (int i = 0; i < cmds_len; ++i) {
|
||||
Xows_ui_cmd cmd = qry.Cmds__get_at(i); byte[] cmd_key = cmd.Key();
|
||||
cmd_hash.Add_if_dupe_use_nth(cmd_key, cmd);
|
||||
boolean searching_db = cmd.Search();
|
||||
html_wkr.Gen_tbl(tmp_bfr, cmd.Rslt(), cmd_key, cmd.Wiki().Domain_bry(), searching_db);
|
||||
}
|
||||
page.Data_raw_(html_wkr.Gen_page(tmp_bfr.To_bry_and_clear()));
|
||||
}
|
||||
public void Search_end(Xows_ui_cmd cmd) {
|
||||
cmd_hash.Del(cmd.Key());
|
||||
}
|
||||
public void Cancel(byte[] cmd_key) {
|
||||
Xows_ui_cmd cmd = (Xows_ui_cmd)cmd_hash.Get_by_bry(cmd_key);
|
||||
if (cmd == null) return;
|
||||
cmd.Cancel();
|
||||
cmd_hash.Del(cmd.Key());
|
||||
}
|
||||
private void Assert_page_count(Xowe_wiki wiki) {
|
||||
Xowd_db_file search_db = wiki.Data__core_mgr().Db__search();
|
||||
if (ask_for_upgrade
|
||||
&& wiki.App().Mode().Tid_is_gui()
|
||||
&& !search_db.Tbl__search_word().Ddl__page_count()
|
||||
&& !upgraded_wikis.Has(wiki.Domain_bry()) ) {
|
||||
ask_for_upgrade = false;
|
||||
upgraded_wikis.Add_as_key_and_val(wiki.Domain_bry());
|
||||
boolean ok = wiki.Appe().Gui_mgr().Kit().Ask_ok_cancel("", "", String_.Concat_lines_nl_skip_last
|
||||
( "XOWA would like to upgrade your search database for " + wiki.Domain_str() + "."
|
||||
, "* Press OK to upgrade. This may take a few minutes."
|
||||
, "* Press Cancel to skip. You will be able to search, but the results may be slower for multi-word searches (EX: 'The Earth')."
|
||||
, "If you cancel, XOWA will ask you to upgrade this wiki again next time you restart the application."
|
||||
));
|
||||
if (ok)
|
||||
search_db.Tbl__search_word().Ddl__page_count__add(search_db.Tbl__search_link(), search_db.Tbl__cfg());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.specials.search.crts.*;
|
||||
class Xows_db_matcher_bldr {
|
||||
public Srch_word_row[] Gather_words_for_db(Cancelable cxl, Srch_crt_node matcher, Xowd_search_word_tbl word_tbl) {
|
||||
List_adp rv = List_adp_.new_();
|
||||
Gather_words_for_db(cxl, matcher, rv, word_tbl);
|
||||
rv.Sort_by(Srch_word_row_sorter.Page_count_dsc);
|
||||
return (Srch_word_row[])rv.To_ary(Srch_word_row.class);
|
||||
}
|
||||
private void Gather_words_for_db(Cancelable cxl, Srch_crt_node matcher, List_adp rv, Xowd_search_word_tbl word_tbl) {
|
||||
switch (matcher.tid) {
|
||||
case Srch_crt_node.Tid_word:
|
||||
byte[] word_text = matcher.raw;
|
||||
if (Bry_.Has(word_text, Byte_ascii.Star))
|
||||
Load_word_many(cxl, rv, word_text, word_tbl);
|
||||
else
|
||||
Load_word_one(rv, word_text, word_tbl);
|
||||
break;
|
||||
case Srch_crt_node.Tid_word_quote:
|
||||
List_adp tmp = List_adp_.new_();
|
||||
byte[][] words = Bry_split_.Split(matcher.raw, Byte_ascii.Space, Bool_.Y);
|
||||
int words_len = words.length;
|
||||
for (int i = 0; i < words_len; ++i) {
|
||||
byte[] word = words[i];
|
||||
Load_word_one(tmp, word, word_tbl);
|
||||
}
|
||||
if (tmp.Count() == 0) return; // no words in db; EX: "xyz cba"
|
||||
tmp.Sort_by(Srch_word_row_sorter.Page_count_dsc);
|
||||
rv.Add(tmp.Get_at(0)); // add lowest page_count word to db; EX: search for "earth and" should search for "earth" only, but match for "earth and"
|
||||
break;
|
||||
case Srch_crt_node.Tid_and:
|
||||
List_adp lhs_tmp = List_adp_.new_(), rhs_tmp = List_adp_.new_();
|
||||
Gather_words_for_db(cxl, matcher.lhs, lhs_tmp, word_tbl);
|
||||
Gather_words_for_db(cxl, matcher.rhs, rhs_tmp, word_tbl);
|
||||
List_adp_.Add_list(rv, Calc_lowest(lhs_tmp, rhs_tmp)); // calc side with lowest count; add to rv;
|
||||
break;
|
||||
case Srch_crt_node.Tid_or:
|
||||
Gather_words_for_db(cxl, matcher.lhs, rv, word_tbl);
|
||||
Gather_words_for_db(cxl, matcher.rhs, rv, word_tbl);
|
||||
break;
|
||||
case Srch_crt_node.Tid_not: break; // never add "NOT" to db_search
|
||||
case Srch_crt_node.Tid_null: break; // should not happen
|
||||
default: throw Err_.new_unhandled(matcher.tid);
|
||||
}
|
||||
}
|
||||
private List_adp Calc_lowest(List_adp lhs, List_adp rhs) {
|
||||
int lhs_count = Calc(lhs);
|
||||
int rhs_count = Calc(rhs);
|
||||
// never return 0 as lowest count; note that NOT will return 0;
|
||||
if (lhs_count == 0) return rhs;
|
||||
else if (rhs_count == 0) return lhs;
|
||||
else return lhs_count < rhs_count ? lhs : rhs;
|
||||
}
|
||||
private int Calc(List_adp list) {
|
||||
int rv = 0;
|
||||
int len = list.Count();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Srch_word_row word = (Srch_word_row)list.Get_at(i);
|
||||
rv += word.page_count;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private void Load_word_one(List_adp rv, byte[] word_text, Xowd_search_word_tbl word_tbl) {
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search:word by text; word=~{0}", word_text);
|
||||
Xowd_search_word_row row = word_tbl.Select_by_or_null(word_text); if (row == Xowd_search_word_row.Null) return;
|
||||
Srch_word_row word = new Srch_word_row(row.Id(), row.Text(), row.Page_count());
|
||||
rv.Add(word);
|
||||
}
|
||||
private void Load_word_many(Cancelable cxl, List_adp rv, byte[] word_text, Xowd_search_word_tbl word_tbl) {
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search:word by wildcard; word=~{0}", word_text);
|
||||
Xowd_search_word_row[] rows = word_tbl.Select_in(cxl, word_text);
|
||||
int len = rows.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xowd_search_word_row row = rows[i];
|
||||
rv.Add(new Srch_word_row(row.Id(), row.Text(), row.Page_count()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.brys.fmtrs.*;
|
||||
import gplx.langs.htmls.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.langs.numbers.*;
|
||||
class Xows_html_wkr {
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
|
||||
private Srch_qry qry; private Xow_wiki wiki; private Xol_num_mgr num_mgr;
|
||||
private Xoh_lnki_bldr lnki_bldr; private Xoh_anchor_kv_bldr self_lnkr = new Xoh_anchor_kv_bldr(); private Xows_html_row html_rows;
|
||||
public void Init_by_wiki(Xow_wiki wiki, Xol_num_mgr num_mgr, Srch_qry qry) {
|
||||
this.wiki = wiki; this.num_mgr = num_mgr; this.qry = qry;
|
||||
this.lnki_bldr = wiki.App().Html__lnki_bldr();
|
||||
this.html_rows = new Xows_html_row(lnki_bldr);
|
||||
self_lnkr.Init_w_qarg(qry.special_link_base_href);
|
||||
}
|
||||
public byte[] Gen_page(byte[] tbls) {
|
||||
byte[] rslts_hdr = fmtr_rslts.Bld_bry_many(tmp_bfr, num_mgr.Format_num(qry.itms_bgn + List_adp_.Base1), num_mgr.Format_num(qry.itms_end), qry.search_raw);
|
||||
byte[] option_link = lnki_bldr.Href_(Bry_.new_a7("home"), wiki.Ttl_parse(Bry_.new_a7("Help:Options/Search"))).Img_16x16(Xoh_img_path.Img_option).Bld_to_bry();
|
||||
fmtr_page.Bld_bfr_many(tmp_bfr, rslts_hdr, option_link, Paging_link(Bool_.N), Paging_link(Bool_.Y), tbls);
|
||||
return tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
public void Gen_tbl(Bry_bfr bfr, Srch_rslt_list rslt, byte[] cmd_key, byte[] wiki_domain, boolean searching_db) {
|
||||
html_rows.Init(rslt);
|
||||
byte[] search_link = lnki_bldr.Href_(wiki_domain, wiki.Ttl_parse(self_lnkr.Bld_to_bry())).Caption_(wiki_domain).Img_16x16(Xoh_img_path.Img_search).Img_pos_is_left_(Bool_.Y).Bld_to_bry();
|
||||
fmtr_tbl.Bld_bfr_many(bfr, search_link, searching_db ? Cancel_link(wiki_domain, cmd_key) : Bry_.Empty, Bry_hdr_len, Bry_hdr_ttl, Xows_ui_async__html.Gen_insert_key(wiki_domain), html_rows);
|
||||
}
|
||||
private byte[] Cancel_link(byte[] domain, byte[] cmd_key) {
|
||||
lnki_bldr.Id_(Bry_.Add(Bry_.new_a7("xowa_cancel_"), domain));
|
||||
lnki_bldr.Href_(wiki, self_lnkr.Add_int(Xows_arg_mgr.Arg_bry_page_index, qry.page_idx).Add_bry(Xows_arg_mgr.Arg_bry_cancel, cmd_key).Bld_to_bry());
|
||||
lnki_bldr.Title_(Bry_cancel);
|
||||
lnki_bldr.Img_16x16(Xoh_img_path.Img_cancel);
|
||||
return lnki_bldr.Bld_to_bry();
|
||||
}
|
||||
public byte[] Paging_link(boolean fwd) {
|
||||
int paging_idx = qry.page_idx;
|
||||
byte[] title = null, img_path = Bry_.Empty;
|
||||
boolean img_pos_is_left = true;
|
||||
if (fwd) {
|
||||
++paging_idx;
|
||||
// if (paging_idx > qry.Page_max()) return Gfh_entity_.Nbsp_num_bry;
|
||||
img_pos_is_left = false;
|
||||
img_path = Xoh_img_path.Img_go_fwd;
|
||||
title = Bry_paging_fwd;
|
||||
}
|
||||
else {
|
||||
--paging_idx;
|
||||
if (paging_idx < 0) return Gfh_entity_.Nbsp_num_bry;
|
||||
img_path = Xoh_img_path.Img_go_bwd;
|
||||
title = Bry_paging_bwd;
|
||||
}
|
||||
return lnki_bldr.Title_(title).Href_(wiki, self_lnkr.Add_int(Xows_arg_mgr.Arg_bry_page_index, paging_idx).Bld_to_bry()).Img_16x16(img_path).Img_pos_is_left_(img_pos_is_left).Caption_(title).Bld_to_bry();
|
||||
}
|
||||
private static final Bry_fmtr fmtr_page = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "~{rslts_hdr}<span style='margin-left:10px'>~{option_link}</span>"
|
||||
, "<div id='xowa_panel_top' style='width:60%;'><div style='float:right;'><span>~{bwd_a}</span><span style='margin-left:10px'>~{fwd_a}</span></div></div>~{tbls}"
|
||||
, "<div id='xowa_panel_bot' style='width:60%;'><div style='float:right;'><span>~{bwd_a}</span><span style='margin-left:10px'>~{fwd_a}</span></div></div>"
|
||||
), "rslts_hdr", "option_link", "bwd_a", "fwd_a", "tbls");
|
||||
private static final Bry_fmtr fmtr_tbl = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<table class='wikitable sortable' style='width:60%;'>"
|
||||
, " <tr>"
|
||||
, " <th colspan='2' style='text-align:left'>~{wiki}<span style='float:right'>~{cancel}</span>"
|
||||
, " </th>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <th width='100'>~{hdr_len}"
|
||||
, " </th>"
|
||||
, " <th>~{hdr_ttl}"
|
||||
, " </th>"
|
||||
, " </tr>~{rows}"
|
||||
, " <tr id='~{insert_key}' style='display:none;'>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
), "wiki", "cancel", "hdr_len", "hdr_ttl", "insert_key", "rows");
|
||||
private static final Bry_fmtr fmtr_rslts = Bry_fmtr.new_("Results <b>~{bgn}</b> of <b>~{end}</b> for <b>~{raw}</b>", "bgn", "end", "raw");
|
||||
private static final byte[] Bry_paging_fwd = Bry_.new_a7("Next"), Bry_paging_bwd = Bry_.new_a7("Previous"), Bry_cancel = Bry_.new_a7("Stop searching")
|
||||
, Bry_hdr_len = Bry_.new_a7("Page length"), Bry_hdr_ttl = Bry_.new_a7("Page title")
|
||||
;
|
||||
}
|
||||
class Xows_html_row implements gplx.core.brys.Bfr_arg {
|
||||
private final Xoh_lnki_bldr lnki_bldr; private Srch_rslt_list rslt;
|
||||
private final Object thread_lock = new Object();
|
||||
public Xows_html_row(Xoh_lnki_bldr lnki_bldr) {this.lnki_bldr = lnki_bldr;}
|
||||
public Xows_html_row Init(Srch_rslt_list rslt) {this.rslt = rslt; return this;}
|
||||
public void Bfr_arg__add(Bry_bfr bfr) { // <a href="/wiki/A" title="A" class="xowa-visited">A</a>
|
||||
int len = rslt.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Srch_rslt_itm row = rslt.Get_at(i);
|
||||
Gen_html(bfr, row);
|
||||
}
|
||||
}
|
||||
public void Gen_html(Bry_bfr bfr, Srch_rslt_itm row) {
|
||||
synchronized (thread_lock) {
|
||||
lnki_bldr.Href_(row.wiki_bry, row.page_ttl);
|
||||
byte[] title = row.page_ttl.Full_txt();
|
||||
lnki_bldr.Title_(title);
|
||||
lnki_bldr.Caption_(title);
|
||||
fmtr.Bld_bfr_many(bfr, Gfh_utl.Encode_id_as_str(row.key), row.page_len, lnki_bldr.Bld_to_bry());
|
||||
}
|
||||
}
|
||||
public Bry_fmtr Fmtr() {return fmtr;} private final Bry_fmtr fmtr = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr id='~{page_key}'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>~{page_len}"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'>~{lnki}" // SERVER:"<a href='"; DATE:2015-04-16
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
), "page_key", "page_len", "lnki");
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.wikis.tdbs.*;
|
||||
import gplx.xowa.wikis.domains.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xows_html_wkr_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xows_html_wkr_fxt fxt = new Xows_html_wkr_fxt();
|
||||
@Test public void Paging() {
|
||||
fxt.Test_paging(Bool_.Y, 1, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D2' title='Next'>Next<img src='file:///mem/xowa/bin/any/xowa/file/app.general/go_fwd.png' width='16' height='16'/></a>");
|
||||
fxt.Test_paging(Bool_.N, 1, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D0' title='Previous'><img src='file:///mem/xowa/bin/any/xowa/file/app.general/go_bwd.png' width='16' height='16'/>Previous</a>");
|
||||
fxt.Test_paging(Bool_.Y, 2, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D3' title='Next'>Next<img src='file:///mem/xowa/bin/any/xowa/file/app.general/go_fwd.png' width='16' height='16'/></a>");
|
||||
fxt.Test_paging(Bool_.N, 0, " ");
|
||||
}
|
||||
@Test public void Rows() {
|
||||
fxt.Test_rows(new Srch_rslt_itm[] {fxt.Make_row(10, "A"), fxt.Make_row(20, "B")}, String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr id='w.7CA'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>10"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'><a href='/site/w/wiki/A' title='A'>A</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " <tr id='w.7CB'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>20"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'><a href='/site/w/wiki/B' title='B'>B</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
));
|
||||
}
|
||||
}
|
||||
class Xows_html_wkr_fxt {
|
||||
private Xoae_app app; private Xowe_wiki wiki; private Xows_html_wkr html_mgr; private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
|
||||
public Xows_html_wkr_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.app_();
|
||||
wiki = Xoa_app_fxt.wiki_tst_(app);
|
||||
html_mgr = new Xows_html_wkr();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public void Test_paging(boolean fwd, int paging_idx, String expd) {
|
||||
Srch_qry qry = new Srch_qry(Bry_.new_a7("A"), paging_idx, 100, new Xows_ns_mgr(), true, new Xow_domain_itm[] {Xow_domain_itm_.parse(wiki.Domain_bry())});
|
||||
qry.page_max = 2;
|
||||
html_mgr.Init_by_wiki(wiki, wiki.Lang().Num_mgr(), qry);
|
||||
byte[] paging_link = html_mgr.Paging_link(fwd);
|
||||
Tfds.Eq(expd, String_.new_a7(paging_link));
|
||||
}
|
||||
public void Test_rows(Srch_rslt_itm[] rows, String expd) {
|
||||
Srch_rslt_list rslt = new Srch_rslt_list();
|
||||
Xows_html_row html_row = new Xows_html_row(wiki.App().Html__lnki_bldr());
|
||||
html_row.Init(rslt);
|
||||
for (int i = 0; i < rows.length; ++i)
|
||||
rslt.Add(rows[i]);
|
||||
html_row.Bfr_arg__add(tmp_bfr);
|
||||
Tfds.Eq_str_lines(expd, tmp_bfr.To_str_and_clear());
|
||||
}
|
||||
public Srch_rslt_itm Make_row(int len, String ttl_str) {
|
||||
byte[] ttl_bry = Bry_.new_u8(ttl_str);
|
||||
return new Srch_rslt_itm(Bry_.new_a7("w"), wiki.Ttl_parse(ttl_bry), 1, len);
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
public class Xows_ns_mgr {
|
||||
private final Ordered_hash ns_hash = Ordered_hash_.New(); private final Int_obj_ref tmp_ns_id = Int_obj_ref.neg1_(); private final Bry_bfr tmp_bfr = Bry_bfr.reset_(32);
|
||||
private boolean ns_all, ns_main;
|
||||
public void Clear() {
|
||||
ns_hash.Clear();
|
||||
ns_all = ns_main = false;
|
||||
}
|
||||
public boolean Has(int ns_id) {
|
||||
return ns_all // all flag set
|
||||
|| ns_main && ns_id == Xow_ns_.Tid__main // main flag set
|
||||
|| ns_hash.Has(tmp_ns_id.Val_(ns_id)) // check against ns_hash
|
||||
;
|
||||
}
|
||||
public void Add_by_id(int ns_id) {
|
||||
if (ns_hash.Has(tmp_ns_id.Val_(ns_id)))
|
||||
ns_hash.Del(tmp_ns_id);
|
||||
ns_hash.Add_as_key_and_val(Int_obj_ref.new_(ns_id));
|
||||
}
|
||||
public void Add_by_name(byte[] ns_name) {
|
||||
int id = Xow_ns_canonical_.To_id(ns_name);
|
||||
if (id != Xow_ns_.Tid__null)
|
||||
Add_by_id(id);
|
||||
}
|
||||
public void Add_all() {
|
||||
ns_all = true;
|
||||
}
|
||||
public void Add_by_parse(byte[] key, byte[] val) {
|
||||
int ns_enabled = Bry_.To_int_or_neg1(val);
|
||||
if (ns_enabled == 1) { // make sure set to 1; EX: ignore &ns0=0
|
||||
int key_len = key.length;
|
||||
if (key_len == 3 && key[2] == Byte_ascii.Star) // translate ns* as ns_all
|
||||
ns_all = true;
|
||||
else {
|
||||
int ns_id = Bry_.To_int_or(key, 2, key_len, Int_.Min_value);
|
||||
if (ns_id != Int_.Min_value) { // ignore invalid ints; EX: &nsabc=1;
|
||||
Add_by_id(ns_id);
|
||||
ns_main = ns_all = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public void Add_main_if_empty() {
|
||||
if (ns_hash.Count() == 0)
|
||||
ns_main = true;
|
||||
}
|
||||
public byte[] To_hash_key() {
|
||||
if (ns_all)
|
||||
return Hash_key_all;
|
||||
else if (ns_main)
|
||||
return Hash_key_main;
|
||||
else {
|
||||
int ns_hash_len = ns_hash.Count();
|
||||
for (int i = 0; i < ns_hash_len; i++) {
|
||||
if (i != 0) tmp_bfr.Add_byte_semic();
|
||||
Int_obj_ref ns_id_ref = (Int_obj_ref)ns_hash.Get_at(i);
|
||||
tmp_bfr.Add_int_variable(ns_id_ref.Val());
|
||||
}
|
||||
return tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
private static final byte[] Hash_key_all = new byte[] {Byte_ascii.Star}, Hash_key_main = new byte[] {Byte_ascii.Num_0};
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.apps.apis.xowa.specials.*;
|
||||
import gplx.xowa.wikis.domains.*; import gplx.xowa.wikis.domains.crts.*;
|
||||
public class Xows_page__search implements Xows_page, GfoInvkAble, GfoEvObj {
|
||||
private final Xoae_app app; private final Xow_domain_itm wiki_domain; private final Xoapi_search search_api;
|
||||
private final Xows_core search_mgr; private final Xows_arg_mgr args_mgr = new Xows_arg_mgr();
|
||||
private Xow_domain_itm[] search_domain_ary;
|
||||
public Xows_page__search(Xowe_wiki wiki) {
|
||||
this.app = wiki.Appe();
|
||||
this.wiki_domain = wiki.Domain_itm();
|
||||
this.search_mgr = new Xows_core(wiki.Appe().Wiki_mgr());
|
||||
this.ev_mgr = GfoEvMgr.new_(this);
|
||||
this.search_api = wiki.Appe().Api_root().Special().Search();
|
||||
GfoEvMgr_.SubSame_many(search_api, this, Xoapi_search.Evt_multi_wikis_changed, Xoapi_search.Evt_multi_wikis_changed);
|
||||
}
|
||||
public GfoEvMgr EvMgr() {return ev_mgr;} private GfoEvMgr ev_mgr;
|
||||
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__search;}
|
||||
private void Multi_wikis_changed() {
|
||||
Xow_domain_crt_itm crt = search_api.Multi_wikis_crt(wiki_domain);
|
||||
this.search_domain_ary = Get_by_crt(app.Usere().Wiki().Xwiki_mgr(), wiki_domain, crt);
|
||||
if (search_domain_ary.length == 0) search_domain_ary = new Xow_domain_itm[] {wiki_domain}; // default to current if bad input
|
||||
Multi_sorts_changed();
|
||||
}
|
||||
private void Multi_sorts_changed() {
|
||||
Xow_domain_crt_itm[] ary = search_api.Multi_sorts_crt(wiki_domain);
|
||||
if (ary == null) return; // default to no sort if bad input
|
||||
Xow_domain_sorter__manual sorter = new Xow_domain_sorter__manual(wiki_domain, ary);
|
||||
Xow_domain_sorter__manual.Sort(sorter, search_domain_ary);
|
||||
}
|
||||
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
if (wiki.Domain_tid() == Xow_domain_tid_.Int__home) return; // do not allow search in home wiki; will throw null ref error b/c no search_ttl dirs
|
||||
if (search_domain_ary == null) Multi_wikis_changed();
|
||||
// get args
|
||||
Xog_search_suggest_mgr search_suggest_mgr = wiki.Appe().Gui_mgr().Search_suggest_mgr();
|
||||
args_mgr.Clear();
|
||||
args_mgr.Parse(search_suggest_mgr.Args_default());
|
||||
args_mgr.Parse(url.Qargs_ary());
|
||||
args_mgr.Ns_mgr().Add_main_if_empty();
|
||||
// get search_bry
|
||||
byte[] search_bry = args_mgr.Search_bry();
|
||||
if (search_bry == null) { // search is not in qarg; EX:Special:Search?search=Earth
|
||||
search_bry = ttl.Leaf_txt_wo_qarg(); // assume search is in leaf; EX: Special:Search/Earth
|
||||
args_mgr.Search_bry_(search_bry);
|
||||
}
|
||||
if (Bry_.Len_eq_0(search_bry)) return; // emptry String; exit now, else null ref error; DATE:2015-08-11
|
||||
if ( search_suggest_mgr.Auto_wildcard() // add * automatically if option set
|
||||
&& wiki.Db_mgr().Tid() == gplx.xowa.wikis.dbs.Xodb_mgr_sql.Tid_sql // only apply to sql
|
||||
&& Bry_find_.Find_fwd(search_bry, Byte_ascii.Star) == -1 // search term does not have asterisk
|
||||
)
|
||||
search_bry = Bry_.Add(search_bry, Byte_ascii.Star);
|
||||
// url.Page_bry_(Bry_.Add(Xows_special_meta_.Itm__search.Ttl_bry(), Byte_ascii.Slash_bry, search_bry));// HACK: need to re-set Page b/c href_parser does not eliminate qargs; DATE:2013-02-08
|
||||
// search wiki
|
||||
Xoa_ttl search_ttl = Xoa_ttl.parse(wiki, search_bry);
|
||||
Xoae_page search_page = page;
|
||||
if (!Bry_.Eq(search_bry, Xows_special_meta_.Itm__search.Ttl_bry())) // do not lookup page else stack overflow; happens when going directly to Special:Search (from history)
|
||||
search_page = wiki.Data_mgr().Get_page(search_ttl, false); // try to find page; EX:Special:Search?search=Earth -> en.w:Earth; needed for search suggest
|
||||
// page not found, or explicit_search invoked
|
||||
if (search_page.Missing() || url.Qargs_mgr().Match(Qarg__fulltext, Qarg__fulltext__y)) {
|
||||
if (args_mgr.Cancel() != null) {
|
||||
search_mgr.Cancel(args_mgr.Cancel());
|
||||
page.Tab_data().Cancel_show_y_();
|
||||
return;
|
||||
}
|
||||
page.Html_data().Html_restricted_n_();
|
||||
page.Html_data().Xtn_search_text_(search_bry);
|
||||
Srch_qry qry = new Srch_qry(search_bry, args_mgr.Paging_idx(), search_api.Results_per_page(), args_mgr.Ns_mgr(), search_api.Async_db(), search_domain_ary);
|
||||
search_mgr.Search(wiki, page, qry);
|
||||
}
|
||||
// page found; return it;
|
||||
else {
|
||||
wiki.Parser_mgr().Parse(search_page, true);
|
||||
page.Data_raw_(search_page.Data_raw());
|
||||
if (page.Root() != null) // NOTE: null when going from w:Earth -> q:Earth; DATE:2013-03-20
|
||||
page.Root().Data_htm_(search_page.Root().Data_htm());
|
||||
page.Ttl_(search_ttl).Url_(Xoa_url.new_(wiki.Domain_bry(), search_ttl.Full_txt())).Redirected_(true);
|
||||
}
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Xoapi_search.Evt_multi_wikis_changed)) Multi_wikis_changed();
|
||||
else if (ctx.Match(k, Xoapi_search.Evt_multi_sorts_changed)) Multi_sorts_changed();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final byte Match_tid_all = 0, Match_tid_bgn = 1;
|
||||
public static final byte Version_null = 0, Version_1 = 1, Version_2 = 2;
|
||||
private static final byte[] Qarg__fulltext = Bry_.new_a7("fulltext"), Qarg__fulltext__y = Bry_.new_a7("y");
|
||||
private static Xow_domain_itm[] Get_by_crt(gplx.xowa.wikis.xwikis.Xow_xwiki_mgr xwiki_mgr, Xow_domain_itm cur, gplx.xowa.wikis.domains.crts.Xow_domain_crt_itm crt) {
|
||||
List_adp rv = List_adp_.new_();
|
||||
int len = xwiki_mgr.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
gplx.xowa.wikis.xwikis.Xow_xwiki_itm xwiki = xwiki_mgr.Get_at(i); if (!xwiki.Offline()) continue;
|
||||
Xow_domain_itm domain_itm = Xow_domain_itm_.parse(xwiki.Domain_bry());
|
||||
if (crt.Matches(cur, domain_itm)) rv.Add(domain_itm);
|
||||
}
|
||||
return (Xow_domain_itm[])rv.To_ary_and_clear(Xow_domain_itm.class);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.brys.*;
|
||||
class Xows_paging_parser {
|
||||
private final List_adp itm_list = List_adp_.new_();
|
||||
private final Bry_rdr_old rdr = new Bry_rdr_old();
|
||||
public Xows_paging_itm[] Parse(byte[] raw) { // EX: en.wikipedia.org|41|60;en.wiktionary.org|21|40;
|
||||
rdr.Init(raw);
|
||||
while (!rdr.Pos_is_eos()) {
|
||||
byte[] wiki = rdr.Read_bry_to_pipe();
|
||||
int bgn = rdr.Read_int_to_pipe();
|
||||
int end = rdr.Read_int_to_semic();
|
||||
Xows_paging_itm itm = new Xows_paging_itm(wiki, bgn, end);
|
||||
itm_list.Add(itm);
|
||||
}
|
||||
return (Xows_paging_itm[])itm_list.To_ary_and_clear(Xows_paging_itm.class);
|
||||
}
|
||||
}
|
||||
class Xows_paging_itm {
|
||||
public Xows_paging_itm(byte[] wiki, int bgn, int end) {this.wiki = wiki; this.bgn = bgn; this.end = end;}
|
||||
public byte[] Wiki() {return wiki;} private final byte[] wiki;
|
||||
public int Bgn() {return bgn;} private final int bgn;
|
||||
public int End() {return end;} private final int end;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.langs.htmls.*; import gplx.xowa.files.gui.*;
|
||||
class Xows_ui_async__html implements Srch_rslt_lnr {
|
||||
private final Xows_html_row html_row; private final Xog_js_wkr js_wkr;
|
||||
private final Srch_rslt_itm[] rows; private final int rows_len;
|
||||
private final Bry_bfr bfr = Bry_bfr.new_(255);
|
||||
private final byte[] insert_new_key;
|
||||
private final Cancelable cxl;
|
||||
public Xows_ui_async__html(Cancelable cxl, Xows_html_row html_row, Xog_js_wkr js_wkr, int paging_len, byte[] wiki) {
|
||||
this.cxl = cxl;
|
||||
this.html_row = html_row; this.js_wkr = js_wkr;
|
||||
this.rows = new Srch_rslt_itm[paging_len];
|
||||
this.rows_len = paging_len;
|
||||
this.insert_new_key = Gen_insert_key(wiki);
|
||||
}
|
||||
public void Notify_rslt_found(Srch_rslt_itm new_row) {
|
||||
Srch_rslt_itm last_row = rows[rows_len - 1];
|
||||
if (last_row != null) {
|
||||
if (Compare(new_row, last_row) == CompareAble_.MoreOrSame) return; // new_row is < last_row; exit
|
||||
}
|
||||
int new_row_slot = Find_insert_slot(new_row); if (new_row_slot == -1) return;
|
||||
Srch_rslt_itm insert_row = rows[new_row_slot];
|
||||
byte[] insert_key = insert_row == null ? insert_new_key : insert_row.key;
|
||||
Displace(new_row_slot, new_row);
|
||||
html_row.Gen_html(bfr, new_row);
|
||||
String html_tbl = bfr.To_str_and_clear();
|
||||
if (cxl.Canceled()) return;
|
||||
js_wkr.Html_elem_append_above(Gfh_utl.Encode_id_as_str(insert_key), html_tbl);
|
||||
if (last_row != null) {
|
||||
if (cxl.Canceled()) return;
|
||||
js_wkr.Html_elem_replace_html(Gfh_utl.Encode_id_as_str(last_row.key), "");
|
||||
}
|
||||
}
|
||||
private int Find_insert_slot(Srch_rslt_itm new_row) {
|
||||
for (int i = 0; i < rows_len; ++i) {
|
||||
Srch_rslt_itm cur_row = rows[i];
|
||||
if (cur_row == null) return i;
|
||||
if (Compare(new_row, cur_row) == CompareAble_.Less) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private void Displace(int new_row_slot, Srch_rslt_itm new_row) {
|
||||
for (int i = rows_len - 2; i >= new_row_slot; --i) {
|
||||
rows[i + 1] = rows[i];
|
||||
}
|
||||
rows[new_row_slot] = new_row;
|
||||
}
|
||||
private int Compare(Srch_rslt_itm lhs, Srch_rslt_itm rhs) {
|
||||
return -Int_.Compare(lhs.page_len, rhs.page_len);
|
||||
}
|
||||
public static byte[] Gen_insert_key(byte[] wiki) {return Bry_.Add(Bry_insert_key, wiki);}
|
||||
private static final byte[] Bry_insert_key = Bry_.new_a7("xowa_insert_");
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import org.junit.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.files.gui.*;
|
||||
public class Xows_ui_async_tst {
|
||||
@Before public void init() {fxt.Clear();} private Xows_ui_async_fxt fxt = new Xows_ui_async_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Test_add(fxt.Make_rslt(50, "L"), fxt.Make_args_append("xowa_insert_w" , "w.7CL")); // insert new
|
||||
fxt.Test_add(fxt.Make_rslt(30, "N"), fxt.Make_args_append("xowa_insert_w" , "w.7CN")); // insert below last
|
||||
fxt.Test_add(fxt.Make_rslt(70, "J"), fxt.Make_args_append("w.7CL" , "w.7CJ")); // insert above first
|
||||
fxt.Test_add(fxt.Make_rslt(60, "K"), fxt.Make_args_append("w.7CL" , "w.7CK")); // insert above mid
|
||||
fxt.Test_add(fxt.Make_rslt(40, "M"), fxt.Make_args_append("w.7CN" , "w.7CM")); // insert below mid
|
||||
fxt.Test_add(fxt.Make_rslt(10, "P")); // insert noop
|
||||
fxt.Test_add(fxt.Make_rslt(80, "I"), fxt.Make_args_append("w.7CJ" , "w.7CI") , fxt.Make_args_replace("w.7CN")); // insert displace all
|
||||
fxt.Test_add(fxt.Make_rslt(61, "K1"), fxt.Make_args_append("w.7CK" , "w.7CK1"), fxt.Make_args_replace("w.7CM")); // insert displace mid
|
||||
}
|
||||
}
|
||||
class Xows_ui_async_fxt {
|
||||
private Xows_html_row html_row; private static final byte[] Bry_enwiki = Bry_.new_a7("w");
|
||||
private Xows_ui_async__html async;
|
||||
private Xog_js_wkr__log js_wkr = new Xog_js_wkr__log();
|
||||
private Xowe_wiki wiki;
|
||||
public void Clear() {
|
||||
Xoae_app app = Xoa_app_fxt.app_();
|
||||
this.wiki = Xoa_app_fxt.wiki_(app, "w");
|
||||
html_row = new Xows_html_row(wiki.App().Html__lnki_bldr());
|
||||
html_row.Fmtr().Fmt_("~{page_key}");
|
||||
async = new Xows_ui_async__html(Cancelable_.Never, html_row, js_wkr, 5, Bry_enwiki);
|
||||
}
|
||||
public Srch_rslt_itm Make_rslt(int len, String ttl) {
|
||||
byte[] ttl_bry = Bry_.new_a7(ttl);
|
||||
return new Srch_rslt_itm(Bry_enwiki, wiki.Ttl_parse(ttl_bry), 1, len);
|
||||
}
|
||||
public Object[] Make_args_append(String uid, String html) {return Object_.Ary(Xog_js_wkr__log.Proc_append_above, uid, html);}
|
||||
public Object[] Make_args_replace(String uid) {return Object_.Ary(Xog_js_wkr__log.Proc_replace_html, uid, "");}
|
||||
public void Test_add(Srch_rslt_itm row, Object[]... expd) {
|
||||
async.Notify_rslt_found(row);
|
||||
int expd_len = expd.length;
|
||||
Tfds.Eq(expd_len, js_wkr.Log__len());
|
||||
for (int i = 0; i < expd_len; ++i) {
|
||||
String expd_str = String_.Concat_with_obj("\n", expd[i]);
|
||||
String actl_str = String_.Concat_with_obj("\n", js_wkr.Log__get_at(i));
|
||||
Tfds.Eq_str_lines(expd_str, actl_str);
|
||||
}
|
||||
js_wkr.Log__clear();
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
|
||||
import gplx.core.threads.*; import gplx.langs.htmls.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.files.gui.*; import gplx.xowa.guis.views.*;
|
||||
class Xows_ui_cmd implements GfoInvkAble, Cancelable, Srch_rslt_lnr, Xog_tab_close_lnr {
|
||||
private final Xows_core mgr; private final Srch_qry qry; private final Srch_rslt_list rslt;
|
||||
private final Xow_wiki wiki; private final Xoae_page page; private final Xog_tab_close_mgr tab_close_mgr; private final Xog_js_wkr js_wkr;
|
||||
private final boolean async; private Srch_rslt_lnr async_wkr;
|
||||
private Srch_rslt_hash cache;
|
||||
public Xows_ui_cmd(Xows_core mgr, Srch_qry qry, Xow_wiki wiki, Xoae_page page, Xog_tab_close_mgr tab_close_mgr, Xog_js_wkr js_wkr, Srch_rslt_hash cache, Srch_rslt_lnr async_wkr) {
|
||||
this.mgr = mgr; this.qry = qry; this.wiki = wiki; this.page = page; this.tab_close_mgr = tab_close_mgr; this.js_wkr = js_wkr; this.async_wkr = async_wkr;
|
||||
this.async = wiki.App().Mode().Tid_is_gui() && qry.async_db;
|
||||
this.rslt = new Srch_rslt_list();
|
||||
this.key = Gfh_utl.Encode_id_as_bry(Bry_.Add(qry.key, Byte_ascii.Pipe_bry, wiki.Domain_bry()));
|
||||
this.cache = cache;
|
||||
}
|
||||
public byte[] Key() {return key;} private final byte[] key;
|
||||
public Xow_wiki Wiki() {return wiki;}
|
||||
public Srch_rslt_list Rslt() {return rslt;}
|
||||
public boolean Canceled() {return canceled;} private boolean canceled;
|
||||
public void Cancel() {
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search canceled: key=~{0}", key);
|
||||
canceled = true;
|
||||
this.Hide_cancel_btn();
|
||||
}
|
||||
public void Cancel_reset() {}
|
||||
public boolean Search() {
|
||||
this.cache = mgr.Get_cache_or_new(key);
|
||||
boolean rv = false, fill_from_cache = true;
|
||||
if (!cache.Done() && (qry.itms_end > cache.Itms_end())) {
|
||||
if (async) {
|
||||
fill_from_cache = false; // NOTE: do not retrieve cached results to page, else ui_async cmd will add out of order; DATE:2015-04-24
|
||||
if (async_wkr == null) async_wkr = new Xows_ui_async__html(this, new Xows_html_row(new gplx.xowa.htmls.core.htmls.utls.Xoh_lnki_bldr(wiki.App(), wiki.App().Html__href_wtr())), js_wkr, qry.page_len, wiki.Domain_bry());
|
||||
Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_search_db, this, Invk_search_db).Start();
|
||||
}
|
||||
else
|
||||
Search_db();
|
||||
rv = true;
|
||||
}
|
||||
if (fill_from_cache) {
|
||||
cache.Get_between(rslt, qry.itms_bgn, qry.itms_end);
|
||||
qry.page_max = cache.Count() / qry.page_len;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Search_db() {
|
||||
tab_close_mgr.Add(this);
|
||||
if (async) {
|
||||
while (!page.Html_data().Mode_wtxt_shown()) // NOTE:must check for wtxt_shown else async can happen first, and then be overwritten by wtxt; DATE:2015-04-26
|
||||
Thread_adp_.Sleep(100);
|
||||
// show any existing items in the cache on screen; new updates wil bump these off; SEE:NOTE:show_existing;DATE:2015-04-26
|
||||
int qry_itms_bgn = qry.itms_bgn, cache_count = cache.Count();
|
||||
for (int i = qry_itms_bgn; i < cache_count; ++i)
|
||||
async_wkr.Notify_rslt_found(cache.Get_at(i));
|
||||
}
|
||||
new Srch_db_wkr().Search(this, this, cache, wiki, wiki.Lang().Case_mgr(), qry);
|
||||
mgr.Search_end(this);
|
||||
if (this.Canceled()) return; // NOTE: must check else throws SWT exception
|
||||
this.Hide_cancel_btn();
|
||||
if (cache.Done())
|
||||
qry.page_max = cache.Count() / qry.page_len;
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "");
|
||||
}
|
||||
private void Hide_cancel_btn() {
|
||||
Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_search_cancel, this, Invk_hide_cancel).Start();
|
||||
}
|
||||
private void Hide_cancel_btn_async() {
|
||||
js_wkr.Html_atr_set("xowa_cancel_" + wiki.Domain_str(), "style", "display:none;");
|
||||
}
|
||||
public void Notify_rslt_found(Srch_rslt_itm rslt) {
|
||||
cache.Add(rslt);
|
||||
if (async) async_wkr.Notify_rslt_found(rslt);
|
||||
}
|
||||
public boolean When_close(Xog_tab_itm tab, Xoa_url url) {
|
||||
if (url != Xoa_url.Null) { // not called by close_tab (Ctrl+W)
|
||||
byte[] cancel_arg = url.Qargs_mgr().Get_val_bry_or(Xows_arg_mgr.Arg_bry_cancel, null);
|
||||
if (cancel_arg != null) return true; // cancel arg exists; assume tab is not being closed; note that cancel will be processed by Xows_page__special; DATE:2015-04-30
|
||||
}
|
||||
this.Cancel();
|
||||
return true;
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_search_db)) Search_db();
|
||||
else if (ctx.Match(k, Invk_hide_cancel)) Hide_cancel_btn_async();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
private static final String Invk_search_db = "search_db", Invk_hide_cancel = "hide_cancel";
|
||||
}
|
||||
/*
|
||||
NOTE:show_existing. code needed to show A1
|
||||
EX: search="A*": "A" has 400 words; "A1" has 1;
|
||||
. search 1-20 returns 20 words for A and 1 word for A1.
|
||||
.. the 1st A word has a len of 999 and the 20th A word has a length of 900;
|
||||
.. A1 has a length of 799
|
||||
. search 21-40 returns 20 words for A
|
||||
.. the 21st word has a len of 899 and the 40th has a len of 800
|
||||
.. A1 should show up briefly, and then get pushed off screen by 21-40
|
||||
. search 61-40 returns 20 words for A
|
||||
.. A1 must show up
|
||||
*/
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.langs.regxs.*;
|
||||
public class Srch_crt_node {
|
||||
private final Gfo_pattern raw_pattern;
|
||||
public Srch_crt_node(int tid, byte[] raw, Srch_crt_node lhs, Srch_crt_node rhs) {
|
||||
this.tid = tid; this.raw = raw; this.lhs = lhs; this.rhs = rhs;
|
||||
this.raw_pattern = Bry_.Has(raw, Byte_ascii.Star) ? new Gfo_pattern(raw) : null;
|
||||
}
|
||||
public final int tid;
|
||||
public final byte[] raw;
|
||||
public final Srch_crt_node lhs;
|
||||
public final Srch_crt_node rhs;
|
||||
|
||||
public boolean Matches(gplx.xowa.langs.cases.Xol_case_mgr case_mgr, byte[] ttl) {
|
||||
byte[] ttl_lower = case_mgr.Case_build_lower(Xoa_ttl.Replace_unders(ttl));
|
||||
byte[][] ttl_words = Bry_split_.Split(ttl_lower, Byte_ascii.Space, Bool_.Y);
|
||||
return Matches(ttl_lower, ttl_words);
|
||||
}
|
||||
private boolean Matches(byte[] ttl_lower, byte[][] ttl_words) {
|
||||
switch (tid) {
|
||||
case Srch_crt_node.Tid_word: {
|
||||
int len = ttl_words.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] word = ttl_words[i];
|
||||
if (raw_pattern == null) {
|
||||
if (Bry_.Eq(word, raw)) return true;
|
||||
}
|
||||
else {
|
||||
if (raw_pattern.Match(word)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case Srch_crt_node.Tid_word_quote: // note that raw does not have quotes; EX: "B*" -> B*
|
||||
return Bry_find_.Find_fwd(ttl_lower, raw) != Bry_find_.Not_found;
|
||||
case Srch_crt_node.Tid_not:
|
||||
return !rhs.Matches(ttl_lower, ttl_words);
|
||||
case Srch_crt_node.Tid_or:
|
||||
return lhs.Matches(ttl_lower, ttl_words) || rhs.Matches(ttl_lower, ttl_words);
|
||||
case Srch_crt_node.Tid_and:
|
||||
return lhs.Matches(ttl_lower, ttl_words) && rhs.Matches(ttl_lower, ttl_words);
|
||||
case Srch_crt_node.Tid_null: return false;
|
||||
default: throw Err_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Srch_crt_node Null = new Srch_crt_node(Srch_crt_node.Tid_null, null, null, null);
|
||||
public static final int
|
||||
Tid_word = 0 // EX: 'A'
|
||||
, Tid_and = 1 // EX: 'A B'
|
||||
, Tid_or = 2 // EX: 'A OR B'
|
||||
, Tid_not = 3 // EX: '-A'
|
||||
, Tid_word_quote = 4 // EX: '"A B"'
|
||||
, Tid_null = 5
|
||||
;
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
public class Srch_crt_parser {
|
||||
private final Srch_parser_ctx parse_ctx = new Srch_parser_ctx(); private byte[] src;
|
||||
public Srch_crt_node Parse(byte[] src) {
|
||||
this.src = src;
|
||||
Srch_crt_tkn[] tkns = new Srch_crt_scanner().Scan(src);
|
||||
return Parse_itm_or(parse_ctx.Init(tkns));
|
||||
}
|
||||
private Srch_crt_node Parse_itm_or(Srch_parser_ctx parse_ctx) {
|
||||
Srch_crt_node lhs = Parse_itm_and(parse_ctx);
|
||||
while (parse_ctx.Cur_tid(Srch_crt_tkn.Tid_or)) {
|
||||
parse_ctx.Move_next();
|
||||
Srch_crt_node rhs = Parse_itm_and(parse_ctx);
|
||||
lhs = New_join(Srch_crt_node.Tid_or, lhs, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
private Srch_crt_node Parse_itm_and(Srch_parser_ctx parse_ctx) {
|
||||
Srch_crt_node lhs = Parse_itm_not(parse_ctx);
|
||||
while (parse_ctx.Cur_tid(Srch_crt_tkn.Tid_and)) {
|
||||
parse_ctx.Move_next();
|
||||
Srch_crt_node rhs = Parse_itm_not(parse_ctx);
|
||||
lhs = New_join(Srch_crt_node.Tid_and, lhs, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
private Srch_crt_node Parse_itm_not(Srch_parser_ctx parse_ctx) {
|
||||
Srch_crt_node lhs = Parse_itm_leaf(parse_ctx);
|
||||
while (parse_ctx.Cur_tid(Srch_crt_tkn.Tid_not)) {
|
||||
parse_ctx.Move_next();
|
||||
Srch_crt_node rhs = Parse_itm_leaf(parse_ctx);
|
||||
lhs = New_join(Srch_crt_node.Tid_not, null, rhs);
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
private Srch_crt_node Parse_itm_leaf(Srch_parser_ctx parse_ctx) {
|
||||
if (parse_ctx.Cur_tid(Srch_crt_tkn.Tid_paren_bgn)) {
|
||||
parse_ctx.Move_next();
|
||||
Srch_crt_node lhs = Parse_itm_or(parse_ctx);
|
||||
if (parse_ctx.Cur_tid(Srch_crt_tkn.Tid_paren_end)) parse_ctx.Move_next(); // skip token
|
||||
return lhs;
|
||||
}
|
||||
else if (parse_ctx.Cur_tid(Srch_crt_tkn.Tid_eos))
|
||||
return Srch_crt_node.Null;
|
||||
else {
|
||||
Srch_crt_tkn word_tkn = parse_ctx.Move_next();
|
||||
if (word_tkn.tid == Srch_crt_tkn.Tid_not) {
|
||||
word_tkn = parse_ctx.Move_next();
|
||||
if (word_tkn == null) return Srch_crt_node.Null; // occurs in "a -"
|
||||
Srch_crt_node word_itm = New_word(word_tkn, src);
|
||||
return New_join(Srch_crt_node.Tid_not, null, word_itm);
|
||||
}
|
||||
else
|
||||
return New_word(word_tkn, src);
|
||||
}
|
||||
}
|
||||
private static Srch_crt_node New_word(Srch_crt_tkn tkn, byte[] src) {
|
||||
int tid = tkn.tid == Srch_crt_tkn.Tid_word ? Srch_crt_node.Tid_word : Srch_crt_node.Tid_word_quote;
|
||||
return new Srch_crt_node(tid, tkn.val, null, null);
|
||||
}
|
||||
private static Srch_crt_node New_join(int tid, Srch_crt_node lhs, Srch_crt_node rhs) {return new Srch_crt_node(tid, null, lhs, rhs);}
|
||||
}
|
||||
class Srch_parser_ctx {
|
||||
private Srch_crt_tkn[] ary; private int pos = 0; private int ary_len;
|
||||
public Srch_parser_ctx Init(Srch_crt_tkn[] ary) {
|
||||
this.ary = ary;
|
||||
this.ary_len = ary.length;
|
||||
this.pos = 0;
|
||||
return this;
|
||||
}
|
||||
public boolean Cur_tid(byte tid) {return pos < ary_len ? tid == ary[pos].tid : tid == Srch_crt_tkn.Tid_eos;}
|
||||
public Srch_crt_tkn Move_next() {
|
||||
Srch_crt_tkn rv = null;
|
||||
if (pos < ary_len) rv = ary[pos++];
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.core.primitives.*; import gplx.core.btries.*;
|
||||
class Srch_crt_scanner {
|
||||
private final List_adp tkns = List_adp_.new_(); private byte[] src; private int src_len, pos, txt_bgn;
|
||||
private final Ordered_hash tmp_list = Ordered_hash_.New(); private final Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
public Srch_crt_tkn[] Scan(byte[] src) {
|
||||
this.src = src; this.src_len = src.length;
|
||||
tkns.Clear(); pos = 0; txt_bgn = -1;
|
||||
while (pos < src_len) {
|
||||
byte cur_b = src[pos];
|
||||
Object cur_obj = trie.Match_bgn_w_byte(cur_b, src, pos, src_len);
|
||||
if (cur_obj == null) { // text character
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
++pos;
|
||||
}
|
||||
else { // AND, OR, (, ), -, \s, "
|
||||
int pos_end = trie.Match_pos();
|
||||
byte cur_tid = ((Byte_obj_val)cur_obj).Val();
|
||||
if (Cur_join_is_word(cur_tid, pos_end)) continue; // ignore words containing "and", "or"; EX: "random"; "for"
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Tkns_add_word(Srch_crt_tkn.Tid_word, txt_bgn, pos);
|
||||
txt_bgn = -1;
|
||||
}
|
||||
switch (cur_tid) {
|
||||
case Srch_crt_tkn.Tid_space: // discard spaces
|
||||
pos = Bry_find_.Find_fwd_while(src, pos, src_len, Byte_ascii.Space);
|
||||
break;
|
||||
case Srch_crt_tkn.Tid_quote: // find end quote and add as word
|
||||
int quote_bgn = pos + 1;
|
||||
int quote_end = Bry_find_.Find_fwd(src, Byte_ascii.Quote, quote_bgn, src_len);
|
||||
if (quote_end == Bry_find_.Not_found) throw Err_.new_wo_type("could not find end quote", "src", String_.new_u8(src));
|
||||
Tkns_add_word(Srch_crt_tkn.Tid_word_quoted, quote_bgn, quote_end);
|
||||
pos = quote_end + 1; // +1 to place after quote
|
||||
break;
|
||||
case Srch_crt_tkn.Tid_not:
|
||||
Tkns_add_word(Srch_crt_tkn.Tid_not, pos, pos_end);
|
||||
pos = pos_end;
|
||||
break;
|
||||
case Srch_crt_tkn.Tid_paren_bgn: case Srch_crt_tkn.Tid_paren_end:
|
||||
case Srch_crt_tkn.Tid_and: case Srch_crt_tkn.Tid_or:
|
||||
tkns.Add(new_tkn(cur_tid, src, pos, pos_end));
|
||||
pos = pos_end;
|
||||
break;
|
||||
default: throw Err_.new_unhandled(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Tkns_add_word(Srch_crt_tkn.Tid_word, txt_bgn, pos);
|
||||
txt_bgn = -1;
|
||||
}
|
||||
return (Srch_crt_tkn[])tkns.To_ary_and_clear(Srch_crt_tkn.class);
|
||||
}
|
||||
private boolean Cur_join_is_word(byte cur_tid, int pos_end) { // extra logic to handle and / or occuring in unquoted strings; EX: "random"; "for"
|
||||
switch (cur_tid) {
|
||||
default: return false; // only look at AND, OR, -
|
||||
case Srch_crt_tkn.Tid_and: case Srch_crt_tkn.Tid_or: case Srch_crt_tkn.Tid_not:
|
||||
break;
|
||||
}
|
||||
boolean join_is_word = true;
|
||||
if (txt_bgn == -1) { // no pending word;
|
||||
if (cur_tid == Srch_crt_tkn.Tid_not) return false; // NOT is only operator if no pending tkn; EX: -abc -> NOT abc; a-b -> a-b
|
||||
byte nxt_b = pos_end < src_len ? src[pos_end] : Byte_ascii.Null;
|
||||
Object nxt_obj = trie.Match_bgn_w_byte(nxt_b, src, pos_end, src_len);
|
||||
if (nxt_obj == null) // next tkn is text; join must be word
|
||||
join_is_word = true;
|
||||
else { // next tkn is tkn
|
||||
byte nxt_tid = ((Byte_obj_val)nxt_obj).Val();
|
||||
switch (nxt_tid) {
|
||||
case Srch_crt_tkn.Tid_space: case Srch_crt_tkn.Tid_quote:
|
||||
case Srch_crt_tkn.Tid_paren_bgn: case Srch_crt_tkn.Tid_paren_end:
|
||||
join_is_word = false; // next tkn is sym; and/or is not word; EX: a AND ; a AND"b"; a AND(b)
|
||||
break;
|
||||
case Srch_crt_tkn.Tid_not: case Srch_crt_tkn.Tid_and: case Srch_crt_tkn.Tid_or:
|
||||
join_is_word = true; // next tkn is and or not; and/or is word; EX: andor; oror; or-abc;
|
||||
break;
|
||||
default: throw Err_.new_unhandled(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // pending word; cur join must be word; EX: "grand": "and" invoked and "gr" pending
|
||||
join_is_word = true;
|
||||
}
|
||||
if (join_is_word) {
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
pos = pos_end;
|
||||
return true;
|
||||
}
|
||||
if (txt_bgn != -1) {
|
||||
Tkns_add_word(Srch_crt_tkn.Tid_word, txt_bgn, pos); // create word
|
||||
txt_bgn = -1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void Tkns_add_word(byte tid, int src_bgn, int src_end) {
|
||||
if (tkns.Count() > 0) { // at least 1 tkn; check for "auto-and"
|
||||
Srch_crt_tkn last_tkn = (Srch_crt_tkn)tkns.Get_at_last();
|
||||
if (last_tkn.tid == Srch_crt_tkn.Tid_word) // previous tkn is word; auto "AND" words; EX: A B -> A AND B
|
||||
tkns.Add(new Srch_crt_tkn(Srch_crt_tkn.Tid_and, Bry_and));
|
||||
}
|
||||
if (tid == Srch_crt_tkn.Tid_word) { // if word has symbol, convert to quoted; EX: a-b should become "a-b"; otherwise searcher would search for a single word a-b
|
||||
byte[] cur_word = Bry_.Mid(src, src_bgn, src_end);
|
||||
byte[][] words = gplx.xowa.bldrs.cmds.texts.Xob_search_base.Split_ttl_into_words(null, tmp_list, tmp_bfr, cur_word);
|
||||
int words_len = words.length;
|
||||
if ( words_len == 1 // only one word
|
||||
&& !Bry_.Eq(words[0], cur_word) // split word not same as raw
|
||||
&& Bry_find_.Find_fwd(cur_word, Byte_ascii.Star) == -1 // no asterisk
|
||||
) {
|
||||
tkns.Add(new Srch_crt_tkn(tid, words[0]));
|
||||
return;
|
||||
}
|
||||
if (words.length > 1) // multiple words; add as quoted-term; EX: "a-b"
|
||||
tid = Srch_crt_tkn.Tid_word_quoted;
|
||||
}
|
||||
tkns.Add(new_tkn(tid, src, src_bgn, src_end));
|
||||
}
|
||||
private Srch_crt_tkn new_tkn(byte tid, byte[] src, int val_bgn, int val_end) {return new Srch_crt_tkn(tid, Bry_.Mid(src, val_bgn, val_end));}
|
||||
private static final byte[] Bry_and = Bry_.new_a7("AND");
|
||||
private static final Btrie_slim_mgr trie = Btrie_slim_mgr.ci_a7()// NOTE:ci.ascii:OR / AND only
|
||||
.Add_str_byte(" " , Srch_crt_tkn.Tid_space)
|
||||
.Add_str_byte("\"" , Srch_crt_tkn.Tid_quote)
|
||||
.Add_str_byte("-" , Srch_crt_tkn.Tid_not)
|
||||
.Add_str_byte("(" , Srch_crt_tkn.Tid_paren_bgn)
|
||||
.Add_str_byte(")" , Srch_crt_tkn.Tid_paren_end)
|
||||
.Add_str_byte("or" , Srch_crt_tkn.Tid_or)
|
||||
.Add_str_byte("and" , Srch_crt_tkn.Tid_and);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
class Srch_crt_tkn {
|
||||
public final byte tid;
|
||||
public final byte[] val;
|
||||
public Srch_crt_tkn(byte tid, byte[] val) {this.tid = tid; this.val = val;}
|
||||
|
||||
public static final byte
|
||||
Tid_root = 1
|
||||
, Tid_word = 2
|
||||
, Tid_word_quoted = 3
|
||||
, Tid_space = 4
|
||||
, Tid_quote = 5
|
||||
, Tid_not = 6
|
||||
, Tid_paren_bgn = 7
|
||||
, Tid_paren_end = 8
|
||||
, Tid_or = 9
|
||||
, Tid_and = 10
|
||||
, Tid_eos = 11
|
||||
;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//namespace gplx.xowa.specials.search.dbs {
|
||||
// using gplx.dbs; using gplx.xowa.wikis.data.tbls;
|
||||
// using gplx.xowa.langs.cases; using gplx.xowa.wikis.nss;
|
||||
// // workset_count
|
||||
// // workset_score_min
|
||||
// class Srch_db_mgr {
|
||||
// private Srch_word_tbl srch_word_tbl = new Srch_word_tbl(null, null);
|
||||
// private Srch_page_tbl srch_page_tbl = new Srch_page_tbl();
|
||||
// private Page_tbl page_tbl = new Page_tbl();
|
||||
// public void Search(Srch_request req) {
|
||||
// List_adp results = req.results;
|
||||
// int curr = results.Count();
|
||||
// int need = curr + req.req__count;
|
||||
// while (curr < need) {
|
||||
// // foreach (word)
|
||||
// srch_word_tbl.Get(req, null); // read words
|
||||
// srch_page_tbl.Get(req); // get pages for every words
|
||||
// // add to potential results; skip if failed and / not (but can't do quote)
|
||||
// page_tbl.Get(req); // get actual page and check for ns; quote; redirect
|
||||
// // repeat until matched
|
||||
// need = results.Count();
|
||||
// }
|
||||
// }
|
||||
// // get all pages in word_id set sorted by page_search_score
|
||||
// // stop if
|
||||
// // - no more pages; normal case
|
||||
// // - page_score < workset_score_min; case with many pages (1000 pages)
|
||||
//// private int Get_word_id_pages
|
||||
//// ( Cancelable cancelable, Xow_wiki wiki, Xol_case_mgr case_mgr
|
||||
//// , Srch_request req, Xows_ui_cmd cmd, Srch_qry qry, Srch_rslt_hash cache
|
||||
//// , Db_attach_rdr attach_rdr, String sql, Xowd_page_tbl page_tbl
|
||||
//// , Srch_word_row word, Srch_crt_node matcher, int rslts_wanted, int workset_score_min) {
|
||||
//// int rslts_found = 0;
|
||||
//// Xow_ns_mgr ns_mgr = wiki.Ns_mgr();
|
||||
//// Db_rdr rdr = attach_rdr.Exec_as_rdr(sql);
|
||||
//// try {
|
||||
//// while (rdr.Move_next()) {
|
||||
//// if (cancelable.Canceled()) return -1;
|
||||
//// word.Rslts_offset_add_1();
|
||||
//// int page_ns = rdr.Read_int(page_tbl.Fld_page_ns());
|
||||
//// if (!qry.Ns_mgr().Has(page_ns)) continue; // ignore: ns doesn't match
|
||||
//// byte[] page_ttl = rdr.Read_bry_by_str(page_tbl.Fld_page_title());
|
||||
//// // Io_mgr.Instance.AppendFilStr("C:\\temp.txt", String_.new_u8(word.Text()) + "|" + Int_.To_str(page_ns) + "|" + String_.new_u8(page_ttl) + "\n");
|
||||
//// byte[] page_ttl_lc = case_mgr.Case_build_lower(Xoa_ttl.Replace_unders(page_ttl));
|
||||
//// byte[][] page_ttl_words = Bry_split_.Split(page_ttl_lc, Byte_ascii.Space, Bool_.Y);
|
||||
//// if (!matcher.Matches(page_ttl_lc, page_ttl_words)) continue; // ignore: ttl doesn't match matcher
|
||||
//// int page_id = rdr.Read_int(page_tbl.Fld_page_id());
|
||||
//// int page_len = rdr.Read_int(page_tbl.Fld_page_len());
|
||||
//// int page_link_score = 0; //rdr.Read_int(page_tbl.Fld_page_link_score());
|
||||
//// Xow_ns ns = ns_mgr.Ids_get_or_null(page_ns);
|
||||
//// byte[] page_ttl_w_ns = ns.Gen_ttl(page_ttl);
|
||||
//// if (cache.Has(page_ttl_w_ns)) continue; // ignore: page already added by another word; EX: "A B"; word is "B", but "A B" already added by "A"
|
||||
//// Xoa_ttl ttl = wiki.Ttl_parse(page_ttl_w_ns);
|
||||
//// Srch_rslt_itm row = new Srch_rslt_itm(wiki.Domain_bry(), ttl, page_id, page_len);
|
||||
//// cmd.Add_rslt(row);
|
||||
//// if (++rslts_found == rslts_wanted) break; // stop: found enough results; DATE:2015-04-24
|
||||
//// }
|
||||
//// } finally {rdr.Rls();}
|
||||
//// if (rslts_found == 0) word.Rslts_done_y_(); // read through entire rdr and nothing found; mark word done
|
||||
//// return rslts_found;
|
||||
//// }
|
||||
// }
|
||||
//}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//namespace gplx.xowa.specials.search.dbs {
|
||||
// using gplx.dbs; using gplx.xowa.wikis.data.tbls;
|
||||
// // a
|
||||
// // a b
|
||||
// // a*
|
||||
// class Srch_word_tbl {
|
||||
// private final Db_conn conn;
|
||||
// private final Xowd_search_word_tbl tbl;
|
||||
// public Srch_word_tbl(Db_conn conn, Xowd_search_word_tbl tbl) {this.conn = conn; this.tbl = tbl;}
|
||||
// public void Get(Srch_request req, Srch_cache_word cache_word) {
|
||||
// // int req_count = req.req__count;
|
||||
// // conn.Stmt_select_order(tbl.Tbl_name(), String_.Ary(tbl.Fld_id(), tbl.Fld_w()));
|
||||
// // SELECT word_id, word_text FROM search_word WHERE word_text LIKE "~{word}%" AND word_text > '' ORDER BY word_page_score DESC OFFSET 0;
|
||||
// Db_qry qry = Db_qry_.select_()
|
||||
// .From_(tbl.Tbl_name())
|
||||
// .Cols_(tbl.Fld_id(), tbl.Fld_text(), tbl.Fld_page_count(), tbl.Fld_page_score_max())
|
||||
// .Where_(Db_crt_.New_like(tbl.Fld_text(), ""))
|
||||
// .OrderBy_(tbl.Fld_page_score_max(), false)
|
||||
// // .Offset_();
|
||||
// ;
|
||||
// Db_stmt stmt = conn.Stmt_new(qry);
|
||||
// stmt.Clear().Crt_str(tbl.Fld_text(), req.search);
|
||||
// Db_rdr rdr = stmt.Exec_select__rls_auto();
|
||||
// int cur_count = 0;
|
||||
// while (rdr.Move_next()) {
|
||||
// int word_id = rdr.Read_int(tbl.Fld_id());
|
||||
// byte[] word_text = rdr.Read_bry_by_str(tbl.Fld_text());
|
||||
// int page_count = rdr.Read_int(tbl.Fld_page_count());
|
||||
// int page_score_max = rdr.Read_int(tbl.Fld_page_score_max());
|
||||
// Srch_word_row row = new Srch_word_row(word_id, word_text, page_count, page_score_max);
|
||||
// cache_word.words.Add(row);
|
||||
// cur_count += page_count;
|
||||
// ++cache_word.offset;
|
||||
// if (cur_count >= (req.req__count * 2)) break;
|
||||
// }
|
||||
// /*
|
||||
// Get_rng; now in set of 100, scores may range from 1234 to 50; search every word to get minimum
|
||||
// */
|
||||
// }
|
||||
// }
|
||||
// class Srch_page_tbl {
|
||||
// public void Get(Srch_request req) {
|
||||
// }
|
||||
// }
|
||||
// class Page_tbl {
|
||||
// public void Get(Srch_request req) {}
|
||||
// }
|
||||
// class Srch_word_row {
|
||||
// public int word_id;
|
||||
// public byte[] text;
|
||||
// public int page_count;
|
||||
// public int page_score_max;
|
||||
// public int rslts_offset;
|
||||
// public boolean rslts_done;
|
||||
// public Srch_word_row(int word_id, byte[] text, int page_count, int page_score_max) {
|
||||
// this.word_id = word_id; this.text = text; this.page_count = page_count; this.page_score_max = page_score_max;
|
||||
// rslts_offset = 0; rslts_done = false;
|
||||
// }
|
||||
// public void Rslts_offset_add_1() {++rslts_offset;}
|
||||
// public void Rslts_done_y_() {rslts_done = true;}
|
||||
// }
|
||||
// class Srch_page_row {
|
||||
// public int word_id;
|
||||
// public int page_id;
|
||||
// public void Load(int word_id, int page_id) {
|
||||
// this.word_id = word_id; this.page_id = page_id;
|
||||
// }
|
||||
// }
|
||||
// class Srch_cache_word {
|
||||
// public byte[] search;
|
||||
// public final List_adp words = List_adp_.new_();
|
||||
// public int offset;
|
||||
// public void Init_new(byte[] search) {
|
||||
// this.search = search;
|
||||
// words.Clear();
|
||||
// offset = 0;
|
||||
// }
|
||||
// }
|
||||
// class Srch_request {
|
||||
// public String search;
|
||||
// public int req__count;
|
||||
// public boolean wildcard;
|
||||
// public String bmk__word__text;
|
||||
// public int bmk__page__word_id;
|
||||
// public int bmk__page__page_id;
|
||||
// // all_pages;
|
||||
// // view_pages
|
||||
// public final List_adp results = List_adp_.new_();
|
||||
// public final Srch_cache_word tbl__word = new Srch_cache_word();
|
||||
// public void Init_new(String search, boolean wildcard, int req__count) {
|
||||
// this.search = search; this.wildcard = wildcard; this.req__count = req__count;
|
||||
// this.bmk__word__text = "";
|
||||
// this.bmk__page__word_id = -1;
|
||||
// this.bmk__page__page_id = -1;
|
||||
// tbl__word.Init_new(Bry_.new_a7(search));
|
||||
// results.Clear();
|
||||
// }
|
||||
// public void Init_continue(int req__count) {
|
||||
// }
|
||||
// }
|
||||
// class Srch_query {
|
||||
// public String raw;
|
||||
// public Srch_query(String raw) {
|
||||
// this.raw = raw;
|
||||
// // separate to words
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.core.primitives.*;
|
||||
import gplx.xowa.langs.*;
|
||||
class Xows_text_parser__v1 {
|
||||
private Xol_lang_itm lang; private Bry_bfr bfr = Bry_bfr.new_(255);
|
||||
private final Ordered_hash list = Ordered_hash_.New_bry();
|
||||
public void Init(Xol_lang_itm lang) {this.lang = lang;}
|
||||
public void Parse(byte[] src, int src_len, int bgn, int end) {
|
||||
if (lang != null) { // null lang passed in by searcher
|
||||
src = lang.Case_mgr().Case_build_lower(src);
|
||||
src_len = src.length;
|
||||
}
|
||||
int i = 0; boolean word_done = false;
|
||||
while (true) {
|
||||
if (word_done || i == src_len) {
|
||||
if (bfr.Len() > 0) {
|
||||
byte[] word = bfr.To_bry_and_clear();
|
||||
if (!list.Has(word)) list.Add(word, word); // don't add same word twice; EX: Title of "Can Can" should only have "Can" in index
|
||||
}
|
||||
if (i == src_len) break;
|
||||
word_done = false;
|
||||
}
|
||||
byte b = src[i];
|
||||
switch (b) {
|
||||
case Byte_ascii.Underline: // underline is word-breaking; EX: A_B -> A, B
|
||||
case Byte_ascii.Space: // should not occur, but just in case (only underscores)
|
||||
case Byte_ascii.Tab: case Byte_ascii.Nl: case Byte_ascii.Cr: // should not occur in titles, but just in case
|
||||
|
||||
case Byte_ascii.Dash: // treat hypenated words separately
|
||||
case Byte_ascii.Dot: // treat abbreviations as separate words; EX: A.B.C.
|
||||
case Byte_ascii.Bang: case Byte_ascii.Hash: case Byte_ascii.Dollar: case Byte_ascii.Percent:
|
||||
case Byte_ascii.Amp: case Byte_ascii.Paren_bgn: case Byte_ascii.Paren_end: case Byte_ascii.Star:
|
||||
case Byte_ascii.Comma: case Byte_ascii.Slash:
|
||||
case Byte_ascii.Colon: case Byte_ascii.Semic: case Byte_ascii.Gt:
|
||||
case Byte_ascii.Question: case Byte_ascii.At: case Byte_ascii.Brack_bgn: case Byte_ascii.Brack_end:
|
||||
case Byte_ascii.Pow: case Byte_ascii.Tick:
|
||||
case Byte_ascii.Curly_bgn: case Byte_ascii.Pipe: case Byte_ascii.Curly_end: case Byte_ascii.Tilde:
|
||||
case Byte_ascii.Quote: case Byte_ascii.Apos: // FUTURE: apos will split "Earth's" to Earth and s; should remove latter
|
||||
++i;
|
||||
word_done = true;
|
||||
break;
|
||||
default:
|
||||
bfr.Add_byte(b);
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// byte[][] rv = (byte[][])list.To_ary(typeof(byte[]));
|
||||
// list.Clear(); list.Resize_bounds(16);
|
||||
// return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.core.btries.*; import gplx.xowa.langs.cases.*;
|
||||
class Xows_text_parser__v2 {
|
||||
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs();
|
||||
private final Bry_bfr bfr = Bry_bfr.new_(32);
|
||||
private Xob_word_mgr word_mgr; private Xol_case_mgr case_mgr;
|
||||
private byte[] src; private int end; // bgn,
|
||||
private boolean dirty; private Xows_text_tkn__split parser__ws;
|
||||
public void Init_for_ttl(Xob_word_mgr word_mgr, Xol_case_mgr case_mgr) {
|
||||
this.word_mgr = word_mgr; this.case_mgr = case_mgr;
|
||||
trie.Clear();
|
||||
this.parser__ws = Xows_text_tkn__split.new_(trie, Bool_.N, " ", "\t", "\n", "\r", "_");
|
||||
Xows_text_tkn__split.new_(trie, Bool_.N, "!", "?");
|
||||
Xows_text_tkn__split.new_(trie, Bool_.N, "(", ")");
|
||||
Xows_text_tkn__split.new_(trie, Bool_.N, "/");
|
||||
Xows_text_tkn__ellipsis.new_(trie, "..");
|
||||
Xows_text_tkn__apos.new_(trie, "'", Byte_ascii.Ltr_s);
|
||||
}
|
||||
public void Parse(byte[] src, int src_len, int bgn, int end) {
|
||||
this.src = src; this.end = end; // this.bgn = bgn;
|
||||
this.dirty = false; this.bgn__ws = bgn__dash = bgn__slash = -1;
|
||||
this.src = case_mgr.Case_build_lower(src); src_len = this.src.length;
|
||||
int pos = bgn;
|
||||
while (true) {
|
||||
boolean is_last = pos == end;
|
||||
if (is_last) { // do split
|
||||
Word__add(bgn__ws, end);
|
||||
break;
|
||||
}
|
||||
byte b = src[pos];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, pos, end);
|
||||
if (o == null) { // unknown sequence; word-char
|
||||
Char__add(b, pos);
|
||||
++pos;
|
||||
}
|
||||
else {
|
||||
Xows_text_tkn parser = (Xows_text_tkn)o;
|
||||
pos = parser.Parse(this, src, end, pos, trie.Match_pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
public int Bgn__ws() {return bgn__ws;} private int bgn__ws;
|
||||
public int Bgn__dash() {return bgn__dash;} private int bgn__dash;
|
||||
public int Bgn__slash() {return bgn__slash;} private int bgn__slash;
|
||||
public void Bgn__ws_clear() {this.bgn__ws = -1;}
|
||||
public void Bgn__dash_(int v) {this.bgn__dash = v;}
|
||||
public void Bgn__slash_(int v) {this.bgn__slash= v;}
|
||||
public void Word__add(int bgn__ws, int word_end) {
|
||||
if (bgn__ws == word_end) return; // handle situations like "A!" where sym is at eos
|
||||
if (bgn__ws == -1) return; // handle situations like "A... " where " " is different than "..."
|
||||
byte[] word = dirty ? bfr.To_bry_and_clear() : Bry_.Mid(src, bgn__ws, word_end);
|
||||
word_mgr.Add(word);
|
||||
if (bgn__dash != -1) {
|
||||
word_mgr.Add(Bry_.Mid(src, bgn__dash, word_end));
|
||||
bgn__dash = -1;
|
||||
}
|
||||
}
|
||||
public void Char__add(byte b, int pos) {
|
||||
if (dirty)
|
||||
bfr.Add_byte(b);
|
||||
else {
|
||||
if (bgn__ws == -1)
|
||||
bgn__ws = pos;
|
||||
}
|
||||
}
|
||||
public boolean Ws__is_word_end(int pos) {return parser__ws.Is_word_end(src, end, pos);}
|
||||
}
|
||||
class Xob_word_mgr {
|
||||
private final Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
public void Clear() {hash.Clear();}
|
||||
public int Len() {return hash.Count();}
|
||||
public Xob_word_itm Get_at(int i) {return (Xob_word_itm)hash.Get_at(i);}
|
||||
public void Add(byte[] word) {
|
||||
Xob_word_itm itm = (Xob_word_itm)hash.Get_by(word);
|
||||
if (itm == null) {
|
||||
itm = new Xob_word_itm(word);
|
||||
hash.Add(word, itm);
|
||||
}
|
||||
itm.Count_add_1_();
|
||||
}
|
||||
}
|
||||
class Xob_word_itm {
|
||||
public Xob_word_itm(byte[] word) {
|
||||
this.word = word;
|
||||
this.count = 0;
|
||||
}
|
||||
public byte[] Word() {return word;} private final byte[] word;
|
||||
public int Count() {return count;} private int count; public void Count_add_1_() {++count;}
|
||||
@gplx.Internal protected Xob_word_itm Count_(int v) {this.count = v; return this;}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import org.junit.*; import gplx.xowa.langs.cases.*;
|
||||
public class Xows_text_parser__v2_tst {
|
||||
private final Xows_text_parser__v2_fxt fxt = new Xows_text_parser__v2_fxt();
|
||||
@Before public void init() {fxt.Init();}
|
||||
@Test public void Word__one() {
|
||||
fxt.Clear().Test_split("abcd", "abcd");
|
||||
}
|
||||
@Test public void Word__many() {
|
||||
fxt.Clear().Test_split("abc d ef", "abc", "d", "ef");
|
||||
}
|
||||
@Test public void Ws__many() {
|
||||
fxt.Clear().Test_split("a b", "a", "b");
|
||||
}
|
||||
@Test public void Ws__bgn() {
|
||||
fxt.Clear().Test_split(" a", "a");
|
||||
}
|
||||
@Test public void Ws__end() {
|
||||
fxt.Clear().Test_split(" a", "a");
|
||||
}
|
||||
@Test public void Under() {
|
||||
fxt.Clear().Test_split("a_b", "a", "b");
|
||||
}
|
||||
@Test public void Lowercase() {
|
||||
fxt.Clear().Test_split("A B C", "a", "b", "c");
|
||||
}
|
||||
@Test public void Dupe() {
|
||||
fxt.Clear().Test_split("a a a", fxt.Make_word("a", 3));
|
||||
}
|
||||
@Test public void Dupe__lowercase() {
|
||||
fxt.Clear().Test_split("a A", fxt.Make_word("a", 2));
|
||||
}
|
||||
@Test public void Dot__acronym() { // EX: "History of U.S.A. Science "
|
||||
fxt.Clear().Test_split("abc D.E.F. ghi", "abc", "d.e.f.", "ghi");
|
||||
}
|
||||
@Test public void Dot__initials() { // EX: "H. G. Wells"
|
||||
fxt.Clear().Test_split("a. b. cde", "a.", "b.", "cde");
|
||||
}
|
||||
@Test public void Dot__abrv() { // EX: "vs.", "no."
|
||||
fxt.Clear().Test_split("a vs. b", "a", "vs.", "b");
|
||||
}
|
||||
@Test public void Dot__internet() { // EX: "en.wikipedia.org"
|
||||
fxt.Clear().Test_split("a.com", "a.com");
|
||||
}
|
||||
@Test public void Ellipsis__basic() { // EX: "Nights into Dreams..."
|
||||
fxt.Clear().Test_split("a... bc d", "a", "...", "bc", "d");
|
||||
}
|
||||
@Test public void Ellipsis__bgn() {
|
||||
fxt.Clear().Test_split("...a", "...", "a");
|
||||
}
|
||||
@Test public void Ellipsis__end() {
|
||||
fxt.Clear().Test_split("a...", "a", "...");
|
||||
}
|
||||
@Test public void Ellipsis__no_ws() {
|
||||
fxt.Clear().Test_split("a...b", "a", "...", "b");
|
||||
}
|
||||
@Test public void Apos__contraction() { // EX: "I'm"
|
||||
fxt.Clear().Test_split("i'm", "i'm");
|
||||
}
|
||||
@Test public void Apos__multiple() {
|
||||
fxt.Clear().Test_split("a''b", "a''b");
|
||||
}
|
||||
@Test public void Apos__possessive_singular_eos() {// EX: "wiki's"
|
||||
fxt.Clear().Test_split("a's", "a", "a's");
|
||||
}
|
||||
@Test public void Apos__possessive_singular_word() {
|
||||
fxt.Clear().Test_split("a's b", "a", "a's", "b");
|
||||
}
|
||||
@Test public void Apos__possessive_plural_eos() {// EX: "wiki'"
|
||||
fxt.Clear().Test_split("a'", "a", "a'");
|
||||
}
|
||||
@Test public void Apos__possessive_plural_word() {
|
||||
fxt.Clear().Test_split("a' b", "a", "a'", "b");
|
||||
}
|
||||
@Test public void Bang__lone() {
|
||||
fxt.Clear().Test_split("! a", "a");
|
||||
}
|
||||
@Test public void Bang__word() {
|
||||
fxt.Clear().Test_split("a!", "a");
|
||||
}
|
||||
@Test public void Bang__sentence() {// EX: "A!"
|
||||
fxt.Clear().Test_split("a b!", "a", "b");
|
||||
}
|
||||
@Test public void Question__sentence() {// EX: "A?"
|
||||
fxt.Clear().Test_split("a?", "a");
|
||||
}
|
||||
@Test public void Parens_both() {// EX: "A (letter)"
|
||||
fxt.Clear().Test_split("a (b)", "a", "b");
|
||||
}
|
||||
@Test public void Slash__word() {// EX: "Good_cop/bad_cop"
|
||||
fxt.Clear().Test_split("a/b", "a", "b");
|
||||
}
|
||||
// apos: 'Some apostrophe sentence' ?
|
||||
}
|
||||
class Xows_text_parser__v2_fxt {
|
||||
private final Xows_text_parser__v2 word_parser = new Xows_text_parser__v2();
|
||||
private final Xob_word_mgr word_mgr = new Xob_word_mgr();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_(32);
|
||||
private Xol_case_mgr case_mgr;
|
||||
public void Init() {
|
||||
case_mgr = Xol_case_mgr_.A7();
|
||||
word_parser.Init_for_ttl(word_mgr, case_mgr);
|
||||
}
|
||||
public Xows_text_parser__v2_fxt Clear() {
|
||||
word_mgr.Clear();
|
||||
return this;
|
||||
}
|
||||
public Xob_word_itm Make_word(String raw, int count) {return new Xob_word_itm(Bry_.new_u8(raw)).Count_(count);}
|
||||
public void Test_split(String src, String... expd_words) {
|
||||
int len = expd_words.length;
|
||||
Xob_word_itm[] ary = new Xob_word_itm[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
ary[i] = Make_word(expd_words[i], 1);
|
||||
}
|
||||
Test_split(src, ary);
|
||||
}
|
||||
public void Test_split(String src, Xob_word_itm... expd_words) {
|
||||
byte[] src_bry = Bry_.new_u8(src);
|
||||
word_parser.Parse(src_bry, src_bry.length, 0, src_bry.length);
|
||||
Tfds.Eq_str_lines(To_str(expd_words), To_str(word_mgr));
|
||||
}
|
||||
private String To_str(Xob_word_itm[] word_ary) {
|
||||
int len = word_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (i != 0) tmp_bfr.Add_byte_nl();
|
||||
Xob_word_itm word = word_ary[i];
|
||||
tmp_bfr.Add(word.Word()).Add_byte_pipe();
|
||||
tmp_bfr.Add_int_variable(word.Count());
|
||||
}
|
||||
return tmp_bfr.To_str_and_clear();
|
||||
}
|
||||
private String To_str(Xob_word_mgr word_mgr) {
|
||||
int len = word_mgr.Len();
|
||||
Xob_word_itm[] ary = new Xob_word_itm[len];
|
||||
for (int i = 0; i < len; ++i)
|
||||
ary[i] = word_mgr.Get_at(i);
|
||||
return To_str(ary);
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.specials.search.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
|
||||
import gplx.core.btries.*; import gplx.core.primitives.*;
|
||||
interface Xows_text_tkn {
|
||||
int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end);
|
||||
}
|
||||
class Xows_text_tkn__split implements Xows_text_tkn {
|
||||
private final boolean add_sym_as_word;
|
||||
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs();
|
||||
public Xows_text_tkn__split(boolean add_sym_as_word, byte[][] ary) {
|
||||
this.add_sym_as_word = add_sym_as_word;
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] itm = ary[i];
|
||||
trie.Add_obj(itm, Int_obj_val.new_(itm.length));
|
||||
}
|
||||
}
|
||||
public int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end) {
|
||||
if (mgr.Bgn__ws() != -1) // pending word
|
||||
mgr.Word__add(mgr.Bgn__ws(), tkn_bgn); // make word; EX: "B" in "A B C"
|
||||
mgr.Bgn__ws_clear();
|
||||
if (add_sym_as_word)
|
||||
mgr.Word__add(tkn_bgn, tkn_end);
|
||||
int rv = tkn_end;
|
||||
while (rv < src_end) { // skip ws; EX: "a b"
|
||||
byte b = src[rv];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, rv, src_end);
|
||||
if (o == null) break;
|
||||
Int_obj_val itm_len = (Int_obj_val)o;
|
||||
rv += itm_len.Val();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public boolean Is_word_end(byte[] src, int end, int pos) {
|
||||
if (pos >= end) return true;
|
||||
byte b = src[pos];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, pos, end);
|
||||
return o != null;
|
||||
}
|
||||
public static Xows_text_tkn__split new_(Btrie_slim_mgr trie, boolean add_sym_as_word, String... str_ary) {
|
||||
byte[][] bry_ary = Bry_.Ary(str_ary);
|
||||
Xows_text_tkn__split rv = new Xows_text_tkn__split(add_sym_as_word, bry_ary);
|
||||
int len = bry_ary.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
trie.Add_obj(bry_ary[i], rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Xows_text_tkn__ellipsis implements Xows_text_tkn {
|
||||
private final byte ellipsis_byte;
|
||||
public Xows_text_tkn__ellipsis(byte ellipsis_byte) {
|
||||
this.ellipsis_byte = ellipsis_byte;
|
||||
}
|
||||
public int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end) {
|
||||
int bgn__ws = mgr.Bgn__ws();
|
||||
if (bgn__ws != -1) {
|
||||
mgr.Word__add(bgn__ws, tkn_bgn); // add word; EX: "Dreams" in "Dreams..."
|
||||
mgr.Bgn__ws_clear(); // clear ws flag, else space will create word; EX: "A... B"
|
||||
}
|
||||
int rv = Bry_find_.Find_fwd_while(src, tkn_end, src_end, ellipsis_byte);
|
||||
mgr.Word__add(tkn_bgn, rv); // add ellipssis
|
||||
return rv;
|
||||
}
|
||||
public static Xows_text_tkn new_(Btrie_slim_mgr trie, String ellipsis) {
|
||||
byte[] bry = Bry_.new_u8(ellipsis);
|
||||
Xows_text_tkn rv = new Xows_text_tkn__ellipsis(Bry_.Get_at_end(bry));
|
||||
trie.Add_obj(bry, rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Xows_text_tkn__apos implements Xows_text_tkn {
|
||||
private final byte possessive_byte;
|
||||
public Xows_text_tkn__apos(byte possessive_byte) {this.possessive_byte = possessive_byte;}
|
||||
public int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end) {
|
||||
int rv = tkn_end;
|
||||
byte apos_mode = Apos_contraction;
|
||||
if (tkn_end == src_end) { // EX: "A'<EOS>"
|
||||
apos_mode = Apos_possessive_plural;
|
||||
rv = src_end;
|
||||
}
|
||||
else if (mgr.Ws__is_word_end(tkn_end)) { // EX: "A' "
|
||||
apos_mode = Apos_possessive_plural;
|
||||
rv = tkn_end;
|
||||
}
|
||||
else if ( src[tkn_end] == possessive_byte // EX: "A's "
|
||||
&& mgr.Ws__is_word_end(tkn_end + 1))
|
||||
{
|
||||
apos_mode = Apos_possessive_singular;
|
||||
rv = tkn_end + 1;
|
||||
}
|
||||
switch (apos_mode) {
|
||||
case Apos_possessive_plural:
|
||||
case Apos_possessive_singular:
|
||||
int word_bgn = mgr.Bgn__ws();
|
||||
mgr.Word__add(word_bgn, tkn_bgn); // add noun; EX: "wiki";
|
||||
mgr.Word__add(word_bgn, rv); // add full; EX: "wiki's"
|
||||
mgr.Bgn__ws_clear();
|
||||
return rv;
|
||||
case Apos_contraction:
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static final byte Apos_contraction = 1, Apos_possessive_plural = 2, Apos_possessive_singular = 3;
|
||||
public static Xows_text_tkn new_(Btrie_slim_mgr trie, String apos, byte possessive_byte) {
|
||||
byte[] bry = Bry_.new_u8(apos);
|
||||
Xows_text_tkn rv = new Xows_text_tkn__apos(possessive_byte);
|
||||
trie.Add_obj(bry, rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
// class Xows_text_tkn__slash : Xows_text_tkn {
|
||||
// public int Parse(Xows_text_parser__v2 mgr, byte[] src, int src_end, int tkn_bgn, int tkn_end) {
|
||||
// int bgn__dash = mgr.Bgn__dash();
|
||||
// // add part;
|
||||
// int part_bgn = mgr.Bgn__dash();
|
||||
// if (part_bgn == -1) // no dash
|
||||
// part_bgn = mgr.Bgn__ws();
|
||||
// if (part_bgn != -1)
|
||||
// mgr.Word__add(part_bgn, tkn_bgn); // add word; EX: "a" in "a-b"
|
||||
// mgr.Bgn__dash_(tkn_end);
|
||||
// return tkn_end;
|
||||
// }
|
||||
// public static Xows_text_tkn new_(Btrie_slim_mgr trie, String dash) {
|
||||
// byte[] bry = Bry_.new_u8(dash);
|
||||
// Xows_text_tkn rv = new Xows_text_tkn__slash();
|
||||
// trie.Add_obj(bry, rv);
|
||||
// return rv;
|
||||
// }
|
||||
// }
|
||||
@@ -52,7 +52,7 @@ class Xop_statistics_stats_page_grp implements gplx.core.brys.Bfr_arg {
|
||||
byte[] lbl_pages = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_statistics_pages);
|
||||
byte[] lbl_pages_desc = wiki.Msg_mgr().Val_by_id(Xol_msg_itm_.Id_statistics_pages_desc);
|
||||
Xol_num_mgr num_mgr = wiki.Lang().Num_mgr();
|
||||
fmtr_page.Bld_bfr_many(bfr, lbl_header_pages, lbl_articles, lbl_pages, lbl_pages_desc , num_mgr.Format_num(wiki.Stats().NumArticles()), num_mgr.Format_num(wiki.Stats().NumPages()));
|
||||
fmtr_page.Bld_bfr_many(bfr, lbl_header_pages, lbl_articles, lbl_pages, lbl_pages_desc , num_mgr.Format_num_by_long(wiki.Stats().Num_articles()), num_mgr.Format_num_by_long(wiki.Stats().Num_pages()));
|
||||
}
|
||||
private Bry_fmtr fmtr_page = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
|
||||
@@ -39,7 +39,7 @@ class Xows_cmd__file_check {
|
||||
atr_main = wiki.File__fsdb_core().File__atr_file__at(Fsm_mnt_mgr.Mnt_idx_main);
|
||||
Write_kv(bfr, "fsdb.atr_file", atr_main.Url());
|
||||
} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx_full(e));}
|
||||
try {Write_kv(bfr, "fsdb.orig", wiki.File__fsdb_core().File__orig_tbl_ary()[0].Conn().Conn_info().Xto_raw());} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx_full(e));}
|
||||
try {Write_kv(bfr, "fsdb.orig", wiki.File__fsdb_core().File__orig_tbl_ary()[0].Conn().Conn_info().Raw());} catch (Exception e) {bfr.Add_str_u8(Err_.Message_gplx_full(e));}
|
||||
Fsdb_sql_mkr sql_mkr = schema_1 ? Fsdb_sql_mkr__v1.Instance : Fsdb_sql_mkr__v2.Instance;
|
||||
String sql = "";
|
||||
try {
|
||||
|
||||
@@ -28,7 +28,7 @@ public class Popup_history_page implements Xows_page {
|
||||
for (int i = len - 1; i > -1; --i) {
|
||||
Xow_popup_itm itm = (Xow_popup_itm)hash.Get_at(i);
|
||||
if (Ttl_chk(itm.Page_ttl())) continue;
|
||||
fmtr_main.Bld_bfr_many(bfr, itm.Page_href(), itm.Page_ttl().Full_txt());
|
||||
fmtr_main.Bld_bfr_many(bfr, itm.Page_href(), itm.Page_ttl().Full_txt_w_ttl_case());
|
||||
}
|
||||
page.Data_raw_(bfr.Trim_end(Byte_ascii.Nl).To_bry_and_rls());
|
||||
page.Html_data().Html_restricted_n_();
|
||||
|
||||
Reference in New Issue
Block a user