mirror of
https://github.com/gnosygnu/xowa.git
synced 2026-03-02 03:49:30 +00:00
'v3.6.3.1'
This commit is contained in:
@@ -1,57 +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.addons.apps.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Xoax_ctg_addon implements Xoax_addon_itm { // TODO:mem_mgr
|
||||
private final Xow_wiki wiki;
|
||||
private final Hash_adp_bry hash = Hash_adp_bry.cs();
|
||||
public Xoax_ctg_addon(Xow_wiki wiki) {this.wiki = wiki;}
|
||||
public Xoctg_ctg_itm Itms__get_or_null(byte[] key) {return (Xoctg_ctg_itm)hash.Get_by_bry(key);}
|
||||
public Xoctg_ctg_itm Itms__load(byte[] key) {
|
||||
Xowd_page_itm tmp_page = new Xowd_page_itm();
|
||||
wiki.Data__core_mgr().Tbl__page().Select_by_ttl(tmp_page, wiki.Ns_mgr().Ns_category(), key);
|
||||
gplx.xowa.wikis.data.tbls.Xowd_category_itm itm = wiki.Data__core_mgr().Db__cat_core().Tbl__cat_core().Select(tmp_page.Id());
|
||||
return Itms__add(key, itm.Count_pages(), itm.Count_subcs(), itm.Count_files());
|
||||
}
|
||||
public Xoctg_ctg_itm Itms__add(byte[] key, int pages, int subcs, int files) { // TEST:
|
||||
Xoctg_ctg_itm rv = new Xoctg_ctg_itm(key, pages, subcs, files);
|
||||
hash.Add(key, rv);
|
||||
return rv;
|
||||
}
|
||||
/*
|
||||
public long Mem__size__max() {return mem__size__max;} private long mem__size__max;
|
||||
public long Mem__size__reduce() {return mem__size__reduce;} private long mem__size__reduce;
|
||||
public void Mem__free__all() {hash.Clear();}
|
||||
public void Mem__free__reduce() {Mem_mgr_.Free__reduce(hash);}
|
||||
public void Mem__free__unused() {Mem_mgr_.Free__unused(hash);}
|
||||
public long Mem__stat__size() {return mem__stat__size;} private long mem__stat__size;
|
||||
public long Mem__stat__last() {return mem__stat__last;} private long mem__stat__last;
|
||||
public int Mem__stat__count() {return mem__stat__count;} private int mem__stat__count;
|
||||
*/
|
||||
public static Xoax_ctg_addon Get(Xow_wiki wiki) {
|
||||
Xoax_ctg_addon rv = (Xoax_ctg_addon)wiki.Addon_mgr().Itms__get_or_null(ADDON_KEY);
|
||||
if (rv == null) {
|
||||
rv = new Xoax_ctg_addon(wiki);
|
||||
wiki.Addon_mgr().Itms__add(rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static final byte[] ADDON_KEY = Bry_.new_a7("xowa.apps.category");
|
||||
public byte[] Addon__key() {return ADDON_KEY;}
|
||||
}
|
||||
@@ -1,32 +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.addons.apps.ctgs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
public class Xoctg_ctg_itm {
|
||||
public Xoctg_ctg_itm(byte[] ttl_wo_ns, int pages, int subcs, int files) {
|
||||
this.Ttl_wo_ns = ttl_wo_ns;
|
||||
this.Pages = pages;
|
||||
this.Subcs = subcs;
|
||||
this.Files = files;
|
||||
this.All = pages + subcs + files;
|
||||
}
|
||||
public final byte[] Ttl_wo_ns;
|
||||
public final int Pages;
|
||||
public final int Subcs;
|
||||
public final int Files;
|
||||
public final int All;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.core.ios.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
class Fbrow_file_itm implements Mustache_doc_itm {
|
||||
private final boolean is_dir, is_core_xowa;
|
||||
private final byte[] owner_dir_enc, path, name, date, size, color;
|
||||
private final Fbrow_file_itm[] subs;
|
||||
public Fbrow_file_itm(boolean is_dir, boolean is_core_xowa, int color, byte[] owner_dir, byte[] path, byte[] name, byte[] date, byte[] size, Fbrow_file_itm[] subs) {
|
||||
this.is_dir = is_dir; this.is_core_xowa = is_core_xowa;
|
||||
this.color = color % 2 == 0 ? Byte_ascii.Num_0_bry : Byte_ascii.Num_1_bry;
|
||||
this.owner_dir_enc = gplx.langs.htmls.encoders.Gfo_url_encoder_.Href.Encode(owner_dir);
|
||||
this.path = path; this.name = name; this.date = date; this.size = size;
|
||||
this.subs = subs;
|
||||
}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "path")) bfr.Add_bry(path);
|
||||
else if (String_.Eq(key, "path_enc")) bfr.Add_bry(gplx.langs.htmls.encoders.Gfo_url_encoder_.Href.Encode(path));
|
||||
else if (String_.Eq(key, "owner_dir_enc")) bfr.Add_bry(owner_dir_enc);
|
||||
else if (String_.Eq(key, "name")) bfr.Add_bry(name);
|
||||
else if (String_.Eq(key, "date")) bfr.Add_bry(date);
|
||||
else if (String_.Eq(key, "size")) bfr.Add_bry(size);
|
||||
else if (String_.Eq(key, "color")) bfr.Add_bry(color);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
if (String_.Eq(key, "is_dir")) return Mustache_doc_itm_.Ary__bool(is_dir);
|
||||
else if (String_.Eq(key, "is_core_xowa")) return Mustache_doc_itm_.Ary__bool(is_core_xowa);
|
||||
else if (String_.Eq(key, "subs")) return subs;
|
||||
return Mustache_doc_itm_.Ary__empty;
|
||||
}
|
||||
public static final Fbrow_file_itm[] Ary_empty = new Fbrow_file_itm[0];
|
||||
public static Fbrow_file_itm New(IoItmDir owner_dir) {
|
||||
List_adp sub_list = List_adp_.new_();
|
||||
New_subs(owner_dir.Url(), sub_list, owner_dir.SubDirs());
|
||||
New_subs(owner_dir.Url(), sub_list, owner_dir.SubFils());
|
||||
Fbrow_file_itm[] subs = (Fbrow_file_itm[])sub_list.To_ary_and_clear(Fbrow_file_itm.class);
|
||||
return new Fbrow_file_itm(Bool_.Y, Bool_.N, 0, owner_dir.Url().OwnerDir().RawBry(), owner_dir.Url().RawBry(), Bry_.new_u8(owner_dir.Name()), Bry_.Empty, Bry_.Empty, subs);
|
||||
}
|
||||
private static void New_subs(Io_url owner_dir, List_adp list, IoItmList subs) {
|
||||
subs.Sort();
|
||||
int len = subs.Len();
|
||||
int list_total = list.Len();
|
||||
byte[] owner_dir_bry = owner_dir.RawBry();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
IoItm_base src = (IoItm_base)subs.Get_at(i);
|
||||
Fbrow_file_itm trg = null;
|
||||
if (src.Type_dir()) {
|
||||
byte[] trg_url = src.Url().RawBry();
|
||||
trg = new Fbrow_file_itm(Bool_.Y, Bool_.N, list_total + i, owner_dir_bry, trg_url, Bry_.new_u8(src.Url().NameAndExt_noDirSpr()), Bry_.Empty, Bry_.Empty, Ary_empty);
|
||||
}
|
||||
else {
|
||||
IoItmFil src_as_fil = (IoItmFil)src;
|
||||
String size_str = Io_size_.To_str(src_as_fil.Size(), "#,###");
|
||||
boolean is_xowa_core = gplx.xowa.wikis.data.Xowd_db_mgr.Maybe_core(owner_dir.NameOnly(), src.Url().NameAndExt());
|
||||
trg = new Fbrow_file_itm(Bool_.N, is_xowa_core, list_total + i, owner_dir_bry, src.Url().RawBry(), Bry_.new_u8(src.Name()), Bry_.new_u8(src_as_fil.ModifiedTime().XtoStr_fmt("yyyy-MM-dd")), Bry_.new_u8(size_str), Ary_empty);
|
||||
}
|
||||
list.Add(trg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +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.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.xowa.specials.*; import gplx.core.net.*; import gplx.xowa.wikis.pages.*;
|
||||
import gplx.core.ios.*;
|
||||
public class Fbrow_special_page implements Xows_page {
|
||||
public void Special__gen(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Xopage_html_data html_data = Write_html(wiki.App(), url.Qargs_ary());
|
||||
html_data.Apply(page);
|
||||
}
|
||||
private static Xopage_html_data Write_html(Xoa_app app, Gfo_qarg_itm[] args_ary) {
|
||||
// scan owner_dir
|
||||
Xoa_url_arg_mgr arg_mgr = new Xoa_url_arg_mgr(null).Init(args_ary);
|
||||
String owner_str = arg_mgr.Read_str_or_null("path"); if (owner_str == null) return Xopage_html_data.err_("url has unknown path");
|
||||
IoItmDir owner_dir = Io_mgr.Instance.QueryDir_args(Io_url_.new_any_(owner_str)).DirInclude_(true).ExecAsDir();
|
||||
Fbrow_file_itm owner_itm = Fbrow_file_itm.New(owner_dir);
|
||||
|
||||
// write body
|
||||
Io_url addon_dir = app.Fsys_mgr().Bin_addon_dir().GenSubDir_nest("import", "file_browser");
|
||||
byte[] template_src = Io_mgr.Instance.LoadFilBry(addon_dir.GenSubFil_nest("bin", "file_browser.mustache.html"));
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
byte[] body = gplx.langs.mustaches.Mustache_wtr_.Write_to_bry(tmp_bfr, template_src, owner_itm);
|
||||
|
||||
// write head
|
||||
Xopage_html_data rv = new Xopage_html_data(Display_ttl, body);
|
||||
rv.Head_tags().Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "file_browser.css")));
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static final String SPECIAL_KEY = "XowaFileBrowser";
|
||||
public static final byte[] Display_ttl = Bry_.new_a7("Import XOWA Wikis");
|
||||
public Xows_special_meta Special__meta() {return new Xows_special_meta(Xows_special_meta_.Src__xowa, SPECIAL_KEY);}
|
||||
public static final Xows_page Prototype = new Fbrow_special_page();
|
||||
public Xows_page Special__clone() {return this;}
|
||||
}
|
||||
@@ -1,46 +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.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.core.ios.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
class Wikis_list_mgr implements Mustache_doc_itm {
|
||||
private final byte[] import_root;
|
||||
private final Wikis_list_itm[] subs;
|
||||
public Wikis_list_mgr(byte[] import_root, Wikis_list_itm[] subs) {this.import_root = import_root; this.subs = subs;}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "import_root")) bfr.Add_bry(import_root);
|
||||
return false;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
if (String_.Eq(key, "subs")) return subs;
|
||||
return Mustache_doc_itm_.Ary__empty;
|
||||
}
|
||||
}
|
||||
class Wikis_list_itm implements Mustache_doc_itm {
|
||||
private final byte[] domain, date;
|
||||
public Wikis_list_itm(byte[] domain, byte[] date) {
|
||||
this.domain = domain; this.date = date;
|
||||
}
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "domain")) bfr.Add_bry(domain);
|
||||
else if (String_.Eq(key, "date")) bfr.Add_bry(date);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
|
||||
}
|
||||
@@ -1,49 +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.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.xowa.specials.*; import gplx.core.net.*; import gplx.xowa.wikis.pages.*;
|
||||
public class Wikis_list_page implements Xows_page {
|
||||
public void Special__gen(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
Xoa_url_arg_mgr arg_mgr = new Xoa_url_arg_mgr(null).Init(url.Qargs_ary());
|
||||
Wikis_list_wtr wtr = new Wikis_list_wtr();
|
||||
byte[] cmd = arg_mgr.Read_bry_or_null("cmd");
|
||||
if (cmd == null) {
|
||||
Xopage_html_data html_data = wtr.Write(wiki.App(), url.Qargs_ary(), GfoInvkAble_.Null);
|
||||
html_data.Apply(page);
|
||||
}
|
||||
else {
|
||||
if (Bry_.Eq(cmd, Bry_.new_a7("add"))) {
|
||||
byte[] file = arg_mgr.Read_bry_or_null("file");
|
||||
if (file != null) {
|
||||
if (wiki.App().Tid_is_edit()) {
|
||||
wiki.App().User().User_db_mgr().Init_site_mgr();
|
||||
}
|
||||
wiki.App().Wiki_mgri().Import_by_url(Io_url_.new_fil_(String_.new_u8(file)));
|
||||
Xopage_html_data html_data = wtr.Write(wiki.App(), url.Qargs_ary(), GfoInvkAble_.Null);
|
||||
html_data.Apply(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final String SPECIAL_KEY = "XowaWikis";
|
||||
public static final byte[] Display_ttl = Bry_.new_a7("XOWA Wikis");
|
||||
public Xows_special_meta Special__meta() {return new Xows_special_meta(Xows_special_meta_.Src__xowa, SPECIAL_KEY);}
|
||||
public static final Xows_page Prototype = new Wikis_list_page();
|
||||
public Xows_page Special__clone() {return this;}
|
||||
}
|
||||
@@ -1,57 +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.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.core.net.*;
|
||||
import gplx.xowa.wikis.xwikis.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
import gplx.xowa.users.data.*; import gplx.xowa.wikis.pages.*;
|
||||
class Wikis_list_wtr {
|
||||
public Xopage_html_data Write(Xoa_app app, Gfo_qarg_itm[] args, GfoInvkAble select_invkable) {
|
||||
// scan wikis
|
||||
List_adp list = List_adp_.new_();
|
||||
app.User().User_db_mgr().Init_site_mgr();
|
||||
Xoud_site_row[] site_ary = app.User().User_db_mgr().Site_mgr().Get_all();
|
||||
int len = site_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoud_site_row site_itm = site_ary[i];
|
||||
if (String_.Eq(site_itm.Domain(), gplx.xowa.wikis.domains.Xow_domain_itm_.Str__home)) continue;
|
||||
list.Add(new Wikis_list_itm(Bry_.new_u8(site_itm.Domain()), Bry_.new_a7("2016-03-05")));
|
||||
}
|
||||
Wikis_list_mgr mgr = new Wikis_list_mgr(Get_root_url(), (Wikis_list_itm[])list.To_ary_and_clear(Wikis_list_itm.class));
|
||||
|
||||
// write body
|
||||
Io_url addon_dir = app.Fsys_mgr().Bin_addon_dir().GenSubDir_nest("app", "wiki_list");
|
||||
byte[] template_src = Io_mgr.Instance.LoadFilBry(addon_dir.GenSubFil_nest("bin", "wiki_list.mustache.html"));
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
byte[] body = gplx.langs.mustaches.Mustache_wtr_.Write_to_bry(tmp_bfr, template_src, mgr);
|
||||
|
||||
// write to html
|
||||
Xopage_html_data rv = new Xopage_html_data(Wikis_list_page.Display_ttl, body);
|
||||
rv.Head_tags().Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "wiki_list.css")));
|
||||
return rv;
|
||||
}
|
||||
private static byte[] Get_root_url() {
|
||||
byte tid = gplx.core.envs.Op_sys.Cur().Tid();
|
||||
byte[] rv = Bry_.new_a7("/");
|
||||
switch (tid) {
|
||||
case gplx.core.envs.Op_sys.Tid_wnt : rv = Bry_.new_a7("C:\\"); break;
|
||||
}
|
||||
rv = gplx.langs.htmls.encoders.Gfo_url_encoder_.Href.Encode(rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,50 +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.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.core.primitives.*; import gplx.core.net.*;
|
||||
public class Xoa_url_arg_mgr {
|
||||
private final Hash_adp_bry hash = Hash_adp_bry.cs();
|
||||
private final Xoa_url_enum_mgr enm_mgr;
|
||||
public Xoa_url_arg_mgr(Xoa_url_enum_mgr enm_mgr) {this.enm_mgr = enm_mgr;}
|
||||
public Xoa_url_arg_mgr Init(Gfo_qarg_itm[] args) {
|
||||
hash.Clear();
|
||||
int len = args.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_qarg_itm arg = args[i];
|
||||
hash.Add_bry_obj(arg.Key_bry(), arg);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public int Read_enm_or_neg1(byte[] key) {
|
||||
Xoa_url_enum_itm enm = enm_mgr.Get(key); if (enm == null) return -1;
|
||||
Gfo_qarg_itm arg = (Gfo_qarg_itm)hash.Get_by_bry(key); if (arg == null) return -1;
|
||||
return enm.Get_as_int_or(arg.Val_bry(), -1);
|
||||
}
|
||||
public byte[] Read_bry_or_empty(byte[] key) {return Read_bry_or(key, Bry_.Empty);}
|
||||
public byte[] Read_bry_or_null(String key) {return Read_bry_or_null(Bry_.new_u8(key));}
|
||||
public byte[] Read_bry_or_null(byte[] key) {return Read_bry_or(key, null);}
|
||||
public byte[] Read_bry_or(byte[] key, byte[] or) {
|
||||
Gfo_qarg_itm arg = (Gfo_qarg_itm)hash.Get_by_bry(key);
|
||||
return arg == null ? or : arg.Val_bry();
|
||||
}
|
||||
public String Read_str_or_null(String key) {return Read_str_or_null(Bry_.new_u8(key));}
|
||||
public String Read_str_or_null(byte[] key) {
|
||||
Gfo_qarg_itm arg = (Gfo_qarg_itm)hash.Get_by_bry(key);
|
||||
return arg == null ? null : String_.new_u8(arg.Val_bry());
|
||||
}
|
||||
}
|
||||
@@ -1,28 +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.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
public class Xoa_url_enum_itm {
|
||||
private final Hash_adp_bry hash = Hash_adp_bry.cs();
|
||||
public Xoa_url_enum_itm(byte[] key) {this.key = key;}
|
||||
public byte[] Key() {return key;} private final byte[] key;
|
||||
public Xoa_url_enum_itm Add(String key, int val) {
|
||||
hash.Add_bry_int(Bry_.new_u8(key), val);
|
||||
return this;
|
||||
}
|
||||
public int Get_as_int_or(byte[] val, int or) {return hash.Get_as_int_or(val, or);}
|
||||
}
|
||||
@@ -1,29 +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.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
public class Xoa_url_enum_mgr {
|
||||
private final Hash_adp_bry hash = Hash_adp_bry.cs();
|
||||
public Xoa_url_enum_mgr(Xoa_url_enum_itm... ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoa_url_enum_itm itm = ary[i];
|
||||
hash.Add_bry_obj(itm.Key(), itm);
|
||||
}
|
||||
}
|
||||
public Xoa_url_enum_itm Get(byte[] key) {return (Xoa_url_enum_itm)hash.Get_by_bry(key);}
|
||||
}
|
||||
@@ -15,16 +15,14 @@ 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.addons.apps.file_browsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.xowa.specials.*;
|
||||
public class Fbrow_addon implements Xoax_addon_itm, Xoax_addon_itm__special {
|
||||
public Xows_page[] Pages_ary() {
|
||||
return new Xows_page[]
|
||||
{ Fbrow_special_page.Prototype
|
||||
, Wikis_list_page.Prototype
|
||||
package gplx.xowa.addons.apps.helps.logs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.helps.*;
|
||||
import gplx.xowa.specials.*; import gplx.xowa.htmls.bridges.*;
|
||||
public class Xolog_addon implements Xoax_addon_itm, Xoax_addon_itm__special {
|
||||
public Xow_special_page[] Special_pages() {
|
||||
return new Xow_special_page[]
|
||||
{ Xolog_special.Prototype
|
||||
};
|
||||
}
|
||||
|
||||
public static final byte[] ADDON_KEY = Bry_.new_a7("xowa.apps.file_browsers");
|
||||
public byte[] Addon__key() {return ADDON_KEY;}
|
||||
public String Addon__key() {return "xowa.apps.helps.logs";}
|
||||
}
|
||||
87
400_xowa/src/gplx/xowa/addons/apps/helps/logs/Xolog_doc.java
Normal file
87
400_xowa/src/gplx/xowa/addons/apps/helps/logs/Xolog_doc.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
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.addons.apps.helps.logs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.helps.*;
|
||||
import gplx.langs.mustaches.*;
|
||||
class Xolog_doc implements Mustache_doc_itm {
|
||||
public Xolog_doc(String log_file, String log_name, byte[] log_data, Xolog_doc_file[] log_files) {
|
||||
this.log_file = log_file; this.log_name = log_name;
|
||||
this.log_data = log_data; this.log_files = log_files;
|
||||
}
|
||||
public String Log_file() {return log_file;} private final String log_file; // EX: 20160613_165025
|
||||
public String Log_name() {return log_name;} private final String log_name; // EX: 2016-06-13 16:50:25
|
||||
public byte[] Log_data() {return log_data;} private final byte[] log_data;
|
||||
public Xolog_doc_file[] Log_files() {return log_files;} private final Xolog_doc_file[] log_files;
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "log_name")) bfr.Add_str_u8(log_name);
|
||||
else if (String_.Eq(key, "log_file")) bfr.Add_str_u8(log_file);
|
||||
else if (String_.Eq(key, "log_data")) bfr.Add_bry(log_data);
|
||||
return false;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {
|
||||
if (String_.Eq(key, "log_files")) return log_files;
|
||||
return Mustache_doc_itm_.Ary__empty;
|
||||
}
|
||||
}
|
||||
class Xolog_doc_ {
|
||||
public static Xolog_doc New(Io_url log_dir, String log_file) {
|
||||
// read fsys
|
||||
Io_url[] fils = Io_mgr.Instance.QueryDir_fils(log_dir);
|
||||
int len = fils.length;
|
||||
|
||||
// get log_files
|
||||
Ordered_hash hash = Ordered_hash_.New();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Io_url fil = fils[i];
|
||||
String file = fil.NameOnly();
|
||||
String name = Xolog_file_utl.To_name(file);
|
||||
hash.Add(file, new Xolog_doc_file(file, name));
|
||||
}
|
||||
|
||||
// determine cur_file
|
||||
String cur_file = log_file;
|
||||
if ( cur_file == null // cur_file is null; happens for plain "Special:XowaLog"
|
||||
|| !hash.Has(cur_file) // cur_file deleted (accessed from history)
|
||||
) {
|
||||
cur_file = hash.Len() == 0
|
||||
? null
|
||||
: ((Xolog_doc_file)hash.Get_at(len - 1)).File();
|
||||
}
|
||||
if (cur_file != null)
|
||||
hash.Del(cur_file); // don't bother showing current item in list
|
||||
Xolog_doc_file[] log_files = (Xolog_doc_file[])hash.To_ary_and_clear(Xolog_doc_file.class);
|
||||
|
||||
// get body
|
||||
byte[] cur_body = Io_mgr.Instance.LoadFilBry(Xolog_file_utl.To_url_by_file(log_dir, cur_file));
|
||||
String cur_name = cur_file == null ? null : Xolog_file_utl.To_name(cur_file);
|
||||
return new Xolog_doc(cur_file, cur_name, cur_body, log_files);
|
||||
}
|
||||
}
|
||||
class Xolog_doc_file implements Mustache_doc_itm {
|
||||
public Xolog_doc_file(String file, String name) {
|
||||
this.file = file; this.name = name;
|
||||
}
|
||||
public String File() {return file;} private final String file;
|
||||
public String Name() {return name;} private final String name;
|
||||
public boolean Mustache__write(String key, Mustache_bfr bfr) {
|
||||
if (String_.Eq(key, "file")) bfr.Add_str_u8(file);
|
||||
else if (String_.Eq(key, "name")) bfr.Add_str_u8(name);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
public Mustache_doc_itm[] Mustache__subs(String key) {return Mustache_doc_itm_.Ary__empty;}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
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.addons.apps.helps.logs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.helps.*;
|
||||
import gplx.xowa.specials.*; import gplx.langs.mustaches.*; import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.tags.*;
|
||||
class Xolog_html extends Xow_special_wtr__base {
|
||||
private final Xolog_doc log_doc;
|
||||
public Xolog_html(Xolog_doc log_doc) {
|
||||
this.log_doc = log_doc;
|
||||
}
|
||||
@Override protected Io_url Get_addon_dir(Xoa_app app) {return app.Fsys_mgr().Http_root().GenSubDir_nest("bin", "any", "xowa", "addon", "app", "help", "log");}
|
||||
@Override protected Io_url Get_mustache_fil(Io_url addon_dir) {return addon_dir.GenSubFil_nest("bin", "xolog.mustache.html");}
|
||||
@Override protected Mustache_doc_itm Bld_mustache_root(Xoa_app app) {
|
||||
return log_doc;
|
||||
}
|
||||
@Override protected void Bld_tags(Xoa_app app, Io_url addon_dir, Xopage_html_data page_data) {
|
||||
Xopg_tag_mgr head_tags = page_data.Head_tags();
|
||||
Xopg_tag_wtr_.Add__xocss (head_tags, app.Fsys_mgr().Http_root());
|
||||
Xopg_tag_wtr_.Add__xohelp (head_tags, app.Fsys_mgr().Http_root());
|
||||
Xopg_alertify_.Add_tags (head_tags, app.Fsys_mgr().Http_root());
|
||||
page_data.Head_tags().Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "xolog.css")));
|
||||
page_data.Head_tags().Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("bin", "xolog.js")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
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.addons.apps.helps.logs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.helps.*;
|
||||
import gplx.xowa.specials.*; import gplx.core.net.*; import gplx.core.net.qargs.*; import gplx.xowa.wikis.pages.*;
|
||||
import gplx.core.net.emails.*;
|
||||
public class Xolog_special implements Xow_special_page {
|
||||
public void Special__gen(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
// init
|
||||
Gfo_qarg_mgr url_args = new Gfo_qarg_mgr().Init(url.Qargs_ary());
|
||||
Xoa_app app = wiki.App();
|
||||
Gfo_log_.Instance.Flush(); // flush log to write all memory itms to disk
|
||||
|
||||
// get file
|
||||
String file = url_args.Read_str_or_null("file");
|
||||
Io_url log_dir = app.Fsys_mgr().Root_dir().GenSubDir_nest("user", "anonymous", "app", "tmp", "xolog");
|
||||
Xolog_doc log_doc = Xolog_doc_.New(log_dir, file);
|
||||
if (log_doc.Log_file() == null) return; // occurs when all logs are deleted
|
||||
|
||||
// get cmd
|
||||
int cmd_tid = url_args.Read_enm_as_int_or(Enm_cmd.Itm, Enm_cmd.Tid__view);
|
||||
boolean redirect = true, redirect_to_same_file = false;;
|
||||
switch (cmd_tid) {
|
||||
case Enm_cmd.Tid__view: redirect = false; break;
|
||||
case Enm_cmd.Tid__email: redirect_to_same_file = true; Gfo_email_mgr_.Instance.Send("gnosygnu+xowa_xologs@gmail.com", "XOWA Log", String_.new_u8(log_doc.Log_data())); break;
|
||||
case Enm_cmd.Tid__delete_one: Io_mgr.Instance.DeleteFil(Xolog_file_utl.To_url_by_file(log_dir, log_doc.Log_file())); break;
|
||||
case Enm_cmd.Tid__delete_all: Io_mgr.Instance.DeleteDirDeep(log_dir); break;
|
||||
}
|
||||
|
||||
if (redirect) {
|
||||
String redirect_ttl = special__meta.Ttl_str() + "?cmd=view";
|
||||
if (redirect_to_same_file && file != null)
|
||||
redirect_ttl += "&file=" + file;
|
||||
page.Redirect_to_ttl_(Bry_.new_u8(redirect_ttl));
|
||||
return;
|
||||
}
|
||||
else
|
||||
new Xolog_html(log_doc).Bld_page_by_mustache(app, page, this);
|
||||
}
|
||||
static class Enm_cmd {//#*nested
|
||||
public static final int Tid__view = 0, Tid__email = 1, Tid__delete_one = 2, Tid__delete_all = 3;
|
||||
public static final Gfo_qarg_enum_itm Itm = new Gfo_qarg_enum_itm("cmd")
|
||||
.Add("view" , Tid__view)
|
||||
.Add("email" , Tid__email)
|
||||
.Add("delete_one" , Tid__delete_one)
|
||||
.Add("delete_all" , Tid__delete_all)
|
||||
;
|
||||
}
|
||||
Xolog_special(Xow_special_meta special__meta) {this.special__meta = special__meta;}
|
||||
public Xow_special_meta Special__meta() {return special__meta;} private final Xow_special_meta special__meta;
|
||||
public Xow_special_page Special__clone() {return this;}
|
||||
public static final Xow_special_page Prototype = new Xolog_special(Xow_special_meta.New_xo("XowaLog", "Logs"));
|
||||
}
|
||||
class Xolog_file_utl {// yyyyMMdd_HHmmss.log
|
||||
private static final String Gui__date_fmt = "yyyy-MM-dd HH:mm:ss";
|
||||
public static String To_name(Io_url url) {return To_name(url.NameOnly());}
|
||||
public static String To_name(String file) {
|
||||
DateAdp date = DateAdp_.parse_fmt(file, Gfo_log_.File__fmt);
|
||||
return date.XtoStr_fmt(Gui__date_fmt);
|
||||
}
|
||||
public static Io_url To_url_by_file(Io_url dir, String file) {
|
||||
return dir.GenSubFil(file + Gfo_log_.File__ext);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +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.addons.apps.searchs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.xowa.addons.apps.searchs.dbs.*; import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.parsers.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*; import gplx.xowa.addons.apps.searchs.searchers.cbks.*;
|
||||
import gplx.xowa.langs.cases.*;
|
||||
public class Srch_search_addon implements Xoax_addon_itm, Srch_search_addon_api {
|
||||
private final Srch_search_mgr search_mgr;
|
||||
public Srch_search_addon(Xow_wiki wiki) {
|
||||
this.wiki_domain = wiki.Domain_bry();
|
||||
this.db_mgr = new Srch_db_mgr(wiki).Init();
|
||||
this.ttl_parser = new Srch_text_parser().Init_for_ttl(wiki.Case_mgr());
|
||||
this.search_mgr = new Srch_search_mgr(this, wiki, ttl_parser);
|
||||
}
|
||||
public byte[] Wiki_domain() {return wiki_domain;} private final byte[] wiki_domain;
|
||||
public Srch_db_mgr Db_mgr() {return db_mgr;} private final Srch_db_mgr db_mgr;
|
||||
public Srch_text_parser Ttl_parser() {return ttl_parser;} private final Srch_text_parser ttl_parser;
|
||||
|
||||
public void Search(Srch_search_qry qry, Srch_rslt_cbk cbk) {search_mgr.Search(qry, cbk);}
|
||||
public void Clear_rslts_cache() {search_mgr.Clear_rslts_cache();}
|
||||
|
||||
public static final int Score_max = 1000000;
|
||||
public static final byte Wildcard__star = Byte_ascii.Star;
|
||||
public static Srch_search_addon Get(Xow_wiki wiki) {
|
||||
Srch_search_addon rv = (Srch_search_addon)wiki.Addon_mgr().Itms__get_or_null(ADDON_KEY);
|
||||
if (rv == null) {
|
||||
rv = new Srch_search_addon(wiki);
|
||||
wiki.Addon_mgr().Itms__add(rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static final byte[] ADDON_KEY = Bry_.new_a7("xowa.apps.search");
|
||||
public byte[] Addon__key() {return ADDON_KEY;}
|
||||
}
|
||||
@@ -1,23 +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.addons.apps.searchs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public interface Srch_search_addon_api {
|
||||
void Search(Srch_search_qry qry, Srch_rslt_cbk cbk);
|
||||
}
|
||||
@@ -1,109 +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.addons.apps.searchs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.core.net.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.cbks.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public class Srch_search_cfg implements GfoInvkAble {
|
||||
private final Xoae_app app;
|
||||
private String args_default_str = "";// default args for search
|
||||
private byte search_mode = Tid_search_mode_all_pages_v2;
|
||||
private int all_pages_extend = 1000; // look ahead by 1000
|
||||
private int all_pages_min = 10000; // only look at pages > 10 kb
|
||||
private boolean log_enabled = false;
|
||||
public Srch_search_cfg(Xoae_app app) {
|
||||
this.app = app;
|
||||
ns_mgr.Add_main_if_empty();
|
||||
}
|
||||
public boolean Enabled() {return enabled;} private boolean enabled = true;
|
||||
public int Rslts_max() {return results_max;} private int results_max = 25;
|
||||
public boolean Auto_wildcard() {return auto_wildcard;} private boolean auto_wildcard = false; // automatically add wild-card; EX: Earth -> *Earth*
|
||||
public Srch_ns_mgr Ns_mgr() {return ns_mgr;} private final Srch_ns_mgr ns_mgr = new Srch_ns_mgr();
|
||||
public Gfo_qarg_itm[] Args_default() {return args_default;} private Gfo_qarg_itm[] args_default = Gfo_qarg_itm.Ary_empty;
|
||||
public void Args_default_str_(String v) {
|
||||
this.args_default_str = v;
|
||||
byte[] bry = Bry_.new_a7("http://x.org/a?" + v);
|
||||
Gfo_url tmp_url = new Gfo_url();
|
||||
app.User().Wikii().Utl__url_parser().Url_parser().Parse(tmp_url, bry, 0, bry.length);
|
||||
args_default = tmp_url.Qargs();
|
||||
}
|
||||
private Srch_search_addon addon;
|
||||
public void Search(Xowe_wiki wiki, byte[] search_bry, byte[] cbk_func) {
|
||||
if ( !enabled
|
||||
|| search_bry.length == 0
|
||||
) return;
|
||||
if (addon == null)
|
||||
addon = Srch_search_addon.Get(wiki);
|
||||
else {
|
||||
if (!Bry_.Eq(wiki.Domain_bry(), addon.Wiki_domain())) // NOTE: suggest-box caches addon at wiki level; need to check if wiki has changed
|
||||
addon = Srch_search_addon.Get(wiki);
|
||||
}
|
||||
// tab_close_mgr.Add(this);
|
||||
Srch_search_qry qry = Srch_search_qry.New__suggest_box(wiki, this, search_bry);
|
||||
Srch_rslt_cbk__suggest_box cbk = new Srch_rslt_cbk__suggest_box(wiki.Appe(), cbk_func, search_bry);
|
||||
addon.Search(qry, cbk);
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_enabled)) return Yn.To_str(enabled);
|
||||
else if (ctx.Match(k, Invk_enabled_)) enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_results_max)) return results_max;
|
||||
else if (ctx.Match(k, Invk_results_max_)) results_max = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_search_mode)) return Search_mode_str(search_mode);
|
||||
else if (ctx.Match(k, Invk_search_mode_)) search_mode = Search_mode_parse(m.ReadStr("v"));
|
||||
else if (ctx.Match(k, Invk_search_mode_list)) return Options_search_mode_list;
|
||||
else if (ctx.Match(k, Invk_all_pages_extend)) return all_pages_extend;
|
||||
else if (ctx.Match(k, Invk_all_pages_extend_)) all_pages_extend = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_all_pages_min)) return all_pages_min;
|
||||
else if (ctx.Match(k, Invk_all_pages_min_)) all_pages_min = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_auto_wildcard)) return Yn.To_str(auto_wildcard);
|
||||
else if (ctx.Match(k, Invk_auto_wildcard_)) auto_wildcard = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_log_enabled)) return Yn.To_str(log_enabled);
|
||||
else if (ctx.Match(k, Invk_log_enabled_)) log_enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk_args_default)) return args_default_str;
|
||||
else if (ctx.Match(k, Invk_args_default_)) Args_default_str_(m.ReadStr("v"));
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final String
|
||||
Invk_enabled = "enabled", Invk_enabled_ = "enabled_", Invk_results_max = "results_max", Invk_results_max_ = "results_max_"
|
||||
, Invk_search_mode = "search_mode", Invk_search_mode_ = "search_mode_", Invk_search_mode_list = "search_mode_list"
|
||||
, Invk_all_pages_extend = "all_pages_extend", Invk_all_pages_extend_ = "all_pages_extend_"
|
||||
, Invk_all_pages_min = "all_pages_min", Invk_all_pages_min_ = "all_pages_min_"
|
||||
, Invk_auto_wildcard = "auto_wildcard", Invk_auto_wildcard_ = "auto_wildcard_"
|
||||
, Invk_log_enabled = "log_enabled", Invk_log_enabled_ = "log_enabled_"
|
||||
, Invk_args_default = "args_default", Invk_args_default_ = "args_default_"
|
||||
;
|
||||
private static final String Str_search_mode_search = "Search", Str_search_mode_all_pages_v1 = "AllPages", Str_search_mode_all_pages_v2 = "AllPages_(v2)";
|
||||
public static final int[] Ns_default_main = new int[] {Xow_ns_.Tid__main};
|
||||
public static final byte Tid_search_mode_all_pages_v1 = 0, Tid_search_mode_search = 1, Tid_search_mode_all_pages_v2 = 2;
|
||||
private static Keyval[] Options_search_mode_list = Keyval_.Ary(Keyval_.new_(Str_search_mode_search), Keyval_.new_(Str_search_mode_all_pages_v1), Keyval_.new_(Str_search_mode_all_pages_v2));
|
||||
private static byte Search_mode_parse(String v) {
|
||||
if (String_.Eq(v, Str_search_mode_search)) return Tid_search_mode_search;
|
||||
else if (String_.Eq(v, Str_search_mode_all_pages_v1)) return Tid_search_mode_all_pages_v1;
|
||||
else if (String_.Eq(v, Str_search_mode_all_pages_v2)) return Tid_search_mode_all_pages_v2;
|
||||
else throw Err_.new_unhandled(v);
|
||||
}
|
||||
private static String Search_mode_str(byte v) {
|
||||
switch (v) {
|
||||
case Tid_search_mode_search: return Str_search_mode_search;
|
||||
case Tid_search_mode_all_pages_v1: return Str_search_mode_all_pages_v1;
|
||||
case Tid_search_mode_all_pages_v2: return Str_search_mode_all_pages_v2;
|
||||
default: throw Err_.new_unhandled(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +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.addons.apps.searchs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.addons.apps.searchs.bldrs.cmds.*;
|
||||
public class Xoax_builds_search_addon implements Xoax_addon_itm, Xoax_addon_itm__bldr {
|
||||
public Xob_cmd[] Cmds_ary() {
|
||||
return new Xob_cmd[]
|
||||
{ Xobldr__link__link_score.Prototype
|
||||
, Xobldr__page__page_score.Prototype
|
||||
, Xobldr__word__link_count.Prototype
|
||||
};
|
||||
}
|
||||
|
||||
public static final byte[] ADDON_KEY = Bry_.new_a7("xowa.builds.search");
|
||||
public byte[] Addon__key() {return ADDON_KEY;}
|
||||
}
|
||||
@@ -1,34 +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.addons.apps.searchs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*;
|
||||
public class Srch_bldr_cmd extends Xob_cmd__base implements Xob_cmd {
|
||||
private int commit_interval = 100000, progress_interval = 10000;
|
||||
public Srch_bldr_cmd(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);}
|
||||
@Override public String Cmd_key() {return Xob_cmd_keys.Key_text_search_cmd;}
|
||||
@Override public void Cmd_run() {
|
||||
if (!gplx.core.envs.Env_.Mode_testing()) wiki.Init_assert();
|
||||
new Srch_temp_tbl_wkr().Exec_by_cmd(wiki, commit_interval, progress_interval);
|
||||
}
|
||||
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_commit_interval_)) commit_interval = m.ReadInt("v");
|
||||
else if (ctx.Match(k, Invk_progress_interval_)) progress_interval = m.ReadInt("v");
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk_progress_interval_ = "progress_interval_", Invk_commit_interval_ = "commit_interval_";
|
||||
}
|
||||
@@ -1,38 +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.addons.apps.searchs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.bldrs.*;
|
||||
import gplx.xowa.addons.apps.searchs.bldrs.cmds.*;
|
||||
public class Srch_bldr_mgr_ {
|
||||
public static void Setup(Xowe_wiki wiki) {
|
||||
Xoae_app app = wiki.Appe();
|
||||
Xob_bldr bldr = app.Bldr();
|
||||
|
||||
bldr.Cmd_mgr().Add_many(wiki, Xob_cmd_keys.Key_text_search_cmd);
|
||||
int page_rank_iterations = app.Api_root().Bldr().Wiki().Import().Page_rank().Iteration_max();
|
||||
boolean page_rank_enabled = page_rank_iterations > 0;
|
||||
if (page_rank_enabled) {
|
||||
bldr.Cmd_mgr().Add(new gplx.xowa.bldrs.cmds.utils.Xob_download_cmd(bldr, wiki).Dump_type_(gplx.xowa.addons.builds.pagelinks.bldrs.Pglnk_bldr_cmd.Dump_type_key));
|
||||
bldr.Cmd_mgr().Add_many(wiki, gplx.xowa.addons.builds.pagelinks.bldrs.Pglnk_bldr_cmd.BLDR_CMD_KEY);
|
||||
}
|
||||
bldr.Cmd_mgr().Add(new Xobldr__page__page_score(bldr, wiki).Iteration_max_(page_rank_iterations));
|
||||
bldr.Cmd_mgr().Add(new Xobldr__link__link_score(bldr, wiki).Page_rank_enabled_(page_rank_enabled).Delete_plink_db_(Bool_.Y));
|
||||
bldr.Cmd_mgr().Add(new Xobldr__word__link_count(bldr, wiki));
|
||||
bldr.Cmd_mgr().Add(new gplx.xowa.bldrs.cmds.utils.Xob_delete_cmd(bldr, wiki).Patterns_ary_("*pagelinks.sql", "*pagelinks.sql.gz", "*pagelinks.sqlite3"));
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*;
|
||||
public class Srch_bldr_wkr implements Xob_page_wkr {
|
||||
private final Xowe_wiki wiki;
|
||||
private final Srch_temp_tbl_wkr temp_tbl_wkr = new Srch_temp_tbl_wkr();
|
||||
public Srch_bldr_wkr(Xob_bldr bldr, Xowe_wiki wiki) {this.wiki = wiki;}
|
||||
public String Page_wkr__key() {return Xob_cmd_keys.Key_text_search_wkr;}
|
||||
public void Page_wkr__bgn() {
|
||||
temp_tbl_wkr.Init(Bool_.N, wiki);
|
||||
}
|
||||
public void Page_wkr__run(gplx.xowa.wikis.data.tbls.Xowd_page_itm page) {
|
||||
try {temp_tbl_wkr.Exec_by_wkr(page.Id(), page.Ttl_page_db());}
|
||||
catch (Exception e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "search:error: page=~{0} err=~{1}", page.Ttl_page_db(), Err_.Message_gplx_full(e));}
|
||||
}
|
||||
public void Page_wkr__run_cleanup() {}
|
||||
public void Page_wkr__end() {
|
||||
temp_tbl_wkr.Term();
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return this;}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.bldrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.apps.searchs.dbs.*; import gplx.xowa.addons.apps.searchs.parsers.*;
|
||||
class Srch_temp_tbl_wkr implements Srch_text_parser_wkr {
|
||||
private Xowe_wiki wiki; private Xowd_db_mgr core_data_mgr; private Srch_search_addon search_addon;
|
||||
private Srch_text_parser title_parser;
|
||||
private Srch_temp_tbl search_temp_tbl; private int word_id, page_id; // needed for Parse_done
|
||||
public Srch_temp_tbl_wkr Init(boolean cmd, Xowe_wiki wiki) {
|
||||
// init
|
||||
this.wiki = wiki;
|
||||
this.core_data_mgr = wiki.Db_mgr_as_sql().Core_data_mgr();
|
||||
this.search_addon = Srch_search_addon.Get(wiki);
|
||||
this.title_parser = search_addon.Ttl_parser();
|
||||
this.word_id = 0;
|
||||
// assert search_word / search_link tables
|
||||
Srch_db_mgr search_db_mgr = search_addon.Db_mgr();
|
||||
if (cmd) { // run from maint or from import.offline
|
||||
if (search_db_mgr.Tbl__word() != null) // called from maint; note that import.offline will always be null (since tables don't exist); DATE:2016-04-04
|
||||
search_db_mgr.Delete_all(core_data_mgr); // always delete if launched by cmd
|
||||
}
|
||||
search_db_mgr.Create_all();
|
||||
// start processing search_temp
|
||||
this.search_temp_tbl = new Srch_temp_tbl(search_db_mgr.Tbl__word().conn);
|
||||
search_temp_tbl.Insert_bgn();
|
||||
return this;
|
||||
}
|
||||
public void Term() {
|
||||
// end inserts
|
||||
search_temp_tbl.Insert_end();
|
||||
|
||||
// init
|
||||
Srch_db_mgr search_db_mgr = search_addon.Db_mgr().Init(); // NOTE: must call .Init for import-offline else Cfg_tbl will be null; note that .Init will bind to newly created search_word / search_link tbl; DATE:2016-04-04
|
||||
Db_conn word_conn = search_temp_tbl.conn;
|
||||
|
||||
// update search_word ids if they exist
|
||||
// Srch_db_mgr.Optimize_unsafe_(word_conn, Bool_.Y); // NOTE: fails in multi-db due to transaction
|
||||
Update_word_id(word_conn, wiki);
|
||||
Search_word__insert(word_conn);
|
||||
// Srch_db_mgr.Optimize_unsafe_(word_conn, Bool_.N);
|
||||
|
||||
// create search_link
|
||||
Db_conn page_conn = wiki.Data__core_mgr().Tbl__page().conn;
|
||||
if (search_db_mgr.Tbl__link__len() == 1) {
|
||||
// single_db; just run sql;
|
||||
Xoa_app_.Usr_dlg().Plog_many("", "", "creating search_link");
|
||||
Srch_link_tbl link_tbl = search_db_mgr.Tbl__link__ary()[0];
|
||||
new Db_attach_mgr(word_conn, new Db_attach_itm("link_db", link_tbl.conn))
|
||||
.Exec_sql(String_.Concat_lines_nl_skip_last
|
||||
( "INSERT INTO <link_db>search_link (word_id, page_id)"
|
||||
, "SELECT w.word_id"
|
||||
, ", t.page_id"
|
||||
, "FROM search_temp t"
|
||||
, " JOIN search_word w ON t.word_text = w.word_text"
|
||||
));
|
||||
link_tbl.Create_idx__page_id();
|
||||
} else {
|
||||
Search_link__insert(search_db_mgr, word_conn, page_conn);
|
||||
}
|
||||
|
||||
// remove search_temp
|
||||
word_conn.Meta_tbl_delete(search_temp_tbl.tbl_name);
|
||||
}
|
||||
private static void Search_link__insert(Srch_db_mgr search_db_mgr, Db_conn word_conn, Db_conn page_conn) {
|
||||
// many_db; split into main links and non-main; ASSUME:link_dbs_is_2
|
||||
Db_attach_mgr attach_mgr = new Db_attach_mgr();
|
||||
|
||||
// dump everything into a temp table in order to index it
|
||||
page_conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_name("page", "page_ns__page_id", "page_namespace", "page_id"));
|
||||
Srch_db_mgr.Optimize_unsafe_(word_conn, Bool_.Y);
|
||||
word_conn.Meta_tbl_remake(Dbmeta_tbl_itm.New("search_link_temp", Dbmeta_fld_itm.new_int("word_id"), Dbmeta_fld_itm.new_int("page_id"), Dbmeta_fld_itm.new_int("page_namespace")));
|
||||
attach_mgr.Main_conn_(word_conn).Init(new Db_attach_itm("page_db", page_conn));
|
||||
attach_mgr.Exec_sql_w_msg
|
||||
( "filling search_link_temp (please wait)", String_.Concat_lines_nl_skip_last
|
||||
( "INSERT INTO search_link_temp (word_id, page_id, page_namespace)"
|
||||
, "SELECT w.word_id"
|
||||
, ", t.page_id"
|
||||
, ", p.page_namespace"
|
||||
, "FROM search_temp t"
|
||||
, " JOIN search_word w ON t.word_text = w.word_text"
|
||||
, " JOIN <page_db>page p ON t.page_id = p.page_id"
|
||||
));
|
||||
word_conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_name("search_link_temp", "main", "page_namespace", "word_id", "page_id"));
|
||||
Srch_db_mgr.Optimize_unsafe_(word_conn, Bool_.N);
|
||||
page_conn.Meta_idx_delete("page__page_ns__page_id");
|
||||
|
||||
int len = search_db_mgr.Tbl__link__len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Xoa_app_.Usr_dlg().Plog_many("", "", "creating search_link_temp: ~{0}", i);
|
||||
Srch_link_tbl link_tbl = search_db_mgr.Tbl__link__ary()[i];
|
||||
Srch_db_mgr.Optimize_unsafe_(link_tbl.conn, Bool_.Y);
|
||||
attach_mgr.Main_conn_(link_tbl.conn).Init(new Db_attach_itm("word_db", word_conn));
|
||||
attach_mgr.Exec_sql_w_msg
|
||||
( Bry_fmt.Make_str("filling search_link: ~{idx} of ~{len}", i, len), String_.Concat_lines_nl_skip_last
|
||||
( "INSERT INTO search_link (word_id, page_id)"
|
||||
, "SELECT t.word_id"
|
||||
, ", t.page_id"
|
||||
, "FROM <word_db>search_link_temp t"
|
||||
, "WHERE t.page_namespace" + (i == 0 ? " = 0" : " != 0")
|
||||
));
|
||||
link_tbl.Create_idx__page_id();
|
||||
Srch_db_mgr.Optimize_unsafe_(link_tbl.conn, Bool_.N);
|
||||
}
|
||||
word_conn.Meta_tbl_delete("search_link_temp");
|
||||
}
|
||||
public void Exec_by_wkr(int page_id, byte[] page_ttl) {
|
||||
this.page_id = page_id;
|
||||
title_parser.Parse(this, page_ttl);
|
||||
}
|
||||
public void Exec_by_cmd(Xowe_wiki wiki, int commit_interval, int progress_interval) {
|
||||
this.Init(Bool_.Y, wiki);
|
||||
Xowd_page_tbl page_tbl = core_data_mgr.Tbl__page(); String fld_page_id = page_tbl.Fld_page_id(); String fld_page_ttl = page_tbl.Fld_page_title();
|
||||
Db_rdr page_rdr = page_tbl.Select_all__id__ttl(); int page_count = 0;
|
||||
try {
|
||||
while (page_rdr.Move_next()) {
|
||||
this.page_id = page_rdr.Read_int(fld_page_id);
|
||||
byte[] page_ttl = page_rdr.Read_bry_by_str(fld_page_ttl);
|
||||
try {title_parser.Parse(this, page_ttl);}
|
||||
catch (Exception e) {Xoa_app_.Usr_dlg().Warn_many("", "", "error while parsing title; id=~{0} title=~{1} err=~{2}", page_id, page_ttl, Err_.Message_gplx_log(e));}
|
||||
++page_count;
|
||||
if ((page_count % commit_interval) == 0) search_temp_tbl.conn.Txn_sav();
|
||||
if ((page_count % progress_interval) == 0) Gfo_usr_dlg_.Instance.Prog_many("", "", "parse progress: count=~{0} last=~{1}", page_count, String_.new_u8(page_ttl));
|
||||
}
|
||||
} finally {page_rdr.Rls();}
|
||||
this.Term();
|
||||
}
|
||||
public void Parse_done(Srch_word_itm word) {
|
||||
search_temp_tbl.Insert_cmd_by_batch(++word_id, page_id, word.Word);
|
||||
}
|
||||
private void Update_word_id(Db_conn cur_conn, Xow_wiki wiki) {
|
||||
// see if prv_url exists
|
||||
Io_url cur_url = gplx.dbs.engines.sqlite.Sqlite_conn_info.To_url(cur_conn); // EX: /xowa/wiki/en.wikipedia.org/en.wikipedia.org-xtn.search.core.xowa
|
||||
Io_url prv_url = wiki.Fsys_mgr().Root_dir().GenSubFil_nest("prv", cur_url.NameAndExt()); // EX: /xowa/wiki/en.wikipedia.org/prv/en.wikipedia.org-xtn.search.core.xowa
|
||||
if (!Io_mgr.Instance.Exists(prv_url)) return;
|
||||
// update ids for old_words
|
||||
cur_conn.Exec_sql("UPDATE search_temp SET word_id = -1");
|
||||
Db_conn prv_conn = Db_conn_bldr.Instance.Get_or_noop(prv_url);
|
||||
new Db_attach_mgr(cur_conn, new Db_attach_itm("prv_db", prv_conn))
|
||||
.Exec_sql_w_msg("updating old word ids", String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE search_temp"
|
||||
, "SET word_id = Coalesce((SELECT prv.word_id FROM <prv_db>search_word prv WHERE prv.word_text = search_temp.word_text), -1)"
|
||||
));
|
||||
// assign incrementing int to new_words
|
||||
int nxt_word_id = cur_conn.Exec_select_as_int("SELECT Max(word_id) AS word_id FROM search_temp", -1); if (nxt_word_id == -1) throw Err_.new_("dbs", "max_id not found");
|
||||
int uids_max = 10000;
|
||||
int[] uids_ary = new int[uids_max]; int uid_last = -1;
|
||||
Db_stmt update_stmt = cur_conn.Stmt_update("search_temp", String_.Ary("word_uid"), "word_id");
|
||||
while (true) {
|
||||
// read 10,000 into memory
|
||||
int uids_len = 0;
|
||||
Db_rdr rdr = cur_conn.Exec_rdr("SELECT word_uid FROM search_temp WHERE word_id = -1 AND word_uid > " + Int_.To_str(uid_last));
|
||||
try {
|
||||
while (rdr.Move_next()) {
|
||||
int uid = rdr.Read_int("word_uid");
|
||||
uids_ary[uids_len++] = uid;
|
||||
if (uids_len == uids_max) {
|
||||
uid_last = uid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {rdr.Rls();}
|
||||
if (uids_len == 0) break;
|
||||
// update
|
||||
for (int i = 0; i < uids_max; ++i) {
|
||||
int uid = uids_ary[i];
|
||||
update_stmt.Clear().Val_int("word_id", ++nxt_word_id).Crt_int("word_uid", uid).Exec_update();
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void Search_word__insert(Db_conn word_conn) {
|
||||
// fill search_word; need to insert into temp first b/c PRIMARY KEY on search_word will dramatically slow down insertion
|
||||
word_conn.Meta_tbl_create(Dbmeta_tbl_itm.New("search_word_temp"
|
||||
, Dbmeta_fld_itm.new_int("word_id")
|
||||
, Dbmeta_fld_itm.new_str("word_text", 255)
|
||||
, Dbmeta_fld_itm.new_int("link_count")
|
||||
));
|
||||
word_conn.Exec_sql_concat_w_msg
|
||||
( "filling search_word_temp (please wait)"
|
||||
, "INSERT INTO search_word_temp (word_id, word_text, link_count)"
|
||||
, "SELECT Min(word_id)"
|
||||
, ", word_text"
|
||||
, ", Count(word_id)" // NOTE: no need to be Count(DISTINCT page_id); each search_temp row will only insert one word per page
|
||||
, "FROM search_temp"
|
||||
, "GROUP BY "
|
||||
, " word_text"
|
||||
, ";"
|
||||
);
|
||||
word_conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_name("search_word_temp", "main", "word_id"));
|
||||
word_conn.Exec_sql_concat_w_msg
|
||||
( "filling search_word (please wait)"
|
||||
, "INSERT INTO search_word (word_id, word_text, link_count)"
|
||||
, "SELECT word_id"
|
||||
, ", word_text"
|
||||
, ", link_count"
|
||||
, "FROM search_word_temp"
|
||||
, "ORDER BY "
|
||||
, " word_id"
|
||||
, ";"
|
||||
);
|
||||
word_conn.Meta_tbl_delete("search_word_temp");
|
||||
}
|
||||
}
|
||||
@@ -1,198 +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.addons.apps.searchs.bldrs.cmds; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.bldrs.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.addons.builds.utils_rankings.bldrs.*;
|
||||
import gplx.xowa.addons.apps.searchs.dbs.*;
|
||||
public class Xobldr__link__link_score extends Xob_cmd__base {
|
||||
private int score_multiplier = 100000000;
|
||||
private boolean page_rank_enabled = false;
|
||||
private boolean delete_plink_db = false;
|
||||
public Xobldr__link__link_score(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);}
|
||||
public Xobldr__link__link_score Page_rank_enabled_(boolean v) {this.page_rank_enabled = v; return this;}
|
||||
public Xobldr__link__link_score Delete_plink_db_(boolean v) {this.delete_plink_db = v; return this;}
|
||||
@Override public void Cmd_run() {
|
||||
wiki.Init_assert();
|
||||
Db_conn plink_conn = Db_conn_bldr.Instance.Get_or_autocreate(false, wiki.Fsys_mgr().Root_dir().GenSubFil(Xob_db_file.Name__page_link));
|
||||
String page_rank_tbl = Xobldr__page__page_score.Pagerank__tbl_name;
|
||||
String log_module = "search.page.score";
|
||||
Xoa_app_.Plog_none(log_module, "adding fields to page_rank_temp");
|
||||
plink_conn.Meta_fld_assert(page_rank_tbl, "page_len" , Dbmeta_fld_tid.Itm__int, 0);
|
||||
plink_conn.Meta_fld_assert(page_rank_tbl, "page_len_score" , Dbmeta_fld_tid.Itm__int, 0);
|
||||
plink_conn.Meta_fld_assert(page_rank_tbl, "page_rank_score" , Dbmeta_fld_tid.Itm__double, 0);
|
||||
plink_conn.Meta_fld_assert(page_rank_tbl, "page_score" , Dbmeta_fld_tid.Itm__int, 0);
|
||||
int link_score_max = Srch_search_addon.Score_max;
|
||||
|
||||
// percentize page_len_score to 0 : 100,000,000; NOTE: 100,000,000 so that no individual score should have 2+ page; i.e.: score_range > page_count
|
||||
new Db_attach_mgr(plink_conn, new Db_attach_itm("page_db", wiki.Data__core_mgr().Tbl__page().conn))
|
||||
.Exec_sql_w_msg("filling page_rank_temp.page_len", String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE page_rank_temp"
|
||||
, "SET page_len = (SELECT page_len FROM <page_db>page p WHERE p.page_id = page_rank_temp.page_id)"
|
||||
));
|
||||
new Sqlite_percentile_cmd(bldr, wiki).Init_by_rel_url(Xob_db_file.Name__page_link, "temp_page_len", link_score_max, String_.Concat_lines_nl_skip_last
|
||||
( "SELECT p.page_id, p.page_len"
|
||||
, "FROM <page_db>page p"
|
||||
, "ORDER BY p.page_len" // NOTE: ORDER BY is needed b/c INSERT into AUTO INCREMENT table
|
||||
)).Cmd_run();
|
||||
plink_conn.Exec_sql("finalizing page_rank_temp.page_len_score", String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE page_rank_temp"
|
||||
, "SET page_len_score = (SELECT tpl.row_score FROM temp_page_len tpl WHERE tpl.row_key = page_rank_temp.page_id)"
|
||||
));
|
||||
|
||||
// calc page_score
|
||||
if (page_rank_enabled) {
|
||||
// get min / max
|
||||
Xoa_app_.Plog_none(log_module, "calculating page_rank range");
|
||||
double page_rank_min = plink_conn.Exec_select_as_double("SELECT Min(page_rank) FROM " + page_rank_tbl, Double_.MinValue); if (page_rank_min == Double_.MinValue) throw Err_.new_("bldr", "failed to get min; tbl=~{0}", page_rank_tbl);
|
||||
double page_rank_max = plink_conn.Exec_select_as_double("SELECT Max(page_rank) FROM " + page_rank_tbl, Double_.MinValue); if (page_rank_max == Double_.MinValue) throw Err_.new_("bldr", "failed to get max; tbl=~{0}", page_rank_tbl);
|
||||
double page_rank_rng = page_rank_max - page_rank_min;
|
||||
if (page_rank_rng == 0) page_rank_rng = 1; // if 0, set to 1 to prevent divide by 0 below;
|
||||
String score_multiplier_as_str = Dbmeta_fld_itm.To_double_str_by_int(score_multiplier);
|
||||
|
||||
// normalize page_rank to 0 : 100,000,000
|
||||
plink_conn.Exec_sql
|
||||
( "normalizing page_rank_temp.page_rank_score"
|
||||
, Bry_fmt.Make_str
|
||||
("UPDATE ~{tbl} SET page_rank_score = ((Coalesce(page_rank, 0)) / ~{page_score_rng}) * ~{score_multiplier}"
|
||||
, page_rank_tbl, Double_.To_str(page_rank_rng), score_multiplier_as_str)
|
||||
);
|
||||
|
||||
// adjust for page_len where pages in lower 60% will get penalized; EX: page_rank = 100; page_len = 50,000,000 -> 100 * (50 M / 100 M) -> 50
|
||||
String page_len_cutoff = Dbmeta_fld_itm.To_double_str_by_int((int)(score_multiplier * .6));
|
||||
plink_conn.Exec_sql
|
||||
( "penalizing short pages"
|
||||
, Bry_fmt.Make_str(String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE page_rank_temp"
|
||||
, "SET page_rank_score = (page_rank_score * CASE WHEN page_len_score < ~{page_len_cutoff} THEN (page_len_score / ~{score_multiplier}) ELSE 1 END)"
|
||||
), page_len_cutoff, score_multiplier_as_str));
|
||||
|
||||
// percentize page_rank_score to 0 : 100,000
|
||||
new Sqlite_percentile_cmd(bldr, wiki).Init_by_rel_url(Xob_db_file.Name__page_link, "temp_page_score", link_score_max, String_.Concat_lines_nl_skip_last
|
||||
( "SELECT prt.page_id, prt.page_rank_score"
|
||||
, "FROM page_rank_temp prt"
|
||||
, "ORDER BY prt.page_rank_score" // NOTE: ORDER BY is needed b/c INSERT into AUTO INCREMENT table
|
||||
)).Cmd_run();
|
||||
plink_conn.Exec_sql
|
||||
( "finalizing page_rank_temp.page_score"
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE page_rank_temp"
|
||||
, "SET page_score = Cast((SELECT tmp.row_score FROM temp_page_score tmp WHERE tmp.row_key = page_rank_temp.page_id) AS int)"
|
||||
));
|
||||
}
|
||||
else {
|
||||
plink_conn.Exec_sql
|
||||
( "finalizing page_rank_temp.page_score"
|
||||
, String_.Format(String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE page_rank_temp"
|
||||
, "SET page_score = Cast(page_len_score AS int)"
|
||||
)));
|
||||
}
|
||||
plink_conn.Meta_idx_create(Xoa_app_.Usr_dlg(), Dbmeta_idx_itm.new_normal_by_tbl("page_rank_temp", "page_score", "page_id", "page_score"));
|
||||
|
||||
// update page table
|
||||
Xowd_page_tbl page_tbl = wiki.Data__core_mgr().Tbl__page();
|
||||
Db_conn page_conn = page_tbl.conn;
|
||||
if (page_tbl.Fld_page_score() == Dbmeta_fld_itm.Key_null) {
|
||||
page_conn.Meta_fld_append(page_tbl.Tbl_name(), Dbmeta_fld_itm.new_int(Xowd_page_tbl.Fld__page_score__key).Default_(0));
|
||||
page_tbl = wiki.Data__core_mgr().Db__core().Tbl__page__rebind();
|
||||
}
|
||||
new Db_attach_mgr(page_conn, new Db_attach_itm("plink_db", plink_conn))
|
||||
.Exec_sql_w_msg("updating page.page_score", String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE page"
|
||||
, "SET page_score = Coalesce((SELECT Cast(pr.page_score AS integer) FROM <plink_db>page_rank_temp pr WHERE pr.page_id = page.page_id), 0)"
|
||||
));
|
||||
|
||||
// update link tables
|
||||
Srch_db_mgr search_db_mgr = Srch_search_addon.Get(wiki).Db_mgr();
|
||||
Srch_word_tbl word_tbl = search_db_mgr.Tbl__word();
|
||||
if (!page_tbl.conn.Eq(word_tbl.conn)) page_tbl.conn.Env_vacuum(); // don't vacuum if single-db
|
||||
// Srch_db_mgr.Optimize_unsafe_(word_tbl.conn, Bool_.Y);
|
||||
word_tbl.conn.Meta_tbl_remake(Dbmeta_tbl_itm.New("link_score_mnx", Dbmeta_fld_itm.new_int("word_id"), Dbmeta_fld_itm.new_int("mnx_val")));
|
||||
int link_tbls_len = search_db_mgr.Tbl__link__len();
|
||||
for (int i = 0; i < link_tbls_len; ++i) {
|
||||
Srch_link_tbl link_tbl = search_db_mgr.Tbl__link__get_at(i);
|
||||
// update search_link.link_score
|
||||
link_tbl.conn.Meta_fld_assert(link_tbl.tbl_name, Srch_link_tbl.Fld_link_score, Dbmeta_fld_tid.Itm__int, 0);
|
||||
new Db_attach_mgr(link_tbl.conn
|
||||
, new Db_attach_itm("page_db", page_conn)
|
||||
).Exec_sql_w_msg
|
||||
( Bry_fmt.Make_str("updating search_link.link_score: ~{idx} of ~{total}", i + 1, link_tbls_len)
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE search_link"
|
||||
, "SET link_score = Coalesce((SELECT page_score FROM <page_db>page p WHERE p.page_id = search_link.page_id), 0)"
|
||||
));
|
||||
Calc_min_max(Bool_.Y, word_tbl, link_tbl, i, link_tbls_len);
|
||||
Calc_min_max(Bool_.N, word_tbl, link_tbl, i, link_tbls_len);
|
||||
link_tbl.Create_idx__link_score();
|
||||
if (!link_tbl.conn.Eq(word_tbl.conn)) link_tbl.conn.Env_vacuum(); // don't vacuum if single-db
|
||||
word_tbl.Create_idx();
|
||||
}
|
||||
word_tbl.conn.Meta_tbl_delete("link_score_mnx");
|
||||
Srch_db_cfg_.Update__bldr__link(search_db_mgr.Tbl__cfg(), search_db_mgr.Cfg(), link_score_max);
|
||||
// Srch_db_mgr.Optimize_unsafe_(word_tbl.conn, Bool_.N);
|
||||
|
||||
if (delete_plink_db) {
|
||||
Xob_db_file plink_db = Xob_db_file.New__page_link(wiki);
|
||||
plink_db.Conn().Rls_conn();
|
||||
Io_mgr.Instance.DeleteFil(plink_db.Url());
|
||||
}
|
||||
}
|
||||
private void Calc_min_max(boolean min, Srch_word_tbl word_tbl, Srch_link_tbl link_tbl, int i, int link_tbls_len) {
|
||||
word_tbl.conn.Meta_idx_delete("link_score_mnx__main");
|
||||
word_tbl.conn.Exec_sql_concat("DELETE FROM link_score_mnx");
|
||||
String prc_name = "Max";
|
||||
String fld_name = "link_score_max";
|
||||
if (min) {
|
||||
prc_name = "Min";
|
||||
fld_name = "link_score_min";
|
||||
}
|
||||
new Db_attach_mgr(word_tbl.conn, new Db_attach_itm("link_db", link_tbl.conn))
|
||||
.Exec_sql_w_msg
|
||||
( Bry_fmt.Make_str("creating temp.link_score_max: ~{idx} of ~{total}", i + 1, link_tbls_len)
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "INSERT INTO link_score_mnx (word_id, mnx_val)"
|
||||
, "SELECT sw.word_id, " + prc_name + "(sl.link_score)"
|
||||
, "FROM search_word sw"
|
||||
, " JOIN <link_db>search_link sl ON sl.word_id = sw.word_id"
|
||||
, "GROUP BY sw.word_id"
|
||||
))
|
||||
;
|
||||
word_tbl.conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_name("link_score_mnx", "main", "word_id", "mnx_val"));
|
||||
word_tbl.conn.Exec_sql_concat_w_msg
|
||||
( Bry_fmt.Make_str("creating temp.link_score_max: ~{idx} of ~{total}", i + 1, link_tbls_len)
|
||||
, "UPDATE search_word"
|
||||
, "SET " + fld_name + " = "
|
||||
, " Coalesce(("
|
||||
, " SELECT mnx_val"
|
||||
, " FROM link_score_mnx lsm"
|
||||
, " WHERE lsm.word_id = search_word.word_id"
|
||||
, " ), " + fld_name + ")"
|
||||
);
|
||||
}
|
||||
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk__page_rank_enabled_)) page_rank_enabled = m.ReadYn("v");
|
||||
else if (ctx.Match(k, Invk__delete_plink_db_)) delete_plink_db = m.ReadYn("v");
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk__page_rank_enabled_ = "page_rank_enabled_", Invk__delete_plink_db_ = "delete_plink_db_";
|
||||
|
||||
public static final String BLDR_CMD_KEY = "search.link__link_score";
|
||||
@Override public String Cmd_key() {return BLDR_CMD_KEY;}
|
||||
public static final Xob_cmd Prototype = new Xobldr__link__link_score(null, null);
|
||||
@Override public Xob_cmd Cmd_clone(Xob_bldr bldr, Xowe_wiki wiki) {return new Xobldr__link__link_score(bldr, wiki);}
|
||||
}
|
||||
@@ -1,113 +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.addons.apps.searchs.bldrs.cmds; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.bldrs.*;
|
||||
import gplx.dbs.*; import gplx.dbs.qrys.*;
|
||||
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.addons.builds.pagelinks.dbs.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*;
|
||||
public class Xobldr__page__page_score extends Xob_cmd__base implements Xob_cmd { // create page_rank in page_db; drop and vaccuum later; avoid cross db for now
|
||||
private double damping_factor = .85;
|
||||
private double error_margin = .0001d;
|
||||
private int iteration_max = 1000;
|
||||
private Db_conn page_conn, plink_conn;
|
||||
private int page_count = 0;
|
||||
public Xobldr__page__page_score(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);}
|
||||
public Xobldr__page__page_score Iteration_max_(int iteration_max) {this.iteration_max = iteration_max; return this;}
|
||||
@Override public void Cmd_run() {
|
||||
Init__tbl();
|
||||
Calc__main();
|
||||
}
|
||||
private void Init__tbl() {
|
||||
wiki.Init_assert();
|
||||
this.page_conn = wiki.Data__core_mgr().Db__core().Conn();
|
||||
page_count = page_conn.Exec_select_as_int("SELECT Count(page_id) FROM page", -1);
|
||||
|
||||
Xob_db_file page_link_db = Xob_db_file.New__page_link(wiki);
|
||||
this.plink_conn = page_link_db.Conn();
|
||||
if (plink_conn.Meta_tbl_exists(Pagerank__tbl_name)) plink_conn.Meta_tbl_delete(Pagerank__tbl_name);
|
||||
Pglnk_page_link_tbl plink_tbl = new Pglnk_page_link_tbl(plink_conn);
|
||||
if (!plink_conn.Meta_tbl_exists(plink_tbl.Tbl_name())) plink_tbl.Create_tbl();// create page_link if it doesn't exist; occurs when page_rank_enabled == false;
|
||||
plink_conn.Meta_tbl_create(Dbmeta_tbl_itm.New
|
||||
( Pagerank__tbl_name
|
||||
, Dbmeta_fld_itm.new_int (Pagerank__fld_page_id).Primary_y_()
|
||||
, Dbmeta_fld_itm.new_int (Pagerank__fld_link_count)
|
||||
, Dbmeta_fld_itm.new_int (Pagerank__fld_has_converged).Default_(0)
|
||||
, Dbmeta_fld_itm.new_double (Pagerank__fld_page_rank).Default_(1)
|
||||
));
|
||||
|
||||
new Db_attach_mgr(plink_conn, new Db_attach_itm("page_db", page_conn))
|
||||
.Exec_sql_w_msg("generating list of pages", String_.Concat_lines_nl_skip_last
|
||||
( "INSERT INTO page_rank_temp (page_id, link_count)"
|
||||
, "SELECT page_id"
|
||||
, ", Coalesce(Count(pl.trg_id), {0}) AS link_count"
|
||||
, "FROM <page_db>page p" // NOTE: JOIN needed to filter out [[User:]] pages which are in pagelinks.sql, but not in pages-articles.xml
|
||||
, " LEFT JOIN page_link pl ON p.page_id = pl.src_id"
|
||||
// , "WHERE p.page_namespace = 0"
|
||||
, "GROUP BY p.page_id"
|
||||
), page_count);
|
||||
}
|
||||
private void Calc__main() {
|
||||
int iteration_idx = 0;
|
||||
double damping_factor_inverse = 1 - damping_factor;
|
||||
while (true) {
|
||||
if (iteration_idx == iteration_max) break;
|
||||
int converged_count = plink_conn.Exec_select_as_int("SELECT Count(page_id) FROM page_rank_temp WHERE has_converged = 0;", 0);
|
||||
if (converged_count == 0) break;
|
||||
new Db_attach_mgr(plink_conn, new Db_attach_itm("page_db", page_conn))
|
||||
.Exec_sql_w_msg(String_.Format("calculating page_rank; iteration={0} unconverged={1}", iteration_idx, converged_count)
|
||||
, String_.Concat_lines_nl_skip_last
|
||||
( "REPLACE INTO page_rank_temp (page_id, page_rank, link_count, has_converged)"
|
||||
, "SELECT pr.page_id"
|
||||
, ", {1} + ({0} * Coalesce(w.page_rank, 0)) AS page_rank"
|
||||
, ", pr.link_count"
|
||||
, ", CASE WHEN Abs(pr.page_rank - ({1} + ({0} * Coalesce(w.page_rank, 0)))) < {2} THEN 1 ELSE 0 END AS has_converged"
|
||||
, "FROM page_rank_temp pr"
|
||||
, " LEFT JOIN"
|
||||
, " (SELECT lnk.trg_id"
|
||||
, " , Sum((Cast(pr2.page_rank AS double) / Cast(pr2.page_rank AS double))) * {0} AS page_rank"
|
||||
, " FROM page_rank_temp pr2"
|
||||
, " JOIN page_link lnk ON pr2.page_id = lnk.src_id"
|
||||
, " JOIN <page_db>page p ON lnk.src_id = p.page_id"
|
||||
// , " WHERE p.page_namespace = 0"
|
||||
, " GROUP BY lnk.trg_id"
|
||||
, " ) AS w ON w.trg_id = pr.page_id"
|
||||
, "WHERE pr.has_converged = 0"
|
||||
), damping_factor, damping_factor_inverse, error_margin);
|
||||
++iteration_idx;
|
||||
}
|
||||
Gfo_usr_dlg_.Instance.Note_many("", "", "page_rank done; iteration=~{0}", iteration_idx);
|
||||
}
|
||||
public static final String
|
||||
Pagerank__tbl_name = "page_rank_temp"
|
||||
, Pagerank__fld_page_id = "page_id"
|
||||
, Pagerank__fld_page_rank = "page_rank"
|
||||
, Pagerank__fld_link_count = "link_count"
|
||||
, Pagerank__fld_has_converged = "has_converged"
|
||||
;
|
||||
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk__damping_factor_)) damping_factor = m.ReadDouble("v");
|
||||
else if (ctx.Match(k, Invk__error_margin_)) error_margin = m.ReadDouble("v");
|
||||
else if (ctx.Match(k, Invk__iteration_max_)) iteration_max = m.ReadInt("v");
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk__damping_factor_ = "damping_factor_", Invk__error_margin_ = "error_margin_", Invk__iteration_max_ = "iteration_max_";
|
||||
|
||||
public static final String BLDR_CMD_KEY = "search.page__page_score";
|
||||
@Override public String Cmd_key() {return BLDR_CMD_KEY;}
|
||||
public static final Xob_cmd Prototype = new Xobldr__page__page_score(null, null);
|
||||
@Override public Xob_cmd Cmd_clone(Xob_bldr bldr, Xowe_wiki wiki) {return new Xobldr__page__page_score(bldr, wiki);}
|
||||
}
|
||||
@@ -1,56 +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.addons.apps.searchs.bldrs.cmds; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.bldrs.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.bldrs.*; import gplx.xowa.bldrs.wkrs.*; import gplx.xowa.addons.builds.utils_rankings.bldrs.*;
|
||||
import gplx.xowa.addons.apps.searchs.dbs.*;
|
||||
public class Xobldr__word__link_count extends Xob_cmd__base implements Xob_cmd {
|
||||
private int score_multiplier = Srch_search_addon.Score_max;
|
||||
public Xobldr__word__link_count(Xob_bldr bldr, Xowe_wiki wiki) {super(bldr, wiki);}
|
||||
@Override public void Cmd_run() {
|
||||
wiki.Init_assert();
|
||||
|
||||
Srch_db_mgr search_db_mgr = Srch_search_addon.Get(wiki).Db_mgr();
|
||||
Srch_word_tbl word_tbl = search_db_mgr.Tbl__word();
|
||||
Db_conn word_conn = word_tbl.conn;
|
||||
String percentile_tbl = "search_word__link_count";
|
||||
Sqlite_percentile_cmd percentile_cmd = new Sqlite_percentile_cmd(bldr, wiki).Init_by_conn(word_conn, percentile_tbl, score_multiplier, String_.Concat_lines_nl_skip_last
|
||||
( "SELECT sw.word_id, sw.link_count"
|
||||
, "FROM search_word sw"
|
||||
, "ORDER BY sw.link_count" // NOTE: ORDER BY is needed b/c INSERT into AUTO INCREMENT table
|
||||
));
|
||||
percentile_cmd.Cmd_run();
|
||||
|
||||
word_conn.Exec_sql("finalizing search_word.link_count_score", String_.Concat_lines_nl_skip_last
|
||||
( "UPDATE search_word"
|
||||
, "SET link_count_score = (SELECT tpl.row_score FROM search_word__link_count tpl WHERE tpl.row_key = search_word.word_id)"
|
||||
));
|
||||
word_conn.Meta_tbl_delete(percentile_tbl);
|
||||
word_conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(word_tbl.tbl_name, "link_count_score__word_text", word_tbl.fld_link_count_score, word_tbl.fld_text));
|
||||
|
||||
int link_count_score_cutoff = word_conn.Exec_select_as_int("SELECT Cast(Min(link_count_score) AS int) AS val FROM search_word WHERE link_count > " + Int_.To_str(Srch_db_cfg_.Link_count_score_cutoff), 0);
|
||||
Srch_db_cfg_.Update__bldr__word(search_db_mgr.Tbl__cfg(), search_db_mgr.Cfg(), percentile_cmd.count, score_multiplier, link_count_score_cutoff);
|
||||
word_conn.Env_vacuum();
|
||||
}
|
||||
@Override public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {return this;}
|
||||
|
||||
public static final String BLDR_CMD_KEY = "search.word__link_count";
|
||||
@Override public String Cmd_key() {return BLDR_CMD_KEY;}
|
||||
public static final Xob_cmd Prototype = new Xobldr__word__link_count(null, null);
|
||||
@Override public Xob_cmd Cmd_clone(Xob_bldr bldr, Xowe_wiki wiki) {return new Xobldr__word__link_count(bldr, wiki);}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
public class Srch_db_cfg {
|
||||
public Srch_db_cfg(int version_id, long page_count, int word_count, int link_count_score_max, int link_count_score_cutoff, int link_score_max) {
|
||||
this.version_id = version_id;
|
||||
this.page_count = page_count;
|
||||
this.word_count = word_count;
|
||||
this.link_count_score_max = link_count_score_max;
|
||||
this.link_count_score_cutoff = link_count_score_cutoff;
|
||||
this.link_score_max = link_score_max;
|
||||
}
|
||||
public int Version_id() {return version_id;} private int version_id;
|
||||
public boolean Version_id__needs_upgrade() {return version_id < Srch_db_upgrade.Version__link_score;}
|
||||
public long Page_count() {return page_count;} private long page_count;
|
||||
public int Word_count() {return word_count;} private int word_count;
|
||||
public int Link_count_score_max() {return link_count_score_max;} private int link_count_score_max;
|
||||
public int Link_count_score_cutoff() {return link_count_score_cutoff;} private int link_count_score_cutoff;
|
||||
public int Link_score_max() {return link_score_max;} private int link_score_max;
|
||||
public void Update_link(int link_score_max) {this.link_score_max = link_score_max;}
|
||||
public void Update_word(int word_count, int link_count_score_max, int link_count_score_cutoff) {
|
||||
this.version_id = Srch_db_upgrade.Version__link_score;
|
||||
this.word_count = word_count;
|
||||
this.link_count_score_max = link_count_score_max;
|
||||
this.link_count_score_cutoff = link_count_score_cutoff;
|
||||
}
|
||||
}
|
||||
@@ -1,61 +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.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.dbs.cfgs.*;
|
||||
public class Srch_db_cfg_ {
|
||||
public static Srch_db_cfg New(Db_cfg_tbl cfg_tbl, long page_count, int version_id) { // NOTE: dflt values are for old search dbs
|
||||
int word_count = cfg_tbl.Assert_int(Grp__search__cfg, Key__word_count, 0);
|
||||
int link_count_score_max = cfg_tbl.Assert_int(Grp__search__cfg, Key__link_count_score_max, 0);
|
||||
int link_count_score_cutoff = cfg_tbl.Assert_int(Grp__search__cfg, Key__link_count_score_cutoff, 0);
|
||||
int link_score_max = cfg_tbl.Assert_int(Grp__search__cfg, Key__link_score_max, 0);
|
||||
return new Srch_db_cfg(version_id, page_count, word_count, link_count_score_max, link_count_score_cutoff, link_score_max);
|
||||
}
|
||||
public static void Update__bldr__link(Db_cfg_tbl cfg_tbl, Srch_db_cfg cfg, int link_score_max) {
|
||||
cfg.Update_link(link_score_max);
|
||||
cfg_tbl.Upsert_int(Grp__search__cfg, Key__link_score_max, link_score_max);
|
||||
}
|
||||
public static void Update__bldr__word(Db_cfg_tbl cfg_tbl, Srch_db_cfg cfg, int word_count, int link_count_score_max, int link_count_score_cutoff) {
|
||||
cfg.Update_word(word_count, link_count_score_max, link_count_score_cutoff);
|
||||
cfg_tbl.Upsert_int(Grp__search__cfg, Key__version_id, Srch_db_upgrade.Version__link_score);
|
||||
cfg_tbl.Upsert_int(Grp__search__cfg, Key__word_count, word_count);
|
||||
cfg_tbl.Upsert_int(Grp__search__cfg, Key__link_count_score_max, link_count_score_max);
|
||||
cfg_tbl.Upsert_int(Grp__search__cfg, Key__link_count_score_cutoff, link_count_score_cutoff);
|
||||
}
|
||||
public static int Select__version_id(Db_cfg_tbl cfg_tbl, Srch_word_tbl word_tbl) {
|
||||
int rv = cfg_tbl.Select_int_or(Grp__search__cfg, Key__version_id, -1);
|
||||
if (rv >= Srch_db_upgrade.Version__link_score) return rv; // version_id exists; return it;
|
||||
if (rv == Srch_db_upgrade.Version__link_score_alpha) { // R.16.03.13 has same schema as later version
|
||||
rv = Srch_db_upgrade.Version__link_score;
|
||||
} else {
|
||||
boolean version_is_page_count = word_tbl.conn.Meta_fld_exists(word_tbl.tbl_name, "word_page_count");
|
||||
rv = version_is_page_count ? Srch_db_upgrade.Version__page_count : Srch_db_upgrade.Version__initial;
|
||||
}
|
||||
cfg_tbl.Upsert_int(Grp__search__cfg, Key__version_id, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static final int Link_count_score_cutoff = 300;
|
||||
private static final String
|
||||
Grp__search__cfg = "xowa.search.cfg"
|
||||
, Key__version_id = "version_id"
|
||||
, Key__word_count = "word_count"
|
||||
, Key__link_count_score_max = "link_count_score_max"
|
||||
, Key__link_count_score_cutoff = "link_count_score_cutoff"
|
||||
, Key__link_score_max = "link_score_max"
|
||||
;
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.dbs.cfgs.*;
|
||||
import gplx.xowa.wikis.data.*;
|
||||
public class Srch_db_mgr {
|
||||
private final Xow_wiki wiki;
|
||||
public final Srch_db_upgrade Upgrade_mgr;
|
||||
public Srch_db_mgr(Xow_wiki wiki) {
|
||||
this.wiki = wiki;
|
||||
Upgrade_mgr = new Srch_db_upgrade(wiki, this);
|
||||
}
|
||||
public Srch_db_cfg Cfg() {return cfg;} private Srch_db_cfg cfg;
|
||||
public Db_cfg_tbl Tbl__cfg() {return tbl__cfg;} private Db_cfg_tbl tbl__cfg;
|
||||
public Srch_word_tbl Tbl__word() {return tbl__word;} private Srch_word_tbl tbl__word;
|
||||
public int Tbl__link__len() {return tbl__link__ary.length;}
|
||||
public Srch_link_tbl Tbl__link__get_at(int i) {return tbl__link__ary[i];}
|
||||
public Srch_link_tbl[] Tbl__link__ary() {return tbl__link__ary;} private Srch_link_tbl[] tbl__link__ary = Srch_link_tbl.Ary_empty;
|
||||
public Srch_db_mgr Init() {
|
||||
Xowd_db_mgr db_mgr = wiki.Data__core_mgr();
|
||||
Xowd_core_db_props db_props = db_mgr.Db__core().Db_props();
|
||||
Xowd_db_file word_db = null;
|
||||
if ( db_props.Schema() == 1
|
||||
|| db_props.Layout_text().Tid_is_all_or_few()) {
|
||||
// single_db; core_db has search_word and search_link
|
||||
word_db = db_mgr.Db__core();
|
||||
tbl__cfg = gplx.xowa.wikis.data.Xowd_cfg_tbl_.New(word_db.Conn());
|
||||
tbl__word = new Srch_word_tbl(word_db.Conn());
|
||||
tbl__link__ary = new Srch_link_tbl[1];
|
||||
Tbl__link__ary__set(tbl__link__ary, 0, word_db);
|
||||
} else {
|
||||
// many_db; figure out link_dbs
|
||||
word_db = db_mgr.Dbs__get_by_tid_or_null(Srch_db_mgr_.Dbtid__search_core);
|
||||
if (word_db == null) return this; // HACK: called during db build; skip;
|
||||
tbl__cfg = gplx.xowa.wikis.data.Xowd_cfg_tbl_.New(word_db.Conn());
|
||||
tbl__word = new Srch_word_tbl(word_db.Conn());
|
||||
Ordered_hash hash = db_mgr.Dbs__get_hash_by_tid(Srch_db_mgr_.Dbtid__search_link);
|
||||
if (hash == null) { // v2 file layout where search_word and search_link is in 1 search_db
|
||||
tbl__link__ary = new Srch_link_tbl[1];
|
||||
Tbl__link__ary__set(tbl__link__ary, 0, word_db);
|
||||
} else { // v3 file layout where search_link is in many db
|
||||
int dbs_len = hash.Count();
|
||||
tbl__link__ary = new Srch_link_tbl[dbs_len];
|
||||
for (int i = 0; i < dbs_len; ++i) {
|
||||
Xowd_db_file db_file = (Xowd_db_file)hash.Get_at(i);
|
||||
Tbl__link__ary__set(tbl__link__ary, i, db_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
cfg = Srch_db_cfg_.New(tbl__cfg, wiki.Stats().Num_pages(), Srch_db_cfg_.Select__version_id(tbl__cfg, tbl__word));
|
||||
return this;
|
||||
}
|
||||
public void Delete_all(Xowd_db_mgr core_data_mgr) {
|
||||
tbl__word.conn.Meta_tbl_delete(Srch_link_reg_tbl.Tbl_name);
|
||||
Xowd_core_db_props db_props = wiki.Data__core_mgr().Db__core().Db_props();
|
||||
if ( db_props.Schema() == 1
|
||||
|| db_props.Layout_text().Tid_is_all_or_few()) {
|
||||
// single_db; just drop tables
|
||||
tbl__word.conn.Meta_tbl_delete(tbl__word.tbl_name);
|
||||
Srch_link_tbl link_tbl = tbl__link__ary[0];
|
||||
link_tbl.conn.Meta_tbl_delete(link_tbl.tbl_name);
|
||||
} else {
|
||||
// many_db; drop databases
|
||||
core_data_mgr.Dbs__delete_by_tid(Xowd_db_file_.Tid_search_core);
|
||||
core_data_mgr.Dbs__delete_by_tid(Xowd_db_file_.Tid_search_link);
|
||||
}
|
||||
}
|
||||
public void Create_all() {
|
||||
Xowd_db_mgr db_mgr = wiki.Data__core_mgr();
|
||||
Xowd_core_db_props db_props = wiki.Data__core_mgr().Db__core().Db_props();
|
||||
if ( db_props.Schema() == 1
|
||||
|| db_props.Layout_text().Tid_is_all_or_few()) {
|
||||
// single_db; put both in core_db
|
||||
Xowd_db_file search_db = db_mgr.Db__core();
|
||||
tbl__word = new Srch_word_tbl(search_db.Conn()); tbl__word.Create_tbl();
|
||||
Srch_link_tbl tbl__link = new Srch_link_tbl(search_db.Conn()); tbl__link.Create_tbl();
|
||||
tbl__link__ary = new Srch_link_tbl[] {tbl__link};
|
||||
Srch_link_reg_tbl tbl__lreg = new Srch_link_reg_tbl(search_db.Conn()); tbl__lreg.Create_tbl();
|
||||
Tbl__link__ary__new(tbl__lreg, tbl__link__ary, db_mgr, 0, Bool_.N, search_db);
|
||||
} else {
|
||||
// many_db: put in 3 db;
|
||||
Xowd_db_file word_db = db_mgr.Dbs__make_by_tid(Srch_db_mgr_.Dbtid__search_core);
|
||||
tbl__word = new Srch_word_tbl(word_db.Conn()); tbl__word.Create_tbl();
|
||||
tbl__link__ary = new Srch_link_tbl[2];
|
||||
Srch_link_reg_tbl tbl__lreg = new Srch_link_reg_tbl(word_db.Conn()); tbl__lreg.Create_tbl();
|
||||
Tbl__link__ary__new(tbl__lreg, tbl__link__ary, db_mgr, 0, Bool_.Y, null);
|
||||
Tbl__link__ary__new(tbl__lreg, tbl__link__ary, db_mgr, 1, Bool_.N, null);
|
||||
}
|
||||
}
|
||||
private static Srch_link_tbl Tbl__link__ary__set(Srch_link_tbl[] ary, int idx, Xowd_db_file db) {
|
||||
Srch_link_tbl tbl = new Srch_link_tbl(db.Conn());
|
||||
ary[idx] = tbl;
|
||||
return tbl;
|
||||
}
|
||||
private static void Tbl__link__ary__new(Srch_link_reg_tbl lreg_tbl, Srch_link_tbl[] ary, Xowd_db_mgr db_mgr, int idx, boolean ns_ids_is_main, Xowd_db_file db) {
|
||||
if (db == null) {
|
||||
String ns_ids = (ns_ids_is_main ? "000" : "999");
|
||||
String suffix = "-xtn.search.link-title-ns." + ns_ids + "-db.001.xowa"; // -xtn.search.link-title-ns.main-db.001.xowa
|
||||
db = db_mgr.Dbs__make_by_tid(Srch_db_mgr_.Dbtid__search_link, ns_ids, idx, suffix);
|
||||
}
|
||||
Srch_link_tbl tbl = Tbl__link__ary__set(ary, idx, db);
|
||||
tbl.Create_tbl();
|
||||
lreg_tbl.Insert(idx, db.Id(), Srch_link_reg_tbl.Db_type__title, ns_ids_is_main ? Srch_link_reg_tbl.Ns_type__main : Srch_link_reg_tbl.Ns_type__rest, 0, -1, -1);
|
||||
}
|
||||
public static void Optimize_unsafe_(gplx.dbs.Db_conn conn, boolean v) {
|
||||
if (v) {
|
||||
conn.Exec_qry(gplx.dbs.engines.sqlite.Sqlite_pragma.New__journal__off());
|
||||
conn.Exec_qry(gplx.dbs.engines.sqlite.Sqlite_pragma.New__synchronous__off());
|
||||
}
|
||||
else {
|
||||
conn.Exec_qry(gplx.dbs.engines.sqlite.Sqlite_pragma.New__journal__delete());
|
||||
conn.Exec_qry(gplx.dbs.engines.sqlite.Sqlite_pragma.New__synchronous__full());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +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.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.wikis.data.*;
|
||||
public class Srch_db_mgr_ {
|
||||
public static final byte Dbtid__search_core = 4, Dbtid__search_link = 16; // SYNC:Xowd_db_file_
|
||||
}
|
||||
@@ -1,55 +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.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.dbs.*; import gplx.dbs.cfgs.*;
|
||||
public class Srch_db_upgrade {
|
||||
private final Xow_wiki wiki;
|
||||
private boolean upgrade_prompted;
|
||||
public Srch_db_upgrade(Xow_wiki wiki, Srch_db_mgr search_db_mgr) {
|
||||
this.wiki = wiki;
|
||||
}
|
||||
public void Upgrade() {
|
||||
if (!wiki.App().Mode().Tid_is_gui()) return; // ignore if html-server or drd-app
|
||||
if (upgrade_prompted) return;
|
||||
upgrade_prompted = true;
|
||||
Xoae_app app = ((Xoae_app)wiki.App());
|
||||
boolean ok = app.Gui_mgr().Kit().Ask_ok_cancel("", "", String_.Concat_lines_nl_skip_last
|
||||
( "XOWA would like to upgrade your search database for " + wiki.Domain_str() + "."
|
||||
, ""
|
||||
, "* Press OK to upgrade. This may take an hour for English Wikipedia."
|
||||
, "* Press Cancel to skip. You will not be able to search."
|
||||
, ""
|
||||
, "If you cancel, XOWA will ask you to upgrade this wiki again next time you restart the application."
|
||||
, ""
|
||||
, "Note that you can run this upgrade process manually by doing:"
|
||||
, " Main Menu -> Tools -> Wiki Maintenance -> Search"
|
||||
));
|
||||
if (!ok) return;
|
||||
Xowe_wiki wikie = (Xowe_wiki)wiki;
|
||||
gplx.xowa.addons.apps.searchs.bldrs.Srch_bldr_mgr_.Setup(wikie);
|
||||
gplx.xowa.bldrs.Xob_bldr bldr = app.Bldr();
|
||||
bldr.Cmd_mgr().Add(new gplx.xowa.bldrs.cmds.utils.Xob_alert_cmd(bldr, wikie).Msg_("search upgrade finished"));
|
||||
gplx.core.threads.Thread_adp_.invk_("search_upgrade", app.Bldr(), gplx.xowa.bldrs.Xob_bldr.Invk_run).Start();
|
||||
}
|
||||
public static final int
|
||||
Version__link_score_alpha = 0 // in 2016-02 android alpha
|
||||
, Version__initial = 1
|
||||
, Version__page_count = 2
|
||||
, Version__link_score = 3
|
||||
;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.dbs.*;
|
||||
public class Srch_link_reg_tbl implements Rls_able {
|
||||
private final String tbl_name; public final Dbmeta_fld_list flds = Dbmeta_fld_list.new_();
|
||||
private final String fld_id, fld_db_id, fld_db_type, fld_ns_ids, fld_sub_id, fld_score_min, fld_score_max;
|
||||
private final Db_conn conn;
|
||||
public Srch_link_reg_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
tbl_name = Tbl_name;
|
||||
fld_id = flds.Add_int_pkey ("reg_id"); // corresponds to link_tbl_ary_idx
|
||||
fld_db_id = flds.Add_int ("reg_db_id"); // corresponds to xowa_db
|
||||
fld_db_type = flds.Add_int ("reg_db_type"); // "title"; "text"
|
||||
fld_ns_ids = flds.Add_int ("reg_ns_ids"); // "0"; "*"
|
||||
fld_sub_id = flds.Add_int ("reg_sub_id"); // "0"; "*"
|
||||
fld_score_min = flds.Add_int ("reg_score_min"); // -1
|
||||
fld_score_max = flds.Add_int ("reg_score_max"); // -1
|
||||
}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
|
||||
public void Rls() {}
|
||||
public void Insert(int id, int db_id, String db_type, String ns_ids, int sub_id, int score_min, int score_max) {
|
||||
Db_stmt stmt_insert = conn.Stmt_insert(tbl_name, flds);
|
||||
stmt_insert.Clear().Val_int(fld_id, id).Val_int(fld_db_id, db_id).Val_str(fld_db_type, db_type).Val_str(fld_ns_ids, ns_ids).Val_int(fld_sub_id, sub_id).Val_int(fld_score_min, score_min).Val_int(fld_score_max, score_max).Exec_insert();
|
||||
}
|
||||
public static final String Tbl_name = "search_link_reg";
|
||||
public static final String Db_type__title = "title" , Db_type__text = "text";
|
||||
public static final String Ns_type__main = "0" , Ns_type__rest = "*";
|
||||
}
|
||||
@@ -1,38 +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.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.dbs.*;
|
||||
public class Srch_link_tbl {
|
||||
public final String tbl_name;
|
||||
public final Dbmeta_fld_list flds = Dbmeta_fld_list.new_();
|
||||
public final String fld_word_id, fld_page_id, fld_link_score;
|
||||
public final Db_conn conn;
|
||||
public Srch_link_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
this.tbl_name = "search_link";
|
||||
fld_word_id = flds.Add_int("word_id");
|
||||
fld_page_id = flds.Add_int("page_id");
|
||||
fld_link_score = flds.Add_int_dflt(Fld_link_score, 0);
|
||||
}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
|
||||
public void Create_idx__page_id() {} // TODO: conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "page_id", fld_page_id));}
|
||||
public void Create_idx__link_score() {conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "word_id__link_score", fld_word_id, Fld_link_score));}
|
||||
|
||||
public static final Srch_link_tbl[] Ary_empty = new Srch_link_tbl[0];
|
||||
public static final String Fld_link_score = "link_score";
|
||||
}
|
||||
@@ -1,48 +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.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.dbs.*;
|
||||
public class Srch_temp_tbl {
|
||||
public final String tbl_name = "search_temp";
|
||||
private final Dbmeta_fld_list flds = Dbmeta_fld_list.new_();
|
||||
private final String fld_word_id, fld_page_id, fld_word_text;
|
||||
public final Db_conn conn; private Db_stmt stmt_insert;
|
||||
public Srch_temp_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
flds.Add_int_pkey_autonum("word_uid");
|
||||
fld_word_id = flds.Add_int("word_id");
|
||||
fld_page_id = flds.Add_int("page_id");
|
||||
fld_word_text = flds.Add_str("word_text", 255);
|
||||
}
|
||||
public void Insert_bgn() {
|
||||
conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));
|
||||
stmt_insert = conn.Stmt_insert(tbl_name, flds);
|
||||
conn.Txn_bgn("schema__search_temp__insert");
|
||||
}
|
||||
public void Insert_cmd_by_batch(int word_id, int page_id, byte[] word) {
|
||||
stmt_insert.Clear().Val_int(fld_word_id, word_id).Val_int(fld_page_id, page_id).Val_bry_as_str(fld_word_text, word).Exec_insert();
|
||||
}
|
||||
public void Insert_end() {
|
||||
conn.Txn_end();
|
||||
stmt_insert = Db_stmt_.Rls(stmt_insert);
|
||||
// Srch_db_mgr.Optimize_unsafe_(conn, Bool_.Y); // NOTE: fails in multi-db due to transaction
|
||||
conn.Meta_idx_create(Xoa_app_.Usr_dlg(), Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "word_text__word_id", fld_word_text, fld_word_id));
|
||||
// conn.Meta_idx_create(Xoa_app_.Usr_dlg(), Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "page_id", fld_page_id));
|
||||
// Srch_db_mgr.Optimize_unsafe_(conn, Bool_.N);
|
||||
}
|
||||
}
|
||||
@@ -1,31 +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.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
public class Srch_word_row {
|
||||
public Srch_word_row(int id, byte[] text, int link_count, int link_score_min, int link_score_max) {
|
||||
this.Id = id; this.Text = text; this.Link_count = link_count;
|
||||
this.Link_score_min = link_score_min; this.Link_score_max = link_score_max;
|
||||
}
|
||||
public final int Id;
|
||||
public final byte[] Text;
|
||||
public final int Link_count;
|
||||
public final int Link_score_min;
|
||||
public final int Link_score_max;
|
||||
|
||||
public static final Srch_word_row Empty = new Srch_word_row(-1, Bry_.Empty, 0, 0, 0);
|
||||
}
|
||||
@@ -1,64 +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.addons.apps.searchs.dbs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.dbs.*;
|
||||
public class Srch_word_tbl implements Rls_able {
|
||||
public final String tbl_name;
|
||||
public final Dbmeta_fld_list flds = Dbmeta_fld_list.new_();
|
||||
public final String fld_id, fld_text, fld_link_count, fld_link_count_score, fld_link_score_min, fld_link_score_max;
|
||||
public final Db_conn conn; private Db_stmt stmt_insert, stmt_select_by;
|
||||
public Srch_word_tbl(Db_conn conn) {
|
||||
this.conn = conn;
|
||||
this.tbl_name = "search_word";
|
||||
this.fld_id = flds.Add_int_pkey("word_id");
|
||||
this.fld_text = flds.Add_str("word_text", 255);
|
||||
this.fld_link_count = flds.Add_int("link_count");
|
||||
this.fld_link_count_score = Dbmeta_fld_itm.Make_or_null(conn, flds, tbl_name, Dbmeta_fld_tid.Tid__int, 0, "link_count_score");
|
||||
this.fld_link_score_min = Dbmeta_fld_itm.Make_or_null(conn, flds, tbl_name, Dbmeta_fld_tid.Tid__int, Int_.Max_value__31, "link_score_min");
|
||||
this.fld_link_score_max = Dbmeta_fld_itm.Make_or_null(conn, flds, tbl_name, Dbmeta_fld_tid.Tid__int, 0, "link_score_max");
|
||||
conn.Rls_reg(this);
|
||||
}
|
||||
public void Create_tbl() {conn.Meta_tbl_create(Dbmeta_tbl_itm.New(tbl_name, flds));}
|
||||
public void Create_idx() {
|
||||
// idx for rng_bgn, rng_end
|
||||
conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "word_text__link_score_max__link_score_min", fld_text, Fld_link_score_max, Fld_link_score_min));
|
||||
|
||||
// idx for like
|
||||
conn.Meta_idx_create(Dbmeta_idx_itm.new_normal_by_tbl(tbl_name, "link_score_max__link_score_min", Fld_link_score_max, Fld_link_score_min));
|
||||
}
|
||||
public void Insert_bgn() {conn.Txn_bgn("schema__search_word__insert"); stmt_insert = conn.Stmt_insert(tbl_name, flds);}
|
||||
public void Insert_end() {conn.Txn_end(); stmt_insert = Db_stmt_.Rls(stmt_insert);}
|
||||
public void Insert_cmd_by_batch(int id, byte[] word, int page_count) {stmt_insert.Clear().Val_int(fld_id, id).Val_bry_as_str(fld_text, word).Val_int(fld_link_count, page_count).Exec_insert();}
|
||||
public Srch_word_row Select_or_empty(byte[] word) {
|
||||
if (stmt_select_by == null) stmt_select_by = conn.Stmt_select(tbl_name, flds, fld_text);
|
||||
Db_rdr rdr = stmt_select_by.Clear().Crt_bry_as_str(fld_text, word).Exec_select__rls_manual();
|
||||
try {return rdr.Move_next() ? New_row(rdr) : Srch_word_row.Empty;}
|
||||
finally {rdr.Rls();}
|
||||
}
|
||||
public Srch_word_row New_row(Db_rdr rdr) {
|
||||
int page_count = fld_link_count == Dbmeta_fld_itm.Key_null ? 0 : rdr.Read_int(fld_link_count);
|
||||
int link_score_min = fld_link_score_min == Dbmeta_fld_itm.Key_null ? page_count : rdr.Read_int(fld_link_score_min);
|
||||
int link_score_max = fld_link_score_max == Dbmeta_fld_itm.Key_null ? page_count : rdr.Read_int(fld_link_score_max);
|
||||
return new Srch_word_row(rdr.Read_int(fld_id), rdr.Read_bry_by_str(fld_text), page_count, link_score_min, link_score_max);
|
||||
}
|
||||
public void Rls() {
|
||||
stmt_insert = Db_stmt_.Rls(stmt_insert);
|
||||
stmt_select_by = Db_stmt_.Rls(stmt_select_by);
|
||||
}
|
||||
public static final String Fld_link_score_min = "link_score_min", Fld_link_score_max = "link_score_max";
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.btries.*;
|
||||
import gplx.xowa.langs.cases.*;
|
||||
public class Srch_highlight_mgr {
|
||||
private final Xol_case_mgr case_mgr;
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_(32);
|
||||
private Srch_highlight_itm[] srch_lc_itms;
|
||||
private int srch_words_len;
|
||||
public Srch_highlight_mgr(Xol_case_mgr case_mgr) {this.case_mgr = case_mgr;}
|
||||
public Srch_highlight_mgr Search_(byte[] srch_mc_bry) {
|
||||
synchronized (tmp_bfr) {
|
||||
// build array of search_words
|
||||
byte[] srch_lc_bry = case_mgr.Case_build_lower(srch_mc_bry);
|
||||
byte[][] srch_lc_ary = Bry_split_.Split(srch_lc_bry, Byte_ascii.Space, Bool_.Y);
|
||||
this.srch_words_len = srch_lc_ary.length;
|
||||
this.srch_lc_itms = new Srch_highlight_itm[srch_words_len];
|
||||
for (int i = 0; i < srch_words_len; ++i) {
|
||||
byte[] srch_lc_itm = srch_lc_ary[i];
|
||||
srch_lc_itms[i] = new Srch_highlight_itm(i, srch_lc_itm);
|
||||
}
|
||||
|
||||
// sort to search first by longest search_word; needed for searches like "A Abc" and titles like "Abc A", else "A" will match "Abc" and "Abc" will match nothing
|
||||
Array_.Sort(srch_lc_itms, Srch_highlight_bry_sorter.Instance);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
public byte[] Highlight(byte[] page_mc_bry) {
|
||||
synchronized (tmp_bfr) {
|
||||
byte[][] page_mc_words = Bry_split_.Split(page_mc_bry, Byte_ascii.Space, Bool_.Y);
|
||||
byte[][] page_lc_words = Bry_split_.Split(case_mgr.Case_build_lower(page_mc_bry), Byte_ascii.Space, Bool_.Y);
|
||||
int page_words_len = page_lc_words.length;
|
||||
boolean[] page_words_done = new boolean[page_words_len];
|
||||
|
||||
// loop over search_words; EX: search_raw="a b" -> "a", "b"
|
||||
for (int i = 0; i < srch_words_len; ++i) {
|
||||
Srch_highlight_itm srch_lc_itm = srch_lc_itms[i];
|
||||
byte[] srch_lc_word = srch_lc_itm.Word;
|
||||
|
||||
// loop over page_title words; EX: page_raw="A B C" -> "a", "b", "c"
|
||||
for (int j = 0; j < page_words_len; ++j) {
|
||||
byte[] page_lc_word = page_lc_words[j];
|
||||
int find_pos = Bry_find_.Find_fwd(page_lc_word, srch_lc_word);
|
||||
|
||||
// skip: search is not in page; EX: page_raw="D e"; should not happen, but exit now else Array out of bounds exception below
|
||||
if (find_pos == Bry_find_.Not_found) continue;
|
||||
|
||||
// skip: find_pos is not BOS and prv byte is not dash or paren; EX: "Za" should be skipped; "-a" and "(a" should not
|
||||
if (find_pos > 0) {
|
||||
byte prv_byte = page_lc_word[find_pos - 1];
|
||||
if ( prv_byte != Byte_ascii.Dash
|
||||
&& prv_byte != Byte_ascii.Paren_bgn
|
||||
)
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip: item already matched; EX: "a"; "a a"
|
||||
if (page_words_done[j]) continue;
|
||||
page_words_done[j] = true;
|
||||
|
||||
// NOTE: lc_idx is guaranteed to equal mc_idx
|
||||
byte[] page_mc_word = page_mc_words[j];
|
||||
int srch_lc_word_len = srch_lc_word.length;
|
||||
|
||||
// build new word; EX: "<strong>A</strong>"
|
||||
tmp_bfr.Clear();
|
||||
tmp_bfr.Add_mid(page_mc_word, 0, find_pos);
|
||||
tmp_bfr.Add(gplx.langs.htmls.Gfh_tag_.Strong_lhs);
|
||||
tmp_bfr.Add_mid(page_mc_word, find_pos, find_pos + srch_lc_word_len);
|
||||
tmp_bfr.Add(gplx.langs.htmls.Gfh_tag_.Strong_rhs);
|
||||
tmp_bfr.Add_mid(page_mc_word, find_pos + srch_lc_word_len, page_mc_word.length);
|
||||
byte[] repl = tmp_bfr.To_bry_and_clear();
|
||||
|
||||
// overwrite page_title word
|
||||
page_mc_words[j] = repl;
|
||||
}
|
||||
}
|
||||
|
||||
// rebuild page_words ary
|
||||
for (int i = 0; i < page_words_len; ++i) {
|
||||
if (i != 0) tmp_bfr.Add_byte_space(); // NOTE: this assumes one space separating titles which is true for all MW titles
|
||||
tmp_bfr.Add(page_mc_words[i]);
|
||||
}
|
||||
return tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
class Srch_highlight_itm {
|
||||
public Srch_highlight_itm(int idx, byte[] word) {this.Idx = idx; this.Word = word; this.Word_len = word.length;}
|
||||
public final int Idx;
|
||||
public final byte[] Word;
|
||||
public final int Word_len;
|
||||
}
|
||||
class Srch_highlight_bry_sorter implements gplx.core.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Srch_highlight_itm lhs = (Srch_highlight_itm)lhsObj;
|
||||
Srch_highlight_itm rhs = (Srch_highlight_itm)rhsObj;
|
||||
return -Int_.Compare(lhs.Word_len, rhs.Word_len); // - for descending
|
||||
}
|
||||
public static final Srch_highlight_bry_sorter Instance = new Srch_highlight_bry_sorter(); Srch_highlight_bry_sorter() {}
|
||||
}
|
||||
@@ -1,47 +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.addons.apps.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import org.junit.*; import gplx.xowa.langs.cases.*;
|
||||
public class Srch_highlight_mgr_tst {
|
||||
private final Srch_highlight_mgr_tstr tstr = new Srch_highlight_mgr_tstr();
|
||||
@Test public void Full__one() {tstr.Test("a" , "A" , "<strong>A</strong>");}
|
||||
@Test public void Full__many() {tstr.Test("a b" , "A B" , "<strong>A</strong> <strong>B</strong>");}
|
||||
@Test public void Part__one() {tstr.Test("a" , "A1" , "<strong>A</strong>1");}
|
||||
@Test public void Part__many() {tstr.Test("a b" , "A1 B1" , "<strong>A</strong>1 <strong>B</strong>1");}
|
||||
@Test public void Unordered() {tstr.Test("b a" , "A1 B1" , "<strong>A</strong>1 <strong>B</strong>1");}
|
||||
@Test public void Repeat__part() {tstr.Test("a ab" , "Ab A" , "<strong>Ab</strong> <strong>A</strong>");}
|
||||
@Test public void Repeat__full() {tstr.Test("a" , "A A" , "<strong>A</strong> <strong>A</strong>");}
|
||||
@Test public void Close() {tstr.Test("a" , "Ba Aa" , "Ba <strong>A</strong>a");}
|
||||
@Test public void Comma() {tstr.Test("a" , "A, b" , "<strong>A</strong>, b");}
|
||||
@Test public void Dash() {tstr.Test("b" , "A-B c" , "A-<strong>B</strong> c");}
|
||||
@Test public void Parens() {tstr.Test("a" , "(A)" , "(<strong>A</strong>)");}
|
||||
@Test public void Strong() {tstr.Test("strong" , "strong strong" , "<strong>strong</strong> <strong>strong</strong>");}
|
||||
@Test public void Dash_w_mixed_cases() {tstr.Test("b" , "A-a B" , "A-a <strong>B</strong>");} // search_parser treats A-a separately from a-a
|
||||
@Test public void Acronymn() {tstr.Test("ab" , "A.B." , "A.B.");}
|
||||
// @Test public void Slash() {tstr.Test("b" , "A/B/C" , "A/<strong>B</strong>/C");}
|
||||
}
|
||||
class Srch_highlight_mgr_tstr {
|
||||
private final Srch_highlight_mgr mgr;
|
||||
private final Xol_case_mgr case_mgr = Xol_case_mgr_.A7();
|
||||
public Srch_highlight_mgr_tstr() {
|
||||
mgr = new Srch_highlight_mgr(case_mgr);
|
||||
}
|
||||
public void Test(String search, String title, String expd) {
|
||||
Tfds.Eq(expd, String_.new_u8(mgr.Search_(Bry_.new_u8(search)).Highlight(Bry_.new_u8(title))));
|
||||
}
|
||||
}
|
||||
@@ -1,262 +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.addons.apps.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.btries.*; import gplx.core.primitives.*;
|
||||
interface Srch_sym_parser {
|
||||
int Tid();
|
||||
byte[][] Hooks_ary();
|
||||
int Parse(Srch_text_parser mgr, byte[] src, int src_end, int hook_bgn, int hook_end);
|
||||
}
|
||||
class Srch_sym_parser_ {
|
||||
public static final int Tid__terminal = 1, Tid__split = 2, Tid__enclosure = 3, Tid__dot = 4, Tid__ellipsis = 5, Tid__apos = 6, Tid__dash = 7;
|
||||
}
|
||||
class Srch_sym_parser__terminal implements Srch_sym_parser {
|
||||
public Srch_sym_parser__terminal(byte[] hook_bry) {this.hooks_ary = Bry_.Ary(hook_bry);}
|
||||
public int Tid() {return Srch_sym_parser_.Tid__terminal;}
|
||||
public byte[][] Hooks_ary() {return hooks_ary;} private final byte[][] hooks_ary;
|
||||
public int Parse(Srch_text_parser mgr, byte[] src, int src_end, int hook_bgn, int hook_end) {
|
||||
if (mgr.Cur__end__chk(hook_end)) { // hook at word_end; EX: "a, b" -> "a", "b"
|
||||
int word_bgn = mgr.Cur__bgn();
|
||||
if (word_bgn == Srch_text_parser.None) return hook_end;
|
||||
int word_end = hook_bgn;
|
||||
for (int i = hook_bgn - 1; i >= word_bgn; --i) { // loop bwd to gobble up streams of terminals; EX: "?!"
|
||||
byte b = src[i];
|
||||
if (mgr.word_end_trie.Match_bgn_w_byte(b, src, i, hook_bgn) == null) break;
|
||||
word_end = i;
|
||||
}
|
||||
mgr.Words__add_if_pending_and_clear(word_end); // make word; note that " , " will not make word b/c word_bgn == -1
|
||||
return hook_end;
|
||||
}
|
||||
else {}// hook at word_mid or word_bgn; noop; EX: "1,000" -> "1,000"; note that " ,abc" will ignore ","
|
||||
// if (mgr.Cur__bgn() == - 1) {
|
||||
// mgr.Cur__bgn__set(hook_bgn);
|
||||
// }
|
||||
// }
|
||||
return hook_end;
|
||||
}
|
||||
}
|
||||
class Srch_sym_parser__split implements Srch_sym_parser {
|
||||
private final Btrie_slim_mgr trie = Btrie_slim_mgr.cs();
|
||||
private final boolean handle_eos;
|
||||
public Srch_sym_parser__split(boolean handle_eos, String... hooks_ary_as_str) {
|
||||
this.handle_eos = handle_eos;
|
||||
this.hooks_ary = Bry_.Ary(hooks_ary_as_str);
|
||||
int hooks_len = hooks_ary.length;
|
||||
for (int i = 0; i < hooks_len; ++i) {
|
||||
byte[] hook = hooks_ary[i];
|
||||
trie.Add_obj(hook, Int_obj_val.new_(hook.length));
|
||||
}
|
||||
}
|
||||
public int Tid() {return Srch_sym_parser_.Tid__split;}
|
||||
public byte[][] Hooks_ary() {return hooks_ary;} private final byte[][] hooks_ary;
|
||||
public int Parse(Srch_text_parser mgr, byte[] src, int src_end, int hook_bgn, int hook_end) {
|
||||
mgr.Words__add_if_pending_and_clear(hook_bgn);
|
||||
|
||||
int rv = hook_end;
|
||||
while (rv < src_end) { // loop to skip multiple syms in same group; EX: "a \n\t\r b"
|
||||
byte b = src[rv];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, rv, src_end);
|
||||
if (o == null) break; // current sequence is not in grp; stop
|
||||
Int_obj_val itm_len = (Int_obj_val)o;
|
||||
rv += itm_len.Val(); // add len of sym to pos
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public int Find_fwd(byte[] src, int src_bgn, int src_end) {
|
||||
for (int i = src_bgn; i < src_end; ++i) {
|
||||
byte b = src[i];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, i, src_end);
|
||||
if (o != null) return i;
|
||||
}
|
||||
return src_end;
|
||||
}
|
||||
public boolean Is_next(byte[] src, int pos, int end) {
|
||||
if (pos >= end) return handle_eos;
|
||||
byte b = src[pos];
|
||||
Object o = trie.Match_bgn_w_byte(b, src, pos, end);
|
||||
return o != null;
|
||||
}
|
||||
}
|
||||
class Srch_sym_parser__paren_bgn implements Srch_sym_parser {
|
||||
private final byte bgn_byte, end_byte;
|
||||
public Srch_sym_parser__paren_bgn(byte bgn_byte, byte end_byte) {
|
||||
this.bgn_byte = bgn_byte; this.end_byte = end_byte;
|
||||
this.hooks_ary = Bry_.Ary(Bry_.New_by_byte(bgn_byte));
|
||||
}
|
||||
public int Tid() {return Srch_sym_parser_.Tid__enclosure;}
|
||||
public byte[][] Hooks_ary() {return hooks_ary;} private final byte[][] hooks_ary;
|
||||
public int Parse(Srch_text_parser mgr, byte[] src, int src_end, int paren_lhs_bgn, int paren_lhs_end) {
|
||||
int word_bgn = mgr.Cur__bgn();
|
||||
paren_lhs_end = Bry_find_.Find_fwd_while(src, paren_lhs_end, src_end, bgn_byte);
|
||||
int paren_rhs_bgn = Bry_find_.Find_fwd(src, end_byte, paren_lhs_end, src_end);
|
||||
if (paren_rhs_bgn == Bry_find_.Not_found) return paren_lhs_end; // paren_rhs missing; noop; NOTE: handles both "a(b" -> "a(b" and "a (b" -> "a", "b"
|
||||
int paren_rhs_end = Bry_find_.Find_fwd_while(src, paren_rhs_bgn, src_end, end_byte);
|
||||
int word_end = mgr.Cur__end__find__text_only(paren_lhs_end + 1);
|
||||
if (word_end < paren_rhs_bgn)
|
||||
word_end = mgr.Cur__end__find__text_only(paren_rhs_end);
|
||||
boolean recurse = false;
|
||||
if (word_bgn == -1) { // paren_lhs at word_bgn; EX: "a (b)"
|
||||
if (word_end == paren_rhs_end) // paren_rhs at word_end; EX: "a (b) c"
|
||||
recurse = true;
|
||||
else { // paren_rhs at word_mid; EX: "a (b)c"
|
||||
mgr.Words__add_direct(paren_lhs_bgn, word_end);
|
||||
mgr.Words__add_direct(paren_rhs_end, word_end);
|
||||
}
|
||||
}
|
||||
else { // paren_lhs at word_mid; EX: "a(b)"
|
||||
mgr.Words__add_direct(word_bgn, word_end);
|
||||
if (word_end == paren_rhs_end) // paren_rhs at word_end; EX: "a(b) c"
|
||||
mgr.Words__add_direct(word_bgn, paren_lhs_bgn);
|
||||
else {} // paren_rhs at word_mid; EX: "a (b)c"
|
||||
mgr.Cur__bgn__reset();
|
||||
}
|
||||
if (recurse)
|
||||
mgr.Make_copy().Parse(mgr.lcase, src, paren_lhs_end, paren_rhs_bgn);
|
||||
return word_end;
|
||||
}
|
||||
}
|
||||
class Srch_sym_parser__dot implements Srch_sym_parser { // handle periods which will add two entries; EX: "H. G. Wells" -> "H.", "G.", "H", "G", "Wells"
|
||||
private final byte[] sym; private final int sym_len;
|
||||
public Srch_sym_parser__dot(String sym_str) {this.sym = Bry_.new_u8(sym_str); this.sym_len = sym.length;}
|
||||
public int Tid() {return Srch_sym_parser_.Tid__dot;}
|
||||
public byte[][] Hooks_ary() {return Hooks_const;} private static final byte[][] Hooks_const = Bry_.Ary(".");
|
||||
public int Parse(Srch_text_parser mgr, byte[] src, int src_end, int hook_bgn, int hook_end) {
|
||||
int word_bgn = mgr.Cur__bgn();
|
||||
if (word_bgn == -1) { // dot at start of word; EX: ".NET", "Colt .45"
|
||||
int word_end = mgr.Cur__end__find(hook_bgn + 1);
|
||||
if (word_end - hook_bgn == 1) return hook_end; // ignore stand-alone sym; EX: "a . . . b"
|
||||
mgr.Words__add__chk_dash(hook_bgn, word_end); // make word; EX: ".45"
|
||||
if (Bry_find_.Find_fwd(src, sym, hook_bgn + 1, word_end) == -1) // only add "root" word, if sym is not in middle of String; EX: ".int" -> "int"; ".A.B" x> "A.B"
|
||||
mgr.Words__add__chk_dash(hook_bgn + 1, word_end); // make word; EX: "45"
|
||||
mgr.Cur__bgn__reset();
|
||||
return word_end;
|
||||
}
|
||||
else {
|
||||
if (mgr.Cur__end__chk(hook_end)) { // at end of word; EX: "U.S.A. b" vs. "H. G. b"
|
||||
mgr.Words__add__chk_dash(word_bgn, hook_end); // make word; EX: "vs."
|
||||
if (Bry_find_.Find_fwd(src, sym, word_bgn, hook_bgn) == -1) // no dots in word; add "root" word; "vs." -> "vs.", "vs"; "U.S.A." -> "U.S.A." x> "U.S.A"
|
||||
mgr.Words__add__chk_dash(word_bgn, hook_bgn); // make word; EX: "vs"
|
||||
else {
|
||||
for (int i = word_bgn; i < hook_end; ++i) { // dots in middle of String; extract word; EX: "U.S.A." -> USA
|
||||
if (Bry_.Eq(src, i, i + sym_len, sym)) continue;// skip syms
|
||||
mgr.Tmp_bfr.Add_byte(src[i]);
|
||||
}
|
||||
mgr.Words__add_direct(mgr.Tmp_bfr.To_bry_and_clear());
|
||||
}
|
||||
mgr.Cur__bgn__reset();
|
||||
}
|
||||
}
|
||||
return hook_end;
|
||||
}
|
||||
}
|
||||
class Srch_sym_parser__ellipsis implements Srch_sym_parser { // ellipsis which have variable length; EX: "..", "...", ".... "
|
||||
private final byte ellipsis_byte;
|
||||
public Srch_sym_parser__ellipsis(byte ellipsis_byte, String hook) {
|
||||
this.ellipsis_byte = ellipsis_byte;
|
||||
this.hooks_ary = Bry_.Ary(hook);
|
||||
}
|
||||
public int Tid() {return Srch_sym_parser_.Tid__ellipsis;}
|
||||
public byte[][] Hooks_ary() {return hooks_ary;} private final byte[][] hooks_ary;
|
||||
public int Parse(Srch_text_parser mgr, byte[] src, int src_end, int hook_bgn, int hook_end) {
|
||||
mgr.Words__add_if_pending_and_clear(hook_bgn); // add word; EX: "Dreams" in "Dreams..."
|
||||
int rv = Bry_find_.Find_fwd_while(src, hook_end, src_end, ellipsis_byte); // skip multiple ellipsis; EX: ......
|
||||
mgr.Words__add__chk_dash(hook_bgn, rv); // add ellipsis
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
class Srch_sym_parser__apos implements Srch_sym_parser { // apos which can be contraction ("I'm"), possessive ("today's") and plural ("plans'")
|
||||
private final byte[] hook_bry;
|
||||
public Srch_sym_parser__apos(String hook) {
|
||||
this.hook_bry = Bry_.new_u8(hook);
|
||||
this.hooks_ary = Bry_.Ary(hook_bry);
|
||||
}
|
||||
public int Tid() {return Srch_sym_parser_.Tid__apos;}
|
||||
public byte[][] Hooks_ary() {return hooks_ary;} private final byte[][] hooks_ary;
|
||||
public int Parse(Srch_text_parser mgr, byte[] src, int src_end, int hook_bgn, int hook_end) {
|
||||
int word_bgn = mgr.Cur__bgn();
|
||||
int word_end = -1;
|
||||
if (word_bgn == -1) { // sym at word_bgn; EX: "'n'"
|
||||
word_bgn = hook_bgn;
|
||||
word_end = mgr.Cur__end__find(hook_bgn + 1);
|
||||
mgr.Words__add__chk_dash(word_bgn, word_end);
|
||||
|
||||
// "'n'" -> "n"
|
||||
int alt_word_bgn = word_bgn + 1;
|
||||
int alt_word_end = Bry_find_.Find_bwd__skip(src, word_end, alt_word_bgn, hook_bry);
|
||||
if (alt_word_end - alt_word_bgn > 0) // do not add if 0-len; EX: "' (disambiguation)"
|
||||
mgr.Words__add__chk_dash(alt_word_bgn, alt_word_end);
|
||||
mgr.Cur__bgn__reset();
|
||||
return word_end;
|
||||
}
|
||||
word_end = mgr.Cur__end__find(hook_end);
|
||||
if (hook_end == word_end) { // sym at word_end; EX: "A' "
|
||||
mgr.Words__add_if_pending_and_clear(hook_bgn); // add root only; EX: "a'" -> "a" x> "a", "a'"
|
||||
return hook_end;
|
||||
}
|
||||
else {
|
||||
byte[] root_word = null;
|
||||
if (hook_bgn - word_bgn == 1)
|
||||
root_word = mgr.Tmp_bfr.Add_byte(src[word_bgn]).Add_mid(src, hook_bgn + 1, word_end).To_bry_and_clear();
|
||||
else if (word_end - hook_end == 1)
|
||||
root_word = mgr.Tmp_bfr.Add_mid(src, word_bgn, hook_bgn).Add_byte(src[hook_end]).To_bry_and_clear();
|
||||
// Tfds.Write(word_bgn, hook_bgn, hook_end, word_end);
|
||||
if (root_word != null) {
|
||||
mgr.Words__add__chk_dash(word_bgn, word_end); // add full; EX: "o'clock"
|
||||
mgr.Words__add_direct(root_word); // add root; EX: "oclock"
|
||||
mgr.Cur__bgn__reset();
|
||||
}
|
||||
return word_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
class Srch_sym_parser__dash implements Srch_sym_parser {
|
||||
public Srch_sym_parser__dash(String hook) {this.hooks_ary = Bry_.Ary(hook);}
|
||||
public int Tid() {return Srch_sym_parser_.Tid__dash;}
|
||||
public byte[][] Hooks_ary() {return hooks_ary;} private final byte[][] hooks_ary;
|
||||
public int Parse(Srch_text_parser mgr, byte[] src, int src_end, int hook_bgn, int hook_end) {
|
||||
int cur_bgn = mgr.Cur__bgn(); // get word_bgn
|
||||
if (cur_bgn == -1) { // no word_bgn; "-" is 1st char
|
||||
if (mgr.Cur__end__chk(hook_end)) { // next char is space
|
||||
mgr.Words__add_direct(hook_bgn, hook_end); // add dash; EX: "a - b" -> "a", "-", "b"
|
||||
}
|
||||
else { // next char is something else
|
||||
mgr.Cur__bgn__set(hook_bgn); // update word_bgn to dash
|
||||
mgr.Dash__bgn_(hook_end);
|
||||
}
|
||||
return hook_end;
|
||||
}
|
||||
else { // word_bgn exists
|
||||
int dash_bgn = mgr.Dash__bgn();
|
||||
if (dash_bgn == Srch_text_parser.None) { // 1st dash
|
||||
mgr.Words__add__chk_dash(cur_bgn, hook_bgn);// add word; EX: "a" in "a-b"
|
||||
} else { // 2nd or more; add stub; EX: "a-b-c"; 2nd "-" should add "b"
|
||||
if (hook_bgn > dash_bgn) // only add if len > 0; handles multiple dashes; EX: "---"
|
||||
mgr.Words__add_direct(dash_bgn, hook_bgn);
|
||||
}
|
||||
}
|
||||
mgr.Dash__bgn_(hook_end);
|
||||
return hook_end;
|
||||
}
|
||||
public void Add_pending_word(Srch_text_parser mgr, byte[] src, int word_end) {
|
||||
int dash_bgn = mgr.Dash__bgn();
|
||||
if (dash_bgn == Srch_text_parser.None) return;
|
||||
if (word_end - dash_bgn > 0) // only add if there is word to right of dash; EX: "a-"
|
||||
mgr.Words__add_direct(dash_bgn, word_end);
|
||||
mgr.Dash__bgn_(Srch_text_parser.None); // clear the dash
|
||||
}
|
||||
}
|
||||
@@ -1,173 +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.addons.apps.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.btries.*; import gplx.xowa.langs.cases.*;
|
||||
public class Srch_text_parser {
|
||||
private Btrie_slim_mgr parser_trie = Btrie_slim_mgr.cs(); public Btrie_slim_mgr word_end_trie = Btrie_slim_mgr.cs(); private Btrie_slim_mgr word_bgn_trie = Btrie_slim_mgr.cs();
|
||||
private Xol_case_mgr case_mgr;
|
||||
public final Bry_bfr Tmp_bfr = Bry_bfr.new_(32);
|
||||
private byte[] src; private int end;
|
||||
private Srch_sym_parser__split parser__ws; private Srch_sym_parser__dash parser__dash;
|
||||
public Srch_word_hash word_hash = new Srch_word_hash();
|
||||
public boolean lcase = true;
|
||||
public Srch_text_parser Init_for_ttl(Xol_case_mgr case_mgr) {
|
||||
this.case_mgr = case_mgr;
|
||||
parser_trie.Clear(); word_end_trie.Clear();
|
||||
parser__ws = new Srch_sym_parser__split(Bool_.Y, " ", "\t", "\n", "\r", "_");
|
||||
parser__dash = new Srch_sym_parser__dash("-");
|
||||
Parsers__reg(Parsers__make__word_end
|
||||
( "!", "?", ",", ":", ";", "\"", "~"
|
||||
//, "@", "&", "*", "`", "+" // should add for symmetry of word_bgn trie but strips "@Home" to "Home" only; also, several have many "*", "`", "+"
|
||||
));
|
||||
Parsers__reg(new Srch_sym_parser__split(Bool_.N, "/"));
|
||||
Parsers__reg(parser__ws, parser__dash
|
||||
, new Srch_sym_parser__paren_bgn(Byte_ascii.Paren_bgn, Byte_ascii.Paren_end)
|
||||
, new Srch_sym_parser__dot("."), new Srch_sym_parser__ellipsis(Byte_ascii.Dot, ".."), new Srch_sym_parser__apos("'")); // NOTE: [ ] { } do not exist in titles
|
||||
word_bgn_trie.Add_many_int(1
|
||||
// , "!", "?", ",", ":", ";" // low #; should add for symmetry of word_end trie;
|
||||
, "\"" // adding for symmetry of word_end trie;
|
||||
, "@", "&", "*", "`", "~", "+" // "@Home", "&c.", "&NSYNC", "Muhammad_ibn_`Ali_at-Tirmidhi"; "Phantom_~Requiem_for_the_Phantom~"; "+pool"
|
||||
);
|
||||
return this;
|
||||
}
|
||||
public Srch_text_parser Make_copy() {
|
||||
Srch_text_parser rv = new Srch_text_parser();
|
||||
rv.parser_trie = parser_trie; rv.word_end_trie = word_end_trie; rv.word_bgn_trie = word_bgn_trie;
|
||||
rv.parser__ws = parser__ws; rv.parser__dash = parser__dash;
|
||||
rv.word_hash = word_hash; rv.case_mgr = case_mgr;
|
||||
rv.lcase = lcase;
|
||||
return rv;
|
||||
}
|
||||
public byte[][] Parse_to_bry_ary(boolean lcase, byte[] src_orig) {
|
||||
word_hash.Clear();
|
||||
this.lcase = lcase;
|
||||
Parse(lcase, src_orig, 0, src_orig.length);
|
||||
int hash_len = word_hash.Len();
|
||||
byte[][] rv = new byte[hash_len][];
|
||||
for (int i = 0; i < hash_len; ++i) {
|
||||
Srch_word_itm itm = (Srch_word_itm)word_hash.Get_at(i);
|
||||
rv[i] = itm.Word;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public void Parse(Srch_text_parser_wkr wkr, byte[] src_orig) {
|
||||
word_hash.Clear();
|
||||
Parse(Bool_.Y, src_orig, 0, src_orig.length);
|
||||
int hash_len = word_hash.Len();
|
||||
for (int i = 0; i < hash_len; ++i) {
|
||||
Srch_word_itm itm = (Srch_word_itm)word_hash.Get_at(i);
|
||||
wkr.Parse_done(itm);
|
||||
}
|
||||
}
|
||||
public void Parse(boolean lcase, byte[] src_orig, int bgn, int end_orig) {
|
||||
this.src = lcase ? case_mgr.Case_build_lower(src_orig) : src_orig;
|
||||
this.end = end_orig + (src.length - src_orig.length);
|
||||
this.cur_bgn = dash_bgn = Srch_text_parser.None;
|
||||
int pos = bgn;
|
||||
while (true) {
|
||||
boolean pos_is_last = pos == end;
|
||||
if (pos_is_last) { // EOS and pending word; add it
|
||||
if (cur_bgn != -1)
|
||||
Words__add__chk_dash(cur_bgn, end);
|
||||
break;
|
||||
}
|
||||
byte b = src[pos];
|
||||
Object o = parser_trie.Match_bgn_w_byte(b, src, pos, end);
|
||||
if (o == null) { // unknown sequence; word-char
|
||||
if (cur_bgn == -1) cur_bgn = pos; // set 1st char for word
|
||||
++pos;
|
||||
}
|
||||
else {
|
||||
Srch_sym_parser parser = (Srch_sym_parser)o;
|
||||
pos = parser.Parse(this, src, end, pos, parser_trie.Match_pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
public int Cur__bgn() {return cur_bgn;} private int cur_bgn; public void Cur__bgn__reset() {this.cur_bgn = -1;}
|
||||
public void Cur__bgn__set(int v) {this.cur_bgn = v;} // called from dash parser
|
||||
public int Dash__bgn() {return dash_bgn;} private int dash_bgn; public void Dash__bgn_(int v) {this.dash_bgn = v;}
|
||||
public int Cur__end__find(int pos) {return parser__ws.Find_fwd(src, pos, end);}
|
||||
public boolean Cur__end__chk(int pos) {return parser__ws.Is_next(src, pos, end);}
|
||||
public int Cur__end__find__text_only(int pos) { // primarily for parens and finding word_end after ")"; EX: "(city), " vs "(a)b "
|
||||
while (pos < end) {
|
||||
byte b = src[pos];
|
||||
Object parser_obj = parser_trie.Match_bgn_w_byte(b, src, pos, end);
|
||||
if (parser_obj == null) // b is text; increment by 1 and continue searching
|
||||
++pos;
|
||||
else // b is some sort of symbol; end word here; EX: "a," should produce "a", not "a,"
|
||||
return pos;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
public void Words__add_if_pending_and_clear(int word_end) {
|
||||
if (cur_bgn == -1) return; // exit; no pending words
|
||||
this.Words__add__chk_dash(cur_bgn, word_end);
|
||||
cur_bgn = -1;
|
||||
}
|
||||
public void Words__add__chk_dash(int word_bgn, int word_end) {
|
||||
parser__dash.Add_pending_word(this, src, word_end);
|
||||
byte[] word = Bry_.Mid(src, word_bgn, word_end);
|
||||
Words__add_direct(word);
|
||||
}
|
||||
public void Words__add_direct(int bgn, int end) {Words__add_direct(Bry_.Mid(src, bgn, end));}
|
||||
public void Words__add_direct(byte[] bry) {
|
||||
word_hash.Add(bry);
|
||||
|
||||
// remove punctuation at bgn of word; EX: "@Home" -> "Home"
|
||||
boolean dirty = false;
|
||||
int pos = 0; int len = bry.length;
|
||||
while (pos < len) {
|
||||
byte b = bry[pos];
|
||||
if (word_bgn_trie.Match_bgn_w_byte(b, bry, pos, len) != null) { // b is symbol;
|
||||
dirty = true;
|
||||
pos = word_bgn_trie.Match_pos();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dirty && pos < len) {
|
||||
byte[] trunc = Bry_.Mid(bry, pos, len);
|
||||
// if (!word_hash.Has(trunc)) // don't add if it exists; EX: "'tis"
|
||||
word_hash.Add(trunc);
|
||||
}
|
||||
}
|
||||
|
||||
private void Parsers__reg(Srch_sym_parser... parsers_ary) {
|
||||
int parsers_len = parsers_ary.length;
|
||||
for (int i = 0; i < parsers_len; ++i) {
|
||||
Srch_sym_parser parser = parsers_ary[i];
|
||||
byte[][] hooks_ary = parser.Hooks_ary();
|
||||
int hooks_len = hooks_ary.length;
|
||||
for (int j = 0; j < hooks_len; ++j) {
|
||||
byte[] hook = hooks_ary[j];
|
||||
parser_trie.Add_obj(hook, parser);
|
||||
if (parser.Tid() == Srch_sym_parser_.Tid__terminal)
|
||||
word_end_trie.Add_obj(hook, parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static Srch_sym_parser[] Parsers__make__word_end(String... hooks) {
|
||||
int rv_len = hooks.length;
|
||||
Srch_sym_parser[] rv = new Srch_sym_parser[rv_len];
|
||||
for (int i = 0; i < rv_len; ++i)
|
||||
rv[i] = new Srch_sym_parser__terminal(Bry_.new_u8(hooks[i]));
|
||||
return rv;
|
||||
}
|
||||
public static final int None = -1;
|
||||
}
|
||||
@@ -1,147 +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.addons.apps.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import org.junit.*; import gplx.xowa.langs.cases.*;
|
||||
public class Srch_text_parser_tst {
|
||||
private final Srch_text_parser_fxt fxt = new Srch_text_parser_fxt();
|
||||
@Before public void init() {fxt.Init();}
|
||||
@Test public void Word__one() {fxt.Clear().Test__split("abcd" , "abcd");}
|
||||
@Test public void Word__many() {fxt.Clear().Test__split("abc d ef" , "abc", "d", "ef");}
|
||||
@Test public void Ws__many() {fxt.Clear().Test__split("a b" , "a", "b");}
|
||||
@Test public void Ws__bgn() {fxt.Clear().Test__split(" a" , "a");}
|
||||
@Test public void Ws__end() {fxt.Clear().Test__split("a " , "a");}
|
||||
@Test public void Under() {fxt.Clear().Test__split("a_b" , "a", "b");} // NOTE: same as space
|
||||
@Test public void Lowercase() {fxt.Clear().Test__split("A B C" , "a", "b", "c");}
|
||||
@Test public void Dupe() {fxt.Clear().Test__split("a a a" , fxt.Make_word("a", 3));}
|
||||
@Test public void Dupe__lowercase() {fxt.Clear().Test__split("a A" , fxt.Make_word("a", 2));}
|
||||
@Test public void Comma__end() {fxt.Clear().Test__split("a, b" , "a", "b");} // EX: "Henry VI, Part 3"; "Bergen County, New Jersey"
|
||||
@Test public void Comma__mid() {fxt.Clear().Test__split("a,b" , "a,b");} // EX: "20,000 Leagues Under the Sea"
|
||||
@Test public void Comma__bgn() {fxt.Clear().Test__split(",a b" , "a", "b");} // EX: skip bad usages; EX: "Little Harbour,Pictou ,Nova Scotia"; "The Hindu Succession Act ,1956"
|
||||
@Test public void Colon__end() {fxt.Clear().Test__split("a: b" , "a", "b");}
|
||||
@Test public void Colon__mid() {fxt.Clear().Test__split("a:b" , "a:b");} // EX: "3:10 to Yuma (2007 film)"; "6:02 AM EST"; "24:7 Theatre Festival"; "Library of Congress Classification:Class P -- Language and Literature"
|
||||
@Test public void Colon__bgn() {fxt.Clear().Test__split(":a b" , "a", "b");}
|
||||
@Test public void Semic__end() {fxt.Clear().Test__split("a; b" , "a", "b");}
|
||||
@Test public void Semic__mid() {fxt.Clear().Test__split("a;b" , "a;b");}
|
||||
@Test public void Semic__bgn() {fxt.Clear().Test__split(";a b" , "a", "b");}
|
||||
@Test public void Bang__end() {fxt.Clear().Test__split("a! b" , "a", "b");}
|
||||
@Test public void Bang__mid() {fxt.Clear().Test__split("a!b" , "a!b");}
|
||||
@Test public void Bang__bgn() {fxt.Clear().Test__split("!a b" , "a", "b");}
|
||||
@Test public void Question__end() {fxt.Clear().Test__split("a? b" , "a", "b");}
|
||||
@Test public void Question__mid() {fxt.Clear().Test__split("a?b" , "a?b");}
|
||||
@Test public void Question__bgn() {fxt.Clear().Test__split("?a b" , "a", "b");}
|
||||
@Test public void Question__sentence() {fxt.Clear().Test__split("a?" , "a");}
|
||||
@Test public void Multiple__1() {fxt.Clear().Test__split("a?!" , "a");}
|
||||
@Test public void Multiple__2() {fxt.Clear().Test__split("a!?" , "a");}
|
||||
@Test public void Dot__word() {fxt.Clear().Test__split("a.org" , "a.org");} // EX: "en.wikipedia.org"; "Earth.png"; "IEEE_802.15"
|
||||
@Test public void Dot__abrv() {fxt.Clear().Test__split("a vs. b" , "a", "vs.", "vs", "b");} // EX: "vs.", "no.", "dr.", "st.", "inc."
|
||||
@Test public void Dot__initials() {fxt.Clear().Test__split("a. b. cde" , "a.", "a", "b.", "b", "cde");} // EX: "H. G. Wells"
|
||||
@Test public void Dot__acronym() {fxt.Clear().Test__split("abc D.E.F. ghi" , "abc", "d.e.f.", "def", "ghi");} // EX: "History of U.S.A. Science", "G.I. Bill", "Washington, D.C."; "Barcelona F.C."; "The Office (U.S.)"; "Agents of S.H.I.E.L.D."; "Gunfight at the O.K. Corral"; "H.M.S. Pinafore"; "R.E.M. discography"
|
||||
@Test public void Dot__bgn() {fxt.Clear().Test__split("a .bcd e" , "a", ".bcd", "bcd", "e");} // EX: "Colt .45", "List of organizations with .int domain names"
|
||||
@Test public void Dot__bgn__end() {fxt.Clear().Test__split("a .b. c" , "a", ".b.", "c");}
|
||||
@Test public void Dot__ellipsis_like() {fxt.Clear().Test__split("a . . . b" , "a", "b");} // EX: "Did you know . . ."
|
||||
@Test public void Ellipsis__len_3() {fxt.Clear().Test__split("a... bc d" , "a", "...", "bc", "d");} // EX: "Nights into Dreams..."
|
||||
@Test public void Ellipsis__len_3__bgn() {fxt.Clear().Test__split("a ...b" , "a", "...", "b"); ;} // NOTE: make sure "dot_bgn" code doesn't break this
|
||||
@Test public void Ellipsis__len_2() {fxt.Clear().Test__split("a.. b" , "a", "..", "b");} // EX: "3.. 6.. 9 Seconds of Light"
|
||||
@Test public void Ellipsis__bgn() {fxt.Clear().Test__split("...a" , "...", "a");}
|
||||
@Test public void Ellipsis__end() {fxt.Clear().Test__split("a..." , "a", "...");}
|
||||
@Test public void Ellipsis__no_ws() {fxt.Clear().Test__split("a...b" , "a", "...", "b");}
|
||||
@Test public void Ellipsis__term() {fxt.Clear().Test__split("a...?!" , "a", "...");} // EX: "Wetten, dass..?"
|
||||
@Test public void Apos__merge__end__eos() {fxt.Clear().Test__split("ab's" , "ab's", "abs");} // EX: "A Midsummer Night's Dream"; "Director's cut"
|
||||
@Test public void Apos__merge__end__word() {fxt.Clear().Test__split("ab's c" , "ab's", "abs", "c");} // EX: "Director's cut"; "Cap'n Crunch";
|
||||
@Test public void Apos__merge__bgn() {fxt.Clear().Test__split("a o'bc" , "a", "o'bc", "obc");} // EX: "Twelve O'Clock High"; "Shaqille O'Neal"; "Banca d'Italia"
|
||||
@Test public void Apos__merge__mid() {fxt.Clear().Test__split("i'm" , "i'm", "im");}
|
||||
@Test public void Apos__bgn__long() {fxt.Clear().Test__split("a 'tis b" , "a", "'tis", "tis", "b");} // EX: "My Country, 'Tis of Thee"; "Omaha hold 'em"; "Slash'EM"; "Expo '92"
|
||||
@Test public void Apos__end__eos() {fxt.Clear().Test__split("a'" , "a");}
|
||||
@Test public void Apos__end__short() {fxt.Clear().Test__split("a' b" , "a", "b");} // EX: "Will-o'-the-wisp"; "Portuguese man o' war";
|
||||
@Test public void Apos__end__long() {fxt.Clear().Test__split("ab' c" , "ab", "c");} // EX: "Dunkin' Donuts"; "'Allo 'Allo!"; "Catherine de' Medici"
|
||||
@Test public void Apos__both__n() {fxt.Clear().Test__split("a 'n' b" , "a", "'n'", "n", "b");} // EX: "Rock 'n' Roll"; "Town 'n' Country, Florida"; "Hill 'n Dale, Florida"; "Chip 'n Dale Rescue Rangers"
|
||||
@Test public void Apos__multiple() {fxt.Clear().Test__split("ab''cd" , "ab''cd");}
|
||||
@Test public void Apos__lone() {fxt.Clear().Test__split("' a" , "'", "a");} // EX: "' (disambiguation)"
|
||||
@Test public void Dash__one() {fxt.Clear().Test__split("a-b" , "a", "b", "a-b");} // EX: "The Amazing Spider-Man"; "On-super percentage"; "Basic Role-Playing"; "Context-sensitive"; "Cross-country skiing"; "Double-barreled shotgun"; "Dot-com bubble"; "Many-worlds interpretation"; "Faster-than-light"; "Gram-positive bacteria"; "Half-life", "Jean-Paul Sartre"; "Austria-Hungary"
|
||||
@Test public void Dash__many() {fxt.Clear().Test__split("a-b-c" , "a", "b", "c", "a-b-c");}
|
||||
@Test public void Dash__ws() {fxt.Clear().Test__split("a - b" , "a", "-", "b");}
|
||||
@Test public void Dash__eos() {fxt.Clear().Test__split("a-" , "a", "a-");}
|
||||
@Test public void Dash__bos() {fxt.Clear().Test__split("-a" , "a", "-a");}
|
||||
@Test public void Dash__mult__2() {fxt.Clear().Test__split("--" , "--");}
|
||||
@Test public void Dash__mult__3() {fxt.Clear().Test__split("---" , "---");}
|
||||
@Test public void Dash__mult__2__words() {fxt.Clear().Test__split("a--b" , "a", "b", "a--b");}
|
||||
@Test public void Dash__w_comma() {fxt.Clear().Test__split("a-, b" , "a", "a-", "b");}
|
||||
@Test public void Slash__one() {fxt.Clear().Test__split("a/b" , "a", "b");} // EX: "Good cop/bad cop"; "Snooker world rankings 2004/2005"; "Debian GNU/Hurd"; "HIV/AIDS in the United States"; "List of minor planets/1<>100"
|
||||
@Test public void Slash__many() {fxt.Clear().Test__split("a/b/c" , "a", "b", "c");} // EX: "Age/sex/location";
|
||||
@Test public void Slash__ws() {fxt.Clear().Test__split("a / b" , "a", "b");}
|
||||
@Test public void Dash__slash() {fxt.Clear().Test__split("a-b/c-d-e/f-g" , "a", "b", "a-b", "c", "d", "e", "c-d-e", "f", "g", "f-g");}
|
||||
@Test public void Paren__both__one() {fxt.Clear().Test__split("a (b) c" , "a", "b", "c");} // EX: "A (letter)"
|
||||
@Test public void Paren__both__many() {fxt.Clear().Test__split("a (b c) d" , "a", "b", "c", "d");} // EX: "A (2016 film)"
|
||||
@Test public void Paren__bgn__multiple() {fxt.Clear().Test__split("a (((b)))" , "a", "b");}
|
||||
@Test public void Paren__unmatched() {fxt.Clear().Test__split("a(b" , "a(b");}
|
||||
@Test public void Paren__unmatched__bgn() {fxt.Clear().Test__split("a (b" , "a", "b");}
|
||||
@Test public void Paren__mid() {fxt.Clear().Test__split("a(b)c" , "a(b)c");} // EX: "Chloro(pyridine)cobaloxime"; "Exi(s)t"
|
||||
@Test public void Paren__end() {fxt.Clear().Test__split("a(b)" , "a(b)", "a");} // EX: "Come What(ever) May"; "501(c) organization"; "Reindeer(s) Are Better Than People"; "(Miss)understood"; "Chromium(III) picolinate"
|
||||
@Test public void Paren__bgn() {fxt.Clear().Test__split("(a)b" , "(a)b", "b");} // EX: "International Student Congress of (bio)Medical Sciences"
|
||||
@Test public void Paren__end__dash() {fxt.Clear().Test__split("a(b-c) d" , "a(b-c)", "a", "d");} // EX: "Bis(2-ethylhexyl) phthalate"
|
||||
@Test public void Paren__end__comma() {fxt.Clear().Test__split("a(b,c) d" , "a(b,c)", "a", "d");} // EX: "Iron(II,III) oxide"
|
||||
@Test public void Paren__comma() {fxt.Clear().Test__split("a (b), c" , "a", "b", "c");} // EX: "Corning (city), New York"
|
||||
@Test public void Paren__multiple() {fxt.Clear().Test__split("(a) (b)" , "a", "b");}
|
||||
@Test public void Quote__both() {fxt.Clear().Test__split("a \"b\" c" , "a", "b", "c");}
|
||||
@Test public void Word_bgn__at() {fxt.Clear().Test__split("@a" , "@a", "a");}
|
||||
@Test public void Word_bgn__tilde() {fxt.Clear().Test__split("~a~" , "a");} // EX: "Phantom ~Requiem for the Phantom~"
|
||||
}
|
||||
class Srch_text_parser_fxt {
|
||||
private final Srch_text_parser word_parser = new Srch_text_parser();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_(32);
|
||||
private Xol_case_mgr case_mgr;
|
||||
public void Init() {
|
||||
case_mgr = Xol_case_mgr_.A7();
|
||||
word_parser.Init_for_ttl(case_mgr);
|
||||
}
|
||||
public Srch_text_parser_fxt Clear() {
|
||||
word_parser.word_hash.Clear();
|
||||
return this;
|
||||
}
|
||||
public Srch_word_itm Make_word(String raw, int count) {return new Srch_word_itm(Bry_.new_u8(raw)).Count_(count);}
|
||||
public void Test__split(String src, String... expd_words) {
|
||||
int len = expd_words.length;
|
||||
Srch_word_itm[] ary = new Srch_word_itm[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
ary[i] = Make_word(expd_words[i], 1);
|
||||
}
|
||||
Test__split(src, ary);
|
||||
}
|
||||
public void Test__split(String src, Srch_word_itm... expd_words) {
|
||||
byte[] src_bry = Bry_.new_u8(src);
|
||||
word_parser.Parse(Bool_.Y, src_bry, 0, src_bry.length);
|
||||
Tfds.Eq_str_lines(To_str(expd_words), To_str(word_parser.word_hash));
|
||||
}
|
||||
private String To_str(Srch_word_itm[] word_ary) {
|
||||
int len = word_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (i != 0) tmp_bfr.Add_byte_nl();
|
||||
Srch_word_itm word = word_ary[i];
|
||||
tmp_bfr.Add(word.Word).Add_byte_pipe();
|
||||
tmp_bfr.Add_int_variable(word.Count());
|
||||
}
|
||||
return tmp_bfr.To_str_and_clear();
|
||||
}
|
||||
private String To_str(Srch_word_hash word_mgr) {
|
||||
int len = word_mgr.Len();
|
||||
Srch_word_itm[] ary = new Srch_word_itm[len];
|
||||
for (int i = 0; i < len; ++i)
|
||||
ary[i] = word_mgr.Get_at(i);
|
||||
return To_str(ary);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +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.addons.apps.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
public interface Srch_text_parser_wkr {
|
||||
void Parse_done(Srch_word_itm word);
|
||||
}
|
||||
class Srch_text_parser_wkr__noop implements Srch_text_parser_wkr {
|
||||
public void Parse_done(Srch_word_itm word) {}
|
||||
public static final Srch_text_parser_wkr__noop Instance = new Srch_text_parser_wkr__noop(); Srch_text_parser_wkr__noop() {}
|
||||
}
|
||||
@@ -1,33 +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.addons.apps.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
public class Srch_word_hash {
|
||||
private final Ordered_hash hash = Ordered_hash_.New_bry();
|
||||
public void Clear() {hash.Clear();}
|
||||
public int Len() {return hash.Count();}
|
||||
public boolean Has(byte[] word) {return hash.Has(word);}
|
||||
public Srch_word_itm Get_at(int i) {return (Srch_word_itm)hash.Get_at(i);}
|
||||
public void Add(byte[] word) {
|
||||
Srch_word_itm itm = (Srch_word_itm)hash.Get_by(word);
|
||||
if (itm == null) {
|
||||
itm = new Srch_word_itm(word);
|
||||
hash.Add(word, itm);
|
||||
}
|
||||
itm.Count_add_1_();
|
||||
}
|
||||
}
|
||||
@@ -1,28 +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.addons.apps.searchs.parsers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
public class Srch_word_itm {
|
||||
public Srch_word_itm(byte[] word) {
|
||||
this.Word = word;
|
||||
this.count = 0;
|
||||
}
|
||||
public final byte[] Word;
|
||||
public int Count() {return count;} private int count;
|
||||
public void Count_add_1_() {++count;}
|
||||
@gplx.Internal protected Srch_word_itm Count_(int v) {this.count = v; return this;}
|
||||
}
|
||||
@@ -1,99 +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.addons.apps.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.primitives.*;
|
||||
import gplx.xowa.wikis.nss.*;
|
||||
public class Srch_ns_mgr {
|
||||
private final Ordered_hash ns_hash = Ordered_hash_.New(); private final Int_obj_ref tmp_ns_id = Int_obj_ref.neg1_();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.reset_(32);
|
||||
private boolean ns_all, ns_main;
|
||||
public void Clear() {
|
||||
ns_hash.Clear();
|
||||
ns_all = ns_main = false;
|
||||
}
|
||||
public boolean Ns_main_only() {return ns_main;}
|
||||
public boolean Has(int ns_id) {
|
||||
return ns_all // ns_all always returns true
|
||||
|| ns_main && ns_id == Xow_ns_.Tid__main // ns_main returns true if main_ns
|
||||
|| ns_hash.Has(tmp_ns_id.Val_(ns_id)); // ns_hash returns true if has ns_id
|
||||
}
|
||||
public void Add_all() {ns_all = true;}
|
||||
public Srch_ns_mgr Add_main_if_empty() {if (ns_hash.Count() == 0) ns_main = true; return this;}
|
||||
public void Add_by_id(int ns_id) {
|
||||
if (ns_hash.Has(tmp_ns_id.Val_(ns_id))) ns_hash.Del(tmp_ns_id);
|
||||
ns_hash.Add_as_key_and_val(Int_obj_ref.new_(ns_id));
|
||||
}
|
||||
public void Add_by_name(byte[] ns_name) {
|
||||
int id = Xow_ns_canonical_.To_id(ns_name);
|
||||
if (id != Xow_ns_.Tid__null)
|
||||
Add_by_id(id);
|
||||
}
|
||||
public void Add_by_parse(byte[] key, byte[] val) {
|
||||
int ns_enabled = Bry_.To_int_or_neg1(val);
|
||||
if (ns_enabled == 1) { // make sure set to 1; EX: ignore &ns0=0
|
||||
int key_len = key.length;
|
||||
if (key_len == 3 && key[2] == Srch_search_addon.Wildcard__star) // key=ns* sets ns_all to true
|
||||
ns_all = true;
|
||||
else {
|
||||
int ns_id = Bry_.To_int_or(key, 2, key_len, Int_.Min_value);
|
||||
if (ns_id != Int_.Min_value) { // ignore invalid ints; EX: &nsabc=1;
|
||||
Add_by_id(ns_id);
|
||||
ns_main = ns_all = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public byte[] To_hash_key() {
|
||||
if (ns_all) return Hash_key_all;
|
||||
else if (ns_main) return Hash_key_main;
|
||||
else {
|
||||
int ns_hash_len = ns_hash.Count();
|
||||
for (int i = 0; i < ns_hash_len; i++) {
|
||||
if (i != 0) tmp_bfr.Add_byte_semic();
|
||||
Int_obj_ref ns_id_ref = (Int_obj_ref)ns_hash.Get_at(i);
|
||||
tmp_bfr.Add_int_variable(ns_id_ref.Val());
|
||||
}
|
||||
return tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
public void Add_by_int_ids(int[] ns_ids) {
|
||||
this.Clear();
|
||||
if (ns_ids.length == 0) {
|
||||
this.Add_all();
|
||||
} else if (ns_ids.length == 1 && ns_ids[0] == Xow_ns_.Tid__main) {
|
||||
this.Add_main_if_empty();
|
||||
} else {
|
||||
for (int ns_id : ns_ids)
|
||||
this.Add_by_id(ns_id);
|
||||
}
|
||||
}
|
||||
public int[] To_int_ary() {
|
||||
if (ns_all) return Int_.Ary_empty;
|
||||
else if (ns_main) return Int_.Ary(Xow_ns_.Tid__main);
|
||||
else {
|
||||
int len = ns_hash.Count();
|
||||
int[] rv = new int[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Int_obj_ref ns_id_ref = (Int_obj_ref)ns_hash.Get_at(i);
|
||||
rv[i] = ns_id_ref.Val();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
private static final byte[] Hash_key_all = new byte[] {Srch_search_addon.Wildcard__star}, Hash_key_main = new byte[] {Byte_ascii.Num_0};
|
||||
}
|
||||
@@ -1,55 +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.addons.apps.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
public class Srch_search_cmd implements Cancelable, GfoInvkAble {
|
||||
private final Srch_search_mgr search_mgr;
|
||||
public final Srch_search_qry qry;
|
||||
public final Srch_crt_mgr crt_mgr;
|
||||
private final Srch_rslt_cbk rslt_cbk;
|
||||
private final Srch_rslt_list rslts_list;
|
||||
public Srch_search_cmd(Srch_search_mgr search_mgr, Srch_search_qry qry, Srch_crt_mgr crt_mgr, Srch_rslt_cbk rslt_cbk, Srch_rslt_list rslts_list) {
|
||||
this.search_mgr = search_mgr; this.qry = qry; this.crt_mgr = crt_mgr; this.rslt_cbk = rslt_cbk; this.rslts_list = rslts_list;
|
||||
}
|
||||
public boolean Canceled() {return canceled;} private boolean canceled;
|
||||
public void Cancel() {
|
||||
canceled = true;
|
||||
rslt_cbk.On_cancel();
|
||||
}
|
||||
private void Search() {
|
||||
try {
|
||||
search_mgr.Search_async(this, qry, crt_mgr, rslt_cbk, rslts_list); // NOTE: must handle any errors in async mode
|
||||
}
|
||||
catch(Exception e) {
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "error during search: err=~{0}", Err_.Message_gplx_log(e));
|
||||
}
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk__search)) Search();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final String Invk__search = "search";
|
||||
public static Srch_search_cmd Noop() {
|
||||
if (noop == null) {
|
||||
noop = new Srch_search_cmd(null, null, null, Srch_rslt_cbk_.Noop, null);
|
||||
}
|
||||
return noop;
|
||||
} private static Srch_search_cmd noop;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.langs.cases.*;
|
||||
import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; import gplx.xowa.addons.apps.searchs.dbs.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.crts.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*; import gplx.dbs.percentiles.*; import gplx.xowa.addons.apps.searchs.searchers.wkrs.*;
|
||||
import gplx.xowa.addons.apps.searchs.parsers.*;
|
||||
public class Srch_search_ctx {
|
||||
public Srch_search_ctx(Cancelable cxl, Xow_wiki wiki, Srch_search_addon addon
|
||||
, Srch_rslt_list cache__page, Hash_adp_bry cache__word_counts
|
||||
, Srch_search_qry qry, Srch_crt_scanner_syms scanner_syms, Srch_crt_mgr crt_mgr, Srch_rslt_list rslts_list) {
|
||||
this.Cxl = cxl;
|
||||
this.Wiki = wiki;
|
||||
this.Wiki_domain = wiki.Domain_bry();
|
||||
this.Case_mgr = wiki.Case_mgr();
|
||||
this.Addon = addon;
|
||||
this.Cache__page = cache__page;
|
||||
this.Cache__word_counts = cache__word_counts;
|
||||
this.Qry = qry;
|
||||
this.Scanner_syms = scanner_syms;
|
||||
this.Crt_mgr = crt_mgr;
|
||||
this.Crt_mgr__root = crt_mgr.Root;
|
||||
this.Rslts_list = rslts_list;
|
||||
this.Db__core = wiki.Data__core_mgr().Db__core();
|
||||
this.Tbl__page = Db__core.Tbl__page();
|
||||
this.Tbl__word = addon.Db_mgr().Tbl__word();
|
||||
this.Tbl__link__ary = addon.Db_mgr().Tbl__link__ary();
|
||||
long page_count = wiki.Stats().Num_pages();
|
||||
this.Score_rng.Init(page_count, addon.Db_mgr().Cfg().Link_score_max());
|
||||
int rslts_needed = qry.Slab_end - rslts_list.Len();
|
||||
if (rslts_needed < 0) rslts_needed = 0;
|
||||
this.Rslts_needed = rslts_needed;
|
||||
this.Highlight_mgr = new Srch_highlight_mgr(this.Case_mgr).Search_(qry.Phrase.Orig);
|
||||
}
|
||||
public final Cancelable Cxl;
|
||||
public final Xow_wiki Wiki;
|
||||
public final byte[] Wiki_domain;
|
||||
public final Srch_search_addon Addon;
|
||||
public final Xol_case_mgr Case_mgr;
|
||||
public final Srch_rslt_list Cache__page;
|
||||
public final Hash_adp_bry Cache__word_counts;
|
||||
public final Xowd_db_file Db__core;
|
||||
public final Xowd_page_tbl Tbl__page;
|
||||
public final Srch_word_tbl Tbl__word;
|
||||
public final Srch_link_tbl[] Tbl__link__ary;
|
||||
public final Srch_search_qry Qry;
|
||||
public final Srch_crt_scanner_syms Scanner_syms;
|
||||
public final Srch_rslt_list Rslts_list;
|
||||
public final int Rslts_needed;
|
||||
public final Percentile_rng Score_rng = new Percentile_rng();
|
||||
public final Srch_crt_mgr Crt_mgr;
|
||||
public final Srch_crt_itm Crt_mgr__root;
|
||||
public final Srch_highlight_mgr Highlight_mgr;
|
||||
}
|
||||
@@ -1,85 +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.addons.apps.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.rslts.*; import gplx.xowa.addons.apps.searchs.searchers.wkrs.*; import gplx.xowa.addons.apps.searchs.parsers.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.crts.visitors.*;
|
||||
public class Srch_search_mgr {
|
||||
private final Srch_search_addon addon;
|
||||
private final Xow_wiki wiki;
|
||||
private final Srch_rslt_list cache__page = new Srch_rslt_list();
|
||||
private final Hash_adp_bry cache__word_counts = Hash_adp_bry.cs();
|
||||
private final Srch_rslt_cache cache__rslts = new Srch_rslt_cache();
|
||||
private final Srch_page_tbl_wkr page_tbl_searcher = new Srch_page_tbl_wkr();
|
||||
private final Srch_crt_parser crt_parser;
|
||||
private final Srch_search_cmd[] cur_cmds;
|
||||
private final Object mutex = new Object();
|
||||
private int search_count;
|
||||
public Srch_search_mgr(Srch_search_addon addon, Xow_wiki wiki, Srch_text_parser parser) {
|
||||
this.addon = addon; this.wiki = wiki;
|
||||
crt_parser = new Srch_crt_parser(Scanner_syms);
|
||||
|
||||
// init cur_cmds with Noop cmd to make cancel logic below easier
|
||||
int len = Srch_search_qry.Tid_len;
|
||||
this.cur_cmds = new Srch_search_cmd[Srch_search_qry.Tid_len];
|
||||
for (int i = 0; i < len; ++i)
|
||||
cur_cmds[i] = Srch_search_cmd.Noop();
|
||||
}
|
||||
public void Clear_rslts_cache() {cache__rslts.Clear();}
|
||||
public void Search_cancel() {
|
||||
cur_cmds[Srch_search_qry.Tid__suggest_box].Cancel();
|
||||
}
|
||||
public void Search(Srch_search_qry qry, Srch_rslt_cbk cbk) {
|
||||
if (qry.Phrase.Orig.length == 0) return;
|
||||
|
||||
// handle obsolete search dbs;
|
||||
if (addon.Db_mgr().Cfg().Version_id__needs_upgrade()) {
|
||||
addon.Db_mgr().Upgrade_mgr.Upgrade();
|
||||
return;
|
||||
}
|
||||
|
||||
// cancel existing cmd
|
||||
Srch_search_cmd cur_cmd = cur_cmds[qry.Tid];
|
||||
cur_cmd.Cancel();
|
||||
|
||||
// create new one; run it;
|
||||
Srch_crt_mgr crt_mgr = crt_parser.Parse_or_invalid(qry.Phrase.Compiled, qry.Phrase.Wildcard);
|
||||
if (crt_mgr == Srch_crt_mgr.Invalid) return; // handle "\\" which is invalid or other fatal errors
|
||||
Srch_rslt_list rslts_list = cache__rslts.Get_or_new(crt_mgr.Key);
|
||||
cur_cmd = new Srch_search_cmd(this, qry, crt_mgr, cbk, rslts_list);
|
||||
cur_cmds[qry.Tid] = cur_cmd;
|
||||
gplx.core.threads.Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_suggest, cur_cmd, Srch_search_cmd.Invk__search).Start();
|
||||
}
|
||||
public void Search_async(Cancelable cxl, Srch_search_qry qry, Srch_crt_mgr crt_mgr, Srch_rslt_cbk rslt_cbk, Srch_rslt_list rslts_list) {
|
||||
synchronized (mutex) { // force only one search at a time; do not (a) place around Thread_sleep; (b) reuse for any other locks
|
||||
if (++search_count > 64) this.Clear(); // lazy way of clearing memory
|
||||
Srch_search_ctx ctx = new Srch_search_ctx(cxl, wiki, addon, cache__page, cache__word_counts, qry, Scanner_syms, crt_mgr, rslts_list);
|
||||
ctx.Score_rng.Select_init(ctx.Rslts_needed, rslts_list.Score_bgn, rslts_list.Score_len, Srch_link_wkr.Percentile_rng__calc_adj(crt_mgr.Words_nth__len()));
|
||||
page_tbl_searcher.Search(ctx, rslt_cbk);
|
||||
if (cxl.Canceled()) return;
|
||||
Srch_link_wkr link_wkr = new Srch_link_wkr();
|
||||
link_wkr.Search(rslts_list, rslt_cbk, ctx);
|
||||
}
|
||||
}
|
||||
private void Clear() {
|
||||
search_count = 0;
|
||||
cache__page.Clear();
|
||||
cache__word_counts.Clear();
|
||||
cache__rslts.Clear();
|
||||
}
|
||||
public static final Srch_crt_scanner_syms Scanner_syms = Srch_crt_scanner_syms.Dflt;
|
||||
}
|
||||
@@ -1,133 +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.addons.apps.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.btries.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
public class Srch_search_phrase {
|
||||
public Srch_search_phrase(boolean wildcard, byte[] orig, byte[] compiled) {
|
||||
this.Orig = orig;
|
||||
this.Compiled = compiled;
|
||||
this.Wildcard = wildcard;
|
||||
}
|
||||
public final boolean Wildcard;
|
||||
public final byte[] Orig; // EX: "Earth"
|
||||
public final byte[] Compiled; // EX: "earth*"
|
||||
|
||||
public static Srch_search_phrase New(gplx.xowa.langs.cases.Xol_case_mgr case_mgr, byte[] orig, boolean wildcard) {
|
||||
int orig_len = orig.length;
|
||||
if ( orig_len > 0 // if "*" at end, remove and change to wildcard; needed for Special:Search which will send in "earth*" but "earth" needed for highlighting
|
||||
&& orig[orig_len - 1] == Srch_crt_scanner_syms.Dflt.Wild()) {
|
||||
orig = Bry_.Mid(orig, 0, orig_len - 1);
|
||||
wildcard = true;
|
||||
}
|
||||
byte[] lcase = case_mgr.Case_build_lower(orig);
|
||||
lcase = Auto_wildcard(lcase, Srch_crt_scanner_syms.Dflt);
|
||||
return new Srch_search_phrase(wildcard, orig, lcase);
|
||||
}
|
||||
public static byte[] Auto_wildcard(byte[] raw, Srch_crt_scanner_syms syms) {
|
||||
Btrie_slim_mgr trie = syms.Trie();
|
||||
int raw_len = raw.length;
|
||||
int insert_pos = -1;
|
||||
int fail_pos = -1;
|
||||
for (int i = raw_len - 1; i > -1; --i) {
|
||||
byte b = raw[i];
|
||||
byte tid = trie.Match_byte_or(b, raw, i, i + 1, Byte_.Max_value_127);
|
||||
if (tid == Byte_.Max_value_127) { // unknown sym
|
||||
if (b == syms.Wild()) { // wildcard is not tokenized
|
||||
fail_pos = i;
|
||||
break;
|
||||
}
|
||||
else { // alphanum-char
|
||||
insert_pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (tid) {
|
||||
case Srch_crt_tkn.Tid__quote:
|
||||
case Srch_crt_tkn.Tid__space:
|
||||
case Srch_crt_tkn.Tid__not:
|
||||
case Srch_crt_tkn.Tid__and:
|
||||
case Srch_crt_tkn.Tid__or:
|
||||
case Srch_crt_tkn.Tid__paren_bgn:
|
||||
fail_pos = i; // these symbols will not auto-wildcard, unless they are escaped
|
||||
i = -1;
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__escape:
|
||||
if (i > 0) {
|
||||
int prv_pos = i -1;
|
||||
if (raw[prv_pos] == syms.Escape()) { // an escaped escape can be wildcarded; EX: "\\" -> "\\*"
|
||||
insert_pos = i;
|
||||
i = -1;
|
||||
}
|
||||
else
|
||||
fail_pos = i;
|
||||
}
|
||||
else
|
||||
fail_pos = i;
|
||||
i = -1;
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__paren_end:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if preceded by escape
|
||||
if (insert_pos == -1) {
|
||||
if ( fail_pos > 0
|
||||
&& raw[fail_pos - 1] == syms.Escape()) {
|
||||
insert_pos = fail_pos;
|
||||
}
|
||||
else
|
||||
return raw;
|
||||
}
|
||||
|
||||
// check if word already has wildcard; EX: "a*b" x> "a*b*"
|
||||
for (int i = insert_pos - 1; i > -1; --i) {
|
||||
byte b = raw[i];
|
||||
if (b == syms.Wild()) {
|
||||
int prv_pos = i - 1;
|
||||
if (prv_pos > -1) {
|
||||
if (raw[prv_pos] == syms.Escape()) { // ignore escaped wildcard
|
||||
i = prv_pos;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return raw; // existing wildcard cancels auto-wildcard
|
||||
}
|
||||
else if (b == syms.Space()) { // stop looking when word ends
|
||||
break;
|
||||
}
|
||||
else {} // alphanum; keep going
|
||||
}
|
||||
|
||||
// add wildcard
|
||||
if (insert_pos == raw_len - 1) return Bry_.Add(raw, syms.Wild());
|
||||
else {
|
||||
byte[] rv = new byte[raw_len + 1];
|
||||
int wildcard_pos = insert_pos + 1;
|
||||
for (int i = 0; i < wildcard_pos; ++i)
|
||||
rv[i] = raw[i];
|
||||
rv[wildcard_pos] = syms.Wild();
|
||||
for (int i = wildcard_pos; i < raw_len; ++i)
|
||||
rv[i + 1] = raw[i];
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +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.addons.apps.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import org.junit.*; import gplx.xowa.addons.apps.searchs.parsers.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
public class Srch_search_phrase_tst {
|
||||
private final Srch_search_phrase_fxt fxt = new Srch_search_phrase_fxt();
|
||||
@Test public void Word() {fxt.Test__auto_wildcard("a" , "a*");}
|
||||
@Test public void Paren_end() {fxt.Test__auto_wildcard("(a)" , "(a*)");}
|
||||
@Test public void Quoted() {fxt.Test__auto_wildcard("\"a\"" , "\"a\"");}
|
||||
@Test public void Space() {fxt.Test__auto_wildcard(" " , " ");}
|
||||
@Test public void Not() {fxt.Test__auto_wildcard("-" , "-");}
|
||||
@Test public void And() {fxt.Test__auto_wildcard("+" , "+");}
|
||||
@Test public void Or() {fxt.Test__auto_wildcard("," , ",");}
|
||||
@Test public void Paren_bgn() {fxt.Test__auto_wildcard("(" , "(");}
|
||||
@Test public void Star() {fxt.Test__auto_wildcard("*" , "*");}
|
||||
@Test public void Wildcard__exists__y() {fxt.Test__auto_wildcard("a*b" , "a*b");}
|
||||
@Test public void Wildcard__exists__escaped() {fxt.Test__auto_wildcard("a\\*b" , "a\\*b*");}
|
||||
@Test public void Wildcard__exists__n() {fxt.Test__auto_wildcard("a* bc" , "a* bc*");}
|
||||
@Test public void Escape() {fxt.Test__auto_wildcard("\\*" , "\\**");}
|
||||
@Test public void Escape__incomplete() {fxt.Test__auto_wildcard("a\\" , "a\\");}
|
||||
@Test public void Escape__escaped() {fxt.Test__auto_wildcard("a\\\\" , "a\\\\*");}
|
||||
}
|
||||
class Srch_search_phrase_fxt {
|
||||
private final Srch_crt_scanner_syms syms = Srch_crt_scanner_syms.Dflt;
|
||||
public Srch_search_phrase_fxt() {}
|
||||
public void Test__auto_wildcard(String src_str, String expd) {
|
||||
byte[] src_raw = Bry_.new_u8(src_str);
|
||||
byte[] actl = Srch_search_phrase.Auto_wildcard(src_raw, syms);
|
||||
Tfds.Eq(expd, String_.new_u8(actl));
|
||||
}
|
||||
}
|
||||
@@ -1,50 +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.addons.apps.searchs.searchers; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.wikis.domains.*;
|
||||
public class Srch_search_qry {
|
||||
public Srch_search_qry(byte tid, Srch_ns_mgr ns_mgr, Srch_search_phrase phrase, int slab_bgn, int slab_end) {
|
||||
this.Tid = tid;
|
||||
this.Ns_mgr = ns_mgr;
|
||||
this.Phrase = phrase;
|
||||
this.Slab_bgn = slab_bgn;
|
||||
this.Slab_end = slab_end;
|
||||
}
|
||||
public final byte Tid;
|
||||
public final Srch_ns_mgr Ns_mgr;
|
||||
public final Srch_search_phrase Phrase;
|
||||
public final int Slab_bgn; // EX: 0
|
||||
public final int Slab_end; // EX: 20
|
||||
|
||||
public static final byte Tid_len = 4, Tid__url_bar = 0, Tid__suggest_box = 1, Tid__search_page = 2, Tid__android = 3;
|
||||
public static Srch_search_qry New__url_bar(Xow_wiki wiki, gplx.xowa.apps.apis.xowa.addons.searchs.Xoapi_url_bar cfg, byte[] search_orig) {
|
||||
return new Srch_search_qry(Tid__url_bar, cfg.Ns_mgr(), Srch_search_phrase.New(wiki.Case_mgr(), search_orig, cfg.Auto_wildcard()), 0, cfg.Max_results());
|
||||
}
|
||||
public static Srch_search_qry New__suggest_box(Xow_wiki wiki, Srch_search_cfg cfg, byte[] search_orig) {
|
||||
return new Srch_search_qry(Tid__suggest_box, cfg.Ns_mgr(), Srch_search_phrase.New(wiki.Case_mgr(), search_orig, Bool_.Y), 0, cfg.Rslts_max());
|
||||
}
|
||||
public static Srch_search_qry New__search_page(Xow_domain_itm[] domains, Xow_wiki wiki, Srch_search_cfg cfg, boolean simple_search, byte[] search_orig, int slab_idx, int slab_len) {
|
||||
int slab_bgn = slab_idx * slab_len;
|
||||
int slab_end = slab_bgn + slab_len;
|
||||
boolean wildcard = simple_search;
|
||||
return new Srch_search_qry(Tid__search_page, cfg.Ns_mgr(), Srch_search_phrase.New(wiki.Case_mgr(), search_orig, wildcard), slab_bgn, slab_end);
|
||||
}
|
||||
public static Srch_search_qry New__drd(Xow_wiki wiki, Srch_ns_mgr ns_mgr, byte[] search_orig, int slab_bgn, int slab_end) {
|
||||
return new Srch_search_qry(Tid__android, ns_mgr, Srch_search_phrase.New(wiki.Case_mgr(), search_orig, Bool_.Y), slab_bgn, slab_end);
|
||||
}
|
||||
}
|
||||
@@ -1,57 +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.addons.apps.searchs.searchers.cbks; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.core.js.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_rslt_cbk__suggest_box implements Srch_rslt_cbk, GfoInvkAble {
|
||||
private final Js_wtr js_wtr = new Js_wtr();
|
||||
private final Xoae_app app;
|
||||
private final byte[] cbk_func;
|
||||
private final byte[] search_raw;
|
||||
public Srch_rslt_cbk__suggest_box(Xoae_app app, byte[] cbk_func, byte[] search_raw) {
|
||||
this.app = app; this.cbk_func = cbk_func;
|
||||
this.search_raw = search_raw;
|
||||
}
|
||||
public void On_cancel() {}
|
||||
public void On_rslts_found(Srch_search_qry qry, Srch_rslt_list rslts_list, int rslts_bgn, int rslts_end) {
|
||||
if (!rslts_list.Rslts_are_enough && !rslts_list.Rslts_are_done) return;
|
||||
js_wtr.Func_init(cbk_func);
|
||||
js_wtr.Prm_bry(search_raw);
|
||||
js_wtr.Prm_spr();
|
||||
js_wtr.Ary_init();
|
||||
int rslts_len = rslts_list.Len();
|
||||
for (int i = 0; i < qry.Slab_end; i++) {
|
||||
if (i >= rslts_len) break; // rslts_end will overshoot actual rslts_len; check for out of bounds and exit; EX: default suggest will have rslts_end of 25, but "earth time" will retrieve 15 results
|
||||
Srch_rslt_row row = rslts_list.Get_at(i);
|
||||
js_wtr.Ary_bry(row.Page_ttl.Full_txt_w_ttl_case());
|
||||
js_wtr.Ary_bry(row.Page_ttl_display(Bool_.Y));
|
||||
}
|
||||
js_wtr.Ary_term();
|
||||
js_wtr.Func_term();
|
||||
GfoInvkAble_.InvkCmd(app.Gui_mgr().Kit().New_cmd_sync(this), Srch_rslt_cbk__suggest_box.Invk__notify);
|
||||
}
|
||||
private void Notify() {
|
||||
app.Gui_mgr().Browser_win().Active_html_box().Html_js_eval_script(js_wtr.To_str_and_clear());
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk__notify)) Notify();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final String Invk__notify = "notify";
|
||||
}
|
||||
@@ -1,86 +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.addons.apps.searchs.searchers.cbks; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.gfui.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
import gplx.xowa.apps.apis.xowa.addons.searchs.*;
|
||||
public class Srch_rslt_cbk__url_bar implements Srch_rslt_cbk, GfoInvkAble {
|
||||
private final Xoae_app app;
|
||||
private final GfuiComboBox url_bar;
|
||||
private final Xoapi_url_bar url_bar_api;
|
||||
private String[] cbo_ary;
|
||||
private boolean rslts_finished;
|
||||
private int rslts_in_this_pass;
|
||||
private boolean rslts_shown = false;
|
||||
public Srch_rslt_cbk__url_bar(Xoae_app app, GfuiComboBox url_bar, Xoapi_url_bar url_bar_api) {
|
||||
this.app = app; this.url_bar = url_bar; this.url_bar_api = url_bar_api;
|
||||
}
|
||||
public void On_cancel() {}
|
||||
public void On_rslts_found(Srch_search_qry qry, Srch_rslt_list rslts_list, int rslts_bgn, int rslts_end) {
|
||||
int rslts_len = rslts_list.Len();
|
||||
this.rslts_finished = rslts_list.Rslts_are_enough || rslts_list.Rslts_are_done;
|
||||
|
||||
// get # of items for drop-down; note special logic to reduce blinking
|
||||
rslts_in_this_pass = rslts_end - rslts_bgn;
|
||||
if ( rslts_in_this_pass == 0 // no new results;
|
||||
&& rslts_bgn != 0 // if first one, still update; blanks out results from previous try;
|
||||
&& !rslts_finished) // if rslts_finished, still update to force cbo to "shrink"
|
||||
return; // exit now else will "blink" when refreshing;
|
||||
int max_rslts = url_bar_api.Max_results();
|
||||
int cbo_len = max_rslts; // force cbo_len to be max_rslts; reduces "blinking" when typing by keeping visible area to same size
|
||||
if (rslts_list.Rslts_are_done) { // "shrink" cbo_len to rslts_len; EX: 10 wanted; 2 returned; shrink to 2 rows;
|
||||
cbo_len = rslts_len;
|
||||
}
|
||||
|
||||
// fill cbo_ary with rslts from search, while "blanking" out rest
|
||||
this.cbo_ary = new String[cbo_len];
|
||||
for (int i = 0; i < cbo_len; ++i) {
|
||||
String cbo_itm = "";
|
||||
if (i >= max_rslts) break;
|
||||
if (i < rslts_len) {
|
||||
Srch_rslt_row rslt = rslts_list.Get_at(i);
|
||||
cbo_itm = String_.new_u8(rslt.Page_ttl_display(Bool_.N));
|
||||
}
|
||||
cbo_ary[i] = cbo_itm;
|
||||
}
|
||||
|
||||
GfoInvkAble_.InvkCmd(app.Gui_mgr().Kit().New_cmd_sync(this), Srch_rslt_cbk__url_bar.Invk__items__update); // NOTE: needs to be sync, b/c page_wkr and link_wkr must execute in order; EX:"Portal:Science" does not show; DATE:2016-03-24
|
||||
}
|
||||
private void Items__update() {
|
||||
url_bar.Items__update(cbo_ary);
|
||||
if (!url_bar.List_visible() // rslt_list not visible
|
||||
&& !rslts_shown // auto-dropdown hasn't happened yet
|
||||
&& (rslts_in_this_pass > 0 || rslts_finished) // at least 1 rslt, or search done
|
||||
) {
|
||||
rslts_shown = true; // only auto-show dropdown once; allows user to close drop-down and not have it continually flashing
|
||||
url_bar.List_visible_(Bool_.Y);
|
||||
}
|
||||
Xoa_app_.Usr_dlg().Prog_none("", "", "");
|
||||
if (rslts_finished) {
|
||||
if (cbo_ary.length == 0)
|
||||
url_bar.List_visible_(Bool_.N);
|
||||
else
|
||||
url_bar.Items__size_to_fit(cbo_ary.length);
|
||||
}
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk__items__update)) Items__update();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
} private static final String Invk__items__update = "items__update";
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//namespace gplx.xowa.addons.apps.searchs.searchers.cbks {
|
||||
// class Srch_suggest_cmd__page_tbl {
|
||||
// private boolean Search_by_all_pages_v2() {
|
||||
// rslts_2.Clear();
|
||||
// Xoa_ttl search_ttl = Xoa_ttl.parse(wiki, search_bry); if (search_ttl == null) return false;
|
||||
// byte[] search_ttl_bry = search_ttl.Page_db();
|
||||
// wiki.Db_mgr().Load_mgr().Load_ttls_for_search_suggest(this, rslts_2, search_ttl.Ns(), search_ttl_bry, max_results, all_pages_min, all_pages_extend, true, false);
|
||||
// return true;
|
||||
// }
|
||||
// private boolean Search_by_all_pages_v1() {
|
||||
// rslts_2.Clear();
|
||||
// Xowd_page_itm rslt_nxt = new Xowd_page_itm();
|
||||
// Xowd_page_itm rslt_prv = new Xowd_page_itm();
|
||||
// Xoa_ttl search_ttl = Xoa_ttl.parse(wiki, search_bry); if (search_ttl == null) return false;
|
||||
// byte[] search_ttl_bry = search_ttl.Page_db();
|
||||
// List_adp page_list = List_adp_.new_();
|
||||
// wiki.Db_mgr().Load_mgr().Load_ttls_for_all_pages(this, page_list, rslt_nxt, rslt_prv, Int_obj_ref.zero_(), wiki.Ns_mgr().Ns_main(), search_ttl_bry, max_results, all_pages_min, all_pages_extend, true, false);
|
||||
// Xowd_page_itm[] page_ary = (Xowd_page_itm[])page_list.To_ary_and_clear(typeof(Xowd_page_itm));
|
||||
// int idx = 0, page_ary_len = page_ary.length;
|
||||
// for (int i = 0; i < page_ary_len; i++) {
|
||||
// Xowd_page_itm page = page_ary[i];
|
||||
// if (page != null) {
|
||||
// if (!Bry_.Has_at_bgn(page.Ttl_page_db(), search_ttl_bry)) continue; // look-ahead may return other titles that don't begin with search; ignore
|
||||
// if (page.Text_len() > all_pages_min) {
|
||||
// rslts_2.Add(page);
|
||||
// idx++;
|
||||
// }
|
||||
// }
|
||||
// if (idx == max_results) break;
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -1,48 +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.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.langs.regxs.*;
|
||||
public class Srch_crt_itm {
|
||||
public Srch_crt_itm(int idx, int tid, Srch_crt_itm[] subs, byte[] raw, Srch_crt_sql raw_data) {
|
||||
this.Idx = idx; this.Tid = tid; this.Subs = subs;
|
||||
this.Raw = raw;
|
||||
this.Sql_data = raw_data;
|
||||
}
|
||||
public final int Idx; // itm index; EX: "a b" -> a:0 b:1
|
||||
public final int Tid;
|
||||
public final byte[] Raw;
|
||||
public final Srch_crt_itm[] Subs;
|
||||
public final Srch_crt_sql Sql_data;
|
||||
public void Accept_visitor(Srch_crt_visitor visitor) {visitor.Visit(this);}
|
||||
|
||||
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__invalid = 5 // EX: 'A OR'; incomplete or otherwise invalid
|
||||
;
|
||||
public static Srch_crt_itm[] Ary_empty = new Srch_crt_itm[0];
|
||||
public static final Srch_crt_itm Invalid = new Srch_crt_itm(-1, Srch_crt_itm.Tid__invalid, Srch_crt_itm.Ary_empty, null, null);
|
||||
public static Srch_crt_itm New_join(int tid, int idx, Srch_crt_itm... ary) {return new Srch_crt_itm(idx, tid, ary, null, Srch_crt_sql.New_or_null(null, Byte_ascii.Null));}
|
||||
public static Srch_crt_itm New_word(byte wildcard_byte, Srch_crt_tkn tkn, int idx, byte[] src) {
|
||||
int tid = tkn.Tid == Srch_crt_tkn.Tid__word_w_quote ? Srch_crt_itm.Tid__word_quote : Srch_crt_itm.Tid__word;
|
||||
return new Srch_crt_itm(idx, tid, Srch_crt_itm.Ary_empty, tkn.Val, Srch_crt_sql.New_or_null(src, wildcard_byte));
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public class Srch_crt_mgr {
|
||||
public Srch_crt_mgr(byte[] key, Srch_crt_tkn[] tkns, Srch_crt_itm root, byte words_tid, Srch_crt_itm[] words_ary, Srch_crt_itm words_nth) {
|
||||
this.Key = key;
|
||||
this.Tkns = tkns;
|
||||
this.Root = root;
|
||||
this.Words_tid = words_tid;
|
||||
this.Words_ary = words_ary;
|
||||
this.Words_nth = words_nth;
|
||||
}
|
||||
public final byte[] Key;
|
||||
public final Srch_crt_tkn[] Tkns;
|
||||
public final Srch_crt_itm Root;
|
||||
public final byte Words_tid;
|
||||
public final Srch_crt_itm[] Words_ary;
|
||||
public final Srch_crt_itm Words_nth;
|
||||
public int Words_nth__len() {
|
||||
return Words_nth == null ? 0 : Words_nth.Raw.length;
|
||||
}
|
||||
|
||||
public static final byte
|
||||
Tid__one = 0
|
||||
, Tid__ands = 1
|
||||
, Tid__mixed = 2
|
||||
;
|
||||
public static Srch_crt_mgr Invalid = new Srch_crt_mgr(Bry_.Empty, Srch_crt_tkn.Ary_empty, Srch_crt_itm.Invalid, Tid__one, Srch_crt_itm.Ary_empty, Srch_crt_itm.Invalid);
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.crts.visitors.*;
|
||||
public class Srch_crt_parser {
|
||||
private final Srch_crt_scanner scanner;
|
||||
private final Srch_crt_visitor__words words_visitor = new Srch_crt_visitor__words();
|
||||
private final Srch_crt_visitor__print print_visitor = new Srch_crt_visitor__print();
|
||||
private final byte wildcard_byte;
|
||||
private int uid_next;
|
||||
public Srch_crt_parser(Srch_crt_scanner_syms trie_bldr) {
|
||||
this.wildcard_byte = trie_bldr.Wild();
|
||||
this.scanner = new Srch_crt_scanner(trie_bldr);
|
||||
}
|
||||
public int Next_uid() {return ++uid_next;}
|
||||
public Srch_crt_mgr Parse_or_invalid(byte[] src, boolean auto_wildcard) {
|
||||
this.uid_next = -1;
|
||||
|
||||
Srch_crt_tkn[] tkns_ary = scanner.Scan(src);
|
||||
Srch_crt_parser_frame root_frame = new Srch_crt_parser_frame(this);
|
||||
Parse_tkns(root_frame, tkns_ary, 0, tkns_ary.length);
|
||||
Srch_crt_itm root_itm = root_frame.Produce_or_null();
|
||||
|
||||
if (root_itm == null) return Srch_crt_mgr.Invalid;
|
||||
byte[] key = print_visitor.Print(root_itm);
|
||||
words_visitor.Gather(root_itm);
|
||||
return new Srch_crt_mgr(key, tkns_ary, root_itm, words_visitor.Words_tid(), words_visitor.Words_ary(), words_visitor.Words_nth());
|
||||
}
|
||||
private int Parse_tkns(Srch_crt_parser_frame frame, Srch_crt_tkn[] tkns_ary, int tkns_bgn, int tkns_end) {
|
||||
int tkns_cur = tkns_bgn;
|
||||
while (tkns_cur < tkns_end) {
|
||||
Srch_crt_tkn cur_tkn = tkns_ary[tkns_cur];
|
||||
int new_tkns_cur = Process_tkn(frame, tkns_ary, tkns_cur, tkns_end, cur_tkn);
|
||||
if (new_tkns_cur < 0) {
|
||||
tkns_cur = -new_tkns_cur;
|
||||
break;
|
||||
}
|
||||
else
|
||||
tkns_cur = new_tkns_cur;
|
||||
}
|
||||
return tkns_cur;
|
||||
}
|
||||
private int Process_tkn(Srch_crt_parser_frame frame, Srch_crt_tkn[] tkns_ary, int tkns_cur, int tkns_end, Srch_crt_tkn cur_tkn) {
|
||||
byte cur_tid = cur_tkn.Tid;
|
||||
switch (cur_tid) {
|
||||
case Srch_crt_tkn.Tid__word:
|
||||
case Srch_crt_tkn.Tid__word_w_quote:
|
||||
frame.Subs__add(Srch_crt_itm.New_word(wildcard_byte, cur_tkn, frame.Next_uid(), cur_tkn.Val));
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__and:
|
||||
frame.Eval_join(Srch_crt_itm.Tid__and);
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__or:
|
||||
frame.Eval_join(Srch_crt_itm.Tid__or);
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__paren_bgn: {
|
||||
Srch_crt_parser_frame paren_frame = new Srch_crt_parser_frame(this);
|
||||
int new_tkns_cur = Parse_tkns(paren_frame, tkns_ary, tkns_cur + 1, tkns_end);
|
||||
Srch_crt_itm paren_itm = paren_frame.Produce_or_null();
|
||||
if (paren_itm != null) {
|
||||
frame.Subs__add(paren_itm);
|
||||
}
|
||||
return new_tkns_cur;
|
||||
}
|
||||
case Srch_crt_tkn.Tid__paren_end:
|
||||
return -(tkns_cur + 1);
|
||||
case Srch_crt_tkn.Tid__not:
|
||||
frame.Notted_y_();
|
||||
break;
|
||||
}
|
||||
return tkns_cur + 1;
|
||||
}
|
||||
}
|
||||
class Srch_crt_parser_frame {
|
||||
public Srch_crt_parser_frame(Srch_crt_parser parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
private int join_tid = Srch_crt_tkn.Tid__null;
|
||||
private boolean notted = false;
|
||||
private final List_adp subs = List_adp_.new_();
|
||||
private final Srch_crt_parser parser;
|
||||
public int Next_uid() {return parser.Next_uid();}
|
||||
public void Notted_y_() {
|
||||
if (notted) // already notted; disable; EX: "--a"
|
||||
notted = false;
|
||||
else
|
||||
notted = true;
|
||||
}
|
||||
public void Subs__add(Srch_crt_itm itm) {
|
||||
// if notted, wrap itm in not; EX: "-a"; "-(a & b)"
|
||||
if (notted) {
|
||||
itm = Srch_crt_itm.New_join(Srch_crt_itm.Tid__not, this.Next_uid(), itm);
|
||||
notted = false;
|
||||
}
|
||||
subs.Add(itm);
|
||||
|
||||
// auto-and behavior; EX: "a b" -> "a & b"; EX: "a (b | c)" -> "a & (b | c)"
|
||||
if ( join_tid == Srch_crt_tkn.Tid__null // if currently null
|
||||
&& subs.Len() > 1 // but 2 items in list
|
||||
)
|
||||
join_tid = Srch_crt_itm.Tid__and; // default to AND; EX: "a (b) c"
|
||||
}
|
||||
public void Eval_join(int tid) {
|
||||
if (join_tid == Srch_crt_tkn.Tid__null) join_tid = tid;
|
||||
else if (join_tid == tid) {} // tid is same; ignore; note that this handles dupes; EX: "a & & b"
|
||||
else { // tid changed; EX: a & b | c
|
||||
Merge_and_add();
|
||||
join_tid = tid;
|
||||
}
|
||||
}
|
||||
public Srch_crt_itm Produce_or_null() {
|
||||
int subs_len = subs.Len();
|
||||
switch (subs_len) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
join_tid = Srch_crt_tkn.Tid__null;
|
||||
return (Srch_crt_itm)subs.Get_at(0);
|
||||
default:
|
||||
Srch_crt_itm[] subs_ary = (Srch_crt_itm[])subs.To_ary_and_clear(Srch_crt_itm.class);
|
||||
Srch_crt_itm rv = Srch_crt_itm.New_join(join_tid, parser.Next_uid(), subs_ary);
|
||||
join_tid = Srch_crt_tkn.Tid__null;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
private void Merge_and_add() {
|
||||
int subs_len = subs.Len();
|
||||
if (subs_len > 1)
|
||||
subs.Add(Produce_or_null());
|
||||
}
|
||||
}
|
||||
@@ -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.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import org.junit.*; import gplx.xowa.addons.apps.searchs.parsers.*; import gplx.xowa.addons.apps.searchs.searchers.crts.visitors.*;
|
||||
public class Srch_crt_parser_tst {
|
||||
private final Srch_crt_parser_fxt fxt = new Srch_crt_parser_fxt();
|
||||
@Test public void Word__one() {fxt.Test__parse("a" , "a");}
|
||||
@Test public void And__one() {fxt.Test__parse("a + b" , "(a AND b)");}
|
||||
@Test public void And__many() {fxt.Test__parse("a + b + c" , "(a AND b AND c)");}
|
||||
@Test public void And__dangling() {fxt.Test__parse("a +" , "a");}
|
||||
@Test public void And__dupe() {fxt.Test__parse("a + + b" , "(a AND b)");}
|
||||
@Test public void Quote() {fxt.Test__parse("\"a b\"" , "\"a b\"");}
|
||||
@Test public void Auto__word() {fxt.Test__parse("a b" , "(a AND b)");}
|
||||
@Test public void Auto__quote() {fxt.Test__parse("a \"b\"" , "(a AND \"b\")");}
|
||||
@Test public void Auto__parens() {fxt.Test__parse("a (b , c)" , "(a AND (b OR c))");}
|
||||
@Test public void Or__one() {fxt.Test__parse("a , b" , "(a OR b)");}
|
||||
@Test public void Or__many() {fxt.Test__parse("a , b , c" , "(a OR b OR c)");}
|
||||
@Test public void Mixed__3() {fxt.Test__parse("a + b , c" , "((a AND b) OR c)");}
|
||||
@Test public void Mixed__5() {fxt.Test__parse("a + b , c + d , e" , "((((a AND b) OR c) AND d) OR e)");}
|
||||
@Test public void Parens__basic() {fxt.Test__parse("a + (b , c)" , "(a AND (b OR c))");}
|
||||
@Test public void Parens__nest() {fxt.Test__parse("a + (b , (c + d))" , "(a AND (b OR (c AND d)))");}
|
||||
@Test public void Parens__mid() {fxt.Test__parse("a + (b , c) + d)" , "(a AND (b OR c) AND d)");}
|
||||
@Test public void Parens__mixed() {fxt.Test__parse("a + (b , c) , d)" , "((a AND (b OR c)) OR d)");}
|
||||
@Test public void Parens__dupe() {fxt.Test__parse("((a))" , "a");}
|
||||
@Test public void Parens__dangling__lhs() {fxt.Test__parse("(a" , "a");}
|
||||
@Test public void Parens__dangling__rhs() {fxt.Test__parse("a)" , "a");}
|
||||
@Test public void Parens__empty__bos() {fxt.Test__parse("()" , "");}
|
||||
@Test public void Parens__empty__mid() {fxt.Test__parse("a () b" , "(a AND b)");}
|
||||
@Test public void Not__bos() {fxt.Test__parse("-abc" , "NOT abc");}
|
||||
@Test public void Not__mid() {fxt.Test__parse("a -b" , "(a AND NOT b)");}
|
||||
@Test public void Not__2() {fxt.Test__parse("a -b -c" , "(a AND NOT b AND NOT c)");}
|
||||
@Test public void Not__dangling__eos() {fxt.Test__parse("a -" , "a");}
|
||||
@Test public void Not__dangling__mid() {fxt.Test__parse("a -- b" , "(a AND b)");} // NOTE: scanner will remove spaces and convert to "a", "--", "b"
|
||||
@Test public void Not__dupe__2() {fxt.Test__parse("a --b" , "(a AND b)");}
|
||||
@Test public void Not__dupe__3() {fxt.Test__parse("a ---b" , "(a AND NOT b)");}
|
||||
@Test public void Not__parens() {fxt.Test__parse("a -(b + c)" , "(a AND NOT (b AND c))");}
|
||||
@Test public void Escape__eos() {fxt.Test__parse("\\" , "");}
|
||||
@Test public void Escape__escaped() {fxt.Test__parse("\\\\*" , "\\*");} // '\\' -> '\*'
|
||||
}
|
||||
class Srch_crt_parser_fxt {
|
||||
private final Srch_crt_parser crt_parser;
|
||||
private final Srch_crt_visitor__print visitor__to_str = new Srch_crt_visitor__print();
|
||||
public Srch_crt_parser_fxt() {
|
||||
crt_parser = new Srch_crt_parser(Srch_crt_scanner_syms.Dflt);
|
||||
Srch_text_parser text_parser = new Srch_text_parser();
|
||||
text_parser.Init_for_ttl(gplx.xowa.langs.cases.Xol_case_mgr_.A7());
|
||||
}
|
||||
public void Test__parse(String src_str, String expd) {
|
||||
byte[] src_bry = Bry_.new_a7(src_str);
|
||||
Srch_crt_mgr crt_mgr = crt_parser.Parse_or_invalid(src_bry, Bool_.N);
|
||||
Tfds.Eq(expd, String_.new_u8(visitor__to_str.Print(crt_mgr.Root)));
|
||||
}
|
||||
}
|
||||
@@ -1,136 +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.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.core.btries.*; import gplx.xowa.langs.cases.*;
|
||||
import gplx.xowa.addons.apps.searchs.parsers.*;
|
||||
class Srch_crt_scanner {
|
||||
private final List_adp tkns = List_adp_.new_(); private byte[] src; private int src_len, pos, txt_bgn;
|
||||
private final Srch_crt_scanner_syms trie_bldr; private final Btrie_slim_mgr trie;
|
||||
private final Bry_bfr word_bfr = Bry_bfr.new_(); private boolean word_is_dirty;
|
||||
public Srch_crt_scanner(Srch_crt_scanner_syms trie_bldr) {
|
||||
this.trie_bldr = trie_bldr;
|
||||
this.trie = trie_bldr.Trie();
|
||||
}
|
||||
public Srch_crt_tkn[] Scan(byte[] src) {
|
||||
this.src = src; this.src_len = src.length;
|
||||
tkns.Clear(); pos = 0; txt_bgn = -1;
|
||||
while (pos < src_len) {
|
||||
byte cur_b = src[pos];
|
||||
byte cur_tid = trie.Match_byte_or(cur_b, src, pos, src_len, Byte_.Max_value_127);
|
||||
if (cur_tid == Byte_.Max_value_127) { // text character
|
||||
if (txt_bgn == -1) txt_bgn = pos; // 1st character not set; set it
|
||||
if (word_is_dirty) word_bfr.Add_byte(cur_b);
|
||||
++pos;
|
||||
}
|
||||
else { // \ \s " - & | ( )
|
||||
int pos_end = trie.Match_pos();
|
||||
if ( cur_tid == Srch_crt_tkn.Tid__not // if "-"
|
||||
&& txt_bgn != -1) { // && "word has started"
|
||||
++pos;
|
||||
continue; // ignore; EX: "a-b" -> "a-b"; "-ab" -> "NOT" "ab"
|
||||
}
|
||||
if ( txt_bgn != -1 // pending word
|
||||
&& cur_tid != Srch_crt_tkn.Tid__escape // not escape
|
||||
) {
|
||||
Add_word(Srch_crt_tkn.Tid__word, txt_bgn, pos);
|
||||
}
|
||||
switch (cur_tid) {
|
||||
case Srch_crt_tkn.Tid__escape: // handle escape
|
||||
int nxt_pos = pos + 1;
|
||||
if (txt_bgn == -1) {
|
||||
txt_bgn = nxt_pos;
|
||||
word_is_dirty = true;
|
||||
} else { // word has started; transfer existing word to bfr;
|
||||
if (!word_is_dirty) {
|
||||
word_is_dirty = true;
|
||||
word_bfr.Add_mid(src, txt_bgn, pos);
|
||||
}
|
||||
}
|
||||
pos = nxt_pos; // skip "\"
|
||||
if (pos < src_len) {
|
||||
word_bfr.Add_byte(src[pos]); // add next char literally
|
||||
++pos;
|
||||
}
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__space: // discard spaces
|
||||
pos = Bry_find_.Find_fwd_while(src, pos, src_len, trie_bldr.Space());
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__quote: // find end quote and add as word
|
||||
int quote_bgn = pos + 1;
|
||||
int quote_end = Int_.Min_value;
|
||||
int tmp_pos = quote_bgn;
|
||||
while (true) {
|
||||
quote_end = Bry_find_.Find_fwd(src, trie_bldr.Quote(), tmp_pos, src_len);
|
||||
if (quote_end == Bry_find_.Not_found) { // no end-quote found; use space
|
||||
quote_end = Bry_find_.Find_fwd(src, trie_bldr.Space(), quote_bgn, src_len);
|
||||
if (quote_end == Bry_find_.Not_found) quote_end = src_len; // no space found; use EOS
|
||||
}
|
||||
else { // end-quote found; check if it's doubled
|
||||
int double_pos = quote_end + 1;
|
||||
if ( double_pos < src_len
|
||||
&& src[double_pos] == Byte_ascii.Quote) {
|
||||
if (!word_is_dirty) {
|
||||
word_is_dirty = true;
|
||||
}
|
||||
word_bfr.Add_mid(src, tmp_pos, double_pos);
|
||||
tmp_pos = double_pos + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (word_is_dirty)
|
||||
word_bfr.Add_mid(src, tmp_pos, quote_end);
|
||||
Add_word(Srch_crt_tkn.Tid__word_w_quote, quote_bgn, quote_end);
|
||||
pos = quote_end + 1; // +1 to place after quote
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__not:
|
||||
Add_word(Srch_crt_tkn.Tid__not, pos, pos_end);
|
||||
pos = pos_end;
|
||||
break;
|
||||
case Srch_crt_tkn.Tid__paren_bgn: case Srch_crt_tkn.Tid__paren_end:
|
||||
case Srch_crt_tkn.Tid__and: case Srch_crt_tkn.Tid__or:
|
||||
tkns.Add(New_tkn(cur_tid, Bry_.Mid(src, pos, pos_end)));
|
||||
pos = pos_end;
|
||||
break;
|
||||
default: throw Err_.new_unhandled_default(cur_tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (txt_bgn != -1) { // pending word; create
|
||||
Add_word(Srch_crt_tkn.Tid__word, txt_bgn, pos);
|
||||
}
|
||||
return (Srch_crt_tkn[])tkns.To_ary_and_clear(Srch_crt_tkn.class);
|
||||
}
|
||||
private void Add_word(byte tid, int src_bgn, int src_end) {
|
||||
// generate word_bry
|
||||
byte[] word_bry = null;
|
||||
if (word_is_dirty) {
|
||||
word_is_dirty = false;
|
||||
if (word_bfr.Len_eq_0()) return;
|
||||
word_bry = word_bfr.To_bry_and_clear();
|
||||
}
|
||||
else {
|
||||
if (src_end - src_bgn == 0) return;
|
||||
word_bry = Bry_.Mid(src, src_bgn, src_end);
|
||||
}
|
||||
tkns.Add(New_tkn(tid, word_bry));
|
||||
txt_bgn = -1;
|
||||
}
|
||||
private static Srch_crt_tkn New_tkn(byte tid, byte[] val) {return new Srch_crt_tkn(tid, val);}
|
||||
}
|
||||
@@ -1,112 +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.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.core.btries.*;
|
||||
public class Srch_crt_scanner_syms {
|
||||
public Srch_crt_scanner_syms(byte escape, byte space, byte quote, byte not, byte and, byte or, byte paren_bgn, byte paren_end, byte wild) {
|
||||
this.escape = escape; this.space = space; this.quote = quote;
|
||||
this.not = not; this.and = and; this.and_bry = Bry_.New_by_byte(and); this.or = or;
|
||||
this.paren_bgn = paren_bgn; this.paren_end = paren_end;
|
||||
this.wild = wild;
|
||||
this.trie = Btrie_slim_mgr.cs();
|
||||
Make_trie(trie, this);
|
||||
}
|
||||
public byte Escape() {return escape;} private byte escape;
|
||||
public byte Space() {return space;} private byte space;
|
||||
public byte Quote() {return quote;} private byte quote;
|
||||
public byte Not() {return not;} private byte not;
|
||||
public byte And() {return and;} private byte and;
|
||||
public byte[] And_bry() {return and_bry;} private byte[] and_bry;
|
||||
public byte Or() {return or;} private byte or;
|
||||
public byte Paren_bgn() {return paren_bgn;} private byte paren_bgn;
|
||||
public byte Paren_end() {return paren_end;} private byte paren_end;
|
||||
public byte Wild() {return wild;} private byte wild;
|
||||
public Btrie_slim_mgr Trie() {return trie;} private final Btrie_slim_mgr trie;
|
||||
public byte[] To_bry() {
|
||||
Bry_bfr bfr = Bry_bfr.new_();
|
||||
To_bry__add(bfr, "wild" , wild);
|
||||
To_bry__add(bfr, "not" , not);
|
||||
To_bry__add(bfr, "or" , or);
|
||||
To_bry__add(bfr, "and" , and);
|
||||
To_bry__add(bfr, "quote" , quote);
|
||||
To_bry__add(bfr, "paren_bgn" , paren_bgn);
|
||||
To_bry__add(bfr, "paren_end" , paren_end);
|
||||
To_bry__add(bfr, "escape" , escape);
|
||||
To_bry__add(bfr, "space" , space);
|
||||
return bfr.To_bry_and_clear();
|
||||
}
|
||||
public void Parse(byte[] src) {
|
||||
byte[][] lines = Bry_split_.Split_lines(src);
|
||||
escape = space = quote = not = and = or = paren_bgn = paren_end = wild = Byte_.Zero;
|
||||
for (byte[] line : lines) {
|
||||
int line_len = line.length;
|
||||
int eq_pos = Bry_find_.Find_fwd(line, Byte_ascii.Eq, 0, line_len); if (eq_pos == Bry_find_.Not_found) continue;
|
||||
String key = String_.new_u8(Bry_.Mid(line, 0, eq_pos));
|
||||
byte val = Parse__val(line, eq_pos + 1, line_len);
|
||||
if (String_.Eq(key, "wild" )) wild = val;
|
||||
else if (String_.Eq(key, "not" )) not = val;
|
||||
else if (String_.Eq(key, "or" )) or = val;
|
||||
else if (String_.Eq(key, "and" )) and = val;
|
||||
else if (String_.Eq(key, "quote" )) quote = val;
|
||||
else if (String_.Eq(key, "paren_bgn" )) paren_bgn = val;
|
||||
else if (String_.Eq(key, "paren_end" )) paren_end = val;
|
||||
else if (String_.Eq(key, "escape" )) escape = val;
|
||||
else if (String_.Eq(key, "space" )) space = val;
|
||||
}
|
||||
}
|
||||
private static void To_bry__add(Bry_bfr bfr, String key, byte val) {
|
||||
bfr.Add_str_u8(key).Add_byte_eq();
|
||||
switch (val) {
|
||||
case Byte_ascii.Null : bfr.Add_str_a7("\\0"); break;
|
||||
case Byte_ascii.Space : bfr.Add_str_a7("\\s"); break;
|
||||
default : bfr.Add_byte(val); break;
|
||||
}
|
||||
bfr.Add_byte_nl();
|
||||
}
|
||||
private static void Make_trie(Btrie_slim_mgr trie, Srch_crt_scanner_syms bldr) {
|
||||
Make_trie__add(trie, bldr.Escape() , Srch_crt_tkn.Tid__escape);
|
||||
Make_trie__add(trie, bldr.Space() , Srch_crt_tkn.Tid__space);
|
||||
Make_trie__add(trie, bldr.Quote() , Srch_crt_tkn.Tid__quote);
|
||||
Make_trie__add(trie, bldr.Not() , Srch_crt_tkn.Tid__not);
|
||||
Make_trie__add(trie, bldr.And() , Srch_crt_tkn.Tid__and);
|
||||
Make_trie__add(trie, bldr.Or() , Srch_crt_tkn.Tid__or);
|
||||
Make_trie__add(trie, bldr.Paren_bgn() , Srch_crt_tkn.Tid__paren_bgn);
|
||||
Make_trie__add(trie, bldr.Paren_end() , Srch_crt_tkn.Tid__paren_end);
|
||||
}
|
||||
private static void Make_trie__add(Btrie_slim_mgr rv, byte b, byte tid) {
|
||||
if (b == Byte_ascii.Null) return;
|
||||
rv.Add_bry_byte(b, tid);
|
||||
}
|
||||
public static final Srch_crt_scanner_syms Dflt =
|
||||
new Srch_crt_scanner_syms
|
||||
( Byte_ascii.Backslash, Byte_ascii.Space, Byte_ascii.Quote, Byte_ascii.Dash, Byte_ascii.Plus, Byte_ascii.Comma
|
||||
, Byte_ascii.Paren_bgn, Byte_ascii.Paren_end, Byte_ascii.Star
|
||||
);
|
||||
private static byte Parse__val(byte[] line, int val_bgn, int line_len) {
|
||||
if (line_len - val_bgn == 1) return line[val_bgn];
|
||||
if ( line_len - val_bgn == 2
|
||||
&& line[val_bgn] == Byte_ascii.Backslash) {
|
||||
byte val_byte = line[val_bgn + 1];
|
||||
switch (val_byte) {
|
||||
case Byte_ascii.Num_0: return Byte_ascii.Null;
|
||||
case Byte_ascii.Ltr_s: return Byte_ascii.Space;
|
||||
}
|
||||
}
|
||||
return Byte_ascii.Null;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +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.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import org.junit.*; import gplx.xowa.addons.apps.searchs.parsers.*;
|
||||
public class Srch_crt_scanner_tst {
|
||||
private final Srch_crt_scanner_fxt fxt = new Srch_crt_scanner_fxt();
|
||||
@Test public void Word() {fxt.Test__scan("abc" , "abc");}
|
||||
@Test public void Word__many() {fxt.Test__scan("abc d ef" , "abc", "d", "ef");}
|
||||
@Test public void Word__symbol() {fxt.Test__scan("a; b" , "a;", "b");}
|
||||
@Test public void And() {fxt.Test__scan("a + b" , "a", "+", "b");}
|
||||
@Test public void And__parens() {fxt.Test__scan("a +(b)" , "a", "+", "(", "b", ")");} // check that ( causes and to be treated as separate word
|
||||
@Test public void Or() {fxt.Test__scan("a , b" , "a", ",", "b");}
|
||||
@Test public void Or__no_space() {fxt.Test__scan("a, b" , "a", ",", "b");}
|
||||
@Test public void Not() {fxt.Test__scan("-abc" , "-", "abc");}
|
||||
@Test public void Not__mid__1() {fxt.Test__scan("a-b" , "a-b");} // fails if "a", "-", "b"
|
||||
@Test public void Not__mid__2() {fxt.Test__scan("a b-c" , "a", "b-c");} // ignore - if in middle of word
|
||||
@Test public void Not__and() {fxt.Test__scan("a -bc" , "a", "-", "bc");} // auto-add AND for -
|
||||
@Test public void Not__dangling() {fxt.Test__scan("a -" , "a", "-");}
|
||||
@Test public void Space() {fxt.Test__scan(" a b " , "a", "b");} // spaces should not generate tkns
|
||||
@Test public void Quote() {fxt.Test__scan("\"a b\"" , "a b");}
|
||||
@Test public void Quote__mid() {fxt.Test__scan("a\"b" , "a", "b");}
|
||||
@Test public void Quote__double() {fxt.Test__scan("\"a\"\"b\"" , "a\"b");}
|
||||
@Test public void Quote__missing__one() {fxt.Test__scan("\"abc" , "abc");}
|
||||
@Test public void Quote__missing__many() {fxt.Test__scan("\"abc a" , "abc", "a");}
|
||||
@Test public void Escape__bgn() {fxt.Test__scan("\\-a" , "-a");} // fails if "-", "a"
|
||||
@Test public void Escape__and__bgn() {fxt.Test__scan("\\+" , "+");} // fails if "a", "&", "b"
|
||||
@Test public void Escape__and__mid() {fxt.Test__scan("a\\+b" , "a+b");} // fails if "a", "&", "b"
|
||||
@Test public void Escape__eos__1() {fxt.Test__scan("\\" , String_.Ary_empty);}
|
||||
@Test public void Escape__eos__2() {fxt.Test__scan("a \\" , "a");}
|
||||
@Test public void Escape__eos__3() {fxt.Test__scan("a\\" , "a");}
|
||||
@Test public void Escape__many() {fxt.Test__scan("c\\+\\+" , "c++");}
|
||||
@Test public void Escape__end() {fxt.Test__scan("a\\\\" , "a\\");}
|
||||
@Test public void Complicated() {fxt.Test__scan("(a + \"b\") , -c", "(", "a", "+", "b", ")", ",", "-", "c");}
|
||||
}
|
||||
class Srch_crt_scanner_fxt {
|
||||
private final Srch_crt_scanner scanner;
|
||||
public Srch_crt_scanner_fxt() {
|
||||
this.scanner = new Srch_crt_scanner(Srch_crt_scanner_syms.Dflt);
|
||||
Srch_text_parser text_parser = new Srch_text_parser();
|
||||
text_parser.Init_for_ttl(gplx.xowa.langs.cases.Xol_case_mgr_.A7());
|
||||
}
|
||||
public void Test__scan(String src_str, String... expd) {
|
||||
byte[] src_bry = Bry_.new_a7(src_str);
|
||||
Srch_crt_tkn[] actl_itms = scanner.Scan(src_bry);
|
||||
Tfds.Eq_ary(expd, To_vals(src_bry, actl_itms));
|
||||
}
|
||||
public void Test__scan_tids(String src_str, byte... expd) {
|
||||
byte[] src_bry = Bry_.new_a7(src_str);
|
||||
Srch_crt_tkn[] actl_itms = scanner.Scan(src_bry);
|
||||
Tfds.Eq_ary(expd, To_tids(actl_itms));
|
||||
}
|
||||
private String[] To_vals(byte[] src, Srch_crt_tkn[] ary) {
|
||||
int len = ary.length;
|
||||
String[] rv = new String[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Srch_crt_tkn tkn = ary[i];
|
||||
rv[i] = String_.new_a7(tkn.Val);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private byte[] To_tids(Srch_crt_tkn[] ary) {
|
||||
int len = ary.length;
|
||||
byte[] rv = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
Srch_crt_tkn tkn = ary[i];
|
||||
rv[i] = tkn.Tid;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,76 +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.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.langs.regxs.*;
|
||||
public class Srch_crt_sql {
|
||||
public Srch_crt_sql(int tid, String eq, String rng_bgn, String rng_end, String like, Gfo_pattern pattern) {
|
||||
this.Tid = tid;
|
||||
this.Eq = eq;
|
||||
this.Rng_bgn = rng_bgn;
|
||||
this.Rng_end = rng_end;
|
||||
this.Like = like;
|
||||
this.Pattern = pattern;
|
||||
}
|
||||
public final int Tid;
|
||||
public final String Eq;
|
||||
public final String Rng_bgn;
|
||||
public final String Rng_end;
|
||||
public final String Like;
|
||||
public final Gfo_pattern Pattern; // NOTE: only supports LIKE; GLOB requires regex
|
||||
public int Eq_id;
|
||||
|
||||
public static final int
|
||||
Tid__eq = 0 // EX: 'ab' -> "word_text = 'ab'"
|
||||
, Tid__rng = 1 // EX: 'ab*' -> "word_text >= 'ab' AND word_text < 'ac'"
|
||||
, Tid__like = 2 // EX: 'a*b', '*a*b'-> "word_text LIKE 'a%b%'"
|
||||
;
|
||||
public static Srch_crt_sql New_or_null(byte[] raw, byte wildcard_byte) {
|
||||
if (raw == null) return null; // null for join itms; EX: "+", ","
|
||||
int raw_len = raw.length;
|
||||
|
||||
// get tid
|
||||
int wildcard_pos = Bry_find_.Find_fwd(raw, wildcard_byte, 0, raw_len);
|
||||
int tid = -1;
|
||||
if (wildcard_pos == Bry_find_.Not_found) tid = Srch_crt_sql.Tid__eq; // EX: 'a'
|
||||
else if (wildcard_pos == raw_len - 1) tid = Srch_crt_sql.Tid__rng; // EX: 'a*'
|
||||
else tid = Srch_crt_sql.Tid__like; // EX: '*a'
|
||||
|
||||
// get rng_bgn, rng_end or like
|
||||
String eq = "", rng_bgn = "", rng_end = "", like = "";
|
||||
byte[] pattern_raw = raw;
|
||||
switch (tid) {
|
||||
case Srch_crt_sql.Tid__eq:
|
||||
eq = String_.new_a7(raw);
|
||||
break;
|
||||
case Srch_crt_sql.Tid__rng:
|
||||
byte[] rng_tmp = Bry_.Mid(raw, 0, raw_len - 1);
|
||||
rng_bgn = String_.new_u8(rng_tmp);
|
||||
rng_end = String_.new_u8(gplx.core.intls.Utf8_.Increment_char_at_last_pos(rng_tmp));
|
||||
break;
|
||||
case Srch_crt_sql.Tid__like:
|
||||
like = String_.new_u8(Bry_.Replace(raw, wildcard_byte, gplx.dbs.sqls.Sql_qry_wtr_.Like_wildcard));
|
||||
byte like_escape_byte = gplx.xowa.addons.apps.searchs.searchers.wkrs.Srch_link_wkr_sql.Like_escape_byte;
|
||||
Bry_bfr tmp_bfr = Bry_bfr_.Get();
|
||||
try {pattern_raw = Bry_.Resolve_escape(tmp_bfr, like_escape_byte, raw, 0, raw.length);}
|
||||
finally {tmp_bfr.Mkr_rls();}
|
||||
break;
|
||||
}
|
||||
Gfo_pattern pattern = tid == Srch_crt_sql.Tid__eq ? null : new Gfo_pattern(pattern_raw);
|
||||
return new Srch_crt_sql(tid, eq, rng_bgn, rng_end, like, pattern);
|
||||
}
|
||||
}
|
||||
@@ -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.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import org.junit.*;
|
||||
public class Srch_crt_sql_tst {
|
||||
private final Srch_crt_sql_fxt fxt = new Srch_crt_sql_fxt();
|
||||
@Test public void Eq() {fxt.Exec__new_or_null("a").Test__tid(Srch_crt_sql.Tid__eq).Test__eq("a");}
|
||||
@Test public void Rng() {fxt.Exec__new_or_null("a*").Test__tid(Srch_crt_sql.Tid__rng).Test__rng_bgn("a").Test__rng_end("b").Test__pattern("a*");}
|
||||
@Test public void Like() {fxt.Exec__new_or_null("a*b").Test__tid(Srch_crt_sql.Tid__like).Test__like("a%b").Test__pattern("a*b");}
|
||||
@Test public void Like__escape() {fxt.Exec__new_or_null("a|\\*b").Test__tid(Srch_crt_sql.Tid__like).Test__like("a|\\%b").Test__pattern("a\\*b");} // "a\*b"
|
||||
@Test public void Quote() {fxt.Exec__new_or_null("\"a b\"").Test__tid(Srch_crt_sql.Tid__eq).Test__eq("\"a b\"");}
|
||||
}
|
||||
class Srch_crt_sql_fxt {
|
||||
private Srch_crt_sql actl;
|
||||
public Srch_crt_sql_fxt Exec__new_or_null(String src_str) {
|
||||
this.actl = Srch_crt_sql.New_or_null(Bry_.new_u8(src_str), Srch_search_addon.Wildcard__star);
|
||||
return this;
|
||||
}
|
||||
public Srch_crt_sql_fxt Test__tid(int expd) {Tfds.Eq(expd, actl.Tid); return this;}
|
||||
public Srch_crt_sql_fxt Test__eq(String expd) {Tfds.Eq(expd, actl.Eq); return this;}
|
||||
public Srch_crt_sql_fxt Test__rng_bgn(String expd) {Tfds.Eq(expd, actl.Rng_bgn); return this;}
|
||||
public Srch_crt_sql_fxt Test__rng_end(String expd) {Tfds.Eq(expd, actl.Rng_end); return this;}
|
||||
public Srch_crt_sql_fxt Test__like(String expd) {Tfds.Eq(expd, actl.Like); return this;}
|
||||
public Srch_crt_sql_fxt Test__pattern(String expd) {Tfds.Eq(expd, String_.new_u8(actl.Pattern.Raw()), "pattern"); return this;}
|
||||
}
|
||||
@@ -1,38 +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.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public class Srch_crt_tkn {
|
||||
public Srch_crt_tkn(byte tid, byte[] val) {this.Tid = tid; this.Val = val;}
|
||||
public final byte Tid;
|
||||
public final byte[] Val;
|
||||
public static final byte
|
||||
Tid__escape = 0
|
||||
, Tid__space = 1
|
||||
, Tid__quote = 2
|
||||
, Tid__not = 3
|
||||
, Tid__and = 4
|
||||
, Tid__or = 5
|
||||
, Tid__paren_bgn = 6
|
||||
, Tid__paren_end = 7
|
||||
, Tid__word = 8
|
||||
, Tid__word_w_quote = 9
|
||||
, Tid__eos = 10
|
||||
, Tid__null = 11
|
||||
;
|
||||
public static final Srch_crt_tkn[] Ary_empty = new Srch_crt_tkn[0];
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.searchers.crts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public interface Srch_crt_visitor {
|
||||
void Visit(Srch_crt_itm node);
|
||||
}
|
||||
@@ -1,49 +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.addons.apps.searchs.searchers.crts.visitors; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
public class Srch_crt_visitor__print implements Srch_crt_visitor {
|
||||
private final Bry_bfr bfr = Bry_bfr.new_();
|
||||
public byte[] Print(Srch_crt_itm root) {
|
||||
Visit(root);
|
||||
return bfr.To_bry_and_clear();
|
||||
}
|
||||
public void Visit(Srch_crt_itm node) {
|
||||
switch (node.Tid) {
|
||||
case Srch_crt_itm.Tid__word: bfr.Add(node.Raw); break;
|
||||
case Srch_crt_itm.Tid__word_quote: bfr.Add_byte_quote().Add(node.Raw).Add_byte_quote(); break;
|
||||
case Srch_crt_itm.Tid__and:
|
||||
case Srch_crt_itm.Tid__or:
|
||||
bfr.Add_byte(Byte_ascii.Paren_bgn);
|
||||
Srch_crt_itm[] subs = node.Subs;
|
||||
int subs_len = subs.length;
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
if (i != 0)
|
||||
bfr.Add_str_a7(node.Tid == Srch_crt_itm.Tid__and ? " AND " : " OR ");
|
||||
subs[i].Accept_visitor(this);
|
||||
}
|
||||
bfr.Add_byte(Byte_ascii.Paren_end);
|
||||
break;
|
||||
case Srch_crt_itm.Tid__not:
|
||||
bfr.Add_str_a7("NOT ");
|
||||
node.Subs[0].Accept_visitor(this);
|
||||
break;
|
||||
case Srch_crt_itm.Tid__invalid: break; // should not happen
|
||||
default: throw Err_.new_unhandled_default(node.Tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.searchers.crts.visitors; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
public class Srch_crt_visitor__words implements Srch_crt_visitor {
|
||||
private final List_adp words_list = List_adp_.new_();
|
||||
public byte Words_tid() {return words_tid;} private byte words_tid;
|
||||
public Srch_crt_itm Words_nth() {return words_nth;} private Srch_crt_itm words_nth;
|
||||
public Srch_crt_itm[] Words_ary() {return (Srch_crt_itm[])words_list.To_ary_and_clear(Srch_crt_itm.class);}
|
||||
public void Gather(Srch_crt_itm root) {
|
||||
words_list.Clear();
|
||||
words_tid = Srch_crt_mgr.Tid__ands;
|
||||
words_nth = null;
|
||||
Visit(root);
|
||||
if (words_list.Count() == 1)
|
||||
words_tid = Srch_crt_mgr.Tid__one;
|
||||
}
|
||||
public void Visit(Srch_crt_itm itm) {
|
||||
int itm_tid = itm.Tid;
|
||||
switch (itm_tid) {
|
||||
case Srch_crt_itm.Tid__and:
|
||||
case Srch_crt_itm.Tid__or:
|
||||
if (itm_tid == Srch_crt_itm.Tid__or)
|
||||
words_tid = Srch_crt_mgr.Tid__mixed;
|
||||
Srch_crt_itm[] subs = itm.Subs;
|
||||
int subs_len = subs.length;
|
||||
for (int i = 0; i < subs_len; ++i)
|
||||
Visit(subs[i]);
|
||||
break;
|
||||
case Srch_crt_itm.Tid__word:
|
||||
case Srch_crt_itm.Tid__word_quote:
|
||||
case Srch_crt_itm.Tid__not:
|
||||
if ( itm_tid == Srch_crt_itm.Tid__not
|
||||
&& itm.Subs.length == 1) {
|
||||
Srch_crt_itm lone = itm.Subs[0];
|
||||
if ( lone.Tid == Srch_crt_itm.Tid__word
|
||||
|| lone.Tid == Srch_crt_itm.Tid__word_quote)
|
||||
words_nth = lone;
|
||||
}
|
||||
else
|
||||
words_nth = itm;
|
||||
words_list.Add(itm);
|
||||
break;
|
||||
case Srch_crt_itm.Tid__invalid: break; // should not happen
|
||||
default: throw Err_.new_unhandled_default(itm.Tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.addons.apps.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.core.primitives.*;
|
||||
class Hash_adp__int {
|
||||
private final Hash_adp hash = Hash_adp_.new_();
|
||||
private final Int_obj_ref tmp_key = Int_obj_ref.neg1_();
|
||||
public void Clear() {hash.Clear();}
|
||||
public Object Get_by(int key) {return hash.Get_by(tmp_key.Val_(key));}
|
||||
public void Add(int key, Object obj) {hash.Add(Int_obj_ref.new_(key), obj);}
|
||||
public void Add_if_dupe_use_1st(int key, Object obj) {hash.Add_if_dupe_use_1st(Int_obj_ref.new_(key), obj);}
|
||||
}
|
||||
@@ -1,32 +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.addons.apps.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public class Srch_rslt_cache {
|
||||
private final Hash_adp_bry hash = Hash_adp_bry.cs();
|
||||
public void Clear() {hash.Clear();}
|
||||
public Srch_rslt_list Get_or_new(byte[] key) {
|
||||
Srch_rslt_list rv = (Srch_rslt_list)hash.Get_by(key);
|
||||
if (rv == null) {
|
||||
rv = new Srch_rslt_list();
|
||||
hash.Add(key, rv);
|
||||
}
|
||||
rv.Rslts_are_first = true;
|
||||
rv.Rslts_are_enough = false;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +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.addons.apps.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public interface Srch_rslt_cbk {
|
||||
void On_rslts_found(Srch_search_qry qry, Srch_rslt_list rslts_list, int rslts_bgn, int rslts_end);
|
||||
void On_cancel();
|
||||
}
|
||||
@@ -1,25 +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.addons.apps.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public class Srch_rslt_cbk_ {
|
||||
public static final Srch_rslt_cbk Noop = new Srch_rslt_cbk__noop();
|
||||
}
|
||||
class Srch_rslt_cbk__noop implements Srch_rslt_cbk {
|
||||
public void On_rslts_found(Srch_search_qry qry, Srch_rslt_list rslts_list, int rslts_bgn, int rslts_end) {}
|
||||
public void On_cancel() {}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public class Srch_rslt_list {
|
||||
private final Ordered_hash key_hash = Ordered_hash_.New_bry();
|
||||
private final Hash_adp__int id_hash = new Hash_adp__int();
|
||||
public int Score_bgn = gplx.dbs.percentiles.Percentile_rng.Score_null;
|
||||
public int Score_len = gplx.dbs.percentiles.Percentile_rng.Score_null;
|
||||
public boolean Rslts_are_first;
|
||||
public boolean Rslts_are_enough;
|
||||
public boolean Rslts_are_done;
|
||||
public int Len() {return key_hash.Len();}
|
||||
public boolean Has(byte[] key) {return key_hash.Has(key);}
|
||||
public Srch_rslt_row Get_by(byte[] key) {return (Srch_rslt_row)key_hash.Get_by(key);}
|
||||
public Srch_rslt_row Get_at(int i) {return (Srch_rslt_row)key_hash.Get_at(i);}
|
||||
public void Clear() {key_hash.Clear(); id_hash.Clear();}
|
||||
public void Add(Srch_rslt_row row) {key_hash.Add(row.Key, row);}
|
||||
public void Sort() {key_hash.Sort_by(Srch_rslt_row_sorter.Score_dsc);}
|
||||
public boolean Ids__has(int id) {return (Srch_rslt_row)id_hash.Get_by(id) != null;}
|
||||
public Srch_rslt_row Ids__get(int id) {return (Srch_rslt_row)id_hash.Get_by(id);}
|
||||
public void Ids__add(int id, Srch_rslt_row r) {id_hash.Add(id, r);}
|
||||
public void Merge(Srch_rslt_list list) {
|
||||
list.Sort();
|
||||
int list_len = list.Len();
|
||||
for (int i = 0; i < list_len; ++i) {
|
||||
Srch_rslt_row row = list.Get_at(i);
|
||||
this.Add(row);
|
||||
}
|
||||
list.Clear();
|
||||
}
|
||||
public void Process_rdr_done(gplx.dbs.percentiles.Percentile_rng rng, boolean rslts_are_enough, boolean rslts_are_done) {
|
||||
this.Score_bgn = rng.Score_bgn();
|
||||
this.Score_len = rng.Score_len();
|
||||
this.Rslts_are_enough = rslts_are_enough;
|
||||
this.Rslts_are_done = rslts_are_done;
|
||||
}
|
||||
}
|
||||
class Srch_rslt_row_sorter implements gplx.core.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Srch_rslt_row lhs = (Srch_rslt_row)lhsObj;
|
||||
Srch_rslt_row rhs = (Srch_rslt_row)rhsObj;
|
||||
int rv = -Int_.Compare(lhs.Page_score, rhs.Page_score);
|
||||
if (rv != CompareAble_.Same) return rv;
|
||||
return Bry_.Compare(lhs.Page_ttl.Page_txt(), rhs.Page_ttl.Page_txt());
|
||||
}
|
||||
public static final Srch_rslt_row_sorter Score_dsc = new Srch_rslt_row_sorter();
|
||||
}
|
||||
@@ -1,53 +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.addons.apps.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
public class Srch_rslt_list_ {
|
||||
public static boolean Add_if_new(Srch_search_ctx ctx, Srch_rslt_list rslts, Srch_rslt_row row) {
|
||||
Srch_rslt_list_.Highlight(ctx, row); // always highlight title first; needed for suggest_box to update highlighting when increasing word; EX: Eart -> Earth; "Earth" should be highlighted, not "Eart"
|
||||
return
|
||||
( !rslts.Has(row.Key) // ignore: page already added by another word; EX: "A B"; word is "B", but "A B" already added by "A"
|
||||
&& !rslts.Ids__has(row.Page_id) // ignore: page already added by page-tbl or by redirect
|
||||
&& !Redirect_exists(rslts, row) // ignore: page is redirect, and target page already added
|
||||
);
|
||||
}
|
||||
public static void Get_redirect_ttl(Xowd_page_tbl page_tbl, Xowd_page_itm tmp_page_itm, Srch_rslt_row row) {
|
||||
int redirect_id = row.Page_redirect_id;
|
||||
if (redirect_id == Srch_rslt_row.Page_redirect_id_null) return;
|
||||
if (!page_tbl.Select_by_id(tmp_page_itm, redirect_id)) {Xoa_app_.Usr_dlg().Warn_many("", "", "page not found for redirect_id; redirect_id=~{0}", redirect_id); return;}
|
||||
row.Page_redirect_ttl = Xoa_ttl.Replace_unders(tmp_page_itm.Ttl_page_db());
|
||||
}
|
||||
private static void Highlight(Srch_search_ctx ctx, Srch_rslt_row row) {
|
||||
try {row.Page_ttl_highlight = ctx.Highlight_mgr.Highlight(row.Page_ttl.Full_txt_w_ttl_case());} // NOTE: always highlight row; needed for when search done in url_bar (highlight=n) and then same search reused for search (highlight=y)
|
||||
catch (Exception e) {Xoa_app_.Usr_dlg().Warn_many("", "", "highlight failed; ttl=~{0} err=~{1}", row.Page_ttl_wo_ns, Err_.Message_gplx_log(e));}
|
||||
}
|
||||
private static boolean Redirect_exists(Srch_rslt_list rslts, Srch_rslt_row cur_row) {
|
||||
int trg_id = cur_row.Page_redirect_id;
|
||||
if (trg_id == Srch_rslt_row.Page_redirect_id_null) { // src_page is not redirect
|
||||
return false;
|
||||
} else { // src_page is redirect
|
||||
Srch_rslt_row trg_row = rslts.Ids__get(trg_id);
|
||||
if (trg_row == null) { // trg_page has not been seen before
|
||||
rslts.Ids__add(trg_id, cur_row); // add trg_id to known ids; handles double-redirects; 1 -> 2 -> 3;
|
||||
return false;
|
||||
}
|
||||
else // trg_page has been seen before
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +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.addons.apps.searchs.searchers.rslts; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public class Srch_rslt_row {
|
||||
public Srch_rslt_row(byte[] key, byte[] wiki_bry, Xoa_ttl page_ttl, int page_ns, byte[] page_ttl_wo_ns, int page_id, int page_len, int page_score, int page_redirect_id) {
|
||||
this.Key = key;
|
||||
this.Wiki_bry = wiki_bry;
|
||||
this.Page_id = page_id;
|
||||
this.Page_ttl = page_ttl;
|
||||
this.Page_ns = page_ns;
|
||||
this.Page_ttl_wo_ns = page_ttl_wo_ns;
|
||||
this.Page_len = page_len;
|
||||
this.Page_redirect_id = page_redirect_id;
|
||||
this.Page_score = page_score;
|
||||
}
|
||||
public final byte[] Key;
|
||||
public final byte[] Wiki_bry;
|
||||
public final int Page_id;
|
||||
public final Xoa_ttl Page_ttl;
|
||||
public final int Page_ns;
|
||||
public final byte[] Page_ttl_wo_ns;
|
||||
public final int Page_len;
|
||||
public final int Page_redirect_id;
|
||||
public final int Page_score;
|
||||
public byte[] Page_redirect_ttl;
|
||||
public byte[] Page_ttl_highlight;
|
||||
public byte[] Page_ttl_display(boolean html) {
|
||||
byte[] rv = html ? Page_ttl_highlight : Page_ttl.Full_txt_w_ttl_case();
|
||||
if (Page_redirect_id == Page_redirect_id_null)
|
||||
return rv;
|
||||
else {
|
||||
byte[] redirect_dlm = html ? Bry__redirect__html : Bry__redirect__text;
|
||||
return Bry_.Add(rv, redirect_dlm, Page_redirect_ttl);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] Bld_key(byte[] wiki_domain, int page_id) {return Bry_.Add(wiki_domain, Byte_ascii.Pipe_bry, Int_.To_bry(page_id));}
|
||||
public static Srch_rslt_row New(byte[] wiki_bry, Xoa_ttl page_ttl, int page_id, int page_len, int page_score, int redirect_id) {
|
||||
return new Srch_rslt_row(Bld_key(wiki_bry, page_id), wiki_bry, page_ttl, page_ttl.Ns().Id(), page_ttl.Page_db(), page_id, page_len, page_score, redirect_id);
|
||||
}
|
||||
public static final int Page_redirect_id_null = gplx.xowa.wikis.data.tbls.Xowd_page_itm.Redirect_id_null;
|
||||
public static final String Str__redirect__text = " -> ";
|
||||
private static final byte[]
|
||||
Bry__redirect__html = Bry_.new_u8(" → ") // 8592; 8594
|
||||
, Bry__redirect__text = Bry_.new_a7(Str__redirect__text);
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.searchers.slabs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
public class Srch_slab_itm {
|
||||
public Srch_slab_itm(byte[] wiki, int bgn, int end) {this.wiki = wiki; this.bgn = bgn; this.end = end;}
|
||||
public byte[] Wiki() {return wiki;} private final byte[] wiki;
|
||||
public int Bgn() {return bgn;} private final int bgn;
|
||||
public int End() {return end;} private final int end;
|
||||
}
|
||||
@@ -1,34 +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.addons.apps.searchs.searchers.slabs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.core.brys.*;
|
||||
public class Srch_slab_itm_parser {
|
||||
private final List_adp itm_list = List_adp_.new_();
|
||||
private final Bry_rdr rdr = new Bry_rdr();
|
||||
public Srch_slab_itm[] Parse(byte[] raw) { // EX: en.wikipedia.org|41|60;en.wiktionary.org|21|40;
|
||||
rdr.Init_by_src(raw);
|
||||
while (!rdr.Pos_is_eos()) {
|
||||
byte[] wiki = rdr.Read_bry_to(Byte_ascii.Pipe);
|
||||
int bgn = rdr.Read_int_to(Byte_ascii.Pipe);
|
||||
int end = rdr.Read_int_to(Byte_ascii.Semic);
|
||||
Srch_slab_itm itm = new Srch_slab_itm(wiki, bgn, end);
|
||||
itm_list.Add(itm);
|
||||
}
|
||||
return (Srch_slab_itm[])itm_list.To_ary_and_clear(Srch_slab_itm.class);
|
||||
}
|
||||
}
|
||||
@@ -1,163 +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.addons.apps.searchs.searchers.wkrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.dbs.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.apps.searchs.dbs.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*; import gplx.dbs.percentiles.*;
|
||||
import gplx.xowa.langs.cases.*; import gplx.xowa.addons.apps.searchs.parsers.*;
|
||||
public class Srch_link_wkr extends Percentile_select_base {
|
||||
private final Srch_link_wkr_sql sql_mkr = new Srch_link_wkr_sql();
|
||||
private final Db_attach_mgr attach_mgr = new Db_attach_mgr();
|
||||
private final Srch_rslt_list tmp_rslts = new Srch_rslt_list();
|
||||
private Srch_rslt_list rslts_list; private Srch_rslt_cbk rslt_cbk; private Srch_search_ctx ctx;
|
||||
private Xowd_page_tbl page_tbl;
|
||||
private Db_stmt stmt;
|
||||
private int rslts_bgn, rslts_end;
|
||||
private Srch_rslt_row cur_row; private final Xowd_page_itm tmp_page_itm = new Xowd_page_itm();
|
||||
private int link_tbl_idx, link_tbl_nth; private boolean link_loop_done;
|
||||
private Srch_crt_itm sql_root;
|
||||
public void Search(Srch_rslt_list rslts_list, Srch_rslt_cbk rslt_cbk, Srch_search_ctx ctx) {
|
||||
// init
|
||||
super.cxl = ctx.Cxl;
|
||||
super.rng = ctx.Score_rng;
|
||||
super.rng_log = new Percentile_rng_log(ctx.Addon.Db_mgr().Cfg().Link_score_max());
|
||||
rng_log.Init(ctx.Qry.Phrase.Orig, ctx.Rslts_needed);
|
||||
this.rslts_list = rslts_list; this.rslt_cbk = rslt_cbk; this.ctx = ctx;
|
||||
this.rslts_bgn = rslts_list.Len(); this.rslts_end = rslts_bgn;
|
||||
this.page_tbl = ctx.Tbl__page;
|
||||
|
||||
try {
|
||||
// enough results at start; occurs in Special:Search when revisiting slabs; EX: 1-100 -> 101-200 -> 1-100
|
||||
if (ctx.Qry.Slab_end < rslts_list.Len()) {
|
||||
rslts_list.Rslts_are_enough = true;
|
||||
rslt_cbk.On_rslts_found(ctx.Qry, rslts_list, 0, rslts_list.Len());
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare for iteration
|
||||
this.link_tbl_idx = 0;
|
||||
this.link_tbl_nth = ctx.Tbl__link__ary.length - 1;
|
||||
sql_root = Srch_link_wkr_.Find_sql_root(ctx);
|
||||
attach_mgr.Init(new Db_attach_itm("page_db", ctx.Db__core.Conn()), new Db_attach_itm("word_db", ctx.Tbl__word.conn));
|
||||
super.Select();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
// gplx.core.consoles.Console_adp__sys.Instance.Write_str_w_nl("detaching: " + String_.new_u8(ctx.Qry.Phrase.Lcase_wild) + " " + Int_.To_str(ctx.Score_rng.Score_bgn()) + " " + Int_.To_str(ctx.Score_rng.Score_end()) + " " + attach_mgr.List__to_str());
|
||||
attach_mgr.Detach();
|
||||
stmt = Db_stmt_.Rls(stmt);
|
||||
}
|
||||
catch (Exception e) {
|
||||
gplx.core.consoles.Console_adp__sys.Instance.Write_str_w_nl("detaching err: " + String_.new_u8(ctx.Qry.Phrase.Orig) + " " + Int_.To_str(ctx.Score_rng.Score_bgn()) + Err_.Message_lang(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override protected Db_rdr Rdr__init() {
|
||||
try {
|
||||
Db_conn link_tbl_conn = ctx.Tbl__link__ary[link_tbl_idx].conn;
|
||||
attach_mgr.Main_conn_(link_tbl_conn);
|
||||
sql_mkr.Init(ctx, attach_mgr, sql_root);
|
||||
if (stmt == null) stmt = sql_mkr.Make(ctx, attach_mgr, link_tbl_conn);
|
||||
sql_mkr.Fill(stmt);
|
||||
return stmt.Exec_select__rls_manual();
|
||||
} finally {sql_mkr.Clear();}
|
||||
}
|
||||
@Override protected boolean Found_enough() {return (rslts_list.Len() + tmp_rslts.Len()) >= ctx.Qry.Slab_end;}
|
||||
@Override protected void Rng__update(int rdr_found) {
|
||||
link_loop_done = false;
|
||||
if (ctx.Qry.Ns_mgr.Ns_main_only()) {
|
||||
link_loop_done = true;
|
||||
}
|
||||
else {
|
||||
if (link_tbl_idx == link_tbl_nth) {
|
||||
link_tbl_idx = 0;
|
||||
link_loop_done = true;
|
||||
}
|
||||
else {
|
||||
++link_tbl_idx;
|
||||
}
|
||||
// NOTE: must do detach_database and rls_stmt b/c link_tbl_conn changes
|
||||
attach_mgr.Detach();
|
||||
stmt = Db_stmt_.Rls(stmt);
|
||||
}
|
||||
if (link_loop_done)
|
||||
rng.Update(rslts_end - rslts_bgn);
|
||||
}
|
||||
@Override protected void Rdr__done(boolean rslts_are_enough, boolean rslts_are_done) {
|
||||
if (!link_loop_done) return;
|
||||
int tmp_rslts_len = tmp_rslts.Len();
|
||||
|
||||
// get redirect ttl; note that main rdr should be closed
|
||||
for (int i = 0; i < tmp_rslts_len; ++i) {
|
||||
Srch_rslt_row row = tmp_rslts.Get_at(i);
|
||||
int redirect_id = row.Page_redirect_id;
|
||||
if (redirect_id != Srch_rslt_row.Page_redirect_id_null)
|
||||
Srch_rslt_list_.Get_redirect_ttl(page_tbl, tmp_page_itm, row);
|
||||
}
|
||||
|
||||
// merge to rslts_list; notify; cleanup;
|
||||
if (tmp_rslts_len > 0) rslts_list.Merge(tmp_rslts);
|
||||
rslts_list.Process_rdr_done(rng, rslts_are_enough, rslts_are_done);
|
||||
rslt_cbk.On_rslts_found(ctx.Qry, rslts_list, rslts_bgn, rslts_end);
|
||||
rslts_list.Rslts_are_first = false;
|
||||
rslts_bgn = rslts_end;
|
||||
// gplx.core.consoles.Console_adp__sys.Instance.Write_str(rng_log.To_str_and_clear());
|
||||
}
|
||||
@Override protected boolean Row__read(Db_rdr rdr) {
|
||||
if (!rdr.Move_next()) return false;
|
||||
byte[] wiki_bry = ctx.Wiki_domain;
|
||||
int page_id = rdr.Read_int(page_tbl.Fld_page_id());
|
||||
byte[] key = Srch_rslt_row.Bld_key(wiki_bry, page_id);
|
||||
this.cur_row = ctx.Cache__page.Get_by(key); // note that page could have been added from another word
|
||||
if (cur_row == null) {
|
||||
int page_len = rdr.Read_int(page_tbl.Fld_page_len());
|
||||
int page_score = page_tbl.Fld_page_score() == Dbmeta_fld_itm.Key_null ? page_len : rdr.Read_int(page_tbl.Fld_page_score());
|
||||
int page_ns_id = rdr.Read_int(page_tbl.Fld_page_ns());
|
||||
byte[] page_ttl_wo_ns = rdr.Read_bry_by_str(page_tbl.Fld_page_title());
|
||||
Xoa_ttl page_ttl = ctx.Wiki.Ttl_parse(page_ns_id, page_ttl_wo_ns);
|
||||
this.cur_row = new Srch_rslt_row(key, wiki_bry, page_ttl, page_ns_id, page_ttl_wo_ns, page_id, page_len, page_score, rdr.Read_int(page_tbl.Fld_redirect_id()));
|
||||
ctx.Cache__page.Add(cur_row);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override protected boolean Row__eval() {
|
||||
if ( !ctx.Qry.Ns_mgr.Has(cur_row.Page_ns) // ignore: ns doesn't match
|
||||
|| !Srch_link_wkr_.Matches(ctx.Crt_mgr__root, ctx.Addon.Ttl_parser(), ctx.Case_mgr, cur_row.Page_ttl_wo_ns) // ignore: ttl doesn't match ttl_matcher; EX: "A B"
|
||||
)
|
||||
return false;
|
||||
boolean rv = Srch_rslt_list_.Add_if_new(ctx, rslts_list, cur_row);
|
||||
if (rv) {
|
||||
++rslts_end;
|
||||
rslts_list.Ids__add(cur_row.Page_id, cur_row);
|
||||
tmp_rslts.Add(cur_row);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public static int Percentile_rng__calc_adj(int last_word_len) {
|
||||
switch (last_word_len) {
|
||||
case 1: return 0;
|
||||
case 2: return 10;
|
||||
case 3: return 20;
|
||||
case 4: return 30;
|
||||
case 5: return 40;
|
||||
case 6: return 50;
|
||||
case 7: return 60;
|
||||
case 8: return 70;
|
||||
default: return 80;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,141 +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.addons.apps.searchs.searchers.wkrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.xowa.addons.apps.searchs.parsers.*; import gplx.xowa.langs.cases.*;
|
||||
import gplx.xowa.addons.apps.searchs.dbs.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
class Srch_link_wkr_ {
|
||||
private static final Srch_word_count_wkr word_count_wkr = new Srch_word_count_wkr();
|
||||
public static Srch_crt_itm Find_sql_root(Srch_search_ctx ctx) {
|
||||
Srch_crt_mgr crt_mgr = ctx.Crt_mgr;
|
||||
// lookup word_ids; needed for one, mixed, and ands
|
||||
Srch_crt_itm[] words_ary = crt_mgr.Words_ary;
|
||||
int words_len = words_ary.length;
|
||||
for (int i = 0; i < words_len; ++i) {
|
||||
Srch_crt_itm word = words_ary[i];
|
||||
switch (word.Tid) {
|
||||
case Srch_crt_itm.Tid__word:
|
||||
if (word.Sql_data.Tid == Srch_crt_sql.Tid__eq) // look up word_id
|
||||
word.Sql_data.Eq_id = ctx.Tbl__word.Select_or_empty(word.Raw).Id;
|
||||
break;
|
||||
case Srch_crt_itm.Tid__word_quote:
|
||||
Srch_word_row[] rows = Find_sql_root__quoted(ctx, word.Raw);
|
||||
if (rows != null && rows.length > 0) // override eq_id
|
||||
word.Sql_data.Eq_id = rows[0].Id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (crt_mgr.Words_tid != Srch_crt_mgr.Tid__ands) return ctx.Crt_mgr__root; // one and mixed returns root;
|
||||
|
||||
// ands need to do more db_lookup for rng words and identify the sql_root
|
||||
Srch_crt_itm rv = null;
|
||||
Srch_word_tbl word_tbl = ctx.Tbl__word;
|
||||
int count_min = Int_.Max_value;
|
||||
for (int i = 0; i < words_len; ++i) {
|
||||
Srch_crt_itm sub = words_ary[i];
|
||||
int sub_count = Find_sql_root__ands(ctx, word_tbl, sub);
|
||||
if (sub_count < count_min) {
|
||||
count_min = sub_count;
|
||||
rv = sub;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
private static Srch_word_row[] Find_sql_root__quoted(Srch_search_ctx ctx, byte[] raw) {
|
||||
List_adp tmp_list = List_adp_.new_();
|
||||
byte[][] ary = Bry_split_.Split(raw, Byte_ascii.Space, Bool_.Y); // TODO: splitting by space is simplistic; should call Srch2_split_words
|
||||
int words_len = ary.length;
|
||||
for (int i = 0; i < words_len; ++i) {
|
||||
byte[] word = ary[i];
|
||||
Srch_word_row word_row = ctx.Tbl__word.Select_or_empty(word); if (word_row == Srch_word_row.Empty) continue;
|
||||
tmp_list.Add(word_row);
|
||||
}
|
||||
if (tmp_list.Count() == 0) return null; // no words exist in db; EX: "xyz1 xyz2"
|
||||
tmp_list.Sort_by(Srch_word_row_sorter__link_count.Desc);
|
||||
Srch_word_row[] rows = (Srch_word_row[])tmp_list.To_ary_and_clear(Srch_word_row.class);
|
||||
return rows;
|
||||
}
|
||||
private static int Find_sql_root__ands(Srch_search_ctx ctx, Srch_word_tbl word_tbl, Srch_crt_itm sub) {
|
||||
if (sub.Tid == Srch_crt_itm.Tid__not) return Int_.Max_value;
|
||||
int cached_count = ctx.Cache__word_counts.Get_as_int_or(sub.Raw, Int_.Min_value);
|
||||
if (cached_count != Int_.Min_value) return cached_count;
|
||||
int rv = Int_.Max_value;
|
||||
if (sub.Sql_data.Tid == Srch_crt_sql.Tid__eq) {
|
||||
Srch_word_row word = word_tbl.Select_or_empty(sub.Raw);
|
||||
if (word != Srch_word_row.Empty) rv = word.Link_count;
|
||||
}
|
||||
else {
|
||||
rv = word_count_wkr.Get_top_10(ctx, word_tbl, sub);
|
||||
}
|
||||
ctx.Cache__word_counts.Add_bry_int(sub.Raw, rv);
|
||||
return rv;
|
||||
}
|
||||
public static boolean Matches(Srch_crt_itm node, Srch_text_parser text_parser, Xol_case_mgr case_mgr, byte[] ttl) {
|
||||
byte[] ttl_lower = case_mgr.Case_build_lower(Xoa_ttl.Replace_unders(ttl));
|
||||
byte[][] ttl_words = text_parser.Parse_to_bry_ary(Bool_.Y, ttl);
|
||||
return Matches(node, ttl_lower, ttl_words);
|
||||
}
|
||||
private static boolean Matches(Srch_crt_itm node, byte[] ttl_lower, byte[][] ttl_words) {
|
||||
int tid = node.Tid;
|
||||
byte[] raw = node.Raw;
|
||||
Srch_crt_itm[] subs = node.Subs;
|
||||
int subs_len = subs.length;
|
||||
switch (tid) {
|
||||
case Srch_crt_itm.Tid__word: {
|
||||
int len = ttl_words.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] word = ttl_words[i];
|
||||
if (node.Sql_data.Pattern == null) {
|
||||
if (Bry_.Eq(word, raw)) return true;
|
||||
}
|
||||
else {
|
||||
if (node.Sql_data.Pattern.Match(word)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case Srch_crt_itm.Tid__word_quote: return Bry_find_.Find_fwd(ttl_lower, raw) != Bry_find_.Not_found;// note that raw does not have quotes; EX: "B*" -> B*
|
||||
case Srch_crt_itm.Tid__not: return !Matches(subs[0], ttl_lower, ttl_words);
|
||||
case Srch_crt_itm.Tid__or: {
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Srch_crt_itm sub = subs[i];
|
||||
if (Matches(sub, ttl_lower, ttl_words))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case Srch_crt_itm.Tid__and:
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Srch_crt_itm sub = subs[i];
|
||||
if (!Matches(sub, ttl_lower, ttl_words))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case Srch_crt_itm.Tid__invalid: return false;
|
||||
default: throw Err_.new_unhandled(tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
class Srch_word_row_sorter__link_count implements gplx.core.lists.ComparerAble {
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Srch_word_row lhs = (Srch_word_row)lhsObj;
|
||||
Srch_word_row rhs = (Srch_word_row)rhsObj;
|
||||
return -Int_.Compare(lhs.Link_count, rhs.Link_count);
|
||||
}
|
||||
public static final Srch_word_row_sorter__link_count Desc = new Srch_word_row_sorter__link_count(); Srch_word_row_sorter__link_count() {}
|
||||
}
|
||||
@@ -1,157 +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.addons.apps.searchs.searchers.wkrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.dbs.*; import gplx.dbs.stmts.*; import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.crts.*; import gplx.xowa.addons.apps.searchs.dbs.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_link_wkr_sql {
|
||||
private final Db_stmt_mgr stmt_mgr = new Db_stmt_mgr();
|
||||
public void Clear() {stmt_mgr.Clear();}
|
||||
public String Dbg(Srch_search_ctx ctx, Db_attach_mgr attach_mgr, Srch_crt_itm sql_root) {
|
||||
stmt_mgr.Mode_is_stmt_(Bool_.N);
|
||||
Init(ctx, attach_mgr, sql_root);
|
||||
stmt_mgr.Mode_is_stmt_(Bool_.Y);
|
||||
String rv = Write(ctx, attach_mgr);
|
||||
stmt_mgr.Clear();
|
||||
return rv;
|
||||
}
|
||||
public void Init(Srch_search_ctx ctx, Db_attach_mgr attach_mgr, Srch_crt_itm sql_root) {
|
||||
synchronized (Fmt__link) { // THREAD:must synchronized on static Object, else 2 wikis with simultaneous search commands will write to same fmtr
|
||||
stmt_mgr.Bfr().Add(Bry__page__bgn);
|
||||
Bld_where(ctx, sql_root);
|
||||
stmt_mgr.Bfr().Add(Bry__page__end);
|
||||
}
|
||||
}
|
||||
public String Write(Srch_search_ctx ctx, Db_attach_mgr attach_mgr) {
|
||||
String sql = stmt_mgr.Bfr().To_str_and_clear();
|
||||
try {
|
||||
// gplx.core.consoles.Console_adp__sys.Instance.Write_str_w_nl("attaching: " + String_.new_u8(ctx.Qry.Phrase.Lcase_wild) + " " + Int_.To_str(ctx.Score_rng.Score_bgn()) + " " + Int_.To_str(ctx.Score_rng.Score_end()) + " " + attach_mgr.List__to_str());
|
||||
sql = attach_mgr.Resolve_sql(sql);
|
||||
}
|
||||
catch (Exception e) {
|
||||
gplx.core.consoles.Console_adp__sys.Instance.Write_str_w_nl("attaching err: " + String_.new_u8(ctx.Qry.Phrase.Orig) + " " + Int_.To_str(ctx.Score_rng.Score_bgn()) + " " + Int_.To_str(ctx.Score_rng.Score_end()) + Err_.Message_lang(e));
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
public Db_stmt Make(Srch_search_ctx ctx, Db_attach_mgr attach_mgr, Db_conn cur_link_conn) {
|
||||
String sql = Write(ctx, attach_mgr);
|
||||
attach_mgr.Attach();
|
||||
return cur_link_conn.Stmt_sql(sql);
|
||||
}
|
||||
public void Fill(Db_stmt stmt) {
|
||||
// gplx.core.consoles.Console_adp__sys.Instance.Write_str_w_nl(String_.new_u8(ctx.Qry.Phrase.Orig) + " " + Int_.To_str(ctx.Score_rng.Score_bgn()) + " " + Int_.To_str(ctx.Score_rng.Score_end()));
|
||||
stmt_mgr.Fill_stmt_and_clear(stmt);
|
||||
}
|
||||
private void Bld_where(Srch_search_ctx ctx, Srch_crt_itm node) {
|
||||
switch (node.Tid) {
|
||||
case Srch_crt_itm.Tid__word:
|
||||
case Srch_crt_itm.Tid__word_quote: // NOTE: quoted word is treated as Eq, except Eq_id is set to "lowest" word_id
|
||||
Bld_leaf(ctx, node);
|
||||
break;
|
||||
case Srch_crt_itm.Tid__or:
|
||||
case Srch_crt_itm.Tid__and:
|
||||
Srch_crt_itm[] subs = node.Subs;
|
||||
int subs_len = subs.length;
|
||||
for (int i = 0; i < subs_len; ++i) {
|
||||
Srch_crt_itm sub = subs[i];
|
||||
if (sub.Tid == Srch_crt_itm.Tid__not) continue; // do not build sql for NOT itms; EX: a + (b, c) + -d
|
||||
if (i != 0)
|
||||
stmt_mgr.Bfr().Add_str_a7(node.Tid == Srch_crt_itm.Tid__and ? "INTERSECT\n" : "UNION\n");
|
||||
Bld_where(ctx, sub);
|
||||
}
|
||||
break;
|
||||
case Srch_crt_itm.Tid__not: break; // never check database for NOT node
|
||||
case Srch_crt_itm.Tid__invalid: break; // should not happen
|
||||
default: throw Err_.new_unhandled_default(node.Tid);
|
||||
}
|
||||
}
|
||||
private void Bld_leaf(Srch_search_ctx ctx, Srch_crt_itm node) {
|
||||
int node_idx = node.Idx;
|
||||
int node_sql_tid = node.Sql_data.Tid;
|
||||
int score_bgn = ctx.Score_rng.Score_bgn();
|
||||
int score_end = ctx.Score_rng.Score_end();
|
||||
Srch_word_tbl word_tbl = ctx.Tbl__word;
|
||||
stmt_mgr.Bfr().Add(Bry__link__bgn);
|
||||
switch (node_sql_tid) {
|
||||
case Srch_crt_sql.Tid__eq: // EX: "earth"
|
||||
stmt_mgr.Add_crt_int(word_tbl.fld_id, node.Sql_data.Eq_id);
|
||||
stmt_mgr.Write_fmt(Fmt__word_id);
|
||||
break;
|
||||
case Srch_crt_sql.Tid__rng: // EX: "earth*"
|
||||
stmt_mgr.Add_var_many(node_idx, "AND ", "search_word__word_text__link_score_max__link_score_min");
|
||||
stmt_mgr.Add_crt_str(word_tbl.fld_text, node.Sql_data.Rng_bgn);
|
||||
stmt_mgr.Add_crt_str(word_tbl.fld_text, node.Sql_data.Rng_end);
|
||||
stmt_mgr.Add_crt_int(word_tbl.fld_link_score_max, score_bgn);
|
||||
stmt_mgr.Add_crt_int(word_tbl.fld_link_score_min, score_end);
|
||||
stmt_mgr.Write_fmt(Fmt__word_text__rng);
|
||||
break;
|
||||
case Srch_crt_sql.Tid__like: // EX: "*earth"
|
||||
stmt_mgr.Add_var_many(node_idx, "WHERE ", "search_word__link_score_max__link_score_min");
|
||||
stmt_mgr.Add_crt_int(word_tbl.fld_link_score_max, score_bgn);
|
||||
stmt_mgr.Add_crt_int(word_tbl.fld_link_score_min, score_end);
|
||||
stmt_mgr.Add_crt_str(word_tbl.fld_text, node.Sql_data.Like);
|
||||
stmt_mgr.Write_fmt(Fmt__word_text__like);
|
||||
break;
|
||||
}
|
||||
Srch_link_tbl link_tbl = ctx.Tbl__link__ary[0];
|
||||
stmt_mgr.Add_crt_int(link_tbl.fld_link_score, score_bgn);
|
||||
stmt_mgr.Add_crt_int(link_tbl.fld_link_score, score_end);
|
||||
stmt_mgr.Write_fmt(Fmt__link);
|
||||
}
|
||||
private static final byte[]
|
||||
Bry__page__bgn = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "SELECT p.page_id, p.page_namespace, p.page_title, p.page_len, p.page_score, p.page_redirect_id"
|
||||
, "FROM <page_db>page p"
|
||||
, "WHERE p.page_id IN"
|
||||
, "("
|
||||
, ""
|
||||
))
|
||||
, Bry__page__end = Bry_.new_a7(")\n")
|
||||
, Bry__link__bgn = Bry_.new_a7(String_.Concat_lines_nl_skip_last
|
||||
( "SELECT l.page_id"
|
||||
, "FROM search_link l INDEXED BY search_link__word_id__link_score"
|
||||
, "WHERE "
|
||||
))
|
||||
;
|
||||
private static final String
|
||||
Str__link__end = String_.Concat_lines_nl_skip_last
|
||||
( "AND l.link_score >= ~{score_bgn}"
|
||||
, "AND l.link_score < ~{score_end}"
|
||||
, ""
|
||||
)
|
||||
, Str__word__text__bgn = String_.Concat_lines_nl_skip_last
|
||||
( "l.word_id IN"
|
||||
, "("
|
||||
, "SELECT w~{uid}.word_id"
|
||||
, "FROM <word_db>search_word w~{uid} INDEXED BY ~{index}"
|
||||
, ""
|
||||
)
|
||||
, Str__word__text__rng = "WHERE w~{uid}.word_text >= ~{word_bgn} AND w~{uid}.word_text < ~{word_end}\n"
|
||||
, Str__word__text__like = "AND w~{uid}.word_text LIKE ~{word_like} ESCAPE '|'\n"
|
||||
, Str__word__text__mnx = String_.Concat_lines_nl_skip_last
|
||||
( "~{and} w~{uid}.link_score_max >= ~{score_bgn}"
|
||||
, "AND w~{uid}.link_score_min < ~{score_end}"
|
||||
, ""
|
||||
);
|
||||
private static final Bry_fmt
|
||||
Fmt__link = Bry_fmt.Auto(Str__link__end)
|
||||
, Fmt__word_id = Bry_fmt.Auto("l.word_id = ~{word_uid}\n")
|
||||
, Fmt__word_text__rng = Bry_fmt.New(Str__word__text__bgn + Str__word__text__rng + Str__word__text__mnx + ")\n", "uid", "and", "index", "word_bgn", "word_end", "score_bgn", "score_end")
|
||||
, Fmt__word_text__like = Bry_fmt.New(Str__word__text__bgn + Str__word__text__mnx + Str__word__text__like + ")\n", "uid", "and", "index", "score_bgn", "score_end", "word_like")
|
||||
;
|
||||
public static final byte Like_escape_byte = Byte_ascii.Pipe;
|
||||
}
|
||||
@@ -1,39 +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.addons.apps.searchs.searchers.wkrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import org.junit.*; import gplx.xowa.addons.apps.searchs.parsers.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*; import gplx.xowa.addons.apps.searchs.searchers.crts.visitors.*;
|
||||
public class Srch_link_wkr_sql_tst {
|
||||
private final Srch_link_wkr_sql_fxt fxt = new Srch_link_wkr_sql_fxt();
|
||||
@Test public void Rng() {
|
||||
fxt.Run__search("a").Test__eq
|
||||
( "select"
|
||||
);
|
||||
}
|
||||
}
|
||||
class Srch_link_wkr_sql_fxt {
|
||||
private final Srch_link_wkr_sql link_wkr = new Srch_link_wkr_sql();
|
||||
public Srch_link_wkr_sql_fxt Run__search(String search) {
|
||||
// attach_mgr.Init(cur_link_tbl.conn, new Db_attach_itm("page_db", ctx.Db__core.Conn()), new Db_attach_itm("word_db", ctx.Tbl__word.conn));
|
||||
// link_wkr.Init(ctx, attach_mgr);
|
||||
// this.actl_sql = link_wkr.Write(ctx, attach_mgr);
|
||||
link_wkr.Clear();
|
||||
return this;
|
||||
}
|
||||
public void Test__eq(String... v) {
|
||||
}
|
||||
}
|
||||
@@ -1,72 +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.addons.apps.searchs.searchers.wkrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
public class Srch_page_tbl_wkr {
|
||||
private final Xowd_page_itm tmp_page_row = new Xowd_page_itm();
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
public void Search(Srch_search_ctx ctx, Srch_rslt_cbk cbk) {
|
||||
byte[] search_raw = To_bry_or_null(tmp_bfr, ctx.Scanner_syms.Wild(), ctx.Crt_mgr); // build up search String but handle escapes "\+" -> "+"
|
||||
if (search_raw == null) return; // search-term has not or symbols; EX: "earth -history"; "(earth & history)"
|
||||
Xoa_ttl ttl = ctx.Wiki.Ttl_parse(search_raw); if (ttl == null) return;
|
||||
Xowd_page_tbl page_tbl = ctx.Tbl__page;
|
||||
if (ctx.Cxl.Canceled()) return;
|
||||
if (page_tbl.Select_by_ttl(tmp_page_row, ttl.Ns(), ttl.Page_db())) {
|
||||
if (ctx.Cxl.Canceled()) return;
|
||||
Srch_rslt_row row = Srch_rslt_row.New(ctx.Wiki_domain, ttl, tmp_page_row.Id(), tmp_page_row.Text_len(), ctx.Addon.Db_mgr().Cfg().Link_score_max() * 3, tmp_page_row.Redirect_id());
|
||||
if (Srch_rslt_list_.Add_if_new(ctx, ctx.Rslts_list, row)) {
|
||||
Srch_rslt_list_.Get_redirect_ttl(page_tbl, tmp_page_row, row);
|
||||
ctx.Rslts_list.Add(row);
|
||||
ctx.Rslts_list.Ids__add(row.Page_id, row);
|
||||
cbk.On_rslts_found(ctx.Qry, ctx.Rslts_list, 0, 1);
|
||||
ctx.Rslts_list.Rslts_are_first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public static byte[] To_bry_or_null(Bry_bfr bfr, byte wildcard_byte, Srch_crt_mgr mgr) {
|
||||
if (mgr.Words_tid == Srch_crt_mgr.Tid__mixed) return null;
|
||||
Srch_crt_tkn[] tkns = mgr.Tkns;
|
||||
int len = tkns.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Srch_crt_tkn tkn = tkns[i];
|
||||
switch (tkn.Tid) {
|
||||
case Srch_crt_tkn.Tid__word:
|
||||
case Srch_crt_tkn.Tid__word_w_quote:
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
if (i != 0) bfr.Add_byte_space();
|
||||
byte[] tkn_raw = tkn.Val;
|
||||
int tkn_raw_len = tkn_raw.length;
|
||||
int wildcard_pos = Bry_find_.Find_fwd(tkn_raw, wildcard_byte, 0, tkn_raw_len);
|
||||
if (wildcard_pos != Bry_find_.Not_found) {
|
||||
int last_pos = tkn_raw_len - 1;
|
||||
if (wildcard_pos == last_pos)
|
||||
bfr.Add_mid(tkn_raw, 0, last_pos);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else
|
||||
bfr.Add(tkn.Val);
|
||||
}
|
||||
return bfr.To_bry_and_clear();
|
||||
}
|
||||
}
|
||||
@@ -1,47 +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.addons.apps.searchs.searchers.wkrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import org.junit.*; import gplx.xowa.addons.apps.searchs.parsers.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*; import gplx.xowa.addons.apps.searchs.searchers.crts.visitors.*;
|
||||
public class Srch_page_tbl_wkr_tst {
|
||||
private final Srch_page_tbl_wkr_fxt fxt = new Srch_page_tbl_wkr_fxt();
|
||||
@Test public void Word__one() {fxt.Test__to_bry_or_null("a" , "a");}
|
||||
@Test public void Word__many() {fxt.Test__to_bry_or_null("a b c" , "a b c");}
|
||||
@Test public void Wild__end() {fxt.Test__to_bry_or_null("a*" , "a");}
|
||||
@Test public void Wild__both() {fxt.Test__to_bry_or_null("a*b*" , null);}
|
||||
@Test public void Quote() {fxt.Test__to_bry_or_null("\"a b\"" , "a b");}
|
||||
@Test public void Quote__mixed() {fxt.Test__to_bry_or_null("a \"b \"\" c\" d" , "a b \" c d");}
|
||||
@Test public void Escape() {fxt.Test__to_bry_or_null("a\\+" , "a+");}
|
||||
@Test public void Not() {fxt.Test__to_bry_or_null("a -b" , null);}
|
||||
@Test public void And() {fxt.Test__to_bry_or_null("a + b" , null);}
|
||||
@Test public void Or() {fxt.Test__to_bry_or_null("a , b" , null);}
|
||||
@Test public void Parens() {fxt.Test__to_bry_or_null("(a)" , null);}
|
||||
}
|
||||
class Srch_page_tbl_wkr_fxt {
|
||||
private final Srch_crt_parser crt_parser;
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
public Srch_page_tbl_wkr_fxt() {
|
||||
crt_parser = new Srch_crt_parser(Srch_crt_scanner_syms.Dflt);
|
||||
Srch_text_parser text_parser = new Srch_text_parser();
|
||||
text_parser.Init_for_ttl(gplx.xowa.langs.cases.Xol_case_mgr_.A7());
|
||||
}
|
||||
public void Test__to_bry_or_null(String src_str, String expd) {
|
||||
byte[] src_bry = Bry_.new_a7(src_str);
|
||||
Srch_crt_mgr crt_mgr = crt_parser.Parse_or_invalid(src_bry, Bool_.N);
|
||||
Tfds.Eq(expd, String_.new_u8(Srch_page_tbl_wkr.To_bry_or_null(tmp_bfr, Srch_search_addon.Wildcard__star, crt_mgr)));
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.searchers.wkrs; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.searchers.*;
|
||||
import gplx.dbs.*; import gplx.dbs.stmts.*; import gplx.dbs.percentiles.*;
|
||||
import gplx.xowa.addons.apps.searchs.dbs.*; import gplx.xowa.addons.apps.searchs.searchers.crts.*;
|
||||
class Srch_word_count_wkr extends Percentile_select_base {
|
||||
private Srch_word_tbl word_tbl; private Srch_db_cfg db_cfg;
|
||||
private Srch_crt_itm sub;
|
||||
private int total_link_count, rows_read; private boolean score_too_low;
|
||||
private final Db_stmt_mgr stmt_mgr = new Db_stmt_mgr(); private Db_stmt stmt;
|
||||
public int Get_top_10(Srch_search_ctx ctx, Srch_word_tbl word_tbl, Srch_crt_itm sub) {
|
||||
super.cxl = ctx.Cxl;
|
||||
this.db_cfg = ctx.Addon.Db_mgr().Cfg();
|
||||
super.rng = new Percentile_rng().Init(db_cfg.Word_count(), db_cfg.Link_count_score_max());
|
||||
super.rng.Select_init(10, Percentile_rng.Score_null, Percentile_rng.Score_null, 0);
|
||||
super.rng_log = new Percentile_rng_log(db_cfg.Link_count_score_max());
|
||||
|
||||
rng_log.Init(sub.Raw, 10);
|
||||
this.word_tbl = word_tbl;
|
||||
this.sub = sub;
|
||||
this.total_link_count = 0;
|
||||
this.rows_read = 0;
|
||||
this.score_too_low = false;
|
||||
try {this.Select();}
|
||||
finally {stmt = Db_stmt_.Rls(stmt);}
|
||||
if (score_too_low) return Srch_db_cfg_.Link_count_score_cutoff;
|
||||
else if (rows_read == 1) return total_link_count * 2;
|
||||
else return total_link_count;
|
||||
}
|
||||
@Override protected Db_rdr Rdr__init() {
|
||||
stmt_mgr.Add_crt_int(word_tbl.fld_link_count_score, rng.Score_bgn());
|
||||
stmt_mgr.Add_crt_int(word_tbl.fld_link_count_score, rng.Score_end());
|
||||
stmt_mgr.Add_crt_str(word_tbl.fld_text, sub.Sql_data.Rng_bgn);
|
||||
stmt_mgr.Add_crt_str(word_tbl.fld_text, sub.Sql_data.Rng_end);
|
||||
if (stmt == null) stmt = stmt_mgr.Make_stmt(word_tbl.conn, Fmt__main);
|
||||
stmt_mgr.Fill_stmt_and_clear(stmt);
|
||||
return stmt.Exec_select__rls_manual();
|
||||
}
|
||||
@Override protected boolean Row__read(Db_rdr rdr) {
|
||||
if (!rdr.Move_next()) return false;
|
||||
int cur_link_count = rdr.Read_int(word_tbl.fld_link_count);
|
||||
total_link_count += cur_link_count;
|
||||
++rows_read;
|
||||
return true;
|
||||
}
|
||||
@Override protected boolean Found_enough() {
|
||||
if (rng.Score_bgn() <= db_cfg.Link_count_score_cutoff()) score_too_low = true;
|
||||
return rows_read > 0 || score_too_low;
|
||||
}
|
||||
@Override protected void Rdr__done(boolean rslts_are_enough, boolean rslts_are_done) {
|
||||
// if (rslts_are_enough) gplx.core.consoles.Console_adp__sys.Instance.Write_str(rng_log.To_str_and_clear());
|
||||
}
|
||||
private static Bry_fmt
|
||||
Fmt__main = Bry_fmt.Auto(String_.Concat_lines_nl_skip_last
|
||||
( "SELECT w.link_count"
|
||||
, "FROM search_word w INDEXED BY search_word__link_count_score__word_text"
|
||||
, "WHERE w.link_count_score >= ~{score_min}"
|
||||
, "AND w.link_count_score < ~{score_max}"
|
||||
, "AND w.word_text >= ~{rng_bgn}"
|
||||
, "AND w.word_text < ~{rng_end}"
|
||||
, "LIMIT 1"
|
||||
));
|
||||
}
|
||||
@@ -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.addons.apps.searchs.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.net.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_qarg_mgr {
|
||||
public Srch_qarg_mgr(Srch_ns_mgr ns_mgr) {this.ns_mgr = ns_mgr;}
|
||||
public Srch_ns_mgr Ns_mgr() {return ns_mgr;} private final Srch_ns_mgr ns_mgr;
|
||||
public byte[] Search_raw() {return search_raw;} private byte[] search_raw; public Srch_qarg_mgr Search_raw_(byte[] v) {search_raw = v; return this;}
|
||||
public int Slab_idx() {return slab_idx;} private int slab_idx;
|
||||
public byte[] Cancel() {return cancel;} private byte[] cancel;
|
||||
public boolean Simple_search() {return simple_search;} private boolean simple_search;
|
||||
public Srch_qarg_mgr Clear() {
|
||||
ns_mgr.Clear();
|
||||
this.search_raw = null;
|
||||
this.slab_idx = 0;
|
||||
this.cancel = null;
|
||||
this.simple_search = false;
|
||||
return this;
|
||||
}
|
||||
public void Parse(Gfo_qarg_itm[] qargs_ary) {
|
||||
if (qargs_ary == null) return;
|
||||
int len = qargs_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
Gfo_qarg_itm qarg = qargs_ary[i];
|
||||
byte[] key = qarg.Key_bry();
|
||||
byte tid = qarg_regy.Get_as_byte_or(key, Byte_.Max_value_127);
|
||||
if (tid == Byte_.Max_value_127) { // unknown qarg; check for ns*; EX: &ns0=1&ns8=1; NOTE: lowercase only
|
||||
if (Bry_.Has_at_bgn(key, Ns_bry))
|
||||
ns_mgr.Add_by_parse(key, qarg.Val_bry());
|
||||
}
|
||||
else {
|
||||
switch (tid) {
|
||||
case Uid__search: this.search_raw = Bry_.Replace(qarg.Val_bry(), Byte_ascii.Plus, Byte_ascii.Space); break;
|
||||
case Uid__slab_idx: this.slab_idx = Bry_.To_int_or(qarg.Val_bry(), 0); break;
|
||||
case Uid__cancel: this.cancel = qarg.Val_bry(); break;
|
||||
case Uid__simple_search: this.simple_search = Bry_.Eq(qarg.Val_bry(), Bool_.Y_bry); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ns_mgr.Add_main_if_empty();
|
||||
}
|
||||
private static byte[] Ns_bry = Bry_.new_a7("ns");
|
||||
private static final byte Uid__search = 0, Uid__slab_idx = 1, Uid__cancel = 2, Uid__simple_search = 3;
|
||||
public static final byte[] Bry__slab_idx = Bry_.new_a7("xowa_page_index"), Bry__cancel = Bry_.new_a7("cancel");
|
||||
private static final Hash_adp_bry qarg_regy = Hash_adp_bry.ci_a7()
|
||||
.Add_str_byte("search" , Uid__search)
|
||||
.Add_bry_byte(Bry__slab_idx , Uid__slab_idx)
|
||||
.Add_bry_byte(Bry__cancel , Uid__cancel)
|
||||
.Add_str_byte("simple_search" , Uid__simple_search)
|
||||
;
|
||||
}
|
||||
@@ -1,105 +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.addons.apps.searchs.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.threads.*;
|
||||
import gplx.xowa.files.gui.*; import gplx.xowa.guis.views.*;
|
||||
import gplx.xowa.addons.apps.searchs.specials.htmls.*; import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_special_cmd implements GfoInvkAble, Srch_rslt_cbk, Xog_tab_close_lnr {
|
||||
private final Srch_special_searcher mgr; private final Srch_search_qry qry;
|
||||
public final Xow_wiki wiki; private final Xog_tab_close_mgr tab_close_mgr; private final Xog_js_wkr js_wkr;
|
||||
private Srch_html_row_wkr html_row_wkr; private final boolean async;
|
||||
public final byte[] key; private boolean canceled = false;
|
||||
public Srch_special_cmd(Srch_special_searcher mgr, Srch_search_qry qry, Xow_wiki wiki, Xog_tab_close_mgr tab_close_mgr, Xog_js_wkr js_wkr, byte[] key, boolean search_is_async) {
|
||||
this.mgr = mgr; this.qry = qry; this.wiki = wiki; this.tab_close_mgr = tab_close_mgr; this.js_wkr = js_wkr; this.key = key;
|
||||
this.async = wiki.App().Mode().Tid_is_gui() && search_is_async;
|
||||
}
|
||||
public void On_cancel() {
|
||||
canceled = true;
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "search canceled: key=~{0}", key);
|
||||
this.Hide_cancel_btn();
|
||||
}
|
||||
public void Search() {
|
||||
if (async) { // NOTE: async useful with multiple wikis; allows parallel searches;
|
||||
Srch_html_row_bldr html_row_bldr = new Srch_html_row_bldr(new gplx.xowa.htmls.core.htmls.utls.Xoh_lnki_bldr(wiki.App(), wiki.App().Html__href_wtr()));
|
||||
html_row_wkr = new Srch_html_row_wkr(html_row_bldr, js_wkr, qry.Slab_end - qry.Slab_bgn, wiki.Domain_bry());
|
||||
Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_search_db, this, Invk_search_db).Start();
|
||||
}
|
||||
else
|
||||
Search_db();
|
||||
}
|
||||
private void Search_db() {
|
||||
synchronized (mgr) { // THREAD: needed else multiple Special:Search pages will fail at startup; DATE:2016-03-27
|
||||
tab_close_mgr.Add(this);
|
||||
// DEPRECATE: causes search to fail when using go back / go forward; DELETE:2016-05; DATE:2016-03-27
|
||||
// if (async) {
|
||||
// while (!page.Html_data().Mode_wtxt_shown()) // NOTE:must check to see if page is shown; else async can happen first, and then be overwritten by page_showing; DATE:2015-04-26
|
||||
// Thread_adp_.Sleep(100);
|
||||
// }
|
||||
Srch_search_addon.Get(wiki).Search(qry, this);
|
||||
mgr.Search__done(this);
|
||||
if (canceled) return; // NOTE: must check else throws SWT exception
|
||||
this.Hide_cancel_btn();
|
||||
}
|
||||
Xoa_app_.Usr_dlg().Prog_many("", "", "");
|
||||
}
|
||||
private void Hide_cancel_btn() {Thread_adp_.invk_(gplx.xowa.apps.Xoa_thread_.Key_special_search_cancel, this, Invk_hide_cancel).Start();}
|
||||
private void Hide_cancel_btn_async() {js_wkr.Html_atr_set("xowa_cancel_" + wiki.Domain_str(), "style", "display:none;");}
|
||||
public void On_rslts_found(Srch_search_qry qry, Srch_rslt_list rslts_list, int rslts_bgn, int rslts_end) {
|
||||
if (rslts_list.Rslts_are_first) {
|
||||
if (rslts_bgn > qry.Slab_bgn) {
|
||||
for (int i = qry.Slab_bgn; i < rslts_bgn; ++i) {
|
||||
Srch_rslt_row row = rslts_list.Get_at(i);
|
||||
html_row_wkr.On_rslt_found(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = rslts_bgn; i < rslts_end; ++i) {
|
||||
if (i < qry.Slab_bgn) continue; // do not write row if < slab_bgn; occurs when restarting app directly at page > 1; EX: 11-20 requested; 1-20 returned; do not write 1-10;
|
||||
if (i >= qry.Slab_end) break; // do not write row if > slab_end; occurs when paging forward; EX: 01-10 requested; 1-12 retrieved; do not write 11, 12
|
||||
Srch_rslt_row row = rslts_list.Get_at(i);
|
||||
html_row_wkr.On_rslt_found(row);
|
||||
}
|
||||
}
|
||||
public boolean When_close(Xog_tab_itm tab, Xoa_url url) {
|
||||
if (url != Xoa_url.Null) { // not called by close_tab (Ctrl+W)
|
||||
byte[] cancel_arg = url.Qargs_mgr().Get_val_bry_or(Srch_qarg_mgr.Bry__cancel, null);
|
||||
if (cancel_arg != null) return true; // cancel arg exists; assume tab is not being closed; note that cancel will be processed by Xows_page__special; DATE:2015-04-30
|
||||
}
|
||||
this.On_cancel();
|
||||
return true;
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Invk_search_db)) Search_db();
|
||||
else if (ctx.Match(k, Invk_hide_cancel)) Hide_cancel_btn_async();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
private static final String Invk_search_db = "search_db", Invk_hide_cancel = "hide_cancel";
|
||||
}
|
||||
/*
|
||||
NOTE:show_existing. code needed to show A1
|
||||
EX: search="A*": "A" has 400 words; "A1" has 1;
|
||||
. search 1-20 returns 20 words for A and 1 word for A1.
|
||||
.. the 1st A word has a len of 999 and the 20th A word has a length of 900;
|
||||
.. A1 has a length of 799
|
||||
. search 21-40 returns 20 words for A
|
||||
.. the 21st word has a len of 899 and the 40th has a len of 800
|
||||
.. A1 should show up briefly, and then get pushed off screen by 21-40
|
||||
. search 61-40 returns 20 words for A
|
||||
.. A1 must show up
|
||||
*/
|
||||
@@ -1,126 +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.addons.apps.searchs.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.apps.apis.xowa.specials.*;
|
||||
import gplx.xowa.wikis.domains.*; import gplx.xowa.wikis.domains.crts.*;
|
||||
import gplx.xowa.specials.*; import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.cbks.*;
|
||||
public class Srch_special_page implements Xows_page, GfoInvkAble, GfoEvObj {
|
||||
private final Xoae_app app; private final Xow_domain_itm wiki_domain; private final Xoapi_search search_api;
|
||||
private final Srch_special_searcher search_mgr; private final Srch_qarg_mgr qargs_mgr;
|
||||
private Xow_domain_itm[] search_domain_ary;
|
||||
public Srch_special_page(Xowe_wiki wiki) {
|
||||
this.ev_mgr = GfoEvMgr.new_(this);
|
||||
this.app = wiki.Appe();
|
||||
this.wiki_domain = wiki.Domain_itm();
|
||||
this.search_mgr = new Srch_special_searcher(wiki.Appe().Wiki_mgr());
|
||||
this.search_api = wiki.Appe().Api_root().Special().Search();
|
||||
this.qargs_mgr = new Srch_qarg_mgr(app.Gui_mgr().Search_cfg().Ns_mgr());
|
||||
GfoEvMgr_.SubSame_many(search_api, this, Xoapi_search.Evt_multi_wikis_changed, Xoapi_search.Evt_multi_wikis_changed);
|
||||
}
|
||||
public GfoEvMgr EvMgr() {return ev_mgr;} private final GfoEvMgr ev_mgr;
|
||||
public Xows_special_meta Special__meta() {return Xows_special_meta_.Itm__search;}
|
||||
public void Special__gen(Xow_wiki wikii, Xoa_page pagei, Xoa_url url, Xoa_ttl ttl) {
|
||||
Xowe_wiki wiki = (Xowe_wiki)wikii; Xoae_page page = (Xoae_page)pagei;
|
||||
if (search_domain_ary == null) Multi_wikis_changed();
|
||||
|
||||
// get args from urls while applying defaults from search_cfg
|
||||
Srch_search_cfg search_cfg = wiki.Appe().Gui_mgr().Search_cfg();
|
||||
qargs_mgr.Clear();
|
||||
qargs_mgr.Parse(search_cfg.Args_default());
|
||||
qargs_mgr.Parse(url.Qargs_ary());
|
||||
qargs_mgr.Ns_mgr().Add_main_if_empty();
|
||||
|
||||
// get search_raw
|
||||
byte[] search_raw = qargs_mgr.Search_raw();
|
||||
if (search_raw == null) { // search is not in qarg; EX:Special:Search?search=Earth
|
||||
search_raw = ttl.Leaf_txt_wo_qarg(); // assume search is in leaf; EX: Special:Search/Earth
|
||||
qargs_mgr.Search_raw_(search_raw);
|
||||
}
|
||||
if (Bry_.Len_eq_0(search_raw)) return; // emptry String; exit now, else null ref error; DATE:2015-08-11
|
||||
if ( search_cfg.Auto_wildcard() // add * automatically if option set
|
||||
&& wiki.Db_mgr().Tid() == gplx.xowa.wikis.dbs.Xodb_mgr_sql.Tid_sql // only apply to sql
|
||||
&& Bry_find_.Find_fwd(search_raw, Srch_search_addon.Wildcard__star) == -1 // search term does not have asterisk
|
||||
)
|
||||
search_raw = Bry_.Add(search_raw, Srch_search_addon.Wildcard__star);
|
||||
|
||||
// get page directly from url
|
||||
boolean fulltext_invoked = url.Qargs_mgr().Match(Qarg__fulltext, Qarg__fulltext__y);
|
||||
Xoa_ttl search_ttl = Xoa_ttl.parse(wiki, search_raw);
|
||||
Xoae_page search_page = page;
|
||||
if ( !fulltext_invoked
|
||||
&& !Bry_.Eq(search_raw, Xows_special_meta_.Itm__search.Ttl_bry())) // do not lookup self else stack overflow; happens when going directly to Special:Search (from history)
|
||||
search_page = wiki.Data_mgr().Get_page(search_ttl, false); // try to find page; EX:Special:Search?search=Earth -> en.w:Earth; needed for search suggest
|
||||
|
||||
// page not found, or explicit_search invoked
|
||||
if (search_page.Missing() || fulltext_invoked) {
|
||||
if (qargs_mgr.Cancel() != null) { // cancel any existing searches
|
||||
search_mgr.Search__cancel(qargs_mgr.Cancel());
|
||||
page.Tab_data().Cancel_show_y_();
|
||||
return;
|
||||
}
|
||||
page.Html_data().Html_restricted_n_();
|
||||
page.Html_data().Xtn_search_text_(search_raw);
|
||||
Srch_search_qry qry = Srch_search_qry.New__search_page(search_domain_ary, wiki, search_cfg, qargs_mgr.Simple_search(), search_raw, qargs_mgr.Slab_idx(), search_api.Results_per_page());
|
||||
search_mgr.Search(wiki, page, search_api.Async_db(), search_domain_ary, qry);
|
||||
}
|
||||
// page found; return it;
|
||||
else {
|
||||
wiki.Parser_mgr().Parse(search_page, true);
|
||||
page.Data_raw_(search_page.Data_raw());
|
||||
if (page.Root() != null) // NOTE: null when going from w:Earth -> q:Earth; DATE:2013-03-20
|
||||
page.Root().Data_htm_(search_page.Root().Data_htm());
|
||||
page.Ttl_(search_ttl).Url_(Xoa_url.new_(wiki.Domain_bry(), search_ttl.Full_txt_w_ttl_case())).Redirected_(true);
|
||||
}
|
||||
}
|
||||
private void Multi_wikis_changed() {
|
||||
Xow_domain_crt_itm crt = search_api.Multi_wikis_crt(wiki_domain);
|
||||
this.search_domain_ary = Get_by_crt(app.Usere().Wiki().Xwiki_mgr(), wiki_domain, crt);
|
||||
if (search_domain_ary.length == 0) search_domain_ary = new Xow_domain_itm[] {wiki_domain}; // default to current if bad input
|
||||
Multi_sorts_changed();
|
||||
}
|
||||
private void Multi_sorts_changed() {
|
||||
Xow_domain_crt_itm[] ary = search_api.Multi_sorts_crt(wiki_domain);
|
||||
if (ary == null) return; // default to no sort if bad input
|
||||
Xow_domain_sorter__manual sorter = new Xow_domain_sorter__manual(wiki_domain, ary);
|
||||
Xow_domain_sorter__manual.Sort(sorter, search_domain_ary);
|
||||
}
|
||||
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
|
||||
if (ctx.Match(k, Xoapi_search.Evt_multi_wikis_changed)) Multi_wikis_changed();
|
||||
else if (ctx.Match(k, Xoapi_search.Evt_multi_sorts_changed)) Multi_sorts_changed();
|
||||
else return GfoInvkAble_.Rv_unhandled;
|
||||
return this;
|
||||
}
|
||||
public static final byte Match_tid_all = 0, Match_tid_bgn = 1;
|
||||
public static final byte Version_null = 0, Version_1 = 1, Version_2 = 2;
|
||||
private static final byte[] Qarg__fulltext = Bry_.new_a7("fulltext"), Qarg__fulltext__y = Bry_.new_a7("y");
|
||||
private static Xow_domain_itm[] Get_by_crt(gplx.xowa.wikis.xwikis.Xow_xwiki_mgr xwiki_mgr, Xow_domain_itm cur, gplx.xowa.wikis.domains.crts.Xow_domain_crt_itm crt) {
|
||||
List_adp rv = List_adp_.new_();
|
||||
int len = xwiki_mgr.Len();
|
||||
for (int i = 0; i < len; ++i) {
|
||||
gplx.xowa.wikis.xwikis.Xow_xwiki_itm xwiki = xwiki_mgr.Get_at(i);
|
||||
if ( !xwiki.Offline() // note that filters are broad (*.wiktionary); skip offline wikis which won't be available on system
|
||||
&& xwiki.Domain_tid() != Xow_domain_tid_.Int__home) // note that home is marked "offline" so it won't show up in wikis sidebar
|
||||
continue;
|
||||
Xow_domain_itm domain_itm = Xow_domain_itm_.parse(xwiki.Domain_bry());
|
||||
if (crt.Matches(cur, domain_itm)) rv.Add(domain_itm);
|
||||
}
|
||||
return (Xow_domain_itm[])rv.To_ary_and_clear(Xow_domain_itm.class);
|
||||
}
|
||||
|
||||
public Xows_page Special__clone() {return this;}
|
||||
}
|
||||
@@ -1,53 +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.addons.apps.searchs.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.xowa.wikis.*; import gplx.xowa.wikis.domains.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.specials.htmls.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_special_searcher {
|
||||
private final Xoae_wiki_mgr wiki_mgr;
|
||||
private final Ordered_hash cancel_hash = Ordered_hash_.New_bry();
|
||||
private final Srch_html_page_bldr html_page_bldr = new Srch_html_page_bldr();
|
||||
public Srch_special_searcher(Xoae_wiki_mgr wiki_mgr) {this.wiki_mgr = wiki_mgr;}
|
||||
public void Search(Xow_wiki search_wiki, Xoae_page page, boolean search_is_async, Xow_domain_itm[] domains_ary, Srch_search_qry qry) {
|
||||
Bry_bfr tmp_bfr = Bry_bfr.new_();
|
||||
html_page_bldr.Init_by_wiki(search_wiki, search_wiki.Lang().Num_mgr(), qry);
|
||||
int domains_len = domains_ary.length;
|
||||
for (int i = 0; i < domains_len; ++i) {
|
||||
Xow_domain_itm domain = domains_ary[i];
|
||||
try {
|
||||
Xowe_wiki wiki = wiki_mgr.Get_by_or_make(domain.Domain_bry()); wiki.Init_assert();
|
||||
byte[] key = gplx.langs.htmls.Gfh_utl.Encode_id_as_bry(Bry_.Add(qry.Phrase.Orig, Byte_ascii.Pipe_bry, qry.Ns_mgr.To_hash_key(), Byte_ascii.Pipe_bry, wiki.Domain_bry()));
|
||||
Srch_special_cmd cmd = new Srch_special_cmd(this, qry, wiki, page.Tab_data().Close_mgr(), page.Tab_data().Tab().Html_itm(), key, search_is_async);
|
||||
cancel_hash.Add(key, cmd);
|
||||
cmd.Search(); // do search; note if async, will return immediately
|
||||
html_page_bldr.Bld_tbl(tmp_bfr, new Srch_rslt_list(), key, cmd.wiki.Domain_bry(), search_is_async, qry.Slab_bgn, qry.Slab_end);
|
||||
} 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
|
||||
}
|
||||
|
||||
// generate html; note if async, this will just generate the page header
|
||||
page.Data_raw_(html_page_bldr.Bld_page(tmp_bfr.To_bry_and_clear()));
|
||||
}
|
||||
public void Search__done(Srch_special_cmd cmd) {
|
||||
cancel_hash.Del(cmd.key);
|
||||
}
|
||||
public void Search__cancel(byte[] cmd_key) {
|
||||
Srch_special_cmd cmd = (Srch_special_cmd)cancel_hash.Get_by(cmd_key); // if (cmd == null) return; // ignore false calls to cancel
|
||||
cmd.On_cancel();
|
||||
cancel_hash.Del(cmd.key);
|
||||
}
|
||||
}
|
||||
@@ -1,223 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
//namespace gplx.xowa.addons.apps.searchs.v1s {
|
||||
// import org.junit.*; using gplx.xowa.wikis.tdbs; using gplx.xowa.wikis.data.tbls;
|
||||
// public class Xosrh_core_tst {
|
||||
// @Before public void Init() {fxt.Clear();} private Xos_search_mgr_fxt fxt = new Xos_search_mgr_fxt();
|
||||
// @Test public void Basic() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Test_search_exact("b2", "B2_22", "B2_12", "B2__2");
|
||||
// fxt.Test_search_exact("a" , "A___0");
|
||||
// fxt.Test_search_exact("b1a"); // missing: mid
|
||||
// fxt.Test_search_exact("d"); // missing: end
|
||||
// fxt.Test_search_exact("$"); // missing: bgn
|
||||
// fxt.Test_search_match_bgn("b*", "B3_23", "B2_22", "B1_21", "B3_13", "B2_12", "B1_11", "B3__3", "B2__2", "B1__1");
|
||||
// }
|
||||
// @Test public void Page_size() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Search_mgr().Page_mgr().Itms_per_page_(1);
|
||||
// fxt.Test_search("b*", 0, "B3_23");
|
||||
// fxt.Test_search("b*", 1, "B2_22");
|
||||
// fxt.Test_search("b*", 2, "B1_21");
|
||||
// fxt.Test_search("b*", 3, "B3_13");
|
||||
// }
|
||||
// @Test public void Url() {
|
||||
// Xoa_url url = Xow_url_parser_old.Parse_url(fxt.App(), fxt.Wiki(), "Special:Search/Abc?fulltext=y&xowa_sort=len_desc");
|
||||
// fxt.Search_mgr().Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(Srch_rslt_row_sorter.Tid_len_dsc, fxt.Search_mgr().Args_mgr().Sort_tid());
|
||||
// }
|
||||
// @Test public void Url_arg_title() {// http://en.wikipedia.org/wiki/Special:Search/Earth?fulltext=yes&title=Mars
|
||||
// fxt.Test_url_search_bry("Special:Search?fulltext=y&search=Abc" , "Abc"); // query arg
|
||||
//// fxt.Test_url_search_bry("Special:Search/Abc?fulltext=y" , "Abc"); // leaf
|
||||
// fxt.Test_url_search_bry("Special:Search/Abc?fulltext=y&search=Def" , "Def"); // leaf overrides query arg
|
||||
// }
|
||||
// @Test public void Url_ns() {
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc&ns0=1&ns1=1", "0|1");
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc&ns*=1", "*");
|
||||
// fxt.Test_url__ns("Special:Search?search=Abc", "0");
|
||||
// }
|
||||
// @Test public void Html() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Test_html_by_url("B1", "", String_.Concat_lines_nl
|
||||
// ( "Result '''1''' of '''3''' for '''B1'''<br/>"
|
||||
// , "{|"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=0|<]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=1|>]]"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_sort=len_desc|length]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_sort=title_asc|title]]"
|
||||
// , "|-"
|
||||
// , "| 42 || [[B1 21]]"
|
||||
// , "|-"
|
||||
// , "| 22 || [[B1 11]]"
|
||||
// , "|-"
|
||||
// , "| 2 || [[B1 1]]"
|
||||
// , "|-"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=0|<]]"
|
||||
// , "| [[Special:Search/B1?fulltext=y&xowa_page_index=1|>]]"
|
||||
// , "|}"
|
||||
// ));
|
||||
// }
|
||||
//// @Test public void Page_next() {
|
||||
//// fxt.Init_basic();
|
||||
//// fxt.Search_mgr().Page_size_(1);
|
||||
//// fxt.Test_search(Srch_special_page.Match_tid_all, "B1", 0, "B1 1");
|
||||
//// fxt.Test_search(Srch_special_page.Match_tid_all, "B1", 1, "B1 11");
|
||||
//// }
|
||||
//// @Test public void Misc_url() {
|
||||
//// fxt.Init_basic();
|
||||
//// fxt.Search_mgr().Page_size_(1);
|
||||
//// fxt.Expd_address_page_("Special:Search/B1");
|
||||
//// fxt.Test_search(Srch_special_page.Match_tid_all, "B1", 0, "B1 1");
|
||||
//// }
|
||||
// @Test public void Sort_defaults_to_len_desc() {
|
||||
// fxt.Init_basic();
|
||||
// fxt.Search_mgr().Page_mgr().Itms_per_page_(3);
|
||||
// fxt.Test_search2(Srch_special_page.Match_tid_bgn, "b" , 0, Srch_rslt_row_sorter.Tid_ttl_asc , "B1_11", "B1_21", "B1__1"); // sort by name; note that _ sorts after alphabet
|
||||
// fxt.Test_search2(Srch_special_page.Match_tid_bgn, "b" , 1, Srch_rslt_row_sorter.Tid_none , "B2_12", "B2_22", "B2__2"); // sort by name still; next page should not reset
|
||||
// fxt.Test_search2(Srch_special_page.Match_tid_bgn, "b2" , 0, Srch_rslt_row_sorter.Tid_none , "B2_22", "B2_12", "B2__2"); // sort by len desc; new search should reset
|
||||
// }
|
||||
// }
|
||||
// class Xos_search_mgr_fxt {
|
||||
// Xoae_app app; Xowe_wiki wiki; Bry_bfr bfr = Bry_bfr.reset_(500); Srch_special_page search_mgr;
|
||||
// public Xoae_app App() {return app;}
|
||||
// public Xowe_wiki Wiki() {return wiki;}
|
||||
// public Xobl_regy_itm regy_itm_(int id, String bgn, String end, int count) {return new Xobl_regy_itm(id, Bry_.new_u8(bgn), Bry_.new_u8(end), count);}
|
||||
// public Xowd_page_itm data_ttl_(int id, String ttl) {return data_ttl_(id, 0, 0, false, 0, ttl);}
|
||||
// public Xowd_page_itm data_ttl_(int id, int fil, int row, boolean redirect, int len, String ttl) {return new Xowd_page_itm().Init(id, Bry_.new_u8(ttl), redirect, len, fil, row);}
|
||||
// public Xowd_page_itm data_id_(int id, String ttl) {return data_id_(id, Xow_ns_.Tid__main, ttl);}
|
||||
// public Xowd_page_itm data_id_(int id, int ns, String ttl) {return new Xowd_page_itm().Id_(id).Ns_id_(ns).Ttl_page_db_(Bry_.new_u8(ttl)).Text_db_id_(0).Text_len_(0);}
|
||||
// public Xobl_search_ttl data_sttl_(String word, params int[] ids) {return new Xobl_search_ttl(Bry_.new_u8(word), data_ttl_word_page_ary_(ids));}
|
||||
// public Xobl_search_ttl_page[] data_ttl_word_page_ary_(params int[] ids) {
|
||||
// int ids_len = ids.length;
|
||||
// Xobl_search_ttl_page[] rv = new Xobl_search_ttl_page[ids_len];
|
||||
// for (int i = 0; i < ids_len; i++) {
|
||||
// int id = ids[i];
|
||||
// rv[i] = new Xobl_search_ttl_page(id, id * 2);
|
||||
// }
|
||||
// return rv;
|
||||
// }
|
||||
// public void Init_regy_site(byte dir_info, params Xobl_regy_itm[] ary) {Init_regy(wiki.Tdb_fsys_mgr().Url_site_reg(dir_info), ary);}
|
||||
// public void Init_regy_ns (String ns_num, byte tid, params Xobl_regy_itm[] ary) {Init_regy(wiki.Tdb_fsys_mgr().Url_ns_reg(ns_num, tid), ary);}
|
||||
// public void Init_regy(Io_url url, Xobl_regy_itm[] ary) {
|
||||
// int ary_len = ary.length;
|
||||
// for (int i = 0; i < ary_len; i++) {
|
||||
// Xobl_regy_itm itm = ary[i];
|
||||
// itm.Srl_save(tmp_bfr);
|
||||
// }
|
||||
// Io_mgr.Instance.SaveFilBfr(url, tmp_bfr);
|
||||
// } private Bry_bfr tmp_bfr = Bry_bfr.reset_(255);
|
||||
// public void Init_data(Io_url fil, params Xobl_data_itm[] ary) {
|
||||
// Xob_xdat_file xdat_file = new Xob_xdat_file();
|
||||
// int ary_len = ary.length;
|
||||
// for (int i = 0; i < ary_len; i++) {
|
||||
// Xobl_data_itm itm = ary[i];
|
||||
// itm.Srl_save(tmp_bfr);
|
||||
// xdat_file.Insert(bfr, tmp_bfr.To_bry_and_clear());
|
||||
// }
|
||||
// xdat_file.Save(fil);
|
||||
// }
|
||||
// public void Init_basic() {
|
||||
// this.Init_regy_ns(wiki.Ns_mgr().Ns_main().Num_str(), Xotdb_dir_info_.Tid_search_ttl, this.regy_itm_(0, "A", "C", 5));
|
||||
// this.Init_data(wiki.Tdb_fsys_mgr().Url_ns_fil(Xotdb_dir_info_.Tid_search_ttl, Xow_ns_.Tid__main, 0)
|
||||
// , this.data_sttl_("a" , 0)
|
||||
// , this.data_sttl_("b1" , 1, 11, 21)
|
||||
// , this.data_sttl_("b2" , 2, 12, 22)
|
||||
// , this.data_sttl_("b3" , 3, 13, 23)
|
||||
// , this.data_sttl_("c" , 4)
|
||||
// );
|
||||
// this.Init_regy_site(Xotdb_dir_info_.Tid_id, this.regy_itm_(0, "A", "C", 11));
|
||||
// this.Init_data(wiki.Tdb_fsys_mgr().Url_site_fil(Xotdb_dir_info_.Tid_id, 0)
|
||||
// , this.data_id_( 0, "A___0")
|
||||
// , this.data_id_( 1, "B1__1")
|
||||
// , this.data_id_( 2, "B2__2")
|
||||
// , this.data_id_( 3, "B3__3")
|
||||
// , this.data_id_( 4, "C___4")
|
||||
// , this.data_id_(11, "B1_11")
|
||||
// , this.data_id_(12, "B2_12")
|
||||
// , this.data_id_(13, "B3_13")
|
||||
// , this.data_id_(21, "B1_21")
|
||||
// , this.data_id_(22, "B2_22")
|
||||
// , this.data_id_(23, "B3_23")
|
||||
// );
|
||||
// search_mgr.Page_mgr().Ns_mgr().Add_all(); // WORKAROUND: xdat fmt does not store ns with search data; pages will be retrieved with ns_id = null; force ns_all (instead of allowing ns_main default);
|
||||
// }
|
||||
// public void Clear() {
|
||||
// Io_mgr.Instance.InitEngine_mem();
|
||||
// app = Xoa_app_fxt.Make__app__edit();
|
||||
// wiki = Xoa_app_fxt.Make__wiki__edit(app);
|
||||
// search_mgr = wiki.Special_mgr().Page_search();
|
||||
// wiki.Appe().Gui_mgr().Search_suggest_mgr().Args_default_str_("ns*=1"); // WORKAROUND: xdat fmt does not store ns with search data; pages will be retrieved with ns_id = null; force ns_all (instead of allowing ns_main default);
|
||||
// }
|
||||
// public Srch_special_page Search_mgr() {return search_mgr;}
|
||||
// public void Test_url_search_bry(String url_str, String expd) {
|
||||
// Xoa_url url = Xow_url_parser_old.Parse_url(app, wiki, url_str);
|
||||
// search_mgr.Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(expd, String_.new_u8(search_mgr.Args_mgr().Search_bry()));
|
||||
// }
|
||||
// public void Test_url__ns(String url_str, String expd) {
|
||||
// Xoa_url url = Xow_url_parser_old.Parse_url(app, wiki, url_str);
|
||||
// search_mgr.Args_mgr().Clear().Parse(url.Args());
|
||||
// Tfds.Eq(expd, String_.new_a7(search_mgr.Args_mgr().Ns_mgr().Xto_hash_key()));
|
||||
// }
|
||||
// public void Test_search_exact(String ttl_str, params String[] expd_ary) {Test_search(ttl_str, 0, expd_ary);}
|
||||
// public void Test_search_match_bgn(String ttl_str, params String[] expd_ary) {Test_search(ttl_str, 0, expd_ary);}
|
||||
// public void Test_search(String ttl_str, int page_idx, params String[] expd_ary) {
|
||||
// byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
// Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b128();
|
||||
// Xosrh_rslt_grp page = search_mgr.Page_mgr().Search(bfr, wiki, ttl_bry, page_idx, search_mgr.Page_mgr());
|
||||
// bfr.Mkr_rls();
|
||||
// Tfds.Eq_ary(expd_ary, Search_itms_to_int_ary(page));
|
||||
// }
|
||||
// public void Test_html_by_url(String ttl_str, String args_str, String expd_html) {
|
||||
// wiki.Init_needed_(false);
|
||||
// byte[] ttl_bry = Bry_.new_a7(ttl_str);
|
||||
// Xoa_ttl ttl = Xoa_ttl.parse(wiki, ttl_bry);
|
||||
// Xoae_page page = Xoae_page.New_test(wiki, ttl);
|
||||
// byte[] url_bry = Bry_.new_a7("http://en.wikipedia.org/wiki/Special:Search/" + ttl_str + args_str);
|
||||
// Xoa_url url = wiki.Appe().Url_parser().Parse(url_bry);
|
||||
// search_mgr.Special__gen(url, page, wiki, ttl);
|
||||
// Tfds.Eq_str_lines(expd_html, String_.new_u8(page.Root().Data_htm()));
|
||||
// }
|
||||
// public void Test_search2(byte match_tid, String ttl_str, int page_idx, byte sort_tid, params String[] expd_ary) {
|
||||
// Bry_bfr bfr = wiki.Utl__bfr_mkr().Get_b128();
|
||||
// Xow_url_parser_old url_parser = new Xow_url_parser_old();
|
||||
// byte[] url_raw = Bry_.new_a7("Special:Search/" + ttl_str + ((match_tid == Srch_special_page.Match_tid_all) ? "" : "*") + "?fulltext=y" + Srch_rslt_row_sorter.Xto_url_arg(sort_tid) + "&xowa_page_size=1&xowa_page_index=" + page_idx);
|
||||
// Xoa_url url = url_parser.Parse(url_raw);
|
||||
// Xoa_ttl ttl = Xoa_ttl.parse(wiki, url_raw);
|
||||
// Xoae_page page = wiki.Ctx().Page();
|
||||
// search_mgr.Special__gen(url, page, wiki, ttl);
|
||||
// Xosrh_rslt_grp cur_grp = search_mgr.Cur_grp();
|
||||
// bfr.Mkr_rls();
|
||||
// Tfds.Eq_ary(expd_ary, Search_itms_to_int_ary(cur_grp));
|
||||
// }
|
||||
// String[] Search_itms_to_int_ary(Xosrh_rslt_grp page) {
|
||||
// int itms_len = page.Itms_len();
|
||||
// String[] rv = new String[itms_len];
|
||||
// for (int i = 0; i < itms_len; i++) {
|
||||
// Xowd_page_itm itm = page.Itms_get_at(i);
|
||||
// rv[i] = String_.new_u8(itm.Ttl_page_db());
|
||||
// }
|
||||
// return rv;
|
||||
// }
|
||||
// }
|
||||
// interface Xobl_data_itm {
|
||||
// void Srl_save(Bry_bfr bfr);
|
||||
// }
|
||||
//}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*;
|
||||
import gplx.core.primitives.*; import gplx.xowa.langs.*;
|
||||
import gplx.xowa.wikis.domains.*; import gplx.xowa.wikis.domains.crts.*;
|
||||
public class Xow_domain_sorter__manual implements gplx.core.lists.ComparerAble {
|
||||
private final Xow_domain_itm cur_domain;
|
||||
private final Xow_domain_crt_itm[] ary; private final int ary_len;
|
||||
public Xow_domain_sorter__manual(Xow_domain_itm cur_domain, Xow_domain_crt_itm[] ary) {
|
||||
this.cur_domain = cur_domain; this.ary = ary; this.ary_len = ary.length;
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain_itm lhs = (Xow_domain_itm)lhsObj;
|
||||
Xow_domain_itm rhs = (Xow_domain_itm)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs);
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs);
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(lhs.Domain_bry(), rhs.Domain_bry());
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(Xow_domain_itm domain) {
|
||||
int sort_idx = domain.Sort_idx(); if (sort_idx != -1) return sort_idx;
|
||||
sort_idx = Int_.Max_value;
|
||||
for (int i = 0; i < ary_len; ++i) {
|
||||
Xow_domain_crt_itm crt = ary[i];
|
||||
if (crt.Matches(cur_domain, domain)) {sort_idx = i; break;}
|
||||
}
|
||||
domain.Sort_idx_(sort_idx);
|
||||
return sort_idx;
|
||||
}
|
||||
public static void Sort(Xow_domain_sorter__manual sorter, Xow_domain_itm[] ary) {
|
||||
int len = ary.length;
|
||||
for (int i = 0; i < len; ++i)
|
||||
ary[i].Sort_idx_(-1);
|
||||
Array_.Sort(ary, sorter);
|
||||
}
|
||||
}
|
||||
class Xow_domain_sorter__manual_tid implements gplx.core.lists.ComparerAble {
|
||||
private final Hash_adp sort_hash = Hash_adp_.new_(); private final Int_obj_ref sort_key = Int_obj_ref.neg1_();
|
||||
public Xow_domain_sorter__manual_tid(int[] id_ary) {
|
||||
int len = id_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int id_itm = id_ary[i];
|
||||
sort_hash.Add_if_dupe_use_nth(Int_obj_ref.new_(id_itm), Int_obj_ref.new_(i));
|
||||
}
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain_itm lhs = (Xow_domain_itm)lhsObj;
|
||||
Xow_domain_itm rhs = (Xow_domain_itm)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs.Domain_type_id());
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs.Domain_type_id());
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(Xow_domain_tid_.Get_type_as_bry(lhs.Domain_type_id()), Xow_domain_tid_.Get_type_as_bry(rhs.Domain_type_id()));
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(int tid) {
|
||||
Object o = sort_hash.Get_by(sort_key.Val_(tid));
|
||||
return o == null ? -1 : ((Int_obj_ref)o).Val();
|
||||
}
|
||||
public static Xow_domain_sorter__manual_tid new_(byte[]... id_brys) {
|
||||
int len = id_brys.length;
|
||||
int[] id_ints = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] id_bry = id_brys[i];
|
||||
int id_int = Xow_domain_tid_.Get_type_as_tid(id_bry);
|
||||
id_ints[i] = id_int;
|
||||
}
|
||||
return new Xow_domain_sorter__manual_tid(id_ints);
|
||||
}
|
||||
}
|
||||
class Xow_domain_sorter__manual_lang implements gplx.core.lists.ComparerAble {
|
||||
private final Hash_adp sort_hash = Hash_adp_.new_(); private final Int_obj_ref sort_key = Int_obj_ref.neg1_();
|
||||
public Xow_domain_sorter__manual_lang(int[] id_ary) {
|
||||
int len = id_ary.length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
int id_int = id_ary[i];
|
||||
sort_hash.Add_if_dupe_use_nth(Int_obj_ref.new_(id_int), Int_obj_ref.new_(i));
|
||||
}
|
||||
}
|
||||
public int compare(Object lhsObj, Object rhsObj) {
|
||||
Xow_domain_itm lhs = (Xow_domain_itm)lhsObj;
|
||||
Xow_domain_itm rhs = (Xow_domain_itm)rhsObj;
|
||||
int lhs_sort = Get_sort_idx_or_neg1(lhs.Lang_actl_uid());
|
||||
int rhs_sort = Get_sort_idx_or_neg1(rhs.Lang_actl_uid());
|
||||
if (lhs_sort == -1 && rhs_sort != -1) return rhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort == -1) return lhs_sort;
|
||||
else if (lhs_sort != -1 && rhs_sort != -1) return Int_.Compare(lhs_sort, rhs_sort);
|
||||
else return Bry_.Compare(lhs.Lang_actl_key(), rhs.Lang_actl_key());
|
||||
}
|
||||
private int Get_sort_idx_or_neg1(int tid) {
|
||||
Object o = sort_hash.Get_by(sort_key.Val_(tid));
|
||||
return o == null ? -1 : ((Int_obj_ref)o).Val();
|
||||
}
|
||||
public static Xow_domain_sorter__manual_lang new_(byte[]... id_brys) {
|
||||
int len = id_brys.length;
|
||||
int[] id_ints = new int[len];
|
||||
for (int i = 0; i < len; ++i) {
|
||||
byte[] id_bry = id_brys[i];
|
||||
int id_int = Xol_lang_stub_.Get_by_key_or_intl(id_bry).Id();
|
||||
id_ints[i] = id_int;
|
||||
}
|
||||
return new Xow_domain_sorter__manual_lang(id_ints);
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.specials.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.specials.*;
|
||||
import gplx.core.brys.fmtrs.*;
|
||||
import gplx.langs.htmls.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.langs.numbers.*;
|
||||
import gplx.xowa.addons.apps.searchs.specials.*; import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_html_page_bldr {
|
||||
private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
|
||||
private Srch_search_qry qry; private Xow_wiki wiki; private Xol_num_mgr num_mgr;
|
||||
private int slab_idx;
|
||||
private Xoh_lnki_bldr lnki_bldr; private Xoh_anchor_kv_bldr self_lnkr = new Xoh_anchor_kv_bldr(); private Srch_html_row_bldr html_row_bldr;
|
||||
public void Init_by_wiki(Xow_wiki wiki, Xol_num_mgr num_mgr, Srch_search_qry qry) {
|
||||
this.wiki = wiki; this.num_mgr = num_mgr; this.qry = qry;
|
||||
this.lnki_bldr = wiki.App().Html__lnki_bldr();
|
||||
int slab_len = qry.Slab_end - qry.Slab_bgn;
|
||||
this.slab_idx = qry.Slab_bgn / slab_len;
|
||||
this.html_row_bldr = new Srch_html_row_bldr(lnki_bldr);
|
||||
self_lnkr.Init_w_qarg(tmp_bfr.Add(Bry__special_search).Add(qry.Phrase.Orig).Add(Bry__fulltext).To_bry_and_clear());
|
||||
}
|
||||
public byte[] Bld_page(byte[] html_tbls_bry) {
|
||||
byte[] rslts_hdr = fmtr_rslts.Bld_bry_many(tmp_bfr, num_mgr.Format_num(qry.Slab_bgn + List_adp_.Base1), num_mgr.Format_num(qry.Slab_end), qry.Phrase.Orig);
|
||||
byte[] option_link = lnki_bldr.Href_(Bry_.new_a7("home"), wiki.Ttl_parse(Bry_.new_a7("Options/Search"))).Img_16x16(Xoh_img_path.Img_option).Bld_to_bry(); // HOME
|
||||
fmtr_page.Bld_bfr_many(tmp_bfr, rslts_hdr, option_link, Bld_paging_link(Bool_.N), Bld_paging_link(Bool_.Y), html_tbls_bry);
|
||||
return tmp_bfr.To_bry_and_clear();
|
||||
}
|
||||
public void Bld_tbl(Bry_bfr bfr, Srch_rslt_list rslt_list, byte[] cmd_key, byte[] wiki_domain, boolean searching_db, int slab_bgn, int slab_end) {
|
||||
html_row_bldr.Init(rslt_list, slab_bgn, slab_end);
|
||||
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 ? Bld_cancel_link(wiki_domain, cmd_key) : Bry_.Empty, Bry_hdr_len, Bry_hdr_ttl, Srch_html_row_wkr.Gen_insert_key(wiki_domain), html_row_bldr);
|
||||
}
|
||||
private byte[] Bld_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(Srch_qarg_mgr.Bry__slab_idx, slab_idx).Add_bry(Srch_qarg_mgr.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[] Bld_paging_link(boolean fwd) {
|
||||
byte[] title = null, img_path = Bry_.Empty;
|
||||
boolean img_pos_is_left = true;
|
||||
int qarg_slab_idx = slab_idx;
|
||||
if (fwd) {
|
||||
++qarg_slab_idx;
|
||||
// if (slab_idx > qry.Page_max()) return Gfh_entity_.Nbsp_num_bry;
|
||||
img_pos_is_left = false;
|
||||
img_path = Xoh_img_path.Img_go_fwd;
|
||||
title = Bry_paging_fwd;
|
||||
}
|
||||
else {
|
||||
--qarg_slab_idx;
|
||||
if (qarg_slab_idx < 0) return Gfh_entity_.Nbsp_num_bry;
|
||||
img_path = Xoh_img_path.Img_go_bwd;
|
||||
title = Bry_paging_bwd;
|
||||
}
|
||||
return lnki_bldr.Title_(title).Href_(wiki, self_lnkr.Add_int(Srch_qarg_mgr.Bry__slab_idx, qarg_slab_idx).Bld_to_bry()).Img_16x16(img_path).Img_pos_is_left_(img_pos_is_left).Caption_(title).Bld_to_bry();
|
||||
}
|
||||
private static final Bry_fmtr fmtr_page = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "~{rslts_hdr}<span style='margin-left:10px'>~{option_link}</span>"
|
||||
, "<div id='xowa_panel_top' style='width:60%;'><div style='float:right;'><span>~{bwd_a}</span><span style='margin-left:10px'>~{fwd_a}</span></div></div>~{tbls}"
|
||||
, "<div id='xowa_panel_bot' style='width:60%;'><div style='float:right;'><span>~{bwd_a}</span><span style='margin-left:10px'>~{fwd_a}</span></div></div>"
|
||||
), "rslts_hdr", "option_link", "bwd_a", "fwd_a", "tbls");
|
||||
private static final Bry_fmtr fmtr_tbl = Bry_fmtr.new_(String_.Concat_lines_nl_skip_last
|
||||
( "<table class='wikitable sortable' style='width:60%;'>"
|
||||
, " <tr>"
|
||||
, " <th colspan='2' style='text-align:left'>~{wiki}<span style='float:right'>~{cancel}</span>"
|
||||
, " </th>"
|
||||
, " </tr>"
|
||||
, " <tr>"
|
||||
, " <th width='100'>~{hdr_len}"
|
||||
, " </th>"
|
||||
, " <th>~{hdr_ttl}"
|
||||
, " </th>"
|
||||
, " </tr>~{rows}"
|
||||
, " <tr id='~{insert_key}' style='display:none;'>"
|
||||
, " </tr>"
|
||||
, "</table>"
|
||||
), "wiki", "cancel", "hdr_len", "hdr_ttl", "insert_key", "rows");
|
||||
private static final Bry_fmtr fmtr_rslts = Bry_fmtr.new_("Results <b>~{bgn}</b> of <b>~{end}</b> for <b>~{raw}</b>", "bgn", "end", "raw");
|
||||
private static final byte[] Bry_paging_fwd = Bry_.new_a7("Next"), Bry_paging_bwd = Bry_.new_a7("Previous"), Bry_cancel = Bry_.new_a7("Stop searching")
|
||||
, Bry_hdr_len = Bry_.new_a7("Page score"), Bry_hdr_ttl = Bry_.new_a7("Page title")
|
||||
;
|
||||
private final byte[] Bry__special_search = Bry_.new_a7("Special:Search/"), Bry__fulltext = Bry_.new_a7("?fulltext=y");
|
||||
}
|
||||
@@ -1,85 +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.addons.apps.searchs.specials.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.specials.*;
|
||||
import org.junit.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.wikis.tdbs.*;
|
||||
import gplx.xowa.wikis.domains.*;
|
||||
import gplx.xowa.wikis.data.tbls.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_html_page_bldr_tst {
|
||||
@Before public void init() {fxt.Clear();} private Srch_html_page_bldr_fxt fxt = new Srch_html_page_bldr_fxt();
|
||||
@Test public void Paging() {
|
||||
fxt.Test_paging(Bool_.Y, 1, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D2' title='Next'>Next<img src='file:///mem/xowa/bin/any/xowa/file/app.general/go_fwd.png' width='16' height='16'/></a>");
|
||||
fxt.Test_paging(Bool_.N, 1, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D0' title='Previous'><img src='file:///mem/xowa/bin/any/xowa/file/app.general/go_bwd.png' width='16' height='16'/>Previous</a>");
|
||||
fxt.Test_paging(Bool_.Y, 2, "<a href='/site/en.wikipedia.org/wiki/Special:Search/A%3Ffulltext%3Dy%26xowa_page_index%3D3' title='Next'>Next<img src='file:///mem/xowa/bin/any/xowa/file/app.general/go_fwd.png' width='16' height='16'/></a>");
|
||||
fxt.Test_paging(Bool_.N, 0, " ");
|
||||
}
|
||||
@Test public void Rows() {
|
||||
fxt.Test_rows(new Srch_rslt_row[] {fxt.Make_row(10, "A"), fxt.Make_row(20, "B")}, String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr id='w.7C1'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>10"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'><a href='/site/w/wiki/A' title='A'>A</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
, " <tr id='w.7C2'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>20"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'><a href='/site/w/wiki/B' title='B'>B</a>"
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
));
|
||||
}
|
||||
}
|
||||
class Srch_html_page_bldr_fxt {
|
||||
private Xoae_app app; private Xowe_wiki wiki; private Srch_html_page_bldr html_mgr; private final Bry_bfr tmp_bfr = Bry_bfr.new_(255);
|
||||
private int page_id;
|
||||
public Srch_html_page_bldr_fxt Clear() {
|
||||
if (app == null) {
|
||||
app = Xoa_app_fxt.Make__app__edit();
|
||||
wiki = Xoa_app_fxt.Make__wiki__edit(app);
|
||||
html_mgr = new Srch_html_page_bldr();
|
||||
}
|
||||
page_id = 0;
|
||||
return this;
|
||||
}
|
||||
public void Test_paging(boolean fwd, int slab_idx, String expd) {
|
||||
byte[] search_orig = Bry_.new_a7("A");
|
||||
Srch_search_qry qry = Srch_search_qry.New__search_page(Xow_domain_itm_.Ary_empty, wiki, app.Gui_mgr().Search_cfg(), Bool_.N, search_orig, slab_idx, 100);
|
||||
html_mgr.Init_by_wiki(wiki, wiki.Lang().Num_mgr(), qry);
|
||||
byte[] paging_link = html_mgr.Bld_paging_link(fwd);
|
||||
Tfds.Eq(expd, String_.new_a7(paging_link));
|
||||
}
|
||||
public void Test_rows(Srch_rslt_row[] rows, String expd) {
|
||||
Srch_rslt_list rslts = new Srch_rslt_list();
|
||||
Srch_html_row_bldr row_bldr = new Srch_html_row_bldr(wiki.App().Html__lnki_bldr());
|
||||
row_bldr.Init(rslts, 0, rows.length);
|
||||
for (int i = 0; i < rows.length; ++i)
|
||||
rslts.Add(rows[i]);
|
||||
row_bldr.Bfr_arg__add(tmp_bfr);
|
||||
Tfds.Eq_str_lines(expd, tmp_bfr.To_str_and_clear());
|
||||
}
|
||||
public Srch_rslt_row Make_row(int len, String ttl_str) {
|
||||
byte[] wiki_bry = Bry_.new_a7("w");
|
||||
byte[] ttl_bry = Bry_.new_u8(ttl_str);
|
||||
++page_id;
|
||||
Srch_rslt_row rv = new Srch_rslt_row(Srch_rslt_row.Bld_key(wiki_bry, page_id), wiki_bry, wiki.Ttl_parse(ttl_bry), gplx.xowa.wikis.nss.Xow_ns_.Tid__main, ttl_bry, page_id, len, len, Srch_rslt_row.Page_redirect_id_null);
|
||||
rv.Page_ttl_highlight = rv.Page_ttl.Full_txt_w_ttl_case();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
XOWA: the XOWA Offline Wiki Application
|
||||
Copyright (C) 2012 gnosygnu@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package gplx.xowa.addons.apps.searchs.specials.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.specials.*;
|
||||
import gplx.xowa.htmls.core.htmls.utls.*; import gplx.langs.htmls.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_html_row_bldr implements gplx.core.brys.Bfr_arg {
|
||||
private final Xoh_lnki_bldr lnki_bldr;
|
||||
private Srch_rslt_list rslt_list; private int slab_bgn, slab_end;
|
||||
private final Object thread_lock = new Object();
|
||||
public Srch_html_row_bldr(Xoh_lnki_bldr lnki_bldr) {this.lnki_bldr = lnki_bldr;}
|
||||
public Srch_html_row_bldr Init(Srch_rslt_list rslt_list, int slab_bgn, int slab_end) {this.rslt_list = rslt_list; this.slab_bgn = slab_bgn; this.slab_end = slab_end; return this;}
|
||||
public void Bfr_arg__add(Bry_bfr bfr) { // <a href="/wiki/A" title="A" class="xowa-visited">A</a>
|
||||
int rslts_len = rslt_list.Len();
|
||||
for (int i = slab_bgn; i < slab_end; ++i) {
|
||||
if (i >= rslts_len) return;
|
||||
Srch_rslt_row row = rslt_list.Get_at(i);
|
||||
Bld_html(bfr, row);
|
||||
}
|
||||
}
|
||||
public void Bld_html(Bry_bfr bfr, Srch_rslt_row row) {
|
||||
synchronized (thread_lock) {
|
||||
lnki_bldr.Href_(row.Wiki_bry, row.Page_ttl);
|
||||
lnki_bldr.Title_(row.Page_ttl.Full_txt_w_ttl_case());
|
||||
lnki_bldr.Caption_direct_(row.Page_ttl_display(Bool_.Y));
|
||||
fmtr.Bld_many(bfr, Gfh_utl.Encode_id_as_str(row.Key), row.Page_score, lnki_bldr.Bld_to_bry());
|
||||
}
|
||||
}
|
||||
public Bry_fmt Fmtr() {return fmtr;} private final Bry_fmt fmtr = Bry_fmt.Auto(String_.Concat_lines_nl_skip_last
|
||||
( ""
|
||||
, " <tr id='~{page_key}'>"
|
||||
, " <td style='padding-right:5px; vertical-align:top; text-align:right;'>~{page_len}"
|
||||
, " </td>"
|
||||
, " <td style='padding-left:5px; vertical-align:top;'>~{lnki}" // SERVER:"<a href='"; DATE:2015-04-16
|
||||
, " </td>"
|
||||
, " </tr>"
|
||||
));
|
||||
}
|
||||
@@ -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.addons.apps.searchs.specials.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.specials.*;
|
||||
import gplx.langs.htmls.*; import gplx.xowa.files.gui.*;
|
||||
import gplx.xowa.addons.apps.searchs.searchers.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_html_row_wkr {
|
||||
private final Srch_html_row_bldr html_row_bldr; private final Xog_js_wkr js_wkr;
|
||||
private final Srch_rslt_row[] rows; private final int rows_len;
|
||||
private final Bry_bfr bfr = Bry_bfr.new_(255);
|
||||
private final byte[] insert_new_key;
|
||||
public Srch_html_row_wkr(Srch_html_row_bldr html_row_bldr, Xog_js_wkr js_wkr, int slab_len, byte[] wiki) {
|
||||
this.html_row_bldr = html_row_bldr; this.js_wkr = js_wkr;
|
||||
this.rows = new Srch_rslt_row[slab_len];
|
||||
this.rows_len = slab_len;
|
||||
this.insert_new_key = Gen_insert_key(wiki);
|
||||
}
|
||||
public void Set(int i, Srch_rslt_row row) {rows[i] = row;}
|
||||
public void On_rslt_found(Srch_rslt_row new_row) {
|
||||
Srch_rslt_row last_row = rows[rows_len - 1];
|
||||
if (last_row != null) {
|
||||
if (Compare(new_row, last_row) == CompareAble_.MoreOrSame) return; // new_row is < last_row; exit
|
||||
}
|
||||
int new_row_slot = Find_insert_slot(new_row); if (new_row_slot == -1) return;
|
||||
Srch_rslt_row 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_bldr.Bld_html(bfr, new_row);
|
||||
String html_tbl = bfr.To_str_and_clear();
|
||||
js_wkr.Html_elem_append_above(Gfh_utl.Encode_id_as_str(insert_key), html_tbl);
|
||||
if (last_row != null) {
|
||||
js_wkr.Html_elem_replace_html(Gfh_utl.Encode_id_as_str(last_row.Key), "");
|
||||
}
|
||||
}
|
||||
private int Find_insert_slot(Srch_rslt_row new_row) {
|
||||
for (int i = 0; i < rows_len; ++i) {
|
||||
Srch_rslt_row cur_row = rows[i];
|
||||
if (cur_row == null) return i;
|
||||
if (Compare(new_row, cur_row) == CompareAble_.Less) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private void Displace(int new_row_slot, Srch_rslt_row new_row) {
|
||||
for (int i = rows_len - 2; i >= new_row_slot; --i) {
|
||||
rows[i + 1] = rows[i];
|
||||
}
|
||||
rows[new_row_slot] = new_row;
|
||||
}
|
||||
private int Compare(Srch_rslt_row lhs, Srch_rslt_row rhs) {
|
||||
return -Int_.Compare(lhs.Page_score, rhs.Page_score);
|
||||
}
|
||||
public static byte[] Gen_insert_key(byte[] wiki) {return Bry_.Add(Bry_insert_key, wiki);}
|
||||
private static final byte[] Bry_insert_key = Bry_.new_a7("xowa_insert_");
|
||||
}
|
||||
@@ -1,66 +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.addons.apps.searchs.specials.htmls; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.searchs.*; import gplx.xowa.addons.apps.searchs.specials.*;
|
||||
import org.junit.*; import gplx.xowa.htmls.core.htmls.utls.*; import gplx.xowa.files.gui.*; import gplx.xowa.addons.apps.searchs.searchers.rslts.*;
|
||||
public class Srch_rslt_cbk_tst {
|
||||
@Before public void init() {fxt.Clear();} private Srch_rslt_cbk_fxt fxt = new Srch_rslt_cbk_fxt();
|
||||
@Test public void Basic() {
|
||||
fxt.Test_add(fxt.Make_rslt(50, "L"), fxt.Make_args_append("xowa_insert_w" , "w.7CL")); // insert new
|
||||
fxt.Test_add(fxt.Make_rslt(30, "N"), fxt.Make_args_append("xowa_insert_w" , "w.7CN")); // insert below last
|
||||
fxt.Test_add(fxt.Make_rslt(70, "J"), fxt.Make_args_append("w.7CL" , "w.7CJ")); // insert above first
|
||||
fxt.Test_add(fxt.Make_rslt(60, "K"), fxt.Make_args_append("w.7CL" , "w.7CK")); // insert above mid
|
||||
fxt.Test_add(fxt.Make_rslt(40, "M"), fxt.Make_args_append("w.7CN" , "w.7CM")); // insert below mid
|
||||
fxt.Test_add(fxt.Make_rslt(10, "P")); // insert noop
|
||||
fxt.Test_add(fxt.Make_rslt(80, "I"), fxt.Make_args_append("w.7CJ" , "w.7CI") , fxt.Make_args_replace("w.7CN")); // insert displace all
|
||||
fxt.Test_add(fxt.Make_rslt(61, "K1"), fxt.Make_args_append("w.7CK" , "w.7CK1"), fxt.Make_args_replace("w.7CM")); // insert displace mid
|
||||
}
|
||||
}
|
||||
class Srch_rslt_cbk_fxt {
|
||||
private Srch_html_row_bldr html_row; private static final byte[] Bry_enwiki = Bry_.new_a7("w");
|
||||
private Srch_html_row_wkr async;
|
||||
private Xog_js_wkr__log js_wkr = new Xog_js_wkr__log();
|
||||
private Xowe_wiki wiki;
|
||||
private int page_id;
|
||||
public void Clear() {
|
||||
Xoae_app app = Xoa_app_fxt.Make__app__edit();
|
||||
this.wiki = Xoa_app_fxt.Make__wiki__edit(app, "w");
|
||||
html_row = new Srch_html_row_bldr(wiki.App().Html__lnki_bldr());
|
||||
html_row.Fmtr().Fmt_("~{page_key}");
|
||||
async = new Srch_html_row_wkr(html_row, js_wkr, 5, Bry_enwiki);
|
||||
page_id = 0;
|
||||
}
|
||||
public Srch_rslt_row Make_rslt(int len, String ttl) {
|
||||
byte[] ttl_bry = Bry_.new_a7(ttl);
|
||||
++page_id;
|
||||
byte[] key = Bry_.Add(Bry_enwiki, Byte_ascii.Pipe_bry, ttl_bry); // NOTE: deliberately changing key to use ttl instead of id to make tests more readable
|
||||
return new Srch_rslt_row(key, Bry_enwiki, wiki.Ttl_parse(ttl_bry), gplx.xowa.wikis.nss.Xow_ns_.Tid__main, ttl_bry, page_id, len, len, Srch_rslt_row.Page_redirect_id_null);
|
||||
}
|
||||
public Object[] Make_args_append(String uid, String html) {return Object_.Ary(Xog_js_wkr__log.Proc_append_above, uid, html);}
|
||||
public Object[] Make_args_replace(String uid) {return Object_.Ary(Xog_js_wkr__log.Proc_replace_html, uid, "");}
|
||||
public void Test_add(Srch_rslt_row row, Object[]... expd) {
|
||||
async.On_rslt_found(row);
|
||||
int expd_len = expd.length;
|
||||
Tfds.Eq(expd_len, js_wkr.Log__len());
|
||||
for (int i = 0; i < expd_len; ++i) {
|
||||
String expd_str = String_.Concat_with_obj("\n", expd[i]);
|
||||
String actl_str = String_.Concat_with_obj("\n", js_wkr.Log__get_at(i));
|
||||
Tfds.Eq_str_lines(expd_str, actl_str);
|
||||
}
|
||||
js_wkr.Log__clear();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +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.addons.apps.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.xowa.specials.*;
|
||||
public class Xoa_special_regy {
|
||||
private final Ordered_hash hash = Ordered_hash_.New_bry(); // NOTE: case-sensitive; case-insensitive requires lang
|
||||
public void Add(Xows_page page) {hash.Add(page.Special__meta().Key_bry(), page);}
|
||||
public void Add_many(Xows_page... ary) {for (Xows_page itm : ary) Add(itm);}
|
||||
public Xows_page Get_by_or_null(byte[] key) {return (Xows_page)hash.Get_by(key);}
|
||||
}
|
||||
@@ -1,54 +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.addons.apps.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*;
|
||||
import gplx.core.net.*;
|
||||
import gplx.xowa.htmls.*;
|
||||
import gplx.xowa.wikis.*;
|
||||
import gplx.xowa.langs.specials.*;
|
||||
public class Xosp_special_mgr {
|
||||
// private final Xowv_wiki wiki;
|
||||
private final Hash_adp_bry hash;
|
||||
public Xosp_special_mgr(Xowv_wiki wiki) {
|
||||
// this.wiki = wiki;
|
||||
// hash.Add_str_obj(Xows_special_meta_.Ttl__statistics , page_statistics);
|
||||
this.hash = Hash_adp_bry.cs();
|
||||
}
|
||||
public void Get_by_ttl(Xoh_page rv, Gfo_url url, Xoa_ttl ttl) {
|
||||
// Xosp_fbrow_rslt rslt = Xosp_fbrow_special.Gen(url.Qargs(), wiki.Appv().Wiki_mgr());
|
||||
// rv.Init(wiki, null, ttl, -1);
|
||||
// rv.Body_(rslt.Html_body());
|
||||
// rv.Html_head_xtn_(rslt.Html_head());
|
||||
}
|
||||
public void Get_by_url(Xow_wiki wiki, Xoa_page page, Xoa_url url, Xoa_ttl ttl) {
|
||||
int slash_pos = Bry_find_.Find_fwd(ttl.Page_txt_wo_qargs(), Xoa_ttl.Subpage_spr); // check for slash
|
||||
byte[] special_name = slash_pos == Bry_find_.Not_found
|
||||
? ttl.Base_txt_wo_qarg() // no slash found; use base_txt; ignore qry args and just get page_names; EX: Search/Earth?fulltext=y; Allpages?from=Earth...
|
||||
: Bry_.Mid(ttl.Page_txt_wo_qargs(), 0, slash_pos); // slash found; use root page; EX: Special:ItemByTitle/enwiki/Earth
|
||||
Object o = hash.Get_by_bry(special_name);
|
||||
if (o == null) {
|
||||
Xol_specials_itm special_itm = wiki.Lang().Specials_mgr().Get_by_alias(special_name);
|
||||
if (special_itm != null)
|
||||
o = hash.Get_by_bry(special_itm.Special());
|
||||
}
|
||||
if (o != null) {
|
||||
// Xows_page special = (Xows_page)o;
|
||||
// page.Revision_data().Modified_on_(DateAdp_.Now());
|
||||
// special.Special__gen(wiki, page, url, ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user