1
0
mirror of https://github.com/gnosygnu/xowa.git synced 2026-03-02 03:49:30 +00:00
This commit is contained in:
gnosygnu
2016-02-07 23:20:20 -05:00
parent 6d179ca59d
commit de67253a9c
215 changed files with 3387 additions and 2055 deletions

View File

@@ -17,8 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package gplx.xowa.specials.randoms; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
public class Rndm_core_row {
public Rndm_core_row(int type, int total, int interval) {this.type = type; this.total = total; this.interval = interval;}
public final int type;
public final int total;
public final int interval;
public void Load(int uid, String where_sql, int total, int interval) {this.uid = uid; this.where_sql = where_sql; this.total = total; this.interval = interval;}
public int uid;
public String where_sql;
public int total;
public int interval;
}

View File

@@ -19,31 +19,34 @@ package gplx.xowa.specials.randoms; import gplx.*; import gplx.xowa.*; import gp
import gplx.core.ios.*; import gplx.dbs.*; import gplx.dbs.utls.*;
public class Rndm_core_tbl implements Rls_able {
private final String tbl_name = "rndm_core"; private final Dbmeta_fld_list flds = Dbmeta_fld_list.new_();
private final String fld_rndm_uid, fld_rndm_total, fld_rndm_interval;
private final Db_conn conn; private Db_stmt stmt_select, stmt_insert;
private final String fld_uid, fld_where_sql, fld_total, fld_interval;
private final Db_conn conn; private Db_stmt stmt_select;
public Rndm_core_tbl(Db_conn conn) {
this.conn = conn;
fld_rndm_uid = flds.Add_int("rndm_uid");
fld_rndm_total = flds.Add_int("rndm_total");
fld_rndm_interval = flds.Add_int("rndm_interval");
fld_uid = flds.Add_int_pkey("rndm_uid");
fld_where_sql = flds.Add_str("rndm_where_sql", 1024);
fld_total = flds.Add_int("rndm_total");
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_rndm_uid)));}
public void Insert(int uid, int total, int interval) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
stmt_insert.Clear().Val_int(fld_rndm_uid, uid).Val_int(fld_rndm_total, total).Val_int(interval).Exec_insert();
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 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();
}
public Rndm_core_row Select(int uid) {
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_rndm_uid);
Db_rdr rdr = stmt_select.Clear().Val_int(fld_rndm_uid, uid).Exec_select__rls_manual();
public void Select(Rndm_core_row rv, int uid) {
if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_uid);
Db_rdr rdr = stmt_select.Clear().Val_int(fld_uid, uid).Exec_select__rls_manual();
try {
int total = rdr.Read_int(fld_rndm_total);
int interval = rdr.Read_int(fld_rndm_interval);
return new Rndm_core_row(uid, total, interval);
if (rdr.Move_next()) {
String where_sql = rdr.Read_str(fld_where_sql);
int total = rdr.Read_int(fld_total);
int interval = rdr.Read_int(fld_interval);
rv.Load(uid, where_sql, total, interval);
}
} finally {rdr.Rls();}
}
public void Rls() {
stmt_select = Db_stmt_.Rls(stmt_select);
stmt_insert = Db_stmt_.Rls(stmt_insert);
}
}

View File

@@ -0,0 +1,90 @@
/*
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.randoms; 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.tbls.*;
public class Rndm_mgr implements Rls_able {
private Rndm_core_tbl core_tbl; private final Rndm_core_row core_row = new Rndm_core_row();
private Rndm_range_tbl rng_tbl;
private Xowd_page_tbl page_tbl; private Db_stmt stmt__page__random;
public void Init(Db_conn conn, Xowd_page_tbl page_tbl) {
core_tbl = new Rndm_core_tbl(conn);
rng_tbl = new Rndm_range_tbl(conn);
this.page_tbl = page_tbl;
conn.Rls_reg(this);
}
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_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 {
while (rdr.Move_next()) {
++total_count; // add to total count first so (total_count % interval) is never 0 for total_count = 0
if (total_count % interval == 0) {
int cur_page_id = rdr.Read_int(page_tbl.Fld_page_id());
rng_list.Add(Int_obj_ref.new_(cur_page_id));
}
}
}
finally {rdr.Rls();}
conn.Txn_bgn("rndm_rebuild");
core_tbl.Upsert(uid, where_sql, total_count, interval);
int rng_ary_len = rng_list.Count();
rng_tbl.Insert_bgn(uid);
for (int i = 0; i < rng_ary_len; ++i) {
Int_obj_ref rng_itm = (Int_obj_ref)rng_list.Get_at(i);
rng_tbl.Insert_itm(uid, i + 1, rng_itm.Val());
}
rng_tbl.Insert_end();
conn.Txn_end();
}
public int Get_rndm_page(int uid) { // EX: ns=0;type_is_redirect=0
synchronized (core_row) {core_tbl.Select(core_row, uid);}
int rndm_num = RandomAdp_.new_().Next(core_row.total);
int rng_idx = rndm_num / core_row.interval;
int itm_idx = rndm_num % core_row.interval;
int page_id_bgn = rng_idx == 0 ? 0 : rng_tbl.Select_or_neg_1(uid, rng_idx);
int rv = Select_by_offset(core_row.where_sql, page_id_bgn, itm_idx);
return rv;
}
private int Select_by_offset(String where_sql, int page_id_bgn, int offset) {
Bry_bfr bfr = Bry_bfr.new_();
where_sql = fmt_where.Fmt_(where_sql).Bld_many_to_str(bfr, page_tbl.Fld_page_ns(), page_tbl.Fld_is_redirect());
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);
return rdr.Move_next() ? rdr.Read_int(page_tbl.Fld_page_id()) : -1;
}
finally {rdr.Rls();}
}
public void Rls() {
stmt__page__random = Db_stmt_.Rls(stmt__page__random);
}
private static final Bry_fmt fmt_sql = Bry_fmt.New(String_.Concat_lines_nl_skip_last
( "SELECT p.~{page_id}"
, "FROM ~{page} p"
, "WHERE p.~{~page_id} > ~{page_id_bgn}"
, "~{where_sql}"
, "ORDER BY ~{page_id}"
, "LIMIT 1"
, "OFFSET ~{offset};"
), "page", "page_id", "where_sql", "page_id_bgn", "offset");
private static final Bry_fmt fmt_where = Bry_fmt.New("", "page_namespace", "page_is_redirect");
}

View File

@@ -29,29 +29,24 @@ public class Rndm_range_tbl implements Rls_able {
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 Insert(int uid, int idx, int page_id) {
if (stmt_insert == null) stmt_insert = conn.Stmt_insert(tbl_name, flds);
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);
}
public void Insert_itm(int uid, int idx, int page_id) {
stmt_insert.Clear().Val_int(fld_rng_uid, uid).Val_int(fld_rng_idx, idx).Val_int(fld_rng_page_id, page_id).Exec_insert();
}
public void Select(int type) {
// if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_rng_uid);
// Db_rdr rdr = stmt_select.Clear().Val_int(fld_rng_type, type).Exec_select__rls_manual();
// try {
// int total = rdr.Read_int(fld_rng_total);
// int interval = rdr.Read_int(fld_rng_interval);
// return new Rndm_core_row(type, total, interval);
// } finally {rdr.Rls();}
public void Insert_end() {
stmt_insert = Db_stmt_.Rls(stmt_insert);
}
public int Select_or_neg_1(int core_uid, int rng_idx) {
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;}
finally {rdr.Rls();}
}
public void Rls() {
stmt_select = Db_stmt_.Rls(stmt_select);
stmt_insert = Db_stmt_.Rls(stmt_insert);
}
public void Get_random(int uid) {
// Rndm_core_row core_row = core_tbl.Get(uid);
// int rnd = RandomAdp_.new_().Next(core_row.total);
// int idx = rnd / core_row.interval;
// int off = rnd % core_row.interval;
// Rndm_rng_row rng_row = rng_tbl.Get(uid, idx);
// Xowd_page page = page_tbl.Get_by_page_offset(rng_row.page_id_bgn, off);
}
}

View File

@@ -0,0 +1,40 @@
/*
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.randoms; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
import gplx.xowa.bldrs.*;
public class Xob_rnd_cmd implements Xob_cmd {
private final Xowe_wiki wiki;
private int rndm_uid = 0; private String rndm_where_sql = "AND ~{page_namespace} = 0 AND ~{page_is_redirect} = 0"; private int rndm_interval = 1000;
public Xob_rnd_cmd(Xob_bldr bldr, Xowe_wiki wiki) {this.wiki = wiki;}
public String Cmd_key() {return Xob_cmd_keys.Key_util_random;}
public void Cmd_run() {
wiki.Special_mgr().Page_random().Mgr().Rebuild(rndm_uid, rndm_where_sql, rndm_interval);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Invk_rndm_uid_)) rndm_uid = m.ReadInt("v");
else if (ctx.Match(k, Invk_rndm_where_sql_)) rndm_where_sql = m.ReadStr("v");
else if (ctx.Match(k, Invk_rndm_interval_)) rndm_interval = m.ReadInt("v");
else return GfoInvkAble_.Rv_unhandled;
return this;
} private static final String Invk_rndm_uid_ = "rndm_uid_", Invk_rndm_where_sql_ = "rndm_where_sql_", Invk_rndm_interval_ = "rndm_interval_";
public void Cmd_init(Xob_bldr bldr) {}
public void Cmd_bgn(Xob_bldr bldr) {}
public void Cmd_end() {}
public void Cmd_term() {}
}

View File

@@ -19,6 +19,7 @@ package gplx.xowa.specials.randoms; import gplx.*; import gplx.xowa.*; import gp
import gplx.xowa.wikis.nss.*;
public class Xows_page_random implements Xows_page {
public Xows_page_random(Xowe_wiki wiki) {}
public Rndm_mgr Mgr() {return mgr;} private final Rndm_mgr mgr = new Rndm_mgr();
public Xows_special_meta Special_meta() {return Xows_special_meta_.Itm__random;}
public void Special_gen(Xowe_wiki wiki, Xoae_page page, Xoa_url url, Xoa_ttl ttl) {
Xow_ns ns = wiki.Ns_mgr().Names_get_or_main(ttl.Rest_txt());

View File

@@ -0,0 +1,130 @@
/*
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");
}

View File

@@ -0,0 +1,44 @@
/*
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);}
}

View File

@@ -16,27 +16,27 @@ 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.parsers_old.*;
class Xows_db_cache { // one cache per search term; EX: "Earth* AND (History OR Future) AND -"middle earth"" is one cache
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 Xows_db_word[] Words() {return words;} private Xows_db_word[] words; // words in cache; EX: earth, history, future but not "middle earth" (since not'ed)
public Xows_db_matcher Matcher() {return matcher;} private Xows_db_matcher matcher; // criteria
public boolean Done() {return done;} public void Done_y_() {done = true;} private boolean done; // marks if db search is done
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.matcher = new Xow_search_parser().Parse(raw);
this.words = new Xows_db_matcher_bldr().Gather_words_for_db(cxl, matcher, 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 Xows_db_row Get_at(int i) {return (Xows_db_row)hash.Get_at(i);}
public void Add(Xows_db_row row) {hash.Add(row.Page_ttl().Full_db(), row);}
public void Get_between(Xows_ui_rslt search_ui, int bgn, int end) {
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((Xows_db_row)hash.Get_at(i));
search_ui.Add((Srch_rslt_itm)hash.Get_at(i));
}
}
public void Sort() {hash.Sort_by(Xows_db_row_sorter.Page_len_dsc);}
public void Sort() {hash.Sort_by(Srch_rslt_itm_sorter.Page_len_dsc);}
}

View File

@@ -0,0 +1,40 @@
/*
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() {}
}

View File

@@ -16,9 +16,9 @@ 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 Xows_ui_rslt {
private final List_adp rslt_list = List_adp_.new_();
public int Len() {return rslt_list.Count();}
public void Add(Xows_db_row rslt) {rslt_list.Add(rslt);}
public Xows_db_row Get_at(int i) {return (Xows_db_row)rslt_list.Get_at(i);}
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);}
}

View File

@@ -16,6 +16,6 @@ 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 Xows_ui_async {
void Add(Xows_db_row new_row);
public interface Srch_rslt_lnr {
void Notify_rslt_found(Srch_rslt_itm rslt);
}

View File

@@ -16,21 +16,21 @@ 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 Xows_db_word {
public Xows_db_word(int id, byte[] text, int page_count) {this.id = id; this.text = text; this.page_count = page_count;}
public int Id() {return id;} private final int id;
public byte[] Text() {return text;} private final byte[] text;
public int Page_count() {return page_count;} private final int page_count;
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 Xows_db_word_sorter implements gplx.core.lists.ComparerAble {
class Srch_word_row_sorter implements gplx.core.lists.ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
Xows_db_word lhs = (Xows_db_word)lhsObj;
Xows_db_word rhs = (Xows_db_word)rhsObj;
return -Int_.Compare(lhs.Page_count(), rhs.Page_count());
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 Xows_db_word_sorter Page_count_dsc = new Xows_db_word_sorter(); Xows_db_word_sorter() {}
public static final Srch_word_row_sorter Page_count_dsc = new Srch_word_row_sorter(); Srch_word_row_sorter() {}
}

View File

@@ -24,17 +24,17 @@ class Xows_core {
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 Xows_db_cache Get_cache_or_new(byte[] key) {
Xows_db_cache cache = (Xows_db_cache)cache_hash.Get_by_bry(key);
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 Xows_db_cache();
cache = new Srch_rslt_hash();
cache_hash.Add_bry_obj(key, cache);
}
return cache;
}
public void Search(Xow_wiki search_wiki, Xoae_page page, Xows_ui_qry qry) {
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;
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 {
@@ -44,7 +44,7 @@ class Xows_core {
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);
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();

View File

@@ -1,68 +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.regxs.*;
public class Xows_db_matcher {
private final Gfo_pattern raw_pattern;
public Xows_db_matcher(int tid, byte[] raw, Xows_db_matcher lhs, Xows_db_matcher 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 int Tid() {return tid;} private final int tid;
public int Page_count() {return page_count;} public void Page_count_(int v) {page_count = v;} private int page_count;
public byte[] Raw() {return raw;} private final byte[] raw;
public Xows_db_matcher Lhs() {return lhs;} private final Xows_db_matcher lhs;
public Xows_db_matcher Rhs() {return rhs;} private final Xows_db_matcher rhs;
public boolean Matches(byte[] page_ttl_lc, byte[][] page_ttl_words) {
switch (tid) {
case Xows_db_matcher.Tid_word: {
int len = page_ttl_words.length;
for (int i = 0; i < len; ++i) {
byte[] word = page_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 Xows_db_matcher.Tid_word_quote: // note that raw does not have quotes; EX: "B*" -> B*
return Bry_find_.Find_fwd(page_ttl_lc, raw) != Bry_find_.Not_found;
case Xows_db_matcher.Tid_not:
return !rhs.Matches(page_ttl_lc, page_ttl_words);
case Xows_db_matcher.Tid_or:
return lhs.Matches(page_ttl_lc, page_ttl_words) || rhs.Matches(page_ttl_lc, page_ttl_words);
case Xows_db_matcher.Tid_and:
return lhs.Matches(page_ttl_lc, page_ttl_words) && rhs.Matches(page_ttl_lc, page_ttl_words);
case Xows_db_matcher.Tid_null: return false;
default: throw Err_.new_unhandled(tid);
}
}
public static final Xows_db_matcher Null = new Xows_db_matcher(Xows_db_matcher.Tid_null, null, null, null);
public static Xows_db_matcher new_join(byte tid, Xows_db_matcher lhs, Xows_db_matcher rhs) {return new Xows_db_matcher(tid, null, lhs, rhs);}
public static final int
Tid_word = 0
, Tid_and = 1
, Tid_or = 2
, Tid_not = 3
, Tid_word_quote = 4
, Tid_null = 5
;
}

View File

@@ -17,47 +17,48 @@ 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 Xows_db_word[] Gather_words_for_db(Cancelable cxl, Xows_db_matcher matcher, Xowd_search_word_tbl word_tbl) {
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(Xows_db_word_sorter.Page_count_dsc);
return (Xows_db_word[])rv.To_ary(Xows_db_word.class);
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, Xows_db_matcher matcher, List_adp rv, Xowd_search_word_tbl word_tbl) {
switch (matcher.Tid()) {
case Xows_db_matcher.Tid_word:
byte[] word_text = matcher.Raw();
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 Xows_db_matcher.Tid_word_quote:
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);
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(Xows_db_word_sorter.Page_count_dsc);
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 Xows_db_matcher.Tid_and:
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);
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 Xows_db_matcher.Tid_or:
Gather_words_for_db(cxl, matcher.Lhs(), rv, word_tbl);
Gather_words_for_db(cxl, matcher.Rhs(), rv, word_tbl);
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 Xows_db_matcher.Tid_not: break; // never add "NOT" to db_search
case Xows_db_matcher.Tid_null: break; // should not happen
default: throw Err_.new_unhandled(matcher.Tid());
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) {
@@ -72,15 +73,15 @@ class Xows_db_matcher_bldr {
int rv = 0;
int len = list.Count();
for (int i = 0; i < len; ++i) {
Xows_db_word word = (Xows_db_word)list.Get_at(i);
rv += word.Page_count();
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;
Xows_db_word word = new Xows_db_word(row.Id(), row.Text(), row.Page_count());
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) {
@@ -89,7 +90,7 @@ class Xows_db_matcher_bldr {
int len = rows.length;
for (int i = 0; i < len; ++i) {
Xowd_search_word_row row = rows[i];
rv.Add(new Xows_db_word(row.Id(), row.Text(), row.Page_count()));
rv.Add(new Srch_word_row(row.Id(), row.Text(), row.Page_count()));
}
}
}

View File

@@ -1,41 +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 Xows_db_row {
public Xows_db_row(byte[] wiki_domain, Xoa_ttl page_ttl, int page_id, int page_len) {
this.wiki_domain = wiki_domain;
this.page_ttl = page_ttl;
this.page_id = page_id;
this.page_len = page_len;
this.key = Bry_.Add(wiki_domain, Byte_ascii.Pipe_bry, page_ttl.Full_db());
}
public byte[] Key() {return key;} private final byte[] key;
public byte[] Wiki_domain() {return wiki_domain;} private final byte[] wiki_domain;
public Xoa_ttl Page_ttl() {return page_ttl;} private final Xoa_ttl page_ttl;
public int Page_id() {return page_id;} private final int page_id;
public int Page_len() {return page_len;} private final int page_len;
public static Xows_db_row[] Ary(Xows_db_row... v) {return v;}
}
class Xows_db_row_sorter implements gplx.core.lists.ComparerAble {
public int compare(Object lhsObj, Object rhsObj) {
Xows_db_row lhs = (Xows_db_row)lhsObj;
Xows_db_row rhs = (Xows_db_row)rhsObj;
return -Int_.Compare(lhs.Page_len(), rhs.Page_len());
}
public static final Xows_db_row_sorter Page_len_dsc = new Xows_db_row_sorter(); Xows_db_row_sorter() {}
}

View File

@@ -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/>.
*/
package gplx.xowa.specials.search; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*;
import gplx.core.primitives.*; import gplx.dbs.*;
import gplx.xowa.wikis.nss.*;
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.langs.cases.*;
import gplx.gfui.*;
public class Xows_db_wkr {
private Xol_case_mgr drd_case_mgr;
public Xows_db_row[] Search_by_drd(Cancelable cancelable, Xow_wiki wiki, Xows_ui_async ui_async, byte[] search, int search_results_max) {
Xows_ns_mgr ns_mgr = new Xows_ns_mgr(); ns_mgr.Add_main_if_empty();
Xows_ui_qry qry = new Xows_ui_qry(search, 0, search_results_max, Xosrh_rslt_itm_sorter.Tid_len_dsc, ns_mgr, Bool_.Y, new gplx.xowa.wikis.domains.Xow_domain_itm[] {wiki.Domain_itm()});
Xows_ui_rslt rslt = new Xows_ui_rslt();
Xows_db_cache cache = new Xows_db_cache(); cache.Init_by_db(Cancelable_.Never, search, wiki.Data__core_mgr().Db__search().Tbl__search_word());
Xows_ui_cmd cmd = new Xows_ui_cmd(null, qry, wiki, null, null, null, cache, ui_async);
if (drd_case_mgr == null) drd_case_mgr = Xol_case_mgr_.U8();
Search(cancelable, cmd, qry, rslt, cache, wiki, drd_case_mgr);
int len = cache.Count();
Xows_db_row[] rv = new Xows_db_row[len];
for (int i = 0; i < len; ++i)
rv[i] = cache.Get_at(i);
return rv;
}
@gplx.Internal protected void Search(Cancelable cancelable, Xows_ui_cmd cmd, Xows_ui_qry qry, Xows_ui_rslt rslt, Xows_db_cache cache, Xow_wiki wiki, Xol_case_mgr case_mgr) {
// assert matcher
Xowd_db_file search_db = wiki.Data__core_mgr().Db__search();
Xoa_app_.Usr_dlg().Prog_many("", "", "search started (please wait)");
Xows_db_matcher matcher = cache.Matcher();
if (matcher == null) {
cache.Init_by_db
( cmd
, wiki.Lang().Case_mgr().Case_build_lower(qry.Search_raw()) // lower-case search
, search_db.Tbl__search_word()
);
matcher = cache.Matcher();
}
// 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();
Xows_db_word[] 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 (cancelable.Canceled()) return;
Xows_db_word 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 = String_.Format(Search_sql, link_tbl.Tbl_name(), link_tbl.Fld_page_id(), link_tbl.Fld_word_id(), word.Id(), "page_len", "DESC", Int_.Max_value, 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(cancelable, cmd, qry, rslt, cache, wiki, case_mgr, page_tbl, attach_rdr, sql, word, matcher, 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();
} finally {attach_rdr.Detach();}
}
private int Search_pages(Cancelable cancelable, Xows_ui_cmd cmd, Xows_ui_qry qry, Xows_ui_rslt rslt, Xows_db_cache cache, Xow_wiki wiki, Xol_case_mgr case_mgr, Xowd_page_tbl page_tbl, Db_attach_rdr attach_rdr, String sql, Xows_db_word word, Xows_db_matcher matcher, 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 (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());
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);
Xows_db_row row = new Xows_db_row(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;
}
private static final String Search_sql = String_.Concat_lines_nl_skip_last
( "SELECT cp.page_id"
, ", cp.page_namespace"
, ", cp.page_title"
, ", cp.page_len"
, "FROM {0} sp"
, " JOIN <attach_db>page cp ON cp.page_id = sp.{1} "
, "WHERE sp.{2} = {3}"
, "ORDER BY {4} {5}"
, "LIMIT {6}"
, "OFFSET {7};"
);
}

View File

@@ -20,34 +20,34 @@ 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 Xows_ui_qry qry; private Xow_wiki wiki; private Xol_num_mgr num_mgr;
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, Xows_ui_qry qry) {
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());
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[] 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, Xows_ui_rslt rslt, byte[] cmd_key, byte[] wiki_domain, boolean searching_db) {
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.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();
int paging_idx = qry.page_idx;
byte[] title = null, img_path = Bry_.Empty;
boolean img_pos_is_left = true;
if (fwd) {
@@ -92,24 +92,24 @@ class Xows_html_wkr {
;
}
class Xows_html_row implements gplx.core.brys.Bfr_arg {
private final Xoh_lnki_bldr lnki_bldr; private Xows_ui_rslt rslt;
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(Xows_ui_rslt rslt) {this.rslt = rslt; return this;}
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) {
Xows_db_row row = rslt.Get_at(i);
Srch_rslt_itm row = rslt.Get_at(i);
Gen_html(bfr, row);
}
}
public void Gen_html(Bry_bfr bfr, Xows_db_row row) {
public void Gen_html(Bry_bfr bfr, Srch_rslt_itm row) {
synchronized (thread_lock) {
lnki_bldr.Href_(row.Wiki_domain(), row.Page_ttl());
byte[] title = row.Page_ttl().Full_txt();
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());
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

View File

@@ -28,7 +28,7 @@ public class Xows_html_wkr_tst {
fxt.Test_paging(Bool_.N, 0, "&#160;");
}
@Test public void Rows() {
fxt.Test_rows(Xows_db_row.Ary(fxt.Make_row(10, "A"), fxt.Make_row(20, "B")), String_.Concat_lines_nl_skip_last
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"
@@ -56,14 +56,14 @@ class Xows_html_wkr_fxt {
return this;
}
public void Test_paging(boolean fwd, int paging_idx, String expd) {
Xows_ui_qry qry = new Xows_ui_qry(Bry_.new_a7("A"), paging_idx, 100, Xosrh_rslt_itm_sorter.Tid_len_dsc, new Xows_ns_mgr(), true, new Xow_domain_itm[] {Xow_domain_itm_.parse(wiki.Domain_bry())});
qry.Page_max_(2);
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(Xows_db_row[] rows, String expd) {
Xows_ui_rslt rslt = new Xows_ui_rslt();
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)
@@ -71,8 +71,8 @@ class Xows_html_wkr_fxt {
html_row.Bfr_arg__add(tmp_bfr);
Tfds.Eq_str_lines(expd, tmp_bfr.To_str_and_clear());
}
public Xows_db_row Make_row(int len, String ttl_str) {
public Srch_rslt_itm Make_row(int len, String ttl_str) {
byte[] ttl_bry = Bry_.new_u8(ttl_str);
return new Xows_db_row(Bry_.new_a7("w"), wiki.Ttl_parse(ttl_bry), 1, len);
return new Srch_rslt_itm(Bry_.new_a7("w"), wiki.Ttl_parse(ttl_bry), 1, len);
}
}

View File

@@ -26,9 +26,9 @@ public class Xows_ns_mgr {
ns_all = ns_main = false;
}
public boolean Has(int ns_id) {
return ns_all // all flag set
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
|| ns_hash.Has(tmp_ns_id.Val_(ns_id)) // check against ns_hash
;
}
public void Add_by_id(int ns_id) {
@@ -48,7 +48,7 @@ public class Xows_ns_mgr {
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
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);

View File

@@ -80,7 +80,7 @@ public class Xows_page__search implements Xows_page, GfoInvkAble, GfoEvObj {
}
page.Html_data().Html_restricted_n_();
page.Html_data().Xtn_search_text_(search_bry);
Xows_ui_qry qry = new Xows_ui_qry(search_bry, args_mgr.Paging_idx(), search_api.Results_per_page(), args_mgr.Sort_tid(), args_mgr.Ns_mgr(), search_api.Async_db(), search_domain_ary);
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;

View File

@@ -17,27 +17,27 @@ 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 Xows_ui_async {
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 Xows_db_row[] rows; private final int rows_len;
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 Xows_db_row[paging_len];
this.rows = new Srch_rslt_itm[paging_len];
this.rows_len = paging_len;
this.insert_new_key = Gen_insert_key(wiki);
}
public void Add(Xows_db_row new_row) {
Xows_db_row last_row = rows[rows_len - 1];
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;
Xows_db_row insert_row = rows[new_row_slot];
byte[] insert_key = insert_row == null ? insert_new_key : insert_row.Key();
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();
@@ -45,25 +45,25 @@ class Xows_ui_async__html implements Xows_ui_async {
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()), "");
js_wkr.Html_elem_replace_html(Gfh_utl.Encode_id_as_str(last_row.key), "");
}
}
private int Find_insert_slot(Xows_db_row new_row) {
private int Find_insert_slot(Srch_rslt_itm new_row) {
for (int i = 0; i < rows_len; ++i) {
Xows_db_row cur_row = rows[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, Xows_db_row new_row) {
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(Xows_db_row lhs, Xows_db_row rhs) {
return -Int_.Compare(lhs.Page_len(), rhs.Page_len());
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_");

View File

@@ -42,14 +42,14 @@ class Xows_ui_async_fxt {
html_row.Fmtr().Fmt_("~{page_key}");
async = new Xows_ui_async__html(Cancelable_.Never, html_row, js_wkr, 5, Bry_enwiki);
}
public Xows_db_row Make_rslt(int len, String ttl) {
public Srch_rslt_itm Make_rslt(int len, String ttl) {
byte[] ttl_bry = Bry_.new_a7(ttl);
return new Xows_db_row(Bry_enwiki, wiki.Ttl_parse(ttl_bry), 1, len);
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(Xows_db_row row, Object[]... expd) {
async.Add(row);
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) {

View File

@@ -18,21 +18,21 @@ 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, Xog_tab_close_lnr {
private final Xows_core mgr; private final Xows_ui_qry qry; private final Xows_ui_rslt rslt;
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 Xows_ui_async async_wkr;
private Xows_db_cache cache;
public Xows_ui_cmd(Xows_core mgr, Xows_ui_qry qry, Xow_wiki wiki, Xoae_page page, Xog_tab_close_mgr tab_close_mgr, Xog_js_wkr js_wkr, Xows_db_cache cache, Xows_ui_async async_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 Xows_ui_rslt();
this.key = Gfh_utl.Encode_id_as_bry(Bry_.Add(qry.Key(), Byte_ascii.Pipe_bry, wiki.Domain_bry()));
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 Xows_ui_rslt Rslt() {return rslt;}
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);
@@ -43,10 +43,10 @@ class Xows_ui_cmd implements GfoInvkAble, Cancelable, Xog_tab_close_lnr {
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 (!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());
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
@@ -54,8 +54,8 @@ class Xows_ui_cmd implements GfoInvkAble, Cancelable, Xog_tab_close_lnr {
rv = true;
}
if (fill_from_cache) {
cache.Get_between(rslt, qry.Itms_bgn(), qry.Itms_end());
qry.Page_max_(cache.Count() / qry.Page_len());
cache.Get_between(rslt, qry.itms_bgn, qry.itms_end);
qry.page_max = cache.Count() / qry.page_len;
}
return rv;
}
@@ -65,16 +65,16 @@ class Xows_ui_cmd implements GfoInvkAble, Cancelable, Xog_tab_close_lnr {
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();
int qry_itms_bgn = qry.itms_bgn, cache_count = cache.Count();
for (int i = qry_itms_bgn; i < cache_count; ++i)
async_wkr.Add(cache.Get_at(i));
async_wkr.Notify_rslt_found(cache.Get_at(i));
}
new Xows_db_wkr().Search(this, this, qry, rslt, cache, wiki, wiki.Lang().Case_mgr());
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());
qry.page_max = cache.Count() / qry.page_len;
Xoa_app_.Usr_dlg().Prog_many("", "", "");
}
private void Hide_cancel_btn() {
@@ -83,9 +83,9 @@ class Xows_ui_cmd implements GfoInvkAble, Cancelable, Xog_tab_close_lnr {
private void Hide_cancel_btn_async() {
js_wkr.Html_atr_set("xowa_cancel_" + wiki.Domain_str(), "style", "display:none;");
}
public void Add_rslt(Xows_db_row rslt) {
public void Notify_rslt_found(Srch_rslt_itm rslt) {
cache.Add(rslt);
if (async) async_wkr.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)

View File

@@ -1,45 +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 Xows_ui_qry {
private final List_adp cmd_list = List_adp_.new_();
public Xows_ui_qry(byte[] search_raw, int page_idx, int page_len, byte sort_tid, 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.sort_tid = sort_tid; this.ns_mgr = ns_mgr; this.async_db = async_db; this.wiki_domains = wiki_domains;
this.itms_bgn = page_idx * 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 byte[] Key() {return key;} private final byte[] key;
public byte[] Search_raw() {return search_raw;} private final byte[] search_raw;
public boolean Async_db() {return async_db;} private boolean async_db;
public int Page_idx() {return page_idx;} private final int page_idx;
public int Page_max() {return page_max;} private int page_max;
public int Page_len() {return page_len;} private final int page_len;
public int Itms_bgn() {return itms_bgn;} private final int itms_bgn;
public int Itms_end() {return itms_bgn + page_len;}
public byte Sort_tid() {return sort_tid;} private final byte sort_tid;
public Xows_ns_mgr Ns_mgr() {return ns_mgr;} private final Xows_ns_mgr ns_mgr;
public Xow_domain_itm[] Wiki_domains() {return wiki_domains;} private final Xow_domain_itm[] wiki_domains;
public void Page_max_(int v) {this.page_max = v;}
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);}
public byte[] Special_link_base_href() {return special_link_base_href;} private final byte[] special_link_base_href;
}

View File

@@ -0,0 +1,73 @@
/*
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
;
}

View File

@@ -0,0 +1,94 @@
/*
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;
}
}

View File

@@ -15,12 +15,12 @@ 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_old; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
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 Xow_search_scanner {
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 Xow_search_tkn[] Scan(byte[] src) {
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) {
@@ -35,27 +35,27 @@ class Xow_search_scanner {
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(Xow_search_tkn.Tid_word, txt_bgn, pos);
Tkns_add_word(Srch_crt_tkn.Tid_word, txt_bgn, pos);
txt_bgn = -1;
}
switch (cur_tid) {
case Xow_search_tkn.Tid_space: // discard spaces
case Srch_crt_tkn.Tid_space: // discard spaces
pos = Bry_find_.Find_fwd_while(src, pos, src_len, Byte_ascii.Space);
break;
case Xow_search_tkn.Tid_quote: // find end quote and add as word
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(Xow_search_tkn.Tid_word_quoted, quote_bgn, quote_end);
Tkns_add_word(Srch_crt_tkn.Tid_word_quoted, quote_bgn, quote_end);
pos = quote_end + 1; // +1 to place after quote
break;
case Xow_search_tkn.Tid_not:
Tkns_add_word(Xow_search_tkn.Tid_not, pos, pos_end);
case Srch_crt_tkn.Tid_not:
Tkns_add_word(Srch_crt_tkn.Tid_not, pos, pos_end);
pos = pos_end;
break;
case Xow_search_tkn.Tid_paren_bgn: case Xow_search_tkn.Tid_paren_end:
case Xow_search_tkn.Tid_and: case Xow_search_tkn.Tid_or:
tkns.Add(new_tkn(cur_tid, pos, pos_end));
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);
@@ -63,20 +63,20 @@ class Xow_search_scanner {
}
}
if (txt_bgn != -1) { // pending word; create
Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos);
Tkns_add_word(Srch_crt_tkn.Tid_word, txt_bgn, pos);
txt_bgn = -1;
}
return (Xow_search_tkn[])tkns.To_ary_and_clear(Xow_search_tkn.class);
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 Xow_search_tkn.Tid_and: case Xow_search_tkn.Tid_or: case Xow_search_tkn.Tid_not:
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 == Xow_search_tkn.Tid_not) return false; // NOT is only operator if no pending tkn; EX: -abc -> NOT abc; a-b -> a-b
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
@@ -84,11 +84,11 @@ class Xow_search_scanner {
else { // next tkn is tkn
byte nxt_tid = ((Byte_obj_val)nxt_obj).Val();
switch (nxt_tid) {
case Xow_search_tkn.Tid_space: case Xow_search_tkn.Tid_quote:
case Xow_search_tkn.Tid_paren_bgn: case Xow_search_tkn.Tid_paren_end:
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 Xow_search_tkn.Tid_not: case Xow_search_tkn.Tid_and: case Xow_search_tkn.Tid_or:
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);
@@ -104,18 +104,18 @@ class Xow_search_scanner {
return true;
}
if (txt_bgn != -1) {
Tkns_add_word(Xow_search_tkn.Tid_word, txt_bgn, pos); // create word
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"
Xow_search_tkn last_tkn = (Xow_search_tkn)tkns.Get_at_last();
if (last_tkn.Tid() == Xow_search_tkn.Tid_word) // previous tkn is word; auto "AND" words; EX: A B -> A AND B
tkns.Add(Xow_search_tkn.new_bry(Xow_search_tkn.Tid_and, Bry_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 == Xow_search_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
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;
@@ -123,22 +123,22 @@ class Xow_search_scanner {
&& !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(Xow_search_tkn.new_bry(tid, words[0]));
tkns.Add(new Srch_crt_tkn(tid, words[0]));
return;
}
if (words.length > 1) // multiple words; add as quoted-term; EX: "a-b"
tid = Xow_search_tkn.Tid_word_quoted;
tid = Srch_crt_tkn.Tid_word_quoted;
}
tkns.Add(new_tkn(tid, src_bgn, src_end));
tkns.Add(new_tkn(tid, src, src_bgn, src_end));
}
private Xow_search_tkn new_tkn(byte tid, int val_bgn, int val_end) {return Xow_search_tkn.new_pos(tid, val_bgn, val_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(" " , Xow_search_tkn.Tid_space)
.Add_str_byte("\"" , Xow_search_tkn.Tid_quote)
.Add_str_byte("-" , Xow_search_tkn.Tid_not)
.Add_str_byte("(" , Xow_search_tkn.Tid_paren_bgn)
.Add_str_byte(")" , Xow_search_tkn.Tid_paren_end)
.Add_str_byte("or" , Xow_search_tkn.Tid_or)
.Add_str_byte("and" , Xow_search_tkn.Tid_and);
.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);
}

View File

@@ -15,11 +15,23 @@ 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.quicks; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
public class Xoa_search_mgr {
public Xoa_search_itm[] Search(byte[] search) {
// page_title LIKE 'Ear%'
// page_title LIKE '%Ear%'
return null;
}
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
;
}

View File

@@ -0,0 +1,80 @@
/*
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;
//// }
// }
//}

View File

@@ -0,0 +1,125 @@
/*
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
// }
// }
//}

View File

@@ -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.parsers_old; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
public class Xow_search_parser {
private Xow_search_parser_ctx parse_ctx = new Xow_search_parser_ctx(); private byte[] src;
public Xows_db_matcher Parse(byte[] src) {
this.src = src;
Xow_search_tkn[] tkns = new Xow_search_scanner().Scan(src);
return Parse_itm_or(parse_ctx.Init(tkns));
}
private Xows_db_matcher Parse_itm_or(Xow_search_parser_ctx parse_ctx) {
Xows_db_matcher lhs = Parse_itm_and(parse_ctx);
while (parse_ctx.Cur_tid(Xow_search_tkn.Tid_or)) {
parse_ctx.Move_next();
Xows_db_matcher rhs = Parse_itm_and(parse_ctx);
lhs = new_join(Xows_db_matcher.Tid_or, lhs, rhs);
}
return lhs;
}
private Xows_db_matcher Parse_itm_and(Xow_search_parser_ctx parse_ctx) {
Xows_db_matcher lhs = Parse_itm_not(parse_ctx);
while (parse_ctx.Cur_tid(Xow_search_tkn.Tid_and)) {
parse_ctx.Move_next();
Xows_db_matcher rhs = Parse_itm_not(parse_ctx);
lhs = new_join(Xows_db_matcher.Tid_and, lhs, rhs);
}
return lhs;
}
private Xows_db_matcher Parse_itm_not(Xow_search_parser_ctx parse_ctx) {
Xows_db_matcher lhs = Parse_itm_leaf(parse_ctx);
while (parse_ctx.Cur_tid(Xow_search_tkn.Tid_not)) {
parse_ctx.Move_next();
Xows_db_matcher rhs = Parse_itm_leaf(parse_ctx);
lhs = new_join(Xows_db_matcher.Tid_not, null, rhs);
}
return lhs;
}
private Xows_db_matcher Parse_itm_leaf(Xow_search_parser_ctx parse_ctx) {
if (parse_ctx.Cur_tid(Xow_search_tkn.Tid_paren_bgn)) {
parse_ctx.Move_next();
Xows_db_matcher lhs = Parse_itm_or(parse_ctx);
if (parse_ctx.Cur_tid(Xow_search_tkn.Tid_paren_end)) parse_ctx.Move_next(); // skip token
return lhs;
}
else if (parse_ctx.Cur_tid(Xow_search_tkn.Tid_eos))
return Xows_db_matcher.Null;
else {
Xow_search_tkn word_tkn = parse_ctx.Move_next();
if (word_tkn.Tid() == Xow_search_tkn.Tid_not) {
word_tkn = parse_ctx.Move_next();
if (word_tkn == null) return Xows_db_matcher.Null; // occurs in "a -"
Xows_db_matcher word_itm = new_word(word_tkn, src);
return new_join(Xows_db_matcher.Tid_not, null, word_itm);
}
else
return new_word(word_tkn, src);
}
}
private static Xows_db_matcher new_word(Xow_search_tkn tkn, byte[] src) {
int tid = tkn.Tid() == Xow_search_tkn.Tid_word ? Xows_db_matcher.Tid_word : Xows_db_matcher.Tid_word_quote;
return new Xows_db_matcher(tid, tkn.Val(src), null, null);
}
private static Xows_db_matcher new_join(int tid, Xows_db_matcher lhs, Xows_db_matcher rhs) {return new Xows_db_matcher(tid, null, lhs, rhs);}
}
class Xow_search_parser_ctx {
private Xow_search_tkn[] ary; private int pos = 0; private int ary_len;
public Xow_search_parser_ctx Init(Xow_search_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 == Xow_search_tkn.Tid_eos;}
public Xow_search_tkn Move_next() {
Xow_search_tkn rv = null;
if (pos < ary_len) rv = ary[pos++];
return rv;
}
}

View File

@@ -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.parsers_old; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
class Xow_search_tkn {
private final int val_bgn, val_end;
private final byte[] val_bry;
Xow_search_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 final byte tid;
public byte[] Val(byte[] src) {return val_bry == null ? Bry_.Mid(src, val_bgn, val_end) : val_bry;}
public static Xow_search_tkn new_pos(byte tid, int val_bgn, int val_end) {return new Xow_search_tkn(tid, val_bgn, val_end, null);}
public static Xow_search_tkn new_bry(byte tid, byte[] val_bry) {return new Xow_search_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
;
}

View File

@@ -1,27 +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.quicks; import gplx.*; import gplx.xowa.*; import gplx.xowa.specials.*; import gplx.xowa.specials.search.*;
public class Xoa_search_itm {
public Xoa_search_itm(byte[] url, byte[] name, byte[] descrip, byte[] img) {
this.url = url; this.name = name; this.descrip = descrip; this.img = img;
}
public byte[] Url() {return url;} private final byte[] url; // EX: en.wikipedia.org/wiki/Earth
public byte[] Name() {return name;} private final byte[] name; // EX: Earth
public byte[] Descrip() {return descrip;} private final byte[] descrip; // EX: Third planet from the Sun
public byte[] Img() {return img;} private final byte[] img; // EX: Earth.png
}

View File

@@ -25,7 +25,7 @@ class Db_rdr_utl {
}
public static Mem_qry_set Load_as_qry_set(Db_conn conn, Dbmeta_fld_list fld_list, String sql) {
Mem_qry_set qry_set = new Mem_qry_set();
DataRdr rdr = conn.Exec_sql_as_rdr(sql);
DataRdr rdr = conn.Exec_sql_as_old_rdr(sql);
try {
int fld_count = rdr.FieldCount();
while (rdr.MoveNextPeer()) {
@@ -42,7 +42,7 @@ class Db_rdr_utl {
}
public static Object[][] Load(Db_conn conn, String sql) {
List_adp list = List_adp_.new_();
DataRdr rdr = conn.Exec_sql_as_rdr(sql);
DataRdr rdr = conn.Exec_sql_as_old_rdr(sql);
try {
int fld_count = rdr.FieldCount();
while (rdr.MoveNextPeer()) {